github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/api/agent/uniter/action_test.go (about) 1 // Copyright 2014 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package uniter_test 5 6 import ( 7 "github.com/juju/errors" 8 "github.com/juju/names/v5" 9 jc "github.com/juju/testing/checkers" 10 gc "gopkg.in/check.v1" 11 12 "github.com/juju/juju/api/agent/uniter" 13 basetesting "github.com/juju/juju/api/base/testing" 14 "github.com/juju/juju/core/watcher/watchertest" 15 "github.com/juju/juju/rpc/params" 16 coretesting "github.com/juju/juju/testing" 17 ) 18 19 type actionSuite struct { 20 coretesting.BaseSuite 21 } 22 23 var _ = gc.Suite(&actionSuite{}) 24 25 func (s *actionSuite) TestAction(c *gc.C) { 26 parallel := true 27 group := "group" 28 actionResult := params.ActionResult{ 29 Action: ¶ms.Action{ 30 Name: "backup", 31 Parameters: map[string]interface{}{"foo": "bar"}, 32 Parallel: ¶llel, 33 ExecutionGroup: &group, 34 }, 35 } 36 apiCaller := basetesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error { 37 c.Assert(objType, gc.Equals, "Uniter") 38 c.Assert(request, gc.Equals, "Actions") 39 c.Assert(arg, gc.DeepEquals, params.Entities{Entities: []params.Entity{{Tag: "action-666"}}}) 40 c.Assert(result, gc.FitsTypeOf, ¶ms.ActionResults{}) 41 *(result.(*params.ActionResults)) = params.ActionResults{ 42 Results: []params.ActionResult{actionResult}, 43 } 44 return nil 45 }) 46 client := uniter.NewState(apiCaller, names.NewUnitTag("mysql/0")) 47 48 a, err := client.Action(names.NewActionTag("666")) 49 c.Assert(err, jc.ErrorIsNil) 50 c.Assert(a.ID(), gc.Equals, "666") 51 c.Assert(a.Name(), gc.Equals, actionResult.Action.Name) 52 c.Assert(a.Params(), jc.DeepEquals, actionResult.Action.Parameters) 53 c.Assert(a.Parallel(), jc.IsTrue) 54 c.Assert(a.ExecutionGroup(), gc.Equals, "group") 55 } 56 57 func (s *actionSuite) TestActionError(c *gc.C) { 58 apiCaller := basetesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error { 59 c.Assert(objType, gc.Equals, "Uniter") 60 c.Assert(request, gc.Equals, "Actions") 61 c.Assert(arg, gc.DeepEquals, params.Entities{Entities: []params.Entity{{Tag: "action-666"}}}) 62 c.Assert(result, gc.FitsTypeOf, ¶ms.ActionResults{}) 63 *(result.(*params.ActionResults)) = params.ActionResults{ 64 Results: []params.ActionResult{{ 65 Error: ¶ms.Error{Message: "boom"}, 66 }}, 67 } 68 return nil 69 }) 70 client := uniter.NewState(apiCaller, names.NewUnitTag("mysql/0")) 71 72 _, err := client.Action(names.NewActionTag("666")) 73 c.Assert(err, gc.ErrorMatches, "boom") 74 } 75 76 func (s *actionSuite) TestActionBegin(c *gc.C) { 77 apiCaller := basetesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error { 78 c.Assert(objType, gc.Equals, "Uniter") 79 c.Assert(request, gc.Equals, "BeginActions") 80 c.Assert(arg, gc.DeepEquals, params.Entities{Entities: []params.Entity{{Tag: "action-666"}}}) 81 c.Assert(result, gc.FitsTypeOf, ¶ms.ErrorResults{}) 82 *(result.(*params.ErrorResults)) = params.ErrorResults{ 83 Results: []params.ErrorResult{{Error: ¶ms.Error{Message: "boom"}}}, 84 } 85 return nil 86 }) 87 client := uniter.NewState(apiCaller, names.NewUnitTag("mysql/0")) 88 err := client.ActionBegin(names.NewActionTag("666")) 89 c.Assert(err, gc.ErrorMatches, "boom") 90 } 91 92 func (s *actionSuite) TestActionFinish(c *gc.C) { 93 apiCaller := basetesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error { 94 c.Assert(objType, gc.Equals, "Uniter") 95 c.Assert(request, gc.Equals, "FinishActions") 96 c.Assert(arg, gc.DeepEquals, params.ActionExecutionResults{Results: []params.ActionExecutionResult{{ 97 ActionTag: "action-666", 98 Status: "failed", 99 Results: map[string]interface{}{"foo": "bar"}, 100 Message: "oops", 101 }}}) 102 c.Assert(result, gc.FitsTypeOf, ¶ms.ErrorResults{}) 103 *(result.(*params.ErrorResults)) = params.ErrorResults{ 104 Results: []params.ErrorResult{{Error: ¶ms.Error{Message: "boom"}}}, 105 } 106 return nil 107 }) 108 client := uniter.NewState(apiCaller, names.NewUnitTag("mysql/0")) 109 err := client.ActionFinish(names.NewActionTag("666"), "failed", map[string]interface{}{"foo": "bar"}, "oops") 110 c.Assert(err, gc.ErrorMatches, "boom") 111 } 112 113 func (s *actionSuite) TestActionStatus(c *gc.C) { 114 apiCaller := basetesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error { 115 c.Assert(objType, gc.Equals, "Uniter") 116 c.Assert(request, gc.Equals, "ActionStatus") 117 c.Assert(arg, gc.DeepEquals, params.Entities{Entities: []params.Entity{{Tag: "action-666"}}}) 118 c.Assert(result, gc.FitsTypeOf, ¶ms.StringResults{}) 119 *(result.(*params.StringResults)) = params.StringResults{ 120 Results: []params.StringResult{{Result: "failed"}}, 121 } 122 return nil 123 }) 124 client := uniter.NewState(apiCaller, names.NewUnitTag("mysql/0")) 125 status, err := client.ActionStatus(names.NewActionTag("666")) 126 c.Assert(err, jc.ErrorIsNil) 127 c.Assert(status, gc.Equals, "failed") 128 } 129 130 func (s *actionSuite) TestLogActionMessage(c *gc.C) { 131 apiCaller := basetesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error { 132 c.Assert(objType, gc.Equals, "Uniter") 133 c.Assert(request, gc.Equals, "LogActionsMessages") 134 c.Assert(arg, gc.DeepEquals, params.ActionMessageParams{ 135 Messages: []params.EntityString{{Tag: "action-666", Value: "hello"}}, 136 }) 137 c.Assert(result, gc.FitsTypeOf, ¶ms.ErrorResults{}) 138 *(result.(*params.ErrorResults)) = params.ErrorResults{ 139 Results: []params.ErrorResult{{¶ms.Error{Message: "biff"}}}, 140 } 141 return nil 142 }) 143 caller := basetesting.BestVersionCaller{apiCaller, 12} 144 client := uniter.NewState(caller, names.NewUnitTag("mysql/0")) 145 146 unit := uniter.CreateUnit(client, names.NewUnitTag("mysql/0")) 147 err := unit.LogActionMessage(names.NewActionTag("666"), "hello") 148 c.Assert(err, gc.ErrorMatches, "biff") 149 } 150 151 func (s *actionSuite) TestWatchActionNotifications(c *gc.C) { 152 apiCaller := basetesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error { 153 if objType == "StringsWatcher" { 154 if request != "Next" && request != "Stop" { 155 c.Fatalf("unexpected watcher request %q", request) 156 } 157 return nil 158 } 159 c.Assert(objType, gc.Equals, "Uniter") 160 c.Assert(request, gc.Equals, "WatchActionNotifications") 161 c.Assert(arg, gc.DeepEquals, params.Entities{Entities: []params.Entity{{Tag: "unit-mysql-0"}}}) 162 c.Assert(result, gc.FitsTypeOf, ¶ms.StringsWatchResults{}) 163 *(result.(*params.StringsWatchResults)) = params.StringsWatchResults{ 164 Results: []params.StringsWatchResult{{ 165 StringsWatcherId: "1", 166 Changes: []string{"666"}, 167 }}, 168 } 169 return nil 170 }) 171 client := uniter.NewState(apiCaller, names.NewUnitTag("mysql/0")) 172 173 unit := uniter.CreateUnit(client, names.NewUnitTag("mysql/0")) 174 w, err := unit.WatchActionNotifications() 175 c.Assert(err, jc.ErrorIsNil) 176 wc := watchertest.NewStringsWatcherC(c, w) 177 defer wc.AssertStops() 178 179 // Initial event. 180 wc.AssertChange("666") 181 } 182 183 func (s *actionSuite) TestWatchActionNotificationsError(c *gc.C) { 184 apiCaller := basetesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error { 185 return errors.New("boom") 186 }) 187 client := uniter.NewState(apiCaller, names.NewUnitTag("mysql/0")) 188 189 unit := uniter.CreateUnit(client, names.NewUnitTag("mysql/0")) 190 _, err := unit.WatchActionNotifications() 191 c.Assert(err, gc.ErrorMatches, "boom") 192 } 193 194 func (s *actionSuite) TestWatchActionNotificationsErrorResults(c *gc.C) { 195 apiCaller := basetesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error { 196 c.Assert(objType, gc.Equals, "Uniter") 197 c.Assert(request, gc.Equals, "WatchActionNotifications") 198 c.Assert(arg, gc.DeepEquals, params.Entities{Entities: []params.Entity{{Tag: "unit-mysql-0"}}}) 199 c.Assert(result, gc.FitsTypeOf, ¶ms.StringsWatchResults{}) 200 *(result.(*params.StringsWatchResults)) = params.StringsWatchResults{ 201 Results: []params.StringsWatchResult{{ 202 Error: ¶ms.Error{Message: "boom"}, 203 }}, 204 } 205 return nil 206 }) 207 client := uniter.NewState(apiCaller, names.NewUnitTag("mysql/0")) 208 209 unit := uniter.CreateUnit(client, names.NewUnitTag("mysql/0")) 210 _, err := unit.WatchActionNotifications() 211 c.Assert(err, gc.ErrorMatches, "boom") 212 } 213 214 func (s *actionSuite) TestWatchActionNotificationsNoResults(c *gc.C) { 215 apiCaller := basetesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error { 216 c.Assert(result, gc.FitsTypeOf, ¶ms.StringsWatchResults{}) 217 *(result.(*params.StringsWatchResults)) = params.StringsWatchResults{} 218 return nil 219 }) 220 client := uniter.NewState(apiCaller, names.NewUnitTag("mysql/0")) 221 222 unit := uniter.CreateUnit(client, names.NewUnitTag("mysql/0")) 223 _, err := unit.WatchActionNotifications() 224 c.Assert(err, gc.ErrorMatches, "expected 1 result, got 0") 225 } 226 227 func (s *actionSuite) TestWatchActionNotificationsMoreResults(c *gc.C) { 228 apiCaller := basetesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error { 229 c.Assert(result, gc.FitsTypeOf, ¶ms.StringsWatchResults{}) 230 *(result.(*params.StringsWatchResults)) = params.StringsWatchResults{ 231 Results: []params.StringsWatchResult{{}, {}}, 232 } 233 return nil 234 }) 235 client := uniter.NewState(apiCaller, names.NewUnitTag("mysql/0")) 236 237 unit := uniter.CreateUnit(client, names.NewUnitTag("mysql/0")) 238 _, err := unit.WatchActionNotifications() 239 c.Assert(err, gc.ErrorMatches, "expected 1 result, got 2") 240 }