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 }