command: show resource actions using resource addresses
Previously we were using the internal resource id syntax in the UI. Now we'll use the standard user-facing resource address syntax instead.
This commit is contained in:
parent
3ea159297c
commit
d4efc95191
|
@ -65,6 +65,7 @@ func (h *UiHook) PreApply(
|
|||
}
|
||||
|
||||
id := n.HumanId()
|
||||
addr := n.ResourceAddress()
|
||||
|
||||
op := uiResourceModify
|
||||
if d.Destroy {
|
||||
|
@ -142,7 +143,7 @@ func (h *UiHook) PreApply(
|
|||
|
||||
h.ui.Output(h.Colorize.Color(fmt.Sprintf(
|
||||
"[reset][bold]%s: %s%s[reset]%s",
|
||||
id,
|
||||
addr,
|
||||
operation,
|
||||
stateIdSuffix,
|
||||
attrString)))
|
||||
|
@ -210,6 +211,7 @@ func (h *UiHook) PostApply(
|
|||
applyerr error) (terraform.HookAction, error) {
|
||||
|
||||
id := n.HumanId()
|
||||
addr := n.ResourceAddress()
|
||||
|
||||
h.l.Lock()
|
||||
state := h.resources[id]
|
||||
|
@ -244,7 +246,7 @@ func (h *UiHook) PostApply(
|
|||
|
||||
colorized := h.Colorize.Color(fmt.Sprintf(
|
||||
"[reset][bold]%s: %s after %s%s[reset]",
|
||||
id, msg, time.Now().Round(time.Second).Sub(state.Start), stateIdSuffix))
|
||||
addr, msg, time.Now().Round(time.Second).Sub(state.Start), stateIdSuffix))
|
||||
|
||||
h.ui.Output(colorized)
|
||||
|
||||
|
@ -260,10 +262,10 @@ func (h *UiHook) PreDiff(
|
|||
func (h *UiHook) PreProvision(
|
||||
n *terraform.InstanceInfo,
|
||||
provId string) (terraform.HookAction, error) {
|
||||
id := n.HumanId()
|
||||
addr := n.ResourceAddress()
|
||||
h.ui.Output(h.Colorize.Color(fmt.Sprintf(
|
||||
"[reset][bold]%s: Provisioning with '%s'...[reset]",
|
||||
id, provId)))
|
||||
addr, provId)))
|
||||
return terraform.HookActionContinue, nil
|
||||
}
|
||||
|
||||
|
@ -271,11 +273,11 @@ func (h *UiHook) ProvisionOutput(
|
|||
n *terraform.InstanceInfo,
|
||||
provId string,
|
||||
msg string) {
|
||||
id := n.HumanId()
|
||||
addr := n.ResourceAddress()
|
||||
var buf bytes.Buffer
|
||||
buf.WriteString(h.Colorize.Color("[reset]"))
|
||||
|
||||
prefix := fmt.Sprintf("%s (%s): ", id, provId)
|
||||
prefix := fmt.Sprintf("%s (%s): ", addr, provId)
|
||||
s := bufio.NewScanner(strings.NewReader(msg))
|
||||
s.Split(scanLines)
|
||||
for s.Scan() {
|
||||
|
@ -293,7 +295,7 @@ func (h *UiHook) PreRefresh(
|
|||
s *terraform.InstanceState) (terraform.HookAction, error) {
|
||||
h.once.Do(h.init)
|
||||
|
||||
id := n.HumanId()
|
||||
addr := n.ResourceAddress()
|
||||
|
||||
var stateIdSuffix string
|
||||
// Data resources refresh before they have ids, whereas managed
|
||||
|
@ -304,7 +306,7 @@ func (h *UiHook) PreRefresh(
|
|||
|
||||
h.ui.Output(h.Colorize.Color(fmt.Sprintf(
|
||||
"[reset][bold]%s: Refreshing state...%s",
|
||||
id, stateIdSuffix)))
|
||||
addr, stateIdSuffix)))
|
||||
return terraform.HookActionContinue, nil
|
||||
}
|
||||
|
||||
|
@ -313,9 +315,10 @@ func (h *UiHook) PreImportState(
|
|||
id string) (terraform.HookAction, error) {
|
||||
h.once.Do(h.init)
|
||||
|
||||
addr := n.ResourceAddress()
|
||||
h.ui.Output(h.Colorize.Color(fmt.Sprintf(
|
||||
"[reset][bold]%s: Importing from ID %q...",
|
||||
n.HumanId(), id)))
|
||||
addr, id)))
|
||||
return terraform.HookActionContinue, nil
|
||||
}
|
||||
|
||||
|
@ -324,9 +327,9 @@ func (h *UiHook) PostImportState(
|
|||
s []*terraform.InstanceState) (terraform.HookAction, error) {
|
||||
h.once.Do(h.init)
|
||||
|
||||
id := n.HumanId()
|
||||
addr := n.ResourceAddress()
|
||||
h.ui.Output(h.Colorize.Color(fmt.Sprintf(
|
||||
"[reset][bold][green]%s: Import complete!", id)))
|
||||
"[reset][bold][green]%s: Import complete!", addr)))
|
||||
for _, s := range s {
|
||||
h.ui.Output(h.Colorize.Color(fmt.Sprintf(
|
||||
"[reset][green] Imported %s (ID: %s)",
|
||||
|
|
|
@ -88,6 +88,46 @@ func (i *InstanceInfo) HumanId() string {
|
|||
i.Id)
|
||||
}
|
||||
|
||||
// ResourceAddress returns the address of the resource that the receiver is describing.
|
||||
func (i *InstanceInfo) ResourceAddress() *ResourceAddress {
|
||||
// GROSS: for tainted and deposed instances, their status gets appended
|
||||
// to i.Id to create a unique id for the graph node. Historically these
|
||||
// ids were displayed to the user, so it's designed to be human-readable:
|
||||
// "aws_instance.bar.0 (deposed #0)"
|
||||
//
|
||||
// So here we detect such suffixes and try to interpret them back to
|
||||
// their original meaning so we can then produce a ResourceAddress
|
||||
// with a suitable InstanceType.
|
||||
id := i.Id
|
||||
instanceType := TypeInvalid
|
||||
if idx := strings.Index(id, " ("); idx != -1 {
|
||||
remain := id[idx:]
|
||||
id = id[:idx]
|
||||
|
||||
switch {
|
||||
case strings.Contains(remain, "tainted"):
|
||||
instanceType = TypeTainted
|
||||
case strings.Contains(remain, "deposed"):
|
||||
instanceType = TypeDeposed
|
||||
}
|
||||
}
|
||||
|
||||
addr, err := parseResourceAddressInternal(id)
|
||||
if err != nil {
|
||||
// should never happen, since that would indicate a bug in the
|
||||
// code that constructed this InstanceInfo.
|
||||
panic(fmt.Errorf("InstanceInfo has invalid Id %s", id))
|
||||
}
|
||||
if len(i.ModulePath) > 1 {
|
||||
addr.Path = i.ModulePath[1:] // trim off "root" prefix, which is implied
|
||||
}
|
||||
if instanceType != TypeInvalid {
|
||||
addr.InstanceTypeSet = true
|
||||
addr.InstanceType = instanceType
|
||||
}
|
||||
return addr
|
||||
}
|
||||
|
||||
func (i *InstanceInfo) uniqueId() string {
|
||||
prefix := i.HumanId()
|
||||
if v := i.uniqueExtra; v != "" {
|
||||
|
|
|
@ -3,6 +3,7 @@ package terraform
|
|||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/hil"
|
||||
|
@ -46,6 +47,63 @@ func TestInstanceInfo(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestInstanceInfoResourceAddress(t *testing.T) {
|
||||
tests := []struct {
|
||||
Input *InstanceInfo
|
||||
Want string
|
||||
}{
|
||||
{
|
||||
&InstanceInfo{
|
||||
Id: "test_resource.baz",
|
||||
},
|
||||
"test_resource.baz",
|
||||
},
|
||||
{
|
||||
&InstanceInfo{
|
||||
Id: "test_resource.baz",
|
||||
ModulePath: rootModulePath,
|
||||
},
|
||||
"test_resource.baz",
|
||||
},
|
||||
{
|
||||
&InstanceInfo{
|
||||
Id: "test_resource.baz",
|
||||
ModulePath: []string{"root", "foo"},
|
||||
},
|
||||
"module.foo.test_resource.baz",
|
||||
},
|
||||
{
|
||||
&InstanceInfo{
|
||||
Id: "test_resource.baz",
|
||||
ModulePath: []string{"root", "foo", "bar"},
|
||||
},
|
||||
"module.foo.module.bar.test_resource.baz",
|
||||
},
|
||||
{
|
||||
&InstanceInfo{
|
||||
Id: "test_resource.baz (tainted)",
|
||||
},
|
||||
"test_resource.baz.tainted",
|
||||
},
|
||||
{
|
||||
&InstanceInfo{
|
||||
Id: "test_resource.baz (deposed #0)",
|
||||
},
|
||||
"test_resource.baz.deposed",
|
||||
},
|
||||
}
|
||||
|
||||
for i, test := range tests {
|
||||
t.Run(strconv.Itoa(i), func(t *testing.T) {
|
||||
gotAddr := test.Input.ResourceAddress()
|
||||
got := gotAddr.String()
|
||||
if got != test.Want {
|
||||
t.Fatalf("wrong result\ngot: %s\nwant: %s", got, test.Want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestResourceConfigGet(t *testing.T) {
|
||||
cases := []struct {
|
||||
Config map[string]interface{}
|
||||
|
|
Loading…
Reference in New Issue