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  `