Example #1
0
// 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
}
Example #2
0
// changed ensures that the named unit is deployed, recalled, or removed, as
// indicated by its state.
func (d *Deployer) changed(unitName string) error {
	// Determine unit life state, and whether we're responsible for it.
	logger.Infof("checking unit %q", unitName)
	var life state.Life
	responsible := false
	unit, err := d.st.Unit(unitName)
	if errors.IsNotFoundError(err) {
		life = state.Dead
	} else if err != nil {
		return err
	} else {
		life = unit.Life()
		if machineId, err := unit.AssignedMachineId(); state.IsNotAssigned(err) {
			logger.Warningf("ignoring unit %q (not assigned)", unitName)
			// Unit is not assigned, so we're not responsible for its deployment.
			responsible = false
		} else if err != nil {
			return err
		} else {
			// We're only responsible for this unit's deployment when we're
			// running inside the machine agent of the machine this unit
			// is assigned to.
			responsible = (machineId == d.machineId)
		}
	}
	// Deployed units must be removed if they're Dead, or if the deployer
	// is no longer responsible for them.
	if d.deployed.Contains(unitName) {
		if life == state.Dead || !responsible {
			if err := d.recall(unitName); err != nil {
				return err
			}
		}
	}
	// The only units that should be deployed are those that (1) we are responsible
	// for and (2) are Alive -- if we're responsible for a Dying unit that is not
	// yet deployed, we should remove it immediately rather than undergo the hassle
	// of deploying a unit agent purely so it can set itself to Dead.
	if responsible && !d.deployed.Contains(unitName) {
		if life == state.Alive {
			return d.deploy(unit)
		} else if unit != nil {
			return d.remove(unit)
		}
	}
	return nil
}
Example #3
0
// ServerError returns an error suitable for returning to an API
// client, with an error code suitable for various kinds of errors
// generated in packages outside the API.
func ServerError(err error) *params.Error {
	if err == nil {
		return nil
	}
	code := singletonErrorCodes[err]
	switch {
	case code != "":
	case errors.IsUnauthorizedError(err):
		code = params.CodeUnauthorized
	case errors.IsNotFoundError(err):
		code = params.CodeNotFound
	case state.IsNotAssigned(err):
		code = params.CodeNotAssigned
	case state.IsHasAssignedUnitsError(err):
		code = params.CodeHasAssignedUnits
	default:
		code = params.ErrCode(err)
	}
	return &params.Error{
		Message: err.Error(),
		Code:    code,
	}
}
Example #4
0
// unitsChanged responds to changes to the assigned units.
func (fw *Firewaller) unitsChanged(change *unitsChange) error {
	changed := []*unitData{}
	for _, name := range change.units {
		unit, err := fw.st.Unit(name)
		if err != nil && !errors.IsNotFoundError(err) {
			return err
		}
		var machineId string
		if unit != nil {
			machineId, err = unit.AssignedMachineId()
			if errors.IsNotFoundError(err) {
				continue
			} else if err != nil && !state.IsNotAssigned(err) {
				return err
			}
		}
		if unitd, known := fw.unitds[name]; known {
			knownMachineId := fw.unitds[name].machined.id
			if unit == nil || unit.Life() == state.Dead || machineId != knownMachineId {
				fw.forgetUnit(unitd)
				changed = append(changed, unitd)
				log.Debugf("worker/firewaller: stopped watching unit %s", name)
			}
		} else if unit != nil && unit.Life() != state.Dead && fw.machineds[machineId] != nil {
			err = fw.startUnit(unit, machineId)
			if err != nil {
				return err
			}
			changed = append(changed, fw.unitds[name])
			log.Debugf("worker/firewaller: started watching unit %s", name)
		}
	}
	if err := fw.flushUnits(changed); err != nil {
		return fmt.Errorf("cannot change firewall ports: %v", err)
	}
	return nil
}