github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/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 11 "github.com/juju/juju/apiserver/action" 12 commontesting "github.com/juju/juju/apiserver/common/testing" 13 "github.com/juju/juju/apiserver/params" 14 apiservertesting "github.com/juju/juju/apiserver/testing" 15 jujutesting "github.com/juju/juju/juju/testing" 16 "github.com/juju/juju/state" 17 "github.com/juju/juju/testing" 18 ) 19 20 type runSuite struct { 21 jujutesting.JujuConnSuite 22 commontesting.BlockHelper 23 24 client *action.ActionAPI 25 } 26 27 var _ = gc.Suite(&runSuite{}) 28 29 func (s *runSuite) SetUpTest(c *gc.C) { 30 s.JujuConnSuite.SetUpTest(c) 31 s.BlockHelper = commontesting.NewBlockHelper(s.APIState) 32 s.AddCleanup(func(*gc.C) { s.BlockHelper.Close() }) 33 34 var err error 35 auth := apiservertesting.FakeAuthorizer{ 36 Tag: s.AdminUserTag(c), 37 } 38 s.client, err = action.NewActionAPI(s.State, nil, auth) 39 c.Assert(err, jc.ErrorIsNil) 40 } 41 42 func (s *runSuite) addMachine(c *gc.C) *state.Machine { 43 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 44 c.Assert(err, jc.ErrorIsNil) 45 return machine 46 } 47 48 func (s *runSuite) addUnit(c *gc.C, service *state.Service) *state.Unit { 49 unit, err := service.AddUnit() 50 c.Assert(err, jc.ErrorIsNil) 51 err = unit.AssignToNewMachine() 52 c.Assert(err, jc.ErrorIsNil) 53 return unit 54 } 55 56 func (s *runSuite) TestGetAllUnitNames(c *gc.C) { 57 charm := s.AddTestingCharm(c, "dummy") 58 owner := s.AdminUserTag(c) 59 magic, err := s.State.AddService(state.AddServiceArgs{Name: "magic", Owner: owner.String(), Charm: charm}) 60 s.addUnit(c, magic) 61 s.addUnit(c, magic) 62 63 notAssigned, err := s.State.AddService(state.AddServiceArgs{Name: "not-assigned", Owner: owner.String(), Charm: charm}) 64 c.Assert(err, jc.ErrorIsNil) 65 _, err = notAssigned.AddUnit() 66 c.Assert(err, jc.ErrorIsNil) 67 68 _, err = s.State.AddService(state.AddServiceArgs{Name: "no-units", Owner: owner.String(), Charm: charm}) 69 c.Assert(err, jc.ErrorIsNil) 70 71 wordpress, err := s.State.AddService(state.AddServiceArgs{Name: "wordpress", Owner: owner.String(), Charm: s.AddTestingCharm(c, "wordpress")}) 72 c.Assert(err, jc.ErrorIsNil) 73 wordpress0 := s.addUnit(c, wordpress) 74 _, err = s.State.AddService(state.AddServiceArgs{Name: "logging", Owner: owner.String(), Charm: s.AddTestingCharm(c, "logging")}) 75 c.Assert(err, jc.ErrorIsNil) 76 77 eps, err := s.State.InferEndpoints("logging", "wordpress") 78 c.Assert(err, jc.ErrorIsNil) 79 rel, err := s.State.AddRelation(eps...) 80 c.Assert(err, jc.ErrorIsNil) 81 ru, err := rel.Unit(wordpress0) 82 c.Assert(err, jc.ErrorIsNil) 83 err = ru.EnterScope(nil) 84 c.Assert(err, jc.ErrorIsNil) 85 86 for i, test := range []struct { 87 message string 88 expected []string 89 units []string 90 services []string 91 error string 92 }{{ 93 message: "no units, expected nil slice", 94 }, { 95 message: "asking for a service that isn't there", 96 services: []string{"foo"}, 97 error: `service "foo" not found`, 98 }, { 99 message: "service with no units is not really an error", 100 services: []string{"no-units"}, 101 }, { 102 message: "A service with units", 103 services: []string{"magic"}, 104 expected: []string{"magic/0", "magic/1"}, 105 }, { 106 message: "Asking for just a unit", 107 units: []string{"magic/0"}, 108 expected: []string{"magic/0"}, 109 }, { 110 message: "Asking for just a subordinate unit", 111 units: []string{"logging/0"}, 112 expected: []string{"logging/0"}, 113 }, { 114 message: "Asking for a unit, and the service", 115 services: []string{"magic"}, 116 units: []string{"magic/0"}, 117 expected: []string{"magic/0", "magic/1"}, 118 }} { 119 c.Logf("%v: %s", i, test.message) 120 result, err := action.GetAllUnitNames(s.State, test.units, test.services) 121 if test.error == "" { 122 c.Check(err, jc.ErrorIsNil) 123 var units []string 124 for _, unit := range result { 125 units = append(units, unit.Id()) 126 } 127 c.Check(units, jc.SameContents, test.expected) 128 } else { 129 c.Check(err, gc.ErrorMatches, test.error) 130 } 131 } 132 } 133 134 func (s *runSuite) AssertBlocked(c *gc.C, err error, msg string) { 135 c.Assert(params.IsCodeOperationBlocked(err), jc.IsTrue, gc.Commentf("error: %#v", err)) 136 c.Assert(errors.Cause(err), gc.DeepEquals, ¶ms.Error{ 137 Message: msg, 138 Code: "operation is blocked", 139 }) 140 } 141 142 func (s *runSuite) TestBlockRunOnAllMachines(c *gc.C) { 143 // block all changes 144 s.BlockAllChanges(c, "TestBlockRunOnAllMachines") 145 _, err := s.client.RunOnAllMachines( 146 params.RunParams{ 147 Commands: "hostname", 148 Timeout: testing.LongWait, 149 }) 150 s.AssertBlocked(c, err, "TestBlockRunOnAllMachines") 151 } 152 153 func (s *runSuite) TestBlockRunMachineAndService(c *gc.C) { 154 // block all changes 155 s.BlockAllChanges(c, "TestBlockRunMachineAndService") 156 _, err := s.client.Run( 157 params.RunParams{ 158 Commands: "hostname", 159 Timeout: testing.LongWait, 160 Machines: []string{"0"}, 161 Services: []string{"magic"}, 162 }) 163 s.AssertBlocked(c, err, "TestBlockRunMachineAndService") 164 } 165 166 func (s *runSuite) TestRunMachineAndService(c *gc.C) { 167 // We only test that we create the actions correctly 168 // There is no need to test anything else at this level. 169 expectedPayload := map[string]interface{}{ 170 "command": "hostname", 171 "timeout": int64(0), 172 } 173 expectedArgs := params.Actions{ 174 Actions: []params.Action{ 175 {Receiver: "unit-magic-0", Name: "juju-run", Parameters: expectedPayload}, 176 {Receiver: "unit-magic-1", Name: "juju-run", Parameters: expectedPayload}, 177 {Receiver: "machine-0", Name: "juju-run", Parameters: expectedPayload}, 178 }, 179 } 180 called := false 181 s.PatchValue(action.QueueActions, func(client *action.ActionAPI, args params.Actions) (params.ActionResults, error) { 182 called = true 183 c.Assert(args, jc.DeepEquals, expectedArgs) 184 return params.ActionResults{}, nil 185 }) 186 187 s.addMachine(c) 188 189 charm := s.AddTestingCharm(c, "dummy") 190 owner := s.Factory.MakeUser(c, nil).Tag() 191 magic, err := s.State.AddService(state.AddServiceArgs{Name: "magic", Owner: owner.String(), Charm: charm}) 192 c.Assert(err, jc.ErrorIsNil) 193 s.addUnit(c, magic) 194 s.addUnit(c, magic) 195 196 s.client.Run( 197 params.RunParams{ 198 Commands: "hostname", 199 Machines: []string{"0"}, 200 Services: []string{"magic"}, 201 }) 202 c.Assert(called, jc.IsTrue) 203 } 204 205 func (s *runSuite) TestRunOnAllMachines(c *gc.C) { 206 // We only test that we create the actions correctly 207 // There is no need to test anything else at this level. 208 expectedPayload := map[string]interface{}{ 209 "command": "hostname", 210 "timeout": testing.LongWait.Nanoseconds(), 211 } 212 expectedArgs := params.Actions{ 213 Actions: []params.Action{ 214 {Receiver: "machine-0", Name: "juju-run", Parameters: expectedPayload}, 215 {Receiver: "machine-1", Name: "juju-run", Parameters: expectedPayload}, 216 {Receiver: "machine-2", Name: "juju-run", Parameters: expectedPayload}, 217 }, 218 } 219 called := false 220 s.PatchValue(action.QueueActions, func(client *action.ActionAPI, args params.Actions) (params.ActionResults, error) { 221 called = true 222 c.Assert(args, jc.DeepEquals, expectedArgs) 223 return params.ActionResults{}, nil 224 }) 225 // Make three machines. 226 s.addMachine(c) 227 s.addMachine(c) 228 s.addMachine(c) 229 230 s.client.RunOnAllMachines( 231 params.RunParams{ 232 Commands: "hostname", 233 Timeout: testing.LongWait, 234 }) 235 c.Assert(called, jc.IsTrue) 236 }