github.com/altoros/juju-vmware@v0.0.0-20150312064031-f19ae857ccca/cmd/juju/main.go (about)

     1  // Copyright 2012, 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package main
     5  
     6  import (
     7  	"fmt"
     8  	"os"
     9  
    10  	"github.com/juju/cmd"
    11  	"github.com/juju/loggo"
    12  	"github.com/juju/utils/featureflag"
    13  
    14  	jujucmd "github.com/juju/juju/cmd"
    15  	"github.com/juju/juju/cmd/envcmd"
    16  	"github.com/juju/juju/cmd/juju/action"
    17  	"github.com/juju/juju/cmd/juju/backups"
    18  	"github.com/juju/juju/cmd/juju/block"
    19  	"github.com/juju/juju/cmd/juju/cachedimages"
    20  	"github.com/juju/juju/cmd/juju/charms"
    21  	"github.com/juju/juju/cmd/juju/environment"
    22  	"github.com/juju/juju/cmd/juju/machine"
    23  	"github.com/juju/juju/cmd/juju/storage"
    24  	"github.com/juju/juju/cmd/juju/user"
    25  	"github.com/juju/juju/environs"
    26  	"github.com/juju/juju/feature"
    27  	"github.com/juju/juju/juju"
    28  	"github.com/juju/juju/juju/osenv"
    29  	"github.com/juju/juju/version"
    30  	// Import the providers.
    31  	_ "github.com/juju/juju/provider/all"
    32  )
    33  
    34  func init() {
    35  	featureflag.SetFlagsFromEnvironment(osenv.JujuFeatureFlagEnvKey)
    36  }
    37  
    38  var logger = loggo.GetLogger("juju.cmd.juju")
    39  
    40  var jujuDoc = `
    41  juju provides easy, intelligent service orchestration on top of cloud
    42  infrastructure providers such as Amazon EC2, HP Cloud, MaaS, OpenStack, Windows
    43  Azure, or your local machine.
    44  
    45  https://juju.ubuntu.com/
    46  `
    47  
    48  var x = []byte("\x96\x8c\x99\x8a\x9c\x94\x96\x91\x98\xdf\x9e\x92\x9e\x85\x96\x91\x98\xf5")
    49  
    50  // Main registers subcommands for the juju executable, and hands over control
    51  // to the cmd package. This function is not redundant with main, because it
    52  // provides an entry point for testing with arbitrary command line arguments.
    53  func Main(args []string) {
    54  	ctx, err := cmd.DefaultContext()
    55  	if err != nil {
    56  		fmt.Fprintf(os.Stderr, "error: %v\n", err)
    57  		os.Exit(2)
    58  	}
    59  	if err = juju.InitJujuHome(); err != nil {
    60  		fmt.Fprintf(os.Stderr, "error: %s\n", err)
    61  		os.Exit(2)
    62  	}
    63  	for i := range x {
    64  		x[i] ^= 255
    65  	}
    66  	if len(args) == 2 && args[1] == string(x[0:2]) {
    67  		os.Stdout.Write(x[2:])
    68  		os.Exit(0)
    69  	}
    70  	jcmd := NewJujuCommand(ctx)
    71  	os.Exit(cmd.Main(jcmd, ctx, args[1:]))
    72  }
    73  
    74  func NewJujuCommand(ctx *cmd.Context) cmd.Command {
    75  	jcmd := jujucmd.NewSuperCommand(cmd.SuperCommandParams{
    76  		Name:            "juju",
    77  		Doc:             jujuDoc,
    78  		MissingCallback: RunPlugin,
    79  	})
    80  	jcmd.AddHelpTopic("basics", "Basic commands", helpBasics)
    81  	jcmd.AddHelpTopic("local-provider", "How to configure a local (LXC) provider",
    82  		helpProviderStart+helpLocalProvider+helpProviderEnd)
    83  	jcmd.AddHelpTopic("openstack-provider", "How to configure an OpenStack provider",
    84  		helpProviderStart+helpOpenstackProvider+helpProviderEnd, "openstack")
    85  	jcmd.AddHelpTopic("ec2-provider", "How to configure an Amazon EC2 provider",
    86  		helpProviderStart+helpEC2Provider+helpProviderEnd, "ec2", "aws", "amazon")
    87  	jcmd.AddHelpTopic("hpcloud-provider", "How to configure an HP Cloud provider",
    88  		helpProviderStart+helpHPCloud+helpProviderEnd, "hpcloud", "hp-cloud")
    89  	jcmd.AddHelpTopic("azure-provider", "How to configure a Windows Azure provider",
    90  		helpProviderStart+helpAzureProvider+helpProviderEnd, "azure")
    91  	jcmd.AddHelpTopic("maas-provider", "How to configure a MAAS provider",
    92  		helpProviderStart+helpMAASProvider+helpProviderEnd, "maas")
    93  	jcmd.AddHelpTopic("constraints", "How to use commands with constraints", helpConstraints)
    94  	jcmd.AddHelpTopic("placement", "How to use placement directives", helpPlacement)
    95  	jcmd.AddHelpTopic("glossary", "Glossary of terms", helpGlossary)
    96  	jcmd.AddHelpTopic("logging", "How Juju handles logging", helpLogging)
    97  
    98  	jcmd.AddHelpTopicCallback("plugins", "Show Juju plugins", PluginHelpTopic)
    99  
   100  	registerCommands(jcmd, ctx)
   101  	return jcmd
   102  }
   103  
   104  type commandRegistry interface {
   105  	Register(cmd.Command)
   106  	RegisterSuperAlias(name, super, forName string, check cmd.DeprecationCheck)
   107  }
   108  
   109  // registerCommands registers commands in the specified registry.
   110  // EnvironCommands must be wrapped with an envCmdWrapper.
   111  func registerCommands(r commandRegistry, ctx *cmd.Context) {
   112  	wrapEnvCommand := func(c envcmd.EnvironCommand) cmd.Command {
   113  		return envCmdWrapper{envcmd.Wrap(c), ctx}
   114  	}
   115  
   116  	// Creation commands.
   117  	r.Register(wrapEnvCommand(&BootstrapCommand{}))
   118  	r.Register(wrapEnvCommand(&DeployCommand{}))
   119  	r.Register(wrapEnvCommand(&AddRelationCommand{}))
   120  	r.Register(wrapEnvCommand(&AddUnitCommand{}))
   121  
   122  	// Destruction commands.
   123  	r.Register(wrapEnvCommand(&RemoveRelationCommand{}))
   124  	r.Register(wrapEnvCommand(&RemoveServiceCommand{}))
   125  	r.Register(wrapEnvCommand(&RemoveUnitCommand{}))
   126  	r.Register(&DestroyEnvironmentCommand{})
   127  
   128  	// Reporting commands.
   129  	r.Register(wrapEnvCommand(&StatusCommand{}))
   130  	r.Register(&SwitchCommand{})
   131  	r.Register(wrapEnvCommand(&EndpointCommand{}))
   132  	r.Register(wrapEnvCommand(&APIInfoCommand{}))
   133  
   134  	// Error resolution and debugging commands.
   135  	r.Register(wrapEnvCommand(&RunCommand{}))
   136  	r.Register(wrapEnvCommand(&SCPCommand{}))
   137  	r.Register(wrapEnvCommand(&SSHCommand{}))
   138  	r.Register(wrapEnvCommand(&ResolvedCommand{}))
   139  	r.Register(wrapEnvCommand(&DebugLogCommand{}))
   140  	r.Register(wrapEnvCommand(&DebugHooksCommand{}))
   141  
   142  	// Configuration commands.
   143  	r.Register(&InitCommand{})
   144  	r.Register(wrapEnvCommand(&GetCommand{}))
   145  	r.Register(wrapEnvCommand(&SetCommand{}))
   146  	r.Register(wrapEnvCommand(&UnsetCommand{}))
   147  	r.Register(wrapEnvCommand(&GetConstraintsCommand{}))
   148  	r.Register(wrapEnvCommand(&SetConstraintsCommand{}))
   149  	r.Register(wrapEnvCommand(&ExposeCommand{}))
   150  	r.Register(wrapEnvCommand(&SyncToolsCommand{}))
   151  	r.Register(wrapEnvCommand(&UnexposeCommand{}))
   152  	r.Register(wrapEnvCommand(&UpgradeJujuCommand{}))
   153  	r.Register(wrapEnvCommand(&UpgradeCharmCommand{}))
   154  
   155  	// Charm publishing commands.
   156  	r.Register(wrapEnvCommand(&PublishCommand{}))
   157  
   158  	// Charm tool commands.
   159  	r.Register(&HelpToolCommand{})
   160  
   161  	// Charm management commands.
   162  	r.Register(charms.NewSuperCommand())
   163  
   164  	// Manage backups.
   165  	r.Register(backups.NewCommand())
   166  
   167  	// Manage authorized ssh keys.
   168  	r.Register(NewAuthorizedKeysCommand())
   169  
   170  	// Manage users and access
   171  	r.Register(user.NewSuperCommand())
   172  
   173  	// Manage cached images
   174  	r.Register(cachedimages.NewSuperCommand())
   175  
   176  	// Manage machines
   177  	r.Register(machine.NewSuperCommand())
   178  	r.RegisterSuperAlias("add-machine", "machine", "add", twoDotOhDeprecation("machine add"))
   179  	r.RegisterSuperAlias("remove-machine", "machine", "remove", twoDotOhDeprecation("machine remove"))
   180  	r.RegisterSuperAlias("destroy-machine", "machine", "remove", twoDotOhDeprecation("machine remove"))
   181  	r.RegisterSuperAlias("terminate-machine", "machine", "remove", twoDotOhDeprecation("machine remove"))
   182  
   183  	// Mangage environment
   184  	r.Register(environment.NewSuperCommand())
   185  	r.RegisterSuperAlias("get-environment", "environment", "get", twoDotOhDeprecation("environment get"))
   186  	r.RegisterSuperAlias("get-env", "environment", "get", twoDotOhDeprecation("environment get"))
   187  	r.RegisterSuperAlias("set-environment", "environment", "set", twoDotOhDeprecation("environment set"))
   188  	r.RegisterSuperAlias("set-env", "environment", "set", twoDotOhDeprecation("environment set"))
   189  	r.RegisterSuperAlias("unset-environment", "environment", "unset", twoDotOhDeprecation("environment unset"))
   190  	r.RegisterSuperAlias("unset-env", "environment", "unset", twoDotOhDeprecation("environment unset"))
   191  	r.RegisterSuperAlias("ensure-availability", "environment", "ensure-availability", twoDotOhDeprecation("environment ensure-availability"))
   192  	r.RegisterSuperAlias("retry-provisioning", "environment", "retry-provisioning", twoDotOhDeprecation("environment retry-provisioning"))
   193  
   194  	// Manage and control actions.
   195  	if featureflag.Enabled(feature.Actions) {
   196  		r.Register(action.NewSuperCommand())
   197  	}
   198  
   199  	// Operation protection commands
   200  	r.Register(wrapEnvCommand(&block.BlockCommand{}))
   201  	r.Register(wrapEnvCommand(&block.UnblockCommand{}))
   202  
   203  	// Manage storage
   204  	if featureflag.Enabled(feature.Storage) {
   205  		r.Register(storage.NewSuperCommand())
   206  	}
   207  }
   208  
   209  // envCmdWrapper is a struct that wraps an environment command and lets us handle
   210  // errors returned from Init before they're returned to the main function.
   211  type envCmdWrapper struct {
   212  	cmd.Command
   213  	ctx *cmd.Context
   214  }
   215  
   216  func (w envCmdWrapper) Init(args []string) error {
   217  	err := w.Command.Init(args)
   218  	if environs.IsNoEnv(err) {
   219  		fmt.Fprintln(w.ctx.Stderr, "No juju environment configuration file exists.")
   220  		fmt.Fprintln(w.ctx.Stderr, err)
   221  		fmt.Fprintln(w.ctx.Stderr, "Please create a configuration by running:")
   222  		fmt.Fprintln(w.ctx.Stderr, "    juju init")
   223  		fmt.Fprintln(w.ctx.Stderr, "then edit the file to configure your juju environment.")
   224  		fmt.Fprintln(w.ctx.Stderr, "You can then re-run the command.")
   225  		return cmd.ErrSilent
   226  	}
   227  	return err
   228  }
   229  
   230  func main() {
   231  	Main(os.Args)
   232  }
   233  
   234  type versionDeprecation struct {
   235  	replacement string
   236  	deprecate   version.Number
   237  	obsolete    version.Number
   238  }
   239  
   240  // Deprecated implements cmd.DeprecationCheck.
   241  // If the current version is after the deprecate version number,
   242  // the command is deprecated and the replacement should be used.
   243  func (v *versionDeprecation) Deprecated() (bool, string) {
   244  	if version.Current.Number.Compare(v.deprecate) > 0 {
   245  		return true, v.replacement
   246  	}
   247  	return false, ""
   248  }
   249  
   250  // Obsolete implements cmd.DeprecationCheck.
   251  // If the current version is after the obsolete version number,
   252  // the command is obsolete and shouldn't be registered.
   253  func (v *versionDeprecation) Obsolete() bool {
   254  	return version.Current.Number.Compare(v.obsolete) > 0
   255  }
   256  
   257  func twoDotOhDeprecation(replacement string) cmd.DeprecationCheck {
   258  	return &versionDeprecation{
   259  		replacement: replacement,
   260  		deprecate:   version.MustParse("2.0-00"),
   261  		obsolete:    version.MustParse("3.0-00"),
   262  	}
   263  }