github.com/tarrant/terraform@v0.3.8-0.20150402012457-f68c9eee638e/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.1023169747.volume_size", "11"),
   144  					resource.TestCheckResourceAttr(
   145  						"aws_instance.foo", "root_block_device.1023169747.volume_type", "gp2"),
   146  					resource.TestCheckResourceAttr(
   147  						"aws_instance.foo", "ebs_block_device.#", "2"),
   148  					resource.TestCheckResourceAttr(
   149  						"aws_instance.foo", "ebs_block_device.2225977507.device_name", "/dev/sdb"),
   150  					resource.TestCheckResourceAttr(
   151  						"aws_instance.foo", "ebs_block_device.2225977507.volume_size", "9"),
   152  					resource.TestCheckResourceAttr(
   153  						"aws_instance.foo", "ebs_block_device.2225977507.volume_type", "standard"),
   154  					resource.TestCheckResourceAttr(
   155  						"aws_instance.foo", "ebs_block_device.1977224956.device_name", "/dev/sdc"),
   156  					resource.TestCheckResourceAttr(
   157  						"aws_instance.foo", "ebs_block_device.1977224956.volume_size", "10"),
   158  					resource.TestCheckResourceAttr(
   159  						"aws_instance.foo", "ebs_block_device.1977224956.volume_type", "io1"),
   160  					resource.TestCheckResourceAttr(
   161  						"aws_instance.foo", "ebs_block_device.1977224956.iops", "100"),
   162  					resource.TestCheckResourceAttr(
   163  						"aws_instance.foo", "ephemeral_block_device.#", "1"),
   164  					resource.TestCheckResourceAttr(
   165  						"aws_instance.foo", "ephemeral_block_device.1692014856.device_name", "/dev/sde"),
   166  					resource.TestCheckResourceAttr(
   167  						"aws_instance.foo", "ephemeral_block_device.1692014856.virtual_name", "ephemeral0"),
   168  					testCheck(),
   169  				),
   170  			},
   171  		},
   172  	})
   173  }
   174  
   175  func TestAccAWSInstance_sourceDestCheck(t *testing.T) {
   176  	var v ec2.Instance
   177  
   178  	testCheck := func(enabled bool) resource.TestCheckFunc {
   179  		return func(*terraform.State) error {
   180  			if *v.SourceDestCheck != enabled {
   181  				return fmt.Errorf("bad source_dest_check: %#v", *v.SourceDestCheck)
   182  			}
   183  
   184  			return nil
   185  		}
   186  	}
   187  
   188  	resource.Test(t, resource.TestCase{
   189  		PreCheck:     func() { testAccPreCheck(t) },
   190  		Providers:    testAccProviders,
   191  		CheckDestroy: testAccCheckInstanceDestroy,
   192  		Steps: []resource.TestStep{
   193  			resource.TestStep{
   194  				Config: testAccInstanceConfigSourceDestDisable,
   195  				Check: resource.ComposeTestCheckFunc(
   196  					testAccCheckInstanceExists("aws_instance.foo", &v),
   197  					testCheck(false),
   198  				),
   199  			},
   200  
   201  			resource.TestStep{
   202  				Config: testAccInstanceConfigSourceDestEnable,
   203  				Check: resource.ComposeTestCheckFunc(
   204  					testAccCheckInstanceExists("aws_instance.foo", &v),
   205  					testCheck(true),
   206  				),
   207  			},
   208  
   209  			resource.TestStep{
   210  				Config: testAccInstanceConfigSourceDestDisable,
   211  				Check: resource.ComposeTestCheckFunc(
   212  					testAccCheckInstanceExists("aws_instance.foo", &v),
   213  					testCheck(false),
   214  				),
   215  			},
   216  		},
   217  	})
   218  }
   219  
   220  func TestAccAWSInstance_vpc(t *testing.T) {
   221  	var v ec2.Instance
   222  
   223  	resource.Test(t, resource.TestCase{
   224  		PreCheck:     func() { testAccPreCheck(t) },
   225  		Providers:    testAccProviders,
   226  		CheckDestroy: testAccCheckInstanceDestroy,
   227  		Steps: []resource.TestStep{
   228  			resource.TestStep{
   229  				Config: testAccInstanceConfigVPC,
   230  				Check: resource.ComposeTestCheckFunc(
   231  					testAccCheckInstanceExists(
   232  						"aws_instance.foo", &v),
   233  				),
   234  			},
   235  		},
   236  	})
   237  }
   238  
   239  func TestAccInstance_NetworkInstanceSecurityGroups(t *testing.T) {
   240  	var v ec2.Instance
   241  
   242  	resource.Test(t, resource.TestCase{
   243  		PreCheck:     func() { testAccPreCheck(t) },
   244  		Providers:    testAccProviders,
   245  		CheckDestroy: testAccCheckInstanceDestroy,
   246  		Steps: []resource.TestStep{
   247  			resource.TestStep{
   248  				Config: testAccInstanceNetworkInstanceSecurityGroups,
   249  				Check: resource.ComposeTestCheckFunc(
   250  					testAccCheckInstanceExists(
   251  						"aws_instance.foo_instance", &v),
   252  				),
   253  			},
   254  		},
   255  	})
   256  }
   257  
   258  func TestAccAWSInstance_tags(t *testing.T) {
   259  	var v ec2.Instance
   260  
   261  	resource.Test(t, resource.TestCase{
   262  		PreCheck:     func() { testAccPreCheck(t) },
   263  		Providers:    testAccProviders,
   264  		CheckDestroy: testAccCheckInstanceDestroy,
   265  		Steps: []resource.TestStep{
   266  			resource.TestStep{
   267  				Config: testAccCheckInstanceConfigTags,
   268  				Check: resource.ComposeTestCheckFunc(
   269  					testAccCheckInstanceExists("aws_instance.foo", &v),
   270  					testAccCheckTags(&v.Tags, "foo", "bar"),
   271  					// Guard against regression of https://github.com/hashicorp/terraform/issues/914
   272  					testAccCheckTags(&v.Tags, "#", ""),
   273  				),
   274  			},
   275  
   276  			resource.TestStep{
   277  				Config: testAccCheckInstanceConfigTagsUpdate,
   278  				Check: resource.ComposeTestCheckFunc(
   279  					testAccCheckInstanceExists("aws_instance.foo", &v),
   280  					testAccCheckTags(&v.Tags, "foo", ""),
   281  					testAccCheckTags(&v.Tags, "bar", "baz"),
   282  				),
   283  			},
   284  		},
   285  	})
   286  }
   287  
   288  func TestAccAWSInstance_privateIP(t *testing.T) {
   289  	var v ec2.Instance
   290  
   291  	testCheckPrivateIP := func() resource.TestCheckFunc {
   292  		return func(*terraform.State) error {
   293  			if *v.PrivateIPAddress != "10.1.1.42" {
   294  				return fmt.Errorf("bad private IP: %s", *v.PrivateIPAddress)
   295  			}
   296  
   297  			return nil
   298  		}
   299  	}
   300  
   301  	resource.Test(t, resource.TestCase{
   302  		PreCheck:     func() { testAccPreCheck(t) },
   303  		Providers:    testAccProviders,
   304  		CheckDestroy: testAccCheckInstanceDestroy,
   305  		Steps: []resource.TestStep{
   306  			resource.TestStep{
   307  				Config: testAccInstanceConfigPrivateIP,
   308  				Check: resource.ComposeTestCheckFunc(
   309  					testAccCheckInstanceExists("aws_instance.foo", &v),
   310  					testCheckPrivateIP(),
   311  				),
   312  			},
   313  		},
   314  	})
   315  }
   316  
   317  func TestAccAWSInstance_associatePublicIPAndPrivateIP(t *testing.T) {
   318  	var v ec2.Instance
   319  
   320  	testCheckPrivateIP := func() resource.TestCheckFunc {
   321  		return func(*terraform.State) error {
   322  			if *v.PrivateIPAddress != "10.1.1.42" {
   323  				return fmt.Errorf("bad private IP: %s", *v.PrivateIPAddress)
   324  			}
   325  
   326  			return nil
   327  		}
   328  	}
   329  
   330  	resource.Test(t, resource.TestCase{
   331  		PreCheck:     func() { testAccPreCheck(t) },
   332  		Providers:    testAccProviders,
   333  		CheckDestroy: testAccCheckInstanceDestroy,
   334  		Steps: []resource.TestStep{
   335  			resource.TestStep{
   336  				Config: testAccInstanceConfigAssociatePublicIPAndPrivateIP,
   337  				Check: resource.ComposeTestCheckFunc(
   338  					testAccCheckInstanceExists("aws_instance.foo", &v),
   339  					testCheckPrivateIP(),
   340  				),
   341  			},
   342  		},
   343  	})
   344  }
   345  
   346  func testAccCheckInstanceDestroy(s *terraform.State) error {
   347  	conn := testAccProvider.Meta().(*AWSClient).ec2conn
   348  
   349  	for _, rs := range s.RootModule().Resources {
   350  		if rs.Type != "aws_instance" {
   351  			continue
   352  		}
   353  
   354  		// Try to find the resource
   355  		resp, err := conn.DescribeInstances(&ec2.DescribeInstancesRequest{
   356  			InstanceIDs: []string{rs.Primary.ID},
   357  		})
   358  		if err == nil {
   359  			if len(resp.Reservations) > 0 {
   360  				return fmt.Errorf("still exist.")
   361  			}
   362  
   363  			return nil
   364  		}
   365  
   366  		// Verify the error is what we want
   367  		ec2err, ok := err.(aws.APIError)
   368  		if !ok {
   369  			return err
   370  		}
   371  		if ec2err.Code != "InvalidInstanceID.NotFound" {
   372  			return err
   373  		}
   374  	}
   375  
   376  	return nil
   377  }
   378  
   379  func testAccCheckInstanceExists(n string, i *ec2.Instance) resource.TestCheckFunc {
   380  	return func(s *terraform.State) error {
   381  		rs, ok := s.RootModule().Resources[n]
   382  		if !ok {
   383  			return fmt.Errorf("Not found: %s", n)
   384  		}
   385  
   386  		if rs.Primary.ID == "" {
   387  			return fmt.Errorf("No ID is set")
   388  		}
   389  
   390  		conn := testAccProvider.Meta().(*AWSClient).ec2conn
   391  		resp, err := conn.DescribeInstances(&ec2.DescribeInstancesRequest{
   392  			InstanceIDs: []string{rs.Primary.ID},
   393  		})
   394  		if err != nil {
   395  			return err
   396  		}
   397  		if len(resp.Reservations) == 0 {
   398  			return fmt.Errorf("Instance not found")
   399  		}
   400  
   401  		*i = resp.Reservations[0].Instances[0]
   402  
   403  		return nil
   404  	}
   405  }
   406  
   407  func TestInstanceTenancySchema(t *testing.T) {
   408  	actualSchema := resourceAwsInstance().Schema["tenancy"]
   409  	expectedSchema := &schema.Schema{
   410  		Type:     schema.TypeString,
   411  		Optional: true,
   412  		Computed: true,
   413  		ForceNew: true,
   414  	}
   415  	if !reflect.DeepEqual(actualSchema, expectedSchema) {
   416  		t.Fatalf(
   417  			"Got:\n\n%#v\n\nExpected:\n\n%#v\n",
   418  			actualSchema,
   419  			expectedSchema)
   420  	}
   421  }
   422  
   423  const testAccInstanceConfig_pre = `
   424  resource "aws_security_group" "tf_test_foo" {
   425  	name = "tf_test_foo"
   426  	description = "foo"
   427  
   428  	ingress {
   429  		protocol = "icmp"
   430  		from_port = -1
   431  		to_port = -1
   432  		cidr_blocks = ["0.0.0.0/0"]
   433  	}
   434  }
   435  `
   436  
   437  const testAccInstanceConfig = `
   438  resource "aws_security_group" "tf_test_foo" {
   439  	name = "tf_test_foo"
   440  	description = "foo"
   441  
   442  	ingress {
   443  		protocol = "icmp"
   444  		from_port = -1
   445  		to_port = -1
   446  		cidr_blocks = ["0.0.0.0/0"]
   447  	}
   448  }
   449  
   450  resource "aws_instance" "foo" {
   451  	# us-west-2
   452  	ami = "ami-4fccb37f"
   453  	availability_zone = "us-west-2a"
   454  
   455  	instance_type = "m1.small"
   456  	security_groups = ["${aws_security_group.tf_test_foo.name}"]
   457  	user_data = "foo:-with-character's"
   458  }
   459  `
   460  
   461  const testAccInstanceConfigBlockDevices = `
   462  resource "aws_instance" "foo" {
   463  	# us-west-2
   464  	ami = "ami-55a7ea65"
   465  	instance_type = "m1.small"
   466  
   467  	root_block_device {
   468  		volume_type = "gp2"
   469  		volume_size = 11
   470  	}
   471  	ebs_block_device {
   472  		device_name = "/dev/sdb"
   473  		volume_size = 9
   474  	}
   475  	ebs_block_device {
   476  		device_name = "/dev/sdc"
   477  		volume_size = 10
   478  		volume_type = "io1"
   479  		iops = 100
   480  	}
   481  	ephemeral_block_device {
   482  		device_name = "/dev/sde"
   483  		virtual_name = "ephemeral0"
   484  	}
   485  }
   486  `
   487  
   488  const testAccInstanceConfigSourceDestEnable = `
   489  resource "aws_vpc" "foo" {
   490  	cidr_block = "10.1.0.0/16"
   491  }
   492  
   493  resource "aws_subnet" "foo" {
   494  	cidr_block = "10.1.1.0/24"
   495  	vpc_id = "${aws_vpc.foo.id}"
   496  }
   497  
   498  resource "aws_instance" "foo" {
   499  	# us-west-2
   500  	ami = "ami-4fccb37f"
   501  	instance_type = "m1.small"
   502  	subnet_id = "${aws_subnet.foo.id}"
   503  	source_dest_check = true
   504  }
   505  `
   506  
   507  const testAccInstanceConfigSourceDestDisable = `
   508  resource "aws_vpc" "foo" {
   509  	cidr_block = "10.1.0.0/16"
   510  }
   511  
   512  resource "aws_subnet" "foo" {
   513  	cidr_block = "10.1.1.0/24"
   514  	vpc_id = "${aws_vpc.foo.id}"
   515  }
   516  
   517  resource "aws_instance" "foo" {
   518  	# us-west-2
   519  	ami = "ami-4fccb37f"
   520  	instance_type = "m1.small"
   521  	subnet_id = "${aws_subnet.foo.id}"
   522  	source_dest_check = false
   523  }
   524  `
   525  
   526  const testAccInstanceConfigVPC = `
   527  resource "aws_vpc" "foo" {
   528  	cidr_block = "10.1.0.0/16"
   529  }
   530  
   531  resource "aws_subnet" "foo" {
   532  	cidr_block = "10.1.1.0/24"
   533  	vpc_id = "${aws_vpc.foo.id}"
   534  }
   535  
   536  resource "aws_instance" "foo" {
   537  	# us-west-2
   538  	ami = "ami-4fccb37f"
   539  	instance_type = "m1.small"
   540  	subnet_id = "${aws_subnet.foo.id}"
   541  	associate_public_ip_address = true
   542  	tenancy = "dedicated"
   543  }
   544  `
   545  
   546  const testAccCheckInstanceConfigTags = `
   547  resource "aws_instance" "foo" {
   548  	ami = "ami-4fccb37f"
   549  	instance_type = "m1.small"
   550  	tags {
   551  		foo = "bar"
   552  	}
   553  }
   554  `
   555  
   556  const testAccCheckInstanceConfigTagsUpdate = `
   557  resource "aws_instance" "foo" {
   558  	ami = "ami-4fccb37f"
   559  	instance_type = "m1.small"
   560  	tags {
   561  		bar = "baz"
   562  	}
   563  }
   564  `
   565  
   566  const testAccInstanceConfigPrivateIP = `
   567  resource "aws_vpc" "foo" {
   568  	cidr_block = "10.1.0.0/16"
   569  }
   570  
   571  resource "aws_subnet" "foo" {
   572  	cidr_block = "10.1.1.0/24"
   573  	vpc_id = "${aws_vpc.foo.id}"
   574  }
   575  
   576  resource "aws_instance" "foo" {
   577  	ami = "ami-c5eabbf5"
   578  	instance_type = "t2.micro"
   579  	subnet_id = "${aws_subnet.foo.id}"
   580  	private_ip = "10.1.1.42"
   581  }
   582  `
   583  
   584  const testAccInstanceConfigAssociatePublicIPAndPrivateIP = `
   585  resource "aws_vpc" "foo" {
   586  	cidr_block = "10.1.0.0/16"
   587  }
   588  
   589  resource "aws_subnet" "foo" {
   590  	cidr_block = "10.1.1.0/24"
   591  	vpc_id = "${aws_vpc.foo.id}"
   592  }
   593  
   594  resource "aws_instance" "foo" {
   595  	ami = "ami-c5eabbf5"
   596  	instance_type = "t2.micro"
   597  	subnet_id = "${aws_subnet.foo.id}"
   598  	associate_public_ip_address = true
   599  	private_ip = "10.1.1.42"
   600  }
   601  `
   602  
   603  const testAccInstanceNetworkInstanceSecurityGroups = `
   604  resource "aws_internet_gateway" "gw" {
   605    vpc_id = "${aws_vpc.foo.id}"
   606  }
   607  
   608  resource "aws_vpc" "foo" {
   609    cidr_block = "10.1.0.0/16"
   610  	tags {
   611  		Name = "tf-network-test"
   612  	}
   613  }
   614  
   615  resource "aws_security_group" "tf_test_foo" {
   616    name = "tf_test_foo"
   617    description = "foo"
   618    vpc_id="${aws_vpc.foo.id}"
   619  
   620    ingress {
   621      protocol = "icmp"
   622      from_port = -1
   623      to_port = -1
   624      cidr_blocks = ["0.0.0.0/0"]
   625    }
   626  }
   627  
   628  resource "aws_subnet" "foo" {
   629    cidr_block = "10.1.1.0/24"
   630    vpc_id = "${aws_vpc.foo.id}"
   631  }
   632  
   633  resource "aws_instance" "foo_instance" {
   634    ami = "ami-21f78e11"
   635    instance_type = "t1.micro"
   636    security_groups = ["${aws_security_group.tf_test_foo.id}"]
   637    subnet_id = "${aws_subnet.foo.id}"
   638    associate_public_ip_address = true
   639  	depends_on = ["aws_internet_gateway.gw"]
   640  }
   641  
   642  resource "aws_eip" "foo_eip" {
   643    instance = "${aws_instance.foo_instance.id}"
   644    vpc = true
   645  	depends_on = ["aws_internet_gateway.gw"]
   646  }
   647  `