Support for image_name

This commit renames image_ref to image_id and adds the image_name
parameter. Users can now specify either an image UUID or image name
when launching instances.

image_name is preferrable as deployers/sysadmins generally regularly
deprecate/remove outdated and insecure images. Using a consistent
naming scheme allows end-users to always retrieve a working image.
This commit is contained in:
Joe Topjian 2015-02-10 05:20:23 +00:00 committed by Jon Perritt
parent fafa946871
commit f51a53000f
2 changed files with 53 additions and 6 deletions

View File

@ -45,9 +45,11 @@ func testAccPreCheck(t *testing.T) {
} }
OS_REGION_NAME = v OS_REGION_NAME = v
v = os.Getenv("OS_IMAGE_ID") v1 := os.Getenv("OS_IMAGE_ID")
if v == "" { v2 := os.Getenv("OS_IMAGE_NAME")
t.Fatal("OS_IMAGE_ID must be set for acceptance tests")
if v1 == "" && v2 == "" {
t.Fatal("OS_IMAGE_ID or OS_IMAGE_NAME must be set for acceptance tests")
} }
v = os.Getenv("OS_POOL_NAME") v = os.Getenv("OS_POOL_NAME")

View File

@ -13,6 +13,7 @@ import (
"github.com/rackspace/gophercloud/openstack/compute/v2/extensions/bootfromvolume" "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/bootfromvolume"
"github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs" "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs"
"github.com/rackspace/gophercloud/openstack/compute/v2/extensions/secgroups" "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/secgroups"
"github.com/rackspace/gophercloud/openstack/compute/v2/images"
"github.com/rackspace/gophercloud/openstack/compute/v2/servers" "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/layer3/floatingips" "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/layer3/floatingips"
"github.com/rackspace/gophercloud/openstack/networking/v2/networks" "github.com/rackspace/gophercloud/openstack/networking/v2/networks"
@ -39,12 +40,18 @@ func resourceComputeInstanceV2() *schema.Resource {
Required: true, Required: true,
ForceNew: false, ForceNew: false,
}, },
"image_ref": &schema.Schema{ "image_id": &schema.Schema{
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Optional: true,
ForceNew: false, ForceNew: true,
DefaultFunc: envDefaultFunc("OS_IMAGE_ID"), DefaultFunc: envDefaultFunc("OS_IMAGE_ID"),
}, },
"image_name": &schema.Schema{
Type: schema.TypeString,
Optional: true,
ForceNew: true,
DefaultFunc: envDefaultFunc("OS_IMAGE_NAME"),
},
"flavor_ref": &schema.Schema{ "flavor_ref": &schema.Schema{
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Optional: true,
@ -165,9 +172,14 @@ func resourceComputeInstanceV2Create(d *schema.ResourceData, meta interface{}) e
var createOpts servers.CreateOptsBuilder var createOpts servers.CreateOptsBuilder
imageId, err := getImageID(computeClient, d)
if err != nil {
return err
}
createOpts = &servers.CreateOpts{ createOpts = &servers.CreateOpts{
Name: d.Get("name").(string), Name: d.Get("name").(string),
ImageRef: d.Get("image_ref").(string), ImageRef: imageId,
FlavorRef: d.Get("flavor_ref").(string), FlavorRef: d.Get("flavor_ref").(string),
SecurityGroups: resourceInstanceSecGroupsV2(d), SecurityGroups: resourceInstanceSecGroupsV2(d),
AvailabilityZone: d.Get("availability_zone").(string), AvailabilityZone: d.Get("availability_zone").(string),
@ -659,3 +671,36 @@ func getFloatingIPs(networkingClient *gophercloud.ServiceClient) ([]floatingips.
} }
return ips, nil return ips, nil
} }
func getImageID(client *gophercloud.ServiceClient, d *schema.ResourceData) (string, error) {
imageID := d.Get("image_id").(string)
imageName := d.Get("image_name").(string)
if imageID == "" {
pager := images.ListDetail(client, nil)
pager.EachPage(func(page pagination.Page) (bool, error) {
imageList, err := images.ExtractImages(page)
if err != nil {
return false, err
}
for _, i := range imageList {
if i.Name == imageName {
imageID = i.ID
}
}
return true, nil
})
if imageID == "" {
return "", fmt.Errorf("Unable to find image: %v", imageName)
}
}
if imageID == "" && imageName == "" {
return "", fmt.Errorf("Neither an image ID nor an image name were able to be determined.")
}
return imageID, nil
}