github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/apiserver/action/run_test.go (about) 1 // Copyright 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package action_test 5 6 import ( 7 "github.com/juju/errors" 8 jc "github.com/juju/testing/checkers" 9 gc "gopkg.in/check.v1" 10 "gopkg.in/juju/names.v2" 11 12 "github.com/juju/juju/apiserver/action" 13 "github.com/juju/juju/apiserver/common" 14 commontesting "github.com/juju/juju/apiserver/common/testing" 15 "github.com/juju/juju/apiserver/params" 16 apiservertesting "github.com/juju/juju/apiserver/testing" 17 jujutesting "github.com/juju/juju/juju/testing" 18 "github.com/juju/juju/state" 19 "github.com/juju/juju/testing" 20 ) 21 22 type runSuite struct { 23 jujutesting.JujuConnSuite 24 commontesting.BlockHelper 25 26 client *action.ActionAPI 27 } 28 29 var _ = gc.Suite(&runSuite{}) 30 31 func (s *runSuite) SetUpTest(c *gc.C) { 32 s.JujuConnSuite.SetUpTest(c) 33 s.BlockHelper = commontesting.NewBlockHelper(s.APIState) 34 s.AddCleanup(func(*gc.C) { s.BlockHelper.Close() }) 35 36 var err error 37 auth := apiservertesting.FakeAuthorizer{ 38 Tag: s.AdminUserTag(c), 39 } 40 s.client, err = action.NewActionAPI(s.State, nil, auth) 41 c.Assert(err, jc.ErrorIsNil) 42 } 43 44 func (s *runSuite) addMachine(c *gc.C) *state.Machine { 45 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 46 c.Assert(err, jc.ErrorIsNil) 47 return machine 48 } 49 50 func (s *runSuite) addUnit(c *gc.C, service *state.Application) *state.Unit { 51 unit, err := service.AddUnit() 52 c.Assert(err, jc.ErrorIsNil) 53 err = unit.AssignToNewMachine() 54 c.Assert(err, jc.ErrorIsNil) 55 return unit 56 } 57 58 func (s *runSuite) TestGetAllUnitNames(c *gc.C) { 59 charm := s.AddTestingCharm(c, "dummy") 60 magic, err := s.State.AddApplication(state.AddApplicationArgs{Name: "magic", Charm: charm}) 61 s.addUnit(c, magic) 62 s.addUnit(c, magic) 63 64 notAssigned, err := s.State.AddApplication(state.AddApplicationArgs{Name: "not-assigned", Charm: charm}) 65 c.Assert(err, jc.ErrorIsNil) 66 _, err = notAssigned.AddUnit() 67 c.Assert(err, jc.ErrorIsNil) 68 69 _, err = s.State.AddApplication(state.AddApplicationArgs{Name: "no-units", Charm: charm}) 70 c.Assert(err, jc.ErrorIsNil) 71 72 wordpress, err := s.State.AddApplication(state.AddApplicationArgs{Name: "wordpress", Charm: s.AddTestingCharm(c, "wordpress")}) 73 c.Assert(err, jc.ErrorIsNil) 74 wordpress0 := s.addUnit(c, wordpress) 75 _, err = s.State.AddApplication(state.AddApplicationArgs{Name: "logging", Charm: s.AddTestingCharm(c, "logging")}) 76 c.Assert(err, jc.ErrorIsNil) 77 78 eps, err := s.State.InferEndpoints("logging", "wordpress") 79 c.Assert(err, jc.ErrorIsNil) 80 rel, err := s.State.AddRelation(eps...) 81 c.Assert(err, jc.ErrorIsNil) 82 ru, err := rel.Unit(wordpress0) 83 c.Assert(err, jc.ErrorIsNil) 84 err = ru.EnterScope(nil) 85 c.Assert(err, jc.ErrorIsNil) 86 87 for i, test := range []struct { 88 message string 89 expected []string 90 units []string 91 services []string 92 error string 93 }{{ 94 message: "no units, expected nil slice", 95 }, { 96 message: "asking for an empty string service", 97 services: []string{""}, 98 error: `"" is not a valid application name`, 99 }, { 100 message: "asking for an empty string unit", 101 units: []string{""}, 102 error: `invalid unit name ""`, 103 }, { 104 message: "asking for a service that isn't there", 105 services: []string{"foo"}, 106 error: `application "foo" not found`, 107 }, { 108 message: "service with no units is not really an error", 109 services: []string{"no-units"}, 110 }, { 111 message: "A service with units", 112 services: []string{"magic"}, 113 expected: []string{"magic/0", "magic/1"}, 114 }, { 115 message: "Asking for just a unit", 116 units: []string{"magic/0"}, 117 expected: []string{"magic/0"}, 118 }, { 119 message: "Asking for just a subordinate unit", 120 units: []string{"logging/0"}, 121 expected: []string{"logging/0"}, 122 }, { 123 message: "Asking for a unit, and the service", 124 services: []string{"magic"}, 125 units: []string{"magic/0"}, 126 expected: []string{"magic/0", "magic/1"}, 127 }} { 128 c.Logf("%v: %s", i, test.message) 129 result, err := action.GetAllUnitNames(s.State, test.units, test.services) 130 if test.error == "" { 131 c.Check(err, jc.ErrorIsNil) 132 var units []string 133 for _, unit := range result { 134 units = append(units, unit.Id()) 135 } 136 c.Check(units, jc.SameContents, test.expected) 137 } else { 138 c.Check(err, gc.ErrorMatches, test.error) 139 } 140 } 141 } 142 143 func (s *runSuite) AssertBlocked(c *gc.C, err error, msg string) { 144 c.Assert(params.IsCodeOperationBlocked(err), jc.IsTrue, gc.Commentf("error: %#v", err)) 145 c.Assert(errors.Cause(err), gc.DeepEquals, ¶ms.Error{ 146 Message: msg, 147 Code: "operation is blocked", 148 }) 149 } 150 151 func (s *runSuite) TestBlockRunOnAllMachines(c *gc.C) { 152 // block all changes 153 s.BlockAllChanges(c, "TestBlockRunOnAllMachines") 154 _, err := s.client.RunOnAllMachines( 155 params.RunParams{ 156 Commands: "hostname", 157 Timeout: testing.LongWait, 158 }) 159 s.AssertBlocked(c, err, "TestBlockRunOnAllMachines") 160 } 161 162 func (s *runSuite) TestBlockRunMachineAndService(c *gc.C) { 163 // block all changes 164 s.BlockAllChanges(c, "TestBlockRunMachineAndService") 165 _, err := s.client.Run( 166 params.RunParams{ 167 Commands: "hostname", 168 Timeout: testing.LongWait, 169 Machines: []string{"0"}, 170 Applications: []string{"magic"}, 171 }) 172 s.AssertBlocked(c, err, "TestBlockRunMachineAndService") 173 } 174 175 func (s *runSuite) TestRunMachineAndService(c *gc.C) { 176 // We only test that we create the actions correctly 177 // There is no need to test anything else at this level. 178 expectedPayload := map[string]interface{}{ 179 "command": "hostname", 180 "timeout": int64(0), 181 } 182 expectedArgs := params.Actions{ 183 Actions: []params.Action{ 184 {Receiver: "unit-magic-0", Name: "juju-run", Parameters: expectedPayload}, 185 {Receiver: "unit-magic-1", Name: "juju-run", Parameters: expectedPayload}, 186 {Receiver: "machine-0", Name: "juju-run", Parameters: expectedPayload}, 187 }, 188 } 189 called := false 190 s.PatchValue(action.QueueActions, func(client *action.ActionAPI, args params.Actions) (params.ActionResults, error) { 191 called = true 192 c.Assert(args, jc.DeepEquals, expectedArgs) 193 return params.ActionResults{}, nil 194 }) 195 196 s.addMachine(c) 197 198 charm := s.AddTestingCharm(c, "dummy") 199 magic, err := s.State.AddApplication(state.AddApplicationArgs{Name: "magic", Charm: charm}) 200 c.Assert(err, jc.ErrorIsNil) 201 s.addUnit(c, magic) 202 s.addUnit(c, magic) 203 204 s.client.Run( 205 params.RunParams{ 206 Commands: "hostname", 207 Machines: []string{"0"}, 208 Applications: []string{"magic"}, 209 }) 210 c.Assert(called, jc.IsTrue) 211 } 212 213 func (s *runSuite) TestRunOnAllMachines(c *gc.C) { 214 // We only test that we create the actions correctly 215 // There is no need to test anything else at this level. 216 expectedPayload := map[string]interface{}{ 217 "command": "hostname", 218 "timeout": testing.LongWait.Nanoseconds(), 219 } 220 expectedArgs := params.Actions{ 221 Actions: []params.Action{ 222 {Receiver: "machine-0", Name: "juju-run", Parameters: expectedPayload}, 223 {Receiver: "machine-1", Name: "juju-run", Parameters: expectedPayload}, 224 {Receiver: "machine-2", Name: "juju-run", Parameters: expectedPayload}, 225 }, 226 } 227 called := false 228 s.PatchValue(action.QueueActions, func(client *action.ActionAPI, args params.Actions) (params.ActionResults, error) { 229 called = true 230 c.Assert(args, jc.DeepEquals, expectedArgs) 231 return params.ActionResults{}, nil 232 }) 233 // Make three machines. 234 s.addMachine(c) 235 s.addMachine(c) 236 s.addMachine(c) 237 238 s.client.RunOnAllMachines( 239 params.RunParams{ 240 Commands: "hostname", 241 Timeout: testing.LongWait, 242 }) 243 c.Assert(called, jc.IsTrue) 244 } 245 246 func (s *runSuite) TestRunRequiresAdmin(c *gc.C) { 247 alpha := names.NewUserTag("alpha@bravo") 248 auth := apiservertesting.FakeAuthorizer{ 249 Tag: alpha, 250 HasWriteTag: alpha, 251 } 252 client, err := action.NewActionAPI(s.State, nil, auth) 253 c.Assert(err, jc.ErrorIsNil) 254 _, err = client.Run(params.RunParams{}) 255 c.Assert(errors.Cause(err), gc.Equals, common.ErrPerm) 256 257 auth.AdminTag = alpha 258 client, err = action.NewActionAPI(s.State, nil, auth) 259 c.Assert(err, jc.ErrorIsNil) 260 _, err = client.Run(params.RunParams{}) 261 c.Assert(err, jc.ErrorIsNil) 262 } 263 264 func (s *runSuite) TestRunOnAllMachinesRequiresAdmin(c *gc.C) { 265 alpha := names.NewUserTag("alpha@bravo") 266 auth := apiservertesting.FakeAuthorizer{ 267 Tag: alpha, 268 HasWriteTag: alpha, 269 } 270 client, err := action.NewActionAPI(s.State, nil, auth) 271 c.Assert(err, jc.ErrorIsNil) 272 _, err = client.RunOnAllMachines(params.RunParams{}) 273 c.Assert(errors.Cause(err), gc.Equals, common.ErrPerm) 274 275 auth.AdminTag = alpha 276 client, err = action.NewActionAPI(s.State, nil, auth) 277 c.Assert(err, jc.ErrorIsNil) 278 _, err = client.RunOnAllMachines(params.RunParams{}) 279 c.Assert(err, jc.ErrorIsNil) 280 }