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