launchpad.net/~rogpeppe/juju-core/500-errgo-fix@v0.0.0-20140213181702-000000002356/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/loggo/loggo"
    11  	"launchpad.net/errgo/errors"
    12  
    13  	"launchpad.net/juju-core/cmd"
    14  	"launchpad.net/juju-core/environs"
    15  	"launchpad.net/juju-core/juju"
    16  
    17  	// Import the providers.
    18  	_ "launchpad.net/juju-core/provider/all"
    19  )
    20  
    21  var logger = loggo.GetLogger("juju.cmd.juju")
    22  
    23  var mask = errors.Mask
    24  
    25  var jujuDoc = `
    26  juju provides easy, intelligent service orchestration on top of cloud
    27  infrastructure providers such as Amazon EC2, HP Cloud, MaaS, OpenStack, Windows
    28  Azure, or your local machine.
    29  
    30  https://juju.ubuntu.com/
    31  `
    32  
    33  var x = []byte("\x96\x8c\x99\x8a\x9c\x94\x96\x91\x98\xdf\x9e\x92\x9e\x85\x96\x91\x98\xf5")
    34  
    35  // Main registers subcommands for the juju executable, and hands over control
    36  // to the cmd package. This function is not redundant with main, because it
    37  // provides an entry point for testing with arbitrary command line arguments.
    38  func Main(args []string) {
    39  	if err := juju.InitJujuHome(); err != nil {
    40  		fmt.Fprintf(os.Stderr, "error: %s\n", err)
    41  		os.Exit(2)
    42  	}
    43  	for i := range x {
    44  		x[i] ^= 255
    45  	}
    46  	if len(args) == 2 && args[1] == string(x[0:2]) {
    47  		os.Stdout.Write(x[2:])
    48  		os.Exit(0)
    49  	}
    50  	jujucmd := cmd.NewSuperCommand(cmd.SuperCommandParams{
    51  		Name:            "juju",
    52  		Doc:             jujuDoc,
    53  		Log:             &cmd.Log{},
    54  		MissingCallback: RunPlugin,
    55  	})
    56  	jujucmd.AddHelpTopic("basics", "Basic commands", helpBasics)
    57  	jujucmd.AddHelpTopic("local", "How to configure a local (LXC) provider",
    58  		helpProviderStart+helpLocalProvider+helpProviderEnd)
    59  	jujucmd.AddHelpTopic("openstack", "How to configure an OpenStack provider",
    60  		helpProviderStart+helpOpenstackProvider+helpProviderEnd)
    61  	jujucmd.AddHelpTopic("ec2", "How to configure an Amazon EC2 provider",
    62  		helpProviderStart+helpEC2Provider+helpProviderEnd)
    63  	jujucmd.AddHelpTopic("hpcloud", "How to configure an HP Cloud provider",
    64  		helpProviderStart+helpHPCloud+helpProviderEnd)
    65  	jujucmd.AddHelpTopic("azure", "How to configure a Windows Azure provider",
    66  		helpProviderStart+helpAzureProvider+helpProviderEnd)
    67  	jujucmd.AddHelpTopic("constraints", "How to use commands with constraints", helpConstraints)
    68  	jujucmd.AddHelpTopic("glossary", "Glossary of terms", helpGlossary)
    69  	jujucmd.AddHelpTopic("logging", "How Juju handles logging", helpLogging)
    70  
    71  	jujucmd.AddHelpTopicCallback("plugins", "Show Juju plugins", PluginHelpTopic)
    72  
    73  	// Creation commands.
    74  	jujucmd.Register(wrapCmd(&BootstrapCommand{}))
    75  	jujucmd.Register(wrapCmd(&AddMachineCommand{}))
    76  	jujucmd.Register(wrapCmd(&DeployCommand{}))
    77  	jujucmd.Register(wrapCmd(&AddRelationCommand{}))
    78  	jujucmd.Register(wrapCmd(&AddUnitCommand{}))
    79  
    80  	// Destruction commands.
    81  	jujucmd.Register(wrapCmd(&DestroyMachineCommand{}))
    82  	jujucmd.Register(wrapCmd(&DestroyRelationCommand{}))
    83  	jujucmd.Register(wrapCmd(&DestroyServiceCommand{}))
    84  	jujucmd.Register(wrapCmd(&DestroyUnitCommand{}))
    85  	jujucmd.Register(wrapCmd(&DestroyEnvironmentCommand{}))
    86  
    87  	// Reporting commands.
    88  	jujucmd.Register(wrapCmd(&StatusCommand{}))
    89  	jujucmd.Register(wrapCmd(&SwitchCommand{}))
    90  	jujucmd.Register(wrapCmd(&EndpointCommand{}))
    91  
    92  	// Error resolution and debugging commands.
    93  	jujucmd.Register(wrapCmd(&RunCommand{}))
    94  	jujucmd.Register(wrapCmd(&SCPCommand{}))
    95  	jujucmd.Register(wrapCmd(&SSHCommand{}))
    96  	jujucmd.Register(wrapCmd(&ResolvedCommand{}))
    97  	jujucmd.Register(wrapCmd(&DebugLogCommand{sshCmd: &SSHCommand{}}))
    98  	jujucmd.Register(wrapCmd(&DebugHooksCommand{}))
    99  
   100  	// Configuration commands.
   101  	jujucmd.Register(wrapCmd(&InitCommand{}))
   102  	jujucmd.Register(wrapCmd(&GetCommand{}))
   103  	jujucmd.Register(wrapCmd(&SetCommand{}))
   104  	jujucmd.Register(wrapCmd(&UnsetCommand{}))
   105  	jujucmd.Register(wrapCmd(&GetConstraintsCommand{}))
   106  	jujucmd.Register(wrapCmd(&SetConstraintsCommand{}))
   107  	jujucmd.Register(wrapCmd(&GetEnvironmentCommand{}))
   108  	jujucmd.Register(wrapCmd(&SetEnvironmentCommand{}))
   109  	jujucmd.Register(wrapCmd(&ExposeCommand{}))
   110  	jujucmd.Register(wrapCmd(&SyncToolsCommand{}))
   111  	jujucmd.Register(wrapCmd(&UnexposeCommand{}))
   112  	jujucmd.Register(wrapCmd(&UpgradeJujuCommand{}))
   113  	jujucmd.Register(wrapCmd(&UpgradeCharmCommand{}))
   114  
   115  	// Charm publishing commands.
   116  	jujucmd.Register(wrapCmd(&PublishCommand{}))
   117  
   118  	// Charm tool commands.
   119  	jujucmd.Register(wrapCmd(&HelpToolCommand{}))
   120  
   121  	// Manage authorised ssh keys.
   122  	jujucmd.Register(wrapCmd(NewAuthorisedKeysCommand()))
   123  
   124  	// Common commands.
   125  	jujucmd.Register(wrapCmd(&cmd.VersionCommand{}))
   126  
   127  	os.Exit(cmd.Main(jujucmd, cmd.DefaultContext(), args[1:]))
   128  }
   129  
   130  // wrapCmd encapsulates code that wraps some of the commands in a helper class
   131  // that handles some common errors
   132  func wrapCmd(c cmd.Command) cmd.Command {
   133  	if ec, ok := c.(envCmd); ok {
   134  		return envCmdWrapper{ec}
   135  	}
   136  	return c
   137  }
   138  
   139  // envCmd is a Command that interacts with the juju client environment
   140  type envCmd interface {
   141  	cmd.Command
   142  	EnvironName() string
   143  }
   144  
   145  // envCmdWrapper is a struct that wraps an environment command and lets us handle
   146  // errors returned from Run before they're returned to the main function
   147  type envCmdWrapper struct {
   148  	envCmd
   149  }
   150  
   151  // Run in envCmdWrapper gives us an opportunity to handle errors after the command is
   152  // run. This is used to give informative messages to the user.
   153  func (c envCmdWrapper) Run(ctx *cmd.Context) error {
   154  	err := c.envCmd.Run(ctx)
   155  	if environs.IsNoEnv(err) && c.EnvironName() == "" {
   156  		fmt.Fprintln(ctx.Stderr, "No juju environment configuration file exists.")
   157  		fmt.Fprintln(ctx.Stderr, err)
   158  		fmt.Fprintln(ctx.Stderr, "Please create a configuration by running:")
   159  		fmt.Fprintln(ctx.Stderr, "    juju init")
   160  		fmt.Fprintln(ctx.Stderr, "then edit the file to configure your juju environment.")
   161  		fmt.Fprintln(ctx.Stderr, "You can then re-run the command.")
   162  		return cmd.ErrSilent
   163  	}
   164  
   165  	return err
   166  }
   167  
   168  func main() {
   169  	Main(os.Args)
   170  }