/
deprovision.go
130 lines (108 loc) · 3.99 KB
/
deprovision.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
119
120
121
122
123
124
125
126
127
128
129
130
package broker
import (
"context"
"sync"
"github.com/kyma-project/kyma/components/remote-environment-broker/internal"
"github.com/pkg/errors"
"github.com/pmorie/go-open-service-broker-client/v2"
osb "github.com/pmorie/go-open-service-broker-client/v2"
"github.com/sirupsen/logrus"
)
// NewDeprovisioner creates new Deprovisioner
func NewDeprovisioner(instStorage instanceStorage, instanceStateGetter instanceStateGetter, operationInserter operationInserter, operationUpdater operationUpdater, opIDProvider func() (internal.OperationID, error), log logrus.FieldLogger) *DeprovisionService {
return &DeprovisionService{
instStorage: instStorage,
instanceStateGetter: instanceStateGetter,
operationInserter: operationInserter,
operationUpdater: operationUpdater,
operationIDProvider: opIDProvider,
log: log.WithField("service", "deprovisioner"),
}
}
// DeprovisionService performs deprovision action
type DeprovisionService struct {
instStorage instanceStorage
instanceStateGetter instanceStateGetter
operationIDProvider func() (internal.OperationID, error)
operationInserter operationInserter
operationUpdater operationUpdater
log logrus.FieldLogger
mu sync.Mutex
asyncHook func()
}
// Deprovision action
func (svc *DeprovisionService) Deprovision(ctx context.Context, osbCtx osbContext, req *v2.DeprovisionRequest) (*v2.DeprovisionResponse, error) {
if !req.AcceptsIncomplete {
return nil, errors.New("asynchronous operation mode required")
}
svc.mu.Lock()
defer svc.mu.Unlock()
iID := internal.InstanceID(req.InstanceID)
deprovisioned, err := svc.instanceStateGetter.IsDeprovisioned(iID)
switch {
case IsNotFoundError(err):
return nil, err
case err != nil:
return nil, errors.Wrap(err, "while checking if instance is already deprovisioned")
case deprovisioned:
return &osb.DeprovisionResponse{Async: false}, nil
}
opIDInProgress, inProgress, err := svc.instanceStateGetter.IsDeprovisioningInProgress(iID)
switch {
case IsNotFoundError(err):
return nil, err
case err != nil:
return nil, errors.Wrap(err, "while checking if instance is being deprovisioned")
case inProgress:
opKeyInProgress := osb.OperationKey(opIDInProgress)
return &osb.DeprovisionResponse{Async: true, OperationKey: &opKeyInProgress}, nil
}
operationID, err := svc.operationIDProvider()
if err != nil {
return nil, errors.Wrap(err, "while generating ID for operation")
}
iNs, err := svc.instStorage.Get(iID)
if err != nil {
return nil, errors.Wrap(err, "while getting instance from storage")
}
paramHash := "TODO"
op := internal.InstanceOperation{
InstanceID: iID,
OperationID: operationID,
Type: internal.OperationTypeRemove,
State: internal.OperationStateInProgress,
ParamsHash: paramHash,
}
if err := svc.operationInserter.Insert(&op); err != nil {
return nil, errors.Wrap(err, "while inserting instance operation to storage")
}
err = svc.instStorage.Remove(iID)
switch {
case IsNotFoundError(err):
return nil, err
case err != nil:
return nil, errors.Wrap(err, "while removing instance from storage")
}
opKey := osb.OperationKey(operationID)
resp := &osb.DeprovisionResponse{
Async: true,
OperationKey: &opKey,
}
svc.doAsync(iID, operationID, req.ServiceID, iNs.Namespace)
return resp, nil
}
func (svc *DeprovisionService) doAsync(iID internal.InstanceID, opID internal.OperationID, reID string, ns internal.Namespace) {
go svc.do(iID, opID, reID, ns)
}
func (svc *DeprovisionService) do(iID internal.InstanceID, opID internal.OperationID, reID string, ns internal.Namespace) {
if svc.asyncHook != nil {
defer svc.asyncHook()
}
opState := internal.OperationStateSucceeded
opDesc := "deprovision succeeded"
// currently, there is no any action, but it is a place for future - any deprovisioning action should be put here
if err := svc.operationUpdater.UpdateStateDesc(iID, opID, opState, &opDesc); err != nil {
svc.log.Errorf("Cannot update state for instance [%s]: [%v]\n", iID, err)
return
}
}