Skip to content

Commit 13ef333

Browse files
committed
Support plain user data
1 parent dbc9790 commit 13ef333

File tree

8 files changed

+198
-69
lines changed

8 files changed

+198
-69
lines changed

Config.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
)
6+
7+
var providers = map[string]DataProvider{
8+
"aws": NewDefaultAwsProvider(),
9+
}
10+
11+
type Config struct {
12+
outputDir string
13+
providerKey string
14+
args []string
15+
}
16+
17+
func (config Config) getProvider() (DataProvider, error) {
18+
if config.providerKey == "" {
19+
input := config.args[0]
20+
return CommandLineProvider{Input: input}, nil
21+
} else {
22+
var ok bool
23+
provider, ok := providers[config.providerKey]
24+
if !ok {
25+
return nil, fmt.Errorf("unknown provider: %s", config.providerKey)
26+
}
27+
return provider, nil
28+
}
29+
}

Config_test.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package main
2+
3+
import (
4+
"github.com/stretchr/testify/assert"
5+
"testing"
6+
)
7+
8+
func TestHandlesUnknownProvider(t *testing.T) {
9+
_, err := Config{providerKey: "talula"}.getProvider()
10+
assert.ErrorContains(t, err, "unknown provider")
11+
}

InputProcessor.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"os"
6+
"path"
7+
"path/filepath"
8+
)
9+
10+
type InputProcessor struct {
11+
config Config
12+
}
13+
14+
func (inputProcessor InputProcessor) writePlainUserDataFile(input DataOutputPair) error {
15+
outputPath := filepath.Join(inputProcessor.config.outputDir, input.OutputDir)
16+
fullPath := filepath.Join(outputPath, "userdata")
17+
err := os.MkdirAll(path.Dir(fullPath), 0755)
18+
19+
if err != nil {
20+
return fmt.Errorf("error creating output directories: %w", err)
21+
}
22+
err = os.WriteFile(fullPath, input.Data, 0755)
23+
if err != nil {
24+
return fmt.Errorf("errir writing file: %w", err)
25+
}
26+
return nil
27+
}
28+
29+
func (inputProcessor InputProcessor) Process(inputs []DataOutputPair) error {
30+
for _, input := range inputs {
31+
decoded, err := decode(input.Data)
32+
33+
if err != nil {
34+
return inputProcessor.writePlainUserDataFile(input)
35+
} else {
36+
attachments, err := ExtractMimeAttachmentsFromBytes(decoded)
37+
if err != nil {
38+
return inputProcessor.writePlainUserDataFile(input)
39+
} else {
40+
outputPath := filepath.Join(inputProcessor.config.outputDir, input.OutputDir)
41+
42+
err = ExtractCloudConfig(attachments, outputPath)
43+
if err != nil {
44+
return fmt.Errorf("failed to save write files: %w", err)
45+
}
46+
}
47+
}
48+
}
49+
50+
return nil
51+
}

InputProcessor_test.go

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package main
2+
3+
import (
4+
"os"
5+
"path/filepath"
6+
"testing"
7+
8+
"github.com/stretchr/testify/assert"
9+
)
10+
11+
func TestWritePlainUserDataFileWhenNotBase64Encoded(t *testing.T) {
12+
tempDir, _ := os.MkdirTemp("", "test")
13+
defer os.RemoveAll(tempDir)
14+
15+
config := Config{outputDir: tempDir}
16+
inputProcessor := InputProcessor{config: config}
17+
18+
dataOutputPair := DataOutputPair{
19+
Data: []byte("some data"),
20+
OutputDir: "some_output_dir",
21+
}
22+
23+
err := inputProcessor.writePlainUserDataFile(dataOutputPair)
24+
25+
assert.Nil(t, err)
26+
27+
expectedFilePath := filepath.Join(tempDir, "some_output_dir", "userdata")
28+
_, err = os.Stat(expectedFilePath)
29+
assert.False(t, os.IsNotExist(err))
30+
}
31+
32+
func TestWritePlainUserDataFileWhenNotMime(t *testing.T) {
33+
tempDir, _ := os.MkdirTemp("", "test")
34+
defer os.RemoveAll(tempDir)
35+
36+
config := Config{outputDir: tempDir}
37+
inputProcessor := InputProcessor{config: config}
38+
39+
dataOutputPairs := []DataOutputPair{
40+
{
41+
Data: []byte(base64EncodedHelloWorld),
42+
OutputDir: "some_output_dir1",
43+
},
44+
}
45+
46+
err := inputProcessor.Process(dataOutputPairs)
47+
48+
assert.Nil(t, err)
49+
}
50+
51+
func TestProcess(t *testing.T) {
52+
53+
tempDir, _ := os.MkdirTemp("", "test")
54+
defer os.RemoveAll(tempDir)
55+
56+
config := Config{outputDir: tempDir}
57+
inputProcessor := InputProcessor{config: config}
58+
59+
dataOutputPairs := []DataOutputPair{
60+
{
61+
Data: []byte("some data"),
62+
OutputDir: "some_output_dir1",
63+
},
64+
{
65+
Data: []byte("some other data"),
66+
OutputDir: "some_output_dir2",
67+
},
68+
}
69+
70+
err := inputProcessor.Process(dataOutputPairs)
71+
72+
assert.Nil(t, err)
73+
}

Mime.go

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,16 @@ import (
44
"bufio"
55
"bytes"
66
"encoding/base64"
7+
"errors"
78
"io"
89
"log"
910
"mime"
1011
"mime/multipart"
1112
"strings"
1213
)
1314

15+
var errFailedToExtractMimeBoundary = errors.New("failed to get MIME boundary")
16+
1417
type MimeAttachment struct {
1518
ContentType string
1619
Content []byte
@@ -35,10 +38,10 @@ func extractBoundary(data []byte) (string, error) {
3538
return "", io.EOF
3639
}
3740

38-
func decodeMimAttachments(data []byte) (attachments []MimeAttachment, err error) {
41+
func ExtractMimeAttachmentsFromBytes(data []byte) (attachments []MimeAttachment, err error) {
3942
boundary, err := extractBoundary(data)
4043
if err != nil {
41-
log.Fatalf("Failed to get boundary: %s", err)
44+
return []MimeAttachment{}, errFailedToExtractMimeBoundary
4245
}
4346

4447
reader := multipart.NewReader(bytes.NewReader(data), boundary)
@@ -81,13 +84,3 @@ func decodeMimAttachments(data []byte) (attachments []MimeAttachment, err error)
8184

8285
return attachments, err
8386
}
84-
85-
func ExtractMimeAttachmentsFromBytes(encodedData []byte) (attachments []MimeAttachment, err error) {
86-
decoded, err := decode(encodedData)
87-
if err != nil {
88-
89-
return
90-
}
91-
92-
return decodeMimAttachments(decoded)
93-
}

Mime_test.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package main
2+
3+
import (
4+
"github.com/stretchr/testify/assert"
5+
"testing"
6+
)
7+
8+
func TestExtractMimeAttachments(t *testing.T) {
9+
decoded, _ := decode([]byte(mimeMessage))
10+
11+
attachments, err := ExtractMimeAttachmentsFromBytes(decoded)
12+
13+
assert.Nil(t, err)
14+
assert.Len(t, attachments, 2)
15+
assert.Equal(t, attachments[0].ContentType, "text/cloud-config; charset=\"utf-8\"")
16+
assert.Equal(t, attachments[1].ContentType, "text/x-shellscript; charset=\"utf-8\"")
17+
}
18+
19+
func TestExtractMimeAttachmentsReturnsErrorWhenNotMime(t *testing.T) {
20+
_, err := ExtractMimeAttachmentsFromBytes([]byte("not mime"))
21+
22+
assert.NotNil(t, err)
23+
assert.Equal(t, err, errFailedToExtractMimeBoundary)
24+
}

main.go

Lines changed: 5 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -4,35 +4,10 @@ import (
44
"errors"
55
"flag"
66
"fmt"
7+
"log"
78
"os"
8-
"path/filepath"
99
)
1010

11-
var providers = map[string]DataProvider{
12-
"aws": NewDefaultAwsProvider(),
13-
}
14-
15-
type Config struct {
16-
outputDir string
17-
providerKey string
18-
args []string
19-
}
20-
21-
func (config Config) getProvider() (DataProvider, error) {
22-
if config.providerKey == "" {
23-
input := config.args[0]
24-
return CommandLineProvider{Input: input}, nil
25-
} else {
26-
var ok bool
27-
provider, ok := providers[config.providerKey]
28-
if !ok {
29-
fmt.Println("Unknown provider:", config.providerKey)
30-
os.Exit(1)
31-
}
32-
return provider, nil
33-
}
34-
}
35-
3611
func main() {
3712
if err := run(); err != nil {
3813
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
@@ -48,29 +23,17 @@ func run() error {
4823
}
4924
provider, err := config.getProvider()
5025
if err != nil {
51-
return err
26+
log.Fatalf("failed to the provider")
5227
}
5328

5429
inputs, err := provider.FetchData()
5530
if err != nil {
5631
return fmt.Errorf("failed to fetch data: %w", err)
5732
}
5833

59-
for _, input := range inputs {
60-
attachments, err := ExtractMimeAttachmentsFromBytes(input.Data)
61-
if err != nil {
62-
return fmt.Errorf("failed to extract mime attachments: %w", err)
63-
}
64-
65-
outputPath := filepath.Join(config.outputDir, input.OutputDir)
66-
67-
err = ExtractCloudConfig(attachments, outputPath)
68-
if err != nil {
69-
return fmt.Errorf("failed to save write files: %w", err)
70-
}
71-
}
72-
73-
return nil
34+
return InputProcessor{
35+
config: config,
36+
}.Process(inputs)
7437
}
7538

7639
func parseFlags() (config Config, err error) {

main_test.go

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,5 @@
11
package main
22

3-
import (
4-
"github.com/stretchr/testify/assert"
5-
"testing"
6-
)
7-
83
const (
94
base64EncodedHelloWorld = "SGVsbG8sIFdvcmxkIQ=="
105
base64EncodedZippedHelloWorld = "H4sIAAAAAAAAA/NIzcnJ11EIzy/KSVEEANDDSuwNAAAA"
@@ -47,13 +42,3 @@ const (
4742
mimeMessage = `
4843
H4sICFuIGWUAA3VzZXJkYXRhAL2USXOjOBTH73wKV+5OC7DTISkfzCKMbXAjQCw3IQhgi2UMXuDTtzqdSk1P9aGnpmp0kepJb/m/+ulpbTPkzTD3xy5/mdUXNlQdOQ9f6uqeZ6+ztL00GTmPq4fVr2u5kL8+K8ulAhaKoiyWXyWwWj0ItmUbc5yf+6ptXmbiIxCE+fxPXAXtl0KG/D58oay9ZHPaNm9V8TqjJTn3+bB6uAxv8+ffpfoMcSZN/5af50ZD26xqipdZSvr8afH5Qq/6ru2r4d2VDAOhZc3tr7O3iuUNqfPVw9+TP46kZg+CYI3qMTUVMdHEYyotaxLSSx7CIV13Mq0ZSLDCbXdGp3ZnaeujBbORRIhZG9Qmnvrhk4m0hkAgoXKxzKRLzaDIzOdiL2EQj8oUh+ItNfFbHKm3/a0tLA0U1ISA6PxcKSwz7SuV4EDNO4skeKOaMgmpJLJ9xMo0vP2sSLN+VFBYJr7EknIi4bI5VGqTc83O0f24c65pg1jauE+WUQAKmO6KCRTQKcNuYEx+k1RYxFxWZmbmVnd8nOAJTm4QjIEhoj1wtu7JMQ/es+QBW6YAASRvgXPKbrYhXpC/vgs2YHdPxDtkwirUlDiV1Q5JCrGl5NtuYvoh6o4pKBcJ65AbbWVvygJ0Go4xRgHZlJV7zM426HwCMRb2Ipbsk2MEG3i39ZNEwuEebnBzgEnPK/So3MVpfT9kJ2gjyR1DYwuJATUHWKMPtnqiJ3IsBpJvxkshCcoxj7o2xKqPpFL3ZTSkOBETM9kTyHyiOzd/Kv2MGcCZLJHqaPQDe4kC8eTrpYYmqPpNCWgAOwGHzmYHysrb2KIfLg+pHtyIr9bIHBYcmUsKsRls4ttuVPY7ADuygUdvKjtPLpaBBBcx6/pDAPcZs0fBa8pvLoaq6/6WI5C8IwIBP7/zxu1XS1NEKlscjbKkdfCJiPCTkecfgQZro5aZWTxZmnXNImfcy04bR1vG9zKN1J4DXNLNmjsrQ+KJIIlKsG/QIvvASfjXPEV4i8R/4GRkoWMiXXB8lXkQqt5UyAFEIQ4VP/bVK+/lXz4OFsRgNreZbuAwu062Id6qbgBVrejGLFwe09B90qp1sffUVOBf410/b/YxDm/XuGYXLgtweVyC01oMrP7LMLrP+zJnrKfnqhv+92nUD3woP/YlH0JJ6LTpuK4CGZWUtzvRrD8WNp8LwncQdAAY8gUAAA==`
4944
)
50-
51-
func TestExtractMimeAttachments(t *testing.T) {
52-
53-
attachments, err := ExtractMimeAttachmentsFromBytes([]byte(mimeMessage))
54-
55-
assert.Nil(t, err)
56-
assert.Len(t, attachments, 2)
57-
assert.Equal(t, attachments[0].ContentType, "text/cloud-config; charset=\"utf-8\"")
58-
assert.Equal(t, attachments[1].ContentType, "text/x-shellscript; charset=\"utf-8\"")
59-
}

0 commit comments

Comments
 (0)