diff --git a/docs/data-sources/compute_instance.md b/docs/data-sources/compute_instance.md index 36ba11e14d..08831027de 100644 --- a/docs/data-sources/compute_instance.md +++ b/docs/data-sources/compute_instance.md @@ -44,6 +44,7 @@ In addition to all arguments above, the following attributes are exported: * `key_pair` - The key pair that is used to authenticate the instance. * `public_ip` - The EIP address that is associted to the instance. * `system_disk_id` - The system disk voume ID. +* `user_data` - The user data (information after encoding) configured during instance creation. * `security_groups` - An array of one or more security group names to associate with the instance. * `network` - An array of one or more networks to attach to the instance. diff --git a/docs/resources/compute_instance.md b/docs/resources/compute_instance.md index aec5608666..0178a900f6 100644 --- a/docs/resources/compute_instance.md +++ b/docs/resources/compute_instance.md @@ -296,6 +296,8 @@ The `scheduler_hints` block supports: In addition to all arguments above, the following attributes are exported: * `id` - Specifies a resource ID in UUID format. +* `status` - The status of the instance. +* `public_ip` - The EIP address that is associted to the instance. * `access_ip_v4` - The first detected Fixed IPv4 address _or_ the Floating IP. * `network/fixed_ip_v4` - The Fixed IPv4 address of the Instance on that network. diff --git a/huaweicloud/resource_huaweicloud_compute_instance.go b/huaweicloud/resource_huaweicloud_compute_instance.go index 3a03a11851..5ac0ef0824 100644 --- a/huaweicloud/resource_huaweicloud_compute_instance.go +++ b/huaweicloud/resource_huaweicloud_compute_instance.go @@ -55,7 +55,11 @@ func ResourceComputeInstanceV2() *schema.Resource { Computed: true, ForceNew: true, }, - + "availability_zone": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, "name": { Type: schema.TypeString, Required: true, @@ -86,6 +90,16 @@ func ResourceComputeInstanceV2() *schema.Resource { Computed: true, DefaultFunc: schema.EnvDefaultFunc("HW_FLAVOR_NAME", nil), }, + "admin_pass": { + Type: schema.TypeString, + Sensitive: true, + Optional: true, + }, + "key_pair": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, "security_groups": { Type: schema.TypeSet, Optional: true, @@ -93,11 +107,6 @@ func ResourceComputeInstanceV2() *schema.Resource { Elem: &schema.Schema{Type: schema.TypeString}, Set: schema.HashString, }, - "availability_zone": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, "network": { Type: schema.TypeList, Required: true, @@ -146,84 +155,6 @@ func ResourceComputeInstanceV2() *schema.Resource { }, }, }, - "user_data": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - // just stash the hash for state & diff comparisons - StateFunc: func(v interface{}) string { - switch v.(type) { - case string: - hash := sha1.Sum([]byte(v.(string))) - return hex.EncodeToString(hash[:]) - default: - return "" - } - }, - }, - "metadata": { - Type: schema.TypeMap, - Optional: true, - ConflictsWith: []string{"system_disk_type", "system_disk_size", "data_disks"}, - Deprecated: "use tags instead", - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "admin_pass": { - Type: schema.TypeString, - Sensitive: true, - Optional: true, - }, - "key_pair": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - }, - "block_device": { - Type: schema.TypeList, - Optional: true, - ConflictsWith: []string{"system_disk_type", "system_disk_size", "data_disks"}, - Deprecated: "use system_disk_type, system_disk_size, data_disks instead", - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "source_type": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "uuid": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - }, - "volume_size": { - Type: schema.TypeInt, - Optional: true, - ForceNew: true, - }, - "destination_type": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - }, - "boot_index": { - Type: schema.TypeInt, - Optional: true, - ForceNew: true, - }, - "delete_on_termination": { - Type: schema.TypeBool, - Optional: true, - Default: false, - ForceNew: true, - }, - "guest_format": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - }, - }, - }, - }, "system_disk_type": { Type: schema.TypeString, Optional: true, @@ -296,6 +227,21 @@ func ResourceComputeInstanceV2() *schema.Resource { }, Set: resourceComputeSchedulerHintsHash, }, + "user_data": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + // just stash the hash for state & diff comparisons + StateFunc: func(v interface{}) string { + switch v.(type) { + case string: + hash := sha1.Sum([]byte(v.(string))) + return hex.EncodeToString(hash[:]) + default: + return "" + } + }, + }, "stop_before_destroy": { Type: schema.TypeBool, Optional: true, @@ -385,6 +331,10 @@ func ResourceComputeInstanceV2() *schema.Resource { Type: schema.TypeString, Computed: true, }, + "public_ip": { + Type: schema.TypeString, + Computed: true, + }, "access_ip_v4": { Type: schema.TypeString, Computed: true, @@ -393,6 +343,65 @@ func ResourceComputeInstanceV2() *schema.Resource { Type: schema.TypeString, Computed: true, }, + "status": { + Type: schema.TypeString, + Computed: true, + }, + + // Deprecated + "metadata": { + Type: schema.TypeMap, + Optional: true, + ConflictsWith: []string{"system_disk_type", "system_disk_size", "data_disks"}, + Deprecated: "use tags instead", + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "block_device": { + Type: schema.TypeList, + Optional: true, + ConflictsWith: []string{"system_disk_type", "system_disk_size", "data_disks"}, + Deprecated: "use system_disk_type, system_disk_size, data_disks instead", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "source_type": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "uuid": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, + "volume_size": { + Type: schema.TypeInt, + Optional: true, + ForceNew: true, + }, + "destination_type": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, + "boot_index": { + Type: schema.TypeInt, + Optional: true, + ForceNew: true, + }, + "delete_on_termination": { + Type: schema.TypeBool, + Optional: true, + Default: false, + ForceNew: true, + }, + "guest_format": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, + }, + }, + }, }, } } @@ -650,14 +659,30 @@ func resourceComputeInstanceV2Read(d *schema.ResourceData, meta interface{}) err d.Set("region", GetRegion(d, config)) d.Set("availability_zone", server.AvailabilityZone) d.Set("name", server.Name) + d.Set("status", server.Status) d.Set("agency_name", server.Metadata.AgencyName) + flavorInfo := server.Flavor + d.Set("flavor_id", flavorInfo.ID) + d.Set("flavor_name", flavorInfo.Name) + + // Set the instance's image information appropriately + if err := setImageInformation(d, computeClient, server.Image.ID); err != nil { + return err + } + + if server.KeyName != "" { + d.Set("key_pair", server.KeyName) + } + if eip := computePublicIP(server); eip != "" { + d.Set("public_ip", eip) + } + // Get the instance network and address information networks, err := flattenInstanceNetworks(d, meta, server) if err != nil { return err } - // Determine the best IPv4 and IPv6 addresses to access the instance with hostv4, hostv6 := getInstanceAccessAddresses(d, networks) @@ -697,10 +722,6 @@ func resourceComputeInstanceV2Read(d *schema.ResourceData, meta interface{}) err } d.Set("security_groups", secGrpNames) - flavorInfo := server.Flavor - d.Set("flavor_id", flavorInfo.ID) - d.Set("flavor_name", flavorInfo.Name) - root_volume := "" // Set volume attached bds := []map[string]interface{}{} @@ -738,11 +759,6 @@ func resourceComputeInstanceV2Read(d *schema.ResourceData, meta interface{}) err d.Set("system_disk_type", v.VolumeType) } - // Set the instance's image information appropriately - if err := setImageInformation(d, computeClient, server.Image.ID); err != nil { - return err - } - // Set instance tags resourceTags, err := tags.Get(ecsClient, "cloudservers", d.Id()).Extract() if err != nil { @@ -1287,6 +1303,22 @@ func setImageInformation(d *schema.ResourceData, computeClient *golangsdk.Servic return nil } +// computePublicIP get the first floating address +func computePublicIP(server *cloudservers.CloudServer) string { + var publicIP string + + for _, addresses := range server.Addresses { + for _, addr := range addresses { + if addr.Type == "floating" { + publicIP = addr.Addr + break + } + } + } + + return publicIP +} + func getFlavorID(client *golangsdk.ServiceClient, d *schema.ResourceData) (string, error) { if flavorID := d.Get("flavor_id").(string); flavorID != "" { return flavorID, nil diff --git a/huaweicloud/resource_huaweicloud_compute_instance_test.go b/huaweicloud/resource_huaweicloud_compute_instance_test.go index ae048674a0..2d79012453 100644 --- a/huaweicloud/resource_huaweicloud_compute_instance_test.go +++ b/huaweicloud/resource_huaweicloud_compute_instance_test.go @@ -28,6 +28,11 @@ func TestAccComputeV2Instance_basic(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckComputeV2InstanceExists(resourceName, &instance), resource.TestCheckResourceAttr(resourceName, "name", rName), + resource.TestCheckResourceAttr(resourceName, "status", "ACTIVE"), + resource.TestCheckResourceAttrSet(resourceName, "system_disk_id"), + resource.TestCheckResourceAttrSet(resourceName, "security_groups.#"), + resource.TestCheckResourceAttrSet(resourceName, "network.#"), + resource.TestCheckResourceAttrSet(resourceName, "volume_attached.#"), ), }, {