diff --git a/DOCS.md b/DOCS.md index 5ed9ddf..a057786 100644 --- a/DOCS.md +++ b/DOCS.md @@ -182,11 +182,25 @@ pipeline: + - destroy ``` +Formatting the Terraform configuration files can be done by specifying the `fmt` action. Use `fmt_options` parameter to handle formatting options. + +```yaml +pipeline: + fmt: + image: jmccann/drone-terraform:5 ++ actions: ++ - fmt ++ fmt_options: ++ write: false ++ diff: true ++ check: true +``` + # Parameter Reference actions : List of terraform actions to perform with the plugin. List includes: -`validate`, `plan`, `apply`, `plan-destroy`, `destroy`. +`fmt`, `validate`, `plan`, `apply`, `plan-destroy`, `destroy`. init_options : contains the configuration for the Terraform backend. @@ -202,6 +216,21 @@ init_options.lock init_options.lock-timeout : Duration to wait for a state lock. Default `0s`. +fmt_options +: contains the configuration for the fmt action. + +fmt_options.list +: List files whose formatting differs (disabled if using STDIN). Default `true`. + +fmt_options.write +: Write result to source file instead of STDOUT (disabled if using STDIN or -check). Default `true`. + +fmt_options.diff +: Display diffs of formatting changes. Default `false`. + +fmt_options.check +: Check if the input is formatted. Exit status will be 0 if all input is properly formatted and non-zero otherwise. Default `false`. + vars : a map of variables to pass to the Terraform `plan` and `apply` commands. Each value is passed as a `-var =` option. diff --git a/main.go b/main.go index ce00fba..20e9d3c 100644 --- a/main.go +++ b/main.go @@ -43,6 +43,11 @@ func main() { Usage: "options for the init command. See https://www.terraform.io/docs/commands/init.html", EnvVar: "PLUGIN_INIT_OPTIONS", }, + cli.StringFlag{ + Name: "fmt_options", + Usage: "options for the fmt command. See https://www.terraform.io/docs/commands/fmt.html", + EnvVar: "PLUGIN_FMT_OPTIONS", + }, cli.IntFlag{ Name: "parallelism", Usage: "The number of concurrent operations as Terraform walks its graph", @@ -134,6 +139,8 @@ func run(c *cli.Context) error { initOptions := InitOptions{} json.Unmarshal([]byte(c.String("init_options")), &initOptions) + fmtOptions := FmtOptions{} + json.Unmarshal([]byte(c.String("fmt_options")), &fmtOptions) plugin := Plugin{ Config: Config{ @@ -141,6 +148,7 @@ func run(c *cli.Context) error { Vars: vars, Secrets: secrets, InitOptions: initOptions, + FmtOptions: fmtOptions, Cacert: c.String("ca_cert"), Sensitive: c.Bool("sensitive"), RoleARN: c.String("role_arn_to_assume"), diff --git a/plugin.go b/plugin.go index 7887143..6fefc24 100644 --- a/plugin.go +++ b/plugin.go @@ -25,6 +25,7 @@ type ( Vars map[string]string Secrets map[string]string InitOptions InitOptions + FmtOptions FmtOptions Cacert string Sensitive bool RoleARN string @@ -48,6 +49,14 @@ type ( LockTimeout string `json:"lock-timeout"` } + // FmtOptions fmt options for the Terraform's fmt command + FmtOptions struct { + List *bool `json:"list"` + Write *bool `json:"write"` + Diff *bool `json:"diff"` + Check *bool `json:"check"` + } + // Plugin represents the plugin instance to be executed Plugin struct { Config Config @@ -94,6 +103,8 @@ func (p Plugin) Exec() error { // Add commands listed from Actions for _, action := range p.Config.Actions { switch action { + case "fmt": + commands = append(commands, tfFmt(p.Config)) case "validate": commands = append(commands, tfValidate(p.Config)) case "plan": @@ -105,7 +116,7 @@ func (p Plugin) Exec() error { case "destroy": commands = append(commands, tfDestroy(p.Config)) default: - return fmt.Errorf("valid actions are: validate, plan, apply, plan-destroy, destroy. You provided %s", action) + return fmt.Errorf("valid actions are: fmt, validate, plan, apply, plan-destroy, destroy. You provided %s", action) } } @@ -321,6 +332,28 @@ func tfValidate(config Config) *exec.Cmd { ) } +func tfFmt(config Config) *exec.Cmd { + args := []string{ + "fmt", + } + if config.FmtOptions.List != nil { + args = append(args, fmt.Sprintf("-list=%t", *config.FmtOptions.List)) + } + if config.FmtOptions.Write != nil { + args = append(args, fmt.Sprintf("-write=%t", *config.FmtOptions.Write)) + } + if config.FmtOptions.Diff != nil { + args = append(args, fmt.Sprintf("-diff=%t", *config.FmtOptions.Diff)) + } + if config.FmtOptions.Check != nil { + args = append(args, fmt.Sprintf("-check=%t", *config.FmtOptions.Check)) + } + return exec.Command( + "terraform", + args..., + ) +} + func vars(vs map[string]string) []string { var args []string for k, v := range vs { diff --git a/plugin_test.go b/plugin_test.go index 7cdd349..dc091d5 100644 --- a/plugin_test.go +++ b/plugin_test.go @@ -148,4 +148,60 @@ func TestPlugin(t *testing.T) { } }) }) + g.Describe("tfFmt", func() { + g.It("Should return correct fmt commands given the arguments", func() { + type args struct { + config Config + } + + affirmative := true + negative := false + + tests := []struct { + name string + args args + want *exec.Cmd + }{ + { + "default", + args{config: Config{}}, + exec.Command("terraform", "fmt"), + }, + { + "with list", + args{config: Config{FmtOptions: FmtOptions{List: &affirmative}}}, + exec.Command("terraform", "fmt", "-list=true"), + }, + { + "with write", + args{config: Config{FmtOptions: FmtOptions{Write: &affirmative}}}, + exec.Command("terraform", "fmt", "-write=true"), + }, + { + "with diff", + args{config: Config{FmtOptions: FmtOptions{Diff: &affirmative}}}, + exec.Command("terraform", "fmt", "-diff=true"), + }, + { + "with check", + args{config: Config{FmtOptions: FmtOptions{Check: &affirmative}}}, + exec.Command("terraform", "fmt", "-check=true"), + }, + { + "with combination", + args{config: Config{FmtOptions: FmtOptions{ + List: &negative, + Write: &negative, + Diff: &affirmative, + Check: &affirmative, + }}}, + exec.Command("terraform", "fmt", "-list=false", "-write=false", "-diff=true", "-check=true"), + }, + } + + for _, tt := range tests { + g.Assert(tfFmt(tt.args.config)).Equal(tt.want) + } + }) + }) }