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