Index: state/apiserver/uniter/uniter.go |
=== modified file 'state/apiserver/uniter/uniter.go' |
--- state/apiserver/uniter/uniter.go 2013-08-13 15:48:38 +0000 |
+++ state/apiserver/uniter/uniter.go 2013-08-16 08:49:10 +0000 |
@@ -6,6 +6,8 @@ |
package uniter |
import ( |
+ "strconv" |
+ |
"launchpad.net/juju-core/charm" |
"launchpad.net/juju-core/errors" |
"launchpad.net/juju-core/names" |
@@ -22,12 +24,11 @@ |
*common.DeadEnsurer |
*common.AgentEntityWatcher |
- st *state.State |
- auth common.Authorizer |
- resources *common.Resources |
- getCanAccessUnit common.GetAuthFunc |
- getCanAccessService common.GetAuthFunc |
- getCanAccessUnitOrService common.GetAuthFunc |
+ st *state.State |
+ auth common.Authorizer |
+ resources *common.Resources |
+ accessUnit common.GetAuthFunc |
+ accessService common.GetAuthFunc |
} |
// NewUniterAPI creates a new instance of the Uniter API. |
@@ -35,10 +36,10 @@ |
if !authorizer.AuthUnitAgent() { |
return nil, common.ErrPerm |
} |
- getCanAccessUnit := func() (common.AuthFunc, error) { |
+ accessUnit := func() (common.AuthFunc, error) { |
return authorizer.AuthOwner, nil |
} |
- getCanAccessService := func() (common.AuthFunc, error) { |
+ accessService := func() (common.AuthFunc, error) { |
unit, ok := authorizer.GetAuthEntity().(*state.Unit) |
if !ok { |
panic("authenticated entity is not a unit") |
@@ -47,25 +48,24 @@ |
return tag == names.ServiceTag(unit.ServiceName()) |
}, nil |
} |
- getCanAccessUnitOrService := func() (common.AuthFunc, error) { |
- // These errors here are ignored: they're always nil. |
- canAccessService, _ := getCanAccessService() |
- canAccessUnit, _ := getCanAccessUnit() |
+ accessRelation := func() (common.AuthFunc, error) { |
return func(tag string) bool { |
- return canAccessService(tag) || canAccessUnit(tag) |
+ _, _, err := names.ParseTag(tag, names.RelationTagKind) |
+ return err == nil |
}, nil |
} |
+ accessUnitOrService := common.AuthEither(accessUnit, accessService) |
+ accessUnitServiceOrRelation := common.AuthEither(accessUnitOrService, accessRelation) |
return &UniterAPI{ |
- LifeGetter: common.NewLifeGetter(st, getCanAccessUnitOrService), |
- StatusSetter: common.NewStatusSetter(st, getCanAccessUnit), |
- DeadEnsurer: common.NewDeadEnsurer(st, getCanAccessUnit), |
- AgentEntityWatcher: common.NewAgentEntityWatcher(st, resources, getCanAccessUnitOrService), |
- st: st, |
- auth: authorizer, |
- resources: resources, |
- getCanAccessUnit: getCanAccessUnit, |
- getCanAccessService: getCanAccessService, |
- getCanAccessUnitOrService: getCanAccessUnitOrService, |
+ LifeGetter: common.NewLifeGetter(st, accessUnitServiceOrRelation), |
+ StatusSetter: common.NewStatusSetter(st, accessUnit), |
+ DeadEnsurer: common.NewDeadEnsurer(st, accessUnit), |
+ AgentEntityWatcher: common.NewAgentEntityWatcher(st, resources, accessUnitOrService), |
+ st: st, |
+ auth: authorizer, |
+ resources: resources, |
+ accessUnit: accessUnit, |
+ accessService: accessService, |
}, nil |
} |
@@ -91,7 +91,7 @@ |
result := params.StringBoolResults{ |
Results: make([]params.StringBoolResult, len(args.Entities)), |
} |
- canAccess, err := u.getCanAccessUnit() |
+ canAccess, err := u.accessUnit() |
if err != nil { |
return params.StringBoolResults{}, err |
} |
@@ -116,7 +116,7 @@ |
result := params.ErrorResults{ |
Results: make([]params.ErrorResult, len(args.Entities)), |
} |
- canAccess, err := u.getCanAccessUnit() |
+ canAccess, err := u.accessUnit() |
if err != nil { |
return params.ErrorResults{}, err |
} |
@@ -140,7 +140,7 @@ |
result := params.StringBoolResults{ |
Results: make([]params.StringBoolResult, len(args.Entities)), |
} |
- canAccess, err := u.getCanAccessUnit() |
+ canAccess, err := u.accessUnit() |
if err != nil { |
return params.StringBoolResults{}, err |
} |
@@ -165,7 +165,7 @@ |
result := params.ErrorResults{ |
Results: make([]params.ErrorResult, len(args.Entities)), |
} |
- canAccess, err := u.getCanAccessUnit() |
+ canAccess, err := u.accessUnit() |
if err != nil { |
return params.ErrorResults{}, err |
} |
@@ -188,7 +188,7 @@ |
result := params.ErrorResults{ |
Results: make([]params.ErrorResult, len(args.Entities)), |
} |
- canAccess, err := u.getCanAccessUnit() |
+ canAccess, err := u.accessUnit() |
if err != nil { |
return params.ErrorResults{}, err |
} |
@@ -211,7 +211,7 @@ |
result := params.StringBoolResults{ |
Results: make([]params.StringBoolResult, len(args.Entities)), |
} |
- canAccess, err := u.getCanAccessUnit() |
+ canAccess, err := u.accessUnit() |
if err != nil { |
return params.StringBoolResults{}, err |
} |
@@ -237,7 +237,7 @@ |
result := params.ErrorResults{ |
Results: make([]params.ErrorResult, len(args.Entities)), |
} |
- canAccess, err := u.getCanAccessUnit() |
+ canAccess, err := u.accessUnit() |
if err != nil { |
return params.ErrorResults{}, err |
} |
@@ -260,7 +260,7 @@ |
result := params.StringsResults{ |
Results: make([]params.StringsResult, len(args.Entities)), |
} |
- canAccess, err := u.getCanAccessUnit() |
+ canAccess, err := u.accessUnit() |
if err != nil { |
return params.StringsResults{}, err |
} |
@@ -283,7 +283,8 @@ |
result := params.StringBoolResults{ |
Results: make([]params.StringBoolResult, len(args.Entities)), |
} |
- canAccess, err := u.getCanAccessUnitOrService() |
+ accessUnitOrService := common.AuthEither(u.accessUnit, u.accessService) |
+ canAccess, err := accessUnitOrService() |
if err != nil { |
return params.StringBoolResults{}, err |
} |
@@ -312,7 +313,7 @@ |
result := params.ErrorResults{ |
Results: make([]params.ErrorResult, len(args.Entities)), |
} |
- canAccess, err := u.getCanAccessUnit() |
+ canAccess, err := u.accessUnit() |
if err != nil { |
return params.ErrorResults{}, err |
} |
@@ -340,7 +341,7 @@ |
result := params.ErrorResults{ |
Results: make([]params.ErrorResult, len(args.Entities)), |
} |
- canAccess, err := u.getCanAccessUnit() |
+ canAccess, err := u.accessUnit() |
if err != nil { |
return params.ErrorResults{}, err |
} |
@@ -364,7 +365,7 @@ |
result := params.ErrorResults{ |
Results: make([]params.ErrorResult, len(args.Entities)), |
} |
- canAccess, err := u.getCanAccessUnit() |
+ canAccess, err := u.accessUnit() |
if err != nil { |
return params.ErrorResults{}, err |
} |
@@ -408,7 +409,7 @@ |
result := params.NotifyWatchResults{ |
Results: make([]params.NotifyWatchResult, len(args.Entities)), |
} |
- canAccess, err := u.getCanAccessUnit() |
+ canAccess, err := u.accessUnit() |
if err != nil { |
return params.NotifyWatchResults{}, err |
} |
@@ -430,7 +431,7 @@ |
result := params.SettingsResults{ |
Results: make([]params.SettingsResult, len(args.Entities)), |
} |
- canAccess, err := u.getCanAccessUnit() |
+ canAccess, err := u.accessUnit() |
if err != nil { |
return params.SettingsResults{}, err |
} |
@@ -476,7 +477,7 @@ |
result := params.StringsWatchResults{ |
Results: make([]params.StringsWatchResult, len(args.Entities)), |
} |
- canAccess, err := u.getCanAccessService() |
+ canAccess, err := u.accessService() |
if err != nil { |
return params.StringsWatchResults{}, err |
} |
@@ -540,15 +541,81 @@ |
return result, nil |
} |
+func (u *UniterAPI) getOneRelation(canAccess common.AuthFunc, relTag, unitTag string) (params.RelationResult, error) { |
+ nothing := params.RelationResult{} |
+ _, id, err := names.ParseTag(relTag, names.RelationTagKind) |
+ if err != nil { |
+ return nothing, common.ErrPerm |
+ } |
+ // TODO(dimitern): Once the relation tags have a different format |
+ // (e.g. "relation-service1@name1+service2@name2"), change the |
+ // following code accordingly. |
+ relId, err := strconv.Atoi(id) |
+ if err != nil { |
+ return nothing, common.ErrPerm |
+ } |
+ rel, err := u.st.Relation(relId) |
+ if errors.IsNotFoundError(err) { |
+ return nothing, common.ErrPerm |
+ } else if err != nil { |
+ return nothing, err |
+ } |
+ if !canAccess(unitTag) { |
+ return nothing, common.ErrPerm |
+ } |
+ unit, err := u.getUnit(unitTag) |
+ if err != nil { |
+ return nothing, err |
+ } |
+ ep, err := rel.Endpoint(unit.ServiceName()) |
+ if err != nil { |
+ return nothing, err |
+ } |
+ return params.RelationResult{ |
+ Id: rel.Id(), |
+ Key: rel.String(), |
+ Endpoint: params.Endpoint{ |
+ ServiceName: ep.ServiceName, |
+ Relation: ep.Relation, |
+ }, |
+ }, nil |
+} |
+ |
+// Relation returns information about all given relation/unit pairs, |
+// including their id, key and the local endpoint. |
+func (u *UniterAPI) Relation(args params.Relations) (params.RelationResults, error) { |
+ result := params.RelationResults{ |
+ Results: make([]params.RelationResult, len(args.Relations)), |
+ } |
+ canAccess, err := u.accessUnit() |
+ if err != nil { |
+ return params.RelationResults{}, err |
+ } |
+ for i, rel := range args.Relations { |
+ relParams, err := u.getOneRelation(canAccess, rel.Relation, rel.Unit) |
+ if err == nil { |
+ result.Results[i] = relParams |
+ } |
+ result.Results[i].Error = common.ServerError(err) |
+ } |
+ return result, nil |
+} |
+ |
+// EnvironUUID returns the UUID for the current juju environment. |
fwereade
2013/08/16 09:38:07
CurrentEnvironUUID
dimitern
2013/08/16 10:32:14
Done in the follow-up branch.
|
+func (u *UniterAPI) CurrentEnvironUUID() (params.StringResult, error) { |
+ result := params.StringResult{} |
+ env, err := u.st.Environment() |
+ if err == nil { |
+ result.Result = env.UUID() |
+ } |
+ return result, err |
+} |
+ |
// TODO(dimitern): Add the following needed calls: |
-// RelationSetDying |
-// RelationIsImplicit |
-// RelationDestroy |
-// RelationRelationUnit |
-// RelationUnitRelation |
-// RelationUnitSettings |
-// RelationUnitEnterScope |
-// RelationUnitLeaveScope |
-// RelationUnitEndpoint |
-// EndpointImplementedBy |
-// EnvironUUID |
+// EnterScope (rel-id, unit-tag) |
+// LeaveScope (rel-id, unit-tag) |
+// Settings (rel-id, unit-tag) |
+// ReadSettings (rel-id, (remote)unit-tag) |
+// WriteSettings (rel-id, unit-tag, settings) |
+// |
+// RelationUnitsWatcher |