func (s *configSuite) TestClientConfigNonLocal(c *gc.C) { cfg := lxd.NewBaseConfig(c) ecfg := lxd.NewConfig(cfg) ecfg = ecfg.Apply(c, map[string]interface{}{ "remote-url": "10.0.0.1", "client-cert": "<a valid x.509 cert>", "client-key": "<a valid x.509 key>", }) clientCfg, err := ecfg.ClientConfig() c.Assert(err, jc.ErrorIsNil) c.Check(clientCfg, jc.DeepEquals, lxdclient.Config{ Namespace: cfg.Name(), Dirname: lxdlib.ConfigPath("juju-testenv"), Remote: lxdclient.Remote{ Name: "juju-remote", Host: "10.0.0.1", Cert: &lxdclient.Cert{ Name: fmt.Sprintf("juju cert for env %q", s.config.Name()), CertPEM: []byte("<a valid x.509 cert>"), KeyPEM: []byte("<a valid x.509 key>"), }, }, }) }
// WithDefaults updates a copy of the config with default values // where needed. func (cfg Config) WithDefaults() (Config, error) { // We leave a blank namespace alone. // Also, note that cfg is a value receiver, so it is an implicit copy. if cfg.Dirname == "" { // TODO(ericsnow) Switch to filepath as soon as LXD does. dirname := path.Dir(lxd.ConfigPath("DUMMY")) cfg.Dirname = path.Clean(dirname) } var err error cfg.Remote, err = cfg.Remote.WithDefaults() if err != nil { return cfg, errors.Trace(err) } return cfg, nil }
func (s *configSuite) TestClientConfigLocal(c *gc.C) { cfg := lxd.NewBaseConfig(c) ecfg := lxd.NewConfig(cfg) values, _ := ecfg.Values(c) c.Assert(values.RemoteURL, gc.Equals, "") clientCfg, err := ecfg.ClientConfig() c.Assert(err, jc.ErrorIsNil) c.Check(clientCfg, jc.DeepEquals, lxdclient.Config{ Namespace: cfg.Name(), Dirname: lxdlib.ConfigPath("juju-testenv"), Remote: lxdclient.Remote{ Name: "juju-remote", Host: "", Cert: nil, }, }) }
func run() error { gettext.BindTextdomain("lxd", "", nil) gettext.Textdomain("lxd") verbose := gnuflag.Bool("verbose", false, gettext.Gettext("Enables verbose mode.")) debug := gnuflag.Bool("debug", false, gettext.Gettext("Enables debug mode.")) forceLocal := gnuflag.Bool("force-local", false, gettext.Gettext("Enables debug mode.")) gnuflag.StringVar(&lxd.ConfigDir, "config", lxd.ConfigDir, gettext.Gettext("Alternate config directory.")) if len(os.Args) >= 3 && os.Args[1] == "config" && os.Args[2] == "profile" { fmt.Fprintf(os.Stderr, "`lxc config profile` is deprecated, please use `lxc profile`\n") os.Args = append(os.Args[:1], os.Args[2:]...) } if len(os.Args) >= 2 && (os.Args[1] == "-h" || os.Args[1] == "--help") { os.Args[1] = "help" } if len(os.Args) >= 2 && (os.Args[1] == "--all") { os.Args[1] = "help" os.Args = append(os.Args, "--all") } if len(os.Args) == 2 && os.Args[1] == "--version" { os.Args[1] = "version" } if len(os.Args) < 2 { commands["help"].run(nil, nil) os.Exit(1) } name := os.Args[1] cmd, ok := commands[name] if !ok { fmt.Fprintf(os.Stderr, gettext.Gettext("error: unknown command: %s\n"), name) commands["help"].run(nil, nil) os.Exit(1) } cmd.flags() gnuflag.Usage = func() { fmt.Fprintf(os.Stderr, gettext.Gettext("Usage: %s\n\nOptions:\n\n"), strings.TrimSpace(cmd.usage())) gnuflag.PrintDefaults() } os.Args = os.Args[1:] gnuflag.Parse(true) shared.SetLogger("", "", *verbose, *debug) var config *lxd.Config var err error if *forceLocal { config = &lxd.DefaultConfig } else { config, err = lxd.LoadConfig() if err != nil { return err } } certf := lxd.ConfigPath("client.crt") keyf := lxd.ConfigPath("client.key") if !*forceLocal && os.Args[0] != "help" && os.Args[0] != "version" && (!shared.PathExists(certf) || !shared.PathExists(keyf)) { fmt.Fprintf(os.Stderr, gettext.Gettext("Generating a client certificate. This may take a minute...\n")) err = shared.FindOrGenCert(certf, keyf) if err != nil { return err } fmt.Fprintf(os.Stderr, gettext.Gettext("If this is your first run, you will need to import images using the 'lxd-images' script.\n")) fmt.Fprintf(os.Stderr, gettext.Gettext("For example: 'lxd-images import ubuntu --alias ubuntu'.\n")) } err = cmd.run(config, gnuflag.Args()) if err == errArgs { fmt.Fprintf(os.Stderr, gettext.Gettext("error: %v\n%s"), err, cmd.usage()) os.Exit(1) } return err }
func run() error { verbose := gnuflag.Bool("verbose", false, i18n.G("Enables verbose mode.")) debug := gnuflag.Bool("debug", false, i18n.G("Enables debug mode.")) forceLocal := gnuflag.Bool("force-local", false, i18n.G("Force using the local unix socket.")) configDir := os.Getenv("LXD_CONF") if configDir != "" { lxd.ConfigDir = configDir } if len(os.Args) >= 3 && os.Args[1] == "config" && os.Args[2] == "profile" { fmt.Fprintf(os.Stderr, i18n.G("`lxc config profile` is deprecated, please use `lxc profile`")+"\n") os.Args = append(os.Args[:1], os.Args[2:]...) } if len(os.Args) >= 2 && (os.Args[1] == "-h" || os.Args[1] == "--help") { os.Args[1] = "help" } if len(os.Args) >= 2 && (os.Args[1] == "--all") { os.Args[1] = "help" os.Args = append(os.Args, "--all") } if len(os.Args) == 2 && os.Args[1] == "--version" { os.Args[1] = "version" } if len(os.Args) < 2 { commands["help"].run(nil, nil) os.Exit(1) } var config *lxd.Config var err error if *forceLocal { config = &lxd.DefaultConfig } else { config, err = lxd.LoadConfig() if err != nil { return err } // One time migration from old config if config.DefaultRemote == "" { _, ok := config.Remotes["local"] if !ok { config.Remotes["local"] = lxd.LocalRemote } config.DefaultRemote = "local" lxd.SaveConfig(config) } } // This is quite impolite, but it seems gnuflag needs us to shift our // own exename out of the arguments before parsing them. However, this // is useful for execIfAlias, which wants to know exactly the command // line we received, and in some cases is called before this shift, and // in others after. So, let's save the original args. origArgs := os.Args name := os.Args[1] cmd, ok := commands[name] if !ok { execIfAliases(config, origArgs) fmt.Fprintf(os.Stderr, i18n.G("error: unknown command: %s")+"\n", name) commands["help"].run(nil, nil) os.Exit(1) } cmd.flags() gnuflag.Usage = func() { fmt.Fprintf(os.Stderr, i18n.G("Usage: %s")+"\n\n"+i18n.G("Options:")+"\n\n", strings.TrimSpace(cmd.usage())) gnuflag.PrintDefaults() } os.Args = os.Args[1:] gnuflag.Parse(true) shared.SetLogger("", "", *verbose, *debug, nil) certf := lxd.ConfigPath("client.crt") keyf := lxd.ConfigPath("client.key") if !*forceLocal && os.Args[0] != "help" && os.Args[0] != "version" && (!shared.PathExists(certf) || !shared.PathExists(keyf)) { fmt.Fprintf(os.Stderr, i18n.G("Generating a client certificate. This may take a minute...")+"\n") err = shared.FindOrGenCert(certf, keyf) if err != nil { return err } fmt.Fprintf(os.Stderr, i18n.G("If this is your first run, you will need to import images using the 'lxd-images' script.")+"\n") fmt.Fprintf(os.Stderr, i18n.G("For example: 'lxd-images import ubuntu --alias ubuntu'.")+"\n") } err = cmd.run(config, gnuflag.Args()) if err == errArgs { /* If we got an error about invalid arguments, let's try to * expand this as an alias */ execIfAliases(config, origArgs) fmt.Fprintf(os.Stderr, i18n.G("error: %v")+"\n%s\n", err, cmd.usage()) os.Exit(1) } return err }
func (c *remoteCmd) run(config *lxd.Config, args []string) error { if len(args) < 1 { return errArgs } switch args[0] { case "add": if len(args) < 3 { return errArgs } if rc, ok := config.Remotes[args[1]]; ok { return fmt.Errorf(i18n.G("remote %s exists as <%s>"), args[1], rc.Addr) } err := addServer(config, args[1], args[2], c.acceptCert, c.password, c.public) if err != nil { delete(config.Remotes, args[1]) removeCertificate(args[1]) return err } case "remove": if len(args) != 2 { return errArgs } if _, ok := config.Remotes[args[1]]; !ok { return fmt.Errorf(i18n.G("remote %s doesn't exist"), args[1]) } if config.DefaultRemote == args[1] { return fmt.Errorf(i18n.G("can't remove the default remote")) } delete(config.Remotes, args[1]) removeCertificate(args[1]) case "list": data := [][]string{} for name, rc := range config.Remotes { if rc.Public { data = append(data, []string{name, rc.Addr, i18n.G("YES")}) } else { data = append(data, []string{name, rc.Addr, i18n.G("NO")}) } } table := tablewriter.NewWriter(os.Stdout) table.SetHeader([]string{ i18n.G("NAME"), i18n.G("URL"), i18n.G("PUBLIC")}) sort.Sort(ByName(data)) table.AppendBulk(data) table.Render() return nil case "rename": if len(args) != 3 { return errArgs } rc, ok := config.Remotes[args[1]] if !ok { return fmt.Errorf(i18n.G("remote %s doesn't exist"), args[1]) } if _, ok := config.Remotes[args[2]]; ok { return fmt.Errorf(i18n.G("remote %s already exists"), args[2]) } // Rename the certificate file oldPath := filepath.Join(lxd.ConfigPath("servercerts"), fmt.Sprintf("%s.crt", args[1])) newPath := filepath.Join(lxd.ConfigPath("servercerts"), fmt.Sprintf("%s.crt", args[2])) if shared.PathExists(oldPath) { err := os.Rename(oldPath, newPath) if err != nil { return err } } config.Remotes[args[2]] = rc delete(config.Remotes, args[1]) if config.DefaultRemote == args[1] { config.DefaultRemote = args[2] } case "set-url": if len(args) != 3 { return errArgs } _, ok := config.Remotes[args[1]] if !ok { return fmt.Errorf(i18n.G("remote %s doesn't exist"), args[1]) } config.Remotes[args[1]] = lxd.RemoteConfig{Addr: args[2]} case "set-default": if len(args) != 2 { return errArgs } _, ok := config.Remotes[args[1]] if !ok { return fmt.Errorf(i18n.G("remote %s doesn't exist"), args[1]) } config.DefaultRemote = args[1] case "get-default": if len(args) != 1 { return errArgs } fmt.Println(config.DefaultRemote) return nil default: return errArgs } return lxd.SaveConfig(config) }
// ConfigPath returns the full path to Juju LXC config directory. // This is here so we do not have to import lxc/lxd into the provider. func ConfigPath(namespace string) string { return lxd.ConfigPath(namespace) }
// ConfigPath returns the full path to Juju LXC config directory. // This is here so we do not have to import lxc/lxd into the provider. func ConfigPath(namespace string) string { // Here we use the same path as lxc for convention, but we could use // any juju specific path. return lxd.ConfigPath(namespace) }