From 403ea9f6d7e8a97389be7f9d008503cabb5564f1 Mon Sep 17 00:00:00 2001 From: Raphael Randschau Date: Mon, 27 Mar 2017 12:00:11 +0200 Subject: [PATCH] provider/scaleway: work around parallel request limitation (#13045) according to the official scaleway support, requests within the same session can not be parallelized. While I do not know for sure that this is a write-only limitation, I've implemented it as a write-only limitation for now. Previously requests like this would produce a 500 internal server error: ``` resource "scaleway_ip" "test_ip" { count = 2 } ``` now this limitation should be lifted, for all scaleway resources --- builtin/providers/scaleway/provider.go | 4 ++++ builtin/providers/scaleway/resource_scaleway_ip.go | 14 ++++++++++---- .../scaleway/resource_scaleway_security_group.go | 9 +++++++++ .../resource_scaleway_security_group_rule.go | 9 +++++++++ .../providers/scaleway/resource_scaleway_server.go | 10 +++++++++- .../providers/scaleway/resource_scaleway_volume.go | 11 +++++++++++ .../resource_scaleway_volume_attachment.go | 7 +++++++ 7 files changed, 59 insertions(+), 5 deletions(-) diff --git a/builtin/providers/scaleway/provider.go b/builtin/providers/scaleway/provider.go index c05d6e977..16069fe21 100644 --- a/builtin/providers/scaleway/provider.go +++ b/builtin/providers/scaleway/provider.go @@ -1,11 +1,15 @@ package scaleway import ( + "sync" + "github.com/hashicorp/terraform/helper/mutexkv" "github.com/hashicorp/terraform/helper/schema" "github.com/hashicorp/terraform/terraform" ) +var mu = sync.Mutex{} + // Provider returns a terraform.ResourceProvider. func Provider() terraform.ResourceProvider { return &schema.Provider{ diff --git a/builtin/providers/scaleway/resource_scaleway_ip.go b/builtin/providers/scaleway/resource_scaleway_ip.go index 27cb6fb47..f388fe4e2 100644 --- a/builtin/providers/scaleway/resource_scaleway_ip.go +++ b/builtin/providers/scaleway/resource_scaleway_ip.go @@ -2,7 +2,6 @@ package scaleway import ( "log" - "sync" "github.com/hashicorp/terraform/helper/schema" "github.com/scaleway/scaleway-cli/pkg/api" @@ -31,13 +30,12 @@ func resourceScalewayIP() *schema.Resource { } } -var mu = sync.Mutex{} - func resourceScalewayIPCreate(d *schema.ResourceData, m interface{}) error { scaleway := m.(*Client).scaleway + mu.Lock() - defer mu.Unlock() resp, err := scaleway.NewIP() + mu.Unlock() if err != nil { return err } @@ -71,6 +69,10 @@ func resourceScalewayIPRead(d *schema.ResourceData, m interface{}) error { func resourceScalewayIPUpdate(d *schema.ResourceData, m interface{}) error { scaleway := m.(*Client).scaleway + + mu.Lock() + defer mu.Unlock() + if d.HasChange("server") { if d.Get("server").(string) != "" { log.Printf("[DEBUG] Attaching IP %q to server %q\n", d.Id(), d.Get("server").(string)) @@ -88,6 +90,10 @@ func resourceScalewayIPUpdate(d *schema.ResourceData, m interface{}) error { func resourceScalewayIPDelete(d *schema.ResourceData, m interface{}) error { scaleway := m.(*Client).scaleway + + mu.Lock() + defer mu.Unlock() + err := scaleway.DeleteIP(d.Id()) if err != nil { return err diff --git a/builtin/providers/scaleway/resource_scaleway_security_group.go b/builtin/providers/scaleway/resource_scaleway_security_group.go index e30c08620..e2c44b676 100644 --- a/builtin/providers/scaleway/resource_scaleway_security_group.go +++ b/builtin/providers/scaleway/resource_scaleway_security_group.go @@ -34,6 +34,9 @@ func resourceScalewaySecurityGroup() *schema.Resource { func resourceScalewaySecurityGroupCreate(d *schema.ResourceData, m interface{}) error { scaleway := m.(*Client).scaleway + mu.Lock() + defer mu.Unlock() + req := api.ScalewayNewSecurityGroup{ Name: d.Get("name").(string), Description: d.Get("description").(string), @@ -94,6 +97,9 @@ func resourceScalewaySecurityGroupRead(d *schema.ResourceData, m interface{}) er func resourceScalewaySecurityGroupUpdate(d *schema.ResourceData, m interface{}) error { scaleway := m.(*Client).scaleway + mu.Lock() + defer mu.Unlock() + var req = api.ScalewayUpdateSecurityGroup{ Organization: scaleway.Organization, Name: d.Get("name").(string), @@ -112,6 +118,9 @@ func resourceScalewaySecurityGroupUpdate(d *schema.ResourceData, m interface{}) func resourceScalewaySecurityGroupDelete(d *schema.ResourceData, m interface{}) error { scaleway := m.(*Client).scaleway + mu.Lock() + defer mu.Unlock() + err := scaleway.DeleteSecurityGroup(d.Id()) if err != nil { if serr, ok := err.(api.ScalewayAPIError); ok { diff --git a/builtin/providers/scaleway/resource_scaleway_security_group_rule.go b/builtin/providers/scaleway/resource_scaleway_security_group_rule.go index 03d29a95f..4359052b5 100644 --- a/builtin/providers/scaleway/resource_scaleway_security_group_rule.go +++ b/builtin/providers/scaleway/resource_scaleway_security_group_rule.go @@ -67,6 +67,9 @@ func resourceScalewaySecurityGroupRule() *schema.Resource { func resourceScalewaySecurityGroupRuleCreate(d *schema.ResourceData, m interface{}) error { scaleway := m.(*Client).scaleway + mu.Lock() + defer mu.Unlock() + req := api.ScalewayNewSecurityGroupRule{ Action: d.Get("action").(string), Direction: d.Get("direction").(string), @@ -140,6 +143,9 @@ func resourceScalewaySecurityGroupRuleRead(d *schema.ResourceData, m interface{} func resourceScalewaySecurityGroupRuleUpdate(d *schema.ResourceData, m interface{}) error { scaleway := m.(*Client).scaleway + mu.Lock() + defer mu.Unlock() + var req = api.ScalewayNewSecurityGroupRule{ Action: d.Get("action").(string), Direction: d.Get("direction").(string), @@ -160,6 +166,9 @@ func resourceScalewaySecurityGroupRuleUpdate(d *schema.ResourceData, m interface func resourceScalewaySecurityGroupRuleDelete(d *schema.ResourceData, m interface{}) error { scaleway := m.(*Client).scaleway + mu.Lock() + defer mu.Unlock() + err := scaleway.DeleteSecurityGroupRule(d.Get("security_group").(string), d.Id()) if err != nil { if serr, ok := err.(api.ScalewayAPIError); ok { diff --git a/builtin/providers/scaleway/resource_scaleway_server.go b/builtin/providers/scaleway/resource_scaleway_server.go index 57183c152..1d27c76ea 100644 --- a/builtin/providers/scaleway/resource_scaleway_server.go +++ b/builtin/providers/scaleway/resource_scaleway_server.go @@ -108,6 +108,9 @@ func resourceScalewayServer() *schema.Resource { func resourceScalewayServerCreate(d *schema.ResourceData, m interface{}) error { scaleway := m.(*Client).scaleway + mu.Lock() + defer mu.Unlock() + image := d.Get("image").(string) var server = api.ScalewayServerDefinition{ Name: d.Get("name").(string), @@ -217,8 +220,10 @@ func resourceScalewayServerRead(d *schema.ResourceData, m interface{}) error { func resourceScalewayServerUpdate(d *schema.ResourceData, m interface{}) error { scaleway := m.(*Client).scaleway - var req api.ScalewayServerPatchDefinition + mu.Lock() + defer mu.Unlock() + var req api.ScalewayServerPatchDefinition if d.HasChange("name") { name := d.Get("name").(string) req.Name = &name @@ -258,6 +263,9 @@ func resourceScalewayServerUpdate(d *schema.ResourceData, m interface{}) error { func resourceScalewayServerDelete(d *schema.ResourceData, m interface{}) error { scaleway := m.(*Client).scaleway + mu.Lock() + defer mu.Unlock() + s, err := scaleway.GetServer(d.Id()) if err != nil { return err diff --git a/builtin/providers/scaleway/resource_scaleway_volume.go b/builtin/providers/scaleway/resource_scaleway_volume.go index 6f72ff59a..e36cf15c9 100644 --- a/builtin/providers/scaleway/resource_scaleway_volume.go +++ b/builtin/providers/scaleway/resource_scaleway_volume.go @@ -45,6 +45,10 @@ func resourceScalewayVolume() *schema.Resource { func resourceScalewayVolumeCreate(d *schema.ResourceData, m interface{}) error { scaleway := m.(*Client).scaleway + + mu.Lock() + defer mu.Unlock() + size := uint64(d.Get("size_in_gb").(int)) * gb req := api.ScalewayVolumeDefinition{ Name: d.Get("name").(string), @@ -88,6 +92,9 @@ func resourceScalewayVolumeRead(d *schema.ResourceData, m interface{}) error { func resourceScalewayVolumeUpdate(d *schema.ResourceData, m interface{}) error { scaleway := m.(*Client).scaleway + mu.Lock() + defer mu.Unlock() + var req api.ScalewayVolumePutDefinition if d.HasChange("name") { req.Name = String(d.Get("name").(string)) @@ -104,6 +111,10 @@ func resourceScalewayVolumeUpdate(d *schema.ResourceData, m interface{}) error { func resourceScalewayVolumeDelete(d *schema.ResourceData, m interface{}) error { scaleway := m.(*Client).scaleway + + mu.Lock() + defer mu.Unlock() + err := scaleway.DeleteVolume(d.Id()) if err != nil { if serr, ok := err.(api.ScalewayAPIError); ok { diff --git a/builtin/providers/scaleway/resource_scaleway_volume_attachment.go b/builtin/providers/scaleway/resource_scaleway_volume_attachment.go index 518b4acfe..532586c66 100644 --- a/builtin/providers/scaleway/resource_scaleway_volume_attachment.go +++ b/builtin/providers/scaleway/resource_scaleway_volume_attachment.go @@ -95,7 +95,9 @@ func resourceScalewayVolumeAttachmentCreate(d *schema.ResourceData, m interface{ var req = api.ScalewayServerPatchDefinition{ Volumes: &volumes, } + mu.Lock() err := scaleway.PatchServer(serverID, req) + mu.Unlock() if err == nil { return nil @@ -172,6 +174,9 @@ func resourceScalewayVolumeAttachmentDelete(d *schema.ResourceData, m interface{ scaleway := m.(*Client).scaleway scaleway.ClearCache() + mu.Lock() + defer mu.Unlock() + var startServerAgain = false // guard against server shutdown/ startup race conditiond @@ -221,7 +226,9 @@ func resourceScalewayVolumeAttachmentDelete(d *schema.ResourceData, m interface{ var req = api.ScalewayServerPatchDefinition{ Volumes: &volumes, } + mu.Lock() err := scaleway.PatchServer(serverID, req) + mu.Unlock() if err == nil { return nil