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