Skip to content

Commit

Permalink
Feat support validate terraform command
Browse files Browse the repository at this point in the history
  • Loading branch information
albertorm95 committed Dec 9, 2022
1 parent f0d952d commit 2cd8eda
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 6 deletions.
18 changes: 12 additions & 6 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,12 @@ type TypetalkNotifier struct {

// Terraform represents terraform configurations
type Terraform struct {
Default Default `yaml:"default"`
Fmt Fmt `yaml:"fmt"`
Plan Plan `yaml:"plan"`
Apply Apply `yaml:"apply"`
UseRawOutput bool `yaml:"use_raw_output,omitempty"`
Default Default `yaml:"default"`
Fmt Fmt `yaml:"fmt"`
Plan Plan `yaml:"plan"`
Apply Apply `yaml:"apply"`
UseRawOutput bool `yaml:"use_raw_output,omitempty"`
Validate Validate `yaml:"validate"`
}

// Default is a default setting for terraform commands
Expand All @@ -79,6 +80,11 @@ type Fmt struct {
Template string `yaml:"template"`
}

// Validate is a terraform validate config
type Validate struct {
Template string `yaml:"template"`
}

// Plan is a terraform plan config
type Plan struct {
Template string `yaml:"template"`
Expand Down Expand Up @@ -174,7 +180,7 @@ func (cfg *Config) Validation() error {
}
if cfg.isDefinedTypetalk() {
if cfg.Notifier.Typetalk.TopicID == "" {
return fmt.Errorf("Typetalk topic id is missing")
return fmt.Errorf("typetalk topic id is missing")
}
}
notifier := cfg.GetNotifierType()
Expand Down
29 changes: 29 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,21 @@ func main() {
},
},
},
{
Name: "validate",
Usage: "Parse stdin as a validate result",
Action: cmdValidate,
Flags: []cli.Flag{
cli.StringFlag{
Name: "title, t",
Usage: "Specify the title to use for notification",
},
cli.StringFlag{
Name: "message, m",
Usage: "Specify the message to use for notification",
},
},
},
{
Name: "plan",
Usage: "Parse stdin as a plan result",
Expand Down Expand Up @@ -291,6 +306,20 @@ func cmdFmt(ctx *cli.Context) error {
return t.Run()
}

func cmdValidate(ctx *cli.Context) error {
cfg, err := newConfig(ctx)
if err != nil {
return err
}
t := &tfnotify{
config: cfg,
context: ctx,
parser: terraform.NewValidateParser(),
template: terraform.NewValidateTemplate(cfg.Terraform.Validate.Template),
}
return t.Run()
}

func cmdPlan(ctx *cli.Context) error {
cfg, err := newConfig(ctx)
if err != nil {
Expand Down
23 changes: 23 additions & 0 deletions terraform/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@ type FmtParser struct {
Fail *regexp.Regexp
}

// ValidateParser is a parser for terraform Validate
type ValidateParser struct {
Pass *regexp.Regexp
Fail *regexp.Regexp
}

// PlanParser is a parser for terraform plan
type PlanParser struct {
Pass *regexp.Regexp
Expand All @@ -58,6 +64,13 @@ func NewFmtParser() *FmtParser {
}
}

// NewValidateParser is ValidateParser initialized with its Regexp
func NewValidateParser() *ValidateParser {
return &ValidateParser{
Fail: regexp.MustCompile(`(?m)^(│\s{1})?(Error: )`),
}
}

// NewPlanParser is PlanParser initialized with its Regexp
func NewPlanParser() *PlanParser {
return &PlanParser{
Expand Down Expand Up @@ -96,6 +109,16 @@ func (p *FmtParser) Parse(body string) ParseResult {
return result
}

// Parse returns ParseResult related with terraform validate
func (p *ValidateParser) Parse(body string) ParseResult {
result := ParseResult{}
if p.Fail.MatchString(body) {
result.Result = "There is a validation error in your Terraform code"
result.ExitCode = ExitFail
}
return result
}

// Parse returns ParseResult related with terraform plan
func (p *PlanParser) Parse(body string) ParseResult {
var exitCode int
Expand Down
67 changes: 67 additions & 0 deletions terraform/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ const (
DefaultDefaultTitle = "## Terraform result"
// DefaultFmtTitle is a default title for terraform fmt
DefaultFmtTitle = "## Fmt result"
// DefaultValidateTitle is a default title for terraform validate
DefaultValidateTitle = "## Validate result"
// DefaultPlanTitle is a default title for terraform plan
DefaultPlanTitle = "## Plan result"
// DefaultDestroyWarningTitle is a default title of destroy warning
Expand Down Expand Up @@ -44,6 +46,23 @@ const (
{{ .Result }}
{{ .Body }}
`

// DefaultValidateTemplate is a default template for terraform validate
DefaultValidateTemplate = `
{{ .Title }}
{{ .Message }}
{{if .Result}}
<pre><code>{{ .Result }}
</code></pre>
{{end}}
<details><summary>Details (Click me)</summary>
<pre><code>{{ .Body }}
</code></pre></details>
`

// DefaultPlanTemplate is a default template for terraform plan
Expand Down Expand Up @@ -124,6 +143,13 @@ type FmtTemplate struct {
CommonTemplate
}

// ValidateTemplate is a default template for terraform validate
type ValidateTemplate struct {
Template string

CommonTemplate
}

// PlanTemplate is a default template for terraform plan
type PlanTemplate struct {
Template string
Expand Down Expand Up @@ -165,6 +191,16 @@ func NewFmtTemplate(template string) *FmtTemplate {
}
}

// NewValidateTemplate is ValidateTemplate initializer
func NewValidateTemplate(template string) *ValidateTemplate {
if template == "" {
template = DefaultValidateTemplate
}
return &ValidateTemplate{
Template: template,
}
}

// NewPlanTemplate is PlanTemplate initializer
func NewPlanTemplate(template string) *PlanTemplate {
if template == "" {
Expand Down Expand Up @@ -255,6 +291,24 @@ func (t *FmtTemplate) Execute() (string, error) {
return resp, nil
}

// Execute binds the execution result of terraform validate into template
func (t *ValidateTemplate) Execute() (string, error) {
data := map[string]interface{}{
"Title": t.Title,
"Message": t.Message,
"Result": t.Result,
"Body": t.Body,
"Link": t.Link,
}

resp, err := generateOutput("validate", t.Template, data, t.UseRawOutput)
if err != nil {
return "", err
}

return resp, nil
}

// Execute binds the execution result of terraform plan into template
func (t *PlanTemplate) Execute() (string, error) {
data := map[string]interface{}{
Expand Down Expand Up @@ -325,6 +379,14 @@ func (t *FmtTemplate) SetValue(ct CommonTemplate) {
t.CommonTemplate = ct
}

// SetValue sets template entities about terraform validate to CommonTemplate
func (t *ValidateTemplate) SetValue(ct CommonTemplate) {
if ct.Title == "" {
ct.Title = DefaultValidateTitle
}
t.CommonTemplate = ct
}

// SetValue sets template entities about terraform plan to CommonTemplate
func (t *PlanTemplate) SetValue(ct CommonTemplate) {
if ct.Title == "" {
Expand Down Expand Up @@ -359,6 +421,11 @@ func (t *FmtTemplate) GetValue() CommonTemplate {
return t.CommonTemplate
}

// GetValue gets template entities
func (t *ValidateTemplate) GetValue() CommonTemplate {
return t.CommonTemplate
}

// GetValue gets template entities
func (t *PlanTemplate) GetValue() CommonTemplate {
return t.CommonTemplate
Expand Down

0 comments on commit 2cd8eda

Please sign in to comment.