diff --git a/resource/file/preparer.go b/resource/file/preparer.go index 4aef5aac6..ec8447e24 100644 --- a/resource/file/preparer.go +++ b/resource/file/preparer.go @@ -32,12 +32,11 @@ type Preparer struct { Destination string `hcl:"destination"` // State sets whether the resource exists - // vaild states are [ "present", "absent" ] - State string `hcl:"state"` + State string `hcl:"state" valid_values:"present,absent"` // Type sets the type of the resource // valid types are [ "file", "directory", "hardlink", "symlink"] - Type string `hcl:"type"` + Type string `hcl:"type" valid_values:"file,directory,hardlink,symlink"` // Target is the target file for a symbolic or hard link // destination -> target @@ -46,10 +45,10 @@ type Preparer struct { // Force Change the resource. For example, if the target is a file and // state is set to directory, the file will be removed // Force on a symlink will remove the previous symlink - Force string `hcl:"force" doc_type:"bool"` + Force bool `hcl:"force" doc_type:"bool"` // Mode is the mode of the file, specified in octal (like 0755). - Mode string `hcl:"mode" doc_type:"octal string"` + Mode *uint32 `hcl:"mode" base:"8" doc_type:"uint32"` // User is the user name of the file owner User string `hcl:"user"` @@ -64,71 +63,16 @@ type Preparer struct { // Prepare a file resource func (p *Preparer) Prepare(render resource.Renderer) (resource.Task, error) { - // render Destination - Destination, err := render.Render("destination", p.Destination) - if err != nil { - return nil, err - } - - State, err := render.Render("state", p.State) - if err != nil { - return nil, err - } - - Type, err := render.Render("type", p.Type) - if err != nil { - return nil, err - } - - Target, err := render.Render("target", p.Target) - if err != nil { - return nil, err - } - - Force, err := render.RenderBool("target", p.Force) - if err != nil { - return nil, err - } - - // render Mode - Mode, err := render.Render("mode", p.Mode) - if err != nil { - return nil, err - } - - fileMode, err := UnixMode(Mode) - if err != nil { - return nil, err - } - - UserName, err := render.Render("user", p.User) - if err != nil { - return nil, err - } - - GroupName, err := render.Render("group", p.Group) - if err != nil { - return nil, err - } - - c, err := render.Render("content", p.Content) - if err != nil { - return nil, err - } - - Content := []byte(c) - fileTask := &File{ - Destination: Destination, - State: State, - Type: Type, - Target: Target, - Force: Force, - Mode: Mode, - FileMode: fileMode, - UserInfo: &user.User{Username: UserName}, - GroupInfo: &user.Group{Name: GroupName}, - Content: Content, + Destination: p.Destination, + Mode: p.Mode, + State: p.State, + Type: p.Type, + Target: p.Target, + Force: p.Force, + UserInfo: &user.User{Username: p.User}, + GroupInfo: &user.Group{Name: p.Group}, + Content: []byte(p.Content), } return fileTask, fileTask.Validate() diff --git a/resource/file/preparer_test.go b/resource/file/preparer_test.go index 0d15cf1c4..5c7d24628 100644 --- a/resource/file/preparer_test.go +++ b/resource/file/preparer_test.go @@ -15,6 +15,7 @@ package file_test import ( + "fmt" "testing" "github.com/asteris-llc/converge/helpers/fakerenderer" @@ -30,113 +31,104 @@ func TestPreparerInterface(t *testing.T) { assert.Implements(t, (*resource.Resource)(nil), new(content.Preparer)) } -func TestPreparerDestinationIsRequired(t *testing.T) { - p := &file.Preparer{} - _, err := p.Prepare(fakerenderer.New()) - if assert.Error(t, err) { - assert.EqualError(t, err, "file requires a destination parameter") - } -} - -func TestPreparerInvalidState(t *testing.T) { - p := &file.Preparer{Destination: "/aster/is", State: "foo"} - _, err := p.Prepare(fakerenderer.New()) - if assert.Error(t, err) { - assert.EqualError(t, err, "state should be one of present, absent, got \"foo\"") - } -} - -func TestPreparerInvalidType(t *testing.T) { - p := &file.Preparer{Destination: "/aster/is", Type: "bar"} - _, err := p.Prepare(fakerenderer.New()) - if assert.Error(t, err) { - assert.EqualError(t, err, "type should be one of directory, file, hardlink, symlink, got \"bar\"") - } -} - -func TestTargetNotDefinedForSymlink(t *testing.T) { - p := &file.Preparer{Destination: "/aster/is", Type: "symlink"} - _, err := p.Prepare(fakerenderer.New()) - if assert.Error(t, err) { - assert.EqualError(t, err, "must define a target if you are using a \"symlink\"") - } -} - -func TestTargetDefinedForSymlink(t *testing.T) { - p := &file.Preparer{Destination: "/aster/is", Type: "symlink", Target: "/get/converge"} - _, err := p.Prepare(fakerenderer.New()) - if !assert.Nil(t, err) { - assert.EqualError(t, err, "target + symlink should pass") - } -} - -func TestTargetNotDefinedForHardlink(t *testing.T) { - p := &file.Preparer{Destination: "/aster/is", Type: "hardlink"} - _, err := p.Prepare(fakerenderer.New()) - if assert.Error(t, err) { - assert.EqualError(t, err, "must define a target if you are using a \"hardlink\"") - } -} - -func TestTargetDefinedForHardLink(t *testing.T) { - p := &file.Preparer{Destination: "/aster/is", Type: "hardlink", Target: "/get/converge"} - _, err := p.Prepare(fakerenderer.New()) - if !assert.Nil(t, err) { - assert.EqualError(t, err, "target + hardlink should pass") - } -} - -func TestBadPermissions1(t *testing.T) { - p := &file.Preparer{Destination: "/aster/is", Mode: "999"} - _, err := p.Prepare(fakerenderer.New()) - if assert.Error(t, err) { - assert.EqualError(t, err, "\"999\" is not a valid file mode") - } -} - -//text permissions not supported yet -func TestBadPermissions2(t *testing.T) { - p := &file.Preparer{Destination: "/aster/is", Mode: "rwxrwxrwx"} - _, err := p.Prepare(fakerenderer.New()) - if assert.Error(t, err) { - assert.EqualError(t, err, "\"rwxrwxrwx\" is not a valid file mode") - } -} - -func TestValidPermissions(t *testing.T) { - p := &file.Preparer{Destination: "/aster/is", Mode: "0755"} - _, err := p.Prepare(fakerenderer.New()) - if !assert.Nil(t, err) { - assert.EqualError(t, err, "correct permissions of 0755 should pass") - } -} - -func TestValidConfig1(t *testing.T) { - p := &file.Preparer{ - Destination: "/aster/is", - Mode: "0755", - Type: "file", - Force: "true", - User: "root", - Group: "wheel", - } - _, err := p.Prepare(fakerenderer.New()) - if !assert.Nil(t, err) { - assert.EqualError(t, err, "correct configuration should pass") - } -} +func TestPrepare(t *testing.T) { + t.Parallel() + t.Run("validConfig1", func(t *testing.T) { + perms := new(uint32) + *perms = uint32(0755) + p := &file.Preparer{ + Destination: "/aster/is", + Mode: perms, + Type: "file", + Force: true, + User: "root", + Group: "wheel", + } + _, err := p.Prepare(fakerenderer.New()) + if !assert.Nil(t, err) { + assert.EqualError(t, err, "correct configuration should pass") + } + }) + + t.Run("validConfig2", func(t *testing.T) { + perms := new(uint32) + *perms = 4700 + p := &file.Preparer{ + Destination: "/aster/is", + Mode: perms, + Type: "directory", + Force: false, + User: "root", + Group: "wheel", + } + _, err := p.Prepare(fakerenderer.New()) + if !assert.Nil(t, err) { + assert.EqualError(t, err, "correct configuration should pass") + } + }) + + t.Run("badConfigNoDestination", func(t *testing.T) { + perms := new(uint32) + *perms = 4700 + p := &file.Preparer{ + Mode: perms, + Type: "directory", + Force: false, + User: "root", + Group: "wheel", + } + _, err := p.Prepare(fakerenderer.New()) + assert.Error(t, err, "file requires a destination parameter") + }) + + t.Run("badConfigType", func(t *testing.T) { + p := &file.Preparer{ + Destination: "/aster/is", + Type: "badType", + } + _, err := p.Prepare(fakerenderer.New()) + assert.NotNil(t, err) + assert.EqualError(t, err, fmt.Sprintf("type should be one of directory, file, hardlink, symlink, got %q", p.Type)) + }) + + t.Run("badConfigState", func(t *testing.T) { + p := &file.Preparer{ + Destination: "/aster/is", + State: "badState", + } + _, err := p.Prepare(fakerenderer.New()) + assert.NotNil(t, err) + assert.EqualError(t, err, fmt.Sprintf("state should be one of present, absent, got %q", p.State)) + }) + + t.Run("badConfigSymlink", func(t *testing.T) { + p := &file.Preparer{ + Destination: "/aster/is", + Type: "symlink", + } + _, err := p.Prepare(fakerenderer.New()) + assert.NotNil(t, err) + assert.EqualError(t, err, fmt.Sprintf("must define a target if you are using a %q", p.Type)) + }) + + t.Run("badConfigHardlink", func(t *testing.T) { + p := &file.Preparer{ + Destination: "/aster/is", + Type: "hardlink", + } + _, err := p.Prepare(fakerenderer.New()) + assert.NotNil(t, err) + assert.EqualError(t, err, fmt.Sprintf("must define a target if you are using a %q", p.Type)) + }) + + t.Run("badConfigTargetNolink", func(t *testing.T) { + p := &file.Preparer{ + Destination: "/aster/is", + Target: "/converge", + } + _, err := p.Prepare(fakerenderer.New()) + assert.NotNil(t, err) + assert.EqualError(t, err, fmt.Sprintf("cannot define target on a type of \"file\": target: %q", p.Target)) + }) -func TestValidConfig2(t *testing.T) { - p := &file.Preparer{ - Destination: "/aster/is", - Mode: "4700", - Type: "directory", - Force: "false", - User: "root", - Group: "wheel", - } - _, err := p.Prepare(fakerenderer.New()) - if !assert.Nil(t, err) { - assert.EqualError(t, err, "correct configuration should pass") - } }