diff --git a/cloudstack/resource_cloudstack_nic.go b/cloudstack/resource_cloudstack_nic.go index 36c25ecf..7f1abb9a 100644 --- a/cloudstack/resource_cloudstack_nic.go +++ b/cloudstack/resource_cloudstack_nic.go @@ -33,6 +33,9 @@ func resourceCloudStackNIC() *schema.Resource { Create: resourceCloudStackNICCreate, Read: resourceCloudStackNICRead, Delete: resourceCloudStackNICDelete, + Importer: &schema.ResourceImporter{ + State: importStateNIC, + }, Schema: map[string]*schema.Schema{ "network_id": { @@ -59,6 +62,12 @@ func resourceCloudStackNIC() *schema.Resource { Computed: true, ForceNew: true, }, + + "project": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, }, } } @@ -107,8 +116,13 @@ func resourceCloudStackNICCreate(d *schema.ResourceData, meta interface{}) error func resourceCloudStackNICRead(d *schema.ResourceData, meta interface{}) error { cs := meta.(*cloudstack.CloudStackClient) - // Get the virtual machine details - vm, count, err := cs.VirtualMachine.GetVirtualMachineByID(d.Get("virtual_machine_id").(string)) + // Get the virtual machine details. Instances that belong to a project are + // not returned by listVirtualMachines unless the project is passed along, + // so scope the lookup the same way the instance resource does. + vm, count, err := cs.VirtualMachine.GetVirtualMachineByID( + d.Get("virtual_machine_id").(string), + cloudstack.WithProject(d.Get("project").(string)), + ) if err != nil { if count == 0 { log.Printf("[DEBUG] Instance %s does no longer exist", d.Get("virtual_machine_id").(string)) @@ -165,6 +179,30 @@ func resourceCloudStackNICDelete(d *schema.ResourceData, meta interface{}) error return nil } +// importStateNIC imports a NIC using "/", or +// "//" when the instance belongs to a +// project. The parent instance cannot be derived from the NIC ID alone, so the +// generic passthrough importer is not usable here. +func importStateNIC(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + s := strings.Split(d.Id(), "/") + + switch len(s) { + case 2: + d.Set("virtual_machine_id", s[0]) + d.SetId(s[1]) + case 3: + d.Set("project", s[0]) + d.Set("virtual_machine_id", s[1]) + d.SetId(s[2]) + default: + return nil, fmt.Errorf( + "invalid import ID %q, expected / or "+ + "//", d.Id()) + } + + return []*schema.ResourceData{d}, nil +} + func retryableAddNicFunc(cs *cloudstack.CloudStackClient, p *cloudstack.AddNicToVirtualMachineParams) func() (interface{}, error) { return func() (interface{}, error) { r, err := cs.VirtualMachine.AddNicToVirtualMachine(p) diff --git a/website/docs/r/nic.html.markdown b/website/docs/r/nic.html.markdown index a000e703..14df34b3 100644 --- a/website/docs/r/nic.html.markdown +++ b/website/docs/r/nic.html.markdown @@ -50,6 +50,11 @@ The following arguments are supported: * `virtual_machine_id` - (Required) The ID of the virtual machine to which to attach the NIC. Changing this forces a new resource to be created. +* `project` - (Optional) The name or ID of the project the virtual machine + belongs to. Required when the virtual machine belongs to a project, + otherwise the NIC cannot be read back. Changing this forces a new resource + to be created. + ## Attributes Reference The following attributes are exported: @@ -57,3 +62,17 @@ The following attributes are exported: * `id` - The ID of the NIC. * `ip_address` - The assigned IP address. * `mac_address` - The assigned MAC address. + +## Import + +NICs can be imported using `/`, e.g. + +```shell +$ terraform import cloudstack_nic.test f8141e2f-4e7e-4c63-9362-986c908b7ea7/2b1a4b3c-5d6e-4f70-8192-a3b4c5d6e7f8 +``` + +When the virtual machine belongs to a project, prefix the project: + +```shell +$ terraform import cloudstack_nic.test my-project/f8141e2f-4e7e-4c63-9362-986c908b7ea7/2b1a4b3c-5d6e-4f70-8192-a3b4c5d6e7f8 +```