Skip to content

Commit

Permalink
Merge pull request chef#17 from go-chef/issue8
Browse files Browse the repository at this point in the history
Issue8
  • Loading branch information
bradbeam committed May 28, 2014
2 parents be535c3 + 155dda6 commit c5adf85
Show file tree
Hide file tree
Showing 7 changed files with 202 additions and 23 deletions.
2 changes: 0 additions & 2 deletions node.go
Expand Up @@ -10,8 +10,6 @@ type Node struct {
*nativeNode
}

type RunList []string

// NativeNode represents the native Go version of the deserialized Node type
type nativeNode struct {
Name string `mapstructure:"name"`
Expand Down
21 changes: 0 additions & 21 deletions node_test.go
Expand Up @@ -59,27 +59,6 @@ func TestNodeName(t *testing.T) {
})
}

func TestNodeRunList(t *testing.T) {
n := testNodeMapStringInterfaceLol
rl := n.RunList

Convey("Node.RunList() should be a RunList", t, func() {
So(rl, ShouldHaveSameTypeAs, RunList{})
})

Convey("Node.RunList() should be populated", t, func() {
So(rl, ShouldContain, "recipe[foo]")
So(rl, ShouldContain, "recipe[baz]")
So(rl, ShouldContain, "role[banana]")
})

rl = RunList{}
Convey("Empty RunList should be valid", t, func() {
So(rl, ShouldBeEmpty)
})

}

func TestNodeAttribute(t *testing.T) {
n := testNodeMapStringInterfaceLol
attr := n.Normal
Expand Down
28 changes: 28 additions & 0 deletions role.go
@@ -0,0 +1,28 @@
package chef

import (
"github.com/mitchellh/mapstructure"
)

// Role has a Reader, hey presto
type Role struct {
*Reader
*nativeRole
}

// NativeRole represents the native Go version of the deserialized Role type
type nativeRole struct {
Name string `mapstructure:"name"`
RunList RunList `mapstructure:"run_list"`
Default map[string]interface{} `mapstructure:"default_attributes"`
Override map[string]interface{} `mapstructure:"override_attributes"`
}

// NewRole wraps a Role around a pointer to a Reader
func NewRole(reader *Reader) (*Role, error) {
role := Role{reader, &nativeRole{}}
if err := mapstructure.Decode(reader, role.nativeRole); err != nil {
return nil, err
}
return &role, nil
}
118 changes: 118 additions & 0 deletions role_test.go
@@ -0,0 +1,118 @@
package chef

import (
"encoding/json"
. "github.com/smartystreets/goconvey/convey"
"io"
"io/ioutil"
"log"
"os"
"path"
"testing"
)

var (
testRoleJSON = "test/role.json"
// FML
testRoleMapStringInterfaceLol, _ = NewRole(&Reader{
"name": "test",
"run_list": []string{"recipe[foo]", "recipe[baz]", "role[banana]"},
"chef_type": "role",
"json_class": "Chef::Role",
"default_attributes": map[string]interface{}{
"tags": map[string]interface{}{},
"openssh": map[string]interface{}{
"server": map[string]string{
"permit_root_login": "no",
"max_auth_tries": "3",
},
},
},
"override_attributes": map[string]interface{}{
"openssh": map[string]interface{}{
"server": map[string]string{
"permit_root_login": "yes",
"max_auth_tries": "1",
},
},
},
})
)

func TestRoleName(t *testing.T) {
// BUG(spheromak): Pull these constructors out into a Convey Decorator
n1 := testRoleMapStringInterfaceLol // (*Role)
name := n1.Name

Convey("Role name is 'test'", t, func() {
So(name, ShouldEqual, "test")
})

swordWithoutASheathe, err := NewRole(&Reader{
"foobar": "baz",
})

name = swordWithoutASheathe.Name
Convey("Role without a name", t, func() {
So(name, ShouldBeEmpty)
So(err, ShouldBeNil)
})
}

func TestRoleAttribute(t *testing.T) {
n := testRoleMapStringInterfaceLol
attr := n.Default
// BUG(spheromak): Holy shit this is ugly. Need to do something to make this easier for sure.
ugh := attr["openssh"].(map[string]interface{})["server"].(map[string]string)["permit_root_login"]
Convey("Role.Default should map", t, func() {
So(ugh, ShouldEqual, "no")
})
}

// BUG(fujin): re-do with goconvey
func TestRoleFromJSONDecoder(t *testing.T) {
if file, err := os.Open(testRoleJSON); err != nil {
t.Error("unexpected error", err, "during os.Open on", testRoleJSON)
} else {
dec := json.NewDecoder(file)
var n Role
if err := dec.Decode(&n); err == io.EOF {
log.Println(n)
} else if err != nil {
log.Fatal(err)
}
}
}

// TestNewRole checks the NewRole Reader chain for Type
func TestNewRole(t *testing.T) {
var v interface{}
v = testRoleMapStringInterfaceLol
Convey("NewRole should create a Role", t, func() {
So(v, ShouldHaveSameTypeAs, &Role{})
})

Convey("NewRole should error if decode fails", t, func() {

failRole, err := NewRole(&Reader{
"name": struct{}{},
})

So(err, ShouldNotBeNil)
So(failRole, ShouldBeNil)
})
}

// TestRoleReadIntoFile tests that Read() can be used to read by io.Readers
// BUG(fujin): re-do with goconvey
func TestRoleReadIntoFile(t *testing.T) {
n1 := testRoleMapStringInterfaceLol // (*Role)
tf, _ := ioutil.TempFile("test", "role-to-file")
// Copy to tempfile (I use Read() internally)
// BUG(fujin): this is currently doing that weird 32768 bytes read thing again.
io.Copy(tf, n1)

// Close and remove tempfile
tf.Close()
os.Remove(path.Clean(tf.Name()))
}
3 changes: 3 additions & 0 deletions run_list.go
@@ -0,0 +1,3 @@
package chef

type RunList []string
30 changes: 30 additions & 0 deletions run_list_test.go
@@ -0,0 +1,30 @@
package chef

import (
. "github.com/smartystreets/goconvey/convey"
"testing"
)

var (
runList RunList = []string{"recipe[foo]", "recipe[baz]", "role[banana]"}
)

func TestNodeRunList(t *testing.T) {
rl := runList

Convey("Node.RunList() should be a RunList", t, func() {
So(rl, ShouldHaveSameTypeAs, RunList{})
})

Convey("Node.RunList() should be populated", t, func() {
So(rl, ShouldContain, "recipe[foo]")
So(rl, ShouldContain, "recipe[baz]")
So(rl, ShouldContain, "role[banana]")
})

rl = RunList{}
Convey("Empty RunList should be valid", t, func() {
So(rl, ShouldBeEmpty)
})

}
23 changes: 23 additions & 0 deletions test/role.json
@@ -0,0 +1,23 @@
{
"name": "testrole",
"chef_environment": "_default",
"json_class": "Chef::Role",
"default_attributes": {
"openssh": {
"server": {
"permit_root_login": "no",
"max_auth_tries": "3",
"password_authentication": "no",
"x11_forwarding": "yes",
"subsystem": "sftp /usr/lib/openssh/sftp-server"
},
"client": {
"forward_x11": "yes",
"forward_agent": "yes"
}
}
},
"chef_type": "role",
"override": {},
"run_list": []
}

0 comments on commit c5adf85

Please sign in to comment.