Skip to content

Commit

Permalink
Merge pull request #173 from xmudrii/volume-extended
Browse files Browse the repository at this point in the history
Added new actions for Volume and Volume-Action
  • Loading branch information
nanzhong authored Dec 23, 2016
2 parents 658f28e + 17d01eb commit b4a5dd5
Show file tree
Hide file tree
Showing 9 changed files with 296 additions and 18 deletions.
7 changes: 4 additions & 3 deletions args.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ const (
ArgResizeDisk = "resize-disk"
// ArgSnapshotName is a snapshot name arugment.
ArgSnapshotName = "snapshot-name"
// ArgSnapshotDesc is the description for volume snapshot.
ArgSnapshotDesc = "snapshot-desc"
// ArgResourceType is the resource type for snapshot.
ArgResourceType = "resource"
// ArgBackups is an enable backups argument.
ArgBackups = "enable-backups"
// ArgIPv6 is an enable IPv6 argument.
Expand Down Expand Up @@ -131,7 +135,4 @@ const (

// ArgDeleteForce forces deletion actions
ArgDeleteForce = "force"

// ArgResourceType is the resource type for snapshot.
ArgResourceType = "resource"
)
65 changes: 65 additions & 0 deletions commands/volume_actions.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
/*
Copyright 2016 The Doctl Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package commands

import (
Expand Down Expand Up @@ -51,6 +64,16 @@ func VolumeAction() *Command {
CmdBuilder(cmd, RunVolumeDetach, "detach <volume-id>", "detach a volume", Writer,
aliasOpt("d"))

CmdBuilder(cmd, RunVolumeDetachByDropletID, "detach-by-droplet-id <volume-id> <droplet-id>", "detach a volume by droplet ID", Writer,
aliasOpt("dd"))

cmdRunVolumeResize := CmdBuilder(cmd, RunVolumeResize, "resize <volume-id>", "resize a volume", Writer,
aliasOpt("r"))
AddIntFlag(cmdRunVolumeResize, doctl.ArgSizeSlug, "", 0, "New size",
requiredOpt())
AddStringFlag(cmdRunVolumeResize, doctl.ArgRegionSlug, "", "", "Volume region",
requiredOpt())

return cmd

}
Expand Down Expand Up @@ -85,3 +108,45 @@ func RunVolumeDetach(c *CmdConfig) error {
}
return performVolumeAction(c, fn)
}

// RunVolumeDetachByDropletID detaches a volume by droplet ID
func RunVolumeDetachByDropletID(c *CmdConfig) error {
fn := func(das do.VolumeActionsService) (*do.Action, error) {
if len(c.Args) != 2 {
return nil, doctl.NewMissingArgsErr(c.NS)
}
volumeID := c.Args[0]
dropletID, err := strconv.Atoi(c.Args[1])
if err != nil {
return nil, err
}
a, err := das.DetachByDropletID(volumeID, dropletID)
return a, err
}
return performVolumeAction(c, fn)
}

// RunVolumeResize resizes a volume
func RunVolumeResize(c *CmdConfig) error {
fn := func(das do.VolumeActionsService) (*do.Action, error) {
if len(c.Args) != 1 {
return nil, doctl.NewMissingArgsErr(c.NS)
}

volumeID := c.Args[0]

size, err := c.Doit.GetInt(c.NS, doctl.ArgSizeSlug)
if err != nil {
return nil, err
}

region, err := c.Doit.GetString(c.NS, doctl.ArgRegionSlug)
if err != nil {
return nil, err
}

a, err := das.Resize(volumeID, size, region)
return a, err
}
return performVolumeAction(c, fn)
}
40 changes: 39 additions & 1 deletion commands/volume_actions_test.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,30 @@
/*
Copyright 2016 The Doctl Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package commands

import (
"fmt"
"testing"

"github.com/digitalocean/doctl"
"github.com/stretchr/testify/assert"
)

func TestVolumeActionCommand(t *testing.T) {
cmd := VolumeAction()
assert.NotNil(t, cmd)
assertCommandNames(t, cmd, "attach", "detach")
assertCommandNames(t, cmd, "attach", "detach", "detach-by-droplet-id", "resize")
}

func TestVolumeActionsAttach(t *testing.T) {
Expand All @@ -33,3 +47,27 @@ func TestVolumeActionsDetach(t *testing.T) {
assert.NoError(t, err)
})
}

func TestVolumeDetachByDropletID(t *testing.T) {
withTestClient(t, func(config *CmdConfig, tm *tcMocks) {
tm.volumeActions.On("DetachByDropletID", testVolume.ID, testDroplet.ID).Return(&testAction, nil)
config.Args = append(config.Args, testVolume.ID)
config.Args = append(config.Args, fmt.Sprintf("%d", testDroplet.ID))

err := RunVolumeDetachByDropletID(config)
assert.NoError(t, err)
})
}

func TestVolumeResize(t *testing.T) {
withTestClient(t, func(config *CmdConfig, tm *tcMocks) {
tm.volumeActions.On("Resize", testVolume.ID, 150, "dev0").Return(&testAction, nil)
config.Args = append(config.Args, testVolume.ID)

config.Doit.Set(config.NS, doctl.ArgSizeSlug, 150)
config.Doit.Set(config.NS, doctl.ArgRegionSlug, "dev0")

err := RunVolumeResize(config)
assert.NoError(t, err)
})
}
51 changes: 51 additions & 0 deletions commands/volumes.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
/*
Copyright 2016 The Doctl Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package commands

import (
Expand Down Expand Up @@ -39,6 +52,11 @@ func Volume() *Command {
CmdBuilder(cmd, RunVolumeGet, "get [ID]", "get a volume", Writer, aliasOpt("g"),
displayerType(&volume{}))

cmdRunVolumeSnapshot := CmdBuilder(cmd, RunVolumeSnapshot, "snapshot [volume-id]", "create a volume snapshot", Writer,
aliasOpt("s"), displayerType(&volume{}))
AddStringFlag(cmdRunVolumeSnapshot, doctl.ArgSnapshotName, "", "", "Snapshot name", requiredOpt())
AddStringFlag(cmdRunVolumeSnapshot, doctl.ArgSnapshotDesc, "", "", "Snapshot description")

return cmd

}
Expand Down Expand Up @@ -174,3 +192,36 @@ func RunVolumeGet(c *CmdConfig) error {
item := &volume{volumes: []do.Volume{*d}}
return c.Display(item)
}

// RunVolumeSnapshot creates a snapshot of a volume
func RunVolumeSnapshot(c *CmdConfig) error {
var err error
if len(c.Args) == 0 {
return doctl.NewMissingArgsErr(c.NS)
}

al := c.Volumes()
id := c.Args[0]

name, err := c.Doit.GetString(c.NS, doctl.ArgSnapshotName)
if err != nil {
return err
}

desc, err := c.Doit.GetString(c.NS, doctl.ArgSnapshotDesc)
if err != nil {
return nil
}

req := &godo.SnapshotCreateRequest{
VolumeID: id,
Name: name,
Description: desc,
}

if _, err := al.CreateSnapshot(req); err != nil {
return err
}

return nil
}
33 changes: 32 additions & 1 deletion commands/volumes_test.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
/*
Copyright 2016 The Doctl Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package commands

import (
Expand Down Expand Up @@ -28,7 +41,7 @@ var (
func TestVolumeCommand(t *testing.T) {
cmd := Volume()
assert.NotNil(t, cmd)
assertCommandNames(t, cmd, "create", "delete", "get", "list")
assertCommandNames(t, cmd, "create", "delete", "get", "list", "snapshot")
}

func TestVolumesGet(t *testing.T) {
Expand Down Expand Up @@ -104,3 +117,21 @@ func TestVolumesDelete(t *testing.T) {
assert.NoError(t, err)
})
}

func TestVolumesSnapshot(t *testing.T) {
withTestClient(t, func(config *CmdConfig, tm *tcMocks) {
tcr := godo.SnapshotCreateRequest{
VolumeID: testVolume.ID,
Name: "test-volume-snapshot",
Description: "test description",
}
tm.volumes.On("CreateSnapshot", &tcr).Return(nil, nil)

config.Args = append(config.Args, testVolume.ID)
config.Doit.Set(config.NS, doctl.ArgSnapshotName, "test-volume-snapshot")
config.Doit.Set(config.NS, doctl.ArgSnapshotDesc, "test description")

err := RunVolumeSnapshot(config)
assert.NoError(t, err)
})
}
54 changes: 50 additions & 4 deletions do/mocks/VolumeActionsService.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
package mocks

import "github.com/digitalocean/doctl/do"
import "github.com/stretchr/testify/mock"

// Generated: please do not edit by hand
import do "github.com/digitalocean/doctl/do"
import mock "github.com/stretchr/testify/mock"

// VolumeActionsService is an autogenerated mock type for the VolumeActionsService type
type VolumeActionsService struct {
Expand Down Expand Up @@ -55,3 +53,51 @@ func (_m *VolumeActionsService) Detach(_a0 string) (*do.Action, error) {

return r0, r1
}

// DetachByDropletID provides a mock function with given fields: _a0, _a1
func (_m *VolumeActionsService) DetachByDropletID(_a0 string, _a1 int) (*do.Action, error) {
ret := _m.Called(_a0, _a1)

var r0 *do.Action
if rf, ok := ret.Get(0).(func(string, int) *do.Action); ok {
r0 = rf(_a0, _a1)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*do.Action)
}
}

var r1 error
if rf, ok := ret.Get(1).(func(string, int) error); ok {
r1 = rf(_a0, _a1)
} else {
r1 = ret.Error(1)
}

return r0, r1
}

// Resize provides a mock function with given fields: _a0, _a1, _a2
func (_m *VolumeActionsService) Resize(_a0 string, _a1 int, _a2 string) (*do.Action, error) {
ret := _m.Called(_a0, _a1, _a2)

var r0 *do.Action
if rf, ok := ret.Get(0).(func(string, int, string) *do.Action); ok {
r0 = rf(_a0, _a1, _a2)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*do.Action)
}
}

var r1 error
if rf, ok := ret.Get(1).(func(string, int, string) error); ok {
r1 = rf(_a0, _a1, _a2)
} else {
r1 = ret.Error(1)
}

return r0, r1
}

var _ do.VolumeActionsService = (*VolumeActionsService)(nil)
34 changes: 28 additions & 6 deletions do/mocks/VolumesService.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,37 @@
package mocks

import "github.com/digitalocean/doctl/do"
import "github.com/stretchr/testify/mock"

import "github.com/digitalocean/godo"

// Generated: please do not edit by hand
import do "github.com/digitalocean/doctl/do"
import godo "github.com/digitalocean/godo"
import mock "github.com/stretchr/testify/mock"

// VolumesService is an autogenerated mock type for the VolumesService type
type VolumesService struct {
mock.Mock
}

// CreateSnapshot provides a mock function with given fields: _a0
func (_m *VolumesService) CreateSnapshot(_a0 *godo.SnapshotCreateRequest) (*do.Snapshot, error) {
ret := _m.Called(_a0)

var r0 *do.Snapshot
if rf, ok := ret.Get(0).(func(*godo.SnapshotCreateRequest) *do.Snapshot); ok {
r0 = rf(_a0)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*do.Snapshot)
}
}

var r1 error
if rf, ok := ret.Get(1).(func(*godo.SnapshotCreateRequest) error); ok {
r1 = rf(_a0)
} else {
r1 = ret.Error(1)
}

return r0, r1
}

// CreateVolume provides a mock function with given fields: _a0
func (_m *VolumesService) CreateVolume(_a0 *godo.VolumeCreateRequest) (*do.Volume, error) {
ret := _m.Called(_a0)
Expand Down Expand Up @@ -94,3 +114,5 @@ func (_m *VolumesService) List() ([]do.Volume, error) {

return r0, r1
}

var _ do.VolumesService = (*VolumesService)(nil)
Loading

0 comments on commit b4a5dd5

Please sign in to comment.