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