github.com/anfernee/terraform@v0.6.16-0.20160430000239-06e5085a92f2/builtin/providers/aws/resource_aws_lambda_function_test.go (about)

     1  package aws
     2  
     3  import (
     4  	"archive/zip"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"os"
     8  	"path/filepath"
     9  	"regexp"
    10  	"strings"
    11  	"testing"
    12  
    13  	"github.com/aws/aws-sdk-go/aws"
    14  	"github.com/aws/aws-sdk-go/service/lambda"
    15  	"github.com/hashicorp/terraform/helper/acctest"
    16  	"github.com/hashicorp/terraform/helper/resource"
    17  	"github.com/hashicorp/terraform/terraform"
    18  )
    19  
    20  func TestAccAWSLambdaFunction_basic(t *testing.T) {
    21  	var conf lambda.GetFunctionOutput
    22  
    23  	resource.Test(t, resource.TestCase{
    24  		PreCheck:     func() { testAccPreCheck(t) },
    25  		Providers:    testAccProviders,
    26  		CheckDestroy: testAccCheckLambdaFunctionDestroy,
    27  		Steps: []resource.TestStep{
    28  			resource.TestStep{
    29  				Config: testAccAWSLambdaConfigBasic,
    30  				Check: resource.ComposeTestCheckFunc(
    31  					testAccCheckAwsLambdaFunctionExists("aws_lambda_function.lambda_function_test", "example_lambda_name", &conf),
    32  					testAccCheckAwsLambdaFunctionName(&conf, "example_lambda_name"),
    33  					testAccCheckAwsLambdaFunctionArnHasSuffix(&conf, ":example_lambda_name"),
    34  				),
    35  			},
    36  		},
    37  	})
    38  }
    39  
    40  func TestAccAWSLambdaFunction_VPC(t *testing.T) {
    41  	var conf lambda.GetFunctionOutput
    42  
    43  	resource.Test(t, resource.TestCase{
    44  		PreCheck:     func() { testAccPreCheck(t) },
    45  		Providers:    testAccProviders,
    46  		CheckDestroy: testAccCheckLambdaFunctionDestroy,
    47  		Steps: []resource.TestStep{
    48  			resource.TestStep{
    49  				Config: testAccAWSLambdaConfigWithVPC,
    50  				Check: resource.ComposeTestCheckFunc(
    51  					testAccCheckAwsLambdaFunctionExists("aws_lambda_function.lambda_function_test", "example_lambda_name", &conf),
    52  					testAccCheckAwsLambdaFunctionName(&conf, "example_lambda_name"),
    53  					testAccCheckAwsLambdaFunctionArnHasSuffix(&conf, ":example_lambda_name"),
    54  					testAccCheckAWSLambdaFunctionVersion(&conf, "$LATEST"),
    55  					resource.TestCheckResourceAttr("aws_lambda_function.lambda_function_test", "vpc_config.#", "1"),
    56  					resource.TestCheckResourceAttr("aws_lambda_function.lambda_function_test", "vpc_config.0.subnet_ids.#", "1"),
    57  					resource.TestCheckResourceAttr("aws_lambda_function.lambda_function_test", "vpc_config.0.security_group_ids.#", "1"),
    58  					resource.TestMatchResourceAttr("aws_lambda_function.lambda_function_test", "vpc_config.0.vpc_id", regexp.MustCompile("^vpc-")),
    59  				),
    60  			},
    61  		},
    62  	})
    63  }
    64  
    65  func TestAccAWSLambdaFunction_s3(t *testing.T) {
    66  	var conf lambda.GetFunctionOutput
    67  
    68  	resource.Test(t, resource.TestCase{
    69  		PreCheck:     func() { testAccPreCheck(t) },
    70  		Providers:    testAccProviders,
    71  		CheckDestroy: testAccCheckLambdaFunctionDestroy,
    72  		Steps: []resource.TestStep{
    73  			resource.TestStep{
    74  				Config: testAccAWSLambdaConfigS3,
    75  				Check: resource.ComposeTestCheckFunc(
    76  					testAccCheckAwsLambdaFunctionExists("aws_lambda_function.lambda_function_s3test", "example_lambda_name_s3", &conf),
    77  					testAccCheckAwsLambdaFunctionName(&conf, "example_lambda_name_s3"),
    78  					testAccCheckAwsLambdaFunctionArnHasSuffix(&conf, ":example_lambda_name_s3"),
    79  					testAccCheckAWSLambdaFunctionVersion(&conf, "$LATEST"),
    80  				),
    81  			},
    82  		},
    83  	})
    84  }
    85  
    86  func TestAccAWSLambdaFunction_localUpdate(t *testing.T) {
    87  	var conf lambda.GetFunctionOutput
    88  
    89  	path, zipFile, err := createTempFile("lambda_localUpdate")
    90  	if err != nil {
    91  		t.Fatal(err)
    92  	}
    93  	defer os.Remove(path)
    94  
    95  	resource.Test(t, resource.TestCase{
    96  		PreCheck:     func() { testAccPreCheck(t) },
    97  		Providers:    testAccProviders,
    98  		CheckDestroy: testAccCheckLambdaFunctionDestroy,
    99  		Steps: []resource.TestStep{
   100  			resource.TestStep{
   101  				PreConfig: func() {
   102  					testAccCreateZipFromFiles(map[string]string{"test-fixtures/lambda_func.js": "lambda.js"}, zipFile)
   103  				},
   104  				Config: genAWSLambdaFunctionConfig_local(path),
   105  				Check: resource.ComposeTestCheckFunc(
   106  					testAccCheckAwsLambdaFunctionExists("aws_lambda_function.lambda_function_local", "tf_acc_lambda_name_local", &conf),
   107  					testAccCheckAwsLambdaFunctionName(&conf, "tf_acc_lambda_name_local"),
   108  					testAccCheckAwsLambdaFunctionArnHasSuffix(&conf, "tf_acc_lambda_name_local"),
   109  					testAccCheckAwsLambdaSourceCodeHash(&conf, "un6qF9S9hKvXbWwJ6m2EYaVCWjcr0PCZWiTV3h4zB0I="),
   110  				),
   111  			},
   112  			resource.TestStep{
   113  				PreConfig: func() {
   114  					testAccCreateZipFromFiles(map[string]string{"test-fixtures/lambda_func_modified.js": "lambda.js"}, zipFile)
   115  				},
   116  				Config: genAWSLambdaFunctionConfig_local(path),
   117  				Check: resource.ComposeTestCheckFunc(
   118  					testAccCheckAwsLambdaFunctionExists("aws_lambda_function.lambda_function_local", "tf_acc_lambda_name_local", &conf),
   119  					testAccCheckAwsLambdaFunctionName(&conf, "tf_acc_lambda_name_local"),
   120  					testAccCheckAwsLambdaFunctionArnHasSuffix(&conf, "tf_acc_lambda_name_local"),
   121  					testAccCheckAwsLambdaSourceCodeHash(&conf, "Y5Jf4Si63UDy1wKNfPs+U56ZL0NxsieKPt9EwRl4GQM="),
   122  				),
   123  			},
   124  		},
   125  	})
   126  }
   127  
   128  func TestAccAWSLambdaFunction_s3Update(t *testing.T) {
   129  	var conf lambda.GetFunctionOutput
   130  
   131  	path, zipFile, err := createTempFile("lambda_s3Update")
   132  	if err != nil {
   133  		t.Fatal(err)
   134  	}
   135  	defer os.Remove(path)
   136  
   137  	bucketName := fmt.Sprintf("tf-acc-lambda-s3-deployments-%d", randomInteger)
   138  	key := "lambda-func.zip"
   139  
   140  	resource.Test(t, resource.TestCase{
   141  		PreCheck:     func() { testAccPreCheck(t) },
   142  		Providers:    testAccProviders,
   143  		CheckDestroy: testAccCheckLambdaFunctionDestroy,
   144  		Steps: []resource.TestStep{
   145  			resource.TestStep{
   146  				PreConfig: func() {
   147  					// Upload 1st version
   148  					testAccCreateZipFromFiles(map[string]string{"test-fixtures/lambda_func.js": "lambda.js"}, zipFile)
   149  				},
   150  				Config: genAWSLambdaFunctionConfig_s3(bucketName, key, path),
   151  				Check: resource.ComposeTestCheckFunc(
   152  					testAccCheckAwsLambdaFunctionExists("aws_lambda_function.lambda_function_s3", "tf_acc_lambda_name_s3", &conf),
   153  					testAccCheckAwsLambdaFunctionName(&conf, "tf_acc_lambda_name_s3"),
   154  					testAccCheckAwsLambdaFunctionArnHasSuffix(&conf, "tf_acc_lambda_name_s3"),
   155  					testAccCheckAwsLambdaSourceCodeHash(&conf, "un6qF9S9hKvXbWwJ6m2EYaVCWjcr0PCZWiTV3h4zB0I="),
   156  				),
   157  			},
   158  			resource.TestStep{
   159  				ExpectNonEmptyPlan: true,
   160  				PreConfig: func() {
   161  					// Upload 2nd version
   162  					testAccCreateZipFromFiles(map[string]string{"test-fixtures/lambda_func_modified.js": "lambda.js"}, zipFile)
   163  				},
   164  				Config: genAWSLambdaFunctionConfig_s3(bucketName, key, path),
   165  			},
   166  			// Extra step because of missing ComputedWhen
   167  			// See https://github.com/hashicorp/terraform/pull/4846 & https://github.com/hashicorp/terraform/pull/5330
   168  			resource.TestStep{
   169  				Config: genAWSLambdaFunctionConfig_s3(bucketName, key, path),
   170  				Check: resource.ComposeTestCheckFunc(
   171  					testAccCheckAwsLambdaFunctionExists("aws_lambda_function.lambda_function_s3", "tf_acc_lambda_name_s3", &conf),
   172  					testAccCheckAwsLambdaFunctionName(&conf, "tf_acc_lambda_name_s3"),
   173  					testAccCheckAwsLambdaFunctionArnHasSuffix(&conf, "tf_acc_lambda_name_s3"),
   174  					testAccCheckAwsLambdaSourceCodeHash(&conf, "Y5Jf4Si63UDy1wKNfPs+U56ZL0NxsieKPt9EwRl4GQM="),
   175  				),
   176  			},
   177  		},
   178  	})
   179  }
   180  
   181  func testAccCheckLambdaFunctionDestroy(s *terraform.State) error {
   182  	conn := testAccProvider.Meta().(*AWSClient).lambdaconn
   183  
   184  	for _, rs := range s.RootModule().Resources {
   185  		if rs.Type != "aws_lambda_function" {
   186  			continue
   187  		}
   188  
   189  		_, err := conn.GetFunction(&lambda.GetFunctionInput{
   190  			FunctionName: aws.String(rs.Primary.ID),
   191  		})
   192  
   193  		if err == nil {
   194  			return fmt.Errorf("Lambda Function still exists")
   195  		}
   196  
   197  	}
   198  
   199  	return nil
   200  
   201  }
   202  
   203  func testAccCheckAwsLambdaFunctionExists(res, funcName string, function *lambda.GetFunctionOutput) resource.TestCheckFunc {
   204  	// Wait for IAM role
   205  	return func(s *terraform.State) error {
   206  		rs, ok := s.RootModule().Resources[res]
   207  		if !ok {
   208  			return fmt.Errorf("Lambda function not found: %s", res)
   209  		}
   210  
   211  		if rs.Primary.ID == "" {
   212  			return fmt.Errorf("Lambda function ID not set")
   213  		}
   214  
   215  		conn := testAccProvider.Meta().(*AWSClient).lambdaconn
   216  
   217  		params := &lambda.GetFunctionInput{
   218  			FunctionName: aws.String(funcName),
   219  		}
   220  
   221  		getFunction, err := conn.GetFunction(params)
   222  		if err != nil {
   223  			return err
   224  		}
   225  
   226  		*function = *getFunction
   227  
   228  		return nil
   229  	}
   230  }
   231  
   232  func testAccCheckAwsLambdaFunctionName(function *lambda.GetFunctionOutput, expectedName string) resource.TestCheckFunc {
   233  	return func(s *terraform.State) error {
   234  		c := function.Configuration
   235  		if *c.FunctionName != expectedName {
   236  			return fmt.Errorf("Expected function name %s, got %s", expectedName, *c.FunctionName)
   237  		}
   238  
   239  		return nil
   240  	}
   241  }
   242  
   243  func testAccCheckAWSLambdaFunctionVersion(function *lambda.GetFunctionOutput, expectedVersion string) resource.TestCheckFunc {
   244  	return func(s *terraform.State) error {
   245  		c := function.Configuration
   246  		if *c.Version != expectedVersion {
   247  			return fmt.Errorf("Expected version %s, got %s", expectedVersion, *c.Version)
   248  		}
   249  		return nil
   250  	}
   251  }
   252  
   253  func testAccCheckAwsLambdaFunctionArnHasSuffix(function *lambda.GetFunctionOutput, arnSuffix string) resource.TestCheckFunc {
   254  	return func(s *terraform.State) error {
   255  		c := function.Configuration
   256  		if !strings.HasSuffix(*c.FunctionArn, arnSuffix) {
   257  			return fmt.Errorf("Expected function ARN %s to have suffix %s", *c.FunctionArn, arnSuffix)
   258  		}
   259  
   260  		return nil
   261  	}
   262  }
   263  
   264  func testAccCheckAwsLambdaSourceCodeHash(function *lambda.GetFunctionOutput, expectedHash string) resource.TestCheckFunc {
   265  	return func(s *terraform.State) error {
   266  		c := function.Configuration
   267  		if *c.CodeSha256 != expectedHash {
   268  			return fmt.Errorf("Expected code hash %s, got %s", expectedHash, *c.CodeSha256)
   269  		}
   270  
   271  		return nil
   272  	}
   273  }
   274  
   275  func testAccCreateZipFromFiles(files map[string]string, zipFile *os.File) error {
   276  	zipFile.Truncate(0)
   277  	zipFile.Seek(0, 0)
   278  
   279  	w := zip.NewWriter(zipFile)
   280  
   281  	for source, destination := range files {
   282  		f, err := w.Create(destination)
   283  		if err != nil {
   284  			return err
   285  		}
   286  
   287  		fileContent, err := ioutil.ReadFile(source)
   288  		if err != nil {
   289  			return err
   290  		}
   291  
   292  		_, err = f.Write(fileContent)
   293  		if err != nil {
   294  			return err
   295  		}
   296  	}
   297  
   298  	err := w.Close()
   299  	if err != nil {
   300  		return err
   301  	}
   302  
   303  	return w.Flush()
   304  }
   305  
   306  func createTempFile(prefix string) (string, *os.File, error) {
   307  	f, err := ioutil.TempFile(os.TempDir(), prefix)
   308  	if err != nil {
   309  		return "", nil, err
   310  	}
   311  
   312  	pathToFile, err := filepath.Abs(f.Name())
   313  	if err != nil {
   314  		return "", nil, err
   315  	}
   316  	return pathToFile, f, nil
   317  }
   318  
   319  const baseAccAWSLambdaConfig = `
   320  resource "aws_iam_role_policy" "iam_policy_for_lambda" {
   321      name = "iam_policy_for_lambda"
   322      role = "${aws_iam_role.iam_for_lambda.id}"
   323      policy = <<EOF
   324  {
   325    "Version": "2012-10-17",
   326    "Statement": [
   327          {
   328              "Effect": "Allow",
   329              "Action": [
   330                  "logs:CreateLogGroup",
   331                  "logs:CreateLogStream",
   332                  "logs:PutLogEvents"
   333              ],
   334              "Resource": "arn:aws:logs:*:*:*"
   335          },
   336      {
   337        "Effect": "Allow",
   338        "Action": [
   339          "ec2:CreateNetworkInterface"
   340        ],
   341        "Resource": [
   342          "*"
   343        ]
   344      }
   345    ]
   346  }
   347  EOF
   348  }
   349  
   350  resource "aws_iam_role" "iam_for_lambda" {
   351      name = "iam_for_lambda"
   352      assume_role_policy = <<EOF
   353  {
   354    "Version": "2012-10-17",
   355    "Statement": [
   356      {
   357        "Action": "sts:AssumeRole",
   358        "Principal": {
   359          "Service": "lambda.amazonaws.com"
   360        },
   361        "Effect": "Allow",
   362        "Sid": ""
   363      }
   364    ]
   365  }
   366  EOF
   367  }
   368  
   369  resource "aws_vpc" "vpc_for_lambda" {
   370      cidr_block = "10.0.0.0/16"
   371  }
   372  
   373  resource "aws_subnet" "subnet_for_lambda" {
   374      vpc_id = "${aws_vpc.vpc_for_lambda.id}"
   375      cidr_block = "10.0.1.0/24"
   376  
   377      tags {
   378          Name = "lambda"
   379      }
   380  }
   381  
   382  resource "aws_security_group" "sg_for_lambda" {
   383    name = "sg_for_lambda"
   384    description = "Allow all inbound traffic for lambda test"
   385    vpc_id = "${aws_vpc.vpc_for_lambda.id}"
   386  
   387    ingress {
   388        from_port = 0
   389        to_port = 0
   390        protocol = "-1"
   391        cidr_blocks = ["0.0.0.0/0"]
   392    }
   393  
   394    egress {
   395        from_port = 0
   396        to_port = 0
   397        protocol = "-1"
   398        cidr_blocks = ["0.0.0.0/0"]
   399    }
   400  }
   401  
   402  `
   403  
   404  const testAccAWSLambdaConfigBasic = baseAccAWSLambdaConfig + `
   405  resource "aws_lambda_function" "lambda_function_test" {
   406      filename = "test-fixtures/lambdatest.zip"
   407      function_name = "example_lambda_name"
   408      role = "${aws_iam_role.iam_for_lambda.arn}"
   409      handler = "exports.example"
   410  }
   411  `
   412  
   413  const testAccAWSLambdaConfigWithVPC = baseAccAWSLambdaConfig + `
   414  resource "aws_lambda_function" "lambda_function_test" {
   415      filename = "test-fixtures/lambdatest.zip"
   416      function_name = "example_lambda_name"
   417      role = "${aws_iam_role.iam_for_lambda.arn}"
   418      handler = "exports.example"
   419  
   420      vpc_config = {
   421          subnet_ids = ["${aws_subnet.subnet_for_lambda.id}"]
   422          security_group_ids = ["${aws_security_group.sg_for_lambda.id}"]
   423      }
   424  }
   425  `
   426  
   427  var testAccAWSLambdaConfigS3 = fmt.Sprintf(`
   428  resource "aws_s3_bucket" "lambda_bucket" {
   429    bucket = "tf-test-bucket-%d"
   430  }
   431  
   432  resource "aws_s3_bucket_object" "lambda_code" {
   433    bucket = "${aws_s3_bucket.lambda_bucket.id}"
   434    key = "lambdatest.zip"
   435    source = "test-fixtures/lambdatest.zip"
   436  }
   437  
   438  resource "aws_iam_role" "iam_for_lambda" {
   439      name = "iam_for_lambda"
   440      assume_role_policy = <<EOF
   441  {
   442    "Version": "2012-10-17",
   443    "Statement": [
   444      {
   445        "Action": "sts:AssumeRole",
   446        "Principal": {
   447          "Service": "lambda.amazonaws.com"
   448        },
   449        "Effect": "Allow",
   450        "Sid": ""
   451      }
   452    ]
   453  }
   454  EOF
   455  }
   456  
   457  resource "aws_lambda_function" "lambda_function_s3test" {
   458      s3_bucket = "${aws_s3_bucket.lambda_bucket.id}"
   459      s3_key = "${aws_s3_bucket_object.lambda_code.id}"
   460      function_name = "example_lambda_name_s3"
   461      role = "${aws_iam_role.iam_for_lambda.arn}"
   462      handler = "exports.example"
   463  }
   464  `, acctest.RandInt())
   465  
   466  const testAccAWSLambdaFunctionConfig_local_tpl = `
   467  resource "aws_iam_role" "iam_for_lambda" {
   468      name = "iam_for_lambda"
   469      assume_role_policy = <<EOF
   470  {
   471    "Version": "2012-10-17",
   472    "Statement": [
   473      {
   474        "Action": "sts:AssumeRole",
   475        "Principal": {
   476          "Service": "lambda.amazonaws.com"
   477        },
   478        "Effect": "Allow",
   479        "Sid": ""
   480      }
   481    ]
   482  }
   483  EOF
   484  }
   485  resource "aws_lambda_function" "lambda_function_local" {
   486      filename = "%s"
   487      source_code_hash = "${base64sha256(file("%s"))}"
   488      function_name = "tf_acc_lambda_name_local"
   489      role = "${aws_iam_role.iam_for_lambda.arn}"
   490      handler = "exports.example"
   491  }
   492  `
   493  
   494  func genAWSLambdaFunctionConfig_local(filePath string) string {
   495  	return fmt.Sprintf(testAccAWSLambdaFunctionConfig_local_tpl,
   496  		filePath, filePath)
   497  }
   498  
   499  const testAccAWSLambdaFunctionConfig_s3_tpl = `
   500  resource "aws_s3_bucket" "artifacts" {
   501  	bucket = "%s"
   502  	acl = "private"
   503  	force_destroy = true
   504  	versioning {
   505  		enabled = true
   506  	}
   507  }
   508  resource "aws_s3_bucket_object" "o" {
   509  	bucket = "${aws_s3_bucket.artifacts.bucket}"
   510  	key = "%s"
   511  	source = "%s"
   512  	etag = "${md5(file("%s"))}"
   513  }
   514  resource "aws_iam_role" "iam_for_lambda" {
   515      name = "iam_for_lambda"
   516      assume_role_policy = <<EOF
   517  {
   518    "Version": "2012-10-17",
   519    "Statement": [
   520      {
   521        "Action": "sts:AssumeRole",
   522        "Principal": {
   523          "Service": "lambda.amazonaws.com"
   524        },
   525        "Effect": "Allow",
   526        "Sid": ""
   527      }
   528    ]
   529  }
   530  EOF
   531  }
   532  resource "aws_lambda_function" "lambda_function_s3" {
   533  	s3_bucket = "${aws_s3_bucket_object.o.bucket}"
   534  	s3_key = "${aws_s3_bucket_object.o.key}"
   535  	s3_object_version = "${aws_s3_bucket_object.o.version_id}"
   536      function_name = "tf_acc_lambda_name_s3"
   537      role = "${aws_iam_role.iam_for_lambda.arn}"
   538      handler = "exports.example"
   539  }
   540  `
   541  
   542  func genAWSLambdaFunctionConfig_s3(bucket, key, path string) string {
   543  	return fmt.Sprintf(testAccAWSLambdaFunctionConfig_s3_tpl,
   544  		bucket, key, path, path)
   545  }