forked from juju/juju
/
listmodelsold.go
231 lines (210 loc) · 6.6 KB
/
listmodelsold.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
// Copyright 2015 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.
package controller
import (
"fmt"
"io"
"strings"
"time"
"github.com/juju/cmd"
"github.com/juju/errors"
"gopkg.in/juju/names.v2"
"github.com/juju/juju/api/base"
"github.com/juju/juju/apiserver/params"
"github.com/juju/juju/cmd/juju/common"
"github.com/juju/juju/cmd/output"
"github.com/juju/juju/jujuclient"
)
// oldModelsCommandBehaviour is the 'models' behavior for pre Juju 2.3.
// This call:
// * gets all possible models (api calls)
// * translates them into user-friendly representation (presentation layer)
// * stores retrieved models in client store
// * identifies current model
// Call returns whether any models hav been found and any errors.
func (c *modelsCommand) oldModelsCommandBehaviour(
ctx *cmd.Context,
modelmanagerAPI ModelManagerAPI,
now time.Time,
) (bool, error) {
var models []base.UserModel
var err error
if c.all {
models, err = c.getAllModels()
} else {
models, err = c.getUserModels(modelmanagerAPI)
}
if err != nil {
return false, errors.Annotate(err, "cannot list models")
}
modelInfo, modelsToStore, err := c.getModelInfo(modelmanagerAPI, now, models)
if err != nil {
return false, errors.Annotate(err, "cannot get model details")
}
found := len(modelInfo) > 0
if err := c.ClientStore().SetModels(c.runVars.controllerName, modelsToStore); err != nil {
return found, errors.Trace(err)
}
// Identifying current model has to be done after models in client store have been updated
// since that call determines/updates current model information.
modelSet := ModelSet{Models: modelInfo}
modelSet.CurrentModelQualified, modelSet.CurrentModel = c.currentModelName()
if err := c.out.Write(ctx, modelSet); err != nil {
return found, err
}
return found, err
}
// (anastasiamac 2017-23-11) This is old, pre juju 2.3 implementation.
func (c *modelsCommand) getModelInfo(
client ModelManagerAPI,
now time.Time,
userModels []base.UserModel,
) ([]common.ModelInfo, map[string]jujuclient.ModelDetails, error) {
tags := make([]names.ModelTag, len(userModels))
for i, m := range userModels {
tags[i] = names.NewModelTag(m.UUID)
}
results, err := client.ModelInfo(tags)
if err != nil {
return nil, nil, errors.Trace(err)
}
info := []common.ModelInfo{}
modelsToStore := map[string]jujuclient.ModelDetails{}
for i, result := range results {
if result.Error != nil {
if params.IsCodeUnauthorized(result.Error) {
// If we get this, then the model was removed
// between the initial listing and the call
// to query its details.
continue
}
return nil, nil, errors.Annotatef(
result.Error, "getting model %s (%q) info",
userModels[i].UUID, userModels[i].Name,
)
}
model, err := common.ModelInfoFromParams(*result.Result, now)
if err != nil {
return nil, nil, errors.Trace(err)
}
model.ControllerName = c.runVars.controllerName
info = append(info, model)
modelsToStore[model.Name] = jujuclient.ModelDetails{ModelUUID: model.UUID, ModelType: model.Type}
if len(model.Machines) != 0 {
c.runVars.hasMachinesCount = true
for _, m := range model.Machines {
if m.Cores != 0 {
c.runVars.hasCoresCount = true
break
}
}
}
}
return info, modelsToStore, nil
}
func (c *modelsCommand) getAllModels() ([]base.UserModel, error) {
client, err := c.getSysAPI()
if err != nil {
return nil, errors.Trace(err)
}
defer client.Close()
return client.AllModels()
}
// ModelsSysAPI defines the methods on the controller manager API that the
// list models command calls.
type ModelsSysAPI interface {
Close() error
AllModels() ([]base.UserModel, error)
}
func (c *modelsCommand) getSysAPI() (ModelsSysAPI, error) {
if c.sysAPI != nil {
return c.sysAPI, nil
}
return c.NewControllerAPIClient()
}
func (c *modelsCommand) getUserModels(client ModelManagerAPI) ([]base.UserModel, error) {
return client.ListModels(c.user)
}
// ModelSet contains the set of models known to the client,
// and UUID of the current model.
// (anastasiamac 2017-23-11) This is old, pre juju 2.3 implementation.
type ModelSet struct {
Models []common.ModelInfo `yaml:"models" json:"models"`
// CurrentModel is the name of the current model, qualified for the
// user for which we're listing models. i.e. for the user admin,
// and the model admin/foo, this field will contain "foo"; for
// bob and the same model, the field will contain "admin/foo".
CurrentModel string `yaml:"current-model,omitempty" json:"current-model,omitempty"`
// CurrentModelQualified is the fully qualified name for the current
// model, i.e. having the format $owner/$model.
CurrentModelQualified string `yaml:"-" json:"-"`
}
// formatTabular takes a model set to adhere to the cmd.Formatter interface
// (anastasiamac 2017-23-11) This is old, pre juju 2.3 implementation.
func (c *modelsCommand) tabularSet(writer io.Writer, modelSet ModelSet) error {
// We need the tag of the user for which we're listing models,
// and for the logged-in user. We use these below when formatting
// the model display names.
loggedInUser := names.NewUserTag(c.loggedInUser)
userForLastConn := loggedInUser
var currentUser names.UserTag
if c.user != "" {
currentUser = names.NewUserTag(c.user)
userForLastConn = currentUser
}
tw := output.TabWriter(writer)
w := output.Wrapper{tw}
c.tabularColumns(tw, w)
for _, model := range modelSet.Models {
cloudRegion := strings.Trim(model.Cloud+"/"+model.CloudRegion, "/")
owner := names.NewUserTag(model.Owner)
name := model.Name
if currentUser == owner {
// No need to display fully qualified model name to its owner.
name = model.ShortName
}
if model.Name == modelSet.CurrentModelQualified {
name += "*"
w.PrintColor(output.CurrentHighlight, name)
} else {
w.Print(name)
}
if c.listUUID {
w.Print(model.UUID)
}
userForAccess := loggedInUser
if c.user != "" {
userForAccess = names.NewUserTag(c.user)
}
status := "-"
if model.Status != nil {
status = model.Status.Current.String()
}
w.Print(cloudRegion, model.ProviderType, status)
if c.runVars.hasMachinesCount {
w.Print(fmt.Sprintf("%d", len(model.Machines)))
}
if c.runVars.hasCoresCount {
cores := uint64(0)
for _, m := range model.Machines {
cores += m.Cores
}
coresInfo := "-"
if cores > 0 {
coresInfo = fmt.Sprintf("%d", cores)
}
w.Print(coresInfo)
}
access := model.Users[userForAccess.Id()].Access
if access == "" {
access = "-"
}
lastConnection := model.Users[userForLastConn.Id()].LastConnection
if lastConnection == "" {
lastConnection = "never connected"
}
w.Println(access, lastConnection)
}
tw.Flush()
return nil
}