From 4a4f2ad9e5e271f7d807b021fa542d5aafeb41f0 Mon Sep 17 00:00:00 2001 From: Joe Topjian Date: Mon, 11 Jan 2016 03:53:30 +0000 Subject: [PATCH] provider/openstack: Add Instance Personality This commit adds the "personality" attribute which is used to provision destination files on the instance. --- .../resource_openstack_compute_instance_v2.go | 50 +++++++++++++++++++ ...urce_openstack_compute_instance_v2_test.go | 32 ++++++++++++ .../r/compute_instance_v2.html.markdown | 12 ++++- 3 files changed, 93 insertions(+), 1 deletion(-) diff --git a/builtin/providers/openstack/resource_openstack_compute_instance_v2.go b/builtin/providers/openstack/resource_openstack_compute_instance_v2.go index c9a0f98328..dfe1a28f03 100644 --- a/builtin/providers/openstack/resource_openstack_compute_instance_v2.go +++ b/builtin/providers/openstack/resource_openstack_compute_instance_v2.go @@ -275,6 +275,24 @@ func resourceComputeInstanceV2() *schema.Resource { }, Set: resourceComputeSchedulerHintsHash, }, + "personality": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + ForceNew: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "file": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + "content": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + }, + }, + Set: resourceComputeInstancePersonalityHash, + }, }, } } @@ -334,6 +352,7 @@ func resourceComputeInstanceV2Create(d *schema.ResourceData, meta interface{}) e ConfigDrive: d.Get("config_drive").(bool), AdminPass: d.Get("admin_pass").(string), UserData: []byte(d.Get("user_data").(string)), + Personality: resourceInstancePersonalityV2(d), } if keyName, ok := d.Get("key_pair").(string); ok && keyName != "" { @@ -1237,3 +1256,34 @@ func checkVolumeConfig(d *schema.ResourceData) error { return nil } + +func resourceComputeInstancePersonalityHash(v interface{}) int { + var buf bytes.Buffer + m := v.(map[string]interface{}) + buf.WriteString(fmt.Sprintf("%s-", m["file"].(string))) + + return hashcode.String(buf.String()) +} + +func resourceInstancePersonalityV2(d *schema.ResourceData) servers.Personality { + var personalities servers.Personality + + if v := d.Get("personality"); v != nil { + personalityList := v.(*schema.Set).List() + if len(personalityList) > 0 { + for _, p := range personalityList { + rawPersonality := p.(map[string]interface{}) + file := servers.File{ + Path: rawPersonality["file"].(string), + Contents: []byte(rawPersonality["content"].(string)), + } + + log.Printf("[DEBUG] OpenStack Compute Instance Personality: %+v", file) + + personalities = append(personalities, &file) + } + } + } + + return personalities +} diff --git a/builtin/providers/openstack/resource_openstack_compute_instance_v2_test.go b/builtin/providers/openstack/resource_openstack_compute_instance_v2_test.go index 63f8714460..574f3b1993 100644 --- a/builtin/providers/openstack/resource_openstack_compute_instance_v2_test.go +++ b/builtin/providers/openstack/resource_openstack_compute_instance_v2_test.go @@ -325,6 +325,38 @@ func TestAccComputeV2Instance_bootFromVolumeVolume(t *testing.T) { }) } +// TODO: verify the personality really exists on the instance. +func TestAccComputeV2Instance_personality(t *testing.T) { + var instance servers.Server + var testAccComputeV2Instance_personality = fmt.Sprintf(` + resource "openstack_compute_instance_v2" "foo" { + name = "terraform-test" + security_groups = ["default"] + personality { + file = "/tmp/foobar.txt" + content = "happy" + } + personality { + file = "/tmp/barfoo.txt" + content = "angry" + } + }`) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckComputeV2InstanceDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccComputeV2Instance_personality, + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeV2InstanceExists(t, "openstack_compute_instance_v2.foo", &instance), + ), + }, + }, + }) +} + func testAccCheckComputeV2InstanceDestroy(s *terraform.State) error { config := testAccProvider.Meta().(*Config) computeClient, err := config.computeV2Client(OS_REGION_NAME) diff --git a/website/source/docs/providers/openstack/r/compute_instance_v2.html.markdown b/website/source/docs/providers/openstack/r/compute_instance_v2.html.markdown index 73e6636461..8dced11dcc 100644 --- a/website/source/docs/providers/openstack/r/compute_instance_v2.html.markdown +++ b/website/source/docs/providers/openstack/r/compute_instance_v2.html.markdown @@ -85,9 +85,13 @@ The following arguments are supported: * `volume` - (Optional) Attach an existing volume to the instance. The volume structure is described below. -* `scheduler_hints` - (Optional) Provider the Nova scheduler with hints on how +* `scheduler_hints` - (Optional) Provide the Nova scheduler with hints on how the instance should be launched. The available hints are described below. +* `personality` - (Optional) Customize the personality of an instance by + defining one or more files and their contents. The personality structure + is described below. + The `network` block supports: * `uuid` - (Required unless `port` or `name` is provided) The network UUID to @@ -143,6 +147,12 @@ The `scheduler_hints` block supports: * `build_near_host_ip` - (Optional) An IP Address in CIDR form. The instance will be placed on a compute node that is in the same subnet. +The `personality` block supports: + +* `file` - (Required) The absolute path of the destination file. + +* `contents` - (Required) The contents of the file. Limited to 255 bytes. + ## Attributes Reference The following attributes are exported: