github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/api/caasunitprovisioner/client_test.go (about) 1 // Copyright 2017 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package caasunitprovisioner_test 5 6 import ( 7 "github.com/juju/errors" 8 "github.com/juju/testing" 9 jc "github.com/juju/testing/checkers" 10 gc "gopkg.in/check.v1" 11 "gopkg.in/juju/names.v2" 12 13 basetesting "github.com/juju/juju/api/base/testing" 14 "github.com/juju/juju/api/caasunitprovisioner" 15 "github.com/juju/juju/apiserver/params" 16 "github.com/juju/juju/core/application" 17 "github.com/juju/juju/core/constraints" 18 "github.com/juju/juju/core/devices" 19 "github.com/juju/juju/core/life" 20 "github.com/juju/juju/core/status" 21 "github.com/juju/juju/storage" 22 ) 23 24 type unitprovisionerSuite struct { 25 testing.IsolationSuite 26 } 27 28 var _ = gc.Suite(&unitprovisionerSuite{}) 29 30 func newClient(f basetesting.APICallerFunc) *caasunitprovisioner.Client { 31 return caasunitprovisioner.NewClient(basetesting.BestVersionCaller{f, 1}) 32 } 33 34 func (s *unitprovisionerSuite) TestProvisioningInfo(c *gc.C) { 35 apiCaller := basetesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error { 36 c.Check(objType, gc.Equals, "CAASUnitProvisioner") 37 c.Check(version, gc.Equals, 0) 38 c.Check(id, gc.Equals, "") 39 c.Check(request, gc.Equals, "ProvisioningInfo") 40 c.Check(arg, jc.DeepEquals, params.Entities{ 41 Entities: []params.Entity{{ 42 Tag: "application-gitlab", 43 }}, 44 }) 45 c.Assert(result, gc.FitsTypeOf, ¶ms.KubernetesProvisioningInfoResults{}) 46 *(result.(*params.KubernetesProvisioningInfoResults)) = params.KubernetesProvisioningInfoResults{ 47 Results: []params.KubernetesProvisioningInfoResult{{ 48 Result: ¶ms.KubernetesProvisioningInfo{ 49 PodSpec: "foo", 50 Tags: map[string]string{"foo": "bar"}, 51 Placement: "a=b,c=d", 52 Constraints: constraints.MustParse("mem=4G"), 53 Filesystems: []params.KubernetesFilesystemParams{{ 54 StorageName: "database", 55 Size: uint64(100), 56 Provider: "k8s", 57 Tags: map[string]string{"tag": "resource"}, 58 Attributes: map[string]interface{}{"key": "value"}, 59 Attachment: ¶ms.KubernetesFilesystemAttachmentParams{ 60 Provider: "k8s", 61 MountPoint: "/path/to/here", 62 ReadOnly: true, 63 }}, 64 }, 65 Devices: []params.KubernetesDeviceParams{ 66 { 67 Type: "nvidia.com/gpu", 68 Count: 3, 69 Attributes: map[string]string{"gpu": "nvidia-tesla-p100"}, 70 }, 71 }, 72 }, 73 }}, 74 } 75 return nil 76 }) 77 78 client := caasunitprovisioner.NewClient(apiCaller) 79 info, err := client.ProvisioningInfo("gitlab") 80 c.Assert(err, jc.ErrorIsNil) 81 c.Assert(info, jc.DeepEquals, &caasunitprovisioner.ProvisioningInfo{ 82 PodSpec: "foo", 83 Tags: map[string]string{"foo": "bar"}, 84 Placement: "a=b,c=d", 85 Constraints: constraints.MustParse("mem=4G"), 86 Filesystems: []storage.KubernetesFilesystemParams{{ 87 StorageName: "database", 88 Size: uint64(100), 89 Provider: storage.ProviderType("k8s"), 90 ResourceTags: map[string]string{"tag": "resource"}, 91 Attributes: map[string]interface{}{"key": "value"}, 92 Attachment: &storage.KubernetesFilesystemAttachmentParams{ 93 Path: "/path/to/here", 94 AttachmentParams: storage.AttachmentParams{ 95 Provider: storage.ProviderType("k8s"), 96 ReadOnly: true, 97 }, 98 }, 99 }}, 100 Devices: []devices.KubernetesDeviceParams{{ 101 Type: devices.DeviceType("nvidia.com/gpu"), 102 Count: 3, 103 Attributes: map[string]string{"gpu": "nvidia-tesla-p100"}, 104 }}, 105 }) 106 } 107 108 func (s *unitprovisionerSuite) TestProvisioningInfoError(c *gc.C) { 109 apiCaller := basetesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error { 110 *(result.(*params.KubernetesProvisioningInfoResults)) = params.KubernetesProvisioningInfoResults{ 111 Results: []params.KubernetesProvisioningInfoResult{{Error: ¶ms.Error{ 112 Code: params.CodeNotFound, 113 Message: "bletch", 114 }}}, 115 } 116 return nil 117 }) 118 119 client := caasunitprovisioner.NewClient(apiCaller) 120 _, err := client.ProvisioningInfo("gitlab") 121 c.Assert(err, gc.ErrorMatches, "bletch") 122 c.Assert(err, jc.Satisfies, errors.IsNotFound) 123 } 124 125 func (s *unitprovisionerSuite) TestProvisioningInfoNoUnits(c *gc.C) { 126 apiCaller := basetesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error { 127 *(result.(*params.KubernetesProvisioningInfoResults)) = params.KubernetesProvisioningInfoResults{ 128 Results: []params.KubernetesProvisioningInfoResult{{}}, 129 } 130 return nil 131 }) 132 133 client := caasunitprovisioner.NewClient(apiCaller) 134 _, err := client.ProvisioningInfo("gitlab") 135 c.Assert(err, jc.DeepEquals, caasunitprovisioner.ErrNoUnits) 136 } 137 138 func (s *unitprovisionerSuite) TestProvisioningInfoInvalidApplicationName(c *gc.C) { 139 client := caasunitprovisioner.NewClient(basetesting.APICallerFunc(func(_ string, _ int, _, _ string, _, _ interface{}) error { 140 return errors.New("should not be called") 141 })) 142 _, err := client.ProvisioningInfo("gitlab/0") 143 c.Assert(err, gc.ErrorMatches, `application name "gitlab/0" not valid`) 144 } 145 146 func (s *unitprovisionerSuite) TestLife(c *gc.C) { 147 s.testLife(c, names.NewApplicationTag("gitlab")) 148 s.testLife(c, names.NewUnitTag("gitlab/0")) 149 } 150 151 func (s *unitprovisionerSuite) testLife(c *gc.C, tag names.Tag) { 152 apiCaller := basetesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error { 153 c.Check(objType, gc.Equals, "CAASUnitProvisioner") 154 c.Check(version, gc.Equals, 0) 155 c.Check(id, gc.Equals, "") 156 c.Check(request, gc.Equals, "Life") 157 c.Check(arg, jc.DeepEquals, params.Entities{ 158 Entities: []params.Entity{{ 159 Tag: tag.String(), 160 }}, 161 }) 162 c.Assert(result, gc.FitsTypeOf, ¶ms.LifeResults{}) 163 *(result.(*params.LifeResults)) = params.LifeResults{ 164 Results: []params.LifeResult{{ 165 Life: params.Alive, 166 }}, 167 } 168 return nil 169 }) 170 171 client := caasunitprovisioner.NewClient(apiCaller) 172 lifeValue, err := client.Life(tag.Id()) 173 c.Assert(err, jc.ErrorIsNil) 174 c.Assert(lifeValue, gc.Equals, life.Alive) 175 } 176 177 func (s *unitprovisionerSuite) TestLifeError(c *gc.C) { 178 apiCaller := basetesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error { 179 *(result.(*params.LifeResults)) = params.LifeResults{ 180 Results: []params.LifeResult{{Error: ¶ms.Error{ 181 Code: params.CodeNotFound, 182 Message: "bletch", 183 }}}, 184 } 185 return nil 186 }) 187 188 client := caasunitprovisioner.NewClient(apiCaller) 189 _, err := client.Life("gitlab/0") 190 c.Assert(err, gc.ErrorMatches, "bletch") 191 c.Assert(err, jc.Satisfies, errors.IsNotFound) 192 } 193 194 func (s *unitprovisionerSuite) TestLifeInvalidEntityame(c *gc.C) { 195 client := caasunitprovisioner.NewClient(basetesting.APICallerFunc(func(_ string, _ int, _, _ string, _, _ interface{}) error { 196 return errors.New("should not be called") 197 })) 198 _, err := client.Life("") 199 c.Assert(err, gc.ErrorMatches, `application or unit name "" not valid`) 200 } 201 202 func (s *unitprovisionerSuite) TestWatchApplications(c *gc.C) { 203 apiCaller := basetesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error { 204 c.Check(objType, gc.Equals, "CAASUnitProvisioner") 205 c.Check(version, gc.Equals, 0) 206 c.Check(id, gc.Equals, "") 207 c.Check(request, gc.Equals, "WatchApplications") 208 c.Assert(result, gc.FitsTypeOf, ¶ms.StringsWatchResult{}) 209 *(result.(*params.StringsWatchResult)) = params.StringsWatchResult{ 210 Error: ¶ms.Error{Message: "FAIL"}, 211 } 212 return nil 213 }) 214 215 client := caasunitprovisioner.NewClient(apiCaller) 216 watcher, err := client.WatchApplications() 217 c.Assert(watcher, gc.IsNil) 218 c.Assert(err, gc.ErrorMatches, "FAIL") 219 } 220 221 func (s *unitprovisionerSuite) TestWatchApplicationScale(c *gc.C) { 222 apiCaller := basetesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error { 223 c.Check(objType, gc.Equals, "CAASUnitProvisioner") 224 c.Check(version, gc.Equals, 0) 225 c.Check(id, gc.Equals, "") 226 c.Check(request, gc.Equals, "WatchApplicationsScale") 227 c.Assert(arg, jc.DeepEquals, params.Entities{ 228 Entities: []params.Entity{{ 229 Tag: "application-gitlab", 230 }}, 231 }) 232 c.Assert(result, gc.FitsTypeOf, ¶ms.NotifyWatchResults{}) 233 *(result.(*params.NotifyWatchResults)) = params.NotifyWatchResults{ 234 Results: []params.NotifyWatchResult{{ 235 Error: ¶ms.Error{Message: "FAIL"}, 236 }}, 237 } 238 return nil 239 }) 240 241 client := caasunitprovisioner.NewClient(apiCaller) 242 watcher, err := client.WatchApplicationScale("gitlab") 243 c.Assert(watcher, gc.IsNil) 244 c.Assert(err, gc.ErrorMatches, "FAIL") 245 } 246 247 func (s *unitprovisionerSuite) TestApplicationScale(c *gc.C) { 248 apiCaller := basetesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error { 249 c.Check(objType, gc.Equals, "CAASUnitProvisioner") 250 c.Check(version, gc.Equals, 0) 251 c.Check(id, gc.Equals, "") 252 c.Check(request, gc.Equals, "ApplicationsScale") 253 c.Assert(arg, jc.DeepEquals, params.Entities{ 254 Entities: []params.Entity{{ 255 Tag: "application-gitlab", 256 }}, 257 }) 258 c.Assert(result, gc.FitsTypeOf, ¶ms.IntResults{}) 259 *(result.(*params.IntResults)) = params.IntResults{ 260 Results: []params.IntResult{{ 261 Result: 5, 262 }}, 263 } 264 return nil 265 }) 266 267 client := caasunitprovisioner.NewClient(apiCaller) 268 scale, err := client.ApplicationScale("gitlab") 269 c.Assert(err, jc.ErrorIsNil) 270 c.Assert(scale, gc.Equals, 5) 271 } 272 273 func (s *unitprovisionerSuite) TestWatchPodSpec(c *gc.C) { 274 apiCaller := basetesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error { 275 c.Check(objType, gc.Equals, "CAASUnitProvisioner") 276 c.Check(version, gc.Equals, 0) 277 c.Check(id, gc.Equals, "") 278 c.Check(request, gc.Equals, "WatchPodSpec") 279 c.Assert(arg, jc.DeepEquals, params.Entities{ 280 Entities: []params.Entity{{ 281 Tag: "application-gitlab", 282 }}, 283 }) 284 c.Assert(result, gc.FitsTypeOf, ¶ms.NotifyWatchResults{}) 285 *(result.(*params.NotifyWatchResults)) = params.NotifyWatchResults{ 286 Results: []params.NotifyWatchResult{{ 287 Error: ¶ms.Error{Message: "FAIL"}, 288 }}, 289 } 290 return nil 291 }) 292 293 client := caasunitprovisioner.NewClient(apiCaller) 294 watcher, err := client.WatchPodSpec("gitlab") 295 c.Assert(watcher, gc.IsNil) 296 c.Assert(err, gc.ErrorMatches, "FAIL") 297 } 298 299 func (s *unitprovisionerSuite) TestApplicationConfig(c *gc.C) { 300 apiCaller := basetesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error { 301 c.Check(objType, gc.Equals, "CAASUnitProvisioner") 302 c.Check(version, gc.Equals, 0) 303 c.Check(id, gc.Equals, "") 304 c.Check(request, gc.Equals, "ApplicationsConfig") 305 c.Assert(arg, jc.DeepEquals, params.Entities{ 306 Entities: []params.Entity{{ 307 Tag: "application-gitlab", 308 }}, 309 }) 310 c.Assert(result, gc.FitsTypeOf, ¶ms.ApplicationGetConfigResults{}) 311 *(result.(*params.ApplicationGetConfigResults)) = params.ApplicationGetConfigResults{ 312 Results: []params.ConfigResult{{ 313 Config: map[string]interface{}{"foo": "bar"}, 314 }}, 315 } 316 return nil 317 }) 318 319 client := caasunitprovisioner.NewClient(apiCaller) 320 cfg, err := client.ApplicationConfig("gitlab") 321 c.Assert(err, jc.ErrorIsNil) 322 c.Assert(cfg, jc.DeepEquals, application.ConfigAttributes{"foo": "bar"}) 323 } 324 325 func (s *unitprovisionerSuite) TestUpdateUnits(c *gc.C) { 326 var called bool 327 client := newClient(func(objType string, version int, id, request string, a, result interface{}) error { 328 called = true 329 c.Check(objType, gc.Equals, "CAASUnitProvisioner") 330 c.Check(id, gc.Equals, "") 331 c.Assert(request, gc.Equals, "UpdateApplicationsUnits") 332 c.Assert(a, jc.DeepEquals, params.UpdateApplicationUnitArgs{ 333 Args: []params.UpdateApplicationUnits{ 334 { 335 ApplicationTag: "application-app", 336 Units: []params.ApplicationUnitParams{ 337 {ProviderId: "uuid", UnitTag: "unit-gitlab-0", Address: "address", Ports: []string{"port"}, 338 Status: "active", Info: "message"}, 339 }, 340 }, 341 }, 342 }) 343 c.Assert(result, gc.FitsTypeOf, ¶ms.ErrorResults{}) 344 *(result.(*params.ErrorResults)) = params.ErrorResults{ 345 Results: []params.ErrorResult{{}}, 346 } 347 return nil 348 }) 349 err := client.UpdateUnits(params.UpdateApplicationUnits{ 350 ApplicationTag: names.NewApplicationTag("app").String(), 351 Units: []params.ApplicationUnitParams{ 352 {ProviderId: "uuid", UnitTag: "unit-gitlab-0", Address: "address", Ports: []string{"port"}, 353 Status: "active", Info: "message"}, 354 }, 355 }) 356 c.Check(err, jc.ErrorIsNil) 357 c.Check(called, jc.IsTrue) 358 } 359 360 func (s *unitprovisionerSuite) TestUpdateUnitsCount(c *gc.C) { 361 client := newClient(func(objType string, version int, id, request string, a, result interface{}) error { 362 *(result.(*params.ErrorResults)) = params.ErrorResults{ 363 Results: []params.ErrorResult{ 364 {Error: ¶ms.Error{Message: "FAIL"}}, 365 {Error: ¶ms.Error{Message: "FAIL"}}, 366 }, 367 } 368 return nil 369 }) 370 err := client.UpdateUnits(params.UpdateApplicationUnits{ 371 ApplicationTag: names.NewApplicationTag("app").String(), 372 Units: []params.ApplicationUnitParams{ 373 {ProviderId: "uuid", Address: "address"}, 374 }, 375 }) 376 c.Check(err, gc.ErrorMatches, `expected 1 result\(s\), got 2`) 377 } 378 379 func (s *unitprovisionerSuite) TestUpdateApplicationService(c *gc.C) { 380 var called bool 381 client := newClient(func(objType string, version int, id, request string, a, result interface{}) error { 382 called = true 383 c.Check(objType, gc.Equals, "CAASUnitProvisioner") 384 c.Check(id, gc.Equals, "") 385 c.Assert(request, gc.Equals, "UpdateApplicationsService") 386 c.Assert(a, jc.DeepEquals, params.UpdateApplicationServiceArgs{ 387 Args: []params.UpdateApplicationServiceArg{ 388 { 389 ApplicationTag: "application-app", 390 ProviderId: "id", 391 Addresses: []params.Address{{Value: "10.0.0.1"}}, 392 }, 393 }, 394 }) 395 c.Assert(result, gc.FitsTypeOf, ¶ms.ErrorResults{}) 396 *(result.(*params.ErrorResults)) = params.ErrorResults{ 397 Results: []params.ErrorResult{{}}, 398 } 399 return nil 400 }) 401 err := client.UpdateApplicationService(params.UpdateApplicationServiceArg{ 402 ApplicationTag: names.NewApplicationTag("app").String(), 403 ProviderId: "id", 404 Addresses: []params.Address{{Value: "10.0.0.1"}}, 405 }) 406 c.Check(err, jc.ErrorIsNil) 407 c.Check(called, jc.IsTrue) 408 } 409 410 func (s *unitprovisionerSuite) TestUpdateApplicationServiceCount(c *gc.C) { 411 client := newClient(func(objType string, version int, id, request string, a, result interface{}) error { 412 *(result.(*params.ErrorResults)) = params.ErrorResults{ 413 Results: []params.ErrorResult{ 414 {Error: ¶ms.Error{Message: "FAIL"}}, 415 {Error: ¶ms.Error{Message: "FAIL"}}, 416 }, 417 } 418 return nil 419 }) 420 err := client.UpdateApplicationService(params.UpdateApplicationServiceArg{ 421 ApplicationTag: names.NewApplicationTag("app").String(), 422 ProviderId: "id", 423 Addresses: []params.Address{{Value: "10.0.0.1"}}, 424 }) 425 c.Check(err, gc.ErrorMatches, `expected 1 result\(s\), got 2`) 426 } 427 428 func (s *unitprovisionerSuite) TestSetOperatorStatus(c *gc.C) { 429 apiCaller := basetesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error { 430 c.Check(objType, gc.Equals, "CAASUnitProvisioner") 431 c.Check(version, gc.Equals, 0) 432 c.Check(id, gc.Equals, "") 433 c.Check(request, gc.Equals, "SetOperatorStatus") 434 c.Assert(arg, jc.DeepEquals, params.SetStatus{ 435 Entities: []params.EntityStatusArgs{{ 436 Tag: "application-gitlab", 437 Status: "error", 438 Info: "broken", 439 Data: map[string]interface{}{"foo": "bar"}, 440 }}, 441 }) 442 c.Assert(result, gc.FitsTypeOf, ¶ms.ErrorResults{}) 443 *(result.(*params.ErrorResults)) = params.ErrorResults{ 444 Results: []params.ErrorResult{{ 445 Error: ¶ms.Error{Message: "FAIL"}, 446 }}, 447 } 448 return nil 449 }) 450 451 client := caasunitprovisioner.NewClient(apiCaller) 452 err := client.SetOperatorStatus("gitlab", status.Error, "broken", map[string]interface{}{"foo": "bar"}) 453 c.Assert(err, gc.ErrorMatches, "FAIL") 454 }