github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/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  	"net/url"
    11  	"path"
    12  
    13  	"github.com/juju/errors"
    14  	"github.com/juju/loggo"
    15  	"github.com/juju/names"
    16  	"gopkg.in/juju/charm.v6-unstable"
    17  
    18  	"github.com/juju/juju/apiserver/common"
    19  	leadershipapiserver "github.com/juju/juju/apiserver/leadership"
    20  	"github.com/juju/juju/apiserver/meterstatus"
    21  	"github.com/juju/juju/apiserver/params"
    22  	"github.com/juju/juju/core/leadership"
    23  	"github.com/juju/juju/network"
    24  	"github.com/juju/juju/state"
    25  	"github.com/juju/juju/state/multiwatcher"
    26  	"github.com/juju/juju/state/watcher"
    27  )
    28  
    29  var logger = loggo.GetLogger("juju.apiserver.uniter")
    30  
    31  func init() {
    32  	common.RegisterStandardFacade("Uniter", 3, NewUniterAPIV3)
    33  }
    34  
    35  // UniterAPIV3 implements the API version 3, used by the uniter worker.
    36  type UniterAPIV3 struct {
    37  	*common.LifeGetter
    38  	*StatusAPI
    39  	*common.DeadEnsurer
    40  	*common.AgentEntityWatcher
    41  	*common.APIAddresser
    42  	*common.ModelWatcher
    43  	*common.RebootRequester
    44  	*leadershipapiserver.LeadershipSettingsAccessor
    45  	meterstatus.MeterStatus
    46  
    47  	st            *state.State
    48  	auth          common.Authorizer
    49  	resources     *common.Resources
    50  	accessUnit    common.GetAuthFunc
    51  	accessService common.GetAuthFunc
    52  	unit          *state.Unit
    53  	accessMachine common.GetAuthFunc
    54  	StorageAPI
    55  }
    56  
    57  // NewUniterAPIV3 creates a new instance of the Uniter API, version 3.
    58  func NewUniterAPIV3(st *state.State, resources *common.Resources, authorizer common.Authorizer) (*UniterAPIV3, error) {
    59  	if !authorizer.AuthUnitAgent() {
    60  		return nil, common.ErrPerm
    61  	}
    62  	var unit *state.Unit
    63  	var err error
    64  	switch tag := authorizer.GetAuthTag().(type) {
    65  	case names.UnitTag:
    66  		unit, err = st.Unit(tag.Id())
    67  		if err != nil {
    68  			return nil, errors.Trace(err)
    69  		}
    70  	default:
    71  		return nil, errors.Errorf("expected names.UnitTag, got %T", tag)
    72  	}
    73  	accessUnit := func() (common.AuthFunc, error) {
    74  		return authorizer.AuthOwner, nil
    75  	}
    76  	accessService := func() (common.AuthFunc, error) {
    77  		switch tag := authorizer.GetAuthTag().(type) {
    78  		case names.UnitTag:
    79  			entity, err := st.Unit(tag.Id())
    80  			if err != nil {
    81  				return nil, errors.Trace(err)
    82  			}
    83  			serviceName := entity.ServiceName()
    84  			serviceTag := names.NewServiceTag(serviceName)
    85  			return func(tag names.Tag) bool {
    86  				return tag == serviceTag
    87  			}, nil
    88  		default:
    89  			return nil, errors.Errorf("expected names.UnitTag, got %T", tag)
    90  		}
    91  	}
    92  	accessMachine := func() (common.AuthFunc, error) {
    93  		switch tag := authorizer.GetAuthTag().(type) {
    94  		case names.UnitTag:
    95  			entity, err := st.Unit(tag.Id())
    96  			if err != nil {
    97  				return nil, errors.Trace(err)
    98  			}
    99  			machineId, err := entity.AssignedMachineId()
   100  			if err != nil {
   101  				return nil, errors.Trace(err)
   102  			}
   103  			machineTag := names.NewMachineTag(machineId)
   104  			return func(tag names.Tag) bool {
   105  				return tag == machineTag
   106  			}, nil
   107  		default:
   108  			return nil, errors.Errorf("expected names.UnitTag, got %T", tag)
   109  		}
   110  	}
   111  	storageAPI, err := newStorageAPI(getStorageState(st), resources, accessUnit)
   112  	if err != nil {
   113  		return nil, err
   114  	}
   115  	msAPI, err := meterstatus.NewMeterStatusAPI(st, resources, authorizer)
   116  	if err != nil {
   117  		return nil, errors.Annotate(err, "could not create meter status API handler")
   118  	}
   119  	accessUnitOrService := common.AuthEither(accessUnit, accessService)
   120  	return &UniterAPIV3{
   121  		LifeGetter:                 common.NewLifeGetter(st, accessUnitOrService),
   122  		DeadEnsurer:                common.NewDeadEnsurer(st, accessUnit),
   123  		AgentEntityWatcher:         common.NewAgentEntityWatcher(st, resources, accessUnitOrService),
   124  		APIAddresser:               common.NewAPIAddresser(st, resources),
   125  		ModelWatcher:               common.NewModelWatcher(st, resources, authorizer),
   126  		RebootRequester:            common.NewRebootRequester(st, accessMachine),
   127  		LeadershipSettingsAccessor: leadershipSettingsAccessorFactory(st, resources, authorizer),
   128  		MeterStatus:                msAPI,
   129  		// TODO(fwereade): so *every* unit should be allowed to get/set its
   130  		// own status *and* its service's? This is not a pleasing arrangement.
   131  		StatusAPI: NewStatusAPI(st, accessUnitOrService),
   132  
   133  		st:            st,
   134  		auth:          authorizer,
   135  		resources:     resources,
   136  		accessUnit:    accessUnit,
   137  		accessService: accessService,
   138  		accessMachine: accessMachine,
   139  		unit:          unit,
   140  		StorageAPI:    *storageAPI,
   141  	}, nil
   142  }
   143  
   144  // AllMachinePorts returns all opened port ranges for each given
   145  // machine (on all networks).
   146  func (u *UniterAPIV3) AllMachinePorts(args params.Entities) (params.MachinePortsResults, error) {
   147  	result := params.MachinePortsResults{
   148  		Results: make([]params.MachinePortsResult, len(args.Entities)),
   149  	}
   150  	canAccess, err := u.accessMachine()
   151  	if err != nil {
   152  		return params.MachinePortsResults{}, err
   153  	}
   154  	for i, entity := range args.Entities {
   155  		result.Results[i] = u.getOneMachinePorts(canAccess, entity.Tag)
   156  	}
   157  	return result, nil
   158  }
   159  
   160  // ServiceOwner returns the owner user for each given service tag.
   161  func (u *UniterAPIV3) ServiceOwner(args params.Entities) (params.StringResults, error) {
   162  	result := params.StringResults{
   163  		Results: make([]params.StringResult, len(args.Entities)),
   164  	}
   165  	canAccess, err := u.accessService()
   166  	if err != nil {
   167  		return params.StringResults{}, err
   168  	}
   169  	for i, entity := range args.Entities {
   170  		tag, err := names.ParseServiceTag(entity.Tag)
   171  		if err != nil {
   172  			result.Results[i].Error = common.ServerError(common.ErrPerm)
   173  			continue
   174  		}
   175  		if !canAccess(tag) {
   176  			result.Results[i].Error = common.ServerError(common.ErrPerm)
   177  			continue
   178  		}
   179  		service, err := u.getService(tag)
   180  		if err != nil {
   181  			result.Results[i].Error = common.ServerError(err)
   182  			continue
   183  		}
   184  		result.Results[i].Result = service.GetOwnerTag()
   185  	}
   186  	return result, nil
   187  }
   188  
   189  // AssignedMachine returns the machine tag for each given unit tag, or
   190  // an error satisfying params.IsCodeNotAssigned when a unit has no
   191  // assigned machine.
   192  func (u *UniterAPIV3) AssignedMachine(args params.Entities) (params.StringResults, error) {
   193  	result := params.StringResults{
   194  		Results: make([]params.StringResult, len(args.Entities)),
   195  	}
   196  	canAccess, err := u.accessUnit()
   197  	if err != nil {
   198  		return params.StringResults{}, err
   199  	}
   200  	for i, entity := range args.Entities {
   201  		tag, err := names.ParseUnitTag(entity.Tag)
   202  		if err != nil {
   203  			result.Results[i].Error = common.ServerError(common.ErrPerm)
   204  			continue
   205  		}
   206  		if !canAccess(tag) {
   207  			result.Results[i].Error = common.ServerError(common.ErrPerm)
   208  			continue
   209  		}
   210  		unit, err := u.getUnit(tag)
   211  		if err != nil {
   212  			result.Results[i].Error = common.ServerError(err)
   213  			continue
   214  		}
   215  		machineId, err := unit.AssignedMachineId()
   216  		if err != nil {
   217  			result.Results[i].Error = common.ServerError(err)
   218  		} else {
   219  			result.Results[i].Result = names.NewMachineTag(machineId).String()
   220  		}
   221  	}
   222  	return result, nil
   223  }
   224  
   225  func (u *UniterAPIV3) getMachine(tag names.MachineTag) (*state.Machine, error) {
   226  	return u.st.Machine(tag.Id())
   227  }
   228  
   229  func (u *UniterAPIV3) getOneMachinePorts(canAccess common.AuthFunc, machineTag string) params.MachinePortsResult {
   230  	tag, err := names.ParseMachineTag(machineTag)
   231  	if err != nil {
   232  		return params.MachinePortsResult{Error: common.ServerError(common.ErrPerm)}
   233  	}
   234  	if !canAccess(tag) {
   235  		return params.MachinePortsResult{Error: common.ServerError(common.ErrPerm)}
   236  	}
   237  	machine, err := u.getMachine(tag)
   238  	if err != nil {
   239  		return params.MachinePortsResult{Error: common.ServerError(err)}
   240  	}
   241  	allPorts, err := machine.AllPorts()
   242  	if err != nil {
   243  		return params.MachinePortsResult{Error: common.ServerError(err)}
   244  	}
   245  	var resultPorts []params.MachinePortRange
   246  	for _, ports := range allPorts {
   247  		// AllPortRanges gives a map, but apis require a stable order
   248  		// for results, so sort the port ranges.
   249  		portRangesToUnits := ports.AllPortRanges()
   250  		portRanges := make([]network.PortRange, 0, len(portRangesToUnits))
   251  		for portRange := range portRangesToUnits {
   252  			portRanges = append(portRanges, portRange)
   253  		}
   254  		network.SortPortRanges(portRanges)
   255  		for _, portRange := range portRanges {
   256  			unitName := portRangesToUnits[portRange]
   257  			resultPorts = append(resultPorts, params.MachinePortRange{
   258  				UnitTag:   names.NewUnitTag(unitName).String(),
   259  				PortRange: params.FromNetworkPortRange(portRange),
   260  			})
   261  		}
   262  	}
   263  	return params.MachinePortsResult{
   264  		Ports: resultPorts,
   265  	}
   266  }
   267  
   268  // PublicAddress returns the public address for each given unit, if set.
   269  func (u *UniterAPIV3) PublicAddress(args params.Entities) (params.StringResults, error) {
   270  	result := params.StringResults{
   271  		Results: make([]params.StringResult, len(args.Entities)),
   272  	}
   273  	canAccess, err := u.accessUnit()
   274  	if err != nil {
   275  		return params.StringResults{}, err
   276  	}
   277  	for i, entity := range args.Entities {
   278  		tag, err := names.ParseUnitTag(entity.Tag)
   279  		if err != nil {
   280  			result.Results[i].Error = common.ServerError(common.ErrPerm)
   281  			continue
   282  		}
   283  		err = common.ErrPerm
   284  		if canAccess(tag) {
   285  			var unit *state.Unit
   286  			unit, err = u.getUnit(tag)
   287  			if err == nil {
   288  				var address network.Address
   289  				address, err = unit.PublicAddress()
   290  				if err == nil {
   291  					result.Results[i].Result = address.Value
   292  				} else if network.IsNoAddress(err) {
   293  					err = common.NoAddressSetError(tag, "public")
   294  				}
   295  			}
   296  		}
   297  		result.Results[i].Error = common.ServerError(err)
   298  	}
   299  	return result, nil
   300  }
   301  
   302  // PrivateAddress returns the private address for each given unit, if set.
   303  func (u *UniterAPIV3) PrivateAddress(args params.Entities) (params.StringResults, error) {
   304  	result := params.StringResults{
   305  		Results: make([]params.StringResult, len(args.Entities)),
   306  	}
   307  	canAccess, err := u.accessUnit()
   308  	if err != nil {
   309  		return params.StringResults{}, err
   310  	}
   311  	for i, entity := range args.Entities {
   312  		tag, err := names.ParseUnitTag(entity.Tag)
   313  		if err != nil {
   314  			result.Results[i].Error = common.ServerError(common.ErrPerm)
   315  			continue
   316  		}
   317  		err = common.ErrPerm
   318  		if canAccess(tag) {
   319  			var unit *state.Unit
   320  			unit, err = u.getUnit(tag)
   321  			if err == nil {
   322  				var address network.Address
   323  				address, err = unit.PrivateAddress()
   324  				if err == nil {
   325  					result.Results[i].Result = address.Value
   326  				} else if network.IsNoAddress(err) {
   327  					err = common.NoAddressSetError(tag, "private")
   328  				}
   329  			}
   330  		}
   331  		result.Results[i].Error = common.ServerError(err)
   332  	}
   333  	return result, nil
   334  }
   335  
   336  // TODO(ericsnow) Factor out the common code amongst the many methods here.
   337  
   338  var getZone = func(st *state.State, tag names.Tag) (string, error) {
   339  	unit, err := st.Unit(tag.Id())
   340  	if err != nil {
   341  		return "", errors.Trace(err)
   342  	}
   343  	zone, err := unit.AvailabilityZone()
   344  	return zone, errors.Trace(err)
   345  }
   346  
   347  // AvailabilityZone returns the availability zone for each given unit, if applicable.
   348  func (u *UniterAPIV3) AvailabilityZone(args params.Entities) (params.StringResults, error) {
   349  	var results params.StringResults
   350  
   351  	canAccess, err := u.accessUnit()
   352  	if err != nil {
   353  		return results, errors.Trace(err)
   354  	}
   355  
   356  	// Prep the results.
   357  	results = params.StringResults{
   358  		Results: make([]params.StringResult, len(args.Entities)),
   359  	}
   360  
   361  	// Collect the zones. No zone will be collected for any entity where
   362  	// the tag is invalid or not authorized. Instead the corresponding
   363  	// result will be updated with the error.
   364  	for i, entity := range args.Entities {
   365  		tag, err := names.ParseUnitTag(entity.Tag)
   366  		if err != nil {
   367  			results.Results[i].Error = common.ServerError(common.ErrPerm)
   368  			continue
   369  		}
   370  		err = common.ErrPerm
   371  		if canAccess(tag) {
   372  			var zone string
   373  			zone, err = getZone(u.st, tag)
   374  			if err == nil {
   375  				results.Results[i].Result = zone
   376  			}
   377  		}
   378  		results.Results[i].Error = common.ServerError(err)
   379  	}
   380  
   381  	return results, nil
   382  }
   383  
   384  // Resolved returns the current resolved setting for each given unit.
   385  func (u *UniterAPIV3) Resolved(args params.Entities) (params.ResolvedModeResults, error) {
   386  	result := params.ResolvedModeResults{
   387  		Results: make([]params.ResolvedModeResult, len(args.Entities)),
   388  	}
   389  	canAccess, err := u.accessUnit()
   390  	if err != nil {
   391  		return params.ResolvedModeResults{}, err
   392  	}
   393  	for i, entity := range args.Entities {
   394  		tag, err := names.ParseUnitTag(entity.Tag)
   395  		if err != nil {
   396  			result.Results[i].Error = common.ServerError(common.ErrPerm)
   397  			continue
   398  		}
   399  		err = common.ErrPerm
   400  		if canAccess(tag) {
   401  			var unit *state.Unit
   402  			unit, err = u.getUnit(tag)
   403  			if err == nil {
   404  				result.Results[i].Mode = params.ResolvedMode(unit.Resolved())
   405  			}
   406  		}
   407  		result.Results[i].Error = common.ServerError(err)
   408  	}
   409  	return result, nil
   410  }
   411  
   412  // ClearResolved removes any resolved setting from each given unit.
   413  func (u *UniterAPIV3) ClearResolved(args params.Entities) (params.ErrorResults, error) {
   414  	result := params.ErrorResults{
   415  		Results: make([]params.ErrorResult, len(args.Entities)),
   416  	}
   417  	canAccess, err := u.accessUnit()
   418  	if err != nil {
   419  		return params.ErrorResults{}, err
   420  	}
   421  	for i, entity := range args.Entities {
   422  		tag, err := names.ParseUnitTag(entity.Tag)
   423  		if err != nil {
   424  			result.Results[i].Error = common.ServerError(common.ErrPerm)
   425  			continue
   426  		}
   427  		err = common.ErrPerm
   428  		if canAccess(tag) {
   429  			var unit *state.Unit
   430  			unit, err = u.getUnit(tag)
   431  			if err == nil {
   432  				err = unit.ClearResolved()
   433  			}
   434  		}
   435  		result.Results[i].Error = common.ServerError(err)
   436  	}
   437  	return result, nil
   438  }
   439  
   440  // GetPrincipal returns the result of calling PrincipalName() and
   441  // converting it to a tag, on each given unit.
   442  func (u *UniterAPIV3) GetPrincipal(args params.Entities) (params.StringBoolResults, error) {
   443  	result := params.StringBoolResults{
   444  		Results: make([]params.StringBoolResult, len(args.Entities)),
   445  	}
   446  	canAccess, err := u.accessUnit()
   447  	if err != nil {
   448  		return params.StringBoolResults{}, err
   449  	}
   450  	for i, entity := range args.Entities {
   451  		tag, err := names.ParseUnitTag(entity.Tag)
   452  		if err != nil {
   453  			result.Results[i].Error = common.ServerError(common.ErrPerm)
   454  			continue
   455  		}
   456  		err = common.ErrPerm
   457  		if canAccess(tag) {
   458  			var unit *state.Unit
   459  			unit, err = u.getUnit(tag)
   460  			if err == nil {
   461  				principal, ok := unit.PrincipalName()
   462  				if principal != "" {
   463  					result.Results[i].Result = names.NewUnitTag(principal).String()
   464  				}
   465  				result.Results[i].Ok = ok
   466  			}
   467  		}
   468  		result.Results[i].Error = common.ServerError(err)
   469  	}
   470  	return result, nil
   471  }
   472  
   473  // Destroy advances all given Alive units' lifecycles as far as
   474  // possible. See state/Unit.Destroy().
   475  func (u *UniterAPIV3) Destroy(args params.Entities) (params.ErrorResults, error) {
   476  	result := params.ErrorResults{
   477  		Results: make([]params.ErrorResult, len(args.Entities)),
   478  	}
   479  	canAccess, err := u.accessUnit()
   480  	if err != nil {
   481  		return params.ErrorResults{}, err
   482  	}
   483  	for i, entity := range args.Entities {
   484  		tag, err := names.ParseUnitTag(entity.Tag)
   485  		if err != nil {
   486  			result.Results[i].Error = common.ServerError(common.ErrPerm)
   487  			continue
   488  		}
   489  		err = common.ErrPerm
   490  		if canAccess(tag) {
   491  			var unit *state.Unit
   492  			unit, err = u.getUnit(tag)
   493  			if err == nil {
   494  				err = unit.Destroy()
   495  			}
   496  		}
   497  		result.Results[i].Error = common.ServerError(err)
   498  	}
   499  	return result, nil
   500  }
   501  
   502  // DestroyAllSubordinates destroys all subordinates of each given unit.
   503  func (u *UniterAPIV3) DestroyAllSubordinates(args params.Entities) (params.ErrorResults, error) {
   504  	result := params.ErrorResults{
   505  		Results: make([]params.ErrorResult, len(args.Entities)),
   506  	}
   507  	canAccess, err := u.accessUnit()
   508  	if err != nil {
   509  		return params.ErrorResults{}, err
   510  	}
   511  	for i, entity := range args.Entities {
   512  		tag, err := names.ParseUnitTag(entity.Tag)
   513  		if err != nil {
   514  			result.Results[i].Error = common.ServerError(common.ErrPerm)
   515  			continue
   516  		}
   517  		err = common.ErrPerm
   518  		if canAccess(tag) {
   519  			var unit *state.Unit
   520  			unit, err = u.getUnit(tag)
   521  			if err == nil {
   522  				err = u.destroySubordinates(unit)
   523  			}
   524  		}
   525  		result.Results[i].Error = common.ServerError(err)
   526  	}
   527  	return result, nil
   528  }
   529  
   530  // HasSubordinates returns the whether each given unit has any subordinates.
   531  func (u *UniterAPIV3) HasSubordinates(args params.Entities) (params.BoolResults, error) {
   532  	result := params.BoolResults{
   533  		Results: make([]params.BoolResult, len(args.Entities)),
   534  	}
   535  	canAccess, err := u.accessUnit()
   536  	if err != nil {
   537  		return params.BoolResults{}, err
   538  	}
   539  	for i, entity := range args.Entities {
   540  		tag, err := names.ParseUnitTag(entity.Tag)
   541  		if err != nil {
   542  			result.Results[i].Error = common.ServerError(common.ErrPerm)
   543  			continue
   544  		}
   545  		err = common.ErrPerm
   546  		if canAccess(tag) {
   547  			var unit *state.Unit
   548  			unit, err = u.getUnit(tag)
   549  			if err == nil {
   550  				subordinates := unit.SubordinateNames()
   551  				result.Results[i].Result = len(subordinates) > 0
   552  			}
   553  		}
   554  		result.Results[i].Error = common.ServerError(err)
   555  	}
   556  	return result, nil
   557  }
   558  
   559  // CharmModifiedVersion returns the most CharmModifiedVersion for all given
   560  // units or services.
   561  func (u *UniterAPIV3) CharmModifiedVersion(args params.Entities) (params.IntResults, error) {
   562  	results := params.IntResults{
   563  		Results: make([]params.IntResult, len(args.Entities)),
   564  	}
   565  
   566  	accessUnitOrService := common.AuthEither(u.accessUnit, u.accessService)
   567  	canAccess, err := accessUnitOrService()
   568  	if err != nil {
   569  		return results, err
   570  	}
   571  	for i, entity := range args.Entities {
   572  		ver, err := u.charmModifiedVersion(entity.Tag, canAccess)
   573  		if err != nil {
   574  			results.Results[i].Error = common.ServerError(err)
   575  			continue
   576  		}
   577  		results.Results[i].Result = ver
   578  	}
   579  	return results, nil
   580  }
   581  
   582  func (u *UniterAPIV3) charmModifiedVersion(tagStr string, canAccess func(names.Tag) bool) (int, error) {
   583  	tag, err := names.ParseTag(tagStr)
   584  	if err != nil {
   585  		return -1, common.ErrPerm
   586  	}
   587  	if !canAccess(tag) {
   588  		return -1, common.ErrPerm
   589  	}
   590  	unitOrService, err := u.st.FindEntity(tag)
   591  	if err != nil {
   592  		return -1, err
   593  	}
   594  	var service *state.Service
   595  	switch entity := unitOrService.(type) {
   596  	case *state.Service:
   597  		service = entity
   598  	case *state.Unit:
   599  		service, err = entity.Service()
   600  		if err != nil {
   601  			return -1, err
   602  		}
   603  	default:
   604  		return -1, errors.BadRequestf("type %t does not have a CharmModifiedVersion", entity)
   605  	}
   606  	return service.CharmModifiedVersion(), nil
   607  }
   608  
   609  // CharmURL returns the charm URL for all given units or services.
   610  func (u *UniterAPIV3) CharmURL(args params.Entities) (params.StringBoolResults, error) {
   611  	result := params.StringBoolResults{
   612  		Results: make([]params.StringBoolResult, len(args.Entities)),
   613  	}
   614  	accessUnitOrService := common.AuthEither(u.accessUnit, u.accessService)
   615  	canAccess, err := accessUnitOrService()
   616  	if err != nil {
   617  		return params.StringBoolResults{}, err
   618  	}
   619  	for i, entity := range args.Entities {
   620  		tag, err := names.ParseTag(entity.Tag)
   621  		if err != nil {
   622  			result.Results[i].Error = common.ServerError(common.ErrPerm)
   623  			continue
   624  		}
   625  		err = common.ErrPerm
   626  		if canAccess(tag) {
   627  			var unitOrService state.Entity
   628  			unitOrService, err = u.st.FindEntity(tag)
   629  			if err == nil {
   630  				charmURLer := unitOrService.(interface {
   631  					CharmURL() (*charm.URL, bool)
   632  				})
   633  				curl, ok := charmURLer.CharmURL()
   634  				if curl != nil {
   635  					result.Results[i].Result = curl.String()
   636  					result.Results[i].Ok = ok
   637  				}
   638  			}
   639  		}
   640  		result.Results[i].Error = common.ServerError(err)
   641  	}
   642  	return result, nil
   643  }
   644  
   645  // SetCharmURL sets the charm URL for each given unit. An error will
   646  // be returned if a unit is dead, or the charm URL is not know.
   647  func (u *UniterAPIV3) SetCharmURL(args params.EntitiesCharmURL) (params.ErrorResults, error) {
   648  	result := params.ErrorResults{
   649  		Results: make([]params.ErrorResult, len(args.Entities)),
   650  	}
   651  	canAccess, err := u.accessUnit()
   652  	if err != nil {
   653  		return params.ErrorResults{}, err
   654  	}
   655  	for i, entity := range args.Entities {
   656  		tag, err := names.ParseUnitTag(entity.Tag)
   657  		if err != nil {
   658  			result.Results[i].Error = common.ServerError(common.ErrPerm)
   659  			continue
   660  		}
   661  		err = common.ErrPerm
   662  		if canAccess(tag) {
   663  			var unit *state.Unit
   664  			unit, err = u.getUnit(tag)
   665  			if err == nil {
   666  				var curl *charm.URL
   667  				curl, err = charm.ParseURL(entity.CharmURL)
   668  				if err == nil {
   669  					err = unit.SetCharmURL(curl)
   670  				}
   671  			}
   672  		}
   673  		result.Results[i].Error = common.ServerError(err)
   674  	}
   675  	return result, nil
   676  }
   677  
   678  // OpenPorts sets the policy of the port range with protocol to be
   679  // opened, for all given units.
   680  func (u *UniterAPIV3) OpenPorts(args params.EntitiesPortRanges) (params.ErrorResults, error) {
   681  	result := params.ErrorResults{
   682  		Results: make([]params.ErrorResult, len(args.Entities)),
   683  	}
   684  	canAccess, err := u.accessUnit()
   685  	if err != nil {
   686  		return params.ErrorResults{}, 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  				err = unit.OpenPorts(entity.Protocol, entity.FromPort, entity.ToPort)
   700  			}
   701  		}
   702  		result.Results[i].Error = common.ServerError(err)
   703  	}
   704  	return result, nil
   705  }
   706  
   707  // ClosePorts sets the policy of the port range with protocol to be
   708  // closed, for all given units.
   709  func (u *UniterAPIV3) ClosePorts(args params.EntitiesPortRanges) (params.ErrorResults, error) {
   710  	result := params.ErrorResults{
   711  		Results: make([]params.ErrorResult, len(args.Entities)),
   712  	}
   713  	canAccess, err := u.accessUnit()
   714  	if err != nil {
   715  		return params.ErrorResults{}, err
   716  	}
   717  	for i, entity := range args.Entities {
   718  		tag, err := names.ParseUnitTag(entity.Tag)
   719  		if err != nil {
   720  			result.Results[i].Error = common.ServerError(common.ErrPerm)
   721  			continue
   722  		}
   723  		err = common.ErrPerm
   724  		if canAccess(tag) {
   725  			var unit *state.Unit
   726  			unit, err = u.getUnit(tag)
   727  			if err == nil {
   728  				err = unit.ClosePorts(entity.Protocol, entity.FromPort, entity.ToPort)
   729  			}
   730  		}
   731  		result.Results[i].Error = common.ServerError(err)
   732  	}
   733  	return result, nil
   734  }
   735  
   736  // WatchConfigSettings returns a NotifyWatcher for observing changes
   737  // to each unit's service configuration settings. See also
   738  // state/watcher.go:Unit.WatchConfigSettings().
   739  func (u *UniterAPIV3) WatchConfigSettings(args params.Entities) (params.NotifyWatchResults, error) {
   740  	result := params.NotifyWatchResults{
   741  		Results: make([]params.NotifyWatchResult, len(args.Entities)),
   742  	}
   743  	canAccess, err := u.accessUnit()
   744  	if err != nil {
   745  		return params.NotifyWatchResults{}, err
   746  	}
   747  	for i, entity := range args.Entities {
   748  		tag, err := names.ParseUnitTag(entity.Tag)
   749  		if err != nil {
   750  			result.Results[i].Error = common.ServerError(common.ErrPerm)
   751  			continue
   752  		}
   753  		err = common.ErrPerm
   754  		watcherId := ""
   755  		if canAccess(tag) {
   756  			watcherId, err = u.watchOneUnitConfigSettings(tag)
   757  		}
   758  		result.Results[i].NotifyWatcherId = watcherId
   759  		result.Results[i].Error = common.ServerError(err)
   760  	}
   761  	return result, nil
   762  }
   763  
   764  // WatchActionNotifications returns a StringsWatcher for observing
   765  // incoming action calls to a unit. See also state/watcher.go
   766  // Unit.WatchActionNotifications(). This method is called from
   767  // api/uniter/uniter.go WatchActionNotifications().
   768  func (u *UniterAPIV3) WatchActionNotifications(args params.Entities) (params.StringsWatchResults, error) {
   769  	tagToActionReceiver := common.TagToActionReceiverFn(u.st.FindEntity)
   770  	watchOne := common.WatchOneActionReceiverNotifications(tagToActionReceiver, u.resources.Register)
   771  	canAccess, err := u.accessUnit()
   772  	if err != nil {
   773  		return params.StringsWatchResults{}, err
   774  	}
   775  	return common.WatchActionNotifications(args, canAccess, watchOne), nil
   776  }
   777  
   778  // ConfigSettings returns the complete set of service charm config
   779  // settings available to each given unit.
   780  func (u *UniterAPIV3) ConfigSettings(args params.Entities) (params.ConfigSettingsResults, error) {
   781  	result := params.ConfigSettingsResults{
   782  		Results: make([]params.ConfigSettingsResult, len(args.Entities)),
   783  	}
   784  	canAccess, err := u.accessUnit()
   785  	if err != nil {
   786  		return params.ConfigSettingsResults{}, err
   787  	}
   788  	for i, entity := range args.Entities {
   789  		tag, err := names.ParseUnitTag(entity.Tag)
   790  		if err != nil {
   791  			result.Results[i].Error = common.ServerError(common.ErrPerm)
   792  			continue
   793  		}
   794  		err = common.ErrPerm
   795  		if canAccess(tag) {
   796  			var unit *state.Unit
   797  			unit, err = u.getUnit(tag)
   798  			if err == nil {
   799  				var settings charm.Settings
   800  				settings, err = unit.ConfigSettings()
   801  				if err == nil {
   802  					result.Results[i].Settings = params.ConfigSettings(settings)
   803  				}
   804  			}
   805  		}
   806  		result.Results[i].Error = common.ServerError(err)
   807  	}
   808  	return result, nil
   809  }
   810  
   811  // WatchServiceRelations returns a StringsWatcher, for each given
   812  // service, that notifies of changes to the lifecycles of relations
   813  // involving that service.
   814  func (u *UniterAPIV3) WatchServiceRelations(args params.Entities) (params.StringsWatchResults, error) {
   815  	result := params.StringsWatchResults{
   816  		Results: make([]params.StringsWatchResult, len(args.Entities)),
   817  	}
   818  	canAccess, err := u.accessService()
   819  	if err != nil {
   820  		return params.StringsWatchResults{}, err
   821  	}
   822  	for i, entity := range args.Entities {
   823  		tag, err := names.ParseServiceTag(entity.Tag)
   824  		if err != nil {
   825  			result.Results[i].Error = common.ServerError(common.ErrPerm)
   826  			continue
   827  		}
   828  		err = common.ErrPerm
   829  		if canAccess(tag) {
   830  			result.Results[i], err = u.watchOneServiceRelations(tag)
   831  		}
   832  		result.Results[i].Error = common.ServerError(err)
   833  	}
   834  	return result, nil
   835  }
   836  
   837  // CharmArchiveSha256 returns the SHA256 digest of the charm archive
   838  // (bundle) data for each charm url in the given parameters.
   839  func (u *UniterAPIV3) CharmArchiveSha256(args params.CharmURLs) (params.StringResults, error) {
   840  	result := params.StringResults{
   841  		Results: make([]params.StringResult, len(args.URLs)),
   842  	}
   843  	for i, arg := range args.URLs {
   844  		curl, err := charm.ParseURL(arg.URL)
   845  		if err != nil {
   846  			err = common.ErrPerm
   847  		} else {
   848  			var sch *state.Charm
   849  			sch, err = u.st.Charm(curl)
   850  			if errors.IsNotFound(err) {
   851  				err = common.ErrPerm
   852  			}
   853  			if err == nil {
   854  				result.Results[i].Result = sch.BundleSha256()
   855  			}
   856  		}
   857  		result.Results[i].Error = common.ServerError(err)
   858  	}
   859  	return result, nil
   860  }
   861  
   862  // CharmArchiveURLs returns the URLS for the charm archive
   863  // (bundle) data for each charm url in the given parameters.
   864  func (u *UniterAPIV3) CharmArchiveURLs(args params.CharmURLs) (params.StringsResults, error) {
   865  	apiHostPorts, err := u.st.APIHostPorts()
   866  	if err != nil {
   867  		return params.StringsResults{}, err
   868  	}
   869  	modelUUID := u.st.ModelUUID()
   870  	result := params.StringsResults{
   871  		Results: make([]params.StringsResult, len(args.URLs)),
   872  	}
   873  	for i, curl := range args.URLs {
   874  		if _, err := charm.ParseURL(curl.URL); err != nil {
   875  			result.Results[i].Error = common.ServerError(common.ErrPerm)
   876  			continue
   877  		}
   878  		urlPath := "/"
   879  		if modelUUID != "" {
   880  			urlPath = path.Join(urlPath, "model", modelUUID)
   881  		}
   882  		urlPath = path.Join(urlPath, "charms")
   883  		archiveURLs := make([]string, len(apiHostPorts))
   884  		for j, server := range apiHostPorts {
   885  			archiveURL := &url.URL{
   886  				Scheme: "https",
   887  				Host:   network.SelectInternalHostPort(server, false),
   888  				Path:   urlPath,
   889  			}
   890  			q := archiveURL.Query()
   891  			q.Set("url", curl.URL)
   892  			q.Set("file", "*")
   893  			archiveURL.RawQuery = q.Encode()
   894  			archiveURLs[j] = archiveURL.String()
   895  		}
   896  		result.Results[i].Result = archiveURLs
   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.ServiceTag) (*state.Service, error) {
  1247  	return u.st.Service(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.ServiceName())
  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  			ServiceName: ep.ServiceName,
  1321  			Relation:    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.ServiceTag) (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.UnitService(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 *common.Resources,
  1479  	auth common.Authorizer,
  1480  ) *leadershipapiserver.LeadershipSettingsAccessor {
  1481  	registerWatcher := func(serviceId string) (string, error) {
  1482  		service, err := st.Service(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.Service(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.Service(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.Service()
  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 && !network.IsNoAddress(err) {
  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 service %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 err != nil {
  1658  			return nil, errors.Annotatef(err, "cannot get subnet for address %q", addr)
  1659  		}
  1660  		if subnet == nil {
  1661  			logger.Debugf("skipping %s: not linked to a known subnet", addr)
  1662  			continue
  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  }