Beispiel #1
0
// authAndActionFromTagFn first authenticates the request, and then returns
// a function with which to authenticate and retrieve each action in the
// request.
func (u *UniterAPIV3) authAndActionFromTagFn() (func(string) (*state.Action, error), error) {
	canAccess, err := u.accessUnit()
	if err != nil {
		return nil, err
	}
	unit, ok := u.auth.GetAuthTag().(names.UnitTag)
	if !ok {
		return nil, fmt.Errorf("calling entity is not a unit")
	}

	return func(tag string) (*state.Action, error) {
		actionTag, err := names.ParseActionTag(tag)
		if err != nil {
			return nil, err
		}
		action, err := u.st.ActionByTag(actionTag)
		if err != nil {
			return nil, err
		}
		receiverTag, err := names.ActionReceiverTag(action.Receiver())
		if err != nil {
			return nil, err
		}
		if unit != receiverTag {
			return nil, common.ErrPerm
		}

		if !canAccess(receiverTag) {
			return nil, common.ErrPerm
		}
		return action, nil
	}, nil
}
Beispiel #2
0
// Actions takes a list of ActionTags, and returns the full Action for
// each ID.
func (a *ActionAPI) Actions(arg params.Entities) (params.ActionResults, error) {
	response := params.ActionResults{Results: make([]params.ActionResult, len(arg.Entities))}
	for i, entity := range arg.Entities {
		currentResult := &response.Results[i]
		tag, err := names.ParseTag(entity.Tag)
		if err != nil {
			currentResult.Error = common.ServerError(common.ErrBadId)
			continue
		}
		actionTag, ok := tag.(names.ActionTag)
		if !ok {
			currentResult.Error = common.ServerError(common.ErrBadId)
			continue
		}
		action, err := a.state.ActionByTag(actionTag)
		if err != nil {
			currentResult.Error = common.ServerError(common.ErrBadId)
			continue
		}
		receiverTag, err := names.ActionReceiverTag(action.Receiver())
		if err != nil {
			currentResult.Error = common.ServerError(err)
			continue
		}
		response.Results[i] = common.MakeActionResult(receiverTag, action)
	}
	return response, nil
}
Beispiel #3
0
// Cancel attempts to cancel enqueued Actions from running.
func (a *ActionAPI) Cancel(arg params.Entities) (params.ActionResults, error) {
	response := params.ActionResults{Results: make([]params.ActionResult, len(arg.Entities))}
	for i, entity := range arg.Entities {
		currentResult := &response.Results[i]
		tag, err := names.ParseTag(entity.Tag)
		if err != nil {
			currentResult.Error = common.ServerError(common.ErrBadId)
			continue
		}
		actionTag, ok := tag.(names.ActionTag)
		if !ok {
			currentResult.Error = common.ServerError(common.ErrBadId)
			continue
		}
		action, err := a.state.ActionByTag(actionTag)
		if err != nil {
			currentResult.Error = common.ServerError(err)
			continue
		}
		result, err := action.Finish(state.ActionResults{Status: state.ActionCancelled, Message: "action cancelled via the API"})
		if err != nil {
			currentResult.Error = common.ServerError(err)
			continue
		}
		receiverTag, err := names.ActionReceiverTag(result.Receiver())
		if err != nil {
			currentResult.Error = common.ServerError(err)
			continue
		}

		response.Results[i] = makeActionResult(receiverTag, result)
	}
	return response, nil
}
Beispiel #4
0
// AuthAndActionFromTagFn takes in an authorizer function and a function that can fetch action by tags from state
// and returns a function that can fetch an action from state by id and check the authorization.
func AuthAndActionFromTagFn(canAccess AuthFunc, getActionByTag func(names.ActionTag) (state.Action, error)) func(string) (state.Action, error) {
	return func(tag string) (state.Action, error) {
		actionTag, err := names.ParseActionTag(tag)
		if err != nil {
			return nil, errors.Trace(err)
		}
		action, err := getActionByTag(actionTag)
		if err != nil {
			return nil, errors.Trace(err)
		}
		receiverTag, err := names.ActionReceiverTag(action.Receiver())
		if err != nil {
			return nil, errors.Trace(err)
		}
		if !canAccess(receiverTag) {
			return nil, ErrPerm
		}
		return action, nil
	}
}
Beispiel #5
0
func (s *actionSuite) TestActionReceiverTag(c *gc.C) {
	testCases := []struct {
		name     string
		expected names.Tag
		valid    bool
	}{
		{name: "mysql", valid: false},
		{name: "mysql/3", expected: names.NewUnitTag("mysql/3"), valid: true},
	}

	for _, tcase := range testCases {
		tag, err := names.ActionReceiverTag(tcase.name)
		c.Check(err == nil, gc.Equals, tcase.valid)
		if err != nil {
			continue
		}
		c.Check(tag, gc.FitsTypeOf, tcase.expected)
		c.Check(tag, gc.Equals, tcase.expected)
	}

}
Beispiel #6
0
func (a *ActionAPI) FindActionsByNames(arg params.FindActionsByNames) (params.ActionsByNames, error) {
	response := params.ActionsByNames{Actions: make([]params.ActionsByName, len(arg.ActionNames))}
	for i, name := range arg.ActionNames {
		currentResult := &response.Actions[i]
		currentResult.Name = name

		actions, err := a.state.FindActionsByName(name)
		if err != nil {
			currentResult.Error = common.ServerError(err)
			continue
		}
		for _, action := range actions {
			recvTag, err := names.ActionReceiverTag(action.Receiver())
			if err != nil {
				currentResult.Actions = append(currentResult.Actions, params.ActionResult{Error: common.ServerError(err)})
				continue
			}
			currentAction := common.MakeActionResult(recvTag, action)
			currentResult.Actions = append(currentResult.Actions, currentAction)
		}
	}
	return response, nil
}
Beispiel #7
0
func (s *actionSuite) TestActionReceiverTag(c *gc.C) {
	testCases := []struct {
		name     string
		expected names.Tag
		err      string
	}{
		{name: "mysql", err: `invalid actionreceiver name "mysql"`},
		{name: "mysql/3", expected: names.NewUnitTag("mysql/3")},
		{name: "3", expected: names.NewMachineTag("3")},
	}

	for _, tcase := range testCases {
		tag, err := names.ActionReceiverTag(tcase.name)
		if tcase.err != "" {
			c.Check(err, gc.ErrorMatches, tcase.err)
			c.Check(tag, gc.IsNil)
			continue
		}
		c.Check(err, jc.ErrorIsNil)
		c.Check(tag, gc.FitsTypeOf, tcase.expected)
		c.Check(tag, gc.Equals, tcase.expected)
	}

}