github.com/recobe182/terraform@v0.8.5-0.20170117231232-49ab22a935b7/builtin/providers/aws/resource_aws_s3_bucket_object_test.go (about)

     1  package aws
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  	"os"
     7  	"reflect"
     8  	"sort"
     9  	"testing"
    10  
    11  	"github.com/hashicorp/terraform/helper/acctest"
    12  	"github.com/hashicorp/terraform/helper/resource"
    13  	"github.com/hashicorp/terraform/terraform"
    14  
    15  	"github.com/aws/aws-sdk-go/aws"
    16  	"github.com/aws/aws-sdk-go/service/s3"
    17  )
    18  
    19  func TestAccAWSS3BucketObject_source(t *testing.T) {
    20  	tmpFile, err := ioutil.TempFile("", "tf-acc-s3-obj-source")
    21  	if err != nil {
    22  		t.Fatal(err)
    23  	}
    24  	defer os.Remove(tmpFile.Name())
    25  
    26  	rInt := acctest.RandInt()
    27  	// first write some data to the tempfile just so it's not 0 bytes.
    28  	err = ioutil.WriteFile(tmpFile.Name(), []byte("{anything will do }"), 0644)
    29  	if err != nil {
    30  		t.Fatal(err)
    31  	}
    32  	var obj s3.GetObjectOutput
    33  
    34  	resource.Test(t, resource.TestCase{
    35  		PreCheck:     func() { testAccPreCheck(t) },
    36  		Providers:    testAccProviders,
    37  		CheckDestroy: testAccCheckAWSS3BucketObjectDestroy,
    38  		Steps: []resource.TestStep{
    39  			resource.TestStep{
    40  				Config: testAccAWSS3BucketObjectConfigSource(rInt, tmpFile.Name()),
    41  				Check:  testAccCheckAWSS3BucketObjectExists("aws_s3_bucket_object.object", &obj),
    42  			},
    43  		},
    44  	})
    45  }
    46  
    47  func TestAccAWSS3BucketObject_content(t *testing.T) {
    48  	rInt := acctest.RandInt()
    49  	var obj s3.GetObjectOutput
    50  
    51  	resource.Test(t, resource.TestCase{
    52  		PreCheck:     func() { testAccPreCheck(t) },
    53  		Providers:    testAccProviders,
    54  		CheckDestroy: testAccCheckAWSS3BucketObjectDestroy,
    55  		Steps: []resource.TestStep{
    56  			resource.TestStep{
    57  				PreConfig: func() {},
    58  				Config:    testAccAWSS3BucketObjectConfigContent(rInt),
    59  				Check:     testAccCheckAWSS3BucketObjectExists("aws_s3_bucket_object.object", &obj),
    60  			},
    61  		},
    62  	})
    63  }
    64  
    65  func TestAccAWSS3BucketObject_withContentCharacteristics(t *testing.T) {
    66  	tmpFile, err := ioutil.TempFile("", "tf-acc-s3-obj-content-characteristics")
    67  	if err != nil {
    68  		t.Fatal(err)
    69  	}
    70  	defer os.Remove(tmpFile.Name())
    71  
    72  	rInt := acctest.RandInt()
    73  	// first write some data to the tempfile just so it's not 0 bytes.
    74  	err = ioutil.WriteFile(tmpFile.Name(), []byte("{anything will do }"), 0644)
    75  	if err != nil {
    76  		t.Fatal(err)
    77  	}
    78  
    79  	var obj s3.GetObjectOutput
    80  
    81  	resource.Test(t, resource.TestCase{
    82  		PreCheck:     func() { testAccPreCheck(t) },
    83  		Providers:    testAccProviders,
    84  		CheckDestroy: testAccCheckAWSS3BucketObjectDestroy,
    85  		Steps: []resource.TestStep{
    86  			resource.TestStep{
    87  				Config: testAccAWSS3BucketObjectConfig_withContentCharacteristics(rInt, tmpFile.Name()),
    88  				Check: resource.ComposeTestCheckFunc(
    89  					testAccCheckAWSS3BucketObjectExists("aws_s3_bucket_object.object", &obj),
    90  					resource.TestCheckResourceAttr(
    91  						"aws_s3_bucket_object.object", "content_type", "binary/octet-stream"),
    92  				),
    93  			},
    94  		},
    95  	})
    96  }
    97  
    98  func TestAccAWSS3BucketObject_updates(t *testing.T) {
    99  	tmpFile, err := ioutil.TempFile("", "tf-acc-s3-obj-updates")
   100  	if err != nil {
   101  		t.Fatal(err)
   102  	}
   103  	defer os.Remove(tmpFile.Name())
   104  
   105  	rInt := acctest.RandInt()
   106  	err = ioutil.WriteFile(tmpFile.Name(), []byte("initial object state"), 0644)
   107  	if err != nil {
   108  		t.Fatal(err)
   109  	}
   110  	var obj s3.GetObjectOutput
   111  
   112  	resource.Test(t, resource.TestCase{
   113  		PreCheck:     func() { testAccPreCheck(t) },
   114  		Providers:    testAccProviders,
   115  		CheckDestroy: testAccCheckAWSS3BucketObjectDestroy,
   116  		Steps: []resource.TestStep{
   117  			resource.TestStep{
   118  				Config: testAccAWSS3BucketObjectConfig_updates(rInt, tmpFile.Name()),
   119  				Check: resource.ComposeTestCheckFunc(
   120  					testAccCheckAWSS3BucketObjectExists("aws_s3_bucket_object.object", &obj),
   121  					resource.TestCheckResourceAttr("aws_s3_bucket_object.object", "etag", "647d1d58e1011c743ec67d5e8af87b53"),
   122  				),
   123  			},
   124  			resource.TestStep{
   125  				PreConfig: func() {
   126  					err = ioutil.WriteFile(tmpFile.Name(), []byte("modified object"), 0644)
   127  					if err != nil {
   128  						t.Fatal(err)
   129  					}
   130  				},
   131  				Config: testAccAWSS3BucketObjectConfig_updates(rInt, tmpFile.Name()),
   132  				Check: resource.ComposeTestCheckFunc(
   133  					testAccCheckAWSS3BucketObjectExists("aws_s3_bucket_object.object", &obj),
   134  					resource.TestCheckResourceAttr("aws_s3_bucket_object.object", "etag", "1c7fd13df1515c2a13ad9eb068931f09"),
   135  				),
   136  			},
   137  		},
   138  	})
   139  }
   140  
   141  func TestAccAWSS3BucketObject_updatesWithVersioning(t *testing.T) {
   142  	tmpFile, err := ioutil.TempFile("", "tf-acc-s3-obj-updates-w-versions")
   143  	if err != nil {
   144  		t.Fatal(err)
   145  	}
   146  	defer os.Remove(tmpFile.Name())
   147  
   148  	rInt := acctest.RandInt()
   149  	err = ioutil.WriteFile(tmpFile.Name(), []byte("initial versioned object state"), 0644)
   150  	if err != nil {
   151  		t.Fatal(err)
   152  	}
   153  
   154  	var originalObj, modifiedObj s3.GetObjectOutput
   155  
   156  	resource.Test(t, resource.TestCase{
   157  		PreCheck:     func() { testAccPreCheck(t) },
   158  		Providers:    testAccProviders,
   159  		CheckDestroy: testAccCheckAWSS3BucketObjectDestroy,
   160  		Steps: []resource.TestStep{
   161  			resource.TestStep{
   162  				Config: testAccAWSS3BucketObjectConfig_updatesWithVersioning(rInt, tmpFile.Name()),
   163  				Check: resource.ComposeTestCheckFunc(
   164  					testAccCheckAWSS3BucketObjectExists("aws_s3_bucket_object.object", &originalObj),
   165  					resource.TestCheckResourceAttr("aws_s3_bucket_object.object", "etag", "cee4407fa91906284e2a5e5e03e86b1b"),
   166  				),
   167  			},
   168  			resource.TestStep{
   169  				PreConfig: func() {
   170  					err = ioutil.WriteFile(tmpFile.Name(), []byte("modified versioned object"), 0644)
   171  					if err != nil {
   172  						t.Fatal(err)
   173  					}
   174  				},
   175  				Config: testAccAWSS3BucketObjectConfig_updatesWithVersioning(rInt, tmpFile.Name()),
   176  				Check: resource.ComposeTestCheckFunc(
   177  					testAccCheckAWSS3BucketObjectExists("aws_s3_bucket_object.object", &modifiedObj),
   178  					resource.TestCheckResourceAttr("aws_s3_bucket_object.object", "etag", "00b8c73b1b50e7cc932362c7225b8e29"),
   179  					testAccCheckAWSS3BucketObjectVersionIdDiffers(&originalObj, &modifiedObj),
   180  				),
   181  			},
   182  		},
   183  	})
   184  }
   185  
   186  func testAccCheckAWSS3BucketObjectVersionIdDiffers(first, second *s3.GetObjectOutput) resource.TestCheckFunc {
   187  	return func(s *terraform.State) error {
   188  		if first.VersionId == nil {
   189  			return fmt.Errorf("Expected first object to have VersionId: %s", first)
   190  		}
   191  		if second.VersionId == nil {
   192  			return fmt.Errorf("Expected second object to have VersionId: %s", second)
   193  		}
   194  
   195  		if *first.VersionId == *second.VersionId {
   196  			return fmt.Errorf("Expected Version IDs to differ, but they are equal (%s)", *first.VersionId)
   197  		}
   198  
   199  		return nil
   200  	}
   201  }
   202  
   203  func testAccCheckAWSS3BucketObjectDestroy(s *terraform.State) error {
   204  	s3conn := testAccProvider.Meta().(*AWSClient).s3conn
   205  
   206  	for _, rs := range s.RootModule().Resources {
   207  		if rs.Type != "aws_s3_bucket_object" {
   208  			continue
   209  		}
   210  
   211  		_, err := s3conn.HeadObject(
   212  			&s3.HeadObjectInput{
   213  				Bucket:  aws.String(rs.Primary.Attributes["bucket"]),
   214  				Key:     aws.String(rs.Primary.Attributes["key"]),
   215  				IfMatch: aws.String(rs.Primary.Attributes["etag"]),
   216  			})
   217  		if err == nil {
   218  			return fmt.Errorf("AWS S3 Object still exists: %s", rs.Primary.ID)
   219  		}
   220  	}
   221  	return nil
   222  }
   223  
   224  func testAccCheckAWSS3BucketObjectExists(n string, obj *s3.GetObjectOutput) resource.TestCheckFunc {
   225  	return func(s *terraform.State) error {
   226  		rs, ok := s.RootModule().Resources[n]
   227  		if !ok {
   228  			return fmt.Errorf("Not Found: %s", n)
   229  		}
   230  
   231  		if rs.Primary.ID == "" {
   232  			return fmt.Errorf("No S3 Bucket Object ID is set")
   233  		}
   234  
   235  		s3conn := testAccProvider.Meta().(*AWSClient).s3conn
   236  		out, err := s3conn.GetObject(
   237  			&s3.GetObjectInput{
   238  				Bucket:  aws.String(rs.Primary.Attributes["bucket"]),
   239  				Key:     aws.String(rs.Primary.Attributes["key"]),
   240  				IfMatch: aws.String(rs.Primary.Attributes["etag"]),
   241  			})
   242  		if err != nil {
   243  			return fmt.Errorf("S3Bucket Object error: %s", err)
   244  		}
   245  
   246  		*obj = *out
   247  
   248  		return nil
   249  	}
   250  }
   251  
   252  func TestAccAWSS3BucketObject_kms(t *testing.T) {
   253  	rInt := acctest.RandInt()
   254  	var obj s3.GetObjectOutput
   255  
   256  	resource.Test(t, resource.TestCase{
   257  		PreCheck:     func() { testAccPreCheck(t) },
   258  		Providers:    testAccProviders,
   259  		CheckDestroy: testAccCheckAWSS3BucketObjectDestroy,
   260  		Steps: []resource.TestStep{
   261  			resource.TestStep{
   262  				PreConfig: func() {},
   263  				Config:    testAccAWSS3BucketObjectConfig_withKMSId(rInt),
   264  				Check:     testAccCheckAWSS3BucketObjectExists("aws_s3_bucket_object.object", &obj),
   265  			},
   266  		},
   267  	})
   268  }
   269  
   270  func TestAccAWSS3BucketObject_acl(t *testing.T) {
   271  	rInt := acctest.RandInt()
   272  	var obj s3.GetObjectOutput
   273  
   274  	resource.Test(t, resource.TestCase{
   275  		PreCheck:     func() { testAccPreCheck(t) },
   276  		Providers:    testAccProviders,
   277  		CheckDestroy: testAccCheckAWSS3BucketObjectDestroy,
   278  		Steps: []resource.TestStep{
   279  			resource.TestStep{
   280  				Config: testAccAWSS3BucketObjectConfig_acl(rInt, "private"),
   281  				Check: resource.ComposeTestCheckFunc(
   282  					testAccCheckAWSS3BucketObjectExists(
   283  						"aws_s3_bucket_object.object", &obj),
   284  					resource.TestCheckResourceAttr(
   285  						"aws_s3_bucket_object.object",
   286  						"acl",
   287  						"private"),
   288  					testAccCheckAWSS3BucketObjectAcl(
   289  						"aws_s3_bucket_object.object",
   290  						[]string{"FULL_CONTROL"}),
   291  				),
   292  			},
   293  			resource.TestStep{
   294  				Config: testAccAWSS3BucketObjectConfig_acl(rInt, "public-read"),
   295  				Check: resource.ComposeTestCheckFunc(
   296  					testAccCheckAWSS3BucketObjectExists(
   297  						"aws_s3_bucket_object.object",
   298  						&obj),
   299  					resource.TestCheckResourceAttr(
   300  						"aws_s3_bucket_object.object",
   301  						"acl",
   302  						"public-read"),
   303  					testAccCheckAWSS3BucketObjectAcl(
   304  						"aws_s3_bucket_object.object",
   305  						[]string{"FULL_CONTROL", "READ"}),
   306  				),
   307  			},
   308  		},
   309  	})
   310  }
   311  
   312  func testAccCheckAWSS3BucketObjectAcl(n string, expectedPerms []string) resource.TestCheckFunc {
   313  	return func(s *terraform.State) error {
   314  		rs, _ := s.RootModule().Resources[n]
   315  		s3conn := testAccProvider.Meta().(*AWSClient).s3conn
   316  
   317  		out, err := s3conn.GetObjectAcl(&s3.GetObjectAclInput{
   318  			Bucket: aws.String(rs.Primary.Attributes["bucket"]),
   319  			Key:    aws.String(rs.Primary.Attributes["key"]),
   320  		})
   321  
   322  		if err != nil {
   323  			return fmt.Errorf("GetObjectAcl error: %v", err)
   324  		}
   325  
   326  		var perms []string
   327  		for _, v := range out.Grants {
   328  			perms = append(perms, *v.Permission)
   329  		}
   330  		sort.Strings(perms)
   331  
   332  		if !reflect.DeepEqual(perms, expectedPerms) {
   333  			return fmt.Errorf("Expected ACL permissions to be %v, got %v", expectedPerms, perms)
   334  		}
   335  
   336  		return nil
   337  	}
   338  }
   339  
   340  func TestResourceAWSS3BucketObjectAcl_validation(t *testing.T) {
   341  	_, errors := validateS3BucketObjectAclType("incorrect", "acl")
   342  	if len(errors) == 0 {
   343  		t.Fatalf("Expected to trigger a validation error")
   344  	}
   345  
   346  	var testCases = []struct {
   347  		Value    string
   348  		ErrCount int
   349  	}{
   350  		{
   351  			Value:    "public-read",
   352  			ErrCount: 0,
   353  		},
   354  		{
   355  			Value:    "public-read-write",
   356  			ErrCount: 0,
   357  		},
   358  	}
   359  
   360  	for _, tc := range testCases {
   361  		_, errors := validateS3BucketObjectAclType(tc.Value, "acl")
   362  		if len(errors) != tc.ErrCount {
   363  			t.Fatalf("Expected not to trigger a validation error")
   364  		}
   365  	}
   366  }
   367  
   368  func TestAccAWSS3BucketObject_storageClass(t *testing.T) {
   369  	rInt := acctest.RandInt()
   370  	var obj s3.GetObjectOutput
   371  
   372  	resource.Test(t, resource.TestCase{
   373  		PreCheck:     func() { testAccPreCheck(t) },
   374  		Providers:    testAccProviders,
   375  		CheckDestroy: testAccCheckAWSS3BucketObjectDestroy,
   376  		Steps: []resource.TestStep{
   377  			resource.TestStep{
   378  				PreConfig: func() {},
   379  				Config:    testAccAWSS3BucketObjectConfigContent(rInt),
   380  				Check: resource.ComposeTestCheckFunc(
   381  					testAccCheckAWSS3BucketObjectExists(
   382  						"aws_s3_bucket_object.object",
   383  						&obj),
   384  					resource.TestCheckResourceAttr(
   385  						"aws_s3_bucket_object.object",
   386  						"storage_class",
   387  						"STANDARD"),
   388  					testAccCheckAWSS3BucketObjectStorageClass(
   389  						"aws_s3_bucket_object.object",
   390  						"STANDARD"),
   391  				),
   392  			},
   393  			resource.TestStep{
   394  				Config: testAccAWSS3BucketObjectConfig_storageClass(rInt, "REDUCED_REDUNDANCY"),
   395  				Check: resource.ComposeTestCheckFunc(
   396  					testAccCheckAWSS3BucketObjectExists(
   397  						"aws_s3_bucket_object.object",
   398  						&obj),
   399  					resource.TestCheckResourceAttr(
   400  						"aws_s3_bucket_object.object",
   401  						"storage_class",
   402  						"REDUCED_REDUNDANCY"),
   403  					testAccCheckAWSS3BucketObjectStorageClass(
   404  						"aws_s3_bucket_object.object",
   405  						"REDUCED_REDUNDANCY"),
   406  				),
   407  			},
   408  		},
   409  	})
   410  }
   411  
   412  func TestResourceAWSS3BucketObjectStorageClass_validation(t *testing.T) {
   413  	_, errors := validateS3BucketObjectStorageClassType("incorrect", "storage_class")
   414  	if len(errors) == 0 {
   415  		t.Fatalf("Expected to trigger a validation error")
   416  	}
   417  
   418  	var testCases = []struct {
   419  		Value    string
   420  		ErrCount int
   421  	}{
   422  		{
   423  			Value:    "STANDARD",
   424  			ErrCount: 0,
   425  		},
   426  		{
   427  			Value:    "REDUCED_REDUNDANCY",
   428  			ErrCount: 0,
   429  		},
   430  	}
   431  
   432  	for _, tc := range testCases {
   433  		_, errors := validateS3BucketObjectStorageClassType(tc.Value, "storage_class")
   434  		if len(errors) != tc.ErrCount {
   435  			t.Fatalf("Expected not to trigger a validation error")
   436  		}
   437  	}
   438  }
   439  
   440  func testAccCheckAWSS3BucketObjectStorageClass(n, expectedClass string) resource.TestCheckFunc {
   441  	return func(s *terraform.State) error {
   442  		rs, _ := s.RootModule().Resources[n]
   443  		s3conn := testAccProvider.Meta().(*AWSClient).s3conn
   444  
   445  		out, err := s3conn.HeadObject(&s3.HeadObjectInput{
   446  			Bucket: aws.String(rs.Primary.Attributes["bucket"]),
   447  			Key:    aws.String(rs.Primary.Attributes["key"]),
   448  		})
   449  
   450  		if err != nil {
   451  			return fmt.Errorf("HeadObject error: %v", err)
   452  		}
   453  
   454  		// The "STANDARD" (which is also the default) storage
   455  		// class when set would not be included in the results.
   456  		storageClass := s3.StorageClassStandard
   457  		if out.StorageClass != nil {
   458  			storageClass = *out.StorageClass
   459  		}
   460  
   461  		if storageClass != expectedClass {
   462  			return fmt.Errorf("Expected Storage Class to be %v, got %v",
   463  				expectedClass, storageClass)
   464  		}
   465  
   466  		return nil
   467  	}
   468  }
   469  
   470  func testAccAWSS3BucketObjectConfigSource(randInt int, source string) string {
   471  	return fmt.Sprintf(`
   472  resource "aws_s3_bucket" "object_bucket" {
   473      bucket = "tf-object-test-bucket-%d"
   474  }
   475  resource "aws_s3_bucket_object" "object" {
   476  	bucket = "${aws_s3_bucket.object_bucket.bucket}"
   477  	key = "test-key"
   478  	source = "%s"
   479  	content_type = "binary/octet-stream"
   480  }
   481  `, randInt, source)
   482  }
   483  
   484  func testAccAWSS3BucketObjectConfig_withContentCharacteristics(randInt int, source string) string {
   485  	return fmt.Sprintf(`
   486  resource "aws_s3_bucket" "object_bucket_2" {
   487  	bucket = "tf-object-test-bucket-%d"
   488  }
   489  
   490  resource "aws_s3_bucket_object" "object" {
   491  	bucket = "${aws_s3_bucket.object_bucket_2.bucket}"
   492  	key = "test-key"
   493  	source = "%s"
   494  	content_language = "en"
   495  	content_type = "binary/octet-stream"
   496  }
   497  `, randInt, source)
   498  }
   499  
   500  func testAccAWSS3BucketObjectConfigContent(randInt int) string {
   501  	return fmt.Sprintf(`
   502  resource "aws_s3_bucket" "object_bucket" {
   503          bucket = "tf-object-test-bucket-%d"
   504  }
   505  resource "aws_s3_bucket_object" "object" {
   506          bucket = "${aws_s3_bucket.object_bucket.bucket}"
   507          key = "test-key"
   508          content = "some_bucket_content"
   509  }
   510  `, randInt)
   511  }
   512  
   513  func testAccAWSS3BucketObjectConfig_updates(randInt int, source string) string {
   514  	return fmt.Sprintf(`
   515  resource "aws_s3_bucket" "object_bucket_3" {
   516  	bucket = "tf-object-test-bucket-%d"
   517  }
   518  
   519  resource "aws_s3_bucket_object" "object" {
   520  	bucket = "${aws_s3_bucket.object_bucket_3.bucket}"
   521  	key = "updateable-key"
   522  	source = "%s"
   523  	etag = "${md5(file("%s"))}"
   524  }
   525  `, randInt, source, source)
   526  }
   527  
   528  func testAccAWSS3BucketObjectConfig_updatesWithVersioning(randInt int, source string) string {
   529  	return fmt.Sprintf(`
   530  resource "aws_s3_bucket" "object_bucket_3" {
   531  	bucket = "tf-object-test-bucket-%d"
   532  	versioning {
   533  		enabled = true
   534  	}
   535  }
   536  
   537  resource "aws_s3_bucket_object" "object" {
   538  	bucket = "${aws_s3_bucket.object_bucket_3.bucket}"
   539  	key = "updateable-key"
   540  	source = "%s"
   541  	etag = "${md5(file("%s"))}"
   542  }
   543  `, randInt, source, source)
   544  }
   545  
   546  func testAccAWSS3BucketObjectConfig_withKMSId(randInt int) string {
   547  	return fmt.Sprintf(`
   548  resource "aws_kms_key" "kms_key_1" {
   549  }
   550  
   551  resource "aws_s3_bucket" "object_bucket_2" {
   552  	bucket = "tf-object-test-bucket-%d"
   553  }
   554  
   555  resource "aws_s3_bucket_object" "object" {
   556  	bucket = "${aws_s3_bucket.object_bucket_2.bucket}"
   557  	key = "test-key"
   558  	content = "stuff"
   559  	kms_key_id = "${aws_kms_key.kms_key_1.arn}"
   560  }
   561  `, randInt)
   562  }
   563  
   564  func testAccAWSS3BucketObjectConfig_acl(randInt int, acl string) string {
   565  	return fmt.Sprintf(`
   566  resource "aws_s3_bucket" "object_bucket" {
   567          bucket = "tf-object-test-bucket-%d"
   568  }
   569  resource "aws_s3_bucket_object" "object" {
   570          bucket = "${aws_s3_bucket.object_bucket.bucket}"
   571          key = "test-key"
   572          content = "some_bucket_content"
   573          acl = "%s"
   574  }
   575  `, randInt, acl)
   576  }
   577  
   578  func testAccAWSS3BucketObjectConfig_storageClass(randInt int, storage_class string) string {
   579  	return fmt.Sprintf(`
   580  resource "aws_s3_bucket" "object_bucket" {
   581          bucket = "tf-object-test-bucket-%d"
   582  }
   583  resource "aws_s3_bucket_object" "object" {
   584          bucket = "${aws_s3_bucket.object_bucket.bucket}"
   585          key = "test-key"
   586          content = "some_bucket_content"
   587          storage_class = "%s"
   588  }
   589  `, randInt, storage_class)
   590  }