This repository has been archived by the owner on Jul 6, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 100
/
deprovisioner.go
118 lines (105 loc) · 2.95 KB
/
deprovisioner.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
package service
import (
"context"
"fmt"
)
// DeprovisioningStepFunction is the signature for functions that implement a
// deprovisioning step
type DeprovisioningStepFunction func(
ctx context.Context,
instance Instance,
) (InstanceDetails, error)
// DeprovisioningStep is an interface to be implemented by types that represent
// a single step in a chain of steps that defines a deprovisioning process
type DeprovisioningStep interface {
GetName() string
Execute(
ctx context.Context,
instance Instance,
) (InstanceDetails, error)
}
type deprovisioningStep struct {
name string
fn DeprovisioningStepFunction
}
// Deprovisioner is an interface to be implemented by types that model a
// declared chain of tasks used to asynchronously deprovision a service
type Deprovisioner interface {
GetFirstStepName() (string, bool)
GetStep(name string) (DeprovisioningStep, bool)
GetNextStepName(name string) (string, bool)
}
type deprovisioner struct {
firstStepName string
steps map[string]DeprovisioningStep
nextSteps map[string]string
}
// NewDeprovisioningStep returns a new DeprovisioningStep
func NewDeprovisioningStep(
name string,
fn DeprovisioningStepFunction,
) DeprovisioningStep {
return &deprovisioningStep{
name: name,
fn: fn,
}
}
// GetName returns a deprovisioning step's name
func (d *deprovisioningStep) GetName() string {
return d.name
}
// Execute executes a step
func (d *deprovisioningStep) Execute(
ctx context.Context,
instance Instance,
) (InstanceDetails, error) {
ctx, cancel := context.WithCancel(ctx)
defer cancel()
return d.fn(
ctx,
instance,
)
}
// NewDeprovisioner returns a new deprovisioner
func NewDeprovisioner(steps ...DeprovisioningStep) (Deprovisioner, error) {
d := &deprovisioner{
steps: make(map[string]DeprovisioningStep),
nextSteps: make(map[string]string),
}
if len(steps) > 0 {
d.firstStepName = steps[0].GetName()
var lastStep DeprovisioningStep
for _, step := range steps {
_, ok := d.steps[step.GetName()]
if ok {
// This means a duplicate step name has been detected. This is a serious
// problem.
return nil, fmt.Errorf(
`duplicate step name "%s" detected`,
step.GetName(),
)
}
d.steps[step.GetName()] = step
if lastStep != nil {
d.nextSteps[lastStep.GetName()] = step.GetName()
}
lastStep = step
}
}
return d, nil
}
// GetFirstStepName retrieves the name of the first step in the chain
func (d *deprovisioner) GetFirstStepName() (string, bool) {
return d.firstStepName, (d.firstStepName != "")
}
// GetStep retrieves a step by name
func (d *deprovisioner) GetStep(name string) (DeprovisioningStep, bool) {
step, ok := d.steps[name]
return step, ok
}
// GetNextStepName, given the name of one step, returns the name of the next
// step and a boolean indicating whether a next step actually exists
func (d *deprovisioner) GetNextStepName(name string) (string, bool) {
nextStepName, ok := d.nextSteps[name]
return nextStepName, ok
}