outputs/requried_output.go (69 lines of code) (raw):

package outputs import ( "fmt" "github.com/hashicorp/hcl/v2" "github.com/terraform-linters/tflint-plugin-sdk/hclext" "github.com/terraform-linters/tflint-plugin-sdk/tflint" ) // variableBodySchema is the schema for the variable block that we want to extract from the config. var outputBodySchema = &hclext.BodySchema{ Blocks: []hclext.BlockSchema{ { Type: "output", LabelNames: []string{"name"}, Body: &hclext.BodySchema{}, }, }, } // Check interface compliance with the tflint.Rule. var _ tflint.Rule = new(RequiredOutputRule) // RequiredOutputRule is the struct that represents a rule that // check for the correct usage of an interface. type RequiredOutputRule struct { tflint.DefaultRule outputName string link string ruleName string } // NewRequiredOutputRule returns a new rule with the given variable. func NewRequiredOutputRule(ruleName, requiredOutputName, link string) *RequiredOutputRule { return &RequiredOutputRule{ ruleName: ruleName, outputName: requiredOutputName, link: link, } } // Name returns the rule name. func (or *RequiredOutputRule) Name() string { return or.ruleName } // Link returns the link to the rule documentation. func (or *RequiredOutputRule) Link() string { return or.link } // Enabled returns whether the rule is enabled. func (or *RequiredOutputRule) Enabled() bool { return true } // Severity returns the severity of the rule. func (or *RequiredOutputRule) Severity() tflint.Severity { return tflint.ERROR } // Check checks whether the module satisfies the interface. // It will search for a variable with the same name as the interface. // It will check the type, default value and nullable attributes. func (vcr *RequiredOutputRule) Check(r tflint.Runner) error { path, err := r.GetModulePath() if err != nil { return err } if !path.IsRoot() { // This rule does not evaluate child modules. return nil } // Define the schema that we want to pull out of the module content. body, err := r.GetModuleContent( outputBodySchema, &tflint.GetModuleContentOption{ExpandMode: tflint.ExpandModeNone}) if err != nil { return err } // Iterate over the outputs and check for the name we are interested in. for _, b := range body.Blocks { if b.Labels[0] == vcr.outputName { return nil } } return r.EmitIssue( vcr, fmt.Sprintf("module owners MUST output the `%s` in their modules", vcr.outputName), hcl.Range{ Filename: "outputs.tf", }, ) }