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  }