1package command
2
3import (
4	"fmt"
5	"strings"
6
7	"github.com/hashicorp/nomad/api"
8	"github.com/posener/complete"
9)
10
11type ACLBootstrapCommand struct {
12	Meta
13}
14
15func (c *ACLBootstrapCommand) Help() string {
16	helpText := `
17Usage: nomad acl bootstrap [options]
18
19  Bootstrap is used to bootstrap the ACL system and get an initial token.
20
21General Options:
22
23  ` + generalOptionsUsage() + `
24
25`
26	return strings.TrimSpace(helpText)
27}
28
29func (c *ACLBootstrapCommand) AutocompleteFlags() complete.Flags {
30	return mergeAutocompleteFlags(c.Meta.AutocompleteFlags(FlagSetClient),
31		complete.Flags{})
32}
33
34func (c *ACLBootstrapCommand) AutocompleteArgs() complete.Predictor {
35	return complete.PredictNothing
36}
37
38func (c *ACLBootstrapCommand) Synopsis() string {
39	return "Bootstrap the ACL system for initial token"
40}
41
42func (c *ACLBootstrapCommand) Name() string { return "acl bootstrap" }
43
44func (c *ACLBootstrapCommand) Run(args []string) int {
45	flags := c.Meta.FlagSet(c.Name(), FlagSetClient)
46	flags.Usage = func() { c.Ui.Output(c.Help()) }
47	if err := flags.Parse(args); err != nil {
48		return 1
49	}
50
51	// Check that we got no arguments
52	args = flags.Args()
53	if l := len(args); l != 0 {
54		c.Ui.Error("This command takes no arguments")
55		c.Ui.Error(commandErrorText(c))
56		return 1
57	}
58
59	// Get the HTTP client
60	client, err := c.Meta.Client()
61	if err != nil {
62		c.Ui.Error(fmt.Sprintf("Error initializing client: %s", err))
63		return 1
64	}
65
66	// Get the bootstrap token
67	token, _, err := client.ACLTokens().Bootstrap(nil)
68	if err != nil {
69		c.Ui.Error(fmt.Sprintf("Error bootstrapping: %s", err))
70		return 1
71	}
72
73	// Format the output
74	c.Ui.Output(formatKVACLToken(token))
75	return 0
76}
77
78// formatKVPolicy returns a K/V formatted policy
79func formatKVPolicy(policy *api.ACLPolicy) string {
80	output := []string{
81		fmt.Sprintf("Name|%s", policy.Name),
82		fmt.Sprintf("Description|%s", policy.Description),
83		fmt.Sprintf("Rules|%s", policy.Rules),
84		fmt.Sprintf("CreateIndex|%v", policy.CreateIndex),
85		fmt.Sprintf("ModifyIndex|%v", policy.ModifyIndex),
86	}
87	return formatKV(output)
88}
89
90// formatKVACLToken returns a K/V formatted ACL token
91func formatKVACLToken(token *api.ACLToken) string {
92	// Add the fixed preamble
93	output := []string{
94		fmt.Sprintf("Accessor ID|%s", token.AccessorID),
95		fmt.Sprintf("Secret ID|%s", token.SecretID),
96		fmt.Sprintf("Name|%s", token.Name),
97		fmt.Sprintf("Type|%s", token.Type),
98		fmt.Sprintf("Global|%v", token.Global),
99	}
100
101	// Special case the policy output
102	if token.Type == "management" {
103		output = append(output, "Policies|n/a")
104	} else {
105		output = append(output, fmt.Sprintf("Policies|%v", token.Policies))
106	}
107
108	// Add the generic output
109	output = append(output,
110		fmt.Sprintf("Create Time|%v", token.CreateTime),
111		fmt.Sprintf("Create Index|%d", token.CreateIndex),
112		fmt.Sprintf("Modify Index|%d", token.ModifyIndex),
113	)
114	return formatKV(output)
115}
116