From fb89a010af3072c54b108add7627334b51784fb0 Mon Sep 17 00:00:00 2001 From: = Date: Thu, 6 Apr 2017 10:46:14 -0600 Subject: [PATCH 1/3] Adding ip address associations --- .../opc/import_ip_address_association_test.go | 33 +++ builtin/providers/opc/provider.go | 1 + .../opc/resource_ip_address_association.go | 151 +++++++++++ .../resource_ip_address_association_test.go | 158 +++++++++++ .../compute/ip_address_associations.go | 152 +++++++++++ .../compute/storage_volume_snapshots.go | 250 ++++++++++++++++++ .../compute/storage_volumes.go | 1 + vendor/vendor.json | 6 +- ...mpute_ip_address_association.html.markdown | 48 ++++ 9 files changed, 797 insertions(+), 3 deletions(-) create mode 100644 builtin/providers/opc/import_ip_address_association_test.go create mode 100644 builtin/providers/opc/resource_ip_address_association.go create mode 100644 builtin/providers/opc/resource_ip_address_association_test.go create mode 100644 vendor/github.com/hashicorp/go-oracle-terraform/compute/ip_address_associations.go create mode 100644 vendor/github.com/hashicorp/go-oracle-terraform/compute/storage_volume_snapshots.go create mode 100644 website/source/docs/providers/opc/r/opc_compute_ip_address_association.html.markdown diff --git a/builtin/providers/opc/import_ip_address_association_test.go b/builtin/providers/opc/import_ip_address_association_test.go new file mode 100644 index 000000000..7730e6cdd --- /dev/null +++ b/builtin/providers/opc/import_ip_address_association_test.go @@ -0,0 +1,33 @@ +package opc + +import ( + "testing" + + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" +) + +func TestAccOPCIPAddressAssociation_importBasic(t *testing.T) { + resourceName := "opc_compute_ip_address_association.test" + + ri := acctest.RandInt() + config := testAccIPAddressAssociationBasic(ri) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheck(t) + }, + Providers: testAccProviders, + CheckDestroy: testAccCheckIPAddressAssociationDestroy, + Steps: []resource.TestStep{ + { + Config: config, + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} diff --git a/builtin/providers/opc/provider.go b/builtin/providers/opc/provider.go index e1ac86dee..364c12db0 100644 --- a/builtin/providers/opc/provider.go +++ b/builtin/providers/opc/provider.go @@ -71,6 +71,7 @@ func Provider() terraform.ResourceProvider { "opc_compute_vnic_set": resourceOPCVNICSet(), "opc_compute_security_protocol": resourceOPCSecurityProtocol(), "opc_compute_ip_address_prefix_set": resourceOPCIPAddressPrefixSet(), + "opc_compute_ip_address_association": resourceOPCIPAddressAssociation(), }, ConfigureFunc: providerConfigure, diff --git a/builtin/providers/opc/resource_ip_address_association.go b/builtin/providers/opc/resource_ip_address_association.go new file mode 100644 index 000000000..7659fbf34 --- /dev/null +++ b/builtin/providers/opc/resource_ip_address_association.go @@ -0,0 +1,151 @@ +package opc + +import ( + "fmt" + + "github.com/hashicorp/go-oracle-terraform/compute" + "github.com/hashicorp/terraform/helper/schema" +) + +func resourceOPCIPAddressAssociation() *schema.Resource { + return &schema.Resource{ + Create: resourceOPCIPAddressAssociationCreate, + Read: resourceOPCIPAddressAssociationRead, + Update: resourceOPCIPAddressAssociationUpdate, + Delete: resourceOPCIPAddressAssociationDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "ip_address_reservation": { + Type: schema.TypeString, + Optional: true, + }, + "vnic": { + Type: schema.TypeString, + Optional: true, + }, + "description": { + Type: schema.TypeString, + Optional: true, + }, + "tags": tagsOptionalSchema(), + "uri": { + Type: schema.TypeString, + Computed: true, + }, + }, + } +} + +func resourceOPCIPAddressAssociationCreate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*compute.Client).IPAddressAssociations() + + input := compute.CreateIPAddressAssociationInput{ + Name: d.Get("name").(string), + } + + if ipAddressReservation, ok := d.GetOk("ip_address_reservation"); ok { + input.IPAddressReservation = ipAddressReservation.(string) + } + + if vnic, ok := d.GetOk("vnic"); ok { + input.Vnic = vnic.(string) + } + + tags := getStringList(d, "tags") + if len(tags) != 0 { + input.Tags = tags + } + + if description, ok := d.GetOk("description"); ok { + input.Description = description.(string) + } + + info, err := client.CreateIPAddressAssociation(&input) + if err != nil { + return fmt.Errorf("Error creating IP Address Association: %s", err) + } + + d.SetId(info.Name) + return resourceOPCIPAddressAssociationRead(d, meta) +} + +func resourceOPCIPAddressAssociationRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*compute.Client).IPAddressAssociations() + + getInput := compute.GetIPAddressAssociationInput{ + Name: d.Id(), + } + result, err := client.GetIPAddressAssociation(&getInput) + if err != nil { + // IP Address Association does not exist + if compute.WasNotFoundError(err) { + d.SetId("") + return nil + } + return fmt.Errorf("Error reading IP Address Association %s: %s", d.Id(), err) + } + + d.Set("name", result.Name) + d.Set("ip_address_reservation", result.IPAddressReservation) + d.Set("vnic", result.Vnic) + d.Set("description", result.Description) + d.Set("uri", result.Uri) + if err := setStringList(d, "tags", result.Tags); err != nil { + return err + } + return nil +} + +func resourceOPCIPAddressAssociationUpdate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*compute.Client).IPAddressAssociations() + + input := compute.UpdateIPAddressAssociationInput{ + Name: d.Get("name").(string), + } + + if ipAddressReservation, ok := d.GetOk("ip_address_reservation"); ok { + input.IPAddressReservation = ipAddressReservation.(string) + } + + if vnic, ok := d.GetOk("vnic"); ok { + input.Vnic = vnic.(string) + } + + tags := getStringList(d, "tags") + if len(tags) != 0 { + input.Tags = tags + } + + if description, ok := d.GetOk("description"); ok { + input.Description = description.(string) + } + + info, err := client.UpdateIPAddressAssociation(&input) + if err != nil { + return fmt.Errorf("Error updating IP Address Association: %s", err) + } + + d.SetId(info.Name) + return resourceOPCIPAddressAssociationRead(d, meta) +} + +func resourceOPCIPAddressAssociationDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*compute.Client).IPAddressAssociations() + name := d.Id() + + input := compute.DeleteIPAddressAssociationInput{ + Name: name, + } + if err := client.DeleteIPAddressAssociation(&input); err != nil { + return fmt.Errorf("Error deleting IP Address Association: %s", err) + } + return nil +} diff --git a/builtin/providers/opc/resource_ip_address_association_test.go b/builtin/providers/opc/resource_ip_address_association_test.go new file mode 100644 index 000000000..9c3804d1e --- /dev/null +++ b/builtin/providers/opc/resource_ip_address_association_test.go @@ -0,0 +1,158 @@ +package opc + +import ( + "fmt" + "testing" + + "github.com/hashicorp/go-oracle-terraform/compute" + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" +) + +func TestAccOPCIPAddressAssociation_Basic(t *testing.T) { + rInt := acctest.RandInt() + resourceName := "opc_compute_ip_address_association.test" + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckIPAddressAssociationDestroy, + Steps: []resource.TestStep{ + { + Config: testAccIPAddressAssociationBasic(rInt), + Check: resource.ComposeTestCheckFunc( + testAccCheckIPAddressAssociationExists, + resource.TestCheckResourceAttr( + resourceName, "tags.#", "2"), + ), + }, + { + Config: testAccIPAddressAssociationBasic_Update(rInt), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + resourceName, "tags.#", "1"), + ), + }, + }, + }) +} + +func TestAccOPCIPAddressAssociation_Full(t *testing.T) { + rInt := acctest.RandInt() + resourceName := "opc_compute_ip_address_association.test" + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckIPAddressAssociationDestroy, + Steps: []resource.TestStep{ + { + Config: testAccIPAddressAssociationFull(rInt), + Check: resource.ComposeTestCheckFunc( + testAccCheckIPAddressAssociationExists, + resource.TestCheckResourceAttr( + resourceName, "vnic", fmt.Sprintf("test-vnic-data-%d", rInt)), + resource.TestCheckResourceAttr( + resourceName, "ip_address_reservation", fmt.Sprintf("testing-ip-address-association-%d", rInt)), + ), + }, + }, + }) +} + +func testAccCheckIPAddressAssociationExists(s *terraform.State) error { + client := testAccProvider.Meta().(*compute.Client).IPAddressAssociations() + + for _, rs := range s.RootModule().Resources { + if rs.Type != "opc_compute_ip_address_association" { + continue + } + + input := compute.GetIPAddressAssociationInput{ + Name: rs.Primary.Attributes["name"], + } + if _, err := client.GetIPAddressAssociation(&input); err != nil { + return fmt.Errorf("Error retrieving state of IP Address Association %s: %s", input.Name, err) + } + } + + return nil +} + +func testAccCheckIPAddressAssociationDestroy(s *terraform.State) error { + client := testAccProvider.Meta().(*compute.Client).IPAddressAssociations() + + for _, rs := range s.RootModule().Resources { + if rs.Type != "opc_compute_ip_address_association" { + continue + } + + input := compute.GetIPAddressAssociationInput{ + Name: rs.Primary.Attributes["name"], + } + if info, err := client.GetIPAddressAssociation(&input); err == nil { + return fmt.Errorf("IP Address Association %s still exists: %#v", input.Name, info) + } + } + + return nil +} + +func testAccIPAddressAssociationBasic(rInt int) string { + return fmt.Sprintf(` +resource "opc_compute_ip_address_association" "test" { + name = "testing-acc-%d" + description = "acctesting ip address association test %d" + tags = ["tag1", "tag2"] +}`, rInt, rInt) +} + +func testAccIPAddressAssociationBasic_Update(rInt int) string { + return fmt.Sprintf(` +resource "opc_compute_ip_address_association" "test" { + name = "testing-acc-%d" + description = "acctesting ip address association test updated %d" + tags = ["tag1"] +}`, rInt, rInt) +} + +func testAccIPAddressAssociationFull(rInt int) string { + return fmt.Sprintf(` +resource "opc_compute_ip_network" "foo" { + name = "testing-vnic-data-%d" + description = "testing-ip-address-association" + ip_address_prefix = "10.1.13.0/24" +} +resource "opc_compute_instance" "test" { + name = "test-%d" + label = "test" + shape = "oc3" + image_list = "/oracle/public/oel_6.7_apaas_16.4.5_1610211300" + networking_info { + index = 0 + ip_network = "${opc_compute_ip_network.foo.id}" + vnic = "test-vnic-data-%d" + shared_network = false + mac_address = "02:5a:cd:ec:2e:4c" + } +} +data "opc_compute_network_interface" "eth0" { + instance_name = "${opc_compute_instance.test.name}" + instance_id = "${opc_compute_instance.test.id}" + interface = "eth0" +} +data "opc_compute_vnic" "foo" { + name = "${data.opc_compute_network_interface.eth0.vnic}" +} +resource "opc_compute_ip_address_reservation" "test" { + name = "testing-ip-address-association-%d" + description = "testing-desc-%d" + ip_address_pool = "public-ippool" +} +resource "opc_compute_ip_address_association" "test" { + name = "testing-acc-%d" + ip_address_reservation = "${opc_compute_ip_address_reservation.test.name}" + vnic = "${data.opc_compute_vnic.foo.name}" + description = "acctesting ip address association test %d" + tags = ["tag1", "tag2"] +}`, rInt, rInt, rInt, rInt, rInt, rInt, rInt) +} diff --git a/vendor/github.com/hashicorp/go-oracle-terraform/compute/ip_address_associations.go b/vendor/github.com/hashicorp/go-oracle-terraform/compute/ip_address_associations.go new file mode 100644 index 000000000..335ada558 --- /dev/null +++ b/vendor/github.com/hashicorp/go-oracle-terraform/compute/ip_address_associations.go @@ -0,0 +1,152 @@ +package compute + +const ( + IPAddressAssociationDescription = "ip address association" + IPAddressAssociationContainerPath = "/network/v1/ipassociation/" + IPAddressAssociationResourcePath = "/network/v1/ipassociation" +) + +type IPAddressAssociationsClient struct { + ResourceClient +} + +// IPAddressAssociations() returns an IPAddressAssociationsClient that can be used to access the +// necessary CRUD functions for IP Address Associations. +func (c *Client) IPAddressAssociations() *IPAddressAssociationsClient { + return &IPAddressAssociationsClient{ + ResourceClient: ResourceClient{ + Client: c, + ResourceDescription: IPAddressAssociationDescription, + ContainerPath: IPAddressAssociationContainerPath, + ResourceRootPath: IPAddressAssociationResourcePath, + }, + } +} + +// IPAddressAssociationInfo contains the exported fields necessary to hold all the information about an +// IP Address Association +type IPAddressAssociationInfo struct { + // The name of the NAT IP address reservation. + IPAddressReservation string `json:"ipAddressReservation"` + // Name of the virtual NIC associated with this NAT IP reservation. + Vnic string `json:"vnic"` + // The name of the IP Address Association + Name string `json:"name"` + // Description of the IP Address Association + Description string `json:"description"` + // Slice of tags associated with the IP Address Association + Tags []string `json:"tags"` + // Uniform Resource Identifier for the IP Address Association + Uri string `json:"uri"` +} + +type CreateIPAddressAssociationInput struct { + // The name of the IP Address Association to create. Object names can only contain alphanumeric, + // underscore, dash, and period characters. Names are case-sensitive. + // Required + Name string `json:"name"` + + // The name of the NAT IP address reservation. + // Optional + IPAddressReservation string `json:"ipAddressReservation,omitempty"` + + // Name of the virtual NIC associated with this NAT IP reservation. + // Optional + Vnic string `json:"vnic,omitempty"` + + // Description of the IPAddressAssociation + // Optional + Description string `json:"description"` + + // String slice of tags to apply to the IP Address Association object + // Optional + Tags []string `json:"tags"` +} + +// Create a new IP Address Association from an IPAddressAssociationsClient and an input struct. +// Returns a populated Info struct for the IP Address Association, and any errors +func (c *IPAddressAssociationsClient) CreateIPAddressAssociation(input *CreateIPAddressAssociationInput) (*IPAddressAssociationInfo, error) { + input.Name = c.getQualifiedName(input.Name) + input.IPAddressReservation = c.getQualifiedName(input.IPAddressReservation) + input.Vnic = c.getQualifiedName(input.Vnic) + + var ipInfo IPAddressAssociationInfo + if err := c.createResource(&input, &ipInfo); err != nil { + return nil, err + } + + return c.success(&ipInfo) +} + +type GetIPAddressAssociationInput struct { + // The name of the IP Address Association to query for. Case-sensitive + // Required + Name string `json:"name"` +} + +// Returns a populated IPAddressAssociationInfo struct from an input struct +func (c *IPAddressAssociationsClient) GetIPAddressAssociation(input *GetIPAddressAssociationInput) (*IPAddressAssociationInfo, error) { + input.Name = c.getQualifiedName(input.Name) + + var ipInfo IPAddressAssociationInfo + if err := c.getResource(input.Name, &ipInfo); err != nil { + return nil, err + } + + return c.success(&ipInfo) +} + +// UpdateIPAddressAssociationInput defines what to update in a ip address association +type UpdateIPAddressAssociationInput struct { + // The name of the IP Address Association to create. Object names can only contain alphanumeric, + // underscore, dash, and period characters. Names are case-sensitive. + // Required + Name string `json:"name"` + + // The name of the NAT IP address reservation. + // Optional + IPAddressReservation string `json:"ipAddressReservation,omitempty"` + + // Name of the virtual NIC associated with this NAT IP reservation. + // Optional + Vnic string `json:"vnic,omitempty"` + + // Description of the IPAddressAssociation + // Optional + Description string `json:"description"` + + // String slice of tags to apply to the IP Address Association object + // Optional + Tags []string `json:"tags"` +} + +// UpdateIPAddressAssociation update the ip address association +func (c *IPAddressAssociationsClient) UpdateIPAddressAssociation(updateInput *UpdateIPAddressAssociationInput) (*IPAddressAssociationInfo, error) { + updateInput.Name = c.getQualifiedName(updateInput.Name) + updateInput.IPAddressReservation = c.getQualifiedName(updateInput.IPAddressReservation) + updateInput.Vnic = c.getQualifiedName(updateInput.Vnic) + var ipInfo IPAddressAssociationInfo + if err := c.updateResource(updateInput.Name, updateInput, &ipInfo); err != nil { + return nil, err + } + + return c.success(&ipInfo) +} + +type DeleteIPAddressAssociationInput struct { + // The name of the IP Address Association to query for. Case-sensitive + // Required + Name string `json:"name"` +} + +func (c *IPAddressAssociationsClient) DeleteIPAddressAssociation(input *DeleteIPAddressAssociationInput) error { + return c.deleteResource(input.Name) +} + +// Unqualifies any qualified fields in the IPAddressAssociationInfo struct +func (c *IPAddressAssociationsClient) success(info *IPAddressAssociationInfo) (*IPAddressAssociationInfo, error) { + c.unqualify(&info.Name) + c.unqualify(&info.Vnic) + c.unqualify(&info.IPAddressReservation) + return info, nil +} diff --git a/vendor/github.com/hashicorp/go-oracle-terraform/compute/storage_volume_snapshots.go b/vendor/github.com/hashicorp/go-oracle-terraform/compute/storage_volume_snapshots.go new file mode 100644 index 000000000..f958d2107 --- /dev/null +++ b/vendor/github.com/hashicorp/go-oracle-terraform/compute/storage_volume_snapshots.go @@ -0,0 +1,250 @@ +package compute + +import ( + "fmt" + "strings" +) + +const ( + StorageVolumeSnapshotDescription = "storage volume snapshot" + StorageVolumeSnapshotContainerPath = "/storage/snapshot/" + StorageVolumeSnapshotResourcePath = "/storage/snapshot" + + WaitForSnapshotCreateTimeout = 1200 + WaitForSnapshotDeleteTimeout = 1500 + + // Collocated Snapshot Property + SnapshotPropertyCollocated = "/oracle/private/storage/snapshot/collocated" +) + +// StorageVolumeSnapshotClient is a client for the Storage Volume Snapshot functions of the Compute API. +type StorageVolumeSnapshotClient struct { + ResourceClient +} + +func (c *Client) StorageVolumeSnapshots() *StorageVolumeSnapshotClient { + return &StorageVolumeSnapshotClient{ + ResourceClient: ResourceClient{ + Client: c, + ResourceDescription: StorageVolumeSnapshotDescription, + ContainerPath: StorageVolumeSnapshotContainerPath, + ResourceRootPath: StorageVolumeSnapshotResourcePath, + }, + } +} + +// StorageVolumeSnapshotInfo represents the information retrieved from the service about a storage volume snapshot +type StorageVolumeSnapshotInfo struct { + // Account to use for snapshots + Account string `json:"account"` + + // Description of the snapshot + Description string `json:"description"` + + // The name of the machine image that's used in the boot volume from which this snapshot is taken + MachineImageName string `json:"machineimage_name"` + + // Name of the snapshot + Name string `json:"name"` + + // String indicating whether the parent volume is bootable or not + ParentVolumeBootable string `json:"parent_volume_bootable"` + + // Platform the snapshot is compatible with + Platform string `json:"platform"` + + // String determining whether the snapshot is remote or collocated + Property string `json:"property"` + + // The size of the snapshot in GB + Size string `json:"size"` + + // The ID of the snapshot. Generated by the server + SnapshotID string `json:"snapshot_id"` + + // The timestamp of the storage snapshot + SnapshotTimestamp string `json:"snapshot_timestamp"` + + // Timestamp for when the operation started + StartTimestamp string `json:"start_timestamp"` + + // Status of the snapshot + Status string `json:"status"` + + // Status Detail of the storage snapshot + StatusDetail string `json:"status_detail"` + + // Indicates the time that the current view of the storage volume snapshot was generated. + StatusTimestamp string `json:"status_timestamp"` + + // Array of tags for the snapshot + Tags []string `json:"tags,omitempty"` + + // Uniform Resource Identifier + URI string `json:"uri"` + + // Name of the parent storage volume for the snapshot + Volume string `json:"volume"` +} + +// CreateStorageVolumeSnapshotInput represents the body of an API request to create a new storage volume snapshot +type CreateStorageVolumeSnapshotInput struct { + // Description of the snapshot + // Optional + Description string `json:"description,omitempty"` + + // Name of the snapshot + // Optional, will be generated if not specified + Name string `json:"name,omitempty"` + + // Whether or not the parent volume is bootable + // Optional + ParentVolumeBootable string `json:"parent_volume_bootable,omitempty"` + + // Whether collocated or remote + // Optional, will be remote if unspecified + Property string `json:"property,omitempty"` + + // Array of tags for the snapshot + // Optional + Tags []string `json:"tags,omitempty"` + + // Name of the volume to create the snapshot from + // Required + Volume string `json:"volume"` + + // Timeout (in seconds) to wait for snapshot to be completed. Will use default if unspecified + Timeout int +} + +// CreateStorageVolumeSnapshot creates a snapshot based on the supplied information struct +func (c *StorageVolumeSnapshotClient) CreateStorageVolumeSnapshot(input *CreateStorageVolumeSnapshotInput) (*StorageVolumeSnapshotInfo, error) { + if input.Name != "" { + input.Name = c.getQualifiedName(input.Name) + } + input.Volume = c.getQualifiedName(input.Volume) + + var storageSnapshotInfo StorageVolumeSnapshotInfo + if err := c.createResource(&input, &storageSnapshotInfo); err != nil { + return nil, err + } + + timeout := WaitForSnapshotCreateTimeout + if input.Timeout != 0 { + timeout = input.Timeout + } + + // The name of the snapshot could have been generated. Use the response name as input + return c.waitForStorageSnapshotAvailable(storageSnapshotInfo.Name, timeout) +} + +// GetStorageVolumeSnapshotInput represents the body of an API request to get information on a storage volume snapshot +type GetStorageVolumeSnapshotInput struct { + // Name of the snapshot + Name string `json:"name"` +} + +// GetStorageVolumeSnapshot makes an API request to populate information on a storage volume snapshot +func (c *StorageVolumeSnapshotClient) GetStorageVolumeSnapshot(input *GetStorageVolumeSnapshotInput) (*StorageVolumeSnapshotInfo, error) { + var storageSnapshot StorageVolumeSnapshotInfo + input.Name = c.getQualifiedName(input.Name) + if err := c.getResource(input.Name, &storageSnapshot); err != nil { + if WasNotFoundError(err) { + return nil, nil + } + + return nil, err + } + return c.success(&storageSnapshot) +} + +// DeleteStorageVolumeSnapshotInput represents the body of an API request to delete a storage volume snapshot +type DeleteStorageVolumeSnapshotInput struct { + // Name of the snapshot to delete + Name string `json:"name"` + + // Timeout in seconds to wait for deletion, will use default if unspecified + Timeout int +} + +// DeleteStoragevolumeSnapshot makes an API request to delete a storage volume snapshot +func (c *StorageVolumeSnapshotClient) DeleteStorageVolumeSnapshot(input *DeleteStorageVolumeSnapshotInput) error { + input.Name = c.getQualifiedName(input.Name) + + if err := c.deleteResource(input.Name); err != nil { + return err + } + + timeout := WaitForSnapshotDeleteTimeout + if input.Timeout != 0 { + timeout = input.Timeout + } + + return c.waitForStorageSnapshotDeleted(input.Name, timeout) +} + +func (c *StorageVolumeSnapshotClient) success(result *StorageVolumeSnapshotInfo) (*StorageVolumeSnapshotInfo, error) { + c.unqualify(&result.Name) + c.unqualify(&result.Volume) + + sizeInGigaBytes, err := sizeInGigaBytes(result.Size) + if err != nil { + return nil, err + } + result.Size = sizeInGigaBytes + + return result, nil +} + +// Waits for a storage snapshot to become available +func (c *StorageVolumeSnapshotClient) waitForStorageSnapshotAvailable(name string, timeout int) (*StorageVolumeSnapshotInfo, error) { + var result *StorageVolumeSnapshotInfo + + err := c.waitFor( + fmt.Sprintf("storage volume snapshot %s to become available", c.getQualifiedName(name)), + timeout, + func() (bool, error) { + req := &GetStorageVolumeSnapshotInput{ + Name: name, + } + res, err := c.GetStorageVolumeSnapshot(req) + if err != nil { + return false, err + } + + if res != nil { + result = res + if strings.ToLower(result.Status) == "completed" { + return true, nil + } else if strings.ToLower(result.Status) == "error" { + return false, fmt.Errorf("Snapshot '%s' failed to create successfully. Status: %s Status Detail: %s", result.Name, result.Status, result.StatusDetail) + } + } + + return false, nil + }) + + return result, err +} + +// Waits for a storage snapshot to be deleted +func (c *StorageVolumeSnapshotClient) waitForStorageSnapshotDeleted(name string, timeout int) error { + return c.waitFor( + fmt.Sprintf("storage volume snapshot %s to be deleted", c.getQualifiedName(name)), + timeout, + func() (bool, error) { + req := &GetStorageVolumeSnapshotInput{ + Name: name, + } + res, err := c.GetStorageVolumeSnapshot(req) + if res == nil { + return true, nil + } + + if err != nil { + return false, err + } + + return res == nil, nil + }) +} diff --git a/vendor/github.com/hashicorp/go-oracle-terraform/compute/storage_volumes.go b/vendor/github.com/hashicorp/go-oracle-terraform/compute/storage_volumes.go index c40c354a9..7193a6c24 100644 --- a/vendor/github.com/hashicorp/go-oracle-terraform/compute/storage_volumes.go +++ b/vendor/github.com/hashicorp/go-oracle-terraform/compute/storage_volumes.go @@ -188,6 +188,7 @@ type GetStorageVolumeInput struct { func (c *StorageVolumeClient) success(result *StorageVolumeInfo) (*StorageVolumeInfo, error) { c.unqualify(&result.Name) + c.unqualify(&result.Snapshot) sizeInMegaBytes, err := sizeInGigaBytes(result.Size) if err != nil { diff --git a/vendor/vendor.json b/vendor/vendor.json index 63c77ed33..0f8bd50ef 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -1970,10 +1970,10 @@ "revision": "d30f09973e19c1dfcd120b2d9c4f168e68d6b5d5" }, { - "checksumSHA1": "QKusHEboSl00AnORqkjv0gZEhqw=", + "checksumSHA1": "mVLpbxsm+8TlXKgkezrh3c5I7+4=", "path": "github.com/hashicorp/go-oracle-terraform/compute", - "revision": "15f277fb824b7af18c6bef8d30d84174154f989b", - "revisionTime": "2017-04-05T20:02:51Z" + "revision": "381402af3554bcca5fa7eeda94d47003e6ba7ee7", + "revisionTime": "2017-04-06T04:33:22Z" }, { "checksumSHA1": "DzK7lYwHt5Isq5Zf73cnQqBO2LI=", diff --git a/website/source/docs/providers/opc/r/opc_compute_ip_address_association.html.markdown b/website/source/docs/providers/opc/r/opc_compute_ip_address_association.html.markdown new file mode 100644 index 000000000..44429a030 --- /dev/null +++ b/website/source/docs/providers/opc/r/opc_compute_ip_address_association.html.markdown @@ -0,0 +1,48 @@ +--- +layout: "opc" +page_title: "Oracle: opc_compute_ip_address_association" +sidebar_current: "docs-opc-resource-ip-address-association" +description: |- + Creates and manages an IP address association in an OPC identity domain. +--- + +# opc\_compute\_ip\_address\_association + +The ``opc_compute_ip_address_association`` resource creates and manages an IP address association in an OPC identity domain. + +## Example Usage + +``` +resource "opc_compute_ip_address_association" "default" { + name = "PrefixSet1" + ip_address_reservation = "${opc_compute_ip_address_reservation.default.name}" + vnic = "${data.opc_compute_vnic.default.name}" + tags = ["tags1", "tags2"] +} +``` + +## Argument Reference + +The following arguments are supported: + +* `name` - (Required) The name of the ip address association. + +* `ip_address_reservation` - (Optional) The name of the NAT IP address reservation. + +* `vnic` - (Optional) The name of the virtual NIC associated with this NAT IP reservation. + +* `description` - (Optional) A description of the ip address association. + +* `tags` - (Optional) List of tags that may be applied to the ip address association. + +In addition to the above, the following variables are exported: + +* `uri` - (Computed) The Uniform Resource Identifier of the ip address association. + +## Import + +IP Address Prefix Set can be imported using the `resource name`, e.g. + +``` +terraform import opc_compute_ip_address_association.default example +``` From 1d02ed51c17b503ed15ceb823f0142224221499c Mon Sep 17 00:00:00 2001 From: = Date: Thu, 6 Apr 2017 16:27:22 -0600 Subject: [PATCH 2/3] fixed nits --- .../providers/opc/import_ip_address_association_test.go | 8 ++------ builtin/providers/opc/provider.go | 2 +- builtin/providers/opc/resource_ip_address_association.go | 6 +++++- .../providers/opc/resource_ip_address_association_test.go | 5 +---- .../r/opc_compute_ip_address_association.html.markdown | 4 ++-- 5 files changed, 11 insertions(+), 14 deletions(-) diff --git a/builtin/providers/opc/import_ip_address_association_test.go b/builtin/providers/opc/import_ip_address_association_test.go index 7730e6cdd..a68f6daf8 100644 --- a/builtin/providers/opc/import_ip_address_association_test.go +++ b/builtin/providers/opc/import_ip_address_association_test.go @@ -11,17 +11,13 @@ func TestAccOPCIPAddressAssociation_importBasic(t *testing.T) { resourceName := "opc_compute_ip_address_association.test" ri := acctest.RandInt() - config := testAccIPAddressAssociationBasic(ri) - resource.Test(t, resource.TestCase{ - PreCheck: func() { - testAccPreCheck(t) - }, + PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, CheckDestroy: testAccCheckIPAddressAssociationDestroy, Steps: []resource.TestStep{ { - Config: config, + Config: testAccIPAddressAssociationBasic(ri), }, { ResourceName: resourceName, diff --git a/builtin/providers/opc/provider.go b/builtin/providers/opc/provider.go index b03f68f58..354439340 100644 --- a/builtin/providers/opc/provider.go +++ b/builtin/providers/opc/provider.go @@ -72,7 +72,7 @@ func Provider() terraform.ResourceProvider { "opc_compute_vnic_set": resourceOPCVNICSet(), "opc_compute_security_protocol": resourceOPCSecurityProtocol(), "opc_compute_ip_address_prefix_set": resourceOPCIPAddressPrefixSet(), - "opc_compute_ip_address_association": resourceOPCIPAddressAssociation(), + "opc_compute_ip_address_association": resourceOPCIPAddressAssociation(), }, ConfigureFunc: providerConfigure, diff --git a/builtin/providers/opc/resource_ip_address_association.go b/builtin/providers/opc/resource_ip_address_association.go index 7659fbf34..32ebf43d9 100644 --- a/builtin/providers/opc/resource_ip_address_association.go +++ b/builtin/providers/opc/resource_ip_address_association.go @@ -90,7 +90,11 @@ func resourceOPCIPAddressAssociationRead(d *schema.ResourceData, meta interface{ d.SetId("") return nil } - return fmt.Errorf("Error reading IP Address Association %s: %s", d.Id(), err) + return fmt.Errorf("Error reading IP Address Association %s: %s", getInput.Name, err) + } + if result == nil { + d.SetId("") + return fmt.Errorf("Error reading IP Address Association %s: %s", getInput.Name, err) } d.Set("name", result.Name) diff --git a/builtin/providers/opc/resource_ip_address_association_test.go b/builtin/providers/opc/resource_ip_address_association_test.go index 9c3804d1e..a08abfbc1 100644 --- a/builtin/providers/opc/resource_ip_address_association_test.go +++ b/builtin/providers/opc/resource_ip_address_association_test.go @@ -140,9 +140,6 @@ data "opc_compute_network_interface" "eth0" { instance_id = "${opc_compute_instance.test.id}" interface = "eth0" } -data "opc_compute_vnic" "foo" { - name = "${data.opc_compute_network_interface.eth0.vnic}" -} resource "opc_compute_ip_address_reservation" "test" { name = "testing-ip-address-association-%d" description = "testing-desc-%d" @@ -151,7 +148,7 @@ resource "opc_compute_ip_address_reservation" "test" { resource "opc_compute_ip_address_association" "test" { name = "testing-acc-%d" ip_address_reservation = "${opc_compute_ip_address_reservation.test.name}" - vnic = "${data.opc_compute_vnic.foo.name}" + vnic = "${data.opc_compute_network_interface.eth0.vnic}" description = "acctesting ip address association test %d" tags = ["tag1", "tag2"] }`, rInt, rInt, rInt, rInt, rInt, rInt, rInt) diff --git a/website/source/docs/providers/opc/r/opc_compute_ip_address_association.html.markdown b/website/source/docs/providers/opc/r/opc_compute_ip_address_association.html.markdown index 44429a030..b531cf559 100644 --- a/website/source/docs/providers/opc/r/opc_compute_ip_address_association.html.markdown +++ b/website/source/docs/providers/opc/r/opc_compute_ip_address_association.html.markdown @@ -8,7 +8,7 @@ description: |- # opc\_compute\_ip\_address\_association -The ``opc_compute_ip_address_association`` resource creates and manages an IP address association in an OPC identity domain. +The ``opc_compute_ip_address_association`` resource creates and manages an IP address association between an IP address reservation and a virtual NIC in an OPC identity domain. ## Example Usage @@ -41,7 +41,7 @@ In addition to the above, the following variables are exported: ## Import -IP Address Prefix Set can be imported using the `resource name`, e.g. +IP Address Associations can be imported using the `resource name`, e.g. ``` terraform import opc_compute_ip_address_association.default example From d79b479ad2fc18e9abc59f0e5cd3ba3cbeca50a3 Mon Sep 17 00:00:00 2001 From: = Date: Thu, 6 Apr 2017 16:28:50 -0600 Subject: [PATCH 3/3] final nit fix --- builtin/providers/opc/resource_ip_address_association.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/builtin/providers/opc/resource_ip_address_association.go b/builtin/providers/opc/resource_ip_address_association.go index 32ebf43d9..de7dec4db 100644 --- a/builtin/providers/opc/resource_ip_address_association.go +++ b/builtin/providers/opc/resource_ip_address_association.go @@ -79,9 +79,10 @@ func resourceOPCIPAddressAssociationCreate(d *schema.ResourceData, meta interfac func resourceOPCIPAddressAssociationRead(d *schema.ResourceData, meta interface{}) error { client := meta.(*compute.Client).IPAddressAssociations() + name := d.Id() getInput := compute.GetIPAddressAssociationInput{ - Name: d.Id(), + name, } result, err := client.GetIPAddressAssociation(&getInput) if err != nil { @@ -90,11 +91,11 @@ func resourceOPCIPAddressAssociationRead(d *schema.ResourceData, meta interface{ d.SetId("") return nil } - return fmt.Errorf("Error reading IP Address Association %s: %s", getInput.Name, err) + return fmt.Errorf("Error reading IP Address Association %s: %s", name, err) } if result == nil { d.SetId("") - return fmt.Errorf("Error reading IP Address Association %s: %s", getInput.Name, err) + return fmt.Errorf("Error reading IP Address Association %s: %s", name, err) } d.Set("name", result.Name)