github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/cmd/juju/action/common.go (about) 1 // Copyright 2014-2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package action 5 6 import ( 7 "github.com/juju/errors" 8 "github.com/juju/loggo" 9 "github.com/juju/names" 10 11 "github.com/juju/juju/apiserver/params" 12 ) 13 14 var logger = loggo.GetLogger("juju.cmd.juju.action") 15 16 // getActionTagByPrefix uses the APIClient to get all ActionTags matching a prefix. 17 func getActionTagsByPrefix(api APIClient, prefix string) ([]names.ActionTag, error) { 18 results := []names.ActionTag{} 19 20 tags, err := api.FindActionTagsByPrefix(params.FindTags{Prefixes: []string{prefix}}) 21 if err != nil { 22 return results, err 23 } 24 25 matches, ok := tags.Matches[prefix] 26 if !ok || len(matches) < 1 { 27 return results, nil 28 } 29 30 results, rejects := getActionTags(matches) 31 if len(rejects) > 0 { 32 logger.Errorf("FindActionTagsByPrefix for prefix %q found invalid tags %v", prefix, rejects) 33 } 34 return results, nil 35 } 36 37 // getActionTagByPrefix uses the APIClient to get an ActionTag from a prefix. 38 func getActionTagByPrefix(api APIClient, prefix string) (names.ActionTag, error) { 39 tag := names.ActionTag{} 40 actiontags, err := getActionTagsByPrefix(api, prefix) 41 if err != nil { 42 return tag, err 43 } 44 45 if len(actiontags) < 1 { 46 return tag, errors.Errorf("actions for identifier %q not found", prefix) 47 } 48 49 if len(actiontags) > 1 { 50 return tag, errors.Errorf("identifier %q matched multiple actions %v", prefix, actiontags) 51 } 52 53 return actiontags[0], nil 54 } 55 56 // getActionTags converts a slice of params.Entity to a slice of names.ActionTag, and 57 // also populates a slice of strings for the params.Entity.Tag that are not a valid 58 // names.ActionTag. 59 func getActionTags(entities []params.Entity) (good []names.ActionTag, bad []string) { 60 for _, entity := range entities { 61 if tag, err := entityToActionTag(entity); err != nil { 62 bad = append(bad, entity.Tag) 63 } else { 64 good = append(good, tag) 65 } 66 } 67 return 68 } 69 70 // entityToActionTag converts the params.Entity type to a names.ActionTag 71 func entityToActionTag(entity params.Entity) (names.ActionTag, error) { 72 return names.ParseActionTag(entity.Tag) 73 } 74 75 // addValueToMap adds the given value to the map on which the method is run. 76 // This allows us to merge maps such as {foo: {bar: baz}} and {foo: {baz: faz}} 77 // into {foo: {bar: baz, baz: faz}}. 78 func addValueToMap(keys []string, value interface{}, target map[string]interface{}) { 79 next := target 80 81 for i := range keys { 82 // If we are on last key set or overwrite the val. 83 if i == len(keys)-1 { 84 next[keys[i]] = value 85 break 86 } 87 88 if iface, ok := next[keys[i]]; ok { 89 switch typed := iface.(type) { 90 case map[string]interface{}: 91 // If we already had a map inside, keep 92 // stepping through. 93 next = typed 94 default: 95 // If we didn't, then overwrite value 96 // with a map and iterate with that. 97 m := map[string]interface{}{} 98 next[keys[i]] = m 99 next = m 100 } 101 continue 102 } 103 104 // Otherwise, it wasn't present, so make it and step 105 // into. 106 m := map[string]interface{}{} 107 next[keys[i]] = m 108 next = m 109 } 110 }