// CanDeploy returns if the currently authenticated entity (a machine // agent) can deploy each passed unit entity. func (d *DeployerAPI) CanDeploy(args params.Entities) (params.BoolResults, error) { result := params.BoolResults{ Results: make([]params.BoolResult, len(args.Entities)), } for i, entity := range args.Entities { unitName := state.UnitNameFromTag(entity.Tag) unit, err := d.st.Unit(unitName) if errors.IsNotFoundError(err) { // Unit not found, so no need to continue. continue } else if err != nil { // Any other error get reported back. result.Results[i].Error = common.ServerError(err) continue } machineId, err := unit.AssignedMachineId() if err != nil && !state.IsNotAssigned(err) && !errors.IsNotFoundError(err) { // Any other errors get reported back. result.Results[i].Error = common.ServerError(err) continue } else if err != nil { // This means the unit wasn't assigned to the machine // agent or it wasn't found. In both cases we just return // false so as not to leak information about the existence // of a unit to a potentially rogue machine agent. continue } // Finally, check if we're allowed to access this unit. // When assigned machineId == "" it will fail. result.Results[i].Result = d.authorizer.AuthOwner(state.MachineTag(machineId)) } return result, nil }
// NewDeployerAPI creates a new client-side DeployerAPI facade. func NewDeployerAPI( st *state.State, resources *common.Resources, authorizer common.Authorizer, ) (*DeployerAPI, error) { if !authorizer.AuthMachineAgent() { return nil, common.ErrPerm } getAuthFunc := func() (common.AuthFunc, error) { // Get all units of the machine and cache them. knownUnits := set.NewStrings() thisMachineTag := authorizer.GetAuthTag() if units, err := getAllUnits(st, thisMachineTag); err != nil { return nil, err } else { for _, unit := range units { knownUnits.Add(unit) } } // Then we just check if the unit is already known. return func(tag string) bool { unitName := state.UnitNameFromTag(tag) return knownUnits.Contains(unitName) }, nil } return &DeployerAPI{ Remover: common.NewRemover(st, getAuthFunc), PasswordChanger: common.NewPasswordChanger(st, getAuthFunc), LifeGetter: common.NewLifeGetter(st, getAuthFunc), st: st, resources: resources, authorizer: authorizer, }, nil }
func (s *UnitSuite) TestUnitNameFromTag(c *C) { // Try both valid and invalid tag formats. c.Assert(state.UnitNameFromTag("unit-wordpress-0"), Equals, "wordpress/0") c.Assert(state.UnitNameFromTag("foo"), Equals, "") }