in rules/provider_version.go [46:121]
func (m *ProviderVersionRule) Check(r tflint.Runner) error {
ver, err := goverison.NewVersion(m.Version)
if err != nil {
return fmt.Errorf("invalid version constraint: %s", err)
}
content, err := r.GetModuleContent(&hclext.BodySchema{
Blocks: []hclext.BlockSchema{
{
Type: "terraform",
Body: &hclext.BodySchema{
Blocks: []hclext.BlockSchema{
{
Type: "required_providers",
Body: &hclext.BodySchema{
Attributes: []hclext.AttributeSchema{
{
Name: m.ProviderName,
},
},
},
},
},
},
},
},
}, &tflint.GetModuleContentOption{ExpandMode: tflint.ExpandModeNone})
if err != nil {
return err
}
if len(content.Blocks) == 0 {
return nil
}
providerFound := false
requiredProviderFound := false
for _, tb := range content.Blocks {
for _, rpb := range tb.Body.Blocks {
requiredProviderFound = true
providerAttr, ok := rpb.Body.Attributes[m.ProviderName]
if !ok {
continue
}
providerFound = true
provider := struct {
Source string `cty:"source"`
Version string `cty:"version"`
}{}
wantType := cty.Object(map[string]cty.Type{
"source": cty.String,
"version": cty.String,
})
if err = r.EvaluateExpr(providerAttr.Expr, &provider, &tflint.EvaluateExprOption{WantType: &wantType}); err != nil {
return err
}
if !strings.EqualFold(provider.Source, m.ProviderSource) {
return r.EmitIssue(m, fmt.Sprintf("provider `%s`'s source should be %s, got %s", m.ProviderName, m.ProviderSource, provider.Source), providerAttr.Range)
}
constraint, err := goverison.NewConstraint(provider.Version)
if err != nil {
return fmt.Errorf("invalid version constraint: %s", err)
}
if constraint.Check(ver) {
continue
}
if err = r.EmitIssue(m, fmt.Sprintf("provider `%s`'s version should satisfy %s, got %s. Recommended version constraint `%s`", m.ProviderName, m.Version, provider.Version, m.RecommendedConstraint), providerAttr.Range); err != nil {
return err
}
}
}
if !requiredProviderFound {
return nil
}
if !providerFound && m.MustExist {
return r.EmitIssue(m, fmt.Sprintf("`%s` provider should be declared in the `required_providers` block", m.ProviderName), content.Blocks[0].DefRange)
}
return nil
}