github.com/mwhudson/juju@v0.0.0-20160512215208-90ff01f3497f/apiserver/uniter/uniter.go (about)

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