Skip to content

Commit 230a00d

Browse files
committed
Refactor distro pkg
1 parent ef6330f commit 230a00d

File tree

4 files changed

+234
-224
lines changed

4 files changed

+234
-224
lines changed

pkg/distro/centos.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package distro
2+
3+
import (
4+
"github.com/tmrts/flamingo/pkg/sys"
5+
"github.com/tmrts/flamingo/pkg/sys/firewall/iptables"
6+
"github.com/tmrts/flamingo/pkg/sys/identity"
7+
"github.com/tmrts/flamingo/pkg/sys/initd/systemd"
8+
"github.com/tmrts/flamingo/pkg/sys/nss"
9+
)
10+
11+
// CentOS returns the distribution implementation of CentOS
12+
// operating system that uses the given sys.Executor.
13+
func CentOS(exec sys.Executor) ContextConsumer {
14+
return &Implementation{
15+
Executor: exec,
16+
17+
ID: identity.NewManager(exec),
18+
NSS: &nss.Server{exec},
19+
Firewall: &iptables.Implementation{exec},
20+
//FileSystem: &file.System{exec},
21+
//Sysconf: conf.Manager hostname, timedate, etc. sysctl for CentOS
22+
Initd: &systemd.Implementation{
23+
UnitDir: "/etc/systemd/userexec",
24+
Exec: exec,
25+
},
26+
}
27+
}

pkg/distro/context_consumer.go

Lines changed: 37 additions & 209 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,27 @@
11
package distro
22

33
import (
4-
"io"
5-
"io/ioutil"
6-
"os"
7-
"strconv"
8-
"strings"
9-
10-
"github.com/tmrts/flamingo/pkg/context"
114
"github.com/tmrts/flamingo/pkg/datasrc/metadata"
125
"github.com/tmrts/flamingo/pkg/datasrc/userdata"
136
"github.com/tmrts/flamingo/pkg/datasrc/userdata/cloudconfig"
14-
"github.com/tmrts/flamingo/pkg/file"
157
"github.com/tmrts/flamingo/pkg/flog"
168
"github.com/tmrts/flamingo/pkg/sys/identity"
17-
"github.com/tmrts/flamingo/pkg/sys/nss"
18-
"github.com/tmrts/flamingo/pkg/sys/ssh"
9+
"github.com/tmrts/flamingo/pkg/util/strutil"
1910
)
2011

12+
// ContextConsumer is the interface that represents the ability to
13+
// use a metadata.Digest and a userdata.Map for mutating itself.
14+
// The expected implementers of the interface are operating
15+
// system implementations.
2116
type ContextConsumer interface {
2217
ConsumeUserdata(userdata.Map) error
2318
ConsumeMetadata(*metadata.Digest) error
2419
}
2520

26-
// ConsumeScript writes the given contents to a temporary file
27-
// and executes the file.
28-
func (imp *Implementation) ConsumeScript(c string) error {
29-
tempFile := &context.TempFile{
30-
Content: c,
31-
Permissions: 0600,
32-
}
33-
34-
return <-context.Using(tempFile, func(f *os.File) error {
35-
f.Close()
36-
_, err := imp.Execute("sh", f.Name())
37-
38-
return err
39-
})
40-
}
41-
42-
func sTorc(s string) (rc io.ReadCloser) {
43-
return ioutil.NopCloser(strings.NewReader(s))
44-
}
45-
21+
// consumeCloudConfig parses the given cloud config file contents and
22+
// consumes the parsed directives.
4623
func (imp *Implementation) consumeCloudConfig(contents string) error {
47-
conf, err := cloudconfig.Parse(sTorc(contents))
24+
conf, err := cloudconfig.Parse(strutil.ToReadCloser(contents))
4825
if err != nil {
4926
flog.Error("Failed to parse cloud config file",
5027
flog.Fields{
@@ -58,75 +35,13 @@ func (imp *Implementation) consumeCloudConfig(contents string) error {
5835

5936
flog.Debug("Persisting files",
6037
flog.Fields{
61-
Event: "distro.consumeCloudConfig",
38+
Event: "distro.Implementation.consumeCloudConfig",
6239
},
6340
)
6441

65-
for _, f := range conf.Files {
66-
p, err := strconv.Atoi(f.Permissions)
67-
if err != nil {
68-
flog.Error("Failed to convert permissions",
69-
flog.Fields{
70-
Event: "strconv.Atoi",
71-
Error: err,
72-
},
73-
flog.Details{
74-
"file": f.Path,
75-
"permissions": f.Permissions,
76-
},
77-
)
78-
continue
79-
}
80-
81-
perms := os.FileMode(p)
82-
83-
err = file.New(f.Path, file.Permissions(perms), file.Contents(f.Content))
84-
if err != nil {
85-
flog.Error("Failed to create file",
86-
flog.Fields{
87-
Event: "file.New",
88-
Error: err,
89-
},
90-
flog.Details{
91-
"file": f.Path,
92-
},
93-
)
94-
}
95-
}
96-
97-
for _, cmd := range conf.Commands {
98-
flog.Debug("Executing command",
99-
flog.Fields{
100-
Event: "distro.consumeCloudConfig",
101-
},
102-
flog.Details{
103-
"command": cmd,
104-
},
105-
)
106-
107-
out, err := imp.Execute(cmd[0], cmd[1:]...)
108-
if err != nil {
109-
flog.Error("Failed to execute command",
110-
flog.Fields{
111-
Event: "Implementation.Execute",
112-
Error: err,
113-
},
114-
flog.Details{
115-
"command": cmd,
116-
},
117-
)
118-
}
42+
imp.writeFiles(conf.Files)
11943

120-
flog.Debug("Executed command",
121-
flog.Fields{
122-
Event: "identityManager.CreateGroup",
123-
},
124-
flog.Details{
125-
"command": cmd,
126-
"output": out,
127-
},
128-
)
129-
}
44+
imp.consumeCommands(conf.Commands)
13045

13146
for grpName, _ := range conf.Groups {
13247
flog.Info("Creating user group",
@@ -205,42 +120,7 @@ func (imp *Implementation) consumeCloudConfig(contents string) error {
205120
}
206121
}
207122

208-
for userName, sshKeys := range conf.AuthorizedKeys {
209-
flog.Info("Authorizing SSH keys",
210-
flog.Fields{
211-
Event: "distro.consumeCloudConfig",
212-
},
213-
flog.Details{
214-
"user": userName,
215-
},
216-
)
217-
218-
usr, err := nss.GetUser(userName)
219-
if err != nil {
220-
flog.Error("Failed to retrieve user NSS entry",
221-
flog.Fields{
222-
Event: "nss.GetUser",
223-
Error: err,
224-
},
225-
flog.Details{
226-
"user": userName,
227-
},
228-
)
229-
continue
230-
}
231-
232-
if err := ssh.AuthorizeKeysFor(usr, sshKeys); err != nil {
233-
flog.Error("Failed to authorize SSH keys for user",
234-
flog.Fields{
235-
Event: "ssh.AuthorizeKeysFor",
236-
Error: err,
237-
},
238-
flog.Details{
239-
"user": userName,
240-
},
241-
)
242-
}
243-
}
123+
imp.consumeSSHKeys(conf.AuthorizedKeys)
244124

245125
return err
246126
}
@@ -257,15 +137,26 @@ func (imp *Implementation) ConsumeUserdata(u userdata.Map) error {
257137

258138
// TODO(tmrts): Use only scripts with 'startup', 'shutdown', 'user-data'.
259139
scripts := u.Scripts()
140+
flog.Info("Searched for script files",
141+
flog.Fields{
142+
Event: "userdata.Map.Scripts",
143+
},
144+
flog.Details{
145+
"count": len(scripts),
146+
},
147+
)
148+
149+
imp.consumeScripts(scripts)
260150

261151
confs := u.CloudConfigs()
262-
if len(confs) > 1 {
263-
flog.Info("Found multiple cloud-config files",
264-
flog.Fields{
265-
Event: "distro.ConsumeUserdata",
266-
},
267-
)
268-
}
152+
flog.Info("Searched for cloud-config files",
153+
flog.Fields{
154+
Event: "userdata.Map.CloudConfigs",
155+
},
156+
flog.Details{
157+
"count": len(confs),
158+
},
159+
)
269160

270161
for name, content := range confs {
271162
flog.Info("Consuming user-data file",
@@ -294,52 +185,27 @@ func (imp *Implementation) ConsumeUserdata(u userdata.Map) error {
294185
}
295186
}
296187

297-
for name, content := range scripts {
298-
flog.Info("Executing script",
299-
flog.Fields{
300-
Event: "distro.ConsumeUserdata",
301-
},
302-
flog.Details{
303-
"name": name,
304-
},
305-
)
306-
307-
if err := imp.ConsumeScript(content); err != nil {
308-
flog.Error("Failed to execute script",
309-
flog.Fields{
310-
Event: "distro.ConsumeScript",
311-
},
312-
flog.Details{
313-
"name": name,
314-
},
315-
flog.DebugFields{
316-
"content": content,
317-
},
318-
)
319-
}
320-
}
321-
322188
flog.Info("Finished consuming user-data",
323189
flog.Fields{
324-
Event: "distro.ConsumeUserdata",
190+
Event: "distro.Implementation.ConsumeUserdata",
325191
},
326192
)
327193

328194
return nil
329195
}
330196

331-
// ConsumeUserdata uses the given userdata to contextualize the distribution implementation.
197+
// ConsumeMetadata uses the given userdata to contextualize the distribution implementation.
332198
func (imp *Implementation) ConsumeMetadata(m *metadata.Digest) error {
333199
flog.Info("Consuming meta-data",
334200
flog.Fields{
335-
Event: "distro.ConsumeMetadata",
201+
Event: "distro.Implementation.ConsumeMetadata",
336202
},
337203
)
338204

339-
if err := imp.SetHostname(m.Hostname); err != nil {
205+
if err := imp.setHostname(m.Hostname); err != nil {
340206
flog.Error("Failed to set hostname",
341207
flog.Fields{
342-
Event: "distro.SetHostname",
208+
Event: "distro.Implementation.setHostname",
343209
},
344210
flog.Details{
345211
"name": m.Hostname,
@@ -348,49 +214,11 @@ func (imp *Implementation) ConsumeMetadata(m *metadata.Digest) error {
348214
return err
349215
}
350216

351-
for userName, sshKeys := range m.SSHKeys {
352-
flog.Info("Authorizing SSH keys",
353-
flog.Fields{
354-
Event: "distro.consumeMetadata",
355-
},
356-
flog.Details{
357-
"user": userName,
358-
},
359-
)
360-
361-
usr, err := nss.GetUser(userName)
362-
if err != nil {
363-
flog.Error("Failed to retrieve user NSS entry",
364-
flog.Fields{
365-
Event: "nss.GetUser",
366-
Error: err,
367-
},
368-
flog.Details{
369-
"user": userName,
370-
},
371-
)
372-
continue
373-
}
374-
375-
if err := ssh.AuthorizeKeysFor(usr, sshKeys); err != nil {
376-
flog.Error("Failed to authorize SSH keys for user",
377-
flog.Fields{
378-
Event: "ssh.AuthorizeKeysFor",
379-
Error: err,
380-
},
381-
flog.Details{
382-
"user": userName,
383-
},
384-
flog.DebugFields{
385-
"SSHKeys": sshKeys,
386-
},
387-
)
388-
}
389-
}
217+
imp.consumeSSHKeys(m.SSHKeys)
390218

391219
flog.Info("Finished consuming meta-data",
392220
flog.Fields{
393-
Event: "distro.ConsumeUserdata",
221+
Event: "distro.Implementation.ConsumeUserdata",
394222
},
395223
)
396224

pkg/distro/doc.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// Package distro contains the implementations of
2+
// different operating systems to be used for
3+
// contextualizing cloud instances.
4+
package distro

0 commit comments

Comments
 (0)