github.com/wata727/tflint@v0.12.2-0.20191013070026-96dd0d36f385/rules/awsrules/aws_launch_configuration_invalid_image_id.go (about)

     1  package awsrules
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  
     7  	"github.com/aws/aws-sdk-go/aws"
     8  	"github.com/aws/aws-sdk-go/aws/awserr"
     9  	"github.com/aws/aws-sdk-go/service/ec2"
    10  	hcl "github.com/hashicorp/hcl/v2"
    11  	"github.com/wata727/tflint/tflint"
    12  )
    13  
    14  // AwsLaunchConfigurationInvalidImageIDRule checks whether "aws_instance" has invalid AMI ID
    15  type AwsLaunchConfigurationInvalidImageIDRule struct {
    16  	resourceType  string
    17  	attributeName string
    18  	amiIDs        map[string]bool
    19  }
    20  
    21  // NewAwsLaunchConfigurationInvalidImageIDRule returns new rule with default attributes
    22  func NewAwsLaunchConfigurationInvalidImageIDRule() *AwsLaunchConfigurationInvalidImageIDRule {
    23  	return &AwsLaunchConfigurationInvalidImageIDRule{
    24  		resourceType:  "aws_launch_configuration",
    25  		attributeName: "image_id",
    26  		amiIDs:        map[string]bool{},
    27  	}
    28  }
    29  
    30  // Name returns the rule name
    31  func (r *AwsLaunchConfigurationInvalidImageIDRule) Name() string {
    32  	return "aws_launch_configuration_invalid_image_id"
    33  }
    34  
    35  // Enabled returns whether the rule is enabled by default
    36  func (r *AwsLaunchConfigurationInvalidImageIDRule) Enabled() bool {
    37  	return true
    38  }
    39  
    40  // Severity returns the rule severity
    41  func (r *AwsLaunchConfigurationInvalidImageIDRule) Severity() string {
    42  	return tflint.ERROR
    43  }
    44  
    45  // Link returns the rule reference link
    46  func (r *AwsLaunchConfigurationInvalidImageIDRule) Link() string {
    47  	return ""
    48  }
    49  
    50  // Check checks whether "aws_instance" has invalid AMI ID
    51  func (r *AwsLaunchConfigurationInvalidImageIDRule) Check(runner *tflint.Runner) error {
    52  	log.Printf("[TRACE] Check `%s` rule for `%s` runner", r.Name(), runner.TFConfigPath())
    53  
    54  	return runner.WalkResourceAttributes(r.resourceType, r.attributeName, func(attribute *hcl.Attribute) error {
    55  		var ami string
    56  		err := runner.EvaluateExpr(attribute.Expr, &ami)
    57  
    58  		return runner.EnsureNoError(err, func() error {
    59  			if !r.amiIDs[ami] {
    60  				log.Printf("[DEBUG] Fetch AMI images: %s", ami)
    61  				resp, err := runner.AwsClient.EC2.DescribeImages(&ec2.DescribeImagesInput{
    62  					ImageIds: aws.StringSlice([]string{ami}),
    63  				})
    64  				if err != nil {
    65  					if aerr, ok := err.(awserr.Error); ok {
    66  						switch aerr.Code() {
    67  						case "InvalidAMIID.Malformed":
    68  							fallthrough
    69  						case "InvalidAMIID.NotFound":
    70  							fallthrough
    71  						case "InvalidAMIID.Unavailable":
    72  							runner.EmitIssue(
    73  								r,
    74  								fmt.Sprintf("\"%s\" is invalid image ID.", ami),
    75  								attribute.Expr.Range(),
    76  							)
    77  							return nil
    78  						}
    79  					}
    80  					err := &tflint.Error{
    81  						Code:    tflint.ExternalAPIError,
    82  						Level:   tflint.ErrorLevel,
    83  						Message: "An error occurred while describing images",
    84  						Cause:   err,
    85  					}
    86  					log.Printf("[ERROR] %s", err)
    87  					return err
    88  				}
    89  
    90  				if len(resp.Images) != 0 {
    91  					for _, image := range resp.Images {
    92  						r.amiIDs[*image.ImageId] = true
    93  					}
    94  				} else {
    95  					runner.EmitIssue(
    96  						r,
    97  						fmt.Sprintf("\"%s\" is invalid image ID.", ami),
    98  						attribute.Expr.Range(),
    99  					)
   100  				}
   101  			}
   102  			return nil
   103  		})
   104  	})
   105  }