github.com/sl1pm4t/consul@v1.4.5-0.20190325224627-74c31c540f9c/command/acl/policy/update/policy_update.go (about) 1 package policyupdate 2 3 import ( 4 "flag" 5 "fmt" 6 "io" 7 8 "github.com/hashicorp/consul/api" 9 "github.com/hashicorp/consul/command/acl" 10 "github.com/hashicorp/consul/command/flags" 11 "github.com/hashicorp/consul/command/helpers" 12 "github.com/mitchellh/cli" 13 ) 14 15 func New(ui cli.Ui) *cmd { 16 c := &cmd{UI: ui} 17 c.init() 18 return c 19 } 20 21 type cmd struct { 22 UI cli.Ui 23 flags *flag.FlagSet 24 http *flags.HTTPFlags 25 help string 26 27 policyID string 28 nameSet bool 29 name string 30 descriptionSet bool 31 description string 32 datacenters []string 33 rulesSet bool 34 rules string 35 noMerge bool 36 showMeta bool 37 testStdin io.Reader 38 } 39 40 func (c *cmd) init() { 41 c.flags = flag.NewFlagSet("", flag.ContinueOnError) 42 c.flags.BoolVar(&c.showMeta, "meta", false, "Indicates that policy metadata such "+ 43 "as the content hash and raft indices should be shown for each entry") 44 c.flags.StringVar(&c.policyID, "id", "", "The ID of the policy to update. "+ 45 "It may be specified as a unique ID prefix but will error if the prefix "+ 46 "matches multiple policy IDs") 47 c.flags.StringVar(&c.name, "name", "", "The policies name.") 48 c.flags.StringVar(&c.description, "description", "", "A description of the policy") 49 c.flags.Var((*flags.AppendSliceValue)(&c.datacenters), "valid-datacenter", "Datacenter "+ 50 "that the policy should be valid within. This flag may be specified multiple times") 51 c.flags.StringVar(&c.rules, "rules", "", "The policy rules. May be prefixed with '@' "+ 52 "to indicate that the value is a file path to load the rules from. '-' may also be "+ 53 "given to indicate that the rules are available on stdin") 54 c.flags.BoolVar(&c.noMerge, "no-merge", false, "Do not merge the current policy "+ 55 "information with what is provided to the command. Instead overwrite all fields "+ 56 "with the exception of the policy ID which is immutable.") 57 c.http = &flags.HTTPFlags{} 58 flags.Merge(c.flags, c.http.ClientFlags()) 59 flags.Merge(c.flags, c.http.ServerFlags()) 60 c.help = flags.Usage(help, c.flags) 61 } 62 63 func (c *cmd) checkSet(f *flag.Flag) { 64 switch f.Name { 65 case "name": 66 c.nameSet = true 67 case "description": 68 c.descriptionSet = true 69 case "rules": 70 c.rulesSet = true 71 } 72 } 73 74 func (c *cmd) Run(args []string) int { 75 if err := c.flags.Parse(args); err != nil { 76 return 1 77 } 78 79 c.flags.Visit(c.checkSet) 80 81 if c.policyID == "" && c.name == "" { 82 c.UI.Error(fmt.Sprintf("Must specify either the -id or -name parameters")) 83 return 1 84 } 85 86 client, err := c.http.APIClient() 87 if err != nil { 88 c.UI.Error(fmt.Sprintf("Error connecting to Consul agent: %s", err)) 89 return 1 90 } 91 92 var policyID string 93 if c.policyID != "" { 94 policyID, err = acl.GetPolicyIDFromPartial(client, c.policyID) 95 } else { 96 policyID, err = acl.GetPolicyIDByName(client, c.name) 97 } 98 if err != nil { 99 c.UI.Error(fmt.Sprintf("Error determining policy ID: %v", err)) 100 return 1 101 } 102 103 rules, err := helpers.LoadDataSource(c.rules, c.testStdin) 104 105 var updated *api.ACLPolicy 106 if c.noMerge { 107 updated = &api.ACLPolicy{ 108 ID: policyID, 109 Name: c.name, 110 Description: c.description, 111 Datacenters: c.datacenters, 112 Rules: rules, 113 } 114 } else { 115 policy, _, err := client.ACL().PolicyRead(policyID, nil) 116 if err != nil { 117 c.UI.Error(fmt.Sprintf("Error reading policy %q: %v", policyID, err)) 118 return 1 119 } 120 121 updated = &api.ACLPolicy{ 122 ID: policyID, 123 Name: policy.Name, 124 Description: policy.Description, 125 Datacenters: policy.Datacenters, 126 Rules: policy.Rules, 127 } 128 129 if c.nameSet { 130 updated.Name = c.name 131 } 132 if c.descriptionSet { 133 updated.Description = c.description 134 } 135 if c.rulesSet { 136 updated.Rules = rules 137 } 138 if c.datacenters != nil { 139 updated.Datacenters = c.datacenters 140 } 141 } 142 143 policy, _, err := client.ACL().PolicyUpdate(updated, nil) 144 if err != nil { 145 c.UI.Error(fmt.Sprintf("Error updating policy %q: %v", policyID, err)) 146 return 1 147 } 148 149 c.UI.Info(fmt.Sprintf("Policy updated successfully")) 150 acl.PrintPolicy(policy, c.UI, c.showMeta) 151 return 0 152 } 153 154 func (c *cmd) Synopsis() string { 155 return synopsis 156 } 157 158 func (c *cmd) Help() string { 159 return flags.Usage(c.help, nil) 160 } 161 162 const synopsis = "Update an ACL Policy" 163 const help = ` 164 Usage: consul acl policy update [options] 165 166 Updates a policy. By default it will merge the policy information with its 167 current state so that you do not have to provide all parameters. This 168 behavior can be disabled by passing -no-merge. 169 170 Rename the Policy: 171 172 $ consul acl policy update -id abcd -name "better-name" 173 174 Override all policy attributes: 175 176 # this will remove any datacenter scope if provided and will remove 177 # the description 178 $consul acl policy update -id abcd -name "better-name" -rules @rules.hcl 179 `