github.com/ndarilek/terraform@v0.3.8-0.20150320140257-d3135c1b2bac/builtin/providers/aws/resource_aws_instance_test.go (about)

     1  package aws
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  	"testing"
     7  
     8  	"github.com/hashicorp/aws-sdk-go/aws"
     9  	"github.com/hashicorp/aws-sdk-go/gen/ec2"
    10  	"github.com/hashicorp/terraform/helper/resource"
    11  	"github.com/hashicorp/terraform/helper/schema"
    12  	"github.com/hashicorp/terraform/terraform"
    13  )
    14  
    15  func TestAccAWSInstance_normal(t *testing.T) {
    16  	var v ec2.Instance
    17  	var vol *ec2.Volume
    18  
    19  	testCheck := func(*terraform.State) error {
    20  		if *v.Placement.AvailabilityZone != "us-west-2a" {
    21  			return fmt.Errorf("bad availability zone: %#v", *v.Placement.AvailabilityZone)
    22  		}
    23  
    24  		if len(v.SecurityGroups) == 0 {
    25  			return fmt.Errorf("no security groups: %#v", v.SecurityGroups)
    26  		}
    27  		if *v.SecurityGroups[0].GroupName != "tf_test_foo" {
    28  			return fmt.Errorf("no security groups: %#v", v.SecurityGroups)
    29  		}
    30  
    31  		return nil
    32  	}
    33  
    34  	resource.Test(t, resource.TestCase{
    35  		PreCheck:     func() { testAccPreCheck(t) },
    36  		Providers:    testAccProviders,
    37  		CheckDestroy: testAccCheckInstanceDestroy,
    38  		Steps: []resource.TestStep{
    39  			// Create a volume to cover #1249
    40  			resource.TestStep{
    41  				// Need a resource in this config so the provisioner will be available
    42  				Config: testAccInstanceConfig_pre,
    43  				Check: func(*terraform.State) error {
    44  					conn := testAccProvider.Meta().(*AWSClient).ec2conn
    45  					var err error
    46  					vol, err = conn.CreateVolume(&ec2.CreateVolumeRequest{
    47  						AvailabilityZone: aws.String("us-west-2a"),
    48  						Size:             aws.Integer(5),
    49  					})
    50  					return err
    51  				},
    52  			},
    53  
    54  			resource.TestStep{
    55  				Config: testAccInstanceConfig,
    56  				Check: resource.ComposeTestCheckFunc(
    57  					testAccCheckInstanceExists(
    58  						"aws_instance.foo", &v),
    59  					testCheck,
    60  					resource.TestCheckResourceAttr(
    61  						"aws_instance.foo",
    62  						"user_data",
    63  						"3dc39dda39be1205215e776bad998da361a5955d"),
    64  					resource.TestCheckResourceAttr(
    65  						"aws_instance.foo", "ebs_block_device.#", "0"),
    66  				),
    67  			},
    68  
    69  			// We repeat the exact same test so that we can be sure
    70  			// that the user data hash stuff is working without generating
    71  			// an incorrect diff.
    72  			resource.TestStep{
    73  				Config: testAccInstanceConfig,
    74  				Check: resource.ComposeTestCheckFunc(
    75  					testAccCheckInstanceExists(
    76  						"aws_instance.foo", &v),
    77  					testCheck,
    78  					resource.TestCheckResourceAttr(
    79  						"aws_instance.foo",
    80  						"user_data",
    81  						"3dc39dda39be1205215e776bad998da361a5955d"),
    82  					resource.TestCheckResourceAttr(
    83  						"aws_instance.foo", "ebs_block_device.#", "0"),
    84  				),
    85  			},
    86  
    87  			// Clean up volume created above
    88  			resource.TestStep{
    89  				Config: testAccInstanceConfig,
    90  				Check: func(*terraform.State) error {
    91  					conn := testAccProvider.Meta().(*AWSClient).ec2conn
    92  					return conn.DeleteVolume(&ec2.DeleteVolumeRequest{VolumeID: vol.VolumeID})
    93  				},
    94  			},
    95  		},
    96  	})
    97  }
    98  
    99  func TestAccAWSInstance_blockDevices(t *testing.T) {
   100  	var v ec2.Instance
   101  
   102  	testCheck := func() resource.TestCheckFunc {
   103  		return func(*terraform.State) error {
   104  
   105  			// Map out the block devices by name, which should be unique.
   106  			blockDevices := make(map[string]ec2.InstanceBlockDeviceMapping)
   107  			for _, blockDevice := range v.BlockDeviceMappings {
   108  				blockDevices[*blockDevice.DeviceName] = blockDevice
   109  			}
   110  
   111  			// Check if the root block device exists.
   112  			if _, ok := blockDevices["/dev/sda1"]; !ok {
   113  				fmt.Errorf("block device doesn't exist: /dev/sda1")
   114  			}
   115  
   116  			// Check if the secondary block device exists.
   117  			if _, ok := blockDevices["/dev/sdb"]; !ok {
   118  				fmt.Errorf("block device doesn't exist: /dev/sdb")
   119  			}
   120  
   121  			// Check if the third block device exists.
   122  			if _, ok := blockDevices["/dev/sdc"]; !ok {
   123  				fmt.Errorf("block device doesn't exist: /dev/sdc")
   124  			}
   125  
   126  			return nil
   127  		}
   128  	}
   129  
   130  	resource.Test(t, resource.TestCase{
   131  		PreCheck:     func() { testAccPreCheck(t) },
   132  		Providers:    testAccProviders,
   133  		CheckDestroy: testAccCheckInstanceDestroy,
   134  		Steps: []resource.TestStep{
   135  			resource.TestStep{
   136  				Config: testAccInstanceConfigBlockDevices,
   137  				Check: resource.ComposeTestCheckFunc(
   138  					testAccCheckInstanceExists(
   139  						"aws_instance.foo", &v),
   140  					resource.TestCheckResourceAttr(
   141  						"aws_instance.foo", "root_block_device.#", "1"),
   142  					resource.TestCheckResourceAttr(
   143  						"aws_instance.foo", "root_block_device.1246122048.device_name", "/dev/sda1"),
   144  					resource.TestCheckResourceAttr(
   145  						"aws_instance.foo", "root_block_device.1246122048.volume_size", "11"),
   146  					resource.TestCheckResourceAttr(
   147  						"aws_instance.foo", "root_block_device.1246122048.volume_type", "gp2"),
   148  					resource.TestCheckResourceAttr(
   149  						"aws_instance.foo", "ebs_block_device.#", "2"),
   150  					resource.TestCheckResourceAttr(
   151  						"aws_instance.foo", "ebs_block_device.2225977507.device_name", "/dev/sdb"),
   152  					resource.TestCheckResourceAttr(
   153  						"aws_instance.foo", "ebs_block_device.2225977507.volume_size", "9"),
   154  					resource.TestCheckResourceAttr(
   155  						"aws_instance.foo", "ebs_block_device.2225977507.volume_type", "standard"),
   156  					resource.TestCheckResourceAttr(
   157  						"aws_instance.foo", "ebs_block_device.1977224956.device_name", "/dev/sdc"),
   158  					resource.TestCheckResourceAttr(
   159  						"aws_instance.foo", "ebs_block_device.1977224956.volume_size", "10"),
   160  					resource.TestCheckResourceAttr(
   161  						"aws_instance.foo", "ebs_block_device.1977224956.volume_type", "io1"),
   162  					resource.TestCheckResourceAttr(
   163  						"aws_instance.foo", "ebs_block_device.1977224956.iops", "100"),
   164  					resource.TestCheckResourceAttr(
   165  						"aws_instance.foo", "ephemeral_block_device.#", "1"),
   166  					resource.TestCheckResourceAttr(
   167  						"aws_instance.foo", "ephemeral_block_device.1692014856.device_name", "/dev/sde"),
   168  					resource.TestCheckResourceAttr(
   169  						"aws_instance.foo", "ephemeral_block_device.1692014856.virtual_name", "ephemeral0"),
   170  					testCheck(),
   171  				),
   172  			},
   173  		},
   174  	})
   175  }
   176  
   177  func TestAccAWSInstance_sourceDestCheck(t *testing.T) {
   178  	var v ec2.Instance
   179  
   180  	testCheck := func(enabled bool) resource.TestCheckFunc {
   181  		return func(*terraform.State) error {
   182  			if *v.SourceDestCheck != enabled {
   183  				return fmt.Errorf("bad source_dest_check: %#v", *v.SourceDestCheck)
   184  			}
   185  
   186  			return nil
   187  		}
   188  	}
   189  
   190  	resource.Test(t, resource.TestCase{
   191  		PreCheck:     func() { testAccPreCheck(t) },
   192  		Providers:    testAccProviders,
   193  		CheckDestroy: testAccCheckInstanceDestroy,
   194  		Steps: []resource.TestStep{
   195  			resource.TestStep{
   196  				Config: testAccInstanceConfigSourceDestDisable,
   197  				Check: resource.ComposeTestCheckFunc(
   198  					testAccCheckInstanceExists("aws_instance.foo", &v),
   199  					testCheck(false),
   200  				),
   201  			},
   202  
   203  			resource.TestStep{
   204  				Config: testAccInstanceConfigSourceDestEnable,
   205  				Check: resource.ComposeTestCheckFunc(
   206  					testAccCheckInstanceExists("aws_instance.foo", &v),
   207  					testCheck(true),
   208  				),
   209  			},
   210  
   211  			resource.TestStep{
   212  				Config: testAccInstanceConfigSourceDestDisable,
   213  				Check: resource.ComposeTestCheckFunc(
   214  					testAccCheckInstanceExists("aws_instance.foo", &v),
   215  					testCheck(false),
   216  				),
   217  			},
   218  		},
   219  	})
   220  }
   221  
   222  func TestAccAWSInstance_vpc(t *testing.T) {
   223  	var v ec2.Instance
   224  
   225  	resource.Test(t, resource.TestCase{
   226  		PreCheck:     func() { testAccPreCheck(t) },
   227  		Providers:    testAccProviders,
   228  		CheckDestroy: testAccCheckInstanceDestroy,
   229  		Steps: []resource.TestStep{
   230  			resource.TestStep{
   231  				Config: testAccInstanceConfigVPC,
   232  				Check: resource.ComposeTestCheckFunc(
   233  					testAccCheckInstanceExists(
   234  						"aws_instance.foo", &v),
   235  				),
   236  			},
   237  		},
   238  	})
   239  }
   240  
   241  func TestAccInstance_NetworkInstanceSecurityGroups(t *testing.T) {
   242  	var v ec2.Instance
   243  
   244  	resource.Test(t, resource.TestCase{
   245  		PreCheck:     func() { testAccPreCheck(t) },
   246  		Providers:    testAccProviders,
   247  		CheckDestroy: testAccCheckInstanceDestroy,
   248  		Steps: []resource.TestStep{
   249  			resource.TestStep{
   250  				Config: testAccInstanceNetworkInstanceSecurityGroups,
   251  				Check: resource.ComposeTestCheckFunc(
   252  					testAccCheckInstanceExists(
   253  						"aws_instance.foo_instance", &v),
   254  				),
   255  			},
   256  		},
   257  	})
   258  }
   259  
   260  func TestAccAWSInstance_tags(t *testing.T) {
   261  	var v ec2.Instance
   262  
   263  	resource.Test(t, resource.TestCase{
   264  		PreCheck:     func() { testAccPreCheck(t) },
   265  		Providers:    testAccProviders,
   266  		CheckDestroy: testAccCheckInstanceDestroy,
   267  		Steps: []resource.TestStep{
   268  			resource.TestStep{
   269  				Config: testAccCheckInstanceConfigTags,
   270  				Check: resource.ComposeTestCheckFunc(
   271  					testAccCheckInstanceExists("aws_instance.foo", &v),
   272  					testAccCheckTags(&v.Tags, "foo", "bar"),
   273  					// Guard against regression of https://github.com/hashicorp/terraform/issues/914
   274  					testAccCheckTags(&v.Tags, "#", ""),
   275  				),
   276  			},
   277  
   278  			resource.TestStep{
   279  				Config: testAccCheckInstanceConfigTagsUpdate,
   280  				Check: resource.ComposeTestCheckFunc(
   281  					testAccCheckInstanceExists("aws_instance.foo", &v),
   282  					testAccCheckTags(&v.Tags, "foo", ""),
   283  					testAccCheckTags(&v.Tags, "bar", "baz"),
   284  				),
   285  			},
   286  		},
   287  	})
   288  }
   289  
   290  func TestAccAWSInstance_privateIP(t *testing.T) {
   291  	var v ec2.Instance
   292  
   293  	testCheckPrivateIP := func() resource.TestCheckFunc {
   294  		return func(*terraform.State) error {
   295  			if *v.PrivateIPAddress != "10.1.1.42" {
   296  				return fmt.Errorf("bad private IP: %s", *v.PrivateIPAddress)
   297  			}
   298  
   299  			return nil
   300  		}
   301  	}
   302  
   303  	resource.Test(t, resource.TestCase{
   304  		PreCheck:     func() { testAccPreCheck(t) },
   305  		Providers:    testAccProviders,
   306  		CheckDestroy: testAccCheckInstanceDestroy,
   307  		Steps: []resource.TestStep{
   308  			resource.TestStep{
   309  				Config: testAccInstanceConfigPrivateIP,
   310  				Check: resource.ComposeTestCheckFunc(
   311  					testAccCheckInstanceExists("aws_instance.foo", &v),
   312  					testCheckPrivateIP(),
   313  				),
   314  			},
   315  		},
   316  	})
   317  }
   318  
   319  func TestAccAWSInstance_associatePublicIPAndPrivateIP(t *testing.T) {
   320  	var v ec2.Instance
   321  
   322  	testCheckPrivateIP := func() resource.TestCheckFunc {
   323  		return func(*terraform.State) error {
   324  			if *v.PrivateIPAddress != "10.1.1.42" {
   325  				return fmt.Errorf("bad private IP: %s", *v.PrivateIPAddress)
   326  			}
   327  
   328  			return nil
   329  		}
   330  	}
   331  
   332  	resource.Test(t, resource.TestCase{
   333  		PreCheck:     func() { testAccPreCheck(t) },
   334  		Providers:    testAccProviders,
   335  		CheckDestroy: testAccCheckInstanceDestroy,
   336  		Steps: []resource.TestStep{
   337  			resource.TestStep{
   338  				Config: testAccInstanceConfigAssociatePublicIPAndPrivateIP,
   339  				Check: resource.ComposeTestCheckFunc(
   340  					testAccCheckInstanceExists("aws_instance.foo", &v),
   341  					testCheckPrivateIP(),
   342  				),
   343  			},
   344  		},
   345  	})
   346  }
   347  
   348  func testAccCheckInstanceDestroy(s *terraform.State) error {
   349  	conn := testAccProvider.Meta().(*AWSClient).ec2conn
   350  
   351  	for _, rs := range s.RootModule().Resources {
   352  		if rs.Type != "aws_instance" {
   353  			continue
   354  		}
   355  
   356  		// Try to find the resource
   357  		resp, err := conn.DescribeInstances(&ec2.DescribeInstancesRequest{
   358  			InstanceIDs: []string{rs.Primary.ID},
   359  		})
   360  		if err == nil {
   361  			if len(resp.Reservations) > 0 {
   362  				return fmt.Errorf("still exist.")
   363  			}
   364  
   365  			return nil
   366  		}
   367  
   368  		// Verify the error is what we want
   369  		ec2err, ok := err.(aws.APIError)
   370  		if !ok {
   371  			return err
   372  		}
   373  		if ec2err.Code != "InvalidInstanceID.NotFound" {
   374  			return err
   375  		}
   376  	}
   377  
   378  	return nil
   379  }
   380  
   381  func testAccCheckInstanceExists(n string, i *ec2.Instance) resource.TestCheckFunc {
   382  	return func(s *terraform.State) error {
   383  		rs, ok := s.RootModule().Resources[n]
   384  		if !ok {
   385  			return fmt.Errorf("Not found: %s", n)
   386  		}
   387  
   388  		if rs.Primary.ID == "" {
   389  			return fmt.Errorf("No ID is set")
   390  		}
   391  
   392  		conn := testAccProvider.Meta().(*AWSClient).ec2conn
   393  		resp, err := conn.DescribeInstances(&ec2.DescribeInstancesRequest{
   394  			InstanceIDs: []string{rs.Primary.ID},
   395  		})
   396  		if err != nil {
   397  			return err
   398  		}
   399  		if len(resp.Reservations) == 0 {
   400  			return fmt.Errorf("Instance not found")
   401  		}
   402  
   403  		*i = resp.Reservations[0].Instances[0]
   404  
   405  		return nil
   406  	}
   407  }
   408  
   409  func TestInstanceTenancySchema(t *testing.T) {
   410  	actualSchema := resourceAwsInstance().Schema["tenancy"]
   411  	expectedSchema := &schema.Schema{
   412  		Type:     schema.TypeString,
   413  		Optional: true,
   414  		Computed: true,
   415  		ForceNew: true,
   416  	}
   417  	if !reflect.DeepEqual(actualSchema, expectedSchema) {
   418  		t.Fatalf(
   419  			"Got:\n\n%#v\n\nExpected:\n\n%#v\n",
   420  			actualSchema,
   421  			expectedSchema)
   422  	}
   423  }
   424  
   425  const testAccInstanceConfig_pre = `
   426  resource "aws_security_group" "tf_test_foo" {
   427  	name = "tf_test_foo"
   428  	description = "foo"
   429  
   430  	ingress {
   431  		protocol = "icmp"
   432  		from_port = -1
   433  		to_port = -1
   434  		cidr_blocks = ["0.0.0.0/0"]
   435  	}
   436  }
   437  `
   438  
   439  const testAccInstanceConfig = `
   440  resource "aws_security_group" "tf_test_foo" {
   441  	name = "tf_test_foo"
   442  	description = "foo"
   443  
   444  	ingress {
   445  		protocol = "icmp"
   446  		from_port = -1
   447  		to_port = -1
   448  		cidr_blocks = ["0.0.0.0/0"]
   449  	}
   450  }
   451  
   452  resource "aws_instance" "foo" {
   453  	# us-west-2
   454  	ami = "ami-4fccb37f"
   455  	availability_zone = "us-west-2a"
   456  
   457  	instance_type = "m1.small"
   458  	security_groups = ["${aws_security_group.tf_test_foo.name}"]
   459  	user_data = "foo:-with-character's"
   460  }
   461  `
   462  
   463  const testAccInstanceConfigBlockDevices = `
   464  resource "aws_instance" "foo" {
   465  	# us-west-2
   466  	ami = "ami-55a7ea65"
   467  	instance_type = "m1.small"
   468  
   469  	root_block_device {
   470  		device_name = "/dev/sda1"
   471  		volume_type = "gp2"
   472  		volume_size = 11
   473  	}
   474  	ebs_block_device {
   475  		device_name = "/dev/sdb"
   476  		volume_size = 9
   477  	}
   478  	ebs_block_device {
   479  		device_name = "/dev/sdc"
   480  		volume_size = 10
   481  		volume_type = "io1"
   482  		iops = 100
   483  	}
   484  	ephemeral_block_device {
   485  		device_name = "/dev/sde"
   486  		virtual_name = "ephemeral0"
   487  	}
   488  }
   489  `
   490  
   491  const testAccInstanceConfigSourceDestEnable = `
   492  resource "aws_vpc" "foo" {
   493  	cidr_block = "10.1.0.0/16"
   494  }
   495  
   496  resource "aws_subnet" "foo" {
   497  	cidr_block = "10.1.1.0/24"
   498  	vpc_id = "${aws_vpc.foo.id}"
   499  }
   500  
   501  resource "aws_instance" "foo" {
   502  	# us-west-2
   503  	ami = "ami-4fccb37f"
   504  	instance_type = "m1.small"
   505  	subnet_id = "${aws_subnet.foo.id}"
   506  	source_dest_check = true
   507  }
   508  `
   509  
   510  const testAccInstanceConfigSourceDestDisable = `
   511  resource "aws_vpc" "foo" {
   512  	cidr_block = "10.1.0.0/16"
   513  }
   514  
   515  resource "aws_subnet" "foo" {
   516  	cidr_block = "10.1.1.0/24"
   517  	vpc_id = "${aws_vpc.foo.id}"
   518  }
   519  
   520  resource "aws_instance" "foo" {
   521  	# us-west-2
   522  	ami = "ami-4fccb37f"
   523  	instance_type = "m1.small"
   524  	subnet_id = "${aws_subnet.foo.id}"
   525  	source_dest_check = false
   526  }
   527  `
   528  
   529  const testAccInstanceConfigVPC = `
   530  resource "aws_vpc" "foo" {
   531  	cidr_block = "10.1.0.0/16"
   532  }
   533  
   534  resource "aws_subnet" "foo" {
   535  	cidr_block = "10.1.1.0/24"
   536  	vpc_id = "${aws_vpc.foo.id}"
   537  }
   538  
   539  resource "aws_instance" "foo" {
   540  	# us-west-2
   541  	ami = "ami-4fccb37f"
   542  	instance_type = "m1.small"
   543  	subnet_id = "${aws_subnet.foo.id}"
   544  	associate_public_ip_address = true
   545  	tenancy = "dedicated"
   546  }
   547  `
   548  
   549  const testAccCheckInstanceConfigTags = `
   550  resource "aws_instance" "foo" {
   551  	ami = "ami-4fccb37f"
   552  	instance_type = "m1.small"
   553  	tags {
   554  		foo = "bar"
   555  	}
   556  }
   557  `
   558  
   559  const testAccCheckInstanceConfigTagsUpdate = `
   560  resource "aws_instance" "foo" {
   561  	ami = "ami-4fccb37f"
   562  	instance_type = "m1.small"
   563  	tags {
   564  		bar = "baz"
   565  	}
   566  }
   567  `
   568  
   569  const testAccInstanceConfigPrivateIP = `
   570  resource "aws_vpc" "foo" {
   571  	cidr_block = "10.1.0.0/16"
   572  }
   573  
   574  resource "aws_subnet" "foo" {
   575  	cidr_block = "10.1.1.0/24"
   576  	vpc_id = "${aws_vpc.foo.id}"
   577  }
   578  
   579  resource "aws_instance" "foo" {
   580  	ami = "ami-c5eabbf5"
   581  	instance_type = "t2.micro"
   582  	subnet_id = "${aws_subnet.foo.id}"
   583  	private_ip = "10.1.1.42"
   584  }
   585  `
   586  
   587  const testAccInstanceConfigAssociatePublicIPAndPrivateIP = `
   588  resource "aws_vpc" "foo" {
   589  	cidr_block = "10.1.0.0/16"
   590  }
   591  
   592  resource "aws_subnet" "foo" {
   593  	cidr_block = "10.1.1.0/24"
   594  	vpc_id = "${aws_vpc.foo.id}"
   595  }
   596  
   597  resource "aws_instance" "foo" {
   598  	ami = "ami-c5eabbf5"
   599  	instance_type = "t2.micro"
   600  	subnet_id = "${aws_subnet.foo.id}"
   601  	associate_public_ip_address = true
   602  	private_ip = "10.1.1.42"
   603  }
   604  `
   605  
   606  const testAccInstanceNetworkInstanceSecurityGroups = `
   607  resource "aws_internet_gateway" "gw" {
   608    vpc_id = "${aws_vpc.foo.id}"
   609  }
   610  
   611  resource "aws_vpc" "foo" {
   612    cidr_block = "10.1.0.0/16"
   613  	tags {
   614  		Name = "tf-network-test"
   615  	}
   616  }
   617  
   618  resource "aws_security_group" "tf_test_foo" {
   619    name = "tf_test_foo"
   620    description = "foo"
   621    vpc_id="${aws_vpc.foo.id}"
   622  
   623    ingress {
   624      protocol = "icmp"
   625      from_port = -1
   626      to_port = -1
   627      cidr_blocks = ["0.0.0.0/0"]
   628    }
   629  }
   630  
   631  resource "aws_subnet" "foo" {
   632    cidr_block = "10.1.1.0/24"
   633    vpc_id = "${aws_vpc.foo.id}"
   634  }
   635  
   636  resource "aws_instance" "foo_instance" {
   637    ami = "ami-21f78e11"
   638    instance_type = "t1.micro"
   639    security_groups = ["${aws_security_group.tf_test_foo.id}"]
   640    subnet_id = "${aws_subnet.foo.id}"
   641    associate_public_ip_address = true
   642  	depends_on = ["aws_internet_gateway.gw"]
   643  }
   644  
   645  resource "aws_eip" "foo_eip" {
   646    instance = "${aws_instance.foo_instance.id}"
   647    vpc = true
   648  	depends_on = ["aws_internet_gateway.gw"]
   649  }
   650  `