1package command
2
3import (
4	"fmt"
5	"os"
6
7	"github.com/hashicorp/nomad/command/agent"
8	"github.com/hashicorp/nomad/version"
9	colorable "github.com/mattn/go-colorable"
10	"github.com/mitchellh/cli"
11)
12
13const (
14	// EnvNomadCLINoColor is an env var that toggles colored UI output.
15	EnvNomadCLINoColor = `NOMAD_CLI_NO_COLOR`
16)
17
18// DeprecatedCommand is a command that wraps an existing command and prints a
19// deprecation notice and points the user to the new command. Deprecated
20// commands are always hidden from help output.
21type DeprecatedCommand struct {
22	cli.Command
23	Meta
24
25	// Old is the old command name, New is the new command name.
26	Old, New string
27}
28
29// Help wraps the embedded Help command and prints a warning about deprecations.
30func (c *DeprecatedCommand) Help() string {
31	c.warn()
32	return c.Command.Help()
33}
34
35// Run wraps the embedded Run command and prints a warning about deprecation.
36func (c *DeprecatedCommand) Run(args []string) int {
37	c.warn()
38	return c.Command.Run(args)
39}
40
41func (c *DeprecatedCommand) warn() {
42	c.Ui.Warn(wrapAtLength(fmt.Sprintf(
43		"WARNING! The \"nomad %s\" command is deprecated. Please use \"nomad %s\" "+
44			"instead. This command will be removed in Nomad 0.10 (or later).",
45		c.Old,
46		c.New)))
47	c.Ui.Warn("")
48}
49
50// NamedCommand is a interface to denote a commmand's name.
51type NamedCommand interface {
52	Name() string
53}
54
55// Commands returns the mapping of CLI commands for Nomad. The meta
56// parameter lets you set meta options for all commands.
57func Commands(metaPtr *Meta, agentUi cli.Ui) map[string]cli.CommandFactory {
58	if metaPtr == nil {
59		metaPtr = new(Meta)
60	}
61
62	meta := *metaPtr
63	if meta.Ui == nil {
64		meta.Ui = &cli.BasicUi{
65			Reader:      os.Stdin,
66			Writer:      colorable.NewColorableStdout(),
67			ErrorWriter: colorable.NewColorableStderr(),
68		}
69	}
70
71	all := map[string]cli.CommandFactory{
72		"acl": func() (cli.Command, error) {
73			return &ACLCommand{
74				Meta: meta,
75			}, nil
76		},
77		"acl bootstrap": func() (cli.Command, error) {
78			return &ACLBootstrapCommand{
79				Meta: meta,
80			}, nil
81		},
82		"acl policy": func() (cli.Command, error) {
83			return &ACLPolicyCommand{
84				Meta: meta,
85			}, nil
86		},
87		"acl policy apply": func() (cli.Command, error) {
88			return &ACLPolicyApplyCommand{
89				Meta: meta,
90			}, nil
91		},
92		"acl policy delete": func() (cli.Command, error) {
93			return &ACLPolicyDeleteCommand{
94				Meta: meta,
95			}, nil
96		},
97		"acl policy info": func() (cli.Command, error) {
98			return &ACLPolicyInfoCommand{
99				Meta: meta,
100			}, nil
101		},
102		"acl policy list": func() (cli.Command, error) {
103			return &ACLPolicyListCommand{
104				Meta: meta,
105			}, nil
106		},
107		"acl token": func() (cli.Command, error) {
108			return &ACLTokenCommand{
109				Meta: meta,
110			}, nil
111		},
112		"acl token create": func() (cli.Command, error) {
113			return &ACLTokenCreateCommand{
114				Meta: meta,
115			}, nil
116		},
117		"acl token update": func() (cli.Command, error) {
118			return &ACLTokenUpdateCommand{
119				Meta: meta,
120			}, nil
121		},
122		"acl token delete": func() (cli.Command, error) {
123			return &ACLTokenDeleteCommand{
124				Meta: meta,
125			}, nil
126		},
127		"acl token info": func() (cli.Command, error) {
128			return &ACLTokenInfoCommand{
129				Meta: meta,
130			}, nil
131		},
132		"acl token list": func() (cli.Command, error) {
133			return &ACLTokenListCommand{
134				Meta: meta,
135			}, nil
136		},
137		"acl token self": func() (cli.Command, error) {
138			return &ACLTokenSelfCommand{
139				Meta: meta,
140			}, nil
141		},
142		"alloc": func() (cli.Command, error) {
143			return &AllocCommand{
144				Meta: meta,
145			}, nil
146		},
147		"alloc exec": func() (cli.Command, error) {
148			return &AllocExecCommand{
149				Meta: meta,
150			}, nil
151		},
152		"alloc signal": func() (cli.Command, error) {
153			return &AllocSignalCommand{
154				Meta: meta,
155			}, nil
156		},
157		"alloc stop": func() (cli.Command, error) {
158			return &AllocStopCommand{
159				Meta: meta,
160			}, nil
161		},
162		"alloc fs": func() (cli.Command, error) {
163			return &AllocFSCommand{
164				Meta: meta,
165			}, nil
166		},
167		"alloc logs": func() (cli.Command, error) {
168			return &AllocLogsCommand{
169				Meta: meta,
170			}, nil
171		},
172		"alloc restart": func() (cli.Command, error) {
173			return &AllocRestartCommand{
174				Meta: meta,
175			}, nil
176		},
177		"alloc status": func() (cli.Command, error) {
178			return &AllocStatusCommand{
179				Meta: meta,
180			}, nil
181		},
182		"alloc-status": func() (cli.Command, error) {
183			return &AllocStatusCommand{
184				Meta: meta,
185			}, nil
186		},
187		"agent": func() (cli.Command, error) {
188			return &agent.Command{
189				Version:    version.GetVersion(),
190				Ui:         agentUi,
191				ShutdownCh: make(chan struct{}),
192			}, nil
193		},
194		"agent-info": func() (cli.Command, error) {
195			return &AgentInfoCommand{
196				Meta: meta,
197			}, nil
198		},
199		"check": func() (cli.Command, error) {
200			return &AgentCheckCommand{
201				Meta: meta,
202			}, nil
203		},
204		"deployment": func() (cli.Command, error) {
205			return &DeploymentCommand{
206				Meta: meta,
207			}, nil
208		},
209		"deployment fail": func() (cli.Command, error) {
210			return &DeploymentFailCommand{
211				Meta: meta,
212			}, nil
213		},
214		"deployment list": func() (cli.Command, error) {
215			return &DeploymentListCommand{
216				Meta: meta,
217			}, nil
218		},
219		"deployment pause": func() (cli.Command, error) {
220			return &DeploymentPauseCommand{
221				Meta: meta,
222			}, nil
223		},
224		"deployment promote": func() (cli.Command, error) {
225			return &DeploymentPromoteCommand{
226				Meta: meta,
227			}, nil
228		},
229		"deployment resume": func() (cli.Command, error) {
230			return &DeploymentResumeCommand{
231				Meta: meta,
232			}, nil
233		},
234		"deployment status": func() (cli.Command, error) {
235			return &DeploymentStatusCommand{
236				Meta: meta,
237			}, nil
238		},
239		"eval": func() (cli.Command, error) {
240			return &EvalCommand{
241				Meta: meta,
242			}, nil
243		},
244		"eval status": func() (cli.Command, error) {
245			return &EvalStatusCommand{
246				Meta: meta,
247			}, nil
248		},
249		"eval-status": func() (cli.Command, error) {
250			return &EvalStatusCommand{
251				Meta: meta,
252			}, nil
253		},
254		"exec": func() (cli.Command, error) {
255			return &AllocExecCommand{
256				Meta: meta,
257			}, nil
258		},
259		"fs": func() (cli.Command, error) {
260			return &AllocFSCommand{
261				Meta: meta,
262			}, nil
263		},
264		"init": func() (cli.Command, error) {
265			return &JobInitCommand{
266				Meta: meta,
267			}, nil
268		},
269		"inspect": func() (cli.Command, error) {
270			return &JobInspectCommand{
271				Meta: meta,
272			}, nil
273		},
274		"keygen": func() (cli.Command, error) {
275			return &OperatorKeygenCommand{
276				Meta: meta,
277			}, nil
278		},
279		"keyring": func() (cli.Command, error) {
280			return &OperatorKeyringCommand{
281				Meta: meta,
282			}, nil
283		},
284		"job": func() (cli.Command, error) {
285			return &JobCommand{
286				Meta: meta,
287			}, nil
288		},
289		"job deployments": func() (cli.Command, error) {
290			return &JobDeploymentsCommand{
291				Meta: meta,
292			}, nil
293		},
294		"job dispatch": func() (cli.Command, error) {
295			return &JobDispatchCommand{
296				Meta: meta,
297			}, nil
298		},
299		"job eval": func() (cli.Command, error) {
300			return &JobEvalCommand{
301				Meta: meta,
302			}, nil
303		},
304		"job history": func() (cli.Command, error) {
305			return &JobHistoryCommand{
306				Meta: meta,
307			}, nil
308		},
309		"job init": func() (cli.Command, error) {
310			return &JobInitCommand{
311				Meta: meta,
312			}, nil
313		},
314		"job inspect": func() (cli.Command, error) {
315			return &JobInspectCommand{
316				Meta: meta,
317			}, nil
318		},
319		"job periodic": func() (cli.Command, error) {
320			return &JobPeriodicCommand{
321				Meta: meta,
322			}, nil
323		},
324		"job periodic force": func() (cli.Command, error) {
325			return &JobPeriodicForceCommand{
326				Meta: meta,
327			}, nil
328		},
329		"job plan": func() (cli.Command, error) {
330			return &JobPlanCommand{
331				Meta: meta,
332			}, nil
333		},
334		"job promote": func() (cli.Command, error) {
335			return &JobPromoteCommand{
336				Meta: meta,
337			}, nil
338		},
339		"job revert": func() (cli.Command, error) {
340			return &JobRevertCommand{
341				Meta: meta,
342			}, nil
343		},
344		"job run": func() (cli.Command, error) {
345			return &JobRunCommand{
346				Meta: meta,
347			}, nil
348		},
349		"job status": func() (cli.Command, error) {
350			return &JobStatusCommand{
351				Meta: meta,
352			}, nil
353		},
354		"job stop": func() (cli.Command, error) {
355			return &JobStopCommand{
356				Meta: meta,
357			}, nil
358		},
359		"job validate": func() (cli.Command, error) {
360			return &JobValidateCommand{
361				Meta: meta,
362			}, nil
363		},
364		"logs": func() (cli.Command, error) {
365			return &AllocLogsCommand{
366				Meta: meta,
367			}, nil
368		},
369		"monitor": func() (cli.Command, error) {
370			return &MonitorCommand{
371				Meta: meta,
372			}, nil
373		},
374		"namespace": func() (cli.Command, error) {
375			return &NamespaceCommand{
376				Meta: meta,
377			}, nil
378		},
379		"namespace apply": func() (cli.Command, error) {
380			return &NamespaceApplyCommand{
381				Meta: meta,
382			}, nil
383		},
384		"namespace delete": func() (cli.Command, error) {
385			return &NamespaceDeleteCommand{
386				Meta: meta,
387			}, nil
388		},
389		"namespace inspect": func() (cli.Command, error) {
390			return &NamespaceInspectCommand{
391				Meta: meta,
392			}, nil
393		},
394		"namespace list": func() (cli.Command, error) {
395			return &NamespaceListCommand{
396				Meta: meta,
397			}, nil
398		},
399		"namespace status": func() (cli.Command, error) {
400			return &NamespaceStatusCommand{
401				Meta: meta,
402			}, nil
403		},
404		"node": func() (cli.Command, error) {
405			return &NodeCommand{
406				Meta: meta,
407			}, nil
408		},
409		"node config": func() (cli.Command, error) {
410			return &NodeConfigCommand{
411				Meta: meta,
412			}, nil
413		},
414		"node-drain": func() (cli.Command, error) {
415			return &NodeDrainCommand{
416				Meta: meta,
417			}, nil
418		},
419		"node drain": func() (cli.Command, error) {
420			return &NodeDrainCommand{
421				Meta: meta,
422			}, nil
423		},
424		"node eligibility": func() (cli.Command, error) {
425			return &NodeEligibilityCommand{
426				Meta: meta,
427			}, nil
428		},
429		"node-status": func() (cli.Command, error) {
430			return &NodeStatusCommand{
431				Meta: meta,
432			}, nil
433		},
434		"node status": func() (cli.Command, error) {
435			return &NodeStatusCommand{
436				Meta: meta,
437			}, nil
438		},
439		"operator": func() (cli.Command, error) {
440			return &OperatorCommand{
441				Meta: meta,
442			}, nil
443		},
444
445		"operator autopilot": func() (cli.Command, error) {
446			return &OperatorAutopilotCommand{
447				Meta: meta,
448			}, nil
449		},
450
451		"operator autopilot get-config": func() (cli.Command, error) {
452			return &OperatorAutopilotGetCommand{
453				Meta: meta,
454			}, nil
455		},
456
457		"operator autopilot set-config": func() (cli.Command, error) {
458			return &OperatorAutopilotSetCommand{
459				Meta: meta,
460			}, nil
461		},
462		"operator keygen": func() (cli.Command, error) {
463			return &OperatorKeygenCommand{
464				Meta: meta,
465			}, nil
466		},
467		"operator keyring": func() (cli.Command, error) {
468			return &OperatorKeyringCommand{
469				Meta: meta,
470			}, nil
471		},
472		"operator raft": func() (cli.Command, error) {
473			return &OperatorRaftCommand{
474				Meta: meta,
475			}, nil
476		},
477
478		"operator raft list-peers": func() (cli.Command, error) {
479			return &OperatorRaftListCommand{
480				Meta: meta,
481			}, nil
482		},
483
484		"operator raft remove-peer": func() (cli.Command, error) {
485			return &OperatorRaftRemoveCommand{
486				Meta: meta,
487			}, nil
488		},
489
490		"plan": func() (cli.Command, error) {
491			return &JobPlanCommand{
492				Meta: meta,
493			}, nil
494		},
495
496		"quota": func() (cli.Command, error) {
497			return &QuotaCommand{
498				Meta: meta,
499			}, nil
500		},
501
502		"quota apply": func() (cli.Command, error) {
503			return &QuotaApplyCommand{
504				Meta: meta,
505			}, nil
506		},
507
508		"quota delete": func() (cli.Command, error) {
509			return &QuotaDeleteCommand{
510				Meta: meta,
511			}, nil
512		},
513
514		"quota init": func() (cli.Command, error) {
515			return &QuotaInitCommand{
516				Meta: meta,
517			}, nil
518		},
519
520		"quota inspect": func() (cli.Command, error) {
521			return &QuotaInspectCommand{
522				Meta: meta,
523			}, nil
524		},
525
526		"quota list": func() (cli.Command, error) {
527			return &QuotaListCommand{
528				Meta: meta,
529			}, nil
530		},
531
532		"quota status": func() (cli.Command, error) {
533			return &QuotaStatusCommand{
534				Meta: meta,
535			}, nil
536		},
537
538		"run": func() (cli.Command, error) {
539			return &JobRunCommand{
540				Meta: meta,
541			}, nil
542		},
543		"sentinel": func() (cli.Command, error) {
544			return &SentinelCommand{
545				Meta: meta,
546			}, nil
547		},
548		"sentinel list": func() (cli.Command, error) {
549			return &SentinelListCommand{
550				Meta: meta,
551			}, nil
552		},
553		"sentinel apply": func() (cli.Command, error) {
554			return &SentinelApplyCommand{
555				Meta: meta,
556			}, nil
557		},
558		"sentinel delete": func() (cli.Command, error) {
559			return &SentinelDeleteCommand{
560				Meta: meta,
561			}, nil
562		},
563		"sentinel read": func() (cli.Command, error) {
564			return &SentinelReadCommand{
565				Meta: meta,
566			}, nil
567		},
568		"server": func() (cli.Command, error) {
569			return &ServerCommand{
570				Meta: meta,
571			}, nil
572		},
573		"server force-leave": func() (cli.Command, error) {
574			return &ServerForceLeaveCommand{
575				Meta: meta,
576			}, nil
577		},
578		"server join": func() (cli.Command, error) {
579			return &ServerJoinCommand{
580				Meta: meta,
581			}, nil
582		},
583		"server members": func() (cli.Command, error) {
584			return &ServerMembersCommand{
585				Meta: meta,
586			}, nil
587		},
588		"server-force-leave": func() (cli.Command, error) {
589			return &ServerForceLeaveCommand{
590				Meta: meta,
591			}, nil
592		},
593		"server-join": func() (cli.Command, error) {
594			return &ServerJoinCommand{
595				Meta: meta,
596			}, nil
597		},
598		"server-members": func() (cli.Command, error) {
599			return &ServerMembersCommand{
600				Meta: meta,
601			}, nil
602		},
603		"status": func() (cli.Command, error) {
604			return &StatusCommand{
605				Meta: meta,
606			}, nil
607		},
608		"stop": func() (cli.Command, error) {
609			return &JobStopCommand{
610				Meta: meta,
611			}, nil
612		},
613		"ui": func() (cli.Command, error) {
614			return &UiCommand{
615				Meta: meta,
616			}, nil
617		},
618		"validate": func() (cli.Command, error) {
619			return &JobValidateCommand{
620				Meta: meta,
621			}, nil
622		},
623		"version": func() (cli.Command, error) {
624			return &VersionCommand{
625				Version: version.GetVersion(),
626				Ui:      meta.Ui,
627			}, nil
628		},
629	}
630
631	deprecated := map[string]cli.CommandFactory{
632		"client-config": func() (cli.Command, error) {
633			return &DeprecatedCommand{
634				Old:  "client-config",
635				New:  "node config",
636				Meta: meta,
637				Command: &NodeConfigCommand{
638					Meta: meta,
639				},
640			}, nil
641		},
642
643		"keygen": func() (cli.Command, error) {
644			return &DeprecatedCommand{
645				Old:  "keygen",
646				New:  "operator keygen",
647				Meta: meta,
648				Command: &OperatorKeygenCommand{
649					Meta: meta,
650				},
651			}, nil
652		},
653
654		"keyring": func() (cli.Command, error) {
655			return &DeprecatedCommand{
656				Old:  "keyring",
657				New:  "operator keyring",
658				Meta: meta,
659				Command: &OperatorKeyringCommand{
660					Meta: meta,
661				},
662			}, nil
663		},
664
665		"server-force-leave": func() (cli.Command, error) {
666			return &DeprecatedCommand{
667				Old:  "server-force-leave",
668				New:  "server force-leave",
669				Meta: meta,
670				Command: &ServerForceLeaveCommand{
671					Meta: meta,
672				},
673			}, nil
674		},
675
676		"server-join": func() (cli.Command, error) {
677			return &DeprecatedCommand{
678				Old:  "server-join",
679				New:  "server join",
680				Meta: meta,
681				Command: &ServerJoinCommand{
682					Meta: meta,
683				},
684			}, nil
685		},
686
687		"server-members": func() (cli.Command, error) {
688			return &DeprecatedCommand{
689				Old:  "server-members",
690				New:  "server members",
691				Meta: meta,
692				Command: &ServerMembersCommand{
693					Meta: meta,
694				},
695			}, nil
696		},
697	}
698
699	for k, v := range deprecated {
700		all[k] = v
701	}
702	return all
703}
704