From 86eb30b8a220639917ca9e867fa80fd8bc60a4a8 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Tue, 25 Oct 2016 11:29:24 -0700 Subject: [PATCH] helper/schema: expose stop information as a Context --- builtin/providers/azurerm/config.go | 9 +--- builtin/providers/azurerm/provider.go | 2 +- .../azurerm/resource_arm_storage_account.go | 6 +-- helper/schema/provider.go | 48 ++++++++----------- helper/schema/provider_test.go | 4 +- 5 files changed, 27 insertions(+), 42 deletions(-) diff --git a/builtin/providers/azurerm/config.go b/builtin/providers/azurerm/config.go index 460355604..3638c6a51 100644 --- a/builtin/providers/azurerm/config.go +++ b/builtin/providers/azurerm/config.go @@ -1,11 +1,11 @@ package azurerm import ( + "context" "fmt" "log" "net/http" "net/http/httputil" - "time" "github.com/Azure/azure-sdk-for-go/arm/cdn" "github.com/Azure/azure-sdk-for-go/arm/compute" @@ -20,7 +20,6 @@ import ( mainStorage "github.com/Azure/azure-sdk-for-go/storage" "github.com/Azure/go-autorest/autorest" "github.com/Azure/go-autorest/autorest/azure" - "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/terraform" riviera "github.com/jen20/riviera/azure" ) @@ -32,7 +31,7 @@ type ArmClient struct { tenantId string subscriptionId string - stopCh <-chan struct{} // From the provider + StopContext context.Context rivieraClient *riviera.Client @@ -489,7 +488,3 @@ func (armClient *ArmClient) getQueueServiceClientForStorageAccount(resourceGroup queueClient := storageClient.GetQueueService() return &queueClient, true, nil } - -func (armClient *ArmClient) CancelCh(max time.Duration) (<-chan struct{}, chan<- struct{}) { - return resource.StopCh(armClient.stopCh, max) -} diff --git a/builtin/providers/azurerm/provider.go b/builtin/providers/azurerm/provider.go index 5415fb985..12fd48f45 100644 --- a/builtin/providers/azurerm/provider.go +++ b/builtin/providers/azurerm/provider.go @@ -161,7 +161,7 @@ func providerConfigure(p *schema.Provider) schema.ConfigureFunc { return nil, err } - client.stopCh = p.StopCh() + client.StopContext = p.StopContext() err = registerAzureResourceProvidersWithSubscription(client.rivieraClient) if err != nil { diff --git a/builtin/providers/azurerm/resource_arm_storage_account.go b/builtin/providers/azurerm/resource_arm_storage_account.go index 9ce8aae5f..7e196980b 100644 --- a/builtin/providers/azurerm/resource_arm_storage_account.go +++ b/builtin/providers/azurerm/resource_arm_storage_account.go @@ -1,6 +1,7 @@ package azurerm import ( + "context" "fmt" "log" "net/http" @@ -192,10 +193,9 @@ func resourceArmStorageAccountCreate(d *schema.ResourceData, meta interface{}) e } // Create - cancelCh, doneCh := client.CancelCh(1 * time.Hour) + cancelCtx, _ := context.WithTimeout(client.StopContext, 1*time.Hour) _, createErr := storageClient.Create( - resourceGroupName, storageAccountName, opts, cancelCh) - close(doneCh) + resourceGroupName, storageAccountName, opts, cancelCtx.Done()) // The only way to get the ID back apparently is to read the resource again read, err := storageClient.GetProperties(resourceGroupName, storageAccountName) diff --git a/helper/schema/provider.go b/helper/schema/provider.go index 636ea5518..5b50d54a1 100644 --- a/helper/schema/provider.go +++ b/helper/schema/provider.go @@ -1,6 +1,7 @@ package schema import ( + "context" "errors" "fmt" "sort" @@ -51,9 +52,9 @@ type Provider struct { meta interface{} - stopCh chan struct{} // stopCh is closed when Stop is called - stopped bool // set to true once stopped to avoid double close of stopCh - stopLock sync.Mutex + stopCtx context.Context + stopCtxCancel context.CancelFunc + stopOnce sync.Once } // ConfigureFunc is the function used to configure a Provider. @@ -111,40 +112,29 @@ func (p *Provider) SetMeta(v interface{}) { // Stopped reports whether the provider has been stopped or not. func (p *Provider) Stopped() bool { - p.stopLock.Lock() - defer p.stopLock.Unlock() - return p.stopped + ctx := p.StopContext() + select { + case <-ctx.Done(): + return true + default: + return false + } } // StopCh returns a channel that is closed once the provider is stopped. -func (p *Provider) StopCh() <-chan struct{} { - p.stopLock.Lock() - defer p.stopLock.Unlock() +func (p *Provider) StopContext() context.Context { + p.stopOnce.Do(p.stopInit) + return p.stopCtx +} - if p.stopCh == nil { - p.stopCh = make(chan struct{}) - } - - return p.stopCh +func (p *Provider) stopInit() { + p.stopCtx, p.stopCtxCancel = context.WithCancel(context.Background()) } // Stop implementation of terraform.ResourceProvider interface. func (p *Provider) Stop() error { - p.stopLock.Lock() - defer p.stopLock.Unlock() - - // Close the stop channel and mark as stopped if we haven't - if !p.stopped { - // Initialize the stop channel so future calls to StopCh work - if p.stopCh == nil { - p.stopCh = make(chan struct{}) - } - - // Close and mark - close(p.stopCh) - p.stopped = true - } - + p.stopOnce.Do(p.stopInit) + p.stopCtxCancel() return nil } diff --git a/helper/schema/provider_test.go b/helper/schema/provider_test.go index cde72d86b..ed5918844 100644 --- a/helper/schema/provider_test.go +++ b/helper/schema/provider_test.go @@ -338,7 +338,7 @@ func TestProviderStop(t *testing.T) { } // Verify stopch blocks - ch := p.StopCh() + ch := p.StopContext().Done() select { case <-ch: t.Fatal("should not be stopped") @@ -376,7 +376,7 @@ func TestProviderStop_stopFirst(t *testing.T) { } select { - case <-p.StopCh(): + case <-p.StopContext().Done(): case <-time.After(10 * time.Millisecond): t.Fatal("should be stopped") }