Skip to content

Commit

Permalink
model status api gains error.
Browse files Browse the repository at this point in the history
  • Loading branch information
anastasiamac committed Oct 27, 2017
1 parent 98171d3 commit 9890c1f
Show file tree
Hide file tree
Showing 19 changed files with 631 additions and 179 deletions.
1 change: 1 addition & 0 deletions api/base/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ type ModelStatus struct {
Machines []Machine
Volumes []Volume
Filesystems []Filesystem
Error error
}

// Machine holds information about a machine in a juju model.
Expand Down
124 changes: 84 additions & 40 deletions api/common/modelstatus.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,14 @@ func NewModelStatusAPI(facade base.FacadeCaller) *ModelStatusAPI {

// ModelStatus returns a status summary for each model tag passed in.
func (c *ModelStatusAPI) ModelStatus(tags ...names.ModelTag) ([]base.ModelStatus, error) {
// This call is used in both Controller and ModelManger facades.
// Luckily, prior to the signature change both of these facades were at version 3.
olderVersion := false
if bestVer := c.facade.BestAPIVersion(); bestVer < 4 {
logger.Debugf("calling older models status on v%d", bestVer)
olderVersion = true
}

result := params.ModelStatusResults{}
models := make([]params.Entity, len(tags))
for i, tag := range tags {
Expand All @@ -37,8 +45,40 @@ func (c *ModelStatusAPI) ModelStatus(tags ...names.ModelTag) ([]base.ModelStatus
return nil, err
}

results := make([]base.ModelStatus, len(result.Results))
for i, r := range result.Results {
if olderVersion {
// This caters for the fact that older version of base.ModelStatus
// did not have an Error field.
return c.processModelStatusResultsV3(result.Results)
}

return c.processModelStatusResults(result.Results)
}

func (c *ModelStatusAPI) processModelStatusResults(rs []params.ModelStatus) ([]base.ModelStatus, error) {
results := make([]base.ModelStatus, len(rs))
for i, r := range rs {
if r.Error != nil {
results[i].Error = errors.Trace(r.Error)
continue
}
model, err := names.ParseModelTag(r.ModelTag)
if err != nil {
results[i].Error = errors.Annotatef(err, "model tag %v", r.ModelTag)
continue
}
owner, err := names.ParseUserTag(r.OwnerTag)
if err != nil {
results[i].Error = errors.Annotatef(err, "owner tag %v", r.OwnerTag)
continue
}
results[i] = constructModelStatus(model, owner, r)
}
return results, nil
}

func (c *ModelStatusAPI) processModelStatusResultsV3(rs []params.ModelStatus) ([]base.ModelStatus, error) {
results := make([]base.ModelStatus, len(rs))
for i, r := range rs {
model, err := names.ParseModelTag(r.ModelTag)
if err != nil {
return nil, errors.Annotatef(err, "ModelTag %q at position %d", r.ModelTag, i)
Expand All @@ -47,50 +87,54 @@ func (c *ModelStatusAPI) ModelStatus(tags ...names.ModelTag) ([]base.ModelStatus
if err != nil {
return nil, errors.Annotatef(err, "OwnerTag %q at position %d", r.OwnerTag, i)
}
results[i] = constructModelStatus(model, owner, r)
}
return results, nil
}

volumes := make([]base.Volume, len(r.Volumes))
for i, in := range r.Volumes {
volumes[i] = base.Volume{
Id: in.Id,
ProviderId: in.ProviderId,
Status: in.Status,
Detachable: in.Detachable,
}
func constructModelStatus(model names.ModelTag, owner names.UserTag, r params.ModelStatus) base.ModelStatus {
volumes := make([]base.Volume, len(r.Volumes))
for i, in := range r.Volumes {
volumes[i] = base.Volume{
Id: in.Id,
ProviderId: in.ProviderId,
Status: in.Status,
Detachable: in.Detachable,
}
}

filesystems := make([]base.Filesystem, len(r.Filesystems))
for i, in := range r.Filesystems {
filesystems[i] = base.Filesystem{
Id: in.Id,
ProviderId: in.ProviderId,
Status: in.Status,
Detachable: in.Detachable,
}
filesystems := make([]base.Filesystem, len(r.Filesystems))
for i, in := range r.Filesystems {
filesystems[i] = base.Filesystem{
Id: in.Id,
ProviderId: in.ProviderId,
Status: in.Status,
Detachable: in.Detachable,
}
}

results[i] = base.ModelStatus{
UUID: model.Id(),
Life: string(r.Life),
Owner: owner.Id(),
HostedMachineCount: r.HostedMachineCount,
ServiceCount: r.ApplicationCount,
TotalMachineCount: len(r.Machines),
Volumes: volumes,
Filesystems: filesystems,
result := base.ModelStatus{
UUID: model.Id(),
Life: string(r.Life),
Owner: owner.Id(),
HostedMachineCount: r.HostedMachineCount,
ServiceCount: r.ApplicationCount,
TotalMachineCount: len(r.Machines),
Volumes: volumes,
Filesystems: filesystems,
}
result.Machines = make([]base.Machine, len(r.Machines))
for j, mm := range r.Machines {
if mm.Hardware != nil && mm.Hardware.Cores != nil {
result.CoreCount += int(*mm.Hardware.Cores)
}
results[i].Machines = make([]base.Machine, len(r.Machines))
for j, mm := range r.Machines {
if mm.Hardware != nil && mm.Hardware.Cores != nil {
results[i].CoreCount += int(*mm.Hardware.Cores)
}
results[i].Machines[j] = base.Machine{
Id: mm.Id,
InstanceId: mm.InstanceId,
HasVote: mm.HasVote,
WantsVote: mm.WantsVote,
Status: mm.Status,
}
result.Machines[j] = base.Machine{
Id: mm.Id,
InstanceId: mm.InstanceId,
HasVote: mm.HasVote,
WantsVote: mm.WantsVote,
Status: mm.Status,
}
}
return results, nil
return result
}
81 changes: 80 additions & 1 deletion api/controller/controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,22 @@ package controller_test

import (
"encoding/json"
"errors"

"github.com/juju/errors"
jujutesting "github.com/juju/testing"
jc "github.com/juju/testing/checkers"
"github.com/juju/utils"
gc "gopkg.in/check.v1"
"gopkg.in/juju/names.v2"
"gopkg.in/macaroon.v1"

"github.com/juju/juju/api/base"
apitesting "github.com/juju/juju/api/base/testing"
"github.com/juju/juju/api/controller"
"github.com/juju/juju/apiserver/common"
"github.com/juju/juju/apiserver/params"
"github.com/juju/juju/environs"
coretesting "github.com/juju/juju/testing"
)

type Suite struct {
Expand Down Expand Up @@ -271,3 +273,80 @@ func makeSpec() controller.MigrationSpec {
func randomUUID() string {
return utils.MustNewUUID().String()
}

func (s *Suite) TestModelStatusEmpty(c *gc.C) {
apiCaller := apitesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error {
c.Check(objType, gc.Equals, "Controller")
c.Check(id, gc.Equals, "")
c.Check(request, gc.Equals, "ModelStatus")
c.Check(result, gc.FitsTypeOf, &params.ModelStatusResults{})

return nil
})

client := controller.NewClient(apiCaller)
results, err := client.ModelStatus()
c.Assert(err, jc.ErrorIsNil)
c.Assert(results, jc.DeepEquals, []base.ModelStatus{})
}

func (s *Suite) TestModelStatus(c *gc.C) {
apiCaller := apitesting.BestVersionCaller{
BestVersion: 4,
APICallerFunc: func(objType string, version int, id, request string, arg, result interface{}) error {
c.Check(objType, gc.Equals, "Controller")
c.Check(id, gc.Equals, "")
c.Check(request, gc.Equals, "ModelStatus")
c.Check(arg, jc.DeepEquals, params.Entities{
[]params.Entity{
{Tag: coretesting.ModelTag.String()},
{Tag: coretesting.ModelTag.String()},
},
})
c.Check(result, gc.FitsTypeOf, &params.ModelStatusResults{})

out := result.(*params.ModelStatusResults)
out.Results = []params.ModelStatus{
params.ModelStatus{
ModelTag: coretesting.ModelTag.String(),
OwnerTag: "user-glenda",
ApplicationCount: 3,
HostedMachineCount: 2,
Life: "alive",
Machines: []params.ModelMachineInfo{{
Id: "0",
InstanceId: "inst-ance",
Status: "pending",
}},
},
params.ModelStatus{Error: common.ServerError(errors.New("model error"))},
}
return nil
},
}

client := controller.NewClient(apiCaller)
results, err := client.ModelStatus(coretesting.ModelTag, coretesting.ModelTag)
c.Assert(err, jc.ErrorIsNil)
c.Assert(results[0], jc.DeepEquals, base.ModelStatus{
UUID: coretesting.ModelTag.Id(),
TotalMachineCount: 1,
HostedMachineCount: 2,
ServiceCount: 3,
Owner: "glenda",
Life: string(params.Alive),
Machines: []base.Machine{{Id: "0", InstanceId: "inst-ance", Status: "pending"}},
})
c.Assert(results[1].Error, gc.ErrorMatches, "model error")
}

func (s *Suite) TestModelStatusError(c *gc.C) {
apiCaller := apitesting.APICallerFunc(
func(objType string, version int, id, request string, args, result interface{}) error {
return errors.New("model error")
})
client := controller.NewClient(apiCaller)
out, err := client.ModelStatus(coretesting.ModelTag, coretesting.ModelTag)
c.Assert(err, gc.ErrorMatches, "model error")
c.Assert(out, gc.IsNil)
}
19 changes: 0 additions & 19 deletions api/controller/legacy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import (
"gopkg.in/juju/names.v2"

"github.com/juju/juju/api"
"github.com/juju/juju/api/base"
"github.com/juju/juju/api/controller"
"github.com/juju/juju/apiserver"
commontesting "github.com/juju/juju/apiserver/common/testing"
Expand Down Expand Up @@ -290,24 +289,6 @@ func (s *legacySuite) TestAPIServerCanShutdownWithOutstandingNext(c *gc.C) {
}
}

func (s *legacySuite) TestModelStatus(c *gc.C) {
sysManager := s.OpenAPI(c)
defer sysManager.Close()
s.Factory.MakeMachine(c, nil)
modelTag := s.IAASModel.ModelTag()
results, err := sysManager.ModelStatus(modelTag)
c.Assert(err, jc.ErrorIsNil)
c.Assert(results, jc.DeepEquals, []base.ModelStatus{{
UUID: modelTag.Id(),
TotalMachineCount: 1,
HostedMachineCount: 1,
ServiceCount: 0,
Owner: "admin",
Life: string(params.Alive),
Machines: []base.Machine{{Id: "0", InstanceId: "id-2", Status: "pending"}},
}})
}

func (s *legacySuite) TestGetControllerAccess(c *gc.C) {
controller := s.OpenAPI(c)
defer controller.Close()
Expand Down
Loading

0 comments on commit 9890c1f

Please sign in to comment.