command: Display state ID in PreApply+PostApply (#12261)
This commit is contained in:
parent
185c3dffe0
commit
2e2b8686dd
|
@ -16,6 +16,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const periodicUiTimer = 10 * time.Second
|
const periodicUiTimer = 10 * time.Second
|
||||||
|
const maxIdLen = 20
|
||||||
|
|
||||||
type UiHook struct {
|
type UiHook struct {
|
||||||
terraform.NilHook
|
terraform.NilHook
|
||||||
|
@ -128,19 +129,25 @@ func (h *UiHook) PreApply(
|
||||||
attrString = "\n " + attrString
|
attrString = "\n " + attrString
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var stateIdSuffix string
|
||||||
|
if s.ID != "" {
|
||||||
|
stateIdSuffix = fmt.Sprintf(" (ID: %s)", truncateId(s.ID, maxIdLen))
|
||||||
|
}
|
||||||
|
|
||||||
h.ui.Output(h.Colorize.Color(fmt.Sprintf(
|
h.ui.Output(h.Colorize.Color(fmt.Sprintf(
|
||||||
"[reset][bold]%s: %s[reset]%s",
|
"[reset][bold]%s: %s%s[reset]%s",
|
||||||
id,
|
id,
|
||||||
operation,
|
operation,
|
||||||
|
stateIdSuffix,
|
||||||
attrString)))
|
attrString)))
|
||||||
|
|
||||||
// Set a timer to show an operation is still happening
|
// Set a timer to show an operation is still happening
|
||||||
time.AfterFunc(periodicUiTimer, func() { h.stillApplying(id) })
|
time.AfterFunc(periodicUiTimer, func() { h.stillApplying(id, s.ID) })
|
||||||
|
|
||||||
return terraform.HookActionContinue, nil
|
return terraform.HookActionContinue, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *UiHook) stillApplying(id string) {
|
func (h *UiHook) stillApplying(id, stateId string) {
|
||||||
// Grab the operation. We defer the lock here to avoid the "still..."
|
// Grab the operation. We defer the lock here to avoid the "still..."
|
||||||
// message showing up after a completion message.
|
// message showing up after a completion message.
|
||||||
h.l.Lock()
|
h.l.Lock()
|
||||||
|
@ -164,15 +171,21 @@ func (h *UiHook) stillApplying(id string) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var stateIdSuffix string
|
||||||
|
if stateId != "" {
|
||||||
|
stateIdSuffix = fmt.Sprintf("ID: %s, ", truncateId(stateId, maxIdLen))
|
||||||
|
}
|
||||||
|
|
||||||
h.ui.Output(h.Colorize.Color(fmt.Sprintf(
|
h.ui.Output(h.Colorize.Color(fmt.Sprintf(
|
||||||
"[reset][bold]%s: %s (%s elapsed)[reset]",
|
"[reset][bold]%s: %s (%s%s elapsed)[reset]",
|
||||||
id,
|
id,
|
||||||
msg,
|
msg,
|
||||||
|
stateIdSuffix,
|
||||||
time.Now().Round(time.Second).Sub(state.Start),
|
time.Now().Round(time.Second).Sub(state.Start),
|
||||||
)))
|
)))
|
||||||
|
|
||||||
// Reschedule
|
// Reschedule
|
||||||
time.AfterFunc(periodicUiTimer, func() { h.stillApplying(id) })
|
time.AfterFunc(periodicUiTimer, func() { h.stillApplying(id, stateId) })
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *UiHook) PostApply(
|
func (h *UiHook) PostApply(
|
||||||
|
@ -186,6 +199,11 @@ func (h *UiHook) PostApply(
|
||||||
delete(h.resources, id)
|
delete(h.resources, id)
|
||||||
h.l.Unlock()
|
h.l.Unlock()
|
||||||
|
|
||||||
|
var stateIdSuffix string
|
||||||
|
if s.ID != "" {
|
||||||
|
stateIdSuffix = fmt.Sprintf(" (ID: %s)", truncateId(s.ID, maxIdLen))
|
||||||
|
}
|
||||||
|
|
||||||
var msg string
|
var msg string
|
||||||
switch state.Op {
|
switch state.Op {
|
||||||
case uiResourceModify:
|
case uiResourceModify:
|
||||||
|
@ -204,8 +222,8 @@ func (h *UiHook) PostApply(
|
||||||
}
|
}
|
||||||
|
|
||||||
h.ui.Output(h.Colorize.Color(fmt.Sprintf(
|
h.ui.Output(h.Colorize.Color(fmt.Sprintf(
|
||||||
"[reset][bold]%s: %s[reset]",
|
"[reset][bold]%s: %s%s[reset]",
|
||||||
id, msg)))
|
id, msg, stateIdSuffix)))
|
||||||
|
|
||||||
return terraform.HookActionContinue, nil
|
return terraform.HookActionContinue, nil
|
||||||
}
|
}
|
||||||
|
@ -258,7 +276,7 @@ func (h *UiHook) PreRefresh(
|
||||||
// Data resources refresh before they have ids, whereas managed
|
// Data resources refresh before they have ids, whereas managed
|
||||||
// resources are only refreshed when they have ids.
|
// resources are only refreshed when they have ids.
|
||||||
if s.ID != "" {
|
if s.ID != "" {
|
||||||
stateIdSuffix = fmt.Sprintf(" (ID: %s)", s.ID)
|
stateIdSuffix = fmt.Sprintf(" (ID: %s)", truncateId(s.ID, maxIdLen))
|
||||||
}
|
}
|
||||||
|
|
||||||
h.ui.Output(h.Colorize.Color(fmt.Sprintf(
|
h.ui.Output(h.Colorize.Color(fmt.Sprintf(
|
||||||
|
@ -336,3 +354,32 @@ func dropCR(data []byte) []byte {
|
||||||
}
|
}
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func truncateId(id string, maxLen int) string {
|
||||||
|
totalLength := len(id)
|
||||||
|
if totalLength <= maxLen {
|
||||||
|
return id
|
||||||
|
}
|
||||||
|
if maxLen < 5 {
|
||||||
|
// We don't shorten to less than 5 chars
|
||||||
|
// as that would be pointless with ... (3 chars)
|
||||||
|
maxLen = 5
|
||||||
|
}
|
||||||
|
|
||||||
|
dots := "..."
|
||||||
|
partLen := maxLen / 2
|
||||||
|
|
||||||
|
leftIdx := partLen - 1
|
||||||
|
leftPart := id[0:leftIdx]
|
||||||
|
|
||||||
|
rightIdx := totalLength - partLen - 1
|
||||||
|
|
||||||
|
overlap := maxLen - (partLen*2 + len(dots))
|
||||||
|
if overlap < 0 {
|
||||||
|
rightIdx -= overlap
|
||||||
|
}
|
||||||
|
|
||||||
|
rightPart := id[rightIdx:]
|
||||||
|
|
||||||
|
return leftPart + dots + rightPart
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
package command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestTruncateId(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
Input string
|
||||||
|
Expected string
|
||||||
|
MaxLen int
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Input: "Hello world",
|
||||||
|
Expected: "H...d",
|
||||||
|
MaxLen: 3,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Input: "Hello world",
|
||||||
|
Expected: "H...d",
|
||||||
|
MaxLen: 5,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Input: "Hello world",
|
||||||
|
Expected: "He...d",
|
||||||
|
MaxLen: 6,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Input: "Hello world",
|
||||||
|
Expected: "He...ld",
|
||||||
|
MaxLen: 7,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Input: "Hello world",
|
||||||
|
Expected: "Hel...ld",
|
||||||
|
MaxLen: 8,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Input: "Hello world",
|
||||||
|
Expected: "Hel...rld",
|
||||||
|
MaxLen: 9,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Input: "Hello world",
|
||||||
|
Expected: "Hell...rld",
|
||||||
|
MaxLen: 10,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Input: "Hello world",
|
||||||
|
Expected: "Hello world",
|
||||||
|
MaxLen: 11,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Input: "Hello world",
|
||||||
|
Expected: "Hello world",
|
||||||
|
MaxLen: 12,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for i, tc := range testCases {
|
||||||
|
testName := fmt.Sprintf("%d", i)
|
||||||
|
t.Run(testName, func(t *testing.T) {
|
||||||
|
out := truncateId(tc.Input, tc.MaxLen)
|
||||||
|
if out != tc.Expected {
|
||||||
|
t.Fatalf("Expected %q to be shortened to %d as %q (given: %q)",
|
||||||
|
tc.Input, tc.MaxLen, tc.Expected, out)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue