diff --git a/outscale/resource_outscale_flexible_gpu_link.go b/outscale/resource_outscale_flexible_gpu_link.go index 8c2addc12..9233582b7 100644 --- a/outscale/resource_outscale_flexible_gpu_link.go +++ b/outscale/resource_outscale_flexible_gpu_link.go @@ -16,16 +16,20 @@ func resourceOutscaleOAPIFlexibleGpuLink() *schema.Resource { return &schema.Resource{ Create: resourceOutscaleOAPIFlexibleGpuLinkCreate, Read: resourceOutscaleOAPIFlexibleGpuLinkRead, + Update: resourceFlexibleGpuLinkUpdate, Delete: resourceOutscaleOAPIFlexibleGpuLinkDelete, Importer: &schema.ResourceImporter{ State: schema.ImportStatePassthrough, }, Schema: map[string]*schema.Schema{ - "flexible_gpu_id": { - Type: schema.TypeString, + "flexible_gpu_ids": { + Type: schema.TypeSet, Required: true, - ForceNew: true, + MinItems: 1, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, }, "vm_id": { Type: schema.TypeString, @@ -42,61 +46,31 @@ func resourceOutscaleOAPIFlexibleGpuLink() *schema.Resource { func resourceOutscaleOAPIFlexibleGpuLinkCreate(d *schema.ResourceData, meta interface{}) error { conn := meta.(*OutscaleClient).OSCAPI - - flexGpuID := d.Get("flexible_gpu_id").(string) vmId := d.Get("vm_id").(string) + GpuIdsList := utils.SetToStringSlice(d.Get("flexible_gpu_ids").(*schema.Set)) - filter := &oscgo.FiltersFlexibleGpu{ - FlexibleGpuIds: &[]string{flexGpuID}, - } - reqFlex := &oscgo.ReadFlexibleGpusRequest{ - Filters: filter, - } - reqLink := oscgo.LinkFlexibleGpuRequest{ - FlexibleGpuId: flexGpuID, - VmId: vmId, - } - var resp oscgo.LinkFlexibleGpuResponse - err := resource.Retry(60*time.Second, func() *resource.RetryError { - var err error - rp, httpResp, err := conn.FlexibleGpuApi.LinkFlexibleGpu( - context.Background()).LinkFlexibleGpuRequest(reqLink).Execute() - if err != nil { - return utils.CheckThrottling(httpResp, err) + for _, flexGpuID := range GpuIdsList { + var resp oscgo.LinkFlexibleGpuResponse + reqLink := oscgo.LinkFlexibleGpuRequest{ + FlexibleGpuId: flexGpuID, + VmId: vmId, } - resp = rp - return nil - }) - - if err != nil { - return fmt.Errorf("Error Link flexibe gpu: %s", err.Error()) - } - - if !resp.HasResponseContext() { - return fmt.Errorf("Error there is not Link flexible gpu (%s)", err) - } - - var respV oscgo.ReadFlexibleGpusResponse - err = resource.Retry(60*time.Second, func() *resource.RetryError { - rp, httpResp, err := conn.FlexibleGpuApi.ReadFlexibleGpus(context.Background()). - ReadFlexibleGpusRequest(*reqFlex).Execute() + err := resource.Retry(60*time.Second, func() *resource.RetryError { + var err error + rp, httpResp, err := conn.FlexibleGpuApi.LinkFlexibleGpu( + context.Background()).LinkFlexibleGpuRequest(reqLink).Execute() + if err != nil { + return utils.CheckThrottling(httpResp, err) + } + resp = rp + return nil + }) if err != nil { - return utils.CheckThrottling(httpResp, err) + return fmt.Errorf("Error Link flexibe gpu: %s", err.Error()) + } + if !resp.HasResponseContext() { + return fmt.Errorf("Error there is not Link flexible gpu (%s)", err) } - respV = rp - return nil - }) - - if err != nil { - return fmt.Errorf("error reading the FlexibleGpu %s", err) - } - - if err := utils.IsResponseEmptyOrMutiple(len(respV.GetFlexibleGpus()), "FlexibleGpu"); err != nil { - return err - } - - if (*respV.FlexibleGpus)[0].GetState() != "attaching" { - return fmt.Errorf("Unable to link Flexible GPU") } if err := changeShutdownBehavior(conn, vmId); err != nil { @@ -108,19 +82,15 @@ func resourceOutscaleOAPIFlexibleGpuLinkCreate(d *schema.ResourceData, meta inte func resourceOutscaleOAPIFlexibleGpuLinkRead(d *schema.ResourceData, meta interface{}) error { conn := meta.(*OutscaleClient).OSCAPI - - flexGpuID := d.Get("flexible_gpu_id").(string) - if flexGpuID == "" { - flexGpuID = d.Id() - } + vmId := d.Get("vm_id").(string) req := &oscgo.ReadFlexibleGpusRequest{ Filters: &oscgo.FiltersFlexibleGpu{ - FlexibleGpuIds: &[]string{flexGpuID}, + VmIds: &[]string{vmId}, }, } - var resp oscgo.ReadFlexibleGpusResponse var err error + err = resource.Retry(60*time.Second, func() *resource.RetryError { rp, httpResp, err := conn.FlexibleGpuApi.ReadFlexibleGpus( context.Background()). @@ -139,82 +109,132 @@ func resourceOutscaleOAPIFlexibleGpuLinkRead(d *schema.ResourceData, meta interf d.SetId("") return nil } - - fg := (*resp.FlexibleGpus)[0] - if err := d.Set("flexible_gpu_id", fg.GetFlexibleGpuId()); err != nil { + flexGpus := resp.GetFlexibleGpus()[:] + readGpuIdsLink := make([]string, len(flexGpus)) + for k, flexGpu := range flexGpus { + readGpuIdsLink[k] = flexGpu.GetFlexibleGpuId() + } + if err := d.Set("flexible_gpu_ids", readGpuIdsLink); err != nil { return err } - if err := d.Set("vm_id", fg.GetVmId()); err != nil { + if err := d.Set("vm_id", vmId); err != nil { return err } - d.SetId(fg.GetFlexibleGpuId()) - + d.SetId(resource.UniqueId()) return nil } func resourceOutscaleOAPIFlexibleGpuLinkDelete(d *schema.ResourceData, meta interface{}) error { conn := meta.(*OutscaleClient).OSCAPI - - flexGpuID := d.Get("flexible_gpu_id").(string) - vmId := d.Get("vm_id").(string) - - filter := &oscgo.FiltersFlexibleGpu{ - FlexibleGpuIds: &[]string{flexGpuID}, - } - reqFlex := &oscgo.ReadFlexibleGpusRequest{ - Filters: filter, - } - - req := &oscgo.UnlinkFlexibleGpuRequest{ - FlexibleGpuId: flexGpuID, - } - + GpuIdsList := utils.SetToStringSlice(d.Get("flexible_gpu_ids").(*schema.Set)) var err error - err = resource.Retry(20*time.Second, func() *resource.RetryError { - _, httpResp, err := conn.FlexibleGpuApi.UnlinkFlexibleGpu( - context.Background()).UnlinkFlexibleGpuRequest(*req).Execute() + + for _, flexGpuID := range GpuIdsList { + req := &oscgo.UnlinkFlexibleGpuRequest{ + FlexibleGpuId: flexGpuID, + } + err = resource.Retry(20*time.Second, func() *resource.RetryError { + _, httpResp, err := conn.FlexibleGpuApi.UnlinkFlexibleGpu( + context.Background()).UnlinkFlexibleGpuRequest(*req).Execute() + if err != nil { + return utils.CheckThrottling(httpResp, err) + } + return nil + }) if err != nil { - return utils.CheckThrottling(httpResp, err) + return err } - return nil - }) - if err != nil { - return err - } - - var resp oscgo.ReadFlexibleGpusResponse - err = resource.Retry(60*time.Second, func() *resource.RetryError { - rp, httpResp, err := conn.FlexibleGpuApi.ReadFlexibleGpus(context.Background()). - ReadFlexibleGpusRequest(*reqFlex).Execute() + var resp oscgo.ReadFlexibleGpusResponse + reqFlex := &oscgo.ReadFlexibleGpusRequest{ + Filters: &oscgo.FiltersFlexibleGpu{ + FlexibleGpuIds: &[]string{flexGpuID}, + }, + } + err = resource.Retry(60*time.Second, func() *resource.RetryError { + rp, httpResp, err := conn.FlexibleGpuApi.ReadFlexibleGpus(context.Background()). + ReadFlexibleGpusRequest(*reqFlex).Execute() + if err != nil { + return utils.CheckThrottling(httpResp, err) + } + resp = rp + return nil + }) if err != nil { - return utils.CheckThrottling(httpResp, err) + return fmt.Errorf("error reading the FlexibleGpu %s", err) } - resp = rp - return nil - }) - if err != nil { - return fmt.Errorf("error reading the FlexibleGpu %s", err) - } - if len(*resp.FlexibleGpus) != 1 { - return fmt.Errorf("Unable to find Flexible GPU") - } - if (*resp.FlexibleGpus)[0].GetState() != "detaching" { - return fmt.Errorf("Unable to unlink Flexible GPU") + if len(*resp.FlexibleGpus) != 1 { + return fmt.Errorf("Unable to find Flexible GPU") + } + if (*resp.FlexibleGpus)[0].GetState() != "detaching" { + return fmt.Errorf("Unable to unlink Flexible GPU") + } } - if err := changeShutdownBehavior(conn, vmId); err != nil { + if err := changeShutdownBehavior(conn, d.Get("vm_id").(string)); err != nil { return fmt.Errorf("Unable to change ShutdownBehavior: %s\n", err) } d.SetId("") return nil +} + +func resourceFlexibleGpuLinkUpdate(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*OutscaleClient).OSCAPI + vmId := d.Get("vm_id").(string) + oldIds, newIds := d.GetChange("flexible_gpu_ids") + + interIds := oldIds.(*schema.Set).Intersection(newIds.(*schema.Set)) + toCreate := newIds.(*schema.Set).Difference(interIds) + toRemove := oldIds.(*schema.Set).Difference(interIds) + var err error + if toRemove.Len() > 0 { + for _, flexGpuID := range utils.SetToStringSlice(toRemove) { + req := &oscgo.UnlinkFlexibleGpuRequest{ + FlexibleGpuId: flexGpuID, + } + err = resource.Retry(20*time.Second, func() *resource.RetryError { + _, httpResp, err := conn.FlexibleGpuApi.UnlinkFlexibleGpu( + context.Background()).UnlinkFlexibleGpuRequest(*req).Execute() + if err != nil { + return utils.CheckThrottling(httpResp, err) + } + return nil + }) + if err != nil { + return err + } + } + } + if toCreate.Len() > 0 { + for _, flexGpuID := range utils.SetToStringSlice(toCreate) { + req := &oscgo.LinkFlexibleGpuRequest{ + FlexibleGpuId: flexGpuID, + VmId: vmId, + } + err = resource.Retry(20*time.Second, func() *resource.RetryError { + _, httpResp, err := conn.FlexibleGpuApi.LinkFlexibleGpu( + context.Background()).LinkFlexibleGpuRequest(*req).Execute() + if err != nil { + return utils.CheckThrottling(httpResp, err) + } + return nil + }) + if err != nil { + return err + } + } + } + if err := changeShutdownBehavior(conn, vmId); err != nil { + return fmt.Errorf("Unable to change ShutdownBehavior: %s\n", err) + } + + return resourceOutscaleOAPIFlexibleGpuLinkRead(d, meta) } func changeShutdownBehavior(conn *oscgo.APIClient, vmId string) error { - var resp oscgo.ReadVmsResponse err := resource.Retry(20*time.Second, func() *resource.RetryError { rp, httpResp, err := conn.VmApi.ReadVms(context.Background()).ReadVmsRequest(oscgo.ReadVmsRequest{ diff --git a/outscale/resource_outscale_flexible_gpu_link_test.go b/outscale/resource_outscale_flexible_gpu_link_test.go index 54e15238f..c720ec5c8 100644 --- a/outscale/resource_outscale_flexible_gpu_link_test.go +++ b/outscale/resource_outscale_flexible_gpu_link_test.go @@ -35,17 +35,21 @@ func testAccOutscaleOAPIFlexibleGpuLinkConfig(omi, vmType, region string) string } - resource "outscale_flexible_gpu" "fGPU-1" { + resource "outscale_flexible_gpu" "fGPU-1" { model_name = "nvidia-p6" generation = "v5" - subregion_name = "%[3]sa" + subregion_name = "%[3]s" + delete_on_vm_deletion = true + } + resource "outscale_flexible_gpu" "fGPU-2" { + model_name = "nvidia-p6" + generation = "v5" + subregion_name = "%[3]s" delete_on_vm_deletion = true } - resource "outscale_flexible_gpu_link" "link_fGPU" { - flexible_gpu_id = outscale_flexible_gpu.fGPU-1.flexible_gpu_id + flexible_gpu_ids = [outscale_flexible_gpu.fGPU-1.flexible_gpu_id,outscale_flexible_gpu.fGPU-2.flexible_gpu_id] vm_id = outscale_vm.basic.vm_id } - `, omi, vmType, region) }