github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/apiserver/uniter/uniter.go (about)

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