Skip to content
This repository was archived by the owner on Dec 17, 2021. It is now read-only.

Commit 2da64a8

Browse files
committed
commands/rm: Add
1 parent f899f56 commit 2da64a8

File tree

2 files changed

+322
-0
lines changed

2 files changed

+322
-0
lines changed

commands/rm.go

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package commands
2+
3+
import (
4+
"fmt"
5+
6+
"strings"
7+
8+
"errors"
9+
10+
"github.com/docker/machine/libmachine"
11+
"github.com/docker/machine/libmachine/log"
12+
)
13+
14+
func cmdRm(c CommandLine, api libmachine.API) error {
15+
if len(c.Args()) == 0 {
16+
c.ShowHelp()
17+
return ErrNoMachineSpecified
18+
}
19+
20+
log.Info(fmt.Sprintf("About to remove %s", strings.Join(c.Args(), ", ")))
21+
log.Warn("WARNING: This action will delete both local reference and remote instance.")
22+
23+
force := c.Bool("force")
24+
confirm := c.Bool("y")
25+
var errorOccurred []string
26+
27+
if !userConfirm(confirm, force) {
28+
return nil
29+
}
30+
31+
for _, hostName := range c.Args() {
32+
err := removeRemoteMachine(hostName, api)
33+
if err != nil {
34+
errorOccurred = collectError(fmt.Sprintf("Error removing host %q: %s", hostName, err), force, errorOccurred)
35+
}
36+
37+
if err == nil || force {
38+
removeErr := removeLocalMachine(hostName, api)
39+
if removeErr != nil {
40+
errorOccurred = collectError(fmt.Sprintf("Can't remove \"%s\"", hostName), force, errorOccurred)
41+
} else {
42+
log.Infof("Successfully removed %s", hostName)
43+
}
44+
}
45+
}
46+
47+
if len(errorOccurred) > 0 && !force {
48+
return errors.New(strings.Join(errorOccurred, "\n"))
49+
}
50+
51+
return nil
52+
}
53+
54+
func userConfirm(confirm bool, force bool) bool {
55+
if confirm || force {
56+
return true
57+
}
58+
59+
sure, err := confirmInput(fmt.Sprintf("Are you sure?"))
60+
if err != nil {
61+
return false
62+
}
63+
64+
return sure
65+
}
66+
67+
func removeRemoteMachine(hostName string, api libmachine.API) error {
68+
currentHost, loaderr := api.Load(hostName)
69+
if loaderr != nil {
70+
return loaderr
71+
}
72+
73+
return currentHost.Driver.Remove()
74+
}
75+
76+
func removeLocalMachine(hostName string, api libmachine.API) error {
77+
exist, _ := api.Exists(hostName)
78+
if !exist {
79+
return errors.New(hostName + " does not exist.")
80+
}
81+
return api.Remove(hostName)
82+
}
83+
84+
func collectError(message string, force bool, errorOccurred []string) []string {
85+
if force {
86+
log.Error(message)
87+
}
88+
return append(errorOccurred, message)
89+
}

commands/rm_test.go

Lines changed: 233 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,233 @@
1+
package commands
2+
3+
import (
4+
"testing"
5+
6+
"errors"
7+
8+
"github.com/docker/machine/commands/commandstest"
9+
"github.com/docker/machine/drivers/fakedriver"
10+
"github.com/docker/machine/libmachine/host"
11+
"github.com/docker/machine/libmachine/libmachinetest"
12+
"github.com/stretchr/testify/assert"
13+
)
14+
15+
func TestCmdRmMissingMachineName(t *testing.T) {
16+
commandLine := &commandstest.FakeCommandLine{}
17+
api := &libmachinetest.FakeAPI{}
18+
19+
err := cmdRm(commandLine, api)
20+
21+
assert.Equal(t, ErrNoMachineSpecified, err)
22+
assert.True(t, commandLine.HelpShown)
23+
}
24+
25+
func TestCmdRm(t *testing.T) {
26+
commandLine := &commandstest.FakeCommandLine{
27+
CliArgs: []string{"machineToRemove1", "machineToRemove2"},
28+
LocalFlags: &commandstest.FakeFlagger{
29+
Data: map[string]interface{}{
30+
"y": true,
31+
},
32+
},
33+
}
34+
api := &libmachinetest.FakeAPI{
35+
Hosts: []*host.Host{
36+
{
37+
Name: "machineToRemove1",
38+
Driver: &fakedriver.Driver{},
39+
},
40+
{
41+
Name: "machineToRemove2",
42+
Driver: &fakedriver.Driver{},
43+
},
44+
{
45+
Name: "machine",
46+
Driver: &fakedriver.Driver{},
47+
},
48+
},
49+
}
50+
51+
err := cmdRm(commandLine, api)
52+
assert.NoError(t, err)
53+
54+
assert.False(t, libmachinetest.Exists(api, "machineToRemove1"))
55+
assert.False(t, libmachinetest.Exists(api, "machineToRemove2"))
56+
assert.True(t, libmachinetest.Exists(api, "machine"))
57+
}
58+
59+
func TestCmdRmforcefully(t *testing.T) {
60+
commandLine := &commandstest.FakeCommandLine{
61+
CliArgs: []string{"machineToRemove1", "machineToRemove2"},
62+
LocalFlags: &commandstest.FakeFlagger{
63+
Data: map[string]interface{}{
64+
"force": true,
65+
},
66+
},
67+
}
68+
api := &libmachinetest.FakeAPI{
69+
Hosts: []*host.Host{
70+
{
71+
Name: "machineToRemove1",
72+
Driver: &fakedriver.Driver{},
73+
},
74+
{
75+
Name: "machineToRemove2",
76+
Driver: &fakedriver.Driver{},
77+
},
78+
},
79+
}
80+
81+
err := cmdRm(commandLine, api)
82+
assert.NoError(t, err)
83+
84+
assert.False(t, libmachinetest.Exists(api, "machineToRemove1"))
85+
assert.False(t, libmachinetest.Exists(api, "machineToRemove2"))
86+
}
87+
88+
func TestCmdRmforceDoesAutoConfirm(t *testing.T) {
89+
commandLine := &commandstest.FakeCommandLine{
90+
CliArgs: []string{"machineToRemove1", "machineToRemove2"},
91+
LocalFlags: &commandstest.FakeFlagger{
92+
Data: map[string]interface{}{
93+
"y": false,
94+
"force": true,
95+
},
96+
},
97+
}
98+
api := &libmachinetest.FakeAPI{
99+
Hosts: []*host.Host{
100+
{
101+
Name: "machineToRemove1",
102+
Driver: &fakedriver.Driver{},
103+
},
104+
{
105+
Name: "machineToRemove2",
106+
Driver: &fakedriver.Driver{},
107+
},
108+
},
109+
}
110+
111+
err := cmdRm(commandLine, api)
112+
assert.NoError(t, err)
113+
114+
assert.False(t, libmachinetest.Exists(api, "machineToRemove1"))
115+
assert.False(t, libmachinetest.Exists(api, "machineToRemove2"))
116+
}
117+
118+
func TestCmdRmforceConfirmUnset(t *testing.T) {
119+
commandLine := &commandstest.FakeCommandLine{
120+
CliArgs: []string{"machineToRemove1"},
121+
LocalFlags: &commandstest.FakeFlagger{
122+
Data: map[string]interface{}{
123+
"y": false,
124+
"force": false,
125+
},
126+
},
127+
}
128+
api := &libmachinetest.FakeAPI{
129+
Hosts: []*host.Host{
130+
{
131+
Name: "machineToRemove1",
132+
Driver: &fakedriver.Driver{},
133+
},
134+
},
135+
}
136+
137+
err := cmdRm(commandLine, api)
138+
assert.NoError(t, err)
139+
140+
assert.True(t, libmachinetest.Exists(api, "machineToRemove1"))
141+
}
142+
143+
type DriverWithRemoveWhichFail struct {
144+
fakedriver.Driver
145+
}
146+
147+
func (d *DriverWithRemoveWhichFail) Remove() error {
148+
return errors.New("unknown error")
149+
}
150+
151+
func TestDontStopWhenADriverRemovalFails(t *testing.T) {
152+
commandLine := &commandstest.FakeCommandLine{
153+
CliArgs: []string{"machineToRemove1", "machineToRemove2", "machineToRemove3"},
154+
LocalFlags: &commandstest.FakeFlagger{
155+
Data: map[string]interface{}{
156+
"y": true,
157+
},
158+
},
159+
}
160+
api := &libmachinetest.FakeAPI{
161+
Hosts: []*host.Host{
162+
{
163+
Name: "machineToRemove1",
164+
Driver: &fakedriver.Driver{},
165+
},
166+
{
167+
Name: "machineToRemove2",
168+
Driver: &DriverWithRemoveWhichFail{},
169+
},
170+
{
171+
Name: "machineToRemove3",
172+
Driver: &fakedriver.Driver{},
173+
},
174+
},
175+
}
176+
177+
err := cmdRm(commandLine, api)
178+
assert.EqualError(t, err, "Error removing host \"machineToRemove2\": unknown error")
179+
180+
assert.False(t, libmachinetest.Exists(api, "machineToRemove1"))
181+
assert.True(t, libmachinetest.Exists(api, "machineToRemove2"))
182+
assert.False(t, libmachinetest.Exists(api, "machineToRemove3"))
183+
}
184+
185+
func TestForceRemoveEvenWhenItFails(t *testing.T) {
186+
commandLine := &commandstest.FakeCommandLine{
187+
CliArgs: []string{"machineToRemove1"},
188+
LocalFlags: &commandstest.FakeFlagger{
189+
Data: map[string]interface{}{
190+
"y": true,
191+
"force": true,
192+
},
193+
},
194+
}
195+
api := &libmachinetest.FakeAPI{
196+
Hosts: []*host.Host{
197+
{
198+
Name: "machineToRemove1",
199+
Driver: &DriverWithRemoveWhichFail{},
200+
},
201+
},
202+
}
203+
204+
err := cmdRm(commandLine, api)
205+
assert.NoError(t, err)
206+
207+
assert.False(t, libmachinetest.Exists(api, "machineToRemove1"))
208+
}
209+
210+
func TestDontRemoveMachineIsRemovalFailsAndNotForced(t *testing.T) {
211+
commandLine := &commandstest.FakeCommandLine{
212+
CliArgs: []string{"machineToRemove1"},
213+
LocalFlags: &commandstest.FakeFlagger{
214+
Data: map[string]interface{}{
215+
"y": true,
216+
"force": false,
217+
},
218+
},
219+
}
220+
api := &libmachinetest.FakeAPI{
221+
Hosts: []*host.Host{
222+
{
223+
Name: "machineToRemove1",
224+
Driver: &DriverWithRemoveWhichFail{},
225+
},
226+
},
227+
}
228+
229+
err := cmdRm(commandLine, api)
230+
assert.EqualError(t, err, "Error removing host \"machineToRemove1\": unknown error")
231+
232+
assert.True(t, libmachinetest.Exists(api, "machineToRemove1"))
233+
}

0 commit comments

Comments
 (0)