github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/cmd/juju/commands/main.go (about)

     1  // Copyright 2012, 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package commands
     5  
     6  import (
     7  	"fmt"
     8  	"os"
     9  	"os/exec"
    10  	"strings"
    11  
    12  	"github.com/juju/cmd"
    13  	"github.com/juju/loggo"
    14  	rcmd "github.com/juju/romulus/cmd/commands"
    15  	"github.com/juju/utils/featureflag"
    16  	"github.com/juju/version"
    17  
    18  	jujucmd "github.com/juju/juju/cmd"
    19  	"github.com/juju/juju/cmd/juju/action"
    20  	"github.com/juju/juju/cmd/juju/backups"
    21  	"github.com/juju/juju/cmd/juju/block"
    22  	"github.com/juju/juju/cmd/juju/cachedimages"
    23  	"github.com/juju/juju/cmd/juju/charmcmd"
    24  	"github.com/juju/juju/cmd/juju/cloud"
    25  	"github.com/juju/juju/cmd/juju/controller"
    26  	"github.com/juju/juju/cmd/juju/gui"
    27  	"github.com/juju/juju/cmd/juju/machine"
    28  	"github.com/juju/juju/cmd/juju/metricsdebug"
    29  	"github.com/juju/juju/cmd/juju/model"
    30  	"github.com/juju/juju/cmd/juju/service"
    31  	"github.com/juju/juju/cmd/juju/setmeterstatus"
    32  	"github.com/juju/juju/cmd/juju/space"
    33  	"github.com/juju/juju/cmd/juju/status"
    34  	"github.com/juju/juju/cmd/juju/storage"
    35  	"github.com/juju/juju/cmd/juju/subnet"
    36  	"github.com/juju/juju/cmd/juju/user"
    37  	"github.com/juju/juju/cmd/modelcmd"
    38  	"github.com/juju/juju/feature"
    39  	"github.com/juju/juju/juju"
    40  	"github.com/juju/juju/juju/osenv"
    41  	jujuversion "github.com/juju/juju/version"
    42  	// Import the providers.
    43  	_ "github.com/juju/juju/provider/all"
    44  )
    45  
    46  var logger = loggo.GetLogger("juju.cmd.juju.commands")
    47  
    48  func init() {
    49  	featureflag.SetFlagsFromEnvironment(osenv.JujuFeatureFlagEnvKey)
    50  }
    51  
    52  // TODO(ericsnow) Move the following to cmd/juju/main.go:
    53  //  jujuDoc
    54  //  Main
    55  
    56  var jujuDoc = `
    57  juju provides easy, intelligent service orchestration on top of cloud
    58  infrastructure providers such as Amazon EC2, HP Cloud, MaaS, OpenStack, Windows
    59  Azure, or your local machine.
    60  
    61  https://juju.ubuntu.com/
    62  `
    63  
    64  const juju1xCmdName = "juju-1"
    65  
    66  var usageHelp = `
    67  Usage: juju [help] <command>
    68  
    69  Summary:
    70  Juju is model & service management software designed to leverage the power
    71  of existing resource pools, particularly cloud-based ones. It has built-in
    72  support for cloud providers such as Amazon EC2, Google GCE, Microsoft
    73  Azure, OpenStack, and Rackspace. It also works very well with MAAS and
    74  LXD. Juju allows for easy installation and management of workloads on a
    75  chosen resource pool.
    76  
    77  See https://jujucharms.com/docs/stable/help for documentation.
    78  
    79  Common commands:
    80  
    81      add-credential      Adds or replaces credentials for a cloud.
    82      add-relation        Adds a relation between two services.
    83      add-unit            Adds extra units of a deployed service.
    84      add-user            Adds a Juju user to a controller.
    85      bootstrap           Initializes a cloud environment.
    86      create-model        Creates a hosted model.
    87      deploy              Deploys a new service.
    88      expose              Makes a service publicly available over the network.
    89      list-controllers    Lists all controllers.
    90      list-models         Lists models a user can access on a controller.
    91      status              Displays the current status of Juju, services, and units.
    92      switch              Selects or identifies the current controller and model.
    93  
    94  Example help commands:
    95  
    96      `[1:] + "`juju help`" + `          This help page
    97      ` + "`juju help commands`" + ` Lists all commands
    98      ` + "`juju help deploy`" + `   Shows help for command 'deploy'
    99  `
   100  
   101  var x = []byte("\x96\x8c\x99\x8a\x9c\x94\x96\x91\x98\xdf\x9e\x92\x9e\x85\x96\x91\x98\xf5")
   102  
   103  // Main registers subcommands for the juju executable, and hands over control
   104  // to the cmd package. This function is not redundant with main, because it
   105  // provides an entry point for testing with arbitrary command line arguments.
   106  func Main(args []string) {
   107  	ctx, err := cmd.DefaultContext()
   108  	if err != nil {
   109  		fmt.Fprintf(os.Stderr, "error: %v\n", err)
   110  		os.Exit(2)
   111  	}
   112  
   113  	if shouldWarnJuju1x() {
   114  		warnJuju1x()
   115  	}
   116  
   117  	if err = juju.InitJujuXDGDataHome(); err != nil {
   118  		fmt.Fprintf(os.Stderr, "error: %s\n", err)
   119  		os.Exit(2)
   120  	}
   121  
   122  	for i := range x {
   123  		x[i] ^= 255
   124  	}
   125  	if len(args) == 2 && args[1] == string(x[0:2]) {
   126  		os.Stdout.Write(x[2:])
   127  		os.Exit(0)
   128  	}
   129  
   130  	jcmd := NewJujuCommand(ctx)
   131  	os.Exit(cmd.Main(jcmd, ctx, args[1:]))
   132  }
   133  
   134  func warnJuju1x() {
   135  	ver := "1.x"
   136  	out, err := execCommand(juju1xCmdName, "version").Output()
   137  	if err == nil {
   138  		v := strings.TrimSpace(string(out))
   139  		// parse so we can drop the series and arch
   140  		bin, err := version.ParseBinary(v)
   141  		if err == nil {
   142  			ver = bin.Number.String()
   143  		}
   144  	}
   145  	fmt.Fprintf(os.Stderr, `
   146      Welcome to Juju %s. If you meant to use Juju %s you can continue using it
   147      with the command %s e.g. '%s switch'.
   148      See https://jujucharms.com/docs/stable/introducing-2 for more details.
   149      `[1:], jujuversion.Current, ver, juju1xCmdName, juju1xCmdName)
   150  }
   151  
   152  var execCommand = exec.Command
   153  var execLookPath = exec.LookPath
   154  
   155  func shouldWarnJuju1x() bool {
   156  	if _, err := execLookPath(juju1xCmdName); err != nil {
   157  		return false
   158  	}
   159  	return osenv.Juju1xEnvConfigExists() &&
   160  		!juju2xConfigDataExists()
   161  }
   162  
   163  func juju2xConfigDataExists() bool {
   164  	_, err := os.Stat(osenv.JujuXDGDataHomeDir())
   165  	return err == nil
   166  }
   167  
   168  // NewJujuCommand ...
   169  func NewJujuCommand(ctx *cmd.Context) cmd.Command {
   170  	jcmd := jujucmd.NewSuperCommand(cmd.SuperCommandParams{
   171  		Name:                "juju",
   172  		Doc:                 jujuDoc,
   173  		MissingCallback:     RunPlugin,
   174  		UserAliasesFilename: osenv.JujuXDGDataHomePath("aliases"),
   175  	})
   176  	jcmd.AddHelpTopic("basics", "Basic Help Summary", usageHelp)
   177  	registerCommands(jcmd, ctx)
   178  	return jcmd
   179  }
   180  
   181  type commandRegistry interface {
   182  	Register(cmd.Command)
   183  	RegisterSuperAlias(name, super, forName string, check cmd.DeprecationCheck)
   184  	RegisterDeprecated(subcmd cmd.Command, check cmd.DeprecationCheck)
   185  }
   186  
   187  // TODO(ericsnow) Factor out the commands and aliases into a static
   188  // registry that can be passed to the supercommand separately.
   189  
   190  // registerCommands registers commands in the specified registry.
   191  func registerCommands(r commandRegistry, ctx *cmd.Context) {
   192  	// Creation commands.
   193  	r.Register(newBootstrapCommand())
   194  	r.Register(service.NewAddRelationCommand())
   195  
   196  	// Destruction commands.
   197  	r.Register(service.NewRemoveRelationCommand())
   198  	r.Register(service.NewRemoveServiceCommand())
   199  	r.Register(service.NewRemoveUnitCommand())
   200  
   201  	// Reporting commands.
   202  	r.Register(status.NewStatusCommand())
   203  	r.Register(newSwitchCommand())
   204  	r.Register(status.NewStatusHistoryCommand())
   205  
   206  	// Error resolution and debugging commands.
   207  	r.Register(newRunCommand())
   208  	r.Register(newSCPCommand())
   209  	r.Register(newSSHCommand())
   210  	r.Register(newResolvedCommand())
   211  	r.Register(newDebugLogCommand())
   212  	r.Register(newDebugHooksCommand())
   213  
   214  	// Configuration commands.
   215  	r.Register(model.NewModelGetConstraintsCommand())
   216  	r.Register(model.NewModelSetConstraintsCommand())
   217  	r.Register(newSyncToolsCommand())
   218  	r.Register(newUpgradeJujuCommand(nil))
   219  	r.Register(service.NewUpgradeCharmCommand())
   220  
   221  	// Charm publishing commands.
   222  	r.Register(newPublishCommand())
   223  
   224  	// Charm tool commands.
   225  	r.Register(newHelpToolCommand())
   226  	r.Register(charmcmd.NewSuperCommand())
   227  
   228  	// Manage backups.
   229  	r.Register(backups.NewCreateCommand())
   230  	r.Register(backups.NewDownloadCommand())
   231  	r.Register(backups.NewShowCommand())
   232  	r.Register(backups.NewListCommand())
   233  	r.Register(backups.NewRemoveCommand())
   234  	r.Register(backups.NewRestoreCommand())
   235  	r.Register(backups.NewUploadCommand())
   236  
   237  	// Manage authorized ssh keys.
   238  	r.Register(NewAddKeysCommand())
   239  	r.Register(NewRemoveKeysCommand())
   240  	r.Register(NewImportKeysCommand())
   241  	r.Register(NewListKeysCommand())
   242  
   243  	// Manage users and access
   244  	r.Register(user.NewAddCommand())
   245  	r.Register(user.NewChangePasswordCommand())
   246  	r.Register(user.NewShowUserCommand())
   247  	r.Register(user.NewListCommand())
   248  	r.Register(user.NewEnableCommand())
   249  	r.Register(user.NewDisableCommand())
   250  	r.Register(user.NewLoginCommand())
   251  	r.Register(user.NewLogoutCommand())
   252  
   253  	// Manage cached images
   254  	r.Register(cachedimages.NewRemoveCommand())
   255  	r.Register(cachedimages.NewListCommand())
   256  
   257  	// Manage machines
   258  	r.Register(machine.NewAddCommand())
   259  	r.Register(machine.NewRemoveCommand())
   260  	r.Register(machine.NewListMachinesCommand())
   261  	r.Register(machine.NewShowMachineCommand())
   262  
   263  	// Manage model
   264  	r.Register(model.NewGetCommand())
   265  	r.Register(model.NewSetCommand())
   266  	r.Register(model.NewUnsetCommand())
   267  	r.Register(model.NewRetryProvisioningCommand())
   268  	r.Register(model.NewDestroyCommand())
   269  	r.Register(model.NewUsersCommand())
   270  	r.Register(model.NewGrantCommand())
   271  	r.Register(model.NewRevokeCommand())
   272  	r.Register(model.NewShowCommand())
   273  
   274  	if featureflag.Enabled(feature.Migration) {
   275  		r.Register(newMigrateCommand())
   276  	}
   277  
   278  	// Manage and control actions
   279  	r.Register(action.NewStatusCommand())
   280  	r.Register(action.NewRunCommand())
   281  	r.Register(action.NewShowOutputCommand())
   282  	r.Register(action.NewListCommand())
   283  
   284  	// Manage controller availability
   285  	r.Register(newEnableHACommand())
   286  
   287  	// Manage and control services
   288  	r.Register(service.NewAddUnitCommand())
   289  	r.Register(service.NewGetCommand())
   290  	r.Register(service.NewSetCommand())
   291  	r.Register(service.NewDeployCommand())
   292  	r.Register(service.NewExposeCommand())
   293  	r.Register(service.NewUnexposeCommand())
   294  	r.Register(service.NewServiceGetConstraintsCommand())
   295  	r.Register(service.NewServiceSetConstraintsCommand())
   296  
   297  	// Operation protection commands
   298  	r.Register(block.NewSuperBlockCommand())
   299  	r.Register(block.NewUnblockCommand())
   300  
   301  	// Manage storage
   302  	r.Register(storage.NewAddCommand())
   303  	r.Register(storage.NewListCommand())
   304  	r.Register(storage.NewPoolCreateCommand())
   305  	r.Register(storage.NewPoolListCommand())
   306  	r.Register(storage.NewShowCommand())
   307  
   308  	// Manage spaces
   309  	r.Register(space.NewAddCommand())
   310  	r.Register(space.NewListCommand())
   311  	if featureflag.Enabled(feature.PostNetCLIMVP) {
   312  		r.Register(space.NewRemoveCommand())
   313  		r.Register(space.NewUpdateCommand())
   314  		r.Register(space.NewRenameCommand())
   315  	}
   316  
   317  	// Manage subnets
   318  	r.Register(subnet.NewAddCommand())
   319  	r.Register(subnet.NewListCommand())
   320  	if featureflag.Enabled(feature.PostNetCLIMVP) {
   321  		r.Register(subnet.NewCreateCommand())
   322  		r.Register(subnet.NewRemoveCommand())
   323  	}
   324  
   325  	// Manage controllers
   326  	r.Register(controller.NewCreateModelCommand())
   327  	r.Register(controller.NewDestroyCommand())
   328  	r.Register(controller.NewListModelsCommand())
   329  	r.Register(controller.NewKillCommand())
   330  	r.Register(controller.NewListControllersCommand())
   331  	r.Register(controller.NewListBlocksCommand())
   332  	r.Register(controller.NewRegisterCommand())
   333  	r.Register(controller.NewRemoveBlocksCommand())
   334  	r.Register(controller.NewShowControllerCommand())
   335  
   336  	// Debug Metrics
   337  	r.Register(metricsdebug.New())
   338  	r.Register(metricsdebug.NewCollectMetricsCommand())
   339  	r.Register(setmeterstatus.New())
   340  
   341  	// Manage clouds and credentials
   342  	r.Register(cloud.NewUpdateCloudsCommand())
   343  	r.Register(cloud.NewListCloudsCommand())
   344  	r.Register(cloud.NewShowCloudCommand())
   345  	r.Register(cloud.NewAddCloudCommand())
   346  	r.Register(cloud.NewListCredentialsCommand())
   347  	r.Register(cloud.NewDetectCredentialsCommand())
   348  	r.Register(cloud.NewSetDefaultRegionCommand())
   349  	r.Register(cloud.NewSetDefaultCredentialCommand())
   350  	r.Register(cloud.NewAddCredentialCommand())
   351  	r.Register(cloud.NewRemoveCredentialCommand())
   352  
   353  	// Juju GUI commands.
   354  	r.Register(gui.NewGUICommand())
   355  	r.Register(gui.NewUpgradeGUICommand())
   356  
   357  	// Commands registered elsewhere.
   358  	for _, newCommand := range registeredCommands {
   359  		command := newCommand()
   360  		r.Register(command)
   361  	}
   362  	for _, newCommand := range registeredEnvCommands {
   363  		command := newCommand()
   364  		r.Register(modelcmd.Wrap(command))
   365  	}
   366  	rcmd.RegisterAll(r)
   367  }