func (c attrsC) Coerce(v interface{}, path []string) (interface{}, error) { // TODO consider allowing only the map variant. switch reflect.TypeOf(v).Kind() { case reflect.String: s, err := schema.String().Coerce(v, path) if err != nil { return nil, errors.Mask(err) } result, err := keyvalues.Parse(strings.Fields(s.(string)), true) if err != nil { return nil, fmt.Errorf("%s%v", pathPrefix(path), err) } return result, nil case reflect.Slice: slice0, err := attrSliceChecker.Coerce(v, path) if err != nil { return nil, errors.Mask(err) } slice := slice0.([]interface{}) fields := make([]string, len(slice)) for i, f := range slice { fields[i] = f.(string) } result, err := keyvalues.Parse(fields, true) if err != nil { return nil, fmt.Errorf("%s%v", pathPrefix(path), err) } return result, nil case reflect.Map: imap0, err := attrMapChecker.Coerce(v, path) if err != nil { return nil, errors.Mask(err) } imap := imap0.(map[interface{}]interface{}) result := make(map[string]string) for k, v := range imap { result[k.(string)] = v.(string) } return result, nil default: return nil, errors.Errorf("%sunexpected type for value, got %T(%v)", pathPrefix(path), v, v) } }
func (s *EnvSuite) TestEnvSetsPath(c *gc.C) { paths := context.OSDependentEnvVars(MockEnvPaths{}) c.Assert(paths, gc.Not(gc.HasLen), 0) vars, err := keyvalues.Parse(paths, true) c.Assert(err, jc.ErrorIsNil) key := "PATH" if runtime.GOOS == "windows" { key = "Path" } c.Assert(vars[key], gc.Not(gc.Equals), "") }
func (keyValuesSuite) TestMapParsing(c *gc.C) { for i, t := range testCases { c.Log("test %d: %s", i, t.about) result, err := keyvalues.Parse(t.input, t.allowEmptyVal) c.Check(result, gc.DeepEquals, t.output) if t.error == "" { c.Check(err, gc.IsNil) } else { c.Check(err, gc.ErrorMatches, t.error) } } }
func (c *CreateCommand) Init(args []string) error { if len(args) == 0 { return errors.New("environment name is required") } c.Name, args = args[0], args[1:] values, err := keyvalues.Parse(args, true) if err != nil { return err } c.ConfValues = values return nil }
func (c *RelationSetCommand) Init(args []string) error { if c.RelationId == -1 { return errors.Errorf("no relation id specified") } // The overrides will be applied during Run when c.settingsFile is handled. overrides, err := keyvalues.Parse(args, true) if err != nil { return errors.Trace(err) } c.Settings = overrides return nil }
// Init parses the command's parameters. func (c *AddMetricCommand) Init(args []string) error { now := time.Now() if len(args) == 0 { return fmt.Errorf("no metrics specified") } options, err := keyvalues.Parse(args, false) if err != nil { return err } for key, value := range options { c.Metrics = append(c.Metrics, Metric{key, value, now}) } return nil }
func (c *SetCommand) Init(args []string) error { if len(args) == 0 || len(strings.Split(args[0], "=")) > 1 { return errors.New("no service name specified") } if c.SettingsYAML.Path != "" && len(args) > 1 { return errors.New("cannot specify --config when using key=value arguments") } c.ServiceName = args[0] settings, err := keyvalues.Parse(args[1:], true) if err != nil { return err } c.SettingsStrings = settings return nil }
func (s *ContextSuite) TestHookContextEnv(c *gc.C) { ctx := meterstatus.NewLimitedContext("u/0") paths := &dummyPaths{} vars, err := ctx.HookVars(paths) c.Assert(err, jc.ErrorIsNil) varMap, err := keyvalues.Parse(vars, true) c.Assert(err, jc.ErrorIsNil) c.Assert(varMap["JUJU_AGENT_SOCKET"], gc.Equals, "/dummy/jujuc.sock") c.Assert(varMap["JUJU_UNIT_NAME"], gc.Equals, "u/0") key := "PATH" if runtime.GOOS == "windows" { key = "Path" } c.Assert(varMap[key], gc.Not(gc.Equals), "") }
// Init implements part of the cmd.Command interface. func (c *configCommand) Init(args []string) error { if c.reset { // We're doing resetConfig. if len(args) == 0 { return errors.New("no keys specified") } for _, k := range args { if k == config.AgentVersionKey { return errors.Errorf("agent-version cannot be reset") } } c.keys = args c.action = c.resetConfig return nil } if len(args) > 0 && strings.Contains(args[0], "=") { // We're setting values. options, err := keyvalues.Parse(args, true) if err != nil { return errors.Trace(err) } c.values = make(attributes) for k, v := range options { if k == config.AgentVersionKey { return errors.Errorf(`agent-version must be set via "upgrade-juju"`) } c.values[k] = v } c.action = c.setConfig return nil } val, err := cmd.ZeroOrOneArgs(args) if err != nil { return errors.New("can only retrieve a single value, or all values") } // We're doing getConfig. if val != "" { c.keys = []string{val} } c.action = c.getConfig return nil }
func (c *CreateEnvironmentCommand) Init(args []string) error { if len(args) == 0 { return errors.New("environment name is required") } c.name, args = args[0], args[1:] values, err := keyvalues.Parse(args, true) if err != nil { return err } c.confValues = values if c.owner != "" && !names.IsValidUser(c.owner) { return errors.Errorf("%q is not a valid user", c.owner) } return nil }
// parseSet parses the command line args when --file is set or if the // positional args are key=value pairs. func (c *configCommand) parseSet(args []string, file bool) error { if file && len(args) > 0 { return errors.New("cannot specify --file and key=value arguments simultaneously") } c.action = c.setConfig if file { c.useFile = true return nil } settings, err := keyvalues.Parse(args, true) if err != nil { return err } c.values = settings return nil }
func (s *ContextSuite) TestHookContextSetEnv(c *gc.C) { ctx := meterstatus.NewLimitedContext("u/0") setVars := map[string]string{ "somekey": "somevalue", "anotherkey": "anothervalue", } ctx.SetEnvVars(setVars) paths := &dummyPaths{} vars, err := ctx.HookVars(paths) c.Assert(err, jc.ErrorIsNil) varMap, err := keyvalues.Parse(vars, true) c.Assert(err, jc.ErrorIsNil) for key, value := range setVars { c.Assert(varMap[key], gc.Equals, value) } c.Assert(varMap["JUJU_AGENT_SOCKET"], gc.Equals, "/dummy/jujuc.sock") c.Assert(varMap["JUJU_UNIT_NAME"], gc.Equals, "u/0") }
// wgetEnvironment creates a script to call wget with the // --no-check-certificate argument, patching the PATH to ensure // the script is invoked by the lxc template bash script. // It returns a slice of env variables to pass to the lxc create command. func wgetEnvironment(caCert []byte) (execEnv []string, closer func(), _ error) { env := os.Environ() kv, err := keyvalues.Parse(env, true) if err != nil { return nil, nil, errors.Trace(err) } // Create a wget bash script in a temporary directory. tmpDir, err := ioutil.TempDir("", "wget") if err != nil { return nil, nil, errors.Trace(err) } closer = func() { os.RemoveAll(tmpDir) } // Write the ca cert. caCertPath := filepath.Join(tmpDir, "ca-cert.pem") err = ioutil.WriteFile(caCertPath, caCert, 0755) if err != nil { defer closer() return nil, nil, errors.Trace(err) } // Write the wget script. Don't use a proxy when getting // the image as it's going through the state server. wgetTmpl := `#!/bin/bash /usr/bin/wget --no-proxy --ca-certificate=%s $* ` wget := fmt.Sprintf(wgetTmpl, caCertPath) err = writeWgetTmpFile(filepath.Join(tmpDir, "wget"), []byte(wget), 0755) if err != nil { defer closer() return nil, nil, errors.Trace(err) } // Update the path to point to the script. for k, v := range kv { if strings.ToUpper(k) == "PATH" { v = strings.Join([]string{tmpDir, v}, string(os.PathListSeparator)) } execEnv = append(execEnv, fmt.Sprintf("%s=%s", k, v)) } return execEnv, closer, nil }
func (c *setCommand) Init(args []string) (err error) { if len(args) == 0 { return fmt.Errorf("no key, value pairs specified") } options, err := keyvalues.Parse(args, true) if err != nil { return err } c.values = make(attributes) for key, value := range options { if key == "agent-version" { return fmt.Errorf("agent-version must be set via upgrade-juju") } c.values[key] = value } return nil }
// parseSetKeys iterates over the args and make sure that the key=value pairs // are valid. It also checks that the same key isn't also being reset. func (c *defaultsCommand) parseSetKeys(args []string) error { options, err := keyvalues.Parse(args, true) if err != nil { return errors.Trace(err) } c.values = make(attributes) for k, v := range options { if k == config.AgentVersionKey { return errors.Errorf(`%q must be set via "upgrade-juju"`, config.AgentVersionKey) } c.values[k] = v } for _, k := range c.resetKeys { if _, ok := c.values[k]; ok { return errors.Errorf( "key %q cannot be both set and unset in the same command", k) } } return nil }
// Init implements Command.Init. func (c *PoolCreateCommand) Init(args []string) (err error) { if len(args) < 3 { return errors.New("pool creation requires names, provider type and attrs for configuration") } c.poolName = args[0] c.provider = args[1] options, err := keyvalues.Parse(args[2:], false) if err != nil { return err } if len(options) == 0 { return errors.New("pool creation requires attrs for configuration") } c.attrs = make(map[string]interface{}) for key, value := range options { c.attrs[key] = value } return nil }
func (c *createModelCommand) Init(args []string) error { if len(args) == 0 { return errors.New("model name is required") } c.Name, args = args[0], args[1:] values, err := keyvalues.Parse(args, true) if err != nil { return err } c.ConfValues = values if c.Owner != "" && !names.IsValidUser(c.Owner) { return errors.Errorf("%q is not a valid user", c.Owner) } if c.configParser == nil { c.configParser = common.ConformYAML } return nil }
// Init is part of the cmd.Command interface. func (c *leaderSetCommand) Init(args []string) (err error) { c.settings, err = keyvalues.Parse(args, true) return }