github.com/rmenn/terraform@v0.3.8-0.20150225065417-fc84b3a78802/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/terraform/helper/resource"
     9  	"github.com/hashicorp/terraform/helper/schema"
    10  	"github.com/hashicorp/terraform/terraform"
    11  	"github.com/mitchellh/goamz/ec2"
    12  )
    13  
    14  func TestAccAWSInstance_normal(t *testing.T) {
    15  	var v ec2.Instance
    16  
    17  	testCheck := func(*terraform.State) error {
    18  		if v.AvailZone != "us-west-2a" {
    19  			return fmt.Errorf("bad availability zone: %#v", v.AvailZone)
    20  		}
    21  
    22  		if len(v.SecurityGroups) == 0 {
    23  			return fmt.Errorf("no security groups: %#v", v.SecurityGroups)
    24  		}
    25  		if v.SecurityGroups[0].Name != "tf_test_foo" {
    26  			return fmt.Errorf("no security groups: %#v", v.SecurityGroups)
    27  		}
    28  
    29  		return nil
    30  	}
    31  
    32  	resource.Test(t, resource.TestCase{
    33  		PreCheck:     func() { testAccPreCheck(t) },
    34  		Providers:    testAccProviders,
    35  		CheckDestroy: testAccCheckInstanceDestroy,
    36  		Steps: []resource.TestStep{
    37  			resource.TestStep{
    38  				Config: testAccInstanceConfig,
    39  				Check: resource.ComposeTestCheckFunc(
    40  					testAccCheckInstanceExists(
    41  						"aws_instance.foo", &v),
    42  					testCheck,
    43  					resource.TestCheckResourceAttr(
    44  						"aws_instance.foo",
    45  						"user_data",
    46  						"0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33"),
    47  				),
    48  			},
    49  
    50  			// We repeat the exact same test so that we can be sure
    51  			// that the user data hash stuff is working without generating
    52  			// an incorrect diff.
    53  			resource.TestStep{
    54  				Config: testAccInstanceConfig,
    55  				Check: resource.ComposeTestCheckFunc(
    56  					testAccCheckInstanceExists(
    57  						"aws_instance.foo", &v),
    58  					testCheck,
    59  					resource.TestCheckResourceAttr(
    60  						"aws_instance.foo",
    61  						"user_data",
    62  						"0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33"),
    63  				),
    64  			},
    65  		},
    66  	})
    67  }
    68  
    69  func TestAccAWSInstance_blockDevices(t *testing.T) {
    70  	var v ec2.Instance
    71  
    72  	testCheck := func() resource.TestCheckFunc {
    73  		return func(*terraform.State) error {
    74  
    75  			// Map out the block devices by name, which should be unique.
    76  			blockDevices := make(map[string]ec2.BlockDevice)
    77  			for _, blockDevice := range v.BlockDevices {
    78  				blockDevices[blockDevice.DeviceName] = blockDevice
    79  			}
    80  
    81  			// Check if the root block device exists.
    82  			if _, ok := blockDevices["/dev/sda1"]; !ok {
    83  				fmt.Errorf("block device doesn't exist: /dev/sda1")
    84  			}
    85  
    86  			// Check if the secondary block device exists.
    87  			if _, ok := blockDevices["/dev/sdb"]; !ok {
    88  				fmt.Errorf("block device doesn't exist: /dev/sdb")
    89  			}
    90  
    91  			return nil
    92  		}
    93  	}
    94  
    95  	resource.Test(t, resource.TestCase{
    96  		PreCheck:     func() { testAccPreCheck(t) },
    97  		Providers:    testAccProviders,
    98  		CheckDestroy: testAccCheckInstanceDestroy,
    99  		Steps: []resource.TestStep{
   100  			resource.TestStep{
   101  				Config: testAccInstanceConfigBlockDevices,
   102  				Check: resource.ComposeTestCheckFunc(
   103  					testAccCheckInstanceExists(
   104  						"aws_instance.foo", &v),
   105  					resource.TestCheckResourceAttr(
   106  						"aws_instance.foo", "root_block_device.#", "1"),
   107  					resource.TestCheckResourceAttr(
   108  						"aws_instance.foo", "root_block_device.0.device_name", "/dev/sda1"),
   109  					resource.TestCheckResourceAttr(
   110  						"aws_instance.foo", "root_block_device.0.volume_size", "11"),
   111  					// this one is important because it's the only root_block_device
   112  					// attribute that comes back from the API. so checking it verifies
   113  					// that we set state properly
   114  					resource.TestCheckResourceAttr(
   115  						"aws_instance.foo", "root_block_device.0.volume_type", "gp2"),
   116  					resource.TestCheckResourceAttr(
   117  						"aws_instance.foo", "block_device.#", "1"),
   118  					resource.TestCheckResourceAttr(
   119  						"aws_instance.foo", "block_device.172787947.device_name", "/dev/sdb"),
   120  					resource.TestCheckResourceAttr(
   121  						"aws_instance.foo", "block_device.172787947.volume_size", "9"),
   122  					testCheck(),
   123  				),
   124  			},
   125  		},
   126  	})
   127  }
   128  
   129  func TestAccAWSInstance_sourceDestCheck(t *testing.T) {
   130  	var v ec2.Instance
   131  
   132  	testCheck := func(enabled bool) resource.TestCheckFunc {
   133  		return func(*terraform.State) error {
   134  			if v.SourceDestCheck != enabled {
   135  				return fmt.Errorf("bad source_dest_check: %#v", v.SourceDestCheck)
   136  			}
   137  
   138  			return nil
   139  		}
   140  	}
   141  
   142  	resource.Test(t, resource.TestCase{
   143  		PreCheck:     func() { testAccPreCheck(t) },
   144  		Providers:    testAccProviders,
   145  		CheckDestroy: testAccCheckInstanceDestroy,
   146  		Steps: []resource.TestStep{
   147  			resource.TestStep{
   148  				Config: testAccInstanceConfigSourceDestDisable,
   149  				Check: resource.ComposeTestCheckFunc(
   150  					testAccCheckInstanceExists("aws_instance.foo", &v),
   151  					testCheck(false),
   152  				),
   153  			},
   154  
   155  			resource.TestStep{
   156  				Config: testAccInstanceConfigSourceDestEnable,
   157  				Check: resource.ComposeTestCheckFunc(
   158  					testAccCheckInstanceExists("aws_instance.foo", &v),
   159  					testCheck(true),
   160  				),
   161  			},
   162  
   163  			resource.TestStep{
   164  				Config: testAccInstanceConfigSourceDestDisable,
   165  				Check: resource.ComposeTestCheckFunc(
   166  					testAccCheckInstanceExists("aws_instance.foo", &v),
   167  					testCheck(false),
   168  				),
   169  			},
   170  		},
   171  	})
   172  }
   173  
   174  func TestAccAWSInstance_vpc(t *testing.T) {
   175  	var v ec2.Instance
   176  
   177  	resource.Test(t, resource.TestCase{
   178  		PreCheck:     func() { testAccPreCheck(t) },
   179  		Providers:    testAccProviders,
   180  		CheckDestroy: testAccCheckInstanceDestroy,
   181  		Steps: []resource.TestStep{
   182  			resource.TestStep{
   183  				Config: testAccInstanceConfigVPC,
   184  				Check: resource.ComposeTestCheckFunc(
   185  					testAccCheckInstanceExists(
   186  						"aws_instance.foo", &v),
   187  				),
   188  			},
   189  		},
   190  	})
   191  }
   192  
   193  func TestAccInstance_tags(t *testing.T) {
   194  	var v ec2.Instance
   195  
   196  	resource.Test(t, resource.TestCase{
   197  		PreCheck:     func() { testAccPreCheck(t) },
   198  		Providers:    testAccProviders,
   199  		CheckDestroy: testAccCheckInstanceDestroy,
   200  		Steps: []resource.TestStep{
   201  			resource.TestStep{
   202  				Config: testAccCheckInstanceConfigTags,
   203  				Check: resource.ComposeTestCheckFunc(
   204  					testAccCheckInstanceExists("aws_instance.foo", &v),
   205  					testAccCheckTags(&v.Tags, "foo", "bar"),
   206  					// Guard against regression of https://github.com/hashicorp/terraform/issues/914
   207  					testAccCheckTags(&v.Tags, "#", ""),
   208  				),
   209  			},
   210  
   211  			resource.TestStep{
   212  				Config: testAccCheckInstanceConfigTagsUpdate,
   213  				Check: resource.ComposeTestCheckFunc(
   214  					testAccCheckInstanceExists("aws_instance.foo", &v),
   215  					testAccCheckTags(&v.Tags, "foo", ""),
   216  					testAccCheckTags(&v.Tags, "bar", "baz"),
   217  				),
   218  			},
   219  		},
   220  	})
   221  }
   222  
   223  func TestAccInstance_privateIP(t *testing.T) {
   224  	var v ec2.Instance
   225  
   226  	testCheckPrivateIP := func() resource.TestCheckFunc {
   227  		return func(*terraform.State) error {
   228  			if v.PrivateIpAddress != "10.1.1.42" {
   229  				return fmt.Errorf("bad private IP: %s", v.PrivateIpAddress)
   230  			}
   231  
   232  			return nil
   233  		}
   234  	}
   235  
   236  	resource.Test(t, resource.TestCase{
   237  		PreCheck:     func() { testAccPreCheck(t) },
   238  		Providers:    testAccProviders,
   239  		CheckDestroy: testAccCheckInstanceDestroy,
   240  		Steps: []resource.TestStep{
   241  			resource.TestStep{
   242  				Config: testAccInstanceConfigPrivateIP,
   243  				Check: resource.ComposeTestCheckFunc(
   244  					testAccCheckInstanceExists("aws_instance.foo", &v),
   245  					testCheckPrivateIP(),
   246  				),
   247  			},
   248  		},
   249  	})
   250  }
   251  
   252  func TestAccInstance_associatePublicIPAndPrivateIP(t *testing.T) {
   253  	var v ec2.Instance
   254  
   255  	testCheckPrivateIP := func() resource.TestCheckFunc {
   256  		return func(*terraform.State) error {
   257  			if v.PrivateIpAddress != "10.1.1.42" {
   258  				return fmt.Errorf("bad private IP: %s", v.PrivateIpAddress)
   259  			}
   260  
   261  			return nil
   262  		}
   263  	}
   264  
   265  	resource.Test(t, resource.TestCase{
   266  		PreCheck:     func() { testAccPreCheck(t) },
   267  		Providers:    testAccProviders,
   268  		CheckDestroy: testAccCheckInstanceDestroy,
   269  		Steps: []resource.TestStep{
   270  			resource.TestStep{
   271  				Config: testAccInstanceConfigAssociatePublicIPAndPrivateIP,
   272  				Check: resource.ComposeTestCheckFunc(
   273  					testAccCheckInstanceExists("aws_instance.foo", &v),
   274  					testCheckPrivateIP(),
   275  				),
   276  			},
   277  		},
   278  	})
   279  }
   280  
   281  func testAccCheckInstanceDestroy(s *terraform.State) error {
   282  	conn := testAccProvider.Meta().(*AWSClient).ec2conn
   283  
   284  	for _, rs := range s.RootModule().Resources {
   285  		if rs.Type != "aws_instance" {
   286  			continue
   287  		}
   288  
   289  		// Try to find the resource
   290  		resp, err := conn.Instances(
   291  			[]string{rs.Primary.ID}, ec2.NewFilter())
   292  		if err == nil {
   293  			if len(resp.Reservations) > 0 {
   294  				return fmt.Errorf("still exist.")
   295  			}
   296  
   297  			return nil
   298  		}
   299  
   300  		// Verify the error is what we want
   301  		ec2err, ok := err.(*ec2.Error)
   302  		if !ok {
   303  			return err
   304  		}
   305  		if ec2err.Code != "InvalidInstanceID.NotFound" {
   306  			return err
   307  		}
   308  	}
   309  
   310  	return nil
   311  }
   312  
   313  func testAccCheckInstanceExists(n string, i *ec2.Instance) resource.TestCheckFunc {
   314  	return func(s *terraform.State) error {
   315  		rs, ok := s.RootModule().Resources[n]
   316  		if !ok {
   317  			return fmt.Errorf("Not found: %s", n)
   318  		}
   319  
   320  		if rs.Primary.ID == "" {
   321  			return fmt.Errorf("No ID is set")
   322  		}
   323  
   324  		conn := testAccProvider.Meta().(*AWSClient).ec2conn
   325  		resp, err := conn.Instances(
   326  			[]string{rs.Primary.ID}, ec2.NewFilter())
   327  		if err != nil {
   328  			return err
   329  		}
   330  		if len(resp.Reservations) == 0 {
   331  			return fmt.Errorf("Instance not found")
   332  		}
   333  
   334  		*i = resp.Reservations[0].Instances[0]
   335  
   336  		return nil
   337  	}
   338  }
   339  
   340  func TestInstanceTenancySchema(t *testing.T) {
   341  	actualSchema := resourceAwsInstance().Schema["tenancy"]
   342  	expectedSchema := &schema.Schema{
   343  		Type:     schema.TypeString,
   344  		Optional: true,
   345  		Computed: true,
   346  		ForceNew: true,
   347  	}
   348  	if !reflect.DeepEqual(actualSchema, expectedSchema) {
   349  		t.Fatalf(
   350  			"Got:\n\n%#v\n\nExpected:\n\n%#v\n",
   351  			actualSchema,
   352  			expectedSchema)
   353  	}
   354  }
   355  
   356  const testAccInstanceConfig = `
   357  resource "aws_security_group" "tf_test_foo" {
   358  	name = "tf_test_foo"
   359  	description = "foo"
   360  
   361  	ingress {
   362  		protocol = "icmp"
   363  		from_port = -1
   364  		to_port = -1
   365  		cidr_blocks = ["0.0.0.0/0"]
   366  	}
   367  }
   368  
   369  resource "aws_instance" "foo" {
   370  	# us-west-2
   371  	ami = "ami-4fccb37f"
   372  	availability_zone = "us-west-2a"
   373  
   374  	instance_type = "m1.small"
   375  	security_groups = ["${aws_security_group.tf_test_foo.name}"]
   376  	user_data = "foo"
   377  }
   378  `
   379  
   380  const testAccInstanceConfigBlockDevices = `
   381  resource "aws_instance" "foo" {
   382  	# us-west-2
   383  	ami = "ami-55a7ea65"
   384  	instance_type = "m1.small"
   385  	root_block_device {
   386  		device_name = "/dev/sda1"
   387  		volume_type = "gp2"
   388  		volume_size = 11
   389  	}
   390  	block_device {
   391  		device_name = "/dev/sdb"
   392  		volume_size = 9
   393  	}
   394  }
   395  `
   396  
   397  const testAccInstanceConfigSourceDestEnable = `
   398  resource "aws_vpc" "foo" {
   399  	cidr_block = "10.1.0.0/16"
   400  }
   401  
   402  resource "aws_subnet" "foo" {
   403  	cidr_block = "10.1.1.0/24"
   404  	vpc_id = "${aws_vpc.foo.id}"
   405  }
   406  
   407  resource "aws_instance" "foo" {
   408  	# us-west-2
   409  	ami = "ami-4fccb37f"
   410  	instance_type = "m1.small"
   411  	subnet_id = "${aws_subnet.foo.id}"
   412  	source_dest_check = true
   413  }
   414  `
   415  
   416  const testAccInstanceConfigSourceDestDisable = `
   417  resource "aws_vpc" "foo" {
   418  	cidr_block = "10.1.0.0/16"
   419  }
   420  
   421  resource "aws_subnet" "foo" {
   422  	cidr_block = "10.1.1.0/24"
   423  	vpc_id = "${aws_vpc.foo.id}"
   424  }
   425  
   426  resource "aws_instance" "foo" {
   427  	# us-west-2
   428  	ami = "ami-4fccb37f"
   429  	instance_type = "m1.small"
   430  	subnet_id = "${aws_subnet.foo.id}"
   431  	source_dest_check = false
   432  }
   433  `
   434  
   435  const testAccInstanceConfigVPC = `
   436  resource "aws_vpc" "foo" {
   437  	cidr_block = "10.1.0.0/16"
   438  }
   439  
   440  resource "aws_subnet" "foo" {
   441  	cidr_block = "10.1.1.0/24"
   442  	vpc_id = "${aws_vpc.foo.id}"
   443  }
   444  
   445  resource "aws_instance" "foo" {
   446  	# us-west-2
   447  	ami = "ami-4fccb37f"
   448  	instance_type = "m1.small"
   449  	subnet_id = "${aws_subnet.foo.id}"
   450  	associate_public_ip_address = true
   451  	tenancy = "dedicated"
   452  }
   453  `
   454  
   455  const testAccCheckInstanceConfigTags = `
   456  resource "aws_instance" "foo" {
   457  	ami = "ami-4fccb37f"
   458  	instance_type = "m1.small"
   459  	tags {
   460  		foo = "bar"
   461  	}
   462  }
   463  `
   464  
   465  const testAccCheckInstanceConfigTagsUpdate = `
   466  resource "aws_instance" "foo" {
   467  	ami = "ami-4fccb37f"
   468  	instance_type = "m1.small"
   469  	tags {
   470  		bar = "baz"
   471  	}
   472  }
   473  `
   474  
   475  const testAccInstanceConfigPrivateIP = `
   476  resource "aws_vpc" "foo" {
   477  	cidr_block = "10.1.0.0/16"
   478  }
   479  
   480  resource "aws_subnet" "foo" {
   481  	cidr_block = "10.1.1.0/24"
   482  	vpc_id = "${aws_vpc.foo.id}"
   483  }
   484  
   485  resource "aws_instance" "foo" {
   486  	ami = "ami-c5eabbf5"
   487  	instance_type = "t2.micro"
   488  	subnet_id = "${aws_subnet.foo.id}"
   489  	private_ip = "10.1.1.42"
   490  }
   491  `
   492  
   493  const testAccInstanceConfigAssociatePublicIPAndPrivateIP = `
   494  resource "aws_vpc" "foo" {
   495  	cidr_block = "10.1.0.0/16"
   496  }
   497  
   498  resource "aws_subnet" "foo" {
   499  	cidr_block = "10.1.1.0/24"
   500  	vpc_id = "${aws_vpc.foo.id}"
   501  }
   502  
   503  resource "aws_instance" "foo" {
   504  	ami = "ami-c5eabbf5"
   505  	instance_type = "t2.micro"
   506  	subnet_id = "${aws_subnet.foo.id}"
   507  	associate_public_ip_address = true
   508  	private_ip = "10.1.1.42"
   509  }
   510  `