github.com/altoros/juju-vmware@v0.0.0-20150312064031-f19ae857ccca/apiserver/uniter/uniter_base.go (about) 1 // Copyright 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 // The uniter package implements the API interface used by the uniter 5 // worker. This file contains code common to all API versions. 6 package uniter 7 8 import ( 9 "fmt" 10 "net/url" 11 "path" 12 "time" 13 14 "github.com/juju/errors" 15 "github.com/juju/names" 16 "gopkg.in/juju/charm.v4" 17 18 "github.com/juju/juju/apiserver/common" 19 leadershipapiserver "github.com/juju/juju/apiserver/leadership" 20 "github.com/juju/juju/apiserver/params" 21 "github.com/juju/juju/leadership" 22 "github.com/juju/juju/lease" 23 "github.com/juju/juju/network" 24 "github.com/juju/juju/state" 25 "github.com/juju/juju/state/multiwatcher" 26 "github.com/juju/juju/state/watcher" 27 ) 28 29 // uniterBaseAPI implements common methods used by all API versions, 30 // and it's intended for embedding. 31 type uniterBaseAPI struct { 32 *common.LifeGetter 33 *common.StatusSetter 34 *common.DeadEnsurer 35 *common.AgentEntityWatcher 36 *common.APIAddresser 37 *common.EnvironWatcher 38 *common.RebootRequester 39 *leadershipapiserver.LeadershipSettingsAccessor 40 41 st *state.State 42 auth common.Authorizer 43 resources *common.Resources 44 accessUnit common.GetAuthFunc 45 accessService common.GetAuthFunc 46 unit *state.Unit 47 } 48 49 // newUniterBaseAPI creates a new instance of the uniter base API. 50 func newUniterBaseAPI(st *state.State, resources *common.Resources, authorizer common.Authorizer) (*uniterBaseAPI, error) { 51 if !authorizer.AuthUnitAgent() { 52 return nil, common.ErrPerm 53 } 54 var unit *state.Unit 55 var err error 56 switch tag := authorizer.GetAuthTag().(type) { 57 case names.UnitTag: 58 unit, err = st.Unit(tag.Id()) 59 if err != nil { 60 return nil, errors.Trace(err) 61 } 62 default: 63 return nil, errors.Errorf("expected names.UnitTag, got %T", tag) 64 } 65 accessUnit := func() (common.AuthFunc, error) { 66 return authorizer.AuthOwner, nil 67 } 68 accessService := func() (common.AuthFunc, error) { 69 switch tag := authorizer.GetAuthTag().(type) { 70 case names.UnitTag: 71 entity, err := st.Unit(tag.Id()) 72 if err != nil { 73 return nil, errors.Trace(err) 74 } 75 serviceName := entity.ServiceName() 76 serviceTag := names.NewServiceTag(serviceName) 77 return func(tag names.Tag) bool { 78 return tag == serviceTag 79 }, nil 80 default: 81 return nil, errors.Errorf("expected names.UnitTag, got %T", tag) 82 } 83 } 84 accessMachine := func() (common.AuthFunc, error) { 85 machineId, err := unit.AssignedMachineId() 86 if err != nil { 87 return nil, errors.Trace(err) 88 } 89 machine, err := st.Machine(machineId) 90 if err != nil { 91 return nil, errors.Trace(err) 92 } 93 return func(tag names.Tag) bool { 94 return tag == machine.Tag() 95 }, nil 96 } 97 98 accessUnitOrService := common.AuthEither(accessUnit, accessService) 99 return &uniterBaseAPI{ 100 LifeGetter: common.NewLifeGetter(st, accessUnitOrService), 101 StatusSetter: common.NewStatusSetter(st, accessUnit), 102 DeadEnsurer: common.NewDeadEnsurer(st, accessUnit), 103 AgentEntityWatcher: common.NewAgentEntityWatcher(st, resources, accessUnitOrService), 104 APIAddresser: common.NewAPIAddresser(st, resources), 105 EnvironWatcher: common.NewEnvironWatcher(st, resources, authorizer), 106 RebootRequester: common.NewRebootRequester(st, accessMachine), 107 LeadershipSettingsAccessor: leadershipSettingsAccessorFactory(st, resources, authorizer), 108 109 st: st, 110 auth: authorizer, 111 resources: resources, 112 accessUnit: accessUnit, 113 accessService: accessService, 114 unit: unit, 115 }, nil 116 } 117 118 // PublicAddress returns the public address for each given unit, if set. 119 func (u *uniterBaseAPI) PublicAddress(args params.Entities) (params.StringResults, error) { 120 result := params.StringResults{ 121 Results: make([]params.StringResult, len(args.Entities)), 122 } 123 canAccess, err := u.accessUnit() 124 if err != nil { 125 return params.StringResults{}, err 126 } 127 for i, entity := range args.Entities { 128 tag, err := names.ParseUnitTag(entity.Tag) 129 if err != nil { 130 result.Results[i].Error = common.ServerError(common.ErrPerm) 131 continue 132 } 133 err = common.ErrPerm 134 if canAccess(tag) { 135 var unit *state.Unit 136 unit, err = u.getUnit(tag) 137 if err == nil { 138 address, ok := unit.PublicAddress() 139 if ok { 140 result.Results[i].Result = address 141 } else { 142 err = common.NoAddressSetError(tag, "public") 143 } 144 } 145 } 146 result.Results[i].Error = common.ServerError(err) 147 } 148 return result, nil 149 } 150 151 // PrivateAddress returns the private address for each given unit, if set. 152 func (u *uniterBaseAPI) PrivateAddress(args params.Entities) (params.StringResults, error) { 153 result := params.StringResults{ 154 Results: make([]params.StringResult, len(args.Entities)), 155 } 156 canAccess, err := u.accessUnit() 157 if err != nil { 158 return params.StringResults{}, err 159 } 160 for i, entity := range args.Entities { 161 tag, err := names.ParseUnitTag(entity.Tag) 162 if err != nil { 163 result.Results[i].Error = common.ServerError(common.ErrPerm) 164 continue 165 } 166 err = common.ErrPerm 167 if canAccess(tag) { 168 var unit *state.Unit 169 unit, err = u.getUnit(tag) 170 if err == nil { 171 address, ok := unit.PrivateAddress() 172 if ok { 173 result.Results[i].Result = address 174 } else { 175 err = common.NoAddressSetError(tag, "private") 176 } 177 } 178 } 179 result.Results[i].Error = common.ServerError(err) 180 } 181 return result, nil 182 } 183 184 // TODO(ericsnow) Factor out the common code amongst the many methods here. 185 186 var getZone = func(st *state.State, tag names.Tag) (string, error) { 187 unit, err := st.Unit(tag.Id()) 188 if err != nil { 189 return "", errors.Trace(err) 190 } 191 zone, err := unit.AvailabilityZone() 192 return zone, errors.Trace(err) 193 } 194 195 // AvailabilityZone returns the availability zone for each given unit, if applicable. 196 func (u *uniterBaseAPI) AvailabilityZone(args params.Entities) (params.StringResults, error) { 197 var results params.StringResults 198 199 canAccess, err := u.accessUnit() 200 if err != nil { 201 return results, errors.Trace(err) 202 } 203 204 // Prep the results. 205 results = params.StringResults{ 206 Results: make([]params.StringResult, len(args.Entities)), 207 } 208 209 // Collect the zones. No zone will be collected for any entity where 210 // the tag is invalid or not authorized. Instead the corresponding 211 // result will be updated with the error. 212 for i, entity := range args.Entities { 213 tag, err := names.ParseUnitTag(entity.Tag) 214 if err != nil { 215 results.Results[i].Error = common.ServerError(common.ErrPerm) 216 continue 217 } 218 err = common.ErrPerm 219 if canAccess(tag) { 220 var zone string 221 zone, err = getZone(u.st, tag) 222 if err == nil { 223 results.Results[i].Result = zone 224 } 225 } 226 results.Results[i].Error = common.ServerError(err) 227 } 228 229 return results, nil 230 } 231 232 // Resolved returns the current resolved setting for each given unit. 233 func (u *uniterBaseAPI) Resolved(args params.Entities) (params.ResolvedModeResults, error) { 234 result := params.ResolvedModeResults{ 235 Results: make([]params.ResolvedModeResult, len(args.Entities)), 236 } 237 canAccess, err := u.accessUnit() 238 if err != nil { 239 return params.ResolvedModeResults{}, err 240 } 241 for i, entity := range args.Entities { 242 tag, err := names.ParseUnitTag(entity.Tag) 243 if err != nil { 244 result.Results[i].Error = common.ServerError(common.ErrPerm) 245 continue 246 } 247 err = common.ErrPerm 248 if canAccess(tag) { 249 var unit *state.Unit 250 unit, err = u.getUnit(tag) 251 if err == nil { 252 result.Results[i].Mode = params.ResolvedMode(unit.Resolved()) 253 } 254 } 255 result.Results[i].Error = common.ServerError(err) 256 } 257 return result, nil 258 } 259 260 // ClearResolved removes any resolved setting from each given unit. 261 func (u *uniterBaseAPI) ClearResolved(args params.Entities) (params.ErrorResults, error) { 262 result := params.ErrorResults{ 263 Results: make([]params.ErrorResult, len(args.Entities)), 264 } 265 canAccess, err := u.accessUnit() 266 if err != nil { 267 return params.ErrorResults{}, err 268 } 269 for i, entity := range args.Entities { 270 tag, err := names.ParseUnitTag(entity.Tag) 271 if err != nil { 272 result.Results[i].Error = common.ServerError(common.ErrPerm) 273 continue 274 } 275 err = common.ErrPerm 276 if canAccess(tag) { 277 var unit *state.Unit 278 unit, err = u.getUnit(tag) 279 if err == nil { 280 err = unit.ClearResolved() 281 } 282 } 283 result.Results[i].Error = common.ServerError(err) 284 } 285 return result, nil 286 } 287 288 // GetPrincipal returns the result of calling PrincipalName() and 289 // converting it to a tag, on each given unit. 290 func (u *uniterBaseAPI) GetPrincipal(args params.Entities) (params.StringBoolResults, error) { 291 result := params.StringBoolResults{ 292 Results: make([]params.StringBoolResult, len(args.Entities)), 293 } 294 canAccess, err := u.accessUnit() 295 if err != nil { 296 return params.StringBoolResults{}, err 297 } 298 for i, entity := range args.Entities { 299 tag, err := names.ParseUnitTag(entity.Tag) 300 if err != nil { 301 result.Results[i].Error = common.ServerError(common.ErrPerm) 302 continue 303 } 304 err = common.ErrPerm 305 if canAccess(tag) { 306 var unit *state.Unit 307 unit, err = u.getUnit(tag) 308 if err == nil { 309 principal, ok := unit.PrincipalName() 310 if principal != "" { 311 result.Results[i].Result = names.NewUnitTag(principal).String() 312 } 313 result.Results[i].Ok = ok 314 } 315 } 316 result.Results[i].Error = common.ServerError(err) 317 } 318 return result, nil 319 } 320 321 // Destroy advances all given Alive units' lifecycles as far as 322 // possible. See state/Unit.Destroy(). 323 func (u *uniterBaseAPI) Destroy(args params.Entities) (params.ErrorResults, error) { 324 result := params.ErrorResults{ 325 Results: make([]params.ErrorResult, len(args.Entities)), 326 } 327 canAccess, err := u.accessUnit() 328 if err != nil { 329 return params.ErrorResults{}, err 330 } 331 for i, entity := range args.Entities { 332 tag, err := names.ParseUnitTag(entity.Tag) 333 if err != nil { 334 result.Results[i].Error = common.ServerError(common.ErrPerm) 335 continue 336 } 337 err = common.ErrPerm 338 if canAccess(tag) { 339 var unit *state.Unit 340 unit, err = u.getUnit(tag) 341 if err == nil { 342 err = unit.Destroy() 343 } 344 } 345 result.Results[i].Error = common.ServerError(err) 346 } 347 return result, nil 348 } 349 350 // DestroyAllSubordinates destroys all subordinates of each given unit. 351 func (u *uniterBaseAPI) DestroyAllSubordinates(args params.Entities) (params.ErrorResults, error) { 352 result := params.ErrorResults{ 353 Results: make([]params.ErrorResult, len(args.Entities)), 354 } 355 canAccess, err := u.accessUnit() 356 if err != nil { 357 return params.ErrorResults{}, err 358 } 359 for i, entity := range args.Entities { 360 tag, err := names.ParseUnitTag(entity.Tag) 361 if err != nil { 362 result.Results[i].Error = common.ServerError(common.ErrPerm) 363 continue 364 } 365 err = common.ErrPerm 366 if canAccess(tag) { 367 var unit *state.Unit 368 unit, err = u.getUnit(tag) 369 if err == nil { 370 err = u.destroySubordinates(unit) 371 } 372 } 373 result.Results[i].Error = common.ServerError(err) 374 } 375 return result, nil 376 } 377 378 // HasSubordinates returns the whether each given unit has any subordinates. 379 func (u *uniterBaseAPI) HasSubordinates(args params.Entities) (params.BoolResults, error) { 380 result := params.BoolResults{ 381 Results: make([]params.BoolResult, len(args.Entities)), 382 } 383 canAccess, err := u.accessUnit() 384 if err != nil { 385 return params.BoolResults{}, err 386 } 387 for i, entity := range args.Entities { 388 tag, err := names.ParseUnitTag(entity.Tag) 389 if err != nil { 390 result.Results[i].Error = common.ServerError(common.ErrPerm) 391 continue 392 } 393 err = common.ErrPerm 394 if canAccess(tag) { 395 var unit *state.Unit 396 unit, err = u.getUnit(tag) 397 if err == nil { 398 subordinates := unit.SubordinateNames() 399 result.Results[i].Result = len(subordinates) > 0 400 } 401 } 402 result.Results[i].Error = common.ServerError(err) 403 } 404 return result, nil 405 } 406 407 // CharmURL returns the charm URL for all given units or services. 408 func (u *uniterBaseAPI) CharmURL(args params.Entities) (params.StringBoolResults, error) { 409 result := params.StringBoolResults{ 410 Results: make([]params.StringBoolResult, len(args.Entities)), 411 } 412 accessUnitOrService := common.AuthEither(u.accessUnit, u.accessService) 413 canAccess, err := accessUnitOrService() 414 if err != nil { 415 return params.StringBoolResults{}, err 416 } 417 for i, entity := range args.Entities { 418 tag, err := names.ParseTag(entity.Tag) 419 if err != nil { 420 result.Results[i].Error = common.ServerError(common.ErrPerm) 421 continue 422 } 423 err = common.ErrPerm 424 if canAccess(tag) { 425 var unitOrService state.Entity 426 unitOrService, err = u.st.FindEntity(tag) 427 if err == nil { 428 charmURLer := unitOrService.(interface { 429 CharmURL() (*charm.URL, bool) 430 }) 431 curl, ok := charmURLer.CharmURL() 432 if curl != nil { 433 result.Results[i].Result = curl.String() 434 result.Results[i].Ok = ok 435 } 436 } 437 } 438 result.Results[i].Error = common.ServerError(err) 439 } 440 return result, nil 441 } 442 443 // SetCharmURL sets the charm URL for each given unit. An error will 444 // be returned if a unit is dead, or the charm URL is not know. 445 func (u *uniterBaseAPI) SetCharmURL(args params.EntitiesCharmURL) (params.ErrorResults, error) { 446 result := params.ErrorResults{ 447 Results: make([]params.ErrorResult, len(args.Entities)), 448 } 449 canAccess, err := u.accessUnit() 450 if err != nil { 451 return params.ErrorResults{}, err 452 } 453 for i, entity := range args.Entities { 454 tag, err := names.ParseUnitTag(entity.Tag) 455 if err != nil { 456 result.Results[i].Error = common.ServerError(common.ErrPerm) 457 continue 458 } 459 err = common.ErrPerm 460 if canAccess(tag) { 461 var unit *state.Unit 462 unit, err = u.getUnit(tag) 463 if err == nil { 464 var curl *charm.URL 465 curl, err = charm.ParseURL(entity.CharmURL) 466 if err == nil { 467 err = unit.SetCharmURL(curl) 468 } 469 } 470 } 471 result.Results[i].Error = common.ServerError(err) 472 } 473 return result, nil 474 } 475 476 // OpenPorts sets the policy of the port range with protocol to be 477 // opened, for all given units. 478 func (u *uniterBaseAPI) OpenPorts(args params.EntitiesPortRanges) (params.ErrorResults, error) { 479 result := params.ErrorResults{ 480 Results: make([]params.ErrorResult, len(args.Entities)), 481 } 482 canAccess, err := u.accessUnit() 483 if err != nil { 484 return params.ErrorResults{}, err 485 } 486 for i, entity := range args.Entities { 487 tag, err := names.ParseUnitTag(entity.Tag) 488 if err != nil { 489 result.Results[i].Error = common.ServerError(common.ErrPerm) 490 continue 491 } 492 err = common.ErrPerm 493 if canAccess(tag) { 494 var unit *state.Unit 495 unit, err = u.getUnit(tag) 496 if err == nil { 497 err = unit.OpenPorts(entity.Protocol, entity.FromPort, entity.ToPort) 498 } 499 } 500 result.Results[i].Error = common.ServerError(err) 501 } 502 return result, nil 503 } 504 505 // ClosePorts sets the policy of the port range with protocol to be 506 // closed, for all given units. 507 func (u *uniterBaseAPI) ClosePorts(args params.EntitiesPortRanges) (params.ErrorResults, error) { 508 result := params.ErrorResults{ 509 Results: make([]params.ErrorResult, len(args.Entities)), 510 } 511 canAccess, err := u.accessUnit() 512 if err != nil { 513 return params.ErrorResults{}, err 514 } 515 for i, entity := range args.Entities { 516 tag, err := names.ParseUnitTag(entity.Tag) 517 if err != nil { 518 result.Results[i].Error = common.ServerError(common.ErrPerm) 519 continue 520 } 521 err = common.ErrPerm 522 if canAccess(tag) { 523 var unit *state.Unit 524 unit, err = u.getUnit(tag) 525 if err == nil { 526 err = unit.ClosePorts(entity.Protocol, entity.FromPort, entity.ToPort) 527 } 528 } 529 result.Results[i].Error = common.ServerError(err) 530 } 531 return result, nil 532 } 533 534 // OpenPort sets the policy of the port with protocol an number to be 535 // opened, for all given units. 536 // 537 // TODO(dimitern): This is deprecated and is kept for 538 // backwards-compatibility. Use OpenPorts instead. 539 func (u *uniterBaseAPI) OpenPort(args params.EntitiesPorts) (params.ErrorResults, error) { 540 rangesArgs := params.EntitiesPortRanges{ 541 Entities: make([]params.EntityPortRange, len(args.Entities)), 542 } 543 for i, entity := range args.Entities { 544 rangesArgs.Entities[i] = params.EntityPortRange{ 545 Tag: entity.Tag, 546 Protocol: entity.Protocol, 547 FromPort: entity.Port, 548 ToPort: entity.Port, 549 } 550 } 551 return u.OpenPorts(rangesArgs) 552 } 553 554 // ClosePort sets the policy of the port with protocol and number to 555 // be closed, for all given units. 556 // 557 // TODO(dimitern): This is deprecated and is kept for 558 // backwards-compatibility. Use ClosePorts instead. 559 func (u *uniterBaseAPI) ClosePort(args params.EntitiesPorts) (params.ErrorResults, error) { 560 rangesArgs := params.EntitiesPortRanges{ 561 Entities: make([]params.EntityPortRange, len(args.Entities)), 562 } 563 for i, entity := range args.Entities { 564 rangesArgs.Entities[i] = params.EntityPortRange{ 565 Tag: entity.Tag, 566 Protocol: entity.Protocol, 567 FromPort: entity.Port, 568 ToPort: entity.Port, 569 } 570 } 571 return u.ClosePorts(rangesArgs) 572 } 573 574 // WatchConfigSettings returns a NotifyWatcher for observing changes 575 // to each unit's service configuration settings. See also 576 // state/watcher.go:Unit.WatchConfigSettings(). 577 func (u *uniterBaseAPI) WatchConfigSettings(args params.Entities) (params.NotifyWatchResults, error) { 578 result := params.NotifyWatchResults{ 579 Results: make([]params.NotifyWatchResult, len(args.Entities)), 580 } 581 canAccess, err := u.accessUnit() 582 if err != nil { 583 return params.NotifyWatchResults{}, err 584 } 585 for i, entity := range args.Entities { 586 tag, err := names.ParseUnitTag(entity.Tag) 587 if err != nil { 588 result.Results[i].Error = common.ServerError(common.ErrPerm) 589 continue 590 } 591 err = common.ErrPerm 592 watcherId := "" 593 if canAccess(tag) { 594 watcherId, err = u.watchOneUnitConfigSettings(tag) 595 } 596 result.Results[i].NotifyWatcherId = watcherId 597 result.Results[i].Error = common.ServerError(err) 598 } 599 return result, nil 600 } 601 602 // WatchMeterStatus returns a NotifyWatcher for observing changes 603 // to each unit's meter status. 604 func (u *uniterBaseAPI) WatchMeterStatus(args params.Entities) (params.NotifyWatchResults, error) { 605 result := params.NotifyWatchResults{ 606 Results: make([]params.NotifyWatchResult, len(args.Entities)), 607 } 608 canAccess, err := u.accessUnit() 609 if err != nil { 610 return params.NotifyWatchResults{}, err 611 } 612 for i, entity := range args.Entities { 613 tag, err := names.ParseUnitTag(entity.Tag) 614 if err != nil { 615 result.Results[i].Error = common.ServerError(common.ErrPerm) 616 continue 617 } 618 err = common.ErrPerm 619 watcherId := "" 620 if canAccess(tag) { 621 watcherId, err = u.watchOneUnitMeterStatus(tag) 622 } 623 result.Results[i].NotifyWatcherId = watcherId 624 result.Results[i].Error = common.ServerError(err) 625 } 626 return result, nil 627 } 628 629 // WatchActionNotifications returns a StringsWatcher for observing 630 // incoming action calls to a unit. See also state/watcher.go 631 // Unit.WatchActionNotifications(). This method is called from 632 // api/uniter/uniter.go WatchActionNotifications(). 633 func (u *uniterBaseAPI) WatchActionNotifications(args params.Entities) (params.StringsWatchResults, error) { 634 nothing := params.StringsWatchResults{} 635 636 result := params.StringsWatchResults{ 637 Results: make([]params.StringsWatchResult, len(args.Entities)), 638 } 639 canAccess, err := u.accessUnit() 640 if err != nil { 641 return nothing, err 642 } 643 for i, entity := range args.Entities { 644 tag, err := names.ParseUnitTag(entity.Tag) 645 if err != nil { 646 return nothing, err 647 } 648 err = common.ErrPerm 649 if canAccess(tag) { 650 result.Results[i], err = u.watchOneUnitActionNotifications(tag) 651 } 652 result.Results[i].Error = common.ServerError(err) 653 } 654 return result, nil 655 } 656 657 // ConfigSettings returns the complete set of service charm config 658 // settings available to each given unit. 659 func (u *uniterBaseAPI) ConfigSettings(args params.Entities) (params.ConfigSettingsResults, error) { 660 result := params.ConfigSettingsResults{ 661 Results: make([]params.ConfigSettingsResult, len(args.Entities)), 662 } 663 canAccess, err := u.accessUnit() 664 if err != nil { 665 return params.ConfigSettingsResults{}, err 666 } 667 for i, entity := range args.Entities { 668 tag, err := names.ParseUnitTag(entity.Tag) 669 if err != nil { 670 result.Results[i].Error = common.ServerError(common.ErrPerm) 671 continue 672 } 673 err = common.ErrPerm 674 if canAccess(tag) { 675 var unit *state.Unit 676 unit, err = u.getUnit(tag) 677 if err == nil { 678 var settings charm.Settings 679 settings, err = unit.ConfigSettings() 680 if err == nil { 681 result.Results[i].Settings = params.ConfigSettings(settings) 682 } 683 } 684 } 685 result.Results[i].Error = common.ServerError(err) 686 } 687 return result, nil 688 } 689 690 // WatchServiceRelations returns a StringsWatcher, for each given 691 // service, that notifies of changes to the lifecycles of relations 692 // involving that service. 693 func (u *uniterBaseAPI) WatchServiceRelations(args params.Entities) (params.StringsWatchResults, error) { 694 result := params.StringsWatchResults{ 695 Results: make([]params.StringsWatchResult, len(args.Entities)), 696 } 697 canAccess, err := u.accessService() 698 if err != nil { 699 return params.StringsWatchResults{}, err 700 } 701 for i, entity := range args.Entities { 702 tag, err := names.ParseServiceTag(entity.Tag) 703 if err != nil { 704 result.Results[i].Error = common.ServerError(common.ErrPerm) 705 continue 706 } 707 err = common.ErrPerm 708 if canAccess(tag) { 709 result.Results[i], err = u.watchOneServiceRelations(tag) 710 } 711 result.Results[i].Error = common.ServerError(err) 712 } 713 return result, nil 714 } 715 716 // CharmArchiveSha256 returns the SHA256 digest of the charm archive 717 // (bundle) data for each charm url in the given parameters. 718 func (u *uniterBaseAPI) CharmArchiveSha256(args params.CharmURLs) (params.StringResults, error) { 719 result := params.StringResults{ 720 Results: make([]params.StringResult, len(args.URLs)), 721 } 722 for i, arg := range args.URLs { 723 curl, err := charm.ParseURL(arg.URL) 724 if err != nil { 725 err = common.ErrPerm 726 } else { 727 var sch *state.Charm 728 sch, err = u.st.Charm(curl) 729 if errors.IsNotFound(err) { 730 err = common.ErrPerm 731 } 732 if err == nil { 733 result.Results[i].Result = sch.BundleSha256() 734 } 735 } 736 result.Results[i].Error = common.ServerError(err) 737 } 738 return result, nil 739 } 740 741 // CharmArchiveURLs returns the URLS for the charm archive 742 // (bundle) data for each charm url in the given parameters. 743 func (u *uniterBaseAPI) CharmArchiveURLs(args params.CharmURLs) (params.StringsResults, error) { 744 apiHostPorts, err := u.st.APIHostPorts() 745 if err != nil { 746 return params.StringsResults{}, err 747 } 748 envUUID := u.st.EnvironUUID() 749 result := params.StringsResults{ 750 Results: make([]params.StringsResult, len(args.URLs)), 751 } 752 for i, curl := range args.URLs { 753 if _, err := charm.ParseURL(curl.URL); err != nil { 754 result.Results[i].Error = common.ServerError(common.ErrPerm) 755 continue 756 } 757 urlPath := "/" 758 if envUUID != "" { 759 urlPath = path.Join(urlPath, "environment", envUUID) 760 } 761 urlPath = path.Join(urlPath, "charms") 762 archiveURLs := make([]string, len(apiHostPorts)) 763 for j, server := range apiHostPorts { 764 archiveURL := &url.URL{ 765 Scheme: "https", 766 Host: network.SelectInternalHostPort(server, false), 767 Path: urlPath, 768 } 769 q := archiveURL.Query() 770 q.Set("url", curl.URL) 771 q.Set("file", "*") 772 archiveURL.RawQuery = q.Encode() 773 archiveURLs[j] = archiveURL.String() 774 } 775 result.Results[i].Result = archiveURLs 776 } 777 return result, nil 778 } 779 780 // Relation returns information about all given relation/unit pairs, 781 // including their id, key and the local endpoint. 782 func (u *uniterBaseAPI) Relation(args params.RelationUnits) (params.RelationResults, error) { 783 result := params.RelationResults{ 784 Results: make([]params.RelationResult, len(args.RelationUnits)), 785 } 786 canAccess, err := u.accessUnit() 787 if err != nil { 788 return params.RelationResults{}, err 789 } 790 for i, rel := range args.RelationUnits { 791 relParams, err := u.getOneRelation(canAccess, rel.Relation, rel.Unit) 792 if err == nil { 793 result.Results[i] = relParams 794 } 795 result.Results[i].Error = common.ServerError(err) 796 } 797 return result, nil 798 } 799 800 // Actions returns the Actions by Tags passed and ensures that the Unit asking 801 // for them is the same Unit that has the Actions. 802 func (u *uniterBaseAPI) Actions(args params.Entities) (params.ActionsQueryResults, error) { 803 nothing := params.ActionsQueryResults{} 804 805 actionFn, err := u.authAndActionFromTagFn() 806 if err != nil { 807 return nothing, err 808 } 809 810 results := params.ActionsQueryResults{ 811 Results: make([]params.ActionsQueryResult, len(args.Entities)), 812 } 813 814 for i, arg := range args.Entities { 815 action, err := actionFn(arg.Tag) 816 if err != nil { 817 results.Results[i].Error = common.ServerError(err) 818 continue 819 } 820 if action.Status() != state.ActionPending { 821 results.Results[i].Error = common.ServerError(common.ErrActionNotAvailable) 822 continue 823 } 824 results.Results[i].Action.Action = ¶ms.Action{ 825 Name: action.Name(), 826 Parameters: action.Parameters(), 827 } 828 } 829 830 return results, nil 831 } 832 833 // BeginActions marks the actions represented by the passed in Tags as running. 834 func (u *uniterBaseAPI) BeginActions(args params.Entities) (params.ErrorResults, error) { 835 nothing := params.ErrorResults{} 836 837 actionFn, err := u.authAndActionFromTagFn() 838 if err != nil { 839 return nothing, err 840 } 841 842 results := params.ErrorResults{Results: make([]params.ErrorResult, len(args.Entities))} 843 844 for i, arg := range args.Entities { 845 action, err := actionFn(arg.Tag) 846 if err != nil { 847 results.Results[i].Error = common.ServerError(err) 848 continue 849 } 850 851 _, err = action.Begin() 852 if err != nil { 853 results.Results[i].Error = common.ServerError(err) 854 continue 855 } 856 } 857 858 return results, nil 859 } 860 861 // FinishActions saves the result of a completed Action 862 func (u *uniterBaseAPI) FinishActions(args params.ActionExecutionResults) (params.ErrorResults, error) { 863 nothing := params.ErrorResults{} 864 865 actionFn, err := u.authAndActionFromTagFn() 866 if err != nil { 867 return nothing, err 868 } 869 870 results := params.ErrorResults{Results: make([]params.ErrorResult, len(args.Results))} 871 872 for i, arg := range args.Results { 873 action, err := actionFn(arg.ActionTag) 874 if err != nil { 875 results.Results[i].Error = common.ServerError(err) 876 continue 877 } 878 actionResults, err := paramsActionExecutionResultsToStateActionResults(arg) 879 if err != nil { 880 results.Results[i].Error = common.ServerError(err) 881 continue 882 } 883 884 _, err = action.Finish(actionResults) 885 if err != nil { 886 results.Results[i].Error = common.ServerError(err) 887 continue 888 } 889 } 890 891 return results, nil 892 } 893 894 // paramsActionExecutionResultsToStateActionResults does exactly what 895 // the name implies. 896 func paramsActionExecutionResultsToStateActionResults(arg params.ActionExecutionResult) (state.ActionResults, error) { 897 var status state.ActionStatus 898 switch arg.Status { 899 case params.ActionCancelled: 900 status = state.ActionCancelled 901 case params.ActionCompleted: 902 status = state.ActionCompleted 903 case params.ActionFailed: 904 status = state.ActionFailed 905 case params.ActionPending: 906 status = state.ActionPending 907 default: 908 return state.ActionResults{}, errors.Errorf("unrecognized action status '%s'", arg.Status) 909 } 910 return state.ActionResults{ 911 Status: status, 912 Results: arg.Results, 913 Message: arg.Message, 914 }, nil 915 } 916 917 // RelationById returns information about all given relations, 918 // specified by their ids, including their key and the local 919 // endpoint. 920 func (u *uniterBaseAPI) RelationById(args params.RelationIds) (params.RelationResults, error) { 921 result := params.RelationResults{ 922 Results: make([]params.RelationResult, len(args.RelationIds)), 923 } 924 for i, relId := range args.RelationIds { 925 relParams, err := u.getOneRelationById(relId) 926 if err == nil { 927 result.Results[i] = relParams 928 } 929 result.Results[i].Error = common.ServerError(err) 930 } 931 return result, nil 932 } 933 934 // JoinedRelations returns the tags of all relations for which each supplied unit 935 // has entered scope. It should be called RelationsInScope, but it's not convenient 936 // to make that change until we have versioned APIs. 937 func (u *uniterBaseAPI) JoinedRelations(args params.Entities) (params.StringsResults, error) { 938 result := params.StringsResults{ 939 Results: make([]params.StringsResult, len(args.Entities)), 940 } 941 if len(args.Entities) == 0 { 942 return result, nil 943 } 944 canRead, err := u.accessUnit() 945 if err != nil { 946 return params.StringsResults{}, err 947 } 948 for i, entity := range args.Entities { 949 tag, err := names.ParseUnitTag(entity.Tag) 950 if err != nil { 951 result.Results[i].Error = common.ServerError(common.ErrPerm) 952 continue 953 } 954 err = common.ErrPerm 955 if canRead(tag) { 956 var unit *state.Unit 957 unit, err = u.getUnit(tag) 958 if err == nil { 959 result.Results[i].Result, err = relationsInScopeTags(unit) 960 } 961 } 962 result.Results[i].Error = common.ServerError(err) 963 } 964 return result, nil 965 } 966 967 // CurrentEnvironUUID returns the UUID for the current juju environment. 968 func (u *uniterBaseAPI) CurrentEnvironUUID() (params.StringResult, error) { 969 result := params.StringResult{} 970 env, err := u.st.Environment() 971 if err == nil { 972 result.Result = env.UUID() 973 } 974 return result, err 975 } 976 977 // CurrentEnvironment returns the name and UUID for the current juju environment. 978 func (u *uniterBaseAPI) CurrentEnvironment() (params.EnvironmentResult, error) { 979 result := params.EnvironmentResult{} 980 env, err := u.st.Environment() 981 if err == nil { 982 result.Name = env.Name() 983 result.UUID = env.UUID() 984 } 985 return result, err 986 } 987 988 // ProviderType returns the provider type used by the current juju 989 // environment. 990 // 991 // TODO(dimitern): Refactor the uniter to call this instead of calling 992 // EnvironConfig() just to get the provider type. Once we have machine 993 // addresses, this might be completely unnecessary though. 994 func (u *uniterBaseAPI) ProviderType() (params.StringResult, error) { 995 result := params.StringResult{} 996 cfg, err := u.st.EnvironConfig() 997 if err == nil { 998 result.Result = cfg.Type() 999 } 1000 return result, err 1001 } 1002 1003 // EnterScope ensures each unit has entered its scope in the relation, 1004 // for all of the given relation/unit pairs. See also 1005 // state.RelationUnit.EnterScope(). 1006 func (u *uniterBaseAPI) EnterScope(args params.RelationUnits) (params.ErrorResults, error) { 1007 result := params.ErrorResults{ 1008 Results: make([]params.ErrorResult, len(args.RelationUnits)), 1009 } 1010 canAccess, err := u.accessUnit() 1011 if err != nil { 1012 return params.ErrorResults{}, err 1013 } 1014 for i, arg := range args.RelationUnits { 1015 tag, err := names.ParseUnitTag(arg.Unit) 1016 if err != nil { 1017 result.Results[i].Error = common.ServerError(common.ErrPerm) 1018 continue 1019 } 1020 relUnit, err := u.getRelationUnit(canAccess, arg.Relation, tag) 1021 if err == nil { 1022 // Construct the settings, passing the unit's 1023 // private address (we already know it). 1024 privateAddress, _ := relUnit.PrivateAddress() 1025 settings := map[string]interface{}{ 1026 "private-address": privateAddress, 1027 } 1028 err = relUnit.EnterScope(settings) 1029 } 1030 result.Results[i].Error = common.ServerError(err) 1031 } 1032 return result, nil 1033 } 1034 1035 // LeaveScope signals each unit has left its scope in the relation, 1036 // for all of the given relation/unit pairs. See also 1037 // state.RelationUnit.LeaveScope(). 1038 func (u *uniterBaseAPI) LeaveScope(args params.RelationUnits) (params.ErrorResults, error) { 1039 result := params.ErrorResults{ 1040 Results: make([]params.ErrorResult, len(args.RelationUnits)), 1041 } 1042 canAccess, err := u.accessUnit() 1043 if err != nil { 1044 return params.ErrorResults{}, err 1045 } 1046 for i, arg := range args.RelationUnits { 1047 unit, err := names.ParseUnitTag(arg.Unit) 1048 if err != nil { 1049 result.Results[i].Error = common.ServerError(common.ErrPerm) 1050 continue 1051 } 1052 relUnit, err := u.getRelationUnit(canAccess, arg.Relation, unit) 1053 if err == nil { 1054 err = relUnit.LeaveScope() 1055 } 1056 result.Results[i].Error = common.ServerError(err) 1057 } 1058 return result, nil 1059 } 1060 1061 // ReadSettings returns the local settings of each given set of 1062 // relation/unit. 1063 func (u *uniterBaseAPI) ReadSettings(args params.RelationUnits) (params.SettingsResults, error) { 1064 result := params.SettingsResults{ 1065 Results: make([]params.SettingsResult, len(args.RelationUnits)), 1066 } 1067 canAccess, err := u.accessUnit() 1068 if err != nil { 1069 return params.SettingsResults{}, err 1070 } 1071 for i, arg := range args.RelationUnits { 1072 unit, err := names.ParseUnitTag(arg.Unit) 1073 if err != nil { 1074 result.Results[i].Error = common.ServerError(common.ErrPerm) 1075 continue 1076 } 1077 relUnit, err := u.getRelationUnit(canAccess, arg.Relation, unit) 1078 if err == nil { 1079 var settings *state.Settings 1080 settings, err = relUnit.Settings() 1081 if err == nil { 1082 result.Results[i].Settings, err = convertRelationSettings(settings.Map()) 1083 } 1084 } 1085 result.Results[i].Error = common.ServerError(err) 1086 } 1087 return result, nil 1088 } 1089 1090 // ReadRemoteSettings returns the remote settings of each given set of 1091 // relation/local unit/remote unit. 1092 func (u *uniterBaseAPI) ReadRemoteSettings(args params.RelationUnitPairs) (params.SettingsResults, error) { 1093 result := params.SettingsResults{ 1094 Results: make([]params.SettingsResult, len(args.RelationUnitPairs)), 1095 } 1096 canAccess, err := u.accessUnit() 1097 if err != nil { 1098 return params.SettingsResults{}, err 1099 } 1100 for i, arg := range args.RelationUnitPairs { 1101 unit, err := names.ParseUnitTag(arg.LocalUnit) 1102 if err != nil { 1103 result.Results[i].Error = common.ServerError(common.ErrPerm) 1104 continue 1105 } 1106 relUnit, err := u.getRelationUnit(canAccess, arg.Relation, unit) 1107 if err == nil { 1108 // TODO(dfc) rework this logic 1109 remoteUnit := "" 1110 remoteUnit, err = u.checkRemoteUnit(relUnit, arg.RemoteUnit) 1111 if err == nil { 1112 var settings map[string]interface{} 1113 settings, err = relUnit.ReadSettings(remoteUnit) 1114 if err == nil { 1115 result.Results[i].Settings, err = convertRelationSettings(settings) 1116 } 1117 } 1118 } 1119 result.Results[i].Error = common.ServerError(err) 1120 } 1121 return result, nil 1122 } 1123 1124 // UpdateSettings persists all changes made to the local settings of 1125 // all given pairs of relation and unit. Keys with empty values are 1126 // considered a signal to delete these values. 1127 func (u *uniterBaseAPI) UpdateSettings(args params.RelationUnitsSettings) (params.ErrorResults, error) { 1128 result := params.ErrorResults{ 1129 Results: make([]params.ErrorResult, len(args.RelationUnits)), 1130 } 1131 canAccess, err := u.accessUnit() 1132 if err != nil { 1133 return params.ErrorResults{}, err 1134 } 1135 for i, arg := range args.RelationUnits { 1136 unit, err := names.ParseUnitTag(arg.Unit) 1137 if err != nil { 1138 result.Results[i].Error = common.ServerError(common.ErrPerm) 1139 continue 1140 } 1141 relUnit, err := u.getRelationUnit(canAccess, arg.Relation, unit) 1142 if err == nil { 1143 var settings *state.Settings 1144 settings, err = relUnit.Settings() 1145 if err == nil { 1146 for k, v := range arg.Settings { 1147 if v == "" { 1148 settings.Delete(k) 1149 } else { 1150 settings.Set(k, v) 1151 } 1152 } 1153 _, err = settings.Write() 1154 } 1155 } 1156 result.Results[i].Error = common.ServerError(err) 1157 } 1158 return result, nil 1159 } 1160 1161 // WatchRelationUnits returns a RelationUnitsWatcher for observing 1162 // changes to every unit in the supplied relation that is visible to 1163 // the supplied unit. See also state/watcher.go:RelationUnit.Watch(). 1164 func (u *uniterBaseAPI) WatchRelationUnits(args params.RelationUnits) (params.RelationUnitsWatchResults, error) { 1165 result := params.RelationUnitsWatchResults{ 1166 Results: make([]params.RelationUnitsWatchResult, len(args.RelationUnits)), 1167 } 1168 canAccess, err := u.accessUnit() 1169 if err != nil { 1170 return params.RelationUnitsWatchResults{}, err 1171 } 1172 for i, arg := range args.RelationUnits { 1173 unit, err := names.ParseUnitTag(arg.Unit) 1174 if err != nil { 1175 result.Results[i].Error = common.ServerError(common.ErrPerm) 1176 continue 1177 } 1178 relUnit, err := u.getRelationUnit(canAccess, arg.Relation, unit) 1179 if err == nil { 1180 result.Results[i], err = u.watchOneRelationUnit(relUnit) 1181 } 1182 result.Results[i].Error = common.ServerError(err) 1183 } 1184 return result, nil 1185 } 1186 1187 // WatchAddresses returns a NotifyWatcher for observing changes 1188 // to each unit's addresses. 1189 func (u *uniterBaseAPI) WatchUnitAddresses(args params.Entities) (params.NotifyWatchResults, error) { 1190 result := params.NotifyWatchResults{ 1191 Results: make([]params.NotifyWatchResult, len(args.Entities)), 1192 } 1193 canAccess, err := u.accessUnit() 1194 if err != nil { 1195 return params.NotifyWatchResults{}, err 1196 } 1197 for i, entity := range args.Entities { 1198 unit, err := names.ParseUnitTag(entity.Tag) 1199 if err != nil { 1200 result.Results[i].Error = common.ServerError(common.ErrPerm) 1201 continue 1202 } 1203 err = common.ErrPerm 1204 watcherId := "" 1205 if canAccess(unit) { 1206 watcherId, err = u.watchOneUnitAddresses(unit) 1207 } 1208 result.Results[i].NotifyWatcherId = watcherId 1209 result.Results[i].Error = common.ServerError(err) 1210 } 1211 return result, nil 1212 } 1213 1214 // AddMetrics adds the metrics for the specified unit. 1215 func (u *uniterBaseAPI) AddMetrics(args params.MetricsParams) (params.ErrorResults, error) { 1216 result := params.ErrorResults{ 1217 Results: make([]params.ErrorResult, len(args.Metrics)), 1218 } 1219 canAccess, err := u.accessUnit() 1220 if err != nil { 1221 return params.ErrorResults{}, common.ErrPerm 1222 } 1223 for i, unitMetrics := range args.Metrics { 1224 tag, err := names.ParseUnitTag(unitMetrics.Tag) 1225 if err != nil { 1226 result.Results[i].Error = common.ServerError(common.ErrPerm) 1227 continue 1228 } 1229 err = common.ErrPerm 1230 if canAccess(tag) { 1231 var unit *state.Unit 1232 unit, err = u.getUnit(tag) 1233 if err == nil { 1234 metricBatch := make([]state.Metric, len(unitMetrics.Metrics)) 1235 for j, metric := range unitMetrics.Metrics { 1236 // TODO (tasdomas) 2014-08-26: set credentials for metrics when available 1237 metricBatch[j] = state.Metric{ 1238 Key: metric.Key, 1239 Value: metric.Value, 1240 Time: metric.Time, 1241 } 1242 } 1243 _, err = unit.AddMetrics(time.Now(), metricBatch) 1244 } 1245 } 1246 result.Results[i].Error = common.ServerError(err) 1247 } 1248 return result, nil 1249 } 1250 1251 // GetMeterStatus returns meter status information for each unit. 1252 func (u *uniterBaseAPI) GetMeterStatus(args params.Entities) (params.MeterStatusResults, error) { 1253 result := params.MeterStatusResults{ 1254 Results: make([]params.MeterStatusResult, len(args.Entities)), 1255 } 1256 canAccess, err := u.accessUnit() 1257 if err != nil { 1258 return params.MeterStatusResults{}, common.ErrPerm 1259 } 1260 for i, entity := range args.Entities { 1261 unitTag, err := names.ParseUnitTag(entity.Tag) 1262 if err != nil { 1263 result.Results[i].Error = common.ServerError(common.ErrPerm) 1264 continue 1265 } 1266 err = common.ErrPerm 1267 var code string 1268 var info string 1269 if canAccess(unitTag) { 1270 var unit *state.Unit 1271 unit, err = u.getUnit(unitTag) 1272 if err == nil { 1273 code, info, err = unit.GetMeterStatus() 1274 } 1275 } 1276 result.Results[i].Code = code 1277 result.Results[i].Info = info 1278 result.Results[i].Error = common.ServerError(err) 1279 } 1280 return result, nil 1281 } 1282 1283 func (u *uniterBaseAPI) getUnit(tag names.UnitTag) (*state.Unit, error) { 1284 return u.st.Unit(tag.Id()) 1285 } 1286 1287 func (u *uniterBaseAPI) getService(tag names.ServiceTag) (*state.Service, error) { 1288 return u.st.Service(tag.Id()) 1289 } 1290 1291 func (u *uniterBaseAPI) getRelationUnit(canAccess common.AuthFunc, relTag string, unitTag names.UnitTag) (*state.RelationUnit, error) { 1292 rel, unit, err := u.getRelationAndUnit(canAccess, relTag, unitTag) 1293 if err != nil { 1294 return nil, err 1295 } 1296 return rel.Unit(unit) 1297 } 1298 1299 func (u *uniterBaseAPI) getOneRelationById(relId int) (params.RelationResult, error) { 1300 nothing := params.RelationResult{} 1301 rel, err := u.st.Relation(relId) 1302 if errors.IsNotFound(err) { 1303 return nothing, common.ErrPerm 1304 } else if err != nil { 1305 return nothing, err 1306 } 1307 tag := u.auth.GetAuthTag() 1308 switch tag.(type) { 1309 case names.UnitTag: 1310 // do nothing 1311 default: 1312 panic("authenticated entity is not a unit") 1313 } 1314 unit, err := u.st.FindEntity(tag) 1315 if err != nil { 1316 return nothing, err 1317 } 1318 // Use the currently authenticated unit to get the endpoint. 1319 result, err := u.prepareRelationResult(rel, unit.(*state.Unit)) 1320 if err != nil { 1321 // An error from prepareRelationResult means the authenticated 1322 // unit's service is not part of the requested 1323 // relation. That's why it's appropriate to return ErrPerm 1324 // here. 1325 return nothing, common.ErrPerm 1326 } 1327 return result, nil 1328 } 1329 1330 func (u *uniterBaseAPI) getRelationAndUnit(canAccess common.AuthFunc, relTag string, unitTag names.UnitTag) (*state.Relation, *state.Unit, error) { 1331 tag, err := names.ParseRelationTag(relTag) 1332 if err != nil { 1333 return nil, nil, common.ErrPerm 1334 } 1335 rel, err := u.st.KeyRelation(tag.Id()) 1336 if errors.IsNotFound(err) { 1337 return nil, nil, common.ErrPerm 1338 } else if err != nil { 1339 return nil, nil, err 1340 } 1341 if !canAccess(unitTag) { 1342 return nil, nil, common.ErrPerm 1343 } 1344 unit, err := u.getUnit(unitTag) 1345 return rel, unit, err 1346 } 1347 1348 func (u *uniterBaseAPI) prepareRelationResult(rel *state.Relation, unit *state.Unit) (params.RelationResult, error) { 1349 nothing := params.RelationResult{} 1350 ep, err := rel.Endpoint(unit.ServiceName()) 1351 if err != nil { 1352 // An error here means the unit's service is not part of the 1353 // relation. 1354 return nothing, err 1355 } 1356 return params.RelationResult{ 1357 Id: rel.Id(), 1358 Key: rel.String(), 1359 Life: params.Life(rel.Life().String()), 1360 Endpoint: multiwatcher.Endpoint{ 1361 ServiceName: ep.ServiceName, 1362 Relation: ep.Relation, 1363 }, 1364 }, nil 1365 } 1366 1367 func (u *uniterBaseAPI) getOneRelation(canAccess common.AuthFunc, relTag, unitTag string) (params.RelationResult, error) { 1368 nothing := params.RelationResult{} 1369 tag, err := names.ParseUnitTag(unitTag) 1370 if err != nil { 1371 return nothing, common.ErrPerm 1372 } 1373 rel, unit, err := u.getRelationAndUnit(canAccess, relTag, tag) 1374 if err != nil { 1375 return nothing, err 1376 } 1377 return u.prepareRelationResult(rel, unit) 1378 } 1379 1380 func (u *uniterBaseAPI) destroySubordinates(principal *state.Unit) error { 1381 subordinates := principal.SubordinateNames() 1382 for _, subName := range subordinates { 1383 unit, err := u.getUnit(names.NewUnitTag(subName)) 1384 if err != nil { 1385 return err 1386 } 1387 if err = unit.Destroy(); err != nil { 1388 return err 1389 } 1390 } 1391 return nil 1392 } 1393 1394 func (u *uniterBaseAPI) watchOneServiceRelations(tag names.ServiceTag) (params.StringsWatchResult, error) { 1395 nothing := params.StringsWatchResult{} 1396 service, err := u.getService(tag) 1397 if err != nil { 1398 return nothing, err 1399 } 1400 watch := service.WatchRelations() 1401 // Consume the initial event and forward it to the result. 1402 if changes, ok := <-watch.Changes(); ok { 1403 return params.StringsWatchResult{ 1404 StringsWatcherId: u.resources.Register(watch), 1405 Changes: changes, 1406 }, nil 1407 } 1408 return nothing, watcher.EnsureErr(watch) 1409 } 1410 1411 func (u *uniterBaseAPI) watchOneUnitConfigSettings(tag names.UnitTag) (string, error) { 1412 unit, err := u.getUnit(tag) 1413 if err != nil { 1414 return "", err 1415 } 1416 watch, err := unit.WatchConfigSettings() 1417 if err != nil { 1418 return "", err 1419 } 1420 // Consume the initial event. Technically, API 1421 // calls to Watch 'transmit' the initial event 1422 // in the Watch response. But NotifyWatchers 1423 // have no state to transmit. 1424 if _, ok := <-watch.Changes(); ok { 1425 return u.resources.Register(watch), nil 1426 } 1427 return "", watcher.EnsureErr(watch) 1428 } 1429 1430 func (u *uniterBaseAPI) watchOneUnitActionNotifications(tag names.UnitTag) (params.StringsWatchResult, error) { 1431 nothing := params.StringsWatchResult{} 1432 unit, err := u.getUnit(tag) 1433 if err != nil { 1434 return nothing, err 1435 } 1436 watch := unit.WatchActionNotifications() 1437 1438 if changes, ok := <-watch.Changes(); ok { 1439 return params.StringsWatchResult{ 1440 StringsWatcherId: u.resources.Register(watch), 1441 Changes: changes, 1442 }, nil 1443 } 1444 return nothing, watcher.EnsureErr(watch) 1445 } 1446 1447 func (u *uniterBaseAPI) watchOneUnitAddresses(tag names.UnitTag) (string, error) { 1448 unit, err := u.getUnit(tag) 1449 if err != nil { 1450 return "", err 1451 } 1452 machineId, err := unit.AssignedMachineId() 1453 if err != nil { 1454 return "", err 1455 } 1456 machine, err := u.st.Machine(machineId) 1457 if err != nil { 1458 return "", err 1459 } 1460 watch := machine.WatchAddresses() 1461 // Consume the initial event. Technically, API 1462 // calls to Watch 'transmit' the initial event 1463 // in the Watch response. But NotifyWatchers 1464 // have no state to transmit. 1465 if _, ok := <-watch.Changes(); ok { 1466 return u.resources.Register(watch), nil 1467 } 1468 return "", watcher.EnsureErr(watch) 1469 } 1470 1471 func (u *uniterBaseAPI) watchOneRelationUnit(relUnit *state.RelationUnit) (params.RelationUnitsWatchResult, error) { 1472 watch := relUnit.Watch() 1473 // Consume the initial event and forward it to the result. 1474 if changes, ok := <-watch.Changes(); ok { 1475 return params.RelationUnitsWatchResult{ 1476 RelationUnitsWatcherId: u.resources.Register(watch), 1477 Changes: changes, 1478 }, nil 1479 } 1480 return params.RelationUnitsWatchResult{}, watcher.EnsureErr(watch) 1481 } 1482 1483 func (u *uniterBaseAPI) watchOneUnitMeterStatus(tag names.UnitTag) (string, error) { 1484 unit, err := u.getUnit(tag) 1485 if err != nil { 1486 return "", err 1487 } 1488 watch := unit.WatchMeterStatus() 1489 if _, ok := <-watch.Changes(); ok { 1490 return u.resources.Register(watch), nil 1491 } 1492 return "", watcher.EnsureErr(watch) 1493 } 1494 1495 func (u *uniterBaseAPI) checkRemoteUnit(relUnit *state.RelationUnit, remoteUnitTag string) (string, error) { 1496 // Make sure the unit is indeed remote. 1497 if remoteUnitTag == u.auth.GetAuthTag().String() { 1498 return "", common.ErrPerm 1499 } 1500 // Check remoteUnit is indeed related. Note that we don't want to actually get 1501 // the *Unit, because it might have been removed; but its relation settings will 1502 // persist until the relation itself has been removed (and must remain accessible 1503 // because the local unit's view of reality may be time-shifted). 1504 tag, err := names.ParseUnitTag(remoteUnitTag) 1505 if err != nil { 1506 return "", common.ErrPerm 1507 } 1508 remoteUnitName := tag.Id() 1509 remoteServiceName, err := names.UnitService(remoteUnitName) 1510 if err != nil { 1511 return "", common.ErrPerm 1512 } 1513 rel := relUnit.Relation() 1514 _, err = rel.RelatedEndpoints(remoteServiceName) 1515 if err != nil { 1516 return "", common.ErrPerm 1517 } 1518 return remoteUnitName, nil 1519 } 1520 1521 // authAndActionFromTagFn first authenticates the request, and then returns 1522 // a function with which to authenticate and retrieve each action in the 1523 // request. 1524 func (u *uniterBaseAPI) authAndActionFromTagFn() (func(string) (*state.Action, error), error) { 1525 canAccess, err := u.accessUnit() 1526 if err != nil { 1527 return nil, err 1528 } 1529 unit, ok := u.auth.GetAuthTag().(names.UnitTag) 1530 if !ok { 1531 return nil, fmt.Errorf("calling entity is not a unit") 1532 } 1533 1534 return func(tag string) (*state.Action, error) { 1535 actionTag, err := names.ParseActionTag(tag) 1536 if err != nil { 1537 return nil, err 1538 } 1539 action, err := u.st.ActionByTag(actionTag) 1540 if err != nil { 1541 return nil, err 1542 } 1543 receiverTag, err := names.ActionReceiverTag(action.Receiver()) 1544 if err != nil { 1545 return nil, err 1546 } 1547 if unit != receiverTag { 1548 return nil, common.ErrPerm 1549 } 1550 1551 if !canAccess(receiverTag) { 1552 return nil, common.ErrPerm 1553 } 1554 return action, nil 1555 }, nil 1556 } 1557 1558 func convertRelationSettings(settings map[string]interface{}) (params.Settings, error) { 1559 result := make(params.Settings) 1560 for k, v := range settings { 1561 // All relation settings should be strings. 1562 sval, ok := v.(string) 1563 if !ok { 1564 return nil, fmt.Errorf("unexpected relation setting %q: expected string, got %T", k, v) 1565 } 1566 result[k] = sval 1567 } 1568 return result, nil 1569 } 1570 1571 func relationsInScopeTags(unit *state.Unit) ([]string, error) { 1572 relations, err := unit.RelationsInScope() 1573 if err != nil { 1574 return nil, err 1575 } 1576 tags := make([]string, len(relations)) 1577 for i, relation := range relations { 1578 tags[i] = relation.Tag().String() 1579 } 1580 return tags, nil 1581 } 1582 1583 func leadershipSettingsAccessorFactory( 1584 st *state.State, 1585 resources *common.Resources, 1586 auth common.Authorizer, 1587 ) *leadershipapiserver.LeadershipSettingsAccessor { 1588 registerWatcher := func(serviceId string) (string, error) { 1589 settingsWatcher := st.WatchLeadershipSettings(serviceId) 1590 if _, ok := <-settingsWatcher.Changes(); ok { 1591 return resources.Register(settingsWatcher), nil 1592 } 1593 1594 return "", watcher.EnsureErr(settingsWatcher) 1595 } 1596 // TODO(katco-): <2015-01-21 Wed> 1597 // Due to time constraints, we're translating between 1598 // map[string]interface{} and map[string]string. At some point we 1599 // should support a native read of this format straight from 1600 // state. 1601 getSettings := func(serviceId string) (map[string]string, error) { 1602 settings, err := st.ReadSettings(state.LeadershipSettingsDocId(serviceId)) 1603 if err != nil { 1604 return nil, err 1605 } 1606 // Perform the conversion 1607 rawMap := settings.Map() 1608 leadershipSettings := make(map[string]string) 1609 for k, v := range rawMap { 1610 leadershipSettings[k] = v.(string) 1611 } 1612 return leadershipSettings, nil 1613 } 1614 writeSettings := func(serviceId string, settings map[string]string) error { 1615 currentSettings, err := st.ReadLeadershipSettings(serviceId) 1616 if err != nil { 1617 return err 1618 } 1619 rawSettings := make(map[string]interface{}) 1620 for k, v := range settings { 1621 rawSettings[k] = v 1622 } 1623 currentSettings.Update(rawSettings) 1624 _, err = currentSettings.Write() 1625 return errors.Annotate(err, "could not write changes") 1626 } 1627 ldrMgr := leadership.NewLeadershipManager(lease.Manager()) 1628 return leadershipapiserver.NewLeadershipSettingsAccessor( 1629 auth, 1630 registerWatcher, 1631 getSettings, 1632 writeSettings, 1633 ldrMgr.Leader, 1634 ) 1635 }