Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[dev] move meter status state to the controller #11405

Merged
4 changes: 2 additions & 2 deletions api/common/unitstate.go
Expand Up @@ -18,8 +18,8 @@ type UnitStateAPI struct {
tag names.UnitTag
}

// NewUpgradeSeriesAPI creates a UpgradeSeriesAPI on the specified facade,
// and uses this name when calling through the caller.
// NewUniterStateAPI creates a UnitStateAPI that uses the provided FacadeCaller
// for making calls.
func NewUniterStateAPI(facade base.FacadeCaller, tag names.UnitTag) *UnitStateAPI {
return &UnitStateAPI{facade: facade, tag: tag}
}
Expand Down
17 changes: 8 additions & 9 deletions apiserver/common/unitstate.go
Expand Up @@ -80,7 +80,6 @@ func NewUnitStateAPI(
accessUnit GetAuthFunc,
logger loggo.Logger,
) *UnitStateAPI {
logger.Tracef("NewUnitStateAPI called with %s", authorizer.GetAuthTag())
return &UnitStateAPI{
backend: backend,
resources: resources,
Expand Down Expand Up @@ -120,14 +119,11 @@ func (u *UnitStateAPI) State(args params.Entities) (params.UnitStateResults, err
res[i].Error = ServerError(err)
continue
}
uState, _ := unitState.State()
res[i].State = uState
uUState, _ := unitState.UniterState()
res[i].UniterState = uUState
rState, _ := unitState.RelationState()
res[i].RelationState = rState
sState, _ := unitState.StorageState()
res[i].StorageState = sState
res[i].State, _ = unitState.State()
res[i].UniterState, _ = unitState.UniterState()
res[i].RelationState, _ = unitState.RelationState()
res[i].StorageState, _ = unitState.StorageState()
res[i].MeterStatusState, _ = unitState.MeterStatusState()
}

return params.UnitStateResults{Results: res}, nil
Expand Down Expand Up @@ -178,6 +174,9 @@ func (u *UnitStateAPI) SetState(args params.SetUnitStateArgs) (params.ErrorResul
if arg.StorageState != nil {
unitState.SetStorageState(*arg.StorageState)
}
if arg.MeterStatusState != nil {
unitState.SetMeterStatusState(*arg.MeterStatusState)
}

ops := unit.SetStateOperation(
unitState,
Expand Down
99 changes: 68 additions & 31 deletions apiserver/facades/agent/meterstatus/meterstatus.go
Expand Up @@ -8,13 +8,18 @@ import (
"gopkg.in/juju/names.v3"

"github.com/juju/errors"
"github.com/juju/loggo"

"github.com/juju/juju/apiserver/common"
"github.com/juju/juju/apiserver/facade"
"github.com/juju/juju/apiserver/params"
"github.com/juju/juju/controller"
"github.com/juju/juju/state"
"github.com/juju/juju/state/watcher"
)

var logger = loggo.GetLogger("juju.apiserver.meterstatus")

// MeterStatus defines the methods exported by the meter status API facade.
type MeterStatus interface {
GetMeterStatus(args params.Entities) (params.MeterStatusResults, error)
Expand All @@ -24,6 +29,8 @@ type MeterStatus interface {
// MeterStatusState represents the state of an model required by the MeterStatus.
//go:generate mockgen -package mocks -destination mocks/meterstatus_mock.go github.com/juju/juju/apiserver/facades/agent/meterstatus MeterStatusState
type MeterStatusState interface {
ApplyOperation(state.ModelOperation) error
ControllerConfig() (controller.Config, error)

// Application returns a application state by name.
Application(name string) (*state.Application, error)
Expand All @@ -35,6 +42,8 @@ type MeterStatusState interface {
// MeterStatusAPI implements the MeterStatus interface and is the concrete implementation
// of the API endpoint.
type MeterStatusAPI struct {
*common.UnitStateAPI

state MeterStatusState
accessUnit common.GetAuthFunc
resources facade.Resources
Expand All @@ -56,38 +65,48 @@ func NewMeterStatusAPI(
if !authorizer.AuthUnitAgent() && !authorizer.AuthApplicationAgent() {
return nil, common.ErrPerm
}
return &MeterStatusAPI{
state: st,
accessUnit: func() (common.AuthFunc, error) {
switch tag := authorizer.GetAuthTag().(type) {
case names.ApplicationTag:
// If called by an application agent, any of the units
// belonging to that application can be accessed.
app, err := st.Application(tag.Name)
if err != nil {
return nil, errors.Trace(err)
}
allUnits, err := app.AllUnits()
if err != nil {
return nil, errors.Trace(err)
}
return func(tag names.Tag) bool {
for _, u := range allUnits {
if u.Tag() == tag {
return true
}
}
return false
}, nil
case names.UnitTag:
return func(tag names.Tag) bool {
return authorizer.AuthOwner(tag)
}, nil
default:
return nil, errors.Errorf("expected names.UnitTag or names.ApplicationTag, got %T", tag)

var accessCheckerFn = func() (common.AuthFunc, error) {
switch tag := authorizer.GetAuthTag().(type) {
case names.ApplicationTag:
// If called by an application agent, any of the units
// belonging to that application can be accessed.
app, err := st.Application(tag.Name)
if err != nil {
return nil, errors.Trace(err)
}
allUnits, err := app.AllUnits()
if err != nil {
return nil, errors.Trace(err)
}
},
resources: resources,
return func(tag names.Tag) bool {
for _, u := range allUnits {
if u.Tag() == tag {
return true
}
}
return false
}, nil
case names.UnitTag:
return func(tag names.Tag) bool {
return authorizer.AuthOwner(tag)
}, nil
default:
return nil, errors.Errorf("expected names.UnitTag or names.ApplicationTag, got %T", tag)
}
}

return &MeterStatusAPI{
state: st,
accessUnit: accessCheckerFn,
resources: resources,
UnitStateAPI: common.NewUnitStateAPI(
unitStateShim{st},
resources,
authorizer,
accessCheckerFn,
logger,
),
}, nil
}

Expand Down Expand Up @@ -160,3 +179,21 @@ func (m *MeterStatusAPI) GetMeterStatus(args params.Entities) (params.MeterStatu
}
return result, nil
}

// unitStateShim adapts the state backend for this facade to make it compatible
// with common.UnitStateAPI.
type unitStateShim struct {
st MeterStatusState
}

func (s unitStateShim) ApplyOperation(op state.ModelOperation) error {
return s.st.ApplyOperation(op)
}

func (s unitStateShim) ControllerConfig() (controller.Config, error) {
return s.st.ControllerConfig()
}

func (s unitStateShim) Unit(name string) (common.UnitStateUnit, error) {
return s.st.Unit(name)
}
37 changes: 35 additions & 2 deletions apiserver/facades/agent/meterstatus/mocks/meterstatus_mock.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

38 changes: 29 additions & 9 deletions apiserver/facades/agent/uniter/uniter.go
Expand Up @@ -3420,18 +3420,38 @@ func (u *UniterAPI) commitHookChangesForOneUnit(unitTag names.UnitTag, changes p
if changes.SetUnitState.Tag != changes.Tag {
return common.ErrPerm
}

newUS := state.NewUnitState()
if changes.SetUnitState.State != nil {
newUS := state.NewUnitState()
newUS.SetState(*changes.SetUnitState.State)
modelOp := unit.SetStateOperation(
newUS,
state.UnitStateSizeLimits{
MaxCharmStateSize: ctrlCfg.MaxCharmStateSize(),
MaxAgentStateSize: ctrlCfg.MaxAgentStateSize(),
},
)
modelOps = append(modelOps, modelOp)
}

// NOTE(achilleasa): The following state fields are not
// presently populated by the uniter calls to this API as they
// get persisted after the hook changes get committed. However,
// they are still checked here for future use and for ensuring
// symmetry with the SetState call (see apiserver/common).
if changes.SetUnitState.UniterState != nil {
newUS.SetUniterState(*changes.SetUnitState.UniterState)
}
if changes.SetUnitState.RelationState != nil {
newUS.SetRelationState(*changes.SetUnitState.RelationState)
}
if changes.SetUnitState.StorageState != nil {
newUS.SetStorageState(*changes.SetUnitState.StorageState)
}
if changes.SetUnitState.MeterStatusState != nil {
newUS.SetMeterStatusState(*changes.SetUnitState.MeterStatusState)
}

modelOp := unit.SetStateOperation(
newUS,
state.UnitStateSizeLimits{
MaxCharmStateSize: ctrlCfg.MaxCharmStateSize(),
MaxAgentStateSize: ctrlCfg.MaxAgentStateSize(),
},
)
modelOps = append(modelOps, modelOp)
}

for _, addParams := range changes.AddStorage {
Expand Down