Skip to content
This repository has been archived by the owner on Sep 18, 2020. It is now read-only.

Commit

Permalink
Merge pull request #423 from cihangir/decoding-support-for-writefiles
Browse files Browse the repository at this point in the history
config: add decoding support for cloud init template write_files section
  • Loading branch information
crawford committed Apr 27, 2016
2 parents d17c76c + 2b5417e commit 1cd1ecb
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 64 deletions.
16 changes: 16 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,22 @@ func NewCloudConfig(contents string) (*CloudConfig, error) {
return &cfg, err
}

// Decode decodes the content of cloud config. Currently only WriteFiles section
// supports several types of encoding and all of them are supported. After
// decode operation, Encoding type is unset.
func (cc *CloudConfig) Decode() error {
for i, file := range cc.WriteFiles {
content, err := DecodeContent(file.Content, file.Encoding)
if err != nil {
return err
}

cc.WriteFiles[i].Content = string(content)
cc.WriteFiles[i].Encoding = ""
}

return nil
}
func (cc CloudConfig) String() string {
bytes, err := yaml.Marshal(cc)
if err != nil {
Expand Down
45 changes: 45 additions & 0 deletions config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package config

import (
"fmt"
"reflect"
"regexp"
"strings"
Expand Down Expand Up @@ -73,6 +74,50 @@ func TestNewCloudConfig(t *testing.T) {
}
}

func TestNewCloudConfigDecode(t *testing.T) {
// //all of these decode to "bar"
contentTests := map[string]string{
"base64": "YmFy",
"b64": "YmFy",
// theoretically gz+gzip are supported but they break yaml
// "gz": "\x1f\x8b\x08\x08w\x14\x87T\x02\xffok\x00KJ,\x02\x00\xaa\x8c\xffv\x03\x00\x00\x00",
// "gzip": "\x1f\x8b\x08\x08w\x14\x87T\x02\xffok\x00KJ,\x02\x00\xaa\x8c\xffv\x03\x00\x00\x00",
"gz+base64": "H4sIABMVh1QAA0tKLAIAqoz/dgMAAAA=",
"gzip+base64": "H4sIABMVh1QAA0tKLAIAqoz/dgMAAAA=",
"gz+b64": "H4sIABMVh1QAA0tKLAIAqoz/dgMAAAA=",
"gzip+b64": "H4sIABMVh1QAA0tKLAIAqoz/dgMAAAA=",
}

type testCase struct {
contents string
config CloudConfig
}

var decodingTests []testCase
for name, content := range contentTests {
decodingTests = append(decodingTests, testCase{
contents: fmt.Sprintf("#cloud-config\nwrite_files:\n - encoding: %q\n content: |\n %s", name, content),
config: CloudConfig{WriteFiles: []File{{Content: "bar"}}},
})
}

for i, tt := range decodingTests {
config, err := NewCloudConfig(tt.contents)
if err != nil {
t.Errorf("bad error (test case #%d): want %v, got %s", i, nil, err)
}

if err := config.Decode(); err != nil {
t.Errorf("bad error (test case #%d): want %v, got %s", i, nil, err)
}

if !reflect.DeepEqual(&tt.config, config) {
t.Errorf("bad config (test case #%d): want %#v, got %#v", i, tt.config, config)
}
}

}

func TestIsZero(t *testing.T) {
tests := []struct {
c interface{}
Expand Down
11 changes: 10 additions & 1 deletion initialize/user_data.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,16 @@ func ParseUserData(contents string) (interface{}, error) {
return config.NewScript(contents)
case config.IsCloudConfig(contents):
log.Printf("Parsing user-data as cloud-config")
return config.NewCloudConfig(contents)
cc, err := config.NewCloudConfig(contents)
if err != nil {
return nil, err
}

if err := cc.Decode(); err != nil {
return nil, err
}

return cc, nil
case config.IsIgnitionConfig(contents):
return nil, ErrIgnitionConfig
default:
Expand Down
13 changes: 6 additions & 7 deletions system/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,17 +45,16 @@ func (f *File) Permissions() (os.FileMode, error) {
return os.FileMode(perm), nil
}

// WriteFile writes given endecoded file to the filesystem
func WriteFile(f *File, root string) (string, error) {
if f.Encoding != "" {
return "", fmt.Errorf("Unable to write file with encoding %s", f.Encoding)
}

fullpath := path.Join(root, f.Path)
dir := path.Dir(fullpath)
log.Printf("Writing file to %q", fullpath)

content, err := config.DecodeContent(f.Content, f.Encoding)

if err != nil {
return "", fmt.Errorf("Unable to decode %s (%v)", f.Path, err)
}

if err := EnsureDirectoryExists(dir); err != nil {
return "", err
}
Expand All @@ -71,7 +70,7 @@ func WriteFile(f *File, root string) (string, error) {
return "", err
}

if err := ioutil.WriteFile(tmp.Name(), content, perm); err != nil {
if err := ioutil.WriteFile(tmp.Name(), []byte(f.Content), perm); err != nil {
return "", err
}

Expand Down
56 changes: 0 additions & 56 deletions system/file_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,62 +147,6 @@ func TestWriteFilePermissions(t *testing.T) {
}
}

func TestWriteFileEncodedContent(t *testing.T) {
dir, err := ioutil.TempDir(os.TempDir(), "coreos-cloudinit-")
if err != nil {
t.Fatalf("Unable to create tempdir: %v", err)
}
defer os.RemoveAll(dir)

//all of these decode to "bar"
content_tests := map[string]string{
"base64": "YmFy",
"b64": "YmFy",
"gz": "\x1f\x8b\x08\x08w\x14\x87T\x02\xffok\x00KJ,\x02\x00\xaa\x8c\xffv\x03\x00\x00\x00",
"gzip": "\x1f\x8b\x08\x08w\x14\x87T\x02\xffok\x00KJ,\x02\x00\xaa\x8c\xffv\x03\x00\x00\x00",
"gz+base64": "H4sIABMVh1QAA0tKLAIAqoz/dgMAAAA=",
"gzip+base64": "H4sIABMVh1QAA0tKLAIAqoz/dgMAAAA=",
"gz+b64": "H4sIABMVh1QAA0tKLAIAqoz/dgMAAAA=",
"gzip+b64": "H4sIABMVh1QAA0tKLAIAqoz/dgMAAAA=",
}

for encoding, content := range content_tests {
fullPath := path.Join(dir, encoding)

wf := File{config.File{
Path: encoding,
Encoding: encoding,
Content: content,
RawFilePermissions: "0644",
}}

path, err := WriteFile(&wf, dir)
if err != nil {
t.Fatalf("Processing of WriteFile failed: %v", err)
} else if path != fullPath {
t.Fatalf("WriteFile returned bad path: want %s, got %s", fullPath, path)
}

fi, err := os.Stat(fullPath)
if err != nil {
t.Fatalf("Unable to stat file: %v", err)
}

if fi.Mode() != os.FileMode(0644) {
t.Errorf("File has incorrect mode: %v", fi.Mode())
}

contents, err := ioutil.ReadFile(fullPath)
if err != nil {
t.Fatalf("Unable to read expected file: %v", err)
}

if string(contents) != "bar" {
t.Fatalf("File has incorrect contents: '%s'", contents)
}
}
}

func TestWriteFileInvalidEncodedContent(t *testing.T) {
dir, err := ioutil.TempDir(os.TempDir(), "coreos-cloudinit-")
if err != nil {
Expand Down

0 comments on commit 1cd1ecb

Please sign in to comment.