forked from cloudfoundry/bosh-bootloader
/
infrastructure_manager.go
128 lines (100 loc) · 3.43 KB
/
infrastructure_manager.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
package cloudformation
import (
"fmt"
"strings"
"time"
"github.com/cloudfoundry/bosh-bootloader/aws/cloudformation/templates"
)
const bblTagKey = "bbl-env-id"
type templateBuilder interface {
Build(keypairName string, azs []string, lbType string, lbCertificateARN string, iamUserName string, envID string, boshAZ string) templates.Template
}
type stackManager interface {
CreateOrUpdate(stackName string, template templates.Template, tags Tags) error
Update(stackName string, template templates.Template, tags Tags) error
WaitForCompletion(stackName string, sleepInterval time.Duration, action string) error
Describe(stackName string) (Stack, error)
Delete(stackName string) error
GetPhysicalIDForResource(stackName string, logicalResourceID string) (string, error)
}
type InfrastructureManager struct {
templateBuilder templateBuilder
stackManager stackManager
}
func NewInfrastructureManager(builder templateBuilder, stackManager stackManager) InfrastructureManager {
return InfrastructureManager{
templateBuilder: builder,
stackManager: stackManager,
}
}
func (m InfrastructureManager) Create(keyPairName string, azs []string, stackName, boshAZ,
lbType, lbCertificateARN, envID string) (Stack, error) {
iamUserName := generateIAMUserName(envID)
stackExists, err := m.Exists(stackName)
if err != nil {
return Stack{}, err
}
if stackExists {
iamUserName, err = m.stackManager.GetPhysicalIDForResource(stackName, "BOSHUser")
if err != nil {
return Stack{}, err
}
}
template := m.templateBuilder.Build(keyPairName, azs, lbType, lbCertificateARN, iamUserName, envID, boshAZ)
tags := Tags{
{
Key: bblTagKey,
Value: envID,
},
}
if err := m.stackManager.CreateOrUpdate(stackName, template, tags); err != nil {
return Stack{}, err
}
if err := m.stackManager.WaitForCompletion(stackName, 15*time.Second, "applying cloudformation template"); err != nil {
return Stack{}, err
}
return m.stackManager.Describe(stackName)
}
func (m InfrastructureManager) Update(keyPairName string, azs []string, stackName, boshAZ, lbType,
lbCertificateARN, envID string) (Stack, error) {
iamUserName, err := m.stackManager.GetPhysicalIDForResource(stackName, "BOSHUser")
if err != nil {
return Stack{}, err
}
template := m.templateBuilder.Build(keyPairName, azs, lbType, lbCertificateARN, iamUserName, envID, boshAZ)
if err := m.stackManager.Update(stackName, template, Tags{{Key: bblTagKey, Value: envID}}); err != nil {
return Stack{}, err
}
if err := m.stackManager.WaitForCompletion(stackName, 15*time.Second, "applying cloudformation template"); err != nil {
return Stack{}, err
}
return m.stackManager.Describe(stackName)
}
func (m InfrastructureManager) Exists(stackName string) (bool, error) {
_, err := m.stackManager.Describe(stackName)
switch err {
case nil:
return true, nil
case StackNotFound:
return false, nil
default:
return false, err
}
}
func (m InfrastructureManager) Describe(stackName string) (Stack, error) {
return m.stackManager.Describe(stackName)
}
func (m InfrastructureManager) Delete(stackName string) error {
err := m.stackManager.Delete(stackName)
if err != nil {
return err
}
err = m.stackManager.WaitForCompletion(stackName, 15*time.Second, "deleting cloudformation stack")
if err != nil && err != StackNotFound {
return err
}
return nil
}
func generateIAMUserName(envID string) string {
return fmt.Sprintf("bosh-iam-user-%s", strings.Replace(envID, ":", "-", -1))
}