Skip to content

Commit d1bb2f3

Browse files
committed
helper/schema: support Stop()
1 parent a61b722 commit d1bb2f3

2 files changed

Lines changed: 97 additions & 0 deletions

File tree

‎helper/schema/provider.go‎

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"errors"
55
"fmt"
66
"sort"
7+
"sync"
78

89
"github.com/hashicorp/go-multierror"
910
"github.com/hashicorp/terraform/terraform"
@@ -49,6 +50,10 @@ type Provider struct {
4950
ConfigureFunc ConfigureFunc
5051

5152
meta interface{}
53+
54+
stopCh chan struct{} // stopCh is closed when Stop is called
55+
stopped bool // set to true once stopped to avoid double close of stopCh
56+
stopLock sync.Mutex
5257
}
5358

5459
// ConfigureFunc is the function used to configure a Provider.
@@ -104,6 +109,45 @@ func (p *Provider) SetMeta(v interface{}) {
104109
p.meta = v
105110
}
106111

112+
// Stopped reports whether the provider has been stopped or not.
113+
func (p *Provider) Stopped() bool {
114+
p.stopLock.Lock()
115+
defer p.stopLock.Unlock()
116+
return p.stopped
117+
}
118+
119+
// StopCh returns a channel that is closed once the provider is stopped.
120+
func (p *Provider) StopCh() <-chan struct{} {
121+
p.stopLock.Lock()
122+
defer p.stopLock.Unlock()
123+
124+
if p.stopCh == nil {
125+
p.stopCh = make(chan struct{})
126+
}
127+
128+
return p.stopCh
129+
}
130+
131+
// Stop implementation of terraform.ResourceProvider interface.
132+
func (p *Provider) Stop() error {
133+
p.stopLock.Lock()
134+
defer p.stopLock.Unlock()
135+
136+
// Close the stop channel and mark as stopped if we haven't
137+
if !p.stopped {
138+
// Initialize the stop channel so future calls to StopCh work
139+
if p.stopCh == nil {
140+
p.stopCh = make(chan struct{})
141+
}
142+
143+
// Close and mark
144+
close(p.stopCh)
145+
p.stopped = true
146+
}
147+
148+
return nil
149+
}
150+
107151
// Input implementation of terraform.ResourceProvider interface.
108152
func (p *Provider) Input(
109153
input terraform.UIInput,

‎helper/schema/provider_test.go‎

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"fmt"
55
"reflect"
66
"testing"
7+
"time"
78

89
"github.com/hashicorp/terraform/config"
910
"github.com/hashicorp/terraform/terraform"
@@ -328,3 +329,55 @@ func TestProviderMeta(t *testing.T) {
328329
t.Fatalf("bad: %#v", v)
329330
}
330331
}
332+
333+
func TestProviderStop(t *testing.T) {
334+
var p Provider
335+
336+
if p.Stopped() {
337+
t.Fatal("should not be stopped")
338+
}
339+
340+
// Verify stopch blocks
341+
ch := p.StopCh()
342+
select {
343+
case <-ch:
344+
t.Fatal("should not be stopped")
345+
case <-time.After(10 * time.Millisecond):
346+
}
347+
348+
// Stop it
349+
if err := p.Stop(); err != nil {
350+
t.Fatalf("err: %s", err)
351+
}
352+
353+
// Verify
354+
if !p.Stopped() {
355+
t.Fatal("should be stopped")
356+
}
357+
358+
select {
359+
case <-ch:
360+
case <-time.After(10 * time.Millisecond):
361+
t.Fatal("should be stopped")
362+
}
363+
}
364+
365+
func TestProviderStop_stopFirst(t *testing.T) {
366+
var p Provider
367+
368+
// Stop it
369+
if err := p.Stop(); err != nil {
370+
t.Fatalf("err: %s", err)
371+
}
372+
373+
// Verify
374+
if !p.Stopped() {
375+
t.Fatal("should be stopped")
376+
}
377+
378+
select {
379+
case <-p.StopCh():
380+
case <-time.After(10 * time.Millisecond):
381+
t.Fatal("should be stopped")
382+
}
383+
}

0 commit comments

Comments
 (0)