Skip to content

Commit

Permalink
Merge pull request #9781 from timClicks/2.5
Browse files Browse the repository at this point in the history
#9781

This commit adds "is-controller" into ModelInfo and ModelSummary.
enabling clients to determine which model is the controller model
directly.

User-facing impacts:

 juju list-models --format=yaml
 juju list-models --formay=json
 juju show-model <controller-name> --format=yaml
 juju show-model <controller-name> --format=json

The resulting reports will include an `is-controller` line for each model.
  • Loading branch information
jujubot committed Feb 25, 2019
2 parents 52281de + 8f74e98 commit 4905fd2
Show file tree
Hide file tree
Showing 19 changed files with 91 additions and 14 deletions.
2 changes: 2 additions & 0 deletions api/base/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ type ModelInfo struct {
UUID string
Type model.ModelType
ControllerUUID string
IsController bool
ProviderType string
DefaultSeries string
Cloud string
Expand Down Expand Up @@ -109,6 +110,7 @@ type UserModelSummary struct {
UUID string
Type model.ModelType
ControllerUUID string
IsController bool
ProviderType string
DefaultSeries string
Cloud string
Expand Down
2 changes: 2 additions & 0 deletions api/modelmanager/modelmanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ func convertParamsModelInfo(modelInfo params.ModelInfo) (base.ModelInfo, error)
Name: modelInfo.Name,
UUID: modelInfo.UUID,
ControllerUUID: modelInfo.ControllerUUID,
IsController: modelInfo.IsController,
ProviderType: modelInfo.ProviderType,
DefaultSeries: modelInfo.DefaultSeries,
Cloud: cloud.Id(),
Expand Down Expand Up @@ -217,6 +218,7 @@ func (c *Client) ListModelSummaries(user string, all bool) ([]base.UserModelSumm
UUID: summary.UUID,
Type: modelType,
ControllerUUID: summary.ControllerUUID,
IsController: summary.IsController,
ProviderType: summary.ProviderType,
DefaultSeries: summary.DefaultSeries,
CloudRegion: summary.CloudRegion,
Expand Down
5 changes: 5 additions & 0 deletions apiserver/common/modelmanagerinterface.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ type ModelManagerBackend interface {
ComposeNewModelConfig(modelAttr map[string]interface{}, regionSpec *environs.RegionSpec) (map[string]interface{}, error)
ControllerModelUUID() string
ControllerModelTag() names.ModelTag
IsController() bool
ControllerConfig() (controller.Config, error)
ModelConfigDefaultValues() (config.ModelDefaultAttributes, error)
UpdateModelConfigDefaultValues(update map[string]interface{}, remove []string, regionSpec *environs.RegionSpec) error
Expand Down Expand Up @@ -176,6 +177,10 @@ func (st modelManagerStateShim) Name() string {
return st.model.Name()
}

func (st modelManagerStateShim) IsController() bool {
return st.State.IsController()
}

var _ Model = (*modelShim)(nil)

type modelShim struct {
Expand Down
21 changes: 12 additions & 9 deletions apiserver/facades/client/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -526,16 +526,19 @@ func (c *Client) ModelInfo() (params.ModelInfo, error) {
if err != nil {
return params.ModelInfo{}, err
}

info := params.ModelInfo{
DefaultSeries: config.PreferredSeries(conf),
CloudTag: names.NewCloudTag(model.Cloud()).String(),
CloudRegion: model.CloudRegion(),
ProviderType: conf.Type(),
Name: conf.Name(),
Type: string(model.Type()),
UUID: model.UUID(),
OwnerTag: model.Owner().String(),
Life: params.Life(model.Life().String()),
DefaultSeries: config.PreferredSeries(conf),
CloudTag: names.NewCloudTag(model.Cloud()).String(),
CloudRegion: model.CloudRegion(),
ProviderType: conf.Type(),
Name: conf.Name(),
Type: string(model.Type()),
UUID: model.UUID(),
OwnerTag: model.Owner().String(),
Life: params.Life(model.Life().String()),
ControllerUUID: state.ControllerTag().String(),
IsController: state.IsController(),
}
if agentVersion, exists := conf.AgentVersion(); exists {
info.AgentVersion = &agentVersion
Expand Down
5 changes: 2 additions & 3 deletions apiserver/facades/client/client/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,8 @@ func (s *serverSuite) TestModelInfo(c *gc.C) {
Level: "advanced",
Owner: "who",
})
// The controller UUID is not returned by the ModelInfo endpoint on the
// Client facade.
c.Assert(info.ControllerUUID, gc.Equals, "")
c.Assert(info.ControllerUUID, gc.Equals, "controller-deadbeef-1bad-500d-9000-4b1d0d06f00d")
c.Assert(info.IsController, gc.Equals, model.IsControllerModel())
}

func (s *serverSuite) TestModelUsersInfo(c *gc.C) {
Expand Down
1 change: 1 addition & 0 deletions apiserver/facades/client/controller/controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,7 @@ func (s *controllerSuite) TestWatchAllModels(c *gc.C) {
c.Assert(deltas, gc.HasLen, 1)
modelInfo := deltas[0].Entity.(*multiwatcher.ModelInfo)
c.Assert(modelInfo.ModelUUID, gc.Equals, s.State.ModelUUID())
c.Assert(modelInfo.IsController, gc.Equals, s.State.IsController())
case <-time.After(testing.LongWait):
c.Fatal("timed out")
}
Expand Down
11 changes: 11 additions & 0 deletions apiserver/facades/client/modelmanager/modelinfo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ func (s *modelInfoSuite) SetUpTest(c *gc.C) {
// default model will end up with the same model tag.
tag: coretesting.ModelTag,
controllerUUID: s.st.controllerUUID,
isController: true,
status: status.StatusInfo{
Status: status.Available,
Since: &time.Time{},
Expand All @@ -106,6 +107,7 @@ func (s *modelInfoSuite) SetUpTest(c *gc.C) {
cfg: coretesting.ModelConfig(c),
tag: coretesting.ModelTag,
controllerUUID: s.st.controllerUUID,
isController: false,
life: state.Dying,
status: status.StatusInfo{
Status: status.Destroying,
Expand Down Expand Up @@ -169,6 +171,7 @@ func (s *modelInfoSuite) TestModelInfo(c *gc.C) {
UUID: s.st.model.cfg.UUID(),
Type: string(s.st.model.Type()),
ControllerUUID: "deadbeef-1bad-500d-9000-4b1d0d06f00d",
IsController: false,
OwnerTag: "user-bob",
ProviderType: "someprovider",
CloudTag: "cloud-some-cloud",
Expand Down Expand Up @@ -217,6 +220,7 @@ func (s *modelInfoSuite) TestModelInfo(c *gc.C) {
{"ModelUUID", nil},
{"GetBackend", []interface{}{s.st.model.cfg.UUID()}},
{"Model", nil},
{"IsController", nil},
{"AllMachines", nil},
{"LatestMigration", nil},
})
Expand All @@ -226,6 +230,7 @@ func (s *modelInfoSuite) TestModelInfo(c *gc.C) {
{"Type", nil},
{"UUID", nil},
{"ControllerUUID", nil},
{"UUID", nil},
{"Owner", nil},
{"Life", nil},
{"Cloud", nil},
Expand Down Expand Up @@ -708,6 +713,11 @@ func (st *mockState) ControllerUUID() string {
return st.controllerUUID
}

func (st *mockState) IsController() bool {
st.MethodCall(st, "IsController")
return st.controllerUUID == st.model.UUID()
}

func (st *mockState) ControllerConfig() (controller.Config, error) {
st.MethodCall(st, "ControllerConfig")
return controller.Config{
Expand Down Expand Up @@ -946,6 +956,7 @@ type mockModel struct {
users []*mockModelUser
migrationStatus state.MigrationMode
controllerUUID string
isController bool
cfgDefaults config.ModelDefaultAttributes
setCloudCredentialF func(tag names.CloudCredentialTag) (bool, error)
}
Expand Down
2 changes: 2 additions & 0 deletions apiserver/facades/client/modelmanager/modelmanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -797,6 +797,7 @@ func (m *ModelManagerAPI) ListModelSummaries(req params.ModelSummariesRequest) (
Type: string(mi.Type),
OwnerTag: names.NewUserTag(mi.Owner).String(),
ControllerUUID: mi.ControllerUUID,
IsController: mi.IsController,
Life: params.Life(mi.Life.String()),

CloudTag: mi.CloudTag,
Expand Down Expand Up @@ -1006,6 +1007,7 @@ func (m *ModelManagerAPI) getModelInfo(tag names.ModelTag) (params.ModelInfo, er
Type: string(model.Type()),
UUID: model.UUID(),
ControllerUUID: model.ControllerUUID(),
IsController: st.IsController(),
OwnerTag: model.Owner().String(),
Life: params.Life(model.Life().String()),
CloudTag: names.NewCloudTag(model.Cloud()).String(),
Expand Down
2 changes: 2 additions & 0 deletions apiserver/facades/client/modelmanager/modelmanager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,7 @@ func (s *modelManagerSuite) TestCreateModelArgs(c *gc.C) {
"Close",
"GetBackend",
"Model",
"IsController",
"AllMachines",
"LatestMigration",
)
Expand Down Expand Up @@ -449,6 +450,7 @@ func (s *modelManagerSuite) TestCreateCAASModelArgs(c *gc.C) {
"Close",
"GetBackend",
"Model",
"IsController",
"AllMachines",
"LatestMigration",
)
Expand Down
2 changes: 2 additions & 0 deletions apiserver/params/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ type ModelInfo struct {
Type string `json:"type"`
UUID string `json:"uuid"`
ControllerUUID string `json:"controller-uuid"`
IsController bool `json:"is-controller"`
ProviderType string `json:"provider-type,omitempty"`
DefaultSeries string `json:"default-series,omitempty"`
CloudTag string `json:"cloud-tag"`
Expand Down Expand Up @@ -175,6 +176,7 @@ type ModelSummary struct {
UUID string `json:"uuid"`
Type string `json:"type"`
ControllerUUID string `json:"controller-uuid"`
IsController bool `json:"is-controller"`
ProviderType string `json:"provider-type,omitempty"`
DefaultSeries string `json:"default-series,omitempty"`
CloudTag string `json:"cloud-tag"`
Expand Down
2 changes: 2 additions & 0 deletions cmd/juju/common/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ type ModelInfo struct {
Type model.ModelType `json:"model-type" yaml:"model-type"`
ControllerUUID string `json:"controller-uuid" yaml:"controller-uuid"`
ControllerName string `json:"controller-name" yaml:"controller-name"`
IsController bool `json:"is-controller" yaml:"is-controller"`
Owner string `json:"owner" yaml:"owner"`
Cloud string `json:"cloud" yaml:"cloud"`
CloudRegion string `json:"region,omitempty" yaml:"region,omitempty"`
Expand Down Expand Up @@ -98,6 +99,7 @@ func ModelInfoFromParams(info params.ModelInfo, now time.Time) (ModelInfo, error
Type: model.ModelType(info.Type),
UUID: info.UUID,
ControllerUUID: info.ControllerUUID,
IsController: info.IsController,
Owner: ownerTag.Id(),
Life: string(info.Life),
Cloud: cloudTag.Id(),
Expand Down
2 changes: 2 additions & 0 deletions cmd/juju/controller/listmodels.go
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@ type ModelSummary struct {

ControllerUUID string `json:"controller-uuid" yaml:"controller-uuid"`
ControllerName string `json:"controller-name" yaml:"controller-name"`
IsController bool `json:"is-controller" yaml:"is-controller"`
Owner string `json:"owner" yaml:"owner"`
Cloud string `json:"cloud" yaml:"cloud"`
CloudRegion string `json:"region,omitempty" yaml:"region,omitempty"`
Expand All @@ -257,6 +258,7 @@ func (c *modelsCommand) modelSummaryFromParams(apiSummary base.UserModelSummary,
UUID: apiSummary.UUID,
Type: apiSummary.Type,
ControllerUUID: apiSummary.ControllerUUID,
IsController: apiSummary.IsController,
Owner: apiSummary.Owner,
Life: apiSummary.Life,
Cloud: apiSummary.Cloud,
Expand Down
14 changes: 12 additions & 2 deletions cmd/juju/controller/listmodels_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ func (f *fakeModelMgrAPIClient) ListModelSummaries(user string, all bool) ([]bas
Type: model.ModelType(info.Result.Type),
UUID: info.Result.UUID,
ControllerUUID: info.Result.ControllerUUID,
IsController: info.Result.IsController,
ProviderType: info.Result.ProviderType,
DefaultSeries: info.Result.DefaultSeries,
Cloud: cloud.Id(),
Expand Down Expand Up @@ -515,6 +516,7 @@ func createBasicModelInfo() *params.ModelInfo {
Type: "iaas",
ProviderType: "local",
ControllerUUID: testing.ControllerTag.Id(),
IsController: false,
OwnerTag: names.NewUserTag("owner").String(),
Life: params.Dead,
CloudTag: names.NewCloudTag("altostratus").String(),
Expand Down Expand Up @@ -576,7 +578,7 @@ func (s *ModelsSuiteV3) TestModelsWithOneUnauthorised(c *gc.C) {
func (s *ModelsSuiteV3) TestModelsJson(c *gc.C) {
context, err := cmdtesting.RunCommand(c, s.newCommand(), "--format", "json")
c.Assert(err, jc.ErrorIsNil)
c.Assert(cmdtesting.Stdout(context), gc.Equals, `{"models":[{"name":"admin/test-model1","short-name":"test-model1","model-uuid":"test-model1-UUID","model-type":"iaas","controller-uuid":"","controller-name":"fake","owner":"admin","cloud":"dummy","type":"local","life":"","status":{"current":"active"},"users":{"admin":{"access":"read","last-connection":"2015-03-20"}},"agent-version":"2.55.5"},{"name":"carlotta/test-model2","short-name":"test-model2","model-uuid":"test-model2-UUID","model-type":"iaas","controller-uuid":"","controller-name":"fake","owner":"carlotta","cloud":"dummy","type":"local","life":"","status":{"current":"active"},"users":{"admin":{"access":"write","last-connection":"2015-03-01"}},"agent-version":"2.55.5"},{"name":"daiwik@external/test-model3","short-name":"test-model3","model-uuid":"test-model3-UUID","model-type":"iaas","controller-uuid":"","controller-name":"fake","owner":"daiwik@external","cloud":"dummy","type":"local","life":"","status":{"current":"destroying"},"agent-version":"2.55.5"}],"current-model":"test-model1"}
c.Assert(cmdtesting.Stdout(context), gc.Equals, `{"models":[{"name":"admin/test-model1","short-name":"test-model1","model-uuid":"test-model1-UUID","model-type":"iaas","controller-uuid":"","controller-name":"fake","is-controller":false,"owner":"admin","cloud":"dummy","type":"local","life":"","status":{"current":"active"},"users":{"admin":{"access":"read","last-connection":"2015-03-20"}},"agent-version":"2.55.5"},{"name":"carlotta/test-model2","short-name":"test-model2","model-uuid":"test-model2-UUID","model-type":"iaas","controller-uuid":"","controller-name":"fake","is-controller":false,"owner":"carlotta","cloud":"dummy","type":"local","life":"","status":{"current":"active"},"users":{"admin":{"access":"write","last-connection":"2015-03-01"}},"agent-version":"2.55.5"},{"name":"daiwik@external/test-model3","short-name":"test-model3","model-uuid":"test-model3-UUID","model-type":"iaas","controller-uuid":"","controller-name":"fake","is-controller":false,"owner":"daiwik@external","cloud":"dummy","type":"local","life":"","status":{"current":"destroying"},"agent-version":"2.55.5"}],"current-model":"test-model1"}
`)
c.Assert(cmdtesting.Stderr(context), gc.Equals, "")
s.checkAPICalls(c, "BestAPIVersion", "ListModels", "ModelInfo", "Close")
Expand All @@ -593,6 +595,7 @@ models:
model-type: iaas
controller-uuid: ""
controller-name: fake
is-controller: false
owner: admin
cloud: dummy
type: local
Expand All @@ -610,6 +613,7 @@ models:
model-type: iaas
controller-uuid: ""
controller-name: fake
is-controller: false
owner: carlotta
cloud: dummy
type: local
Expand All @@ -627,6 +631,7 @@ models:
model-type: iaas
controller-uuid: ""
controller-name: fake
is-controller: false
owner: daiwik@external
cloud: dummy
type: local
Expand Down Expand Up @@ -670,7 +675,9 @@ func (s *ModelsSuiteV4) SetUpTest(c *gc.C) {
func (s *ModelsSuiteV4) TestModelsJson(c *gc.C) {
context, err := cmdtesting.RunCommand(c, s.newCommand(), "--format", "json")
c.Assert(err, jc.ErrorIsNil)
c.Assert(cmdtesting.Stdout(context), gc.Equals, `{"models":[{"name":"admin/test-model1","short-name":"test-model1","model-uuid":"test-model1-UUID","model-type":"iaas","controller-uuid":"","controller-name":"fake","owner":"admin","cloud":"dummy","credential":{"name":"one","owner":"bob","cloud":"foo"},"type":"local","life":"","status":{"current":"active"},"access":"read","last-connection":"2015-03-20","agent-version":"2.55.5"},{"name":"carlotta/test-model2","short-name":"test-model2","model-uuid":"test-model2-UUID","model-type":"iaas","controller-uuid":"","controller-name":"fake","owner":"carlotta","cloud":"dummy","credential":{"name":"one","owner":"bob","cloud":"foo"},"type":"local","life":"","status":{"current":"active"},"access":"write","last-connection":"2015-03-01","agent-version":"2.55.5"},{"name":"daiwik@external/test-model3","short-name":"test-model3","model-uuid":"test-model3-UUID","model-type":"iaas","controller-uuid":"","controller-name":"fake","owner":"daiwik@external","cloud":"dummy","credential":{"name":"one","owner":"bob","cloud":"foo"},"type":"local","life":"","status":{"current":"destroying"},"access":"","last-connection":"never connected","agent-version":"2.55.5"}],"current-model":"test-model1"}
//c.Assert(cmdtesting.Stdout(context), gc.Equals, `{"models":[{"name":"admin/test-model1","short-name":"test-model1","model-uuid":"test-model1-UUID","model-type":"iaas","controller-uuid":"","controller-name":"fake","owner":"admin","cloud":"dummy","credential":{"name":"one","owner":"bob","cloud":"foo"},"type":"local","life":"","status":{"current":"active"},"access":"read","last-connection":"2015-03-20","agent-version":"2.55.5"},{"name":"carlotta/test-model2","short-name":"test-model2","model-uuid":"test-model2-UUID","model-type":"iaas","controller-uuid":"","controller-name":"fake","owner":"carlotta","cloud":"dummy","credential":{"name":"one","owner":"bob","cloud":"foo"},"type":"local","life":"","status":{"current":"active"},"access":"write","last-connection":"2015-03-01","agent-version":"2.55.5"},{"name":"daiwik@external/test-model3","short-name":"test-model3","model-uuid":"test-model3-UUID","model-type":"iaas","controller-uuid":"","controller-name":"fake","owner":"daiwik@external","cloud":"dummy","credential":{"name":"one","owner":"bob","cloud":"foo"},"type":"local","life":"","status":{"current":"destroying"},"access":"","last-connection":"never connected","agent-version":"2.55.5"}],"current-model":"test-model1"}

c.Assert(cmdtesting.Stdout(context), gc.Equals, `{"models":[{"name":"admin/test-model1","short-name":"test-model1","model-uuid":"test-model1-UUID","model-type":"iaas","controller-uuid":"","controller-name":"fake","is-controller":false,"owner":"admin","cloud":"dummy","credential":{"name":"one","owner":"bob","cloud":"foo"},"type":"local","life":"","status":{"current":"active"},"access":"read","last-connection":"2015-03-20","agent-version":"2.55.5"},{"name":"carlotta/test-model2","short-name":"test-model2","model-uuid":"test-model2-UUID","model-type":"iaas","controller-uuid":"","controller-name":"fake","is-controller":false,"owner":"carlotta","cloud":"dummy","credential":{"name":"one","owner":"bob","cloud":"foo"},"type":"local","life":"","status":{"current":"active"},"access":"write","last-connection":"2015-03-01","agent-version":"2.55.5"},{"name":"daiwik@external/test-model3","short-name":"test-model3","model-uuid":"test-model3-UUID","model-type":"iaas","controller-uuid":"","controller-name":"fake","is-controller":false,"owner":"daiwik@external","cloud":"dummy","credential":{"name":"one","owner":"bob","cloud":"foo"},"type":"local","life":"","status":{"current":"destroying"},"access":"","last-connection":"never connected","agent-version":"2.55.5"}],"current-model":"test-model1"}
`)
c.Assert(cmdtesting.Stderr(context), gc.Equals, "")
s.checkAPICalls(c, "BestAPIVersion", "ListModels", "ModelInfo", "Close")
Expand All @@ -687,6 +694,7 @@ models:
model-type: iaas
controller-uuid: ""
controller-name: fake
is-controller: false
owner: admin
cloud: dummy
credential:
Expand All @@ -706,6 +714,7 @@ models:
model-type: iaas
controller-uuid: ""
controller-name: fake
is-controller: false
owner: carlotta
cloud: dummy
credential:
Expand All @@ -725,6 +734,7 @@ models:
model-type: iaas
controller-uuid: ""
controller-name: fake
is-controller: false
owner: daiwik@external
cloud: dummy
credential:
Expand Down

0 comments on commit 4905fd2

Please sign in to comment.