github.com/cloud-green/juju@v0.0.0-20151002100041-a00291338d3d/cmd/juju/machine/add_test.go (about) 1 // Copyright 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package machine_test 5 6 import ( 7 "strconv" 8 "strings" 9 10 "github.com/juju/cmd" 11 "github.com/juju/errors" 12 jc "github.com/juju/testing/checkers" 13 gc "gopkg.in/check.v1" 14 15 "github.com/juju/juju/apiserver/common" 16 "github.com/juju/juju/apiserver/params" 17 "github.com/juju/juju/cmd/envcmd" 18 "github.com/juju/juju/cmd/juju/machine" 19 "github.com/juju/juju/environs/manual" 20 "github.com/juju/juju/state/multiwatcher" 21 "github.com/juju/juju/storage" 22 "github.com/juju/juju/testing" 23 ) 24 25 type AddMachineSuite struct { 26 testing.FakeJujuHomeSuite 27 fakeAddMachine *fakeAddMachineAPI 28 fakeMachineManager *fakeMachineManagerAPI 29 } 30 31 var _ = gc.Suite(&AddMachineSuite{}) 32 33 func (s *AddMachineSuite) SetUpTest(c *gc.C) { 34 s.FakeJujuHomeSuite.SetUpTest(c) 35 s.fakeAddMachine = &fakeAddMachineAPI{} 36 s.fakeAddMachine.agentVersion = "1.21.0" 37 s.fakeMachineManager = &fakeMachineManagerAPI{} 38 } 39 40 func (s *AddMachineSuite) TestInit(c *gc.C) { 41 for i, test := range []struct { 42 args []string 43 series string 44 constraints string 45 placement string 46 count int 47 errorString string 48 }{ 49 { 50 count: 1, 51 }, { 52 args: []string{"--series", "some-series"}, 53 count: 1, 54 series: "some-series", 55 }, { 56 args: []string{"-n", "2"}, 57 count: 2, 58 }, { 59 args: []string{"lxc"}, 60 count: 1, 61 placement: "lxc:", 62 }, { 63 args: []string{"lxc", "-n", "2"}, 64 count: 2, 65 placement: "lxc:", 66 }, { 67 args: []string{"lxc:4"}, 68 count: 1, 69 placement: "lxc:4", 70 }, { 71 args: []string{"--constraints", "mem=8G"}, 72 count: 1, 73 constraints: "mem=8192M", 74 }, { 75 args: []string{"--constraints", "container=lxc"}, 76 errorString: `container constraint "lxc" not allowed when adding a machine`, 77 }, { 78 args: []string{"ssh:user@10.10.0.3"}, 79 count: 1, 80 placement: "ssh:user@10.10.0.3", 81 }, { 82 args: []string{"zone=us-east-1a"}, 83 count: 1, 84 placement: "env-uuid:zone=us-east-1a", 85 }, { 86 args: []string{"anything-here"}, 87 count: 1, 88 placement: "env-uuid:anything-here", 89 }, { 90 args: []string{"anything", "else"}, 91 errorString: `unrecognized args: \["else"\]`, 92 }, { 93 args: []string{"something:special"}, 94 count: 1, 95 placement: "something:special", 96 }, 97 } { 98 c.Logf("test %d", i) 99 addCmd := &machine.AddCommand{} 100 err := testing.InitCommand(addCmd, test.args) 101 if test.errorString == "" { 102 c.Check(err, jc.ErrorIsNil) 103 c.Check(addCmd.Series, gc.Equals, test.series) 104 c.Check(addCmd.Constraints.String(), gc.Equals, test.constraints) 105 if addCmd.Placement != nil { 106 c.Check(addCmd.Placement.String(), gc.Equals, test.placement) 107 } else { 108 c.Check("", gc.Equals, test.placement) 109 } 110 c.Check(addCmd.NumMachines, gc.Equals, test.count) 111 } else { 112 c.Check(err, gc.ErrorMatches, test.errorString) 113 } 114 } 115 } 116 117 func (s *AddMachineSuite) run(c *gc.C, args ...string) (*cmd.Context, error) { 118 add := machine.NewAddCommand(s.fakeAddMachine, s.fakeMachineManager) 119 return testing.RunCommand(c, envcmd.Wrap(add), args...) 120 } 121 122 func (s *AddMachineSuite) TestAddMachine(c *gc.C) { 123 context, err := s.run(c) 124 c.Assert(err, jc.ErrorIsNil) 125 c.Assert(testing.Stderr(context), gc.Equals, "created machine 0\n") 126 127 c.Assert(s.fakeAddMachine.args, gc.HasLen, 1) 128 param := s.fakeAddMachine.args[0] 129 c.Assert(param.Jobs, jc.DeepEquals, []multiwatcher.MachineJob{ 130 multiwatcher.JobHostUnits, 131 multiwatcher.JobManageNetworking, 132 }) 133 } 134 135 func (s *AddMachineSuite) TestSSHPlacement(c *gc.C) { 136 s.PatchValue(machine.ManualProvisioner, func(args manual.ProvisionMachineArgs) (string, error) { 137 return "42", nil 138 }) 139 context, err := s.run(c, "ssh:10.1.2.3") 140 c.Assert(err, jc.ErrorIsNil) 141 c.Assert(testing.Stderr(context), gc.Equals, "created machine 42\n") 142 } 143 144 func (s *AddMachineSuite) TestSSHPlacementError(c *gc.C) { 145 s.PatchValue(machine.ManualProvisioner, func(args manual.ProvisionMachineArgs) (string, error) { 146 return "", errors.New("failed to initialize warp core") 147 }) 148 context, err := s.run(c, "ssh:10.1.2.3") 149 c.Assert(err, gc.ErrorMatches, "failed to initialize warp core") 150 c.Assert(testing.Stderr(context), gc.Equals, "") 151 } 152 153 func (s *AddMachineSuite) TestParamsPassedOn(c *gc.C) { 154 _, err := s.run(c, "--constraints", "mem=8G", "--series=special", "zone=nz") 155 c.Assert(err, jc.ErrorIsNil) 156 c.Assert(s.fakeAddMachine.args, gc.HasLen, 1) 157 param := s.fakeAddMachine.args[0] 158 c.Assert(param.Placement.String(), gc.Equals, "fake-uuid:zone=nz") 159 c.Assert(param.Series, gc.Equals, "special") 160 c.Assert(param.Constraints.String(), gc.Equals, "mem=8192M") 161 } 162 163 func (s *AddMachineSuite) TestParamsPassedOnNTimes(c *gc.C) { 164 _, err := s.run(c, "-n", "3", "--constraints", "mem=8G", "--series=special") 165 c.Assert(err, jc.ErrorIsNil) 166 c.Assert(s.fakeAddMachine.args, gc.HasLen, 3) 167 param := s.fakeAddMachine.args[0] 168 c.Assert(param.Series, gc.Equals, "special") 169 c.Assert(param.Constraints.String(), gc.Equals, "mem=8192M") 170 c.Assert(s.fakeAddMachine.args[0], jc.DeepEquals, s.fakeAddMachine.args[1]) 171 c.Assert(s.fakeAddMachine.args[0], jc.DeepEquals, s.fakeAddMachine.args[2]) 172 } 173 174 func (s *AddMachineSuite) TestAddThreeMachinesWithTwoFailures(c *gc.C) { 175 s.fakeAddMachine.successOrder = []bool{true, false, false} 176 expectedOutput := `created machine 0 177 failed to create 2 machines 178 ` 179 context, err := s.run(c, "-n", "3") 180 c.Assert(err, gc.ErrorMatches, "something went wrong, something went wrong") 181 c.Assert(testing.Stderr(context), gc.Equals, expectedOutput) 182 } 183 184 func (s *AddMachineSuite) TestBlockedError(c *gc.C) { 185 s.fakeAddMachine.addError = common.ErrOperationBlocked("TestBlockedError") 186 _, err := s.run(c) 187 c.Assert(err, gc.Equals, cmd.ErrSilent) 188 // msg is logged 189 stripped := strings.Replace(c.GetTestLog(), "\n", "", -1) 190 c.Check(stripped, gc.Matches, ".*TestBlockedError.*") 191 } 192 193 func (s *AddMachineSuite) TestServerIsPreJobManageNetworking(c *gc.C) { 194 s.fakeAddMachine.agentVersion = "1.18.1" 195 _, err := s.run(c) 196 c.Assert(err, jc.ErrorIsNil) 197 198 c.Assert(s.fakeAddMachine.args, gc.HasLen, 1) 199 param := s.fakeAddMachine.args[0] 200 c.Assert(param.Jobs, jc.DeepEquals, []multiwatcher.MachineJob{ 201 multiwatcher.JobHostUnits, 202 }) 203 } 204 205 func (s *AddMachineSuite) TestAddMachineWithDisks(c *gc.C) { 206 s.fakeMachineManager.apiVersion = 1 207 _, err := s.run(c, "--disks", "2,1G", "--disks", "2G") 208 c.Assert(err, jc.ErrorIsNil) 209 c.Assert(s.fakeAddMachine.args, gc.HasLen, 0) 210 c.Assert(s.fakeMachineManager.args, gc.HasLen, 1) 211 param := s.fakeMachineManager.args[0] 212 c.Assert(param.Disks, gc.DeepEquals, []storage.Constraints{ 213 {Size: 1024, Count: 2}, 214 {Size: 2048, Count: 1}, 215 }) 216 } 217 218 func (s *AddMachineSuite) TestAddMachineWithDisksUnsupported(c *gc.C) { 219 _, err := s.run(c, "--disks", "2,1G", "--disks", "2G") 220 c.Assert(err, gc.ErrorMatches, "cannot add machines with disks: not supported by the API server") 221 } 222 223 type fakeAddMachineAPI struct { 224 successOrder []bool 225 currentOp int 226 args []params.AddMachineParams 227 addError error 228 agentVersion interface{} 229 } 230 231 func (f *fakeAddMachineAPI) Close() error { 232 return nil 233 } 234 235 func (f *fakeAddMachineAPI) EnvironmentUUID() string { 236 return "fake-uuid" 237 } 238 239 func (f *fakeAddMachineAPI) AddMachines(args []params.AddMachineParams) ([]params.AddMachinesResult, error) { 240 if f.addError != nil { 241 return nil, f.addError 242 } 243 results := []params.AddMachinesResult{} 244 for i := range args { 245 f.args = append(f.args, args[i]) 246 if i >= len(f.successOrder) || f.successOrder[i] { 247 results = append(results, params.AddMachinesResult{ 248 Machine: strconv.Itoa(i), 249 Error: nil, 250 }) 251 } else { 252 results = append(results, params.AddMachinesResult{ 253 Machine: string(i), 254 Error: ¶ms.Error{"something went wrong", "1"}, 255 }) 256 } 257 f.currentOp++ 258 } 259 return results, nil 260 } 261 262 func (f *fakeAddMachineAPI) AddMachines1dot18(args []params.AddMachineParams) ([]params.AddMachinesResult, error) { 263 return f.AddMachines(args) 264 } 265 266 func (f *fakeAddMachineAPI) ForceDestroyMachines(machines ...string) error { 267 return errors.NotImplementedf("ForceDestroyMachines") 268 } 269 270 func (f *fakeAddMachineAPI) ProvisioningScript(params.ProvisioningScriptParams) (script string, err error) { 271 return "", errors.NotImplementedf("ProvisioningScript") 272 } 273 274 func (f *fakeAddMachineAPI) EnvironmentGet() (map[string]interface{}, error) { 275 return map[string]interface{}{"agent-version": f.agentVersion}, nil 276 } 277 278 type fakeMachineManagerAPI struct { 279 apiVersion int 280 fakeAddMachineAPI 281 } 282 283 func (f *fakeMachineManagerAPI) BestAPIVersion() int { 284 return f.apiVersion 285 }