func (c *addModelCommand) getConfigValues(ctx *cmd.Context) (map[string]interface{}, error) { configValues, err := c.Config.ReadAttrs(ctx) if err != nil { return nil, errors.Annotate(err, "unable to parse config") } coercedValues, err := common.ConformYAML(configValues) if err != nil { return nil, errors.Annotatef(err, "unable to parse config") } attrs, ok := coercedValues.(map[string]interface{}) if !ok { return nil, errors.New("params must contain a YAML map with string keys") } if err := common.FinalizeAuthorizedKeys(ctx, attrs); err != nil { if errors.Cause(err) != common.ErrNoAuthorizedKeys { return nil, errors.Trace(err) } } return attrs, nil }
func (c *createModelCommand) getConfigValues(ctx *cmd.Context, serverSkeleton params.ModelConfig) (map[string]interface{}, error) { configValues := make(map[string]interface{}) for key, value := range serverSkeleton { configValues[key] = value } configAttr, err := c.Config.ReadAttrs(ctx) if err != nil { return nil, errors.Annotate(err, "unable to parse config") } for key, value := range configAttr { configValues[key] = value } configValues["name"] = c.Name coercedValues, err := common.ConformYAML(configValues) if err != nil { return nil, errors.Annotatef(err, "unable to parse config") } stringParams, ok := coercedValues.(map[string]interface{}) if !ok { return nil, errors.New("params must contain a YAML map with string keys") } return stringParams, nil }
func (c *doCommand) Run(ctx *cmd.Context) error { api, err := c.NewActionAPIClient() if err != nil { return err } defer api.Close() actionParams := map[string]interface{}{} if c.paramsYAML.Path != "" { b, err := c.paramsYAML.Read(ctx) if err != nil { return err } err = yaml.Unmarshal(b, &actionParams) if err != nil { return err } conformantParams, err := common.ConformYAML(actionParams) if err != nil { return err } betterParams, ok := conformantParams.(map[string]interface{}) if !ok { return errors.New("params must contain a YAML map with string keys") } actionParams = betterParams } // If we had explicit args {..., [key, key, key, key, value], ...} // then iterate and set params ..., key.key.key.key=value, ... for _, argSlice := range c.args { valueIndex := len(argSlice) - 1 keys := argSlice[:valueIndex] value := argSlice[valueIndex] cleansedValue := interface{}(value) if !c.parseStrings { err := yaml.Unmarshal([]byte(value), &cleansedValue) if err != nil { return err } } // Insert the value in the map. addValueToMap(keys, cleansedValue, actionParams) } conformantParams, err := common.ConformYAML(actionParams) if err != nil { return err } typedConformantParams, ok := conformantParams.(map[string]interface{}) if !ok { return errors.Errorf("params must be a map, got %T", typedConformantParams) } actionParam := params.Actions{ Actions: []params.Action{{ Receiver: c.unitTag.String(), Name: c.actionName, Parameters: actionParams, }}, } results, err := api.Enqueue(actionParam) if err != nil { return err } if len(results.Results) != 1 { return errors.New("illegal number of results returned") } result := results.Results[0] if result.Error != nil { return result.Error } if result.Action == nil { return errors.New("action failed to enqueue") } tag, err := names.ParseActionTag(result.Action.Tag) if err != nil { return err } output := map[string]string{"Action queued with id": tag.Id()} return c.out.Write(ctx, output) }
func (s *ConformSuite) TestConformYAML(c *gc.C) { var goodInterfaceTests = []struct { description string inputInterface interface{} expectedInterface map[string]interface{} expectedError string }{{ description: "An interface requiring no changes.", inputInterface: map[string]interface{}{ "key1": "value1", "key2": "value2", "key3": map[string]interface{}{ "foo1": "val1", "foo2": "val2"}}, expectedInterface: map[string]interface{}{ "key1": "value1", "key2": "value2", "key3": map[string]interface{}{ "foo1": "val1", "foo2": "val2"}}, }, { description: "Substitute a single inner map[i]i.", inputInterface: map[string]interface{}{ "key1": "value1", "key2": "value2", "key3": map[interface{}]interface{}{ "foo1": "val1", "foo2": "val2"}}, expectedInterface: map[string]interface{}{ "key1": "value1", "key2": "value2", "key3": map[string]interface{}{ "foo1": "val1", "foo2": "val2"}}, }, { description: "Substitute nested inner map[i]i.", inputInterface: map[string]interface{}{ "key1a": "val1a", "key2a": "val2a", "key3a": map[interface{}]interface{}{ "key1b": "val1b", "key2b": map[interface{}]interface{}{ "key1c": "val1c"}}}, expectedInterface: map[string]interface{}{ "key1a": "val1a", "key2a": "val2a", "key3a": map[string]interface{}{ "key1b": "val1b", "key2b": map[string]interface{}{ "key1c": "val1c"}}}, }, { description: "Substitute nested map[i]i within []i.", inputInterface: map[string]interface{}{ "key1a": "val1a", "key2a": []interface{}{5, "foo", map[string]interface{}{ "key1b": "val1b", "key2b": map[interface{}]interface{}{ "key1c": "val1c"}}}}, expectedInterface: map[string]interface{}{ "key1a": "val1a", "key2a": []interface{}{5, "foo", map[string]interface{}{ "key1b": "val1b", "key2b": map[string]interface{}{ "key1c": "val1c"}}}}, }, { description: "An inner map[interface{}]interface{} with an int key.", inputInterface: map[string]interface{}{ "key1": "value1", "key2": "value2", "key3": map[interface{}]interface{}{ "foo1": "val1", 5: "val2"}}, expectedError: "map keyed with non-string value", }, { description: "An inner []interface{} containing a map[i]i with an int key.", inputInterface: map[string]interface{}{ "key1a": "val1b", "key2a": "val2b", "key3a": []interface{}{"foo1", 5, map[interface{}]interface{}{ "key1b": "val1b", "key2b": map[interface{}]interface{}{ "key1c": "val1c", 5: "val2c"}}}}, expectedError: "map keyed with non-string value", }} for i, test := range goodInterfaceTests { c.Logf("test %d: %s", i, test.description) input := test.inputInterface cleansedInterfaceMap, err := common.ConformYAML(input) if test.expectedError == "" { if !c.Check(err, jc.ErrorIsNil) { continue } c.Check(cleansedInterfaceMap, gc.DeepEquals, test.expectedInterface) } else { c.Check(err, gc.ErrorMatches, test.expectedError) } } }