Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

core: Add support for marking outputs as sensitive #6559

Merged
merged 3 commits into from
May 9, 2016
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 20 additions & 7 deletions command/apply.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (

"github.com/hashicorp/go-getter"
"github.com/hashicorp/go-multierror"
"github.com/hashicorp/terraform/config"
"github.com/hashicorp/terraform/terraform"
)

Expand Down Expand Up @@ -250,7 +251,7 @@ func (c *ApplyCommand) Run(args []string) int {
}

if !c.Destroy {
if outputs := outputsAsString(state); outputs != "" {
if outputs := outputsAsString(state, ctx.Module().Config().Outputs); outputs != "" {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Module() and Config() are guaranteed to be non-nil?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, if we have got to this stage.

c.Ui.Output(c.Colorize().Color(outputs))
}
}
Expand Down Expand Up @@ -376,14 +377,19 @@ Options:
return strings.TrimSpace(helpText)
}

func outputsAsString(state *terraform.State) string {
func outputsAsString(state *terraform.State, schema []*config.Output) string {
if state == nil {
return ""
}

outputs := state.RootModule().Outputs
outputBuf := new(bytes.Buffer)
if len(outputs) > 0 {
schemaMap := make(map[string]*config.Output)
for _, s := range schema {
schemaMap[s.Name] = s
}

outputBuf.WriteString("[reset][bold][green]\nOutputs:\n\n")

// Output the outputs in alphabetical order
Expand All @@ -400,11 +406,18 @@ func outputsAsString(state *terraform.State) string {
for _, k := range keys {
v := outputs[k]

outputBuf.WriteString(fmt.Sprintf(
" %s%s = %s\n",
k,
strings.Repeat(" ", keyLen-len(k)),
v))
if schemaMap[k].Sensitive {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this panic if I have an output in the state but remove it from config?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It shouldn't at this stage - apply has already run so the state will be modified.

outputBuf.WriteString(fmt.Sprintf(
" %s%s = <sensitive>\n",
k,
strings.Repeat(" ", keyLen-len(k))))
} else {
outputBuf.WriteString(fmt.Sprintf(
" %s%s = %s\n",
k,
strings.Repeat(" ", keyLen-len(k)),
v))
}
}
}

Expand Down
30 changes: 30 additions & 0 deletions command/apply_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -886,6 +886,36 @@ func TestApply_stateNoExist(t *testing.T) {
}
}

func TestApply_sensitiveOutput(t *testing.T) {
statePath := testTempFile(t)

p := testProvider()
ui := new(cli.MockUi)
c := &ApplyCommand{
Meta: Meta{
ContextOpts: testCtxConfig(p),
Ui: ui,
},
}

args := []string{
"-state", statePath,
testFixturePath("apply-sensitive-output"),
}

if code := c.Run(args); code != 0 {
t.Fatalf("bad: \n%s", ui.OutputWriter.String())
}

output := ui.OutputWriter.String()
if !strings.Contains(output, "notsensitive = Hello world") {
t.Fatalf("bad: output should contain 'notsensitive' output\n%s", output)
}
if !strings.Contains(output, "sensitive = <sensitive>") {
t.Fatalf("bad: output should contain 'sensitive' output\n%s", output)
}
}

func TestApply_vars(t *testing.T) {
statePath := testTempFile(t)

Expand Down
1 change: 1 addition & 0 deletions command/output.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ func (c *OutputCommand) Run(args []string) int {

for _, k := range ks {
v := mod.Outputs[k]

c.Ui.Output(fmt.Sprintf("%s = %s", k, v))
}
return 0
Expand Down
2 changes: 1 addition & 1 deletion command/refresh.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ func (c *RefreshCommand) Run(args []string) int {
return 1
}

if outputs := outputsAsString(newState); outputs != "" {
if outputs := outputsAsString(newState, ctx.Module().Config().Outputs); outputs != "" {
c.Ui.Output(c.Colorize().Color(outputs))
}

Expand Down
12 changes: 12 additions & 0 deletions command/test-fixtures/apply-sensitive-output/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
variable "input" {
default = "Hello world"
}

output "notsensitive" {
value = "${var.input}"
}

output "sensitive" {
sensitive = true
value = "${var.input}"
}
22 changes: 19 additions & 3 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,9 +146,12 @@ type Variable struct {
}

// Output is an output defined within the configuration. An output is
// resulting data that is highlighted by Terraform when finished.
// resulting data that is highlighted by Terraform when finished. An
// output marked Sensitive will be output in a masked form following
// application, but will still be available in state.
type Output struct {
Name string
Sensitive bool
RawConfig *RawConfig
}

Expand Down Expand Up @@ -558,9 +561,22 @@ func (c *Config) Validate() error {
for k := range o.RawConfig.Raw {
if k == "value" {
valueKeyFound = true
} else {
invalidKeys = append(invalidKeys, k)
continue
}
if k == "sensitive" {
if sensitive, ok := o.RawConfig.config[k].(bool); ok {
if sensitive {
o.Sensitive = true
}
continue
}

errs = append(errs, fmt.Errorf(
"%s: value for 'sensitive' must be boolean",
o.Name))
continue
}
invalidKeys = append(invalidKeys, k)
}
if len(invalidKeys) > 0 {
errs = append(errs, fmt.Errorf(
Expand Down