diff --git a/.gitignore b/.gitignore index 4c88a1f..f005b42 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ +/tfvar profile.cov dist/ diff --git a/cmd/cmd.go b/cmd/cmd.go index b7ddef9..e1154e6 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -12,14 +12,15 @@ import ( ) const ( - flagAutoAssign = "auto-assign" - flagDebug = "debug" - flagEnvVar = "env-var" - flagNoDefault = "ignore-default" - flagResource = "resource" - flagVar = "var" - flagVarFile = "var-file" - flagWorkspace = "workspace" + flagAutoAssign = "auto-assign" + flagDebug = "debug" + flagDescsAsComments = "descs-as-comments" + flagEnvVar = "env-var" + flagNoDefault = "ignore-default" + flagResource = "resource" + flagVar = "var" + flagVarFile = "var-file" + flagWorkspace = "workspace" ) // New returns a new instance of cobra.Command for tfvar. Usage: @@ -50,6 +51,7 @@ one would write it in variable definitions files (.tfvars). rootCmd.PersistentFlags().BoolP(flagAutoAssign, "a", false, `Use values from environment variables TF_VAR_* and variable definitions files e.g. terraform.tfvars[.json] *.auto.tfvars[.json]`) rootCmd.PersistentFlags().BoolP(flagDebug, "d", false, "Print debug log on stderr") + rootCmd.PersistentFlags().BoolP(flagDescsAsComments, "c", false, "Include variable descriptions as comments.") rootCmd.PersistentFlags().BoolP(flagEnvVar, "e", false, "Print output in export TF_VAR_image_id=ami-abc123 format") rootCmd.PersistentFlags().BoolP(flagResource, "r", false, "Print output in Terraform Enterprise (tfe) provider's tfe_variable resource format") rootCmd.PersistentFlags().BoolP(flagWorkspace, "w", false, "Print output variables as payloads for Workspace Variables API") @@ -179,21 +181,31 @@ func (r *runner) rootRunE(cmd *cobra.Command, args []string) error { return err } - writer := tfvar.WriteAsTFVars + var writer func(w io.Writer, vars []tfvar.Variable) error if isEnvVar { r.log.Debug("Print outputs in environment variables format") writer = tfvar.WriteAsEnvVars - } - - if isWorkspace { + } else if isWorkspace { r.log.Debug("Print outputs in Workspace API payload format") writer = tfvar.WriteAsWorkspacePayload - } - - if isResource { + } else if isResource { r.log.Debug("Print outputs in tfe_resource format") writer = tfvar.WriteAsTFEResource + } else { + r.log.Debug("Print outputs in tfvars format") + withComments, err := cmd.PersistentFlags().GetBool(flagDescsAsComments) + if err != nil { + return errors.Wrapf(err, "cmd: get flag --%s", flagDescsAsComments) + } + if withComments { + r.log.Debug("Including comments in tfvars output") + } else { + r.log.Debug("Not including comments in tfvars output") + } + writer = func(w io.Writer, vars []tfvar.Variable) error { + return tfvar.WriteAsTFVars(withComments, w, vars) + } } return writer(r.out, vars) } diff --git a/pkg/tfvar/tfvar.go b/pkg/tfvar/tfvar.go index c31f5ac..c8f6d88 100644 --- a/pkg/tfvar/tfvar.go +++ b/pkg/tfvar/tfvar.go @@ -6,6 +6,7 @@ import ( "encoding/json" "fmt" "io" + "strings" "github.com/cockroachdb/errors" "github.com/hashicorp/hcl/v2/hclsyntax" @@ -101,11 +102,17 @@ func oneliner(original hclwrite.Tokens) hclwrite.Tokens { // WriteAsTFVars outputs the given vars in Terraform's variable definitions format, e.g. // region = "ap-northeast-1" -func WriteAsTFVars(w io.Writer, vars []Variable) error { +func WriteAsTFVars(withComments bool, w io.Writer, vars []Variable) error { f := hclwrite.NewEmptyFile() rootBody := f.Body() for _, v := range vars { + if withComments { + comment := strings.TrimSpace(v.Description) + if len(comment) > 0 { + rootBody.AppendUnstructuredTokens(commentToTokens(comment)) + } + } rootBody.SetAttributeValue(v.Name, v.Value) } @@ -113,6 +120,25 @@ func WriteAsTFVars(w io.Writer, vars []Variable) error { return errors.Wrap(err, "tfvar: failed to write as tfvars") } +func commentToTokens(comment string) hclwrite.Tokens { + lines := strings.Split(comment, "\n") + newLine := hclwrite.Token{ + Type: hclsyntax.TokenNewline, + Bytes: []byte(string(hclsyntax.TokenNewline)), + } + + var tokens hclwrite.Tokens + for _, line := range lines { + tokens = append(tokens, &hclwrite.Token{ + Type: hclsyntax.TokenComment, + Bytes: []byte(fmt.Sprintf("# %s", line)), + }) + tokens = append(tokens, &newLine) + } + + return tokens +} + type workspacePayload struct { Data workspaceData `json:"data"` } diff --git a/pkg/tfvar/tfvar_test.go b/pkg/tfvar/tfvar_test.go index 9980670..73300fd 100644 --- a/pkg/tfvar/tfvar_test.go +++ b/pkg/tfvar/tfvar_test.go @@ -79,7 +79,7 @@ func TestWriteAsTFVars(t *testing.T) { sort.Slice(vars, func(i, j int) bool { return vars[i].Name < vars[j].Name }) var buf bytes.Buffer - assert.NoError(t, WriteAsTFVars(&buf, vars)) + assert.NoError(t, WriteAsTFVars(true, &buf, vars)) expected := `availability_zone_names = ["us-west-1a"] aws_amis = { @@ -94,8 +94,9 @@ docker_ports = [{ protocol = "tcp" }] instance_name = "my-instance" -password = null -region = null +# the root password to use with the database +password = null +region = null ` assert.Equal(t, expected, buf.String()) }