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