forked from cloudfoundry/bosh-bootloader
-
Notifications
You must be signed in to change notification settings - Fork 0
/
manager.go
150 lines (123 loc) · 3.56 KB
/
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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
package cloudconfig
import (
"bytes"
"fmt"
"io"
"io/ioutil"
"os"
"path/filepath"
"golang.org/x/net/proxy"
"github.com/cloudfoundry/bosh-bootloader/bosh"
"github.com/cloudfoundry/bosh-bootloader/storage"
)
var (
tempDir func(string, string) (string, error) = ioutil.TempDir
writeFile func(string, []byte, os.FileMode) error = ioutil.WriteFile
proxySOCKS5 func(string, string, *proxy.Auth, proxy.Dialer) (proxy.Dialer, error) = proxy.SOCKS5
)
type Manager struct {
logger logger
command command
opsGenerator opsGenerator
boshClientProvider boshClientProvider
socks5Proxy socks5Proxy
terraformManager terraformManager
sshKeyGetter sshKeyGetter
}
type logger interface {
Step(string, ...interface{})
}
type command interface {
Run(stdout io.Writer, workingDirectory string, args []string) error
}
type opsGenerator interface {
Generate(state storage.State) (string, error)
}
type boshClientProvider interface {
Client(directorAddress, directorUsername, directorPassword string) bosh.Client
}
type socks5Proxy interface {
Start(string, string) error
Addr() string
}
type terraformManager interface {
GetOutputs(storage.State) (map[string]interface{}, error)
}
type sshKeyGetter interface {
Get(storage.State) (string, error)
}
func NewManager(logger logger, cmd command, opsGenerator opsGenerator, boshClientProvider boshClientProvider,
socks5Proxy socks5Proxy, terraformManager terraformManager, sshKeyGetter sshKeyGetter) Manager {
return Manager{
logger: logger,
command: cmd,
opsGenerator: opsGenerator,
boshClientProvider: boshClientProvider,
socks5Proxy: socks5Proxy,
terraformManager: terraformManager,
sshKeyGetter: sshKeyGetter,
}
}
func (m Manager) Generate(state storage.State) (string, error) {
buf := bytes.NewBuffer([]byte{})
workingDir, err := tempDir("", "")
if err != nil {
return "", err
}
err = writeFile(filepath.Join(workingDir, "cloud-config.yml"), []byte(BaseCloudConfig), os.ModePerm)
if err != nil {
return "", err
}
ops, err := m.opsGenerator.Generate(state)
if err != nil {
return "", err
}
err = writeFile(filepath.Join(workingDir, "ops.yml"), []byte(ops), os.ModePerm)
if err != nil {
return "", err
}
args := []string{
"interpolate", fmt.Sprintf("%s/cloud-config.yml", workingDir),
"-o", fmt.Sprintf("%s/ops.yml", workingDir),
}
err = m.command.Run(buf, workingDir, args)
if err != nil {
return "", err
}
return buf.String(), nil
}
func (m Manager) Update(state storage.State) error {
boshClient := m.boshClientProvider.Client(state.BOSH.DirectorAddress, state.BOSH.DirectorUsername, state.BOSH.DirectorPassword)
if state.Jumpbox.Enabled {
privateKey, err := m.sshKeyGetter.Get(state)
if err != nil {
return err
}
terraformOutputs, err := m.terraformManager.GetOutputs(state)
if err != nil {
return err
}
jumpboxURL := fmt.Sprintf("%s:%d", terraformOutputs["external_ip"], 22)
m.logger.Step("starting socks5 proxy")
err = m.socks5Proxy.Start(privateKey, jumpboxURL)
if err != nil {
return err
}
socks5Client, err := proxySOCKS5("tcp", m.socks5Proxy.Addr(), nil, proxy.Direct)
if err != nil {
return err
}
boshClient.ConfigureHTTPClient(socks5Client)
}
m.logger.Step("generating cloud config")
cloudConfig, err := m.Generate(state)
if err != nil {
return err
}
m.logger.Step("applying cloud config")
err = boshClient.UpdateCloudConfig([]byte(cloudConfig))
if err != nil {
return err
}
return nil
}