github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/apiserver/facades/agent/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  package uniter
     6  
     7  import (
     8  	"fmt"
     9  	"strings"
    10  
    11  	"github.com/juju/collections/set"
    12  	"github.com/juju/errors"
    13  	"github.com/juju/juju/environs"
    14  	"github.com/juju/loggo"
    15  	"gopkg.in/juju/charm.v6"
    16  	"gopkg.in/juju/names.v2"
    17  
    18  	"github.com/juju/juju/apiserver/common"
    19  	"github.com/juju/juju/apiserver/common/cloudspec"
    20  	"github.com/juju/juju/apiserver/common/networkingcommon"
    21  	"github.com/juju/juju/apiserver/facade"
    22  	leadershipapiserver "github.com/juju/juju/apiserver/facades/agent/leadership"
    23  	"github.com/juju/juju/apiserver/facades/agent/meterstatus"
    24  	"github.com/juju/juju/apiserver/facades/client/application"
    25  	"github.com/juju/juju/apiserver/params"
    26  	"github.com/juju/juju/caas"
    27  	"github.com/juju/juju/core/leadership"
    28  	corenetwork "github.com/juju/juju/core/network"
    29  	"github.com/juju/juju/core/status"
    30  	"github.com/juju/juju/network"
    31  	"github.com/juju/juju/state"
    32  	"github.com/juju/juju/state/multiwatcher"
    33  	"github.com/juju/juju/state/watcher"
    34  )
    35  
    36  var logger = loggo.GetLogger("juju.apiserver.uniter")
    37  
    38  // UniterAPI implements the latest version (v9) of the Uniter API,
    39  // which adds WatchConfigSettingsHash, WatchTrustConfigSettingsHash
    40  // and WatchUnitAddressesHash.
    41  type UniterAPI struct {
    42  	*common.LifeGetter
    43  	*StatusAPI
    44  	*common.DeadEnsurer
    45  	*common.AgentEntityWatcher
    46  	*common.APIAddresser
    47  	*common.ModelWatcher
    48  	*common.RebootRequester
    49  	*common.UpgradeSeriesAPI
    50  	*LXDProfileAPI
    51  	*leadershipapiserver.LeadershipSettingsAccessor
    52  	meterstatus.MeterStatus
    53  	m                 *state.Model
    54  	st                *state.State
    55  	auth              facade.Authorizer
    56  	resources         facade.Resources
    57  	leadershipChecker leadership.Checker
    58  	accessUnit        common.GetAuthFunc
    59  	accessApplication common.GetAuthFunc
    60  	accessMachine     common.GetAuthFunc
    61  	*StorageAPI
    62  
    63  	// A cloud spec can only be accessed for the model of the unit or
    64  	// application that is authorised for this API facade.
    65  	// We do not need to use an AuthFunc, because we do not need to pass a tag.
    66  	accessCloudSpec func() (func() bool, error)
    67  	cloudSpec       cloudspec.CloudSpecAPI
    68  }
    69  
    70  // UniterAPIV8 adds SetContainerSpec, GoalStates, CloudSpec,
    71  // WatchTrustConfigSettings, WatchActionNotifications,
    72  // UpgradeSeriesStatus, SetUpgradeSeriesStatus.
    73  type UniterAPIV8 struct {
    74  	UniterAPI
    75  }
    76  
    77  // UniterAPIV7 adds CMR support to NetworkInfo.
    78  type UniterAPIV7 struct {
    79  	UniterAPIV8
    80  }
    81  
    82  // UniterAPIV6 adds NetworkInfo as a preferred method to calling NetworkConfig.
    83  type UniterAPIV6 struct {
    84  	UniterAPIV7
    85  }
    86  
    87  // UniterAPIV5 returns a RelationResultsV5 instead of RelationResults
    88  // from Relation and RelationById - elements don't have an
    89  // OtherApplication field.
    90  type UniterAPIV5 struct {
    91  	UniterAPIV6
    92  }
    93  
    94  // UniterAPIV4 has old WatchApplicationRelations and NetworkConfig
    95  // methods, and doesn't have the new SLALevel, NetworkInfo or
    96  // WatchUnitRelations methods.
    97  type UniterAPIV4 struct {
    98  	UniterAPIV5
    99  }
   100  
   101  // NewUniterAPI creates a new instance of the core Uniter API.
   102  func NewUniterAPI(context facade.Context) (*UniterAPI, error) {
   103  	authorizer := context.Auth()
   104  	if !authorizer.AuthUnitAgent() && !authorizer.AuthApplicationAgent() {
   105  		return nil, common.ErrPerm
   106  	}
   107  	st := context.State()
   108  	resources := context.Resources()
   109  	leadershipChecker, err := context.LeadershipChecker()
   110  	if err != nil {
   111  		return nil, errors.Trace(err)
   112  	}
   113  	accessUnit := func() (common.AuthFunc, error) {
   114  		switch tag := authorizer.GetAuthTag().(type) {
   115  		case names.ApplicationTag:
   116  			// If called by an application agent, any of the units
   117  			// belonging to that application can be accessed.
   118  			app, err := st.Application(tag.Name)
   119  			if err != nil {
   120  				return nil, errors.Trace(err)
   121  			}
   122  			allUnits, err := app.AllUnits()
   123  			if err != nil {
   124  				return nil, errors.Trace(err)
   125  			}
   126  			return func(tag names.Tag) bool {
   127  				for _, u := range allUnits {
   128  					if u.Tag() == tag {
   129  						return true
   130  					}
   131  				}
   132  				return false
   133  			}, nil
   134  		case names.UnitTag:
   135  			return func(tag names.Tag) bool {
   136  				return authorizer.AuthOwner(tag)
   137  			}, nil
   138  		default:
   139  			return nil, errors.Errorf("expected names.UnitTag or names.ApplicationTag, got %T", tag)
   140  		}
   141  	}
   142  	accessApplication := func() (common.AuthFunc, error) {
   143  		switch tag := authorizer.GetAuthTag().(type) {
   144  		case names.ApplicationTag:
   145  			return func(applicationTag names.Tag) bool {
   146  				return tag == applicationTag
   147  			}, nil
   148  		case names.UnitTag:
   149  			entity, err := st.Unit(tag.Id())
   150  			if err != nil {
   151  				return nil, errors.Trace(err)
   152  			}
   153  			applicationName := entity.ApplicationName()
   154  			applicationTag := names.NewApplicationTag(applicationName)
   155  			return func(tag names.Tag) bool {
   156  				return tag == applicationTag
   157  			}, nil
   158  		default:
   159  			return nil, errors.Errorf("expected names.UnitTag or names.ApplicationTag, got %T", tag)
   160  		}
   161  	}
   162  	accessMachine := func() (common.AuthFunc, error) {
   163  		switch tag := authorizer.GetAuthTag().(type) {
   164  		// Application agents can't access machines.
   165  		case names.ApplicationTag:
   166  			return func(tag names.Tag) bool {
   167  				return false
   168  			}, nil
   169  		case names.UnitTag:
   170  			entity, err := st.Unit(tag.Id())
   171  			if err != nil {
   172  				return nil, errors.Trace(err)
   173  			}
   174  			machineId, err := entity.AssignedMachineId()
   175  			if err != nil {
   176  				return nil, errors.Trace(err)
   177  			}
   178  			machineTag := names.NewMachineTag(machineId)
   179  			return func(tag names.Tag) bool {
   180  				return tag == machineTag
   181  			}, nil
   182  		default:
   183  			return nil, errors.Errorf("expected names.UnitTag or names.ApplicationTag, got %T", tag)
   184  		}
   185  	}
   186  	accessCloudSpec := func() (func() bool, error) {
   187  		var appName string
   188  		var err error
   189  
   190  		switch tag := authorizer.GetAuthTag().(type) {
   191  		case names.ApplicationTag:
   192  			appName = tag.String()
   193  		case names.UnitTag:
   194  			entity, err := st.Unit(tag.Id())
   195  			if err != nil {
   196  				return nil, errors.Trace(err)
   197  			}
   198  			appName = entity.ApplicationName()
   199  		default:
   200  			return nil, errors.Errorf("expected names.UnitTag or names.ApplicationTag, got %T", tag)
   201  		}
   202  
   203  		app, err := st.Application(appName)
   204  		if err != nil {
   205  			return nil, errors.Trace(err)
   206  		}
   207  		config, err := app.ApplicationConfig()
   208  		if err != nil {
   209  			return nil, errors.Trace(err)
   210  		}
   211  		return func() bool {
   212  			return config.GetBool(application.TrustConfigOptionName, false)
   213  		}, nil
   214  	}
   215  
   216  	m, err := st.Model()
   217  	if err != nil {
   218  		return nil, errors.Trace(err)
   219  	}
   220  
   221  	storageAccessor, err := getStorageState(st)
   222  	storageAPI, err := newStorageAPI(
   223  		stateShim{st}, storageAccessor, resources, accessUnit)
   224  	if err != nil {
   225  		return nil, err
   226  	}
   227  	msAPI, err := meterstatus.NewMeterStatusAPI(st, resources, authorizer)
   228  	if err != nil {
   229  		return nil, errors.Annotate(err, "could not create meter status API handler")
   230  	}
   231  	accessUnitOrApplication := common.AuthAny(accessUnit, accessApplication)
   232  
   233  	cloudSpec := cloudspec.NewCloudSpec(
   234  		cloudspec.MakeCloudSpecGetterForModel(st),
   235  		common.AuthFuncForTag(m.ModelTag()),
   236  	)
   237  
   238  	return &UniterAPI{
   239  		LifeGetter:                 common.NewLifeGetter(st, accessUnitOrApplication),
   240  		DeadEnsurer:                common.NewDeadEnsurer(st, accessUnit),
   241  		AgentEntityWatcher:         common.NewAgentEntityWatcher(st, resources, accessUnitOrApplication),
   242  		APIAddresser:               common.NewAPIAddresser(st, resources),
   243  		ModelWatcher:               common.NewModelWatcher(m, resources, authorizer),
   244  		RebootRequester:            common.NewRebootRequester(st, accessMachine),
   245  		UpgradeSeriesAPI:           common.NewExternalUpgradeSeriesAPI(st, resources, authorizer, accessMachine, accessUnit, logger),
   246  		LXDProfileAPI:              NewExternalLXDProfileAPI(st, resources, authorizer, accessMachine, accessUnit, logger),
   247  		LeadershipSettingsAccessor: leadershipSettingsAccessorFactory(st, leadershipChecker, resources, authorizer),
   248  		MeterStatus:                msAPI,
   249  		// TODO(fwereade): so *every* unit should be allowed to get/set its
   250  		// own status *and* its application's? This is not a pleasing arrangement.
   251  		StatusAPI: NewStatusAPI(st, accessUnitOrApplication),
   252  
   253  		st:                st,
   254  		m:                 m,
   255  		auth:              authorizer,
   256  		resources:         resources,
   257  		leadershipChecker: leadershipChecker,
   258  		accessUnit:        accessUnit,
   259  		accessApplication: accessApplication,
   260  		accessMachine:     accessMachine,
   261  		accessCloudSpec:   accessCloudSpec,
   262  		cloudSpec:         cloudSpec,
   263  		StorageAPI:        storageAPI,
   264  	}, nil
   265  }
   266  
   267  // NewUniterAPIV8 creates an instance of the V8 uniter API.
   268  func NewUniterAPIV8(context facade.Context) (*UniterAPIV8, error) {
   269  	uniterAPI, err := NewUniterAPI(context)
   270  	if err != nil {
   271  		return nil, err
   272  	}
   273  	return &UniterAPIV8{
   274  		UniterAPI: *uniterAPI,
   275  	}, nil
   276  }
   277  
   278  // NewUniterAPIV7 creates an instance of the V7 uniter API.
   279  func NewUniterAPIV7(context facade.Context) (*UniterAPIV7, error) {
   280  	uniterAPI, err := NewUniterAPIV8(context)
   281  	if err != nil {
   282  		return nil, err
   283  	}
   284  	return &UniterAPIV7{
   285  		UniterAPIV8: *uniterAPI,
   286  	}, nil
   287  }
   288  
   289  // NewUniterAPIV6 creates an instance of the V6 uniter API.
   290  func NewUniterAPIV6(context facade.Context) (*UniterAPIV6, error) {
   291  	uniterAPI, err := NewUniterAPIV7(context)
   292  	if err != nil {
   293  		return nil, err
   294  	}
   295  	return &UniterAPIV6{
   296  		UniterAPIV7: *uniterAPI,
   297  	}, nil
   298  }
   299  
   300  // NewUniterAPIV5 creates an instance of the V5 uniter API.
   301  func NewUniterAPIV5(context facade.Context) (*UniterAPIV5, error) {
   302  	uniterAPI, err := NewUniterAPIV6(context)
   303  	if err != nil {
   304  		return nil, err
   305  	}
   306  	return &UniterAPIV5{
   307  		UniterAPIV6: *uniterAPI,
   308  	}, nil
   309  }
   310  
   311  // NewUniterAPIV4 creates an instance of the V4 uniter API.
   312  func NewUniterAPIV4(context facade.Context) (*UniterAPIV4, error) {
   313  	uniterAPI, err := NewUniterAPIV5(context)
   314  	if err != nil {
   315  		return nil, err
   316  	}
   317  	return &UniterAPIV4{
   318  		UniterAPIV5: *uniterAPI,
   319  	}, nil
   320  }
   321  
   322  // AllMachinePorts returns all opened port ranges for each given
   323  // machine (on all networks).
   324  func (u *UniterAPI) AllMachinePorts(args params.Entities) (params.MachinePortsResults, error) {
   325  	result := params.MachinePortsResults{
   326  		Results: make([]params.MachinePortsResult, len(args.Entities)),
   327  	}
   328  	canAccess, err := u.accessMachine()
   329  	if err != nil {
   330  		return params.MachinePortsResults{}, err
   331  	}
   332  	for i, entity := range args.Entities {
   333  		result.Results[i] = u.getOneMachinePorts(canAccess, entity.Tag)
   334  	}
   335  	return result, nil
   336  }
   337  
   338  // AssignedMachine returns the machine tag for each given unit tag, or
   339  // an error satisfying params.IsCodeNotAssigned when a unit has no
   340  // assigned machine.
   341  func (u *UniterAPI) AssignedMachine(args params.Entities) (params.StringResults, error) {
   342  	result := params.StringResults{
   343  		Results: make([]params.StringResult, len(args.Entities)),
   344  	}
   345  	canAccess, err := u.accessUnit()
   346  	if err != nil {
   347  		return params.StringResults{}, err
   348  	}
   349  	for i, entity := range args.Entities {
   350  		tag, err := names.ParseUnitTag(entity.Tag)
   351  		if err != nil {
   352  			result.Results[i].Error = common.ServerError(common.ErrPerm)
   353  			continue
   354  		}
   355  		if !canAccess(tag) {
   356  			result.Results[i].Error = common.ServerError(common.ErrPerm)
   357  			continue
   358  		}
   359  		unit, err := u.getUnit(tag)
   360  		if err != nil {
   361  			result.Results[i].Error = common.ServerError(err)
   362  			continue
   363  		}
   364  		machineId, err := unit.AssignedMachineId()
   365  		if err != nil {
   366  			result.Results[i].Error = common.ServerError(err)
   367  		} else {
   368  			result.Results[i].Result = names.NewMachineTag(machineId).String()
   369  		}
   370  	}
   371  	return result, nil
   372  }
   373  
   374  func (u *UniterAPI) getMachine(tag names.MachineTag) (*state.Machine, error) {
   375  	return u.st.Machine(tag.Id())
   376  }
   377  
   378  func (u *UniterAPI) getOneMachinePorts(canAccess common.AuthFunc, machineTag string) params.MachinePortsResult {
   379  	tag, err := names.ParseMachineTag(machineTag)
   380  	if err != nil {
   381  		return params.MachinePortsResult{Error: common.ServerError(common.ErrPerm)}
   382  	}
   383  	if !canAccess(tag) {
   384  		return params.MachinePortsResult{Error: common.ServerError(common.ErrPerm)}
   385  	}
   386  	machine, err := u.getMachine(tag)
   387  	if err != nil {
   388  		return params.MachinePortsResult{Error: common.ServerError(err)}
   389  	}
   390  	allPorts, err := machine.AllPorts()
   391  	if err != nil {
   392  		return params.MachinePortsResult{Error: common.ServerError(err)}
   393  	}
   394  	var resultPorts []params.MachinePortRange
   395  	for _, ports := range allPorts {
   396  		// AllPortRanges gives a map, but apis require a stable order
   397  		// for results, so sort the port ranges.
   398  		portRangesToUnits := ports.AllPortRanges()
   399  		portRanges := make([]corenetwork.PortRange, 0, len(portRangesToUnits))
   400  		for portRange := range portRangesToUnits {
   401  			portRanges = append(portRanges, portRange)
   402  		}
   403  		corenetwork.SortPortRanges(portRanges)
   404  		for _, portRange := range portRanges {
   405  			unitName := portRangesToUnits[portRange]
   406  			resultPorts = append(resultPorts, params.MachinePortRange{
   407  				UnitTag:   names.NewUnitTag(unitName).String(),
   408  				PortRange: params.FromNetworkPortRange(portRange),
   409  			})
   410  		}
   411  	}
   412  	return params.MachinePortsResult{
   413  		Ports: resultPorts,
   414  	}
   415  }
   416  
   417  // PublicAddress returns the public address for each given unit, if set.
   418  func (u *UniterAPI) PublicAddress(args params.Entities) (params.StringResults, error) {
   419  	result := params.StringResults{
   420  		Results: make([]params.StringResult, len(args.Entities)),
   421  	}
   422  	canAccess, err := u.accessUnit()
   423  	if err != nil {
   424  		return params.StringResults{}, err
   425  	}
   426  	for i, entity := range args.Entities {
   427  		tag, err := names.ParseUnitTag(entity.Tag)
   428  		if err != nil {
   429  			result.Results[i].Error = common.ServerError(common.ErrPerm)
   430  			continue
   431  		}
   432  		err = common.ErrPerm
   433  		if canAccess(tag) {
   434  			var unit *state.Unit
   435  			unit, err = u.getUnit(tag)
   436  			if err == nil {
   437  				var address network.Address
   438  				address, err = unit.PublicAddress()
   439  				if err == nil {
   440  					result.Results[i].Result = address.Value
   441  				} else if network.IsNoAddressError(err) {
   442  					err = common.NoAddressSetError(tag, "public")
   443  				}
   444  			}
   445  		}
   446  		result.Results[i].Error = common.ServerError(err)
   447  	}
   448  	return result, nil
   449  }
   450  
   451  // PrivateAddress returns the private address for each given unit, if set.
   452  func (u *UniterAPI) PrivateAddress(args params.Entities) (params.StringResults, error) {
   453  	result := params.StringResults{
   454  		Results: make([]params.StringResult, len(args.Entities)),
   455  	}
   456  	canAccess, err := u.accessUnit()
   457  	if err != nil {
   458  		return params.StringResults{}, err
   459  	}
   460  	for i, entity := range args.Entities {
   461  		tag, err := names.ParseUnitTag(entity.Tag)
   462  		if err != nil {
   463  			result.Results[i].Error = common.ServerError(common.ErrPerm)
   464  			continue
   465  		}
   466  		err = common.ErrPerm
   467  		if canAccess(tag) {
   468  			var unit *state.Unit
   469  			unit, err = u.getUnit(tag)
   470  			if err == nil {
   471  				var address network.Address
   472  				address, err = unit.PrivateAddress()
   473  				if err == nil {
   474  					result.Results[i].Result = address.Value
   475  				} else if network.IsNoAddressError(err) {
   476  					err = common.NoAddressSetError(tag, "private")
   477  				}
   478  			}
   479  		}
   480  		result.Results[i].Error = common.ServerError(err)
   481  	}
   482  	return result, nil
   483  }
   484  
   485  // TODO(ericsnow) Factor out the common code amongst the many methods here.
   486  
   487  var getZone = func(st *state.State, tag names.Tag) (string, error) {
   488  	unit, err := st.Unit(tag.Id())
   489  	if err != nil {
   490  		return "", errors.Trace(err)
   491  	}
   492  	zone, err := unit.AvailabilityZone()
   493  	return zone, errors.Trace(err)
   494  }
   495  
   496  // AvailabilityZone returns the availability zone for each given unit, if applicable.
   497  func (u *UniterAPI) AvailabilityZone(args params.Entities) (params.StringResults, error) {
   498  	var results params.StringResults
   499  
   500  	canAccess, err := u.accessUnit()
   501  	if err != nil {
   502  		return results, errors.Trace(err)
   503  	}
   504  
   505  	// Prep the results.
   506  	results = params.StringResults{
   507  		Results: make([]params.StringResult, len(args.Entities)),
   508  	}
   509  
   510  	// Collect the zones. No zone will be collected for any entity where
   511  	// the tag is invalid or not authorized. Instead the corresponding
   512  	// result will be updated with the error.
   513  	for i, entity := range args.Entities {
   514  		tag, err := names.ParseUnitTag(entity.Tag)
   515  		if err != nil {
   516  			results.Results[i].Error = common.ServerError(common.ErrPerm)
   517  			continue
   518  		}
   519  		err = common.ErrPerm
   520  		if canAccess(tag) {
   521  			var zone string
   522  			zone, err = getZone(u.st, tag)
   523  			if err == nil {
   524  				results.Results[i].Result = zone
   525  			}
   526  		}
   527  		results.Results[i].Error = common.ServerError(err)
   528  	}
   529  
   530  	return results, nil
   531  }
   532  
   533  // Resolved returns the current resolved setting for each given unit.
   534  func (u *UniterAPI) Resolved(args params.Entities) (params.ResolvedModeResults, error) {
   535  	result := params.ResolvedModeResults{
   536  		Results: make([]params.ResolvedModeResult, len(args.Entities)),
   537  	}
   538  	canAccess, err := u.accessUnit()
   539  	if err != nil {
   540  		return params.ResolvedModeResults{}, err
   541  	}
   542  	for i, entity := range args.Entities {
   543  		tag, err := names.ParseUnitTag(entity.Tag)
   544  		if err != nil {
   545  			result.Results[i].Error = common.ServerError(common.ErrPerm)
   546  			continue
   547  		}
   548  		err = common.ErrPerm
   549  		if canAccess(tag) {
   550  			var unit *state.Unit
   551  			unit, err = u.getUnit(tag)
   552  			if err == nil {
   553  				result.Results[i].Mode = params.ResolvedMode(unit.Resolved())
   554  			}
   555  		}
   556  		result.Results[i].Error = common.ServerError(err)
   557  	}
   558  	return result, nil
   559  }
   560  
   561  // ClearResolved removes any resolved setting from each given unit.
   562  func (u *UniterAPI) ClearResolved(args params.Entities) (params.ErrorResults, error) {
   563  	result := params.ErrorResults{
   564  		Results: make([]params.ErrorResult, len(args.Entities)),
   565  	}
   566  	canAccess, err := u.accessUnit()
   567  	if err != nil {
   568  		return params.ErrorResults{}, err
   569  	}
   570  	for i, entity := range args.Entities {
   571  		tag, err := names.ParseUnitTag(entity.Tag)
   572  		if err != nil {
   573  			result.Results[i].Error = common.ServerError(common.ErrPerm)
   574  			continue
   575  		}
   576  		err = common.ErrPerm
   577  		if canAccess(tag) {
   578  			var unit *state.Unit
   579  			unit, err = u.getUnit(tag)
   580  			if err == nil {
   581  				err = unit.ClearResolved()
   582  			}
   583  		}
   584  		result.Results[i].Error = common.ServerError(err)
   585  	}
   586  	return result, nil
   587  }
   588  
   589  // GetPrincipal returns the result of calling PrincipalName() and
   590  // converting it to a tag, on each given unit.
   591  func (u *UniterAPI) GetPrincipal(args params.Entities) (params.StringBoolResults, error) {
   592  	result := params.StringBoolResults{
   593  		Results: make([]params.StringBoolResult, len(args.Entities)),
   594  	}
   595  	canAccess, err := u.accessUnit()
   596  	if err != nil {
   597  		return params.StringBoolResults{}, err
   598  	}
   599  	for i, entity := range args.Entities {
   600  		tag, err := names.ParseUnitTag(entity.Tag)
   601  		if err != nil {
   602  			result.Results[i].Error = common.ServerError(common.ErrPerm)
   603  			continue
   604  		}
   605  		err = common.ErrPerm
   606  		if canAccess(tag) {
   607  			var unit *state.Unit
   608  			unit, err = u.getUnit(tag)
   609  			if err == nil {
   610  				principal, ok := unit.PrincipalName()
   611  				if principal != "" {
   612  					result.Results[i].Result = names.NewUnitTag(principal).String()
   613  				}
   614  				result.Results[i].Ok = ok
   615  			}
   616  		}
   617  		result.Results[i].Error = common.ServerError(err)
   618  	}
   619  	return result, nil
   620  }
   621  
   622  // Destroy advances all given Alive units' lifecycles as far as
   623  // possible. See state/Unit.Destroy().
   624  func (u *UniterAPI) Destroy(args params.Entities) (params.ErrorResults, error) {
   625  	result := params.ErrorResults{
   626  		Results: make([]params.ErrorResult, len(args.Entities)),
   627  	}
   628  	canAccess, err := u.accessUnit()
   629  	if err != nil {
   630  		return params.ErrorResults{}, err
   631  	}
   632  	for i, entity := range args.Entities {
   633  		tag, err := names.ParseUnitTag(entity.Tag)
   634  		if err != nil {
   635  			result.Results[i].Error = common.ServerError(common.ErrPerm)
   636  			continue
   637  		}
   638  		err = common.ErrPerm
   639  		if canAccess(tag) {
   640  			var unit *state.Unit
   641  			unit, err = u.getUnit(tag)
   642  			if err == nil {
   643  				err = unit.Destroy()
   644  			}
   645  		}
   646  		result.Results[i].Error = common.ServerError(err)
   647  	}
   648  	return result, nil
   649  }
   650  
   651  // DestroyAllSubordinates destroys all subordinates of each given unit.
   652  func (u *UniterAPI) DestroyAllSubordinates(args params.Entities) (params.ErrorResults, error) {
   653  	result := params.ErrorResults{
   654  		Results: make([]params.ErrorResult, len(args.Entities)),
   655  	}
   656  	canAccess, err := u.accessUnit()
   657  	if err != nil {
   658  		return params.ErrorResults{}, err
   659  	}
   660  	for i, entity := range args.Entities {
   661  		tag, err := names.ParseUnitTag(entity.Tag)
   662  		if err != nil {
   663  			result.Results[i].Error = common.ServerError(common.ErrPerm)
   664  			continue
   665  		}
   666  		err = common.ErrPerm
   667  		if canAccess(tag) {
   668  			var unit *state.Unit
   669  			unit, err = u.getUnit(tag)
   670  			if err == nil {
   671  				err = u.destroySubordinates(unit)
   672  			}
   673  		}
   674  		result.Results[i].Error = common.ServerError(err)
   675  	}
   676  	return result, nil
   677  }
   678  
   679  // HasSubordinates returns the whether each given unit has any subordinates.
   680  func (u *UniterAPI) HasSubordinates(args params.Entities) (params.BoolResults, error) {
   681  	result := params.BoolResults{
   682  		Results: make([]params.BoolResult, len(args.Entities)),
   683  	}
   684  	canAccess, err := u.accessUnit()
   685  	if err != nil {
   686  		return params.BoolResults{}, err
   687  	}
   688  	for i, entity := range args.Entities {
   689  		tag, err := names.ParseUnitTag(entity.Tag)
   690  		if err != nil {
   691  			result.Results[i].Error = common.ServerError(common.ErrPerm)
   692  			continue
   693  		}
   694  		err = common.ErrPerm
   695  		if canAccess(tag) {
   696  			var unit *state.Unit
   697  			unit, err = u.getUnit(tag)
   698  			if err == nil {
   699  				subordinates := unit.SubordinateNames()
   700  				result.Results[i].Result = len(subordinates) > 0
   701  			}
   702  		}
   703  		result.Results[i].Error = common.ServerError(err)
   704  	}
   705  	return result, nil
   706  }
   707  
   708  // CharmModifiedVersion returns the most CharmModifiedVersion for all given
   709  // units or applications.
   710  func (u *UniterAPI) CharmModifiedVersion(args params.Entities) (params.IntResults, error) {
   711  	results := params.IntResults{
   712  		Results: make([]params.IntResult, len(args.Entities)),
   713  	}
   714  
   715  	accessUnitOrApplication := common.AuthAny(u.accessUnit, u.accessApplication)
   716  	canAccess, err := accessUnitOrApplication()
   717  	if err != nil {
   718  		return results, err
   719  	}
   720  	for i, entity := range args.Entities {
   721  		ver, err := u.charmModifiedVersion(entity.Tag, canAccess)
   722  		if err != nil {
   723  			results.Results[i].Error = common.ServerError(err)
   724  			continue
   725  		}
   726  		results.Results[i].Result = ver
   727  	}
   728  	return results, nil
   729  }
   730  
   731  func (u *UniterAPI) charmModifiedVersion(tagStr string, canAccess func(names.Tag) bool) (int, error) {
   732  	tag, err := names.ParseTag(tagStr)
   733  	if err != nil {
   734  		return -1, common.ErrPerm
   735  	}
   736  	if !canAccess(tag) {
   737  		return -1, common.ErrPerm
   738  	}
   739  	unitOrApplication, err := u.st.FindEntity(tag)
   740  	if err != nil {
   741  		return -1, err
   742  	}
   743  	var application *state.Application
   744  	switch entity := unitOrApplication.(type) {
   745  	case *state.Application:
   746  		application = entity
   747  	case *state.Unit:
   748  		application, err = entity.Application()
   749  		if err != nil {
   750  			return -1, err
   751  		}
   752  	default:
   753  		return -1, errors.BadRequestf("type %T does not have a CharmModifiedVersion", entity)
   754  	}
   755  	return application.CharmModifiedVersion(), nil
   756  }
   757  
   758  // CharmURL returns the charm URL for all given units or applications.
   759  func (u *UniterAPI) CharmURL(args params.Entities) (params.StringBoolResults, error) {
   760  	result := params.StringBoolResults{
   761  		Results: make([]params.StringBoolResult, len(args.Entities)),
   762  	}
   763  	accessUnitOrApplication := common.AuthAny(u.accessUnit, u.accessApplication)
   764  	canAccess, err := accessUnitOrApplication()
   765  	if err != nil {
   766  		return params.StringBoolResults{}, err
   767  	}
   768  	for i, entity := range args.Entities {
   769  		tag, err := names.ParseTag(entity.Tag)
   770  		if err != nil {
   771  			result.Results[i].Error = common.ServerError(common.ErrPerm)
   772  			continue
   773  		}
   774  		err = common.ErrPerm
   775  		if canAccess(tag) {
   776  			var unitOrApplication state.Entity
   777  			unitOrApplication, err = u.st.FindEntity(tag)
   778  			if err == nil {
   779  				charmURLer := unitOrApplication.(interface {
   780  					CharmURL() (*charm.URL, bool)
   781  				})
   782  				curl, ok := charmURLer.CharmURL()
   783  				if curl != nil {
   784  					result.Results[i].Result = curl.String()
   785  					result.Results[i].Ok = ok
   786  				}
   787  			}
   788  		}
   789  		result.Results[i].Error = common.ServerError(err)
   790  	}
   791  	return result, nil
   792  }
   793  
   794  // SetCharmURL sets the charm URL for each given unit. An error will
   795  // be returned if a unit is dead, or the charm URL is not know.
   796  func (u *UniterAPI) SetCharmURL(args params.EntitiesCharmURL) (params.ErrorResults, error) {
   797  	result := params.ErrorResults{
   798  		Results: make([]params.ErrorResult, len(args.Entities)),
   799  	}
   800  	canAccess, err := u.accessUnit()
   801  	if err != nil {
   802  		return params.ErrorResults{}, err
   803  	}
   804  	for i, entity := range args.Entities {
   805  		tag, err := names.ParseUnitTag(entity.Tag)
   806  		if err != nil {
   807  			result.Results[i].Error = common.ServerError(common.ErrPerm)
   808  			continue
   809  		}
   810  		err = common.ErrPerm
   811  		if canAccess(tag) {
   812  			var unit *state.Unit
   813  			unit, err = u.getUnit(tag)
   814  			if err == nil {
   815  				var curl *charm.URL
   816  				curl, err = charm.ParseURL(entity.CharmURL)
   817  				if err == nil {
   818  					err = unit.SetCharmURL(curl)
   819  				}
   820  			}
   821  		}
   822  		result.Results[i].Error = common.ServerError(err)
   823  	}
   824  	return result, nil
   825  }
   826  
   827  // WorkloadVersion returns the workload version for all given units or applications.
   828  func (u *UniterAPI) WorkloadVersion(args params.Entities) (params.StringResults, error) {
   829  	result := params.StringResults{
   830  		Results: make([]params.StringResult, len(args.Entities)),
   831  	}
   832  	canAccess, err := u.accessUnit()
   833  	if err != nil {
   834  		return params.StringResults{}, err
   835  	}
   836  	for i, entity := range args.Entities {
   837  		resultItem := &result.Results[i]
   838  		tag, err := names.ParseUnitTag(entity.Tag)
   839  		if err != nil {
   840  			resultItem.Error = common.ServerError(err)
   841  			continue
   842  		}
   843  		if !canAccess(tag) {
   844  			resultItem.Error = common.ServerError(common.ErrPerm)
   845  			continue
   846  		}
   847  		unit, err := u.getUnit(tag)
   848  		if err != nil {
   849  			resultItem.Error = common.ServerError(err)
   850  			continue
   851  		}
   852  		version, err := unit.WorkloadVersion()
   853  		if err != nil {
   854  			resultItem.Error = common.ServerError(err)
   855  			continue
   856  		}
   857  		resultItem.Result = version
   858  	}
   859  	return result, nil
   860  }
   861  
   862  // SetWorkloadVersion sets the workload version for each given unit. An error will
   863  // be returned if a unit is dead.
   864  func (u *UniterAPI) SetWorkloadVersion(args params.EntityWorkloadVersions) (params.ErrorResults, error) {
   865  	result := params.ErrorResults{
   866  		Results: make([]params.ErrorResult, len(args.Entities)),
   867  	}
   868  	canAccess, err := u.accessUnit()
   869  	if err != nil {
   870  		return params.ErrorResults{}, err
   871  	}
   872  	for i, entity := range args.Entities {
   873  		resultItem := &result.Results[i]
   874  		tag, err := names.ParseUnitTag(entity.Tag)
   875  		if err != nil {
   876  			resultItem.Error = common.ServerError(err)
   877  			continue
   878  		}
   879  		if !canAccess(tag) {
   880  			resultItem.Error = common.ServerError(common.ErrPerm)
   881  			continue
   882  		}
   883  		unit, err := u.getUnit(tag)
   884  		if err != nil {
   885  			resultItem.Error = common.ServerError(err)
   886  			continue
   887  		}
   888  		err = unit.SetWorkloadVersion(entity.WorkloadVersion)
   889  		if err != nil {
   890  			resultItem.Error = common.ServerError(err)
   891  		}
   892  	}
   893  	return result, nil
   894  }
   895  
   896  // OpenPorts sets the policy of the port range with protocol to be
   897  // opened, for all given units.
   898  func (u *UniterAPI) OpenPorts(args params.EntitiesPortRanges) (params.ErrorResults, error) {
   899  	result := params.ErrorResults{
   900  		Results: make([]params.ErrorResult, len(args.Entities)),
   901  	}
   902  	canAccess, err := u.accessUnit()
   903  	if err != nil {
   904  		return params.ErrorResults{}, err
   905  	}
   906  	for i, entity := range args.Entities {
   907  		tag, err := names.ParseUnitTag(entity.Tag)
   908  		if err != nil {
   909  			result.Results[i].Error = common.ServerError(common.ErrPerm)
   910  			continue
   911  		}
   912  		err = common.ErrPerm
   913  		if canAccess(tag) {
   914  			var unit *state.Unit
   915  			unit, err = u.getUnit(tag)
   916  			if err == nil {
   917  				err = unit.OpenPorts(entity.Protocol, entity.FromPort, entity.ToPort)
   918  			}
   919  		}
   920  		result.Results[i].Error = common.ServerError(err)
   921  	}
   922  	return result, nil
   923  }
   924  
   925  // ClosePorts sets the policy of the port range with protocol to be
   926  // closed, for all given units.
   927  func (u *UniterAPI) ClosePorts(args params.EntitiesPortRanges) (params.ErrorResults, error) {
   928  	result := params.ErrorResults{
   929  		Results: make([]params.ErrorResult, len(args.Entities)),
   930  	}
   931  	canAccess, err := u.accessUnit()
   932  	if err != nil {
   933  		return params.ErrorResults{}, err
   934  	}
   935  	for i, entity := range args.Entities {
   936  		tag, err := names.ParseUnitTag(entity.Tag)
   937  		if err != nil {
   938  			result.Results[i].Error = common.ServerError(common.ErrPerm)
   939  			continue
   940  		}
   941  		err = common.ErrPerm
   942  		if canAccess(tag) {
   943  			var unit *state.Unit
   944  			unit, err = u.getUnit(tag)
   945  			if err == nil {
   946  				err = unit.ClosePorts(entity.Protocol, entity.FromPort, entity.ToPort)
   947  			}
   948  		}
   949  		result.Results[i].Error = common.ServerError(err)
   950  	}
   951  	return result, nil
   952  }
   953  
   954  // WatchConfigSettings returns a NotifyWatcher for observing changes
   955  // to each unit's application configuration settings. See also
   956  // state/watcher.go:Unit.WatchConfigSettings().
   957  func (u *UniterAPIV8) WatchConfigSettings(args params.Entities) (params.NotifyWatchResults, error) {
   958  	watcherFn := func(u *state.Unit) (state.NotifyWatcher, error) {
   959  		return u.WatchConfigSettings()
   960  	}
   961  	result, err := u.WatchSettings(args, watcherFn)
   962  	if err != nil {
   963  		return params.NotifyWatchResults{}, errors.Trace(err)
   964  	}
   965  
   966  	return result, nil
   967  }
   968  
   969  func (u *UniterAPIV8) WatchTrustConfigSettings(args params.Entities) (params.NotifyWatchResults, error) {
   970  	watcherFn := func(u *state.Unit) (state.NotifyWatcher, error) {
   971  		return u.WatchApplicationConfigSettings()
   972  	}
   973  	result, err := u.WatchSettings(args, watcherFn)
   974  	if err != nil {
   975  		return params.NotifyWatchResults{}, errors.Trace(err)
   976  	}
   977  
   978  	return result, nil
   979  }
   980  
   981  func (u *UniterAPIV8) WatchSettings(args params.Entities, configWatcherFn func(u *state.Unit) (state.NotifyWatcher, error)) (params.NotifyWatchResults, error) {
   982  	result := params.NotifyWatchResults{
   983  		Results: make([]params.NotifyWatchResult, len(args.Entities)),
   984  	}
   985  	canAccess, err := u.accessUnit()
   986  	if err != nil {
   987  		return params.NotifyWatchResults{}, err
   988  	}
   989  	for i, entity := range args.Entities {
   990  		tag, err := names.ParseUnitTag(entity.Tag)
   991  		if err != nil {
   992  			result.Results[i].Error = common.ServerError(common.ErrPerm)
   993  			continue
   994  		}
   995  		err = common.ErrPerm
   996  		watcherId := ""
   997  		if canAccess(tag) {
   998  			watcherId, err = u.watchOneUnitConfigSettings(tag, configWatcherFn)
   999  		}
  1000  		result.Results[i].NotifyWatcherId = watcherId
  1001  		result.Results[i].Error = common.ServerError(err)
  1002  	}
  1003  	return result, nil
  1004  }
  1005  
  1006  // WatchActionNotifications returns a StringsWatcher for observing
  1007  // incoming action calls to a unit. See also state/watcher.go
  1008  // Unit.WatchActionNotifications(). This method is called from
  1009  // api/uniter/uniter.go WatchActionNotifications().
  1010  func (u *UniterAPI) WatchActionNotifications(args params.Entities) (params.StringsWatchResults, error) {
  1011  	tagToActionReceiver := common.TagToActionReceiverFn(u.st.FindEntity)
  1012  	watchOne := common.WatchOneActionReceiverNotifications(tagToActionReceiver, u.resources.Register)
  1013  	canAccess, err := u.accessUnit()
  1014  	if err != nil {
  1015  		return params.StringsWatchResults{}, err
  1016  	}
  1017  	return common.WatchActionNotifications(args, canAccess, watchOne), nil
  1018  }
  1019  
  1020  // ConfigSettings returns the complete set of application charm config
  1021  // settings available to each given unit.
  1022  func (u *UniterAPI) ConfigSettings(args params.Entities) (params.ConfigSettingsResults, error) {
  1023  	result := params.ConfigSettingsResults{
  1024  		Results: make([]params.ConfigSettingsResult, len(args.Entities)),
  1025  	}
  1026  	canAccess, err := u.accessUnit()
  1027  	if err != nil {
  1028  		return params.ConfigSettingsResults{}, err
  1029  	}
  1030  	for i, entity := range args.Entities {
  1031  		tag, err := names.ParseUnitTag(entity.Tag)
  1032  		if err != nil {
  1033  			result.Results[i].Error = common.ServerError(common.ErrPerm)
  1034  			continue
  1035  		}
  1036  		err = common.ErrPerm
  1037  		if canAccess(tag) {
  1038  			var unit *state.Unit
  1039  			unit, err = u.getUnit(tag)
  1040  			if err == nil {
  1041  				var settings charm.Settings
  1042  				settings, err = unit.ConfigSettings()
  1043  				if err == nil {
  1044  					result.Results[i].Settings = params.ConfigSettings(settings)
  1045  				}
  1046  			}
  1047  		}
  1048  		result.Results[i].Error = common.ServerError(err)
  1049  	}
  1050  	return result, nil
  1051  }
  1052  
  1053  // CharmArchiveSha256 returns the SHA256 digest of the charm archive
  1054  // (bundle) data for each charm url in the given parameters.
  1055  func (u *UniterAPI) CharmArchiveSha256(args params.CharmURLs) (params.StringResults, error) {
  1056  	result := params.StringResults{
  1057  		Results: make([]params.StringResult, len(args.URLs)),
  1058  	}
  1059  	for i, arg := range args.URLs {
  1060  		curl, err := charm.ParseURL(arg.URL)
  1061  		if err != nil {
  1062  			err = common.ErrPerm
  1063  		} else {
  1064  			var sch *state.Charm
  1065  			sch, err = u.st.Charm(curl)
  1066  			if errors.IsNotFound(err) {
  1067  				err = common.ErrPerm
  1068  			}
  1069  			if err == nil {
  1070  				result.Results[i].Result = sch.BundleSha256()
  1071  			}
  1072  		}
  1073  		result.Results[i].Error = common.ServerError(err)
  1074  	}
  1075  	return result, nil
  1076  }
  1077  
  1078  // Relation returns information about all given relation/unit pairs,
  1079  // including their id, key and the local endpoint.
  1080  func (u *UniterAPI) Relation(args params.RelationUnits) (params.RelationResults, error) {
  1081  	result := params.RelationResults{
  1082  		Results: make([]params.RelationResult, len(args.RelationUnits)),
  1083  	}
  1084  	canAccess, err := u.accessUnit()
  1085  	if err != nil {
  1086  		return params.RelationResults{}, err
  1087  	}
  1088  	for i, rel := range args.RelationUnits {
  1089  		relParams, err := u.getOneRelation(canAccess, rel.Relation, rel.Unit)
  1090  		if err == nil {
  1091  			result.Results[i] = relParams
  1092  		}
  1093  		result.Results[i].Error = common.ServerError(err)
  1094  	}
  1095  	return result, nil
  1096  }
  1097  
  1098  // Actions returns the Actions by Tags passed and ensures that the Unit asking
  1099  // for them is the same Unit that has the Actions.
  1100  func (u *UniterAPI) Actions(args params.Entities) (params.ActionResults, error) {
  1101  	canAccess, err := u.accessUnit()
  1102  	if err != nil {
  1103  		return params.ActionResults{}, err
  1104  	}
  1105  
  1106  	m, err := u.st.Model()
  1107  	if err != nil {
  1108  		return params.ActionResults{}, errors.Trace(err)
  1109  	}
  1110  
  1111  	actionFn := common.AuthAndActionFromTagFn(canAccess, m.ActionByTag)
  1112  	return common.Actions(args, actionFn), nil
  1113  }
  1114  
  1115  // BeginActions marks the actions represented by the passed in Tags as running.
  1116  func (u *UniterAPI) BeginActions(args params.Entities) (params.ErrorResults, error) {
  1117  	canAccess, err := u.accessUnit()
  1118  	if err != nil {
  1119  		return params.ErrorResults{}, err
  1120  	}
  1121  
  1122  	m, err := u.st.Model()
  1123  	if err != nil {
  1124  		return params.ErrorResults{}, errors.Trace(err)
  1125  	}
  1126  
  1127  	actionFn := common.AuthAndActionFromTagFn(canAccess, m.ActionByTag)
  1128  	return common.BeginActions(args, actionFn), nil
  1129  }
  1130  
  1131  // FinishActions saves the result of a completed Action
  1132  func (u *UniterAPI) FinishActions(args params.ActionExecutionResults) (params.ErrorResults, error) {
  1133  	canAccess, err := u.accessUnit()
  1134  	if err != nil {
  1135  		return params.ErrorResults{}, err
  1136  	}
  1137  
  1138  	m, err := u.st.Model()
  1139  	if err != nil {
  1140  		return params.ErrorResults{}, errors.Trace(err)
  1141  	}
  1142  
  1143  	actionFn := common.AuthAndActionFromTagFn(canAccess, m.ActionByTag)
  1144  	return common.FinishActions(args, actionFn), nil
  1145  }
  1146  
  1147  // RelationById returns information about all given relations,
  1148  // specified by their ids, including their key and the local
  1149  // endpoint.
  1150  func (u *UniterAPI) RelationById(args params.RelationIds) (params.RelationResults, error) {
  1151  	result := params.RelationResults{
  1152  		Results: make([]params.RelationResult, len(args.RelationIds)),
  1153  	}
  1154  	for i, relId := range args.RelationIds {
  1155  		relParams, err := u.getOneRelationById(relId)
  1156  		if err == nil {
  1157  			result.Results[i] = relParams
  1158  		}
  1159  		result.Results[i].Error = common.ServerError(err)
  1160  	}
  1161  	return result, nil
  1162  }
  1163  
  1164  // JoinedRelations returns the tags of all relations for which each supplied unit
  1165  // has entered scope.
  1166  // TODO(wallyworld) - this API is replaced by RelationsStatus
  1167  func (u *UniterAPIV6) JoinedRelations(args params.Entities) (params.StringsResults, error) {
  1168  	result := params.StringsResults{
  1169  		Results: make([]params.StringsResult, len(args.Entities)),
  1170  	}
  1171  	if len(args.Entities) == 0 {
  1172  		return result, nil
  1173  	}
  1174  	canRead, err := u.accessUnit()
  1175  	if err != nil {
  1176  		return params.StringsResults{}, err
  1177  	}
  1178  	for i, entity := range args.Entities {
  1179  		tag, 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  		if canRead(tag) {
  1186  			var unit *state.Unit
  1187  			unit, err = u.getUnit(tag)
  1188  			if err == nil {
  1189  				result.Results[i].Result, err = relationsInScopeTags(unit)
  1190  			}
  1191  		}
  1192  		result.Results[i].Error = common.ServerError(err)
  1193  	}
  1194  	return result, nil
  1195  }
  1196  
  1197  // RelationsStatus returns for each unit the corresponding relation and status information.
  1198  func (u *UniterAPI) RelationsStatus(args params.Entities) (params.RelationUnitStatusResults, error) {
  1199  	result := params.RelationUnitStatusResults{
  1200  		Results: make([]params.RelationUnitStatusResult, len(args.Entities)),
  1201  	}
  1202  	if len(args.Entities) == 0 {
  1203  		return result, nil
  1204  	}
  1205  	canRead, err := u.accessUnit()
  1206  	if err != nil {
  1207  		return params.RelationUnitStatusResults{}, err
  1208  	}
  1209  
  1210  	oneRelationUnitStatus := func(rel *state.Relation, unit *state.Unit) (params.RelationUnitStatus, error) {
  1211  		rus := params.RelationUnitStatus{
  1212  			RelationTag: rel.Tag().String(),
  1213  			Suspended:   rel.Suspended(),
  1214  		}
  1215  		ru, err := rel.Unit(unit)
  1216  		if err != nil {
  1217  			return params.RelationUnitStatus{}, errors.Trace(err)
  1218  		}
  1219  		inScope, err := ru.InScope()
  1220  		if err != nil {
  1221  			return params.RelationUnitStatus{}, errors.Trace(err)
  1222  		}
  1223  		rus.InScope = inScope
  1224  		return rus, nil
  1225  	}
  1226  
  1227  	relationResults := func(unit *state.Unit) ([]params.RelationUnitStatus, error) {
  1228  		var ruStatus []params.RelationUnitStatus
  1229  		app, err := unit.Application()
  1230  		if err != nil {
  1231  			return nil, errors.Trace(err)
  1232  		}
  1233  		relations, err := app.Relations()
  1234  		for _, rel := range relations {
  1235  			rus, err := oneRelationUnitStatus(rel, unit)
  1236  			if err != nil {
  1237  				return nil, errors.Trace(err)
  1238  			}
  1239  			ruStatus = append(ruStatus, rus)
  1240  		}
  1241  		return ruStatus, nil
  1242  	}
  1243  
  1244  	for i, entity := range args.Entities {
  1245  		tag, err := names.ParseUnitTag(entity.Tag)
  1246  		if err != nil {
  1247  			result.Results[i].Error = common.ServerError(common.ErrPerm)
  1248  			continue
  1249  		}
  1250  		err = common.ErrPerm
  1251  		if canRead(tag) {
  1252  			var unit *state.Unit
  1253  			unit, err = u.getUnit(tag)
  1254  			if err == nil {
  1255  				result.Results[i].RelationResults, err = relationResults(unit)
  1256  			}
  1257  		}
  1258  		result.Results[i].Error = common.ServerError(err)
  1259  	}
  1260  	return result, nil
  1261  }
  1262  
  1263  // Refresh retrieves the latest values for attributes on this unit.
  1264  func (u *UniterAPI) Refresh(args params.Entities) (params.UnitRefreshResults, error) {
  1265  	result := params.UnitRefreshResults{
  1266  		Results: make([]params.UnitRefreshResult, len(args.Entities)),
  1267  	}
  1268  	if len(args.Entities) == 0 {
  1269  		return result, nil
  1270  	}
  1271  	canRead, err := u.accessUnit()
  1272  	if err != nil {
  1273  		return params.UnitRefreshResults{}, err
  1274  	}
  1275  	for i, entity := range args.Entities {
  1276  		tag, err := names.ParseUnitTag(entity.Tag)
  1277  		if err != nil {
  1278  			result.Results[i].Error = common.ServerError(common.ErrPerm)
  1279  			continue
  1280  		}
  1281  		err = common.ErrPerm
  1282  		if canRead(tag) {
  1283  			var unit *state.Unit
  1284  			if unit, err = u.getUnit(tag); err == nil {
  1285  				result.Results[i].Life = params.Life(unit.Life().String())
  1286  				result.Results[i].Resolved = params.ResolvedMode(unit.Resolved())
  1287  			}
  1288  		}
  1289  		result.Results[i].Error = common.ServerError(err)
  1290  	}
  1291  	return result, nil
  1292  }
  1293  
  1294  // CurrentModel returns the name and UUID for the current juju model.
  1295  func (u *UniterAPI) CurrentModel() (params.ModelResult, error) {
  1296  	result := params.ModelResult{}
  1297  	model, err := u.st.Model()
  1298  	if err == nil {
  1299  		result.Name = model.Name()
  1300  		result.UUID = model.UUID()
  1301  		result.Type = string(model.Type())
  1302  	}
  1303  	return result, err
  1304  }
  1305  
  1306  // ProviderType returns the provider type used by the current juju
  1307  // model.
  1308  //
  1309  // TODO(dimitern): Refactor the uniter to call this instead of calling
  1310  // ModelConfig() just to get the provider type. Once we have machine
  1311  // addresses, this might be completely unnecessary though.
  1312  func (u *UniterAPI) ProviderType() (params.StringResult, error) {
  1313  	result := params.StringResult{}
  1314  	cfg, err := u.m.ModelConfig()
  1315  	if err == nil {
  1316  		result.Result = cfg.Type()
  1317  	}
  1318  	return result, err
  1319  }
  1320  
  1321  // EnterScope ensures each unit has entered its scope in the relation,
  1322  // for all of the given relation/unit pairs. See also
  1323  // state.RelationUnit.EnterScope().
  1324  func (u *UniterAPI) EnterScope(args params.RelationUnits) (params.ErrorResults, error) {
  1325  	result := params.ErrorResults{
  1326  		Results: make([]params.ErrorResult, len(args.RelationUnits)),
  1327  	}
  1328  	canAccess, err := u.accessUnit()
  1329  	if err != nil {
  1330  		return params.ErrorResults{}, err
  1331  	}
  1332  	one := func(relTag string, unitTag names.UnitTag, modelSubnets []string) error {
  1333  		rel, unit, err := u.getRelationAndUnit(canAccess, relTag, unitTag)
  1334  		if err != nil {
  1335  			return err
  1336  		}
  1337  		relUnit, err := rel.Unit(unit)
  1338  		if err != nil {
  1339  			return err
  1340  		}
  1341  
  1342  		valid, err := relUnit.Valid()
  1343  		if err != nil {
  1344  			return err
  1345  		}
  1346  		if !valid {
  1347  			principalName, _ := unit.PrincipalName()
  1348  			logger.Debugf("ignoring %q EnterScope for %q - unit has invalid principal %q",
  1349  				unit.Name(), rel.String(), principalName)
  1350  			return nil
  1351  		}
  1352  
  1353  		settings := map[string]interface{}{}
  1354  		_, ingressAddresses, egressSubnets, err := state.NetworksForRelation(relUnit.Endpoint().Name, unit, rel, modelSubnets)
  1355  		if err == nil && len(ingressAddresses) > 0 {
  1356  			ingressAddress := ingressAddresses[0]
  1357  			// private-address is historically a cloud local address for the machine.
  1358  			// Existing charms are built to ask for this attribute from relation
  1359  			// settings to find out what address to use to connect to the app
  1360  			// on the other side of a relation. For cross model scenarios, we'll
  1361  			// replace this with possibly a public address; we expect to fix more
  1362  			// charms than we break - breakage will not occur for correctly written
  1363  			// charms, since the semantics of this value dictates the use case described.
  1364  			// Any other use goes against the intended purpose of this value.
  1365  			settings["private-address"] = ingressAddress
  1366  			// ingress-address is the preferred settings attribute name as it more accurately
  1367  			// reflects the purpose of the attribute value. We'll deprecate private-address.
  1368  			settings["ingress-address"] = ingressAddress
  1369  		} else {
  1370  			logger.Warningf("cannot set ingress/egress addresses for unit %v in relation %v: %v", unitTag.Id(), relTag, err)
  1371  		}
  1372  		if len(egressSubnets) > 0 {
  1373  			settings["egress-subnets"] = strings.Join(egressSubnets, ",")
  1374  		}
  1375  		return relUnit.EnterScope(settings)
  1376  	}
  1377  	cfg, err := u.m.ModelConfig()
  1378  	if err != nil {
  1379  		return params.ErrorResults{}, errors.Trace(err)
  1380  	}
  1381  	for i, arg := range args.RelationUnits {
  1382  		tag, err := names.ParseUnitTag(arg.Unit)
  1383  		if err != nil {
  1384  			result.Results[i].Error = common.ServerError(common.ErrPerm)
  1385  			continue
  1386  		}
  1387  		err = one(arg.Relation, tag, cfg.EgressSubnets())
  1388  		if err != nil {
  1389  			result.Results[i].Error = common.ServerError(err)
  1390  		}
  1391  	}
  1392  	return result, nil
  1393  }
  1394  
  1395  // LeaveScope signals each unit has left its scope in the relation,
  1396  // for all of the given relation/unit pairs. See also
  1397  // state.RelationUnit.LeaveScope().
  1398  func (u *UniterAPI) LeaveScope(args params.RelationUnits) (params.ErrorResults, error) {
  1399  	result := params.ErrorResults{
  1400  		Results: make([]params.ErrorResult, len(args.RelationUnits)),
  1401  	}
  1402  	canAccess, err := u.accessUnit()
  1403  	if err != nil {
  1404  		return params.ErrorResults{}, err
  1405  	}
  1406  	for i, arg := range args.RelationUnits {
  1407  		unit, err := names.ParseUnitTag(arg.Unit)
  1408  		if err != nil {
  1409  			result.Results[i].Error = common.ServerError(common.ErrPerm)
  1410  			continue
  1411  		}
  1412  		relUnit, err := u.getRelationUnit(canAccess, arg.Relation, unit)
  1413  		if err == nil {
  1414  			err = relUnit.LeaveScope()
  1415  		}
  1416  		result.Results[i].Error = common.ServerError(err)
  1417  	}
  1418  	return result, nil
  1419  }
  1420  
  1421  // ReadSettings returns the local settings of each given set of
  1422  // relation/unit.
  1423  func (u *UniterAPI) ReadSettings(args params.RelationUnits) (params.SettingsResults, error) {
  1424  	result := params.SettingsResults{
  1425  		Results: make([]params.SettingsResult, len(args.RelationUnits)),
  1426  	}
  1427  	canAccess, err := u.accessUnit()
  1428  	if err != nil {
  1429  		return params.SettingsResults{}, err
  1430  	}
  1431  	for i, arg := range args.RelationUnits {
  1432  		unit, err := names.ParseUnitTag(arg.Unit)
  1433  		if err != nil {
  1434  			result.Results[i].Error = common.ServerError(common.ErrPerm)
  1435  			continue
  1436  		}
  1437  		relUnit, err := u.getRelationUnit(canAccess, arg.Relation, unit)
  1438  		if err == nil {
  1439  			var settings *state.Settings
  1440  			settings, err = relUnit.Settings()
  1441  			if err == nil {
  1442  				result.Results[i].Settings, err = convertRelationSettings(settings.Map())
  1443  			}
  1444  		}
  1445  		result.Results[i].Error = common.ServerError(err)
  1446  	}
  1447  	return result, nil
  1448  }
  1449  
  1450  // ReadRemoteSettings returns the remote settings of each given set of
  1451  // relation/local unit/remote unit.
  1452  func (u *UniterAPI) ReadRemoteSettings(args params.RelationUnitPairs) (params.SettingsResults, error) {
  1453  	result := params.SettingsResults{
  1454  		Results: make([]params.SettingsResult, len(args.RelationUnitPairs)),
  1455  	}
  1456  	canAccess, err := u.accessUnit()
  1457  	if err != nil {
  1458  		return params.SettingsResults{}, err
  1459  	}
  1460  	for i, arg := range args.RelationUnitPairs {
  1461  		unit, err := names.ParseUnitTag(arg.LocalUnit)
  1462  		if err != nil {
  1463  			result.Results[i].Error = common.ServerError(common.ErrPerm)
  1464  			continue
  1465  		}
  1466  		relUnit, err := u.getRelationUnit(canAccess, arg.Relation, unit)
  1467  		if err == nil {
  1468  			// TODO(dfc) rework this logic
  1469  			remoteUnit := ""
  1470  			remoteUnit, err = u.checkRemoteUnit(relUnit, arg.RemoteUnit)
  1471  			if err == nil {
  1472  				var settings map[string]interface{}
  1473  				settings, err = relUnit.ReadSettings(remoteUnit)
  1474  				if err == nil {
  1475  					result.Results[i].Settings, err = convertRelationSettings(settings)
  1476  				}
  1477  			}
  1478  		}
  1479  		result.Results[i].Error = common.ServerError(err)
  1480  	}
  1481  	return result, nil
  1482  }
  1483  
  1484  // UpdateSettings persists all changes made to the local settings of
  1485  // all given pairs of relation and unit. Keys with empty values are
  1486  // considered a signal to delete these values.
  1487  func (u *UniterAPI) UpdateSettings(args params.RelationUnitsSettings) (params.ErrorResults, error) {
  1488  	result := params.ErrorResults{
  1489  		Results: make([]params.ErrorResult, len(args.RelationUnits)),
  1490  	}
  1491  	canAccess, err := u.accessUnit()
  1492  	if err != nil {
  1493  		return params.ErrorResults{}, err
  1494  	}
  1495  	for i, arg := range args.RelationUnits {
  1496  		unit, err := names.ParseUnitTag(arg.Unit)
  1497  		if err != nil {
  1498  			result.Results[i].Error = common.ServerError(common.ErrPerm)
  1499  			continue
  1500  		}
  1501  		relUnit, err := u.getRelationUnit(canAccess, arg.Relation, unit)
  1502  		if err == nil {
  1503  			var settings *state.Settings
  1504  			settings, err = relUnit.Settings()
  1505  			if err == nil {
  1506  				for k, v := range arg.Settings {
  1507  					if v == "" {
  1508  						settings.Delete(k)
  1509  					} else {
  1510  						settings.Set(k, v)
  1511  					}
  1512  				}
  1513  				_, err = settings.Write()
  1514  			}
  1515  		}
  1516  		result.Results[i].Error = common.ServerError(err)
  1517  	}
  1518  	return result, nil
  1519  }
  1520  
  1521  // WatchRelationUnits returns a RelationUnitsWatcher for observing
  1522  // changes to every unit in the supplied relation that is visible to
  1523  // the supplied unit. See also state/watcher.go:RelationUnit.Watch().
  1524  func (u *UniterAPI) WatchRelationUnits(args params.RelationUnits) (params.RelationUnitsWatchResults, error) {
  1525  	result := params.RelationUnitsWatchResults{
  1526  		Results: make([]params.RelationUnitsWatchResult, len(args.RelationUnits)),
  1527  	}
  1528  	canAccess, err := u.accessUnit()
  1529  	if err != nil {
  1530  		return params.RelationUnitsWatchResults{}, err
  1531  	}
  1532  	for i, arg := range args.RelationUnits {
  1533  		unit, err := names.ParseUnitTag(arg.Unit)
  1534  		if err != nil {
  1535  			result.Results[i].Error = common.ServerError(common.ErrPerm)
  1536  			continue
  1537  		}
  1538  		relUnit, err := u.getRelationUnit(canAccess, arg.Relation, unit)
  1539  		if err == nil {
  1540  			result.Results[i], err = u.watchOneRelationUnit(relUnit)
  1541  		}
  1542  		result.Results[i].Error = common.ServerError(err)
  1543  	}
  1544  	return result, nil
  1545  }
  1546  
  1547  // SetRelationStatus updates the status of the specified relations.
  1548  func (u *UniterAPI) SetRelationStatus(args params.RelationStatusArgs) (params.ErrorResults, error) {
  1549  	var statusResults params.ErrorResults
  1550  
  1551  	unitCache := make(map[string]*state.Unit)
  1552  	getUnit := func(tag string) (*state.Unit, error) {
  1553  		if unit, ok := unitCache[tag]; ok {
  1554  			return unit, nil
  1555  		}
  1556  		unitTag, err := names.ParseUnitTag(tag)
  1557  		if err != nil {
  1558  			return nil, errors.Trace(err)
  1559  		}
  1560  		unit, err := u.st.Unit(unitTag.Id())
  1561  		if errors.IsNotFound(err) {
  1562  			return nil, common.ErrPerm
  1563  		}
  1564  		if err != nil {
  1565  			return nil, errors.Trace(err)
  1566  		}
  1567  		unitCache[tag] = unit
  1568  		return unit, nil
  1569  	}
  1570  
  1571  	checker := u.leadershipChecker
  1572  	changeOne := func(arg params.RelationStatusArg) error {
  1573  		// TODO(wallyworld) - the token should be passed to SetStatus() but the
  1574  		// interface method doesn't allow for that yet.
  1575  		unitTag := arg.UnitTag
  1576  		if unitTag == "" {
  1577  			// Older clients don't pass in the unit tag explicitly.
  1578  			unitTag = u.auth.GetAuthTag().String()
  1579  		}
  1580  		unit, err := getUnit(unitTag)
  1581  		if err != nil {
  1582  			return err
  1583  		}
  1584  		token := checker.LeadershipCheck(unit.ApplicationName(), unit.Name())
  1585  		if err := token.Check(0, nil); err != nil {
  1586  			return errors.Trace(err)
  1587  		}
  1588  
  1589  		rel, err := u.st.Relation(arg.RelationId)
  1590  		if errors.IsNotFound(err) {
  1591  			return common.ErrPerm
  1592  		} else if err != nil {
  1593  			return errors.Trace(err)
  1594  		}
  1595  		_, err = rel.Unit(unit)
  1596  		if errors.IsNotFound(err) {
  1597  			return common.ErrPerm
  1598  		} else if err != nil {
  1599  			return errors.Trace(err)
  1600  		}
  1601  		// If we are transitioning from "suspending" to "suspended",
  1602  		// we retain any existing message so that if the user has
  1603  		// previously specified a reason for suspending, it is retained.
  1604  		message := arg.Message
  1605  		if message == "" && arg.Status == params.Suspended {
  1606  			current, err := rel.Status()
  1607  			if err != nil {
  1608  				return errors.Trace(err)
  1609  			}
  1610  			if current.Status == status.Suspending {
  1611  				message = current.Message
  1612  			}
  1613  		}
  1614  		return rel.SetStatus(status.StatusInfo{
  1615  			Status:  status.Status(arg.Status),
  1616  			Message: message,
  1617  		})
  1618  	}
  1619  	results := make([]params.ErrorResult, len(args.Args))
  1620  	for i, arg := range args.Args {
  1621  		err := changeOne(arg)
  1622  		results[i].Error = common.ServerError(err)
  1623  	}
  1624  	statusResults.Results = results
  1625  	return statusResults, nil
  1626  }
  1627  
  1628  // WatchUnitAddresses returns a NotifyWatcher for observing changes
  1629  // to each unit's addresses.
  1630  func (u *UniterAPIV8) WatchUnitAddresses(args params.Entities) (params.NotifyWatchResults, error) {
  1631  	result := params.NotifyWatchResults{
  1632  		Results: make([]params.NotifyWatchResult, len(args.Entities)),
  1633  	}
  1634  	canAccess, err := u.accessUnit()
  1635  	if err != nil {
  1636  		return params.NotifyWatchResults{}, err
  1637  	}
  1638  	for i, entity := range args.Entities {
  1639  		unit, err := names.ParseUnitTag(entity.Tag)
  1640  		if err != nil {
  1641  			result.Results[i].Error = common.ServerError(common.ErrPerm)
  1642  			continue
  1643  		}
  1644  		err = common.ErrPerm
  1645  		watcherId := ""
  1646  		if canAccess(unit) {
  1647  			watcherId, err = u.watchOneUnitAddresses(unit)
  1648  		}
  1649  		result.Results[i].NotifyWatcherId = watcherId
  1650  		result.Results[i].Error = common.ServerError(err)
  1651  	}
  1652  	return result, nil
  1653  }
  1654  
  1655  func (u *UniterAPI) getUnit(tag names.UnitTag) (*state.Unit, error) {
  1656  	return u.st.Unit(tag.Id())
  1657  }
  1658  
  1659  func (u *UniterAPI) getApplication(tag names.ApplicationTag) (*state.Application, error) {
  1660  	return u.st.Application(tag.Id())
  1661  }
  1662  
  1663  func (u *UniterAPI) getRelationUnit(canAccess common.AuthFunc, relTag string, unitTag names.UnitTag) (*state.RelationUnit, error) {
  1664  	rel, unit, err := u.getRelationAndUnit(canAccess, relTag, unitTag)
  1665  	if err != nil {
  1666  		return nil, err
  1667  	}
  1668  	return rel.Unit(unit)
  1669  }
  1670  
  1671  func (u *UniterAPI) getOneRelationById(relId int) (params.RelationResult, error) {
  1672  	nothing := params.RelationResult{}
  1673  	rel, err := u.st.Relation(relId)
  1674  	if errors.IsNotFound(err) {
  1675  		return nothing, common.ErrPerm
  1676  	} else if err != nil {
  1677  		return nothing, err
  1678  	}
  1679  	var applicationName string
  1680  	tag := u.auth.GetAuthTag()
  1681  	switch tag.(type) {
  1682  	case names.UnitTag:
  1683  		unit, err := u.st.Unit(tag.Id())
  1684  		if err != nil {
  1685  			return nothing, err
  1686  		}
  1687  		applicationName = unit.ApplicationName()
  1688  	case names.ApplicationTag:
  1689  		applicationName = tag.Id()
  1690  	default:
  1691  		panic("authenticated entity is not a unit or application")
  1692  	}
  1693  	// Use the currently authenticated unit to get the endpoint.
  1694  	result, err := u.prepareRelationResult(rel, applicationName)
  1695  	if err != nil {
  1696  		// An error from prepareRelationResult means the authenticated
  1697  		// unit's application is not part of the requested
  1698  		// relation. That's why it's appropriate to return ErrPerm
  1699  		// here.
  1700  		return nothing, common.ErrPerm
  1701  	}
  1702  	return result, nil
  1703  }
  1704  
  1705  func (u *UniterAPI) getRelationAndUnit(canAccess common.AuthFunc, relTag string, unitTag names.UnitTag) (*state.Relation, *state.Unit, error) {
  1706  	tag, err := names.ParseRelationTag(relTag)
  1707  	if err != nil {
  1708  		return nil, nil, common.ErrPerm
  1709  	}
  1710  	rel, err := u.st.KeyRelation(tag.Id())
  1711  	if errors.IsNotFound(err) {
  1712  		return nil, nil, common.ErrPerm
  1713  	} else if err != nil {
  1714  		return nil, nil, err
  1715  	}
  1716  	if !canAccess(unitTag) {
  1717  		return nil, nil, common.ErrPerm
  1718  	}
  1719  	unit, err := u.getUnit(unitTag)
  1720  	return rel, unit, err
  1721  }
  1722  
  1723  func (u *UniterAPI) prepareRelationResult(rel *state.Relation, applicationName string) (params.RelationResult, error) {
  1724  	nothing := params.RelationResult{}
  1725  	ep, err := rel.Endpoint(applicationName)
  1726  	if err != nil {
  1727  		// An error here means the unit's application is not part of the
  1728  		// relation.
  1729  		return nothing, err
  1730  	}
  1731  	var otherAppName string
  1732  	otherEndpoints, err := rel.RelatedEndpoints(applicationName)
  1733  	if err != nil {
  1734  		return nothing, err
  1735  	}
  1736  	for _, otherEp := range otherEndpoints {
  1737  		otherAppName = otherEp.ApplicationName
  1738  	}
  1739  	return params.RelationResult{
  1740  		Id:        rel.Id(),
  1741  		Key:       rel.String(),
  1742  		Life:      params.Life(rel.Life().String()),
  1743  		Suspended: rel.Suspended(),
  1744  		Endpoint: multiwatcher.Endpoint{
  1745  			ApplicationName: ep.ApplicationName,
  1746  			Relation:        multiwatcher.NewCharmRelation(ep.Relation),
  1747  		},
  1748  		OtherApplication: otherAppName,
  1749  	}, nil
  1750  }
  1751  
  1752  func (u *UniterAPI) getOneRelation(canAccess common.AuthFunc, relTag, unitTag string) (params.RelationResult, error) {
  1753  	nothing := params.RelationResult{}
  1754  	tag, err := names.ParseUnitTag(unitTag)
  1755  	if err != nil {
  1756  		return nothing, common.ErrPerm
  1757  	}
  1758  	rel, unit, err := u.getRelationAndUnit(canAccess, relTag, tag)
  1759  	if err != nil {
  1760  		return nothing, err
  1761  	}
  1762  	return u.prepareRelationResult(rel, unit.ApplicationName())
  1763  }
  1764  
  1765  func (u *UniterAPI) destroySubordinates(principal *state.Unit) error {
  1766  	subordinates := principal.SubordinateNames()
  1767  	for _, subName := range subordinates {
  1768  		unit, err := u.getUnit(names.NewUnitTag(subName))
  1769  		if err != nil {
  1770  			return err
  1771  		}
  1772  		if err = unit.Destroy(); err != nil {
  1773  			return err
  1774  		}
  1775  	}
  1776  	return nil
  1777  }
  1778  
  1779  func (u *UniterAPIV8) watchOneUnitConfigSettings(tag names.UnitTag, configWatcherFn func(u *state.Unit) (state.NotifyWatcher, error)) (string, error) {
  1780  	unit, err := u.getUnit(tag)
  1781  	if err != nil {
  1782  		return "", err
  1783  	}
  1784  	configWatcher, err := configWatcherFn(unit)
  1785  	if err != nil {
  1786  		return "", errors.Trace(err)
  1787  	}
  1788  	// Consume the initial event. Technically, API
  1789  	// calls to Watch 'transmit' the initial event
  1790  	// in the Watch response. But NotifyWatchers
  1791  	// have no state to transmit.
  1792  	if _, ok := <-configWatcher.Changes(); ok {
  1793  		return u.resources.Register(configWatcher), nil
  1794  	}
  1795  	return "", watcher.EnsureErr(configWatcher)
  1796  }
  1797  
  1798  func (u *UniterAPIV8) watchOneUnitAddresses(tag names.UnitTag) (string, error) {
  1799  	unit, err := u.getUnit(tag)
  1800  	if err != nil {
  1801  		return "", err
  1802  	}
  1803  	var watch state.NotifyWatcher
  1804  	if unit.ShouldBeAssigned() {
  1805  		machineId, err := unit.AssignedMachineId()
  1806  		if err != nil {
  1807  			return "", err
  1808  		}
  1809  		machine, err := u.st.Machine(machineId)
  1810  		if err != nil {
  1811  			return "", err
  1812  		}
  1813  		watch = machine.WatchAddresses()
  1814  	} else {
  1815  		watch = unit.WatchContainerAddresses()
  1816  	}
  1817  	// Consume the initial event. Technically, API
  1818  	// calls to Watch 'transmit' the initial event
  1819  	// in the Watch response. But NotifyWatchers
  1820  	// have no state to transmit.
  1821  	if _, ok := <-watch.Changes(); ok {
  1822  		return u.resources.Register(watch), nil
  1823  	}
  1824  	return "", watcher.EnsureErr(watch)
  1825  }
  1826  
  1827  func (u *UniterAPI) watchOneRelationUnit(relUnit *state.RelationUnit) (params.RelationUnitsWatchResult, error) {
  1828  	watch := relUnit.Watch()
  1829  	// Consume the initial event and forward it to the result.
  1830  	if changes, ok := <-watch.Changes(); ok {
  1831  		return params.RelationUnitsWatchResult{
  1832  			RelationUnitsWatcherId: u.resources.Register(watch),
  1833  			Changes:                changes,
  1834  		}, nil
  1835  	}
  1836  	return params.RelationUnitsWatchResult{}, watcher.EnsureErr(watch)
  1837  }
  1838  
  1839  func (u *UniterAPI) checkRemoteUnit(relUnit *state.RelationUnit, remoteUnitTag string) (string, error) {
  1840  	// Make sure the unit is indeed remote.
  1841  	switch tag := u.auth.GetAuthTag().(type) {
  1842  	case names.UnitTag:
  1843  		if remoteUnitTag == tag.String() {
  1844  			return "", common.ErrPerm
  1845  		}
  1846  	case names.ApplicationTag:
  1847  		// If called by an application agent, we need
  1848  		// to check the units of the application.
  1849  		app, err := u.st.Application(tag.Name)
  1850  		if err != nil {
  1851  			return "", errors.Trace(err)
  1852  		}
  1853  		allUnits, err := app.AllUnits()
  1854  		if err != nil {
  1855  			return "", errors.Trace(err)
  1856  		}
  1857  		for _, unit := range allUnits {
  1858  			if remoteUnitTag == unit.Tag().String() {
  1859  				return "", common.ErrPerm
  1860  			}
  1861  		}
  1862  	}
  1863  
  1864  	// Check remoteUnit is indeed related. Note that we don't want to actually get
  1865  	// the *Unit, because it might have been removed; but its relation settings will
  1866  	// persist until the relation itself has been removed (and must remain accessible
  1867  	// because the local unit's view of reality may be time-shifted).
  1868  	tag, err := names.ParseUnitTag(remoteUnitTag)
  1869  	if err != nil {
  1870  		return "", common.ErrPerm
  1871  	}
  1872  	remoteUnitName := tag.Id()
  1873  	remoteApplicationName, err := names.UnitApplication(remoteUnitName)
  1874  	if err != nil {
  1875  		return "", common.ErrPerm
  1876  	}
  1877  	rel := relUnit.Relation()
  1878  	_, err = rel.RelatedEndpoints(remoteApplicationName)
  1879  	if err != nil {
  1880  		return "", common.ErrPerm
  1881  	}
  1882  	return remoteUnitName, nil
  1883  }
  1884  
  1885  func convertRelationSettings(settings map[string]interface{}) (params.Settings, error) {
  1886  	result := make(params.Settings)
  1887  	for k, v := range settings {
  1888  		// All relation settings should be strings.
  1889  		sval, ok := v.(string)
  1890  		if !ok {
  1891  			return nil, fmt.Errorf("unexpected relation setting %q: expected string, got %T", k, v)
  1892  		}
  1893  		result[k] = sval
  1894  	}
  1895  	return result, nil
  1896  }
  1897  
  1898  func relationsInScopeTags(unit *state.Unit) ([]string, error) {
  1899  	relations, err := unit.RelationsInScope()
  1900  	if err != nil {
  1901  		return nil, err
  1902  	}
  1903  	tags := make([]string, len(relations))
  1904  	for i, relation := range relations {
  1905  		tags[i] = relation.Tag().String()
  1906  	}
  1907  	return tags, nil
  1908  }
  1909  
  1910  func leadershipSettingsAccessorFactory(
  1911  	st *state.State,
  1912  	checker leadership.Checker,
  1913  	resources facade.Resources,
  1914  	auth facade.Authorizer,
  1915  ) *leadershipapiserver.LeadershipSettingsAccessor {
  1916  	registerWatcher := func(applicationId string) (string, error) {
  1917  		application, err := st.Application(applicationId)
  1918  		if err != nil {
  1919  			return "", err
  1920  		}
  1921  		w := application.WatchLeaderSettings()
  1922  		if _, ok := <-w.Changes(); ok {
  1923  			return resources.Register(w), nil
  1924  		}
  1925  		return "", watcher.EnsureErr(w)
  1926  	}
  1927  	getSettings := func(applicationId string) (map[string]string, error) {
  1928  		application, err := st.Application(applicationId)
  1929  		if err != nil {
  1930  			return nil, err
  1931  		}
  1932  		return application.LeaderSettings()
  1933  	}
  1934  	writeSettings := func(token leadership.Token, applicationId string, settings map[string]string) error {
  1935  		application, err := st.Application(applicationId)
  1936  		if err != nil {
  1937  			return err
  1938  		}
  1939  		return application.UpdateLeaderSettings(token, settings)
  1940  	}
  1941  	return leadershipapiserver.NewLeadershipSettingsAccessor(
  1942  		auth,
  1943  		registerWatcher,
  1944  		getSettings,
  1945  		checker.LeadershipCheck,
  1946  		writeSettings,
  1947  	)
  1948  }
  1949  
  1950  // AddMetricBatches adds the metrics for the specified unit.
  1951  func (u *UniterAPI) AddMetricBatches(args params.MetricBatchParams) (params.ErrorResults, error) {
  1952  	result := params.ErrorResults{
  1953  		Results: make([]params.ErrorResult, len(args.Batches)),
  1954  	}
  1955  	canAccess, err := u.accessUnit()
  1956  	if err != nil {
  1957  		logger.Warningf("failed to check unit access: %v", err)
  1958  		return params.ErrorResults{}, common.ErrPerm
  1959  	}
  1960  	for i, batch := range args.Batches {
  1961  		tag, err := names.ParseUnitTag(batch.Tag)
  1962  		if err != nil {
  1963  			result.Results[i].Error = common.ServerError(err)
  1964  			continue
  1965  		}
  1966  		if !canAccess(tag) {
  1967  			result.Results[i].Error = common.ServerError(common.ErrPerm)
  1968  			continue
  1969  		}
  1970  		metrics := make([]state.Metric, len(batch.Batch.Metrics))
  1971  		for j, metric := range batch.Batch.Metrics {
  1972  			metrics[j] = state.Metric{
  1973  				Key:    metric.Key,
  1974  				Value:  metric.Value,
  1975  				Time:   metric.Time,
  1976  				Labels: metric.Labels,
  1977  			}
  1978  		}
  1979  		_, err = u.st.AddMetrics(state.BatchParam{
  1980  			UUID:     batch.Batch.UUID,
  1981  			Created:  batch.Batch.Created,
  1982  			CharmURL: batch.Batch.CharmURL,
  1983  			Metrics:  metrics,
  1984  			Unit:     tag,
  1985  		})
  1986  		result.Results[i].Error = common.ServerError(err)
  1987  	}
  1988  	return result, nil
  1989  }
  1990  
  1991  // V4 specific methods.
  1992  
  1993  //  specific methods - the new SLALevel, NetworkInfo and
  1994  // WatchUnitRelations methods.
  1995  
  1996  // SLALevel returns the model's SLA level.
  1997  func (u *UniterAPI) SLALevel() (params.StringResult, error) {
  1998  	result := params.StringResult{}
  1999  	sla, err := u.st.SLALevel()
  2000  	if err == nil {
  2001  		result.Result = sla
  2002  	}
  2003  	return result, err
  2004  }
  2005  
  2006  // NetworkInfo returns network interfaces/addresses for specified bindings.
  2007  func (u *UniterAPI) NetworkInfo(args params.NetworkInfoParams) (params.NetworkInfoResults, error) {
  2008  	canAccess, err := u.accessUnit()
  2009  	if err != nil {
  2010  		return params.NetworkInfoResults{}, err
  2011  	}
  2012  
  2013  	unitTag, err := names.ParseUnitTag(args.Unit)
  2014  	if err != nil {
  2015  		return params.NetworkInfoResults{}, err
  2016  	}
  2017  
  2018  	if !canAccess(unitTag) {
  2019  		return params.NetworkInfoResults{}, common.ErrPerm
  2020  	}
  2021  
  2022  	unit, err := u.getUnit(unitTag)
  2023  	if err != nil {
  2024  		return params.NetworkInfoResults{}, err
  2025  	}
  2026  
  2027  	result := params.NetworkInfoResults{
  2028  		Results: make(map[string]params.NetworkInfoResult),
  2029  	}
  2030  
  2031  	spaces := set.NewStrings()
  2032  	bindingsToSpace := make(map[string]string)
  2033  	bindingsToEgressSubnets := make(map[string][]string)
  2034  	bindingsToIngressAddresses := make(map[string][]string)
  2035  
  2036  	model, err := u.st.Model()
  2037  	if err != nil {
  2038  		return params.NetworkInfoResults{}, err
  2039  	}
  2040  	modelCfg, err := model.ModelConfig()
  2041  	if err != nil {
  2042  		return params.NetworkInfoResults{}, err
  2043  	}
  2044  	for _, binding := range args.Bindings {
  2045  		if boundSpace, err := unit.GetSpaceForBinding(binding); err != nil {
  2046  			result.Results[binding] = params.NetworkInfoResult{Error: common.ServerError(err)}
  2047  		} else {
  2048  			spaces.Add(boundSpace)
  2049  			bindingsToSpace[binding] = boundSpace
  2050  		}
  2051  		bindingsToEgressSubnets[binding] = modelCfg.EgressSubnets()
  2052  	}
  2053  
  2054  	if args.RelationId != nil {
  2055  		// We're in a relation context.
  2056  		rel, err := u.st.Relation(*args.RelationId)
  2057  		if err != nil {
  2058  			return params.NetworkInfoResults{}, err
  2059  		}
  2060  		endpoint, err := rel.Endpoint(unit.ApplicationName())
  2061  		if err != nil {
  2062  			return params.NetworkInfoResults{}, err
  2063  		}
  2064  		boundSpace, ingress, egress, err := state.NetworksForRelation(endpoint.Name, unit, rel, modelCfg.EgressSubnets())
  2065  		if err != nil {
  2066  			return params.NetworkInfoResults{}, err
  2067  		}
  2068  		spaces.Add(boundSpace)
  2069  		if len(egress) > 0 {
  2070  			bindingsToEgressSubnets[endpoint.Name] = egress
  2071  		}
  2072  		bindingsToIngressAddresses[endpoint.Name] = ingress
  2073  	}
  2074  
  2075  	var (
  2076  		networkInfos            map[string]state.MachineNetworkInfoResult
  2077  		defaultIngressAddresses []string
  2078  	)
  2079  
  2080  	if unit.ShouldBeAssigned() {
  2081  		machineID, err := unit.AssignedMachineId()
  2082  		if err != nil {
  2083  			return params.NetworkInfoResults{}, err
  2084  		}
  2085  		machine, err := u.st.Machine(machineID)
  2086  		if err != nil {
  2087  			return params.NetworkInfoResults{}, err
  2088  		}
  2089  		networkInfos = machine.GetNetworkInfoForSpaces(spaces)
  2090  	} else {
  2091  		// For CAAS units, we build up a minimal result struct
  2092  		// based on the default space and unit public/private addresses,
  2093  		// ie the addresses of the CAAS service.
  2094  		addr, err := unit.AllAddresses()
  2095  		if err != nil {
  2096  			return params.NetworkInfoResults{}, err
  2097  		}
  2098  		network.SortAddresses(addr)
  2099  
  2100  		// We record the interface addresses as the machine local ones - these
  2101  		// are used later as the binding addresses.
  2102  		// For CAAS models, we need to default ingress addresses to all available
  2103  		// addresses so record those in the default ingress address slice.
  2104  		var interfaceAddr []network.InterfaceAddress
  2105  		for _, a := range addr {
  2106  			if a.Scope == network.ScopeMachineLocal {
  2107  				interfaceAddr = append(interfaceAddr, network.InterfaceAddress{Address: a.Value})
  2108  			}
  2109  			defaultIngressAddresses = append(defaultIngressAddresses, a.Value)
  2110  		}
  2111  		networkInfos = make(map[string]state.MachineNetworkInfoResult)
  2112  		networkInfos[environs.DefaultSpaceName] = state.MachineNetworkInfoResult{
  2113  			NetworkInfos: []network.NetworkInfo{{Addresses: interfaceAddr}},
  2114  		}
  2115  	}
  2116  
  2117  	for binding, space := range bindingsToSpace {
  2118  		// The binding address information based on link layer devices.
  2119  		info := networkingcommon.MachineNetworkInfoResultToNetworkInfoResult(networkInfos[space])
  2120  
  2121  		// Set egress and ingress address information.
  2122  		info.EgressSubnets = bindingsToEgressSubnets[binding]
  2123  		info.IngressAddresses = bindingsToIngressAddresses[binding]
  2124  
  2125  		// If there is no ingress address explicitly defined for a given binding,
  2126  		// set the ingress addresses to either any defaults set above, or the binding addresses.
  2127  		if len(info.IngressAddresses) == 0 {
  2128  			for _, addr := range defaultIngressAddresses {
  2129  				info.IngressAddresses = append(info.IngressAddresses, addr)
  2130  			}
  2131  		}
  2132  		if len(info.IngressAddresses) == 0 {
  2133  			for _, nwInfo := range info.Info {
  2134  				for _, addr := range nwInfo.Addresses {
  2135  					info.IngressAddresses = append(info.IngressAddresses, addr.Address)
  2136  				}
  2137  			}
  2138  		}
  2139  
  2140  		// If there is no egress subnet explicitly defined for a given binding,
  2141  		// default to the first ingress address. This matches the behaviour when
  2142  		// there's a relation in place.
  2143  		if len(info.EgressSubnets) == 0 && len(info.IngressAddresses) > 0 {
  2144  			info.EgressSubnets, err = network.FormatAsCIDR([]string{info.IngressAddresses[0]})
  2145  			if err != nil {
  2146  				return result, errors.Trace(err)
  2147  			}
  2148  		}
  2149  
  2150  		result.Results[binding] = info
  2151  	}
  2152  
  2153  	return result, nil
  2154  }
  2155  
  2156  // WatchUnitRelations returns a StringsWatcher, for each given
  2157  // unit, that notifies of changes to the lifecycles of relations
  2158  // relevant to that unit. For principal units, this will be all of the
  2159  // relations for the application. For subordinate units, only
  2160  // relations with the principal unit's application will be monitored.
  2161  func (u *UniterAPI) WatchUnitRelations(args params.Entities) (params.StringsWatchResults, error) {
  2162  	result := params.StringsWatchResults{
  2163  		Results: make([]params.StringsWatchResult, len(args.Entities)),
  2164  	}
  2165  	canAccess, err := u.accessUnit()
  2166  	if err != nil {
  2167  		return params.StringsWatchResults{}, err
  2168  	}
  2169  	for i, entity := range args.Entities {
  2170  		tag, err := names.ParseUnitTag(entity.Tag)
  2171  		if err != nil {
  2172  			result.Results[i].Error = common.ServerError(common.ErrPerm)
  2173  			continue
  2174  		}
  2175  		err = common.ErrPerm
  2176  		if canAccess(tag) {
  2177  			result.Results[i], err = u.watchOneUnitRelations(tag)
  2178  		}
  2179  		result.Results[i].Error = common.ServerError(err)
  2180  	}
  2181  	return result, nil
  2182  }
  2183  
  2184  func (u *UniterAPI) watchOneUnitRelations(tag names.UnitTag) (params.StringsWatchResult, error) {
  2185  	nothing := params.StringsWatchResult{}
  2186  	unit, err := u.getUnit(tag)
  2187  	if err != nil {
  2188  		return nothing, err
  2189  	}
  2190  	app, err := unit.Application()
  2191  	if err != nil {
  2192  		return nothing, err
  2193  	}
  2194  	principalName, isSubordinate := unit.PrincipalName()
  2195  	var watch state.StringsWatcher
  2196  	if isSubordinate {
  2197  		principalUnit, err := u.st.Unit(principalName)
  2198  		if err != nil {
  2199  			return nothing, errors.Trace(err)
  2200  		}
  2201  		principalApp, err := principalUnit.Application()
  2202  		if err != nil {
  2203  			return nothing, errors.Trace(err)
  2204  		}
  2205  		watch, err = newSubordinateRelationsWatcher(u.st, app, principalApp.Name())
  2206  		if err != nil {
  2207  			return nothing, errors.Trace(err)
  2208  		}
  2209  	} else {
  2210  		watch = app.WatchRelations()
  2211  	}
  2212  	// Consume the initial event and forward it to the result.
  2213  	if changes, ok := <-watch.Changes(); ok {
  2214  		return params.StringsWatchResult{
  2215  			StringsWatcherId: u.resources.Register(watch),
  2216  			Changes:          changes,
  2217  		}, nil
  2218  	}
  2219  	return nothing, watcher.EnsureErr(watch)
  2220  }
  2221  
  2222  // NetworkConfig returns information about all given relation/unit pairs,
  2223  // including their id, key and the local endpoint.
  2224  // It's not included in APIv5
  2225  // TODO(wpk): NetworkConfig API is obsoleted by Uniter.NetworkInfo
  2226  func (u *UniterAPIV4) NetworkConfig(args params.UnitsNetworkConfig) (params.UnitNetworkConfigResults, error) {
  2227  	result := params.UnitNetworkConfigResults{
  2228  		Results: make([]params.UnitNetworkConfigResult, len(args.Args)),
  2229  	}
  2230  
  2231  	canAccess, err := u.accessUnit()
  2232  	if err != nil {
  2233  		return params.UnitNetworkConfigResults{}, err
  2234  	}
  2235  
  2236  	for i, arg := range args.Args {
  2237  		netConfig, err := u.getOneNetworkConfig(canAccess, arg.UnitTag, arg.BindingName)
  2238  		if err == nil {
  2239  			result.Results[i].Config = netConfig
  2240  		} else {
  2241  			result.Results[i].Error = common.ServerError(err)
  2242  		}
  2243  	}
  2244  	return result, nil
  2245  }
  2246  
  2247  func (u *UniterAPIV4) getOneNetworkConfig(canAccess common.AuthFunc, unitTagArg, bindingName string) ([]params.NetworkConfig, error) {
  2248  	unitTag, err := names.ParseUnitTag(unitTagArg)
  2249  	if err != nil {
  2250  		return nil, errors.Trace(err)
  2251  	}
  2252  
  2253  	if bindingName == "" {
  2254  		return nil, errors.Errorf("binding name cannot be empty")
  2255  	}
  2256  
  2257  	if !canAccess(unitTag) {
  2258  		return nil, common.ErrPerm
  2259  	}
  2260  
  2261  	unit, err := u.getUnit(unitTag)
  2262  	if err != nil {
  2263  		return nil, errors.Trace(err)
  2264  	}
  2265  
  2266  	application, err := unit.Application()
  2267  	if err != nil {
  2268  		return nil, errors.Trace(err)
  2269  	}
  2270  
  2271  	bindings, err := application.EndpointBindings()
  2272  	if err != nil {
  2273  		return nil, errors.Trace(err)
  2274  	}
  2275  	boundSpace, known := bindings[bindingName]
  2276  	if !known {
  2277  		return nil, errors.Errorf("binding name %q not defined by the unit's charm", bindingName)
  2278  	}
  2279  
  2280  	machineID, err := unit.AssignedMachineId()
  2281  	if err != nil {
  2282  		return nil, errors.Trace(err)
  2283  	}
  2284  
  2285  	machine, err := u.st.Machine(machineID)
  2286  	if err != nil {
  2287  		return nil, errors.Trace(err)
  2288  	}
  2289  
  2290  	var results []params.NetworkConfig
  2291  	if boundSpace == "" {
  2292  		logger.Debugf(
  2293  			"endpoint %q not explicitly bound to a space, using preferred private address for machine %q",
  2294  			bindingName, machineID,
  2295  		)
  2296  
  2297  		privateAddress, err := machine.PrivateAddress()
  2298  		if err != nil {
  2299  			return nil, errors.Annotatef(err, "getting machine %q preferred private address", machineID)
  2300  		}
  2301  
  2302  		results = append(results, params.NetworkConfig{
  2303  			Address: privateAddress.Value,
  2304  		})
  2305  		return results, nil
  2306  	} else {
  2307  		logger.Debugf("endpoint %q is explicitly bound to space %q", bindingName, boundSpace)
  2308  	}
  2309  
  2310  	// TODO(dimitern): Use NetworkInterfaces() instead later, this is just for
  2311  	// the PoC to enable minimal network-get implementation returning just the
  2312  	// primary address.
  2313  	//
  2314  	// LKK Card: https://canonical.leankit.com/Boards/View/101652562/119258804
  2315  	addresses, err := machine.AllAddresses()
  2316  	if err != nil {
  2317  		return nil, errors.Annotate(err, "cannot get devices addresses")
  2318  	}
  2319  	logger.Debugf(
  2320  		"getting network config for machine %q with addresses %+v, hosting unit %q of application %q, with bindings %+v",
  2321  		machineID, addresses, unit.Name(), application.Name(), bindings,
  2322  	)
  2323  
  2324  	for _, addr := range addresses {
  2325  		subnet, err := addr.Subnet()
  2326  		if errors.IsNotFound(err) {
  2327  			logger.Debugf("skipping %s: not linked to a known subnet (%v)", addr, err)
  2328  			continue
  2329  		} else if err != nil {
  2330  			return nil, errors.Annotatef(err, "cannot get subnet for address %q", addr)
  2331  		}
  2332  
  2333  		if space := subnet.SpaceName(); space != boundSpace {
  2334  			logger.Debugf("skipping %s: want bound to space %q, got space %q", addr, boundSpace, space)
  2335  			continue
  2336  		}
  2337  		logger.Debugf("endpoint %q bound to space %q has address %q", bindingName, boundSpace, addr)
  2338  
  2339  		// TODO(dimitern): Fill in the rest later (see linked LKK card above).
  2340  		results = append(results, params.NetworkConfig{
  2341  			Address: addr.Value(),
  2342  		})
  2343  	}
  2344  
  2345  	return results, nil
  2346  }
  2347  
  2348  func relationResultsToV5(v6Results params.RelationResults) params.RelationResultsV5 {
  2349  	results := make([]params.RelationResultV5, len(v6Results.Results))
  2350  	for i, v6Result := range v6Results.Results {
  2351  		results[i].Error = v6Result.Error
  2352  		results[i].Life = v6Result.Life
  2353  		results[i].Id = v6Result.Id
  2354  		results[i].Key = v6Result.Key
  2355  		results[i].Endpoint = v6Result.Endpoint
  2356  	}
  2357  	return params.RelationResultsV5{Results: results}
  2358  }
  2359  
  2360  // Relation returns information about all given relation/unit pairs,
  2361  // including their id, key and the local endpoint (without other
  2362  // application name).
  2363  func (u *UniterAPIV5) Relation(args params.RelationUnits) (params.RelationResultsV5, error) {
  2364  	v6Results, err := u.UniterAPI.Relation(args)
  2365  	if err != nil {
  2366  		return params.RelationResultsV5{}, errors.Trace(err)
  2367  	}
  2368  	return relationResultsToV5(v6Results), nil
  2369  }
  2370  
  2371  // RelationById returns information about all given relations,
  2372  // specified by their ids, including their key and the local
  2373  // endpoint (without other application name).
  2374  func (u *UniterAPIV5) RelationById(args params.RelationIds) (params.RelationResultsV5, error) {
  2375  	v6Results, err := u.UniterAPI.RelationById(args)
  2376  	if err != nil {
  2377  		return params.RelationResultsV5{}, errors.Trace(err)
  2378  	}
  2379  	return relationResultsToV5(v6Results), nil
  2380  }
  2381  
  2382  // WatchApplicationRelations returns a StringsWatcher, for each given
  2383  // application, that notifies of changes to the lifecycles of
  2384  // relations involving that application. This method is obsolete -
  2385  // it's been replaced by WatchUnitRelations in V5 of the uniter API.
  2386  func (u *UniterAPIV4) WatchApplicationRelations(args params.Entities) (params.StringsWatchResults, error) {
  2387  	result := params.StringsWatchResults{
  2388  		Results: make([]params.StringsWatchResult, len(args.Entities)),
  2389  	}
  2390  	canAccess, err := u.accessApplication()
  2391  	if err != nil {
  2392  		return params.StringsWatchResults{}, err
  2393  	}
  2394  	for i, entity := range args.Entities {
  2395  		tag, err := names.ParseApplicationTag(entity.Tag)
  2396  		if err != nil {
  2397  			result.Results[i].Error = common.ServerError(common.ErrPerm)
  2398  			continue
  2399  		}
  2400  		err = common.ErrPerm
  2401  		if canAccess(tag) {
  2402  			result.Results[i], err = u.watchOneApplicationRelations(tag)
  2403  		}
  2404  		result.Results[i].Error = common.ServerError(err)
  2405  	}
  2406  	return result, nil
  2407  }
  2408  
  2409  func (u *UniterAPIV4) watchOneApplicationRelations(tag names.ApplicationTag) (params.StringsWatchResult, error) {
  2410  	nothing := params.StringsWatchResult{}
  2411  	application, err := u.getApplication(tag)
  2412  	if err != nil {
  2413  		return nothing, err
  2414  	}
  2415  	watch := application.WatchRelations()
  2416  	// Consume the initial event and forward it to the result.
  2417  	if changes, ok := <-watch.Changes(); ok {
  2418  		return params.StringsWatchResult{
  2419  			StringsWatcherId: u.resources.Register(watch),
  2420  			Changes:          changes,
  2421  		}, nil
  2422  	}
  2423  	return nothing, watcher.EnsureErr(watch)
  2424  }
  2425  
  2426  // Mask the new methods from the V4 API. The API reflection code in
  2427  // rpc/rpcreflect/type.go:newMethod skips 2-argument methods, so this
  2428  // removes the method as far as the RPC machinery is concerned.
  2429  
  2430  // SLALevel isn't on the V4 API.
  2431  func (u *UniterAPIV4) SLALevel(_, _ struct{}) {}
  2432  
  2433  // NetworkInfo isn't on the V4 API.
  2434  func (u *UniterAPIV4) NetworkInfo(_, _ struct{}) {}
  2435  
  2436  // WatchUnitRelations isn't on the V4 API.
  2437  func (u *UniterAPIV4) WatchUnitRelations(_, _ struct{}) {}
  2438  
  2439  func networkInfoResultsToV6(v7Results params.NetworkInfoResults) params.NetworkInfoResultsV6 {
  2440  	results := make(map[string]params.NetworkInfoResultV6)
  2441  	for k, v6Result := range v7Results.Results {
  2442  		results[k] = params.NetworkInfoResultV6{Error: v6Result.Error, Info: v6Result.Info}
  2443  	}
  2444  	return params.NetworkInfoResultsV6{Results: results}
  2445  }
  2446  
  2447  // Network Info implements UniterAPIV6 version of NetworkInfo by constructing an API V6 compatible result.
  2448  func (u *UniterAPIV6) NetworkInfo(args params.NetworkInfoParams) (params.NetworkInfoResultsV6, error) {
  2449  	v6Results, err := u.UniterAPI.NetworkInfo(args)
  2450  	if err != nil {
  2451  		return params.NetworkInfoResultsV6{}, errors.Trace(err)
  2452  	}
  2453  	return networkInfoResultsToV6(v6Results), nil
  2454  }
  2455  
  2456  // Mask the SetPodSpec method from the v7 API. The API reflection code
  2457  // in rpc/rpcreflect/type.go:newMethod skips 2-argument methods, so
  2458  // this removes the method as far as the RPC machinery is concerned.
  2459  
  2460  // SetPodSpec isn't on the v7 API.
  2461  func (u *UniterAPIV7) SetPodSpec(_, _ struct{}) {}
  2462  
  2463  // SetPodSpec sets the pod specs for a set of applications.
  2464  func (u *UniterAPI) SetPodSpec(args params.SetPodSpecParams) (params.ErrorResults, error) {
  2465  	results := params.ErrorResults{
  2466  		Results: make([]params.ErrorResult, len(args.Specs)),
  2467  	}
  2468  	authTag := u.auth.GetAuthTag()
  2469  	canAccess := func(tag names.Tag) bool {
  2470  		if tag, ok := tag.(names.ApplicationTag); ok {
  2471  			switch authTag.(type) {
  2472  			case names.UnitTag:
  2473  				appName, err := names.UnitApplication(authTag.Id())
  2474  				return err == nil && appName == tag.Id()
  2475  			case names.ApplicationTag:
  2476  				return tag == authTag
  2477  			}
  2478  		}
  2479  		return false
  2480  	}
  2481  
  2482  	cfg, err := u.m.ModelConfig()
  2483  	if err != nil {
  2484  		return params.ErrorResults{}, errors.Trace(err)
  2485  	}
  2486  	provider, err := environs.Provider(cfg.Type())
  2487  	if err != nil {
  2488  		return params.ErrorResults{}, errors.Trace(err)
  2489  	}
  2490  	cassProvider, ok := provider.(caas.ContainerEnvironProvider)
  2491  	if !ok {
  2492  		return params.ErrorResults{}, errors.NotValidf("container environ provider %T", provider)
  2493  	}
  2494  
  2495  	for i, arg := range args.Specs {
  2496  		tag, err := names.ParseApplicationTag(arg.Tag)
  2497  		if err != nil {
  2498  			results.Results[i].Error = common.ServerError(err)
  2499  			continue
  2500  		}
  2501  		if !canAccess(tag) {
  2502  			results.Results[i].Error = common.ServerError(common.ErrPerm)
  2503  			continue
  2504  		}
  2505  		if _, err := cassProvider.ParsePodSpec(arg.Value); err != nil {
  2506  			results.Results[i].Error = common.ServerError(errors.Annotate(err, "invalid pod spec"))
  2507  			continue
  2508  		}
  2509  		cm, err := u.m.CAASModel()
  2510  		if err != nil {
  2511  			results.Results[i].Error = common.ServerError(err)
  2512  			continue
  2513  		}
  2514  		results.Results[i].Error = common.ServerError(
  2515  			cm.SetPodSpec(tag, arg.Value),
  2516  		)
  2517  	}
  2518  	return results, nil
  2519  }
  2520  
  2521  // CloudSpec returns the cloud spec used by the model in which the
  2522  // authenticated unit or application resides.
  2523  // A check is made beforehand to ensure that the request is made by an entity
  2524  // that has been granted the appropriate trust.
  2525  func (u *UniterAPI) CloudSpec() (params.CloudSpecResult, error) {
  2526  	canAccess, err := u.accessCloudSpec()
  2527  	if err != nil {
  2528  		return params.CloudSpecResult{}, err
  2529  	}
  2530  	if !canAccess() {
  2531  		return params.CloudSpecResult{Error: common.ServerError(common.ErrPerm)}, nil
  2532  	}
  2533  
  2534  	return u.cloudSpec.GetCloudSpec(u.m.Tag().(names.ModelTag)), nil
  2535  }
  2536  
  2537  // GoalStates returns information of charm units and relations.
  2538  func (u *UniterAPI) GoalStates(args params.Entities) (params.GoalStateResults, error) {
  2539  	result := params.GoalStateResults{
  2540  		Results: make([]params.GoalStateResult, len(args.Entities)),
  2541  	}
  2542  
  2543  	canAccess, err := u.accessUnit()
  2544  	if err != nil {
  2545  		return params.GoalStateResults{}, err
  2546  	}
  2547  	for i, entity := range args.Entities {
  2548  		tag, err := names.ParseUnitTag(entity.Tag)
  2549  		if err != nil {
  2550  			result.Results[i].Error = common.ServerError(common.ErrPerm)
  2551  			continue
  2552  		}
  2553  		if !canAccess(tag) {
  2554  			result.Results[i].Error = common.ServerError(common.ErrPerm)
  2555  			continue
  2556  		}
  2557  		unit, err := u.getUnit(tag)
  2558  		if err != nil {
  2559  			result.Results[i].Error = common.ServerError(err)
  2560  			continue
  2561  		}
  2562  		result.Results[i].Result, err = u.oneGoalState(unit)
  2563  		if err != nil {
  2564  			result.Results[i].Error = common.ServerError(err)
  2565  		}
  2566  	}
  2567  	return result, nil
  2568  }
  2569  
  2570  // oneGoalState creates the goal state for a given unit.
  2571  func (u *UniterAPI) oneGoalState(unit *state.Unit) (*params.GoalState, error) {
  2572  	app, err := unit.Application()
  2573  	if err != nil {
  2574  		return nil, err
  2575  	}
  2576  
  2577  	gs := params.GoalState{}
  2578  	gs.Units, err = u.goalStateUnits(app, unit.Name())
  2579  	if err != nil {
  2580  		return nil, err
  2581  	}
  2582  	allRelations, err := app.Relations()
  2583  	if err != nil {
  2584  		return nil, err
  2585  	}
  2586  	if allRelations != nil {
  2587  		gs.Relations, err = u.goalStateRelations(app.Name(), unit.Name(), allRelations)
  2588  		if err != nil {
  2589  			return nil, err
  2590  		}
  2591  	}
  2592  	return &gs, nil
  2593  }
  2594  
  2595  // goalStateRelations creates the structure with all the relations between endpoints in an application.
  2596  func (u *UniterAPI) goalStateRelations(appName, principalName string, allRelations []*state.Relation) (map[string]params.UnitsGoalState, error) {
  2597  
  2598  	result := map[string]params.UnitsGoalState{}
  2599  
  2600  	for _, r := range allRelations {
  2601  		statusInfo, err := r.Status()
  2602  		if err != nil {
  2603  			return nil, errors.Annotate(err, "getting relation status")
  2604  		}
  2605  		endPoints := r.Endpoints()
  2606  		for _, e := range endPoints {
  2607  			if e.Relation.Role == "peer" {
  2608  				continue
  2609  			}
  2610  			var key string
  2611  			app, err := u.st.Application(e.ApplicationName)
  2612  			if err == nil {
  2613  				key = app.Name()
  2614  			} else if errors.IsNotFound(err) {
  2615  				logger.Debugf("application %q must be a remote application.", e.ApplicationName)
  2616  				remoteApplication, err := u.st.RemoteApplication(e.ApplicationName)
  2617  				if err != nil {
  2618  					return nil, err
  2619  				}
  2620  				var ok bool
  2621  				key, ok = remoteApplication.URL()
  2622  				if !ok {
  2623  					// If we are on the offering side of a remote relation, don't show anything
  2624  					// in goal state for that relation.
  2625  					continue
  2626  				}
  2627  			} else {
  2628  				return nil, err
  2629  			}
  2630  
  2631  			// We don't show units for the same application as we are currently processing.
  2632  			if key == appName {
  2633  				continue
  2634  			}
  2635  
  2636  			goalState := params.GoalStateStatus{}
  2637  			goalState.Status = statusInfo.Status.String()
  2638  			goalState.Since = statusInfo.Since
  2639  			relationGoalState := result[e.Name]
  2640  			if relationGoalState == nil {
  2641  				relationGoalState = params.UnitsGoalState{}
  2642  			}
  2643  			relationGoalState[key] = goalState
  2644  
  2645  			// For local applications, add in the status of units as well.
  2646  			if app != nil {
  2647  				units, err := u.goalStateUnits(app, principalName)
  2648  				if err != nil {
  2649  					return nil, err
  2650  				}
  2651  				for unitName, unitGS := range units {
  2652  					relationGoalState[unitName] = unitGS
  2653  				}
  2654  			}
  2655  
  2656  			result[e.Name] = relationGoalState
  2657  		}
  2658  	}
  2659  	return result, nil
  2660  }
  2661  
  2662  // goalStateUnits loops through all application units related to principalName,
  2663  // and stores the goal state status in UnitsGoalState.
  2664  func (u *UniterAPI) goalStateUnits(app *state.Application, principalName string) (params.UnitsGoalState, error) {
  2665  
  2666  	allUnits, err := app.AllUnits()
  2667  	if err != nil {
  2668  		return nil, err
  2669  	}
  2670  	unitsGoalState := params.UnitsGoalState{}
  2671  	for _, unit := range allUnits {
  2672  		// Ignore subordinates belonging to other units.
  2673  		pn, ok := unit.PrincipalName()
  2674  		if ok && pn != principalName {
  2675  			continue
  2676  		}
  2677  		unitLife := unit.Life()
  2678  		if unitLife == state.Dead {
  2679  			// only show Alive and Dying units
  2680  			logger.Debugf("unit %q is dead, ignore it.", unit.Name())
  2681  			continue
  2682  		}
  2683  		unitGoalState := params.GoalStateStatus{}
  2684  		statusInfo, err := unit.Status()
  2685  		if err != nil {
  2686  			return nil, errors.Trace(err)
  2687  		}
  2688  		unitGoalState.Status = statusInfo.Status.String()
  2689  		if unitLife == state.Dying {
  2690  			unitGoalState.Status = unitLife.String()
  2691  		}
  2692  		unitGoalState.Since = statusInfo.Since
  2693  		unitsGoalState[unit.Name()] = unitGoalState
  2694  	}
  2695  
  2696  	return unitsGoalState, nil
  2697  }
  2698  
  2699  // WatchConfigSettingsHash returns a StringsWatcher that yields a hash
  2700  // of the config values every time the config changes. The uniter can
  2701  // save this hash and use it to decide whether the config-changed hook
  2702  // needs to be run (or whether this was just an agent restart with no
  2703  // substantive config change).
  2704  func (u *UniterAPI) WatchConfigSettingsHash(args params.Entities) (params.StringsWatchResults, error) {
  2705  	getWatcher := func(unit *state.Unit) (state.StringsWatcher, error) {
  2706  		return unit.WatchConfigSettingsHash()
  2707  	}
  2708  	result, err := u.watchHashes(args, getWatcher)
  2709  	if err != nil {
  2710  		return params.StringsWatchResults{}, errors.Trace(err)
  2711  	}
  2712  	return result, nil
  2713  }
  2714  
  2715  // WatchTrustConfigSettingsHash returns a StringsWatcher that yields a
  2716  // hash of the application config values whenever they change. The
  2717  // uniter can use the hash to determine whether the actual values have
  2718  // changed since it last saw the config.
  2719  func (u *UniterAPI) WatchTrustConfigSettingsHash(args params.Entities) (params.StringsWatchResults, error) {
  2720  	getWatcher := func(unit *state.Unit) (state.StringsWatcher, error) {
  2721  		return unit.WatchApplicationConfigSettingsHash()
  2722  	}
  2723  	result, err := u.watchHashes(args, getWatcher)
  2724  	if err != nil {
  2725  		return params.StringsWatchResults{}, errors.Trace(err)
  2726  	}
  2727  	return result, nil
  2728  }
  2729  
  2730  // WatchUnitAddressesHash returns a StringsWatcher that yields the
  2731  // hashes of the addresses for the unit whenever the addresses
  2732  // change. The uniter can use the hash to determine whether the actual
  2733  // address values have changed since it last saw the config.
  2734  func (u *UniterAPI) WatchUnitAddressesHash(args params.Entities) (params.StringsWatchResults, error) {
  2735  	getWatcher := func(unit *state.Unit) (state.StringsWatcher, error) {
  2736  		if !unit.ShouldBeAssigned() {
  2737  			return unit.WatchContainerAddressesHash(), nil
  2738  		}
  2739  		machineId, err := unit.AssignedMachineId()
  2740  		if err != nil {
  2741  			return nil, err
  2742  		}
  2743  		machine, err := u.st.Machine(machineId)
  2744  		if err != nil {
  2745  			return nil, err
  2746  		}
  2747  		return machine.WatchAddressesHash(), nil
  2748  	}
  2749  	result, err := u.watchHashes(args, getWatcher)
  2750  	if err != nil {
  2751  		return params.StringsWatchResults{}, errors.Trace(err)
  2752  	}
  2753  	return result, nil
  2754  }
  2755  
  2756  // Mask WatchConfigSettingsHash from the v8 API. The API reflection
  2757  // code in rpc/rpcreflect/type.go:newMethod skips 2-argument methods,
  2758  // so this removes the method as far as the RPC machinery is
  2759  // concerned.
  2760  
  2761  // WatchConfigSettingsHash isn't on the v8 API.
  2762  func (u *UniterAPIV8) WatchConfigSettingsHash(_, _ struct{}) {}
  2763  
  2764  // WatchTrustConfigSettingsHash isn't on the v8 API.
  2765  func (u *UniterAPIV8) WatchTrustConfigSettingsHash(_, _ struct{}) {}
  2766  
  2767  // WatchUnitAddressesHash isn't on the v8 API.
  2768  func (u *UniterAPIV8) WatchUnitAddressesHash(_, _ struct{}) {}
  2769  
  2770  func (u *UniterAPI) watchHashes(args params.Entities, getWatcher func(u *state.Unit) (state.StringsWatcher, error)) (params.StringsWatchResults, error) {
  2771  	result := params.StringsWatchResults{
  2772  		Results: make([]params.StringsWatchResult, len(args.Entities)),
  2773  	}
  2774  	canAccess, err := u.accessUnit()
  2775  	if err != nil {
  2776  		return params.StringsWatchResults{}, err
  2777  	}
  2778  	for i, entity := range args.Entities {
  2779  		tag, err := names.ParseUnitTag(entity.Tag)
  2780  		if err != nil {
  2781  			result.Results[i].Error = common.ServerError(common.ErrPerm)
  2782  			continue
  2783  		}
  2784  		err = common.ErrPerm
  2785  		watcherId := ""
  2786  		var changes []string
  2787  		if canAccess(tag) {
  2788  			watcherId, changes, err = u.watchOneUnitHashes(tag, getWatcher)
  2789  		}
  2790  		result.Results[i].StringsWatcherId = watcherId
  2791  		result.Results[i].Changes = changes
  2792  		result.Results[i].Error = common.ServerError(err)
  2793  	}
  2794  	return result, nil
  2795  }
  2796  
  2797  func (u *UniterAPI) watchOneUnitHashes(tag names.UnitTag, getWatcher func(u *state.Unit) (state.StringsWatcher, error)) (string, []string, error) {
  2798  	unit, err := u.getUnit(tag)
  2799  	if err != nil {
  2800  		return "", nil, err
  2801  	}
  2802  	w, err := getWatcher(unit)
  2803  	if err != nil {
  2804  		return "", nil, errors.Trace(err)
  2805  	}
  2806  	// Consume the initial event.
  2807  	if changes, ok := <-w.Changes(); ok {
  2808  		return u.resources.Register(w), changes, nil
  2809  	}
  2810  	return "", nil, watcher.EnsureErr(w)
  2811  }