github.com/hernad/nomad@v1.6.112/command/service_list.go (about)

     1  // Copyright (c) HashiCorp, Inc.
     2  // SPDX-License-Identifier: MPL-2.0
     3  
     4  package command
     5  
     6  import (
     7  	"fmt"
     8  	"sort"
     9  	"strings"
    10  
    11  	"github.com/hernad/nomad/api"
    12  	"github.com/mitchellh/cli"
    13  	"github.com/posener/complete"
    14  )
    15  
    16  // Ensure ServiceListCommand satisfies the cli.Command interface.
    17  var _ cli.Command = &ServiceListCommand{}
    18  
    19  // ServiceListCommand implements cli.Command.
    20  type ServiceListCommand struct {
    21  	Meta
    22  }
    23  
    24  // Help satisfies the cli.Command Help function.
    25  func (s *ServiceListCommand) Help() string {
    26  	helpText := `
    27  Usage: nomad service list [options]
    28  
    29    List is used to list the currently registered services.
    30  
    31    If ACLs are enabled, this command requires a token with the 'read-job'
    32    capabilities for the namespace of all services. Any namespaces that the token
    33    does not have access to will have its services filtered from the results.
    34  
    35  General Options:
    36  
    37    ` + generalOptionsUsage(usageOptsDefault) + `
    38  
    39  Service List Options:
    40  
    41    -json
    42      Output the services in JSON format.
    43  
    44    -t
    45      Format and display the services using a Go template.
    46  `
    47  	return strings.TrimSpace(helpText)
    48  }
    49  
    50  // Synopsis satisfies the cli.Command Synopsis function.
    51  func (s *ServiceListCommand) Synopsis() string {
    52  	return "Display all registered Nomad services"
    53  }
    54  
    55  func (s *ServiceListCommand) AutocompleteFlags() complete.Flags {
    56  	return mergeAutocompleteFlags(s.Meta.AutocompleteFlags(FlagSetClient),
    57  		complete.Flags{
    58  			"-json": complete.PredictNothing,
    59  			"-t":    complete.PredictAnything,
    60  		})
    61  }
    62  
    63  // Name returns the name of this command.
    64  func (s *ServiceListCommand) Name() string { return "service list" }
    65  
    66  // Run satisfies the cli.Command Run function.
    67  func (s *ServiceListCommand) Run(args []string) int {
    68  
    69  	var (
    70  		json       bool
    71  		tmpl, name string
    72  	)
    73  
    74  	flags := s.Meta.FlagSet(s.Name(), FlagSetClient)
    75  	flags.Usage = func() { s.Ui.Output(s.Help()) }
    76  	flags.BoolVar(&json, "json", false, "")
    77  	flags.StringVar(&name, "name", "", "")
    78  	flags.StringVar(&tmpl, "t", "", "")
    79  	if err := flags.Parse(args); err != nil {
    80  		return 1
    81  	}
    82  
    83  	if args = flags.Args(); len(args) > 0 {
    84  		s.Ui.Error("This command takes no arguments")
    85  		s.Ui.Error(commandErrorText(s))
    86  		return 1
    87  	}
    88  
    89  	client, err := s.Meta.Client()
    90  	if err != nil {
    91  		s.Ui.Error(fmt.Sprintf("Error initializing client: %s", err))
    92  		return 1
    93  	}
    94  
    95  	list, _, err := client.Services().List(nil)
    96  	if err != nil {
    97  		s.Ui.Error(fmt.Sprintf("Error listing service registrations: %s", err))
    98  		return 1
    99  	}
   100  
   101  	if len(list) == 0 {
   102  		s.Ui.Output("No service registrations found")
   103  		return 0
   104  	}
   105  
   106  	if json || len(tmpl) > 0 {
   107  		out, err := Format(json, tmpl, list)
   108  		if err != nil {
   109  			s.Ui.Error(err.Error())
   110  			return 1
   111  		}
   112  		s.Ui.Output(out)
   113  		return 0
   114  	}
   115  
   116  	s.formatOutput(list)
   117  	return 0
   118  }
   119  
   120  func (s *ServiceListCommand) formatOutput(regs []*api.ServiceRegistrationListStub) {
   121  
   122  	// Create objects to hold sorted a sorted namespace array and a mapping, so
   123  	// we can perform service lookups on a namespace basis.
   124  	sortedNamespaces := make([]string, len(regs))
   125  	namespacedServices := make(map[string][]*api.ServiceRegistrationStub)
   126  
   127  	for i, namespaceServices := range regs {
   128  		sortedNamespaces[i] = namespaceServices.Namespace
   129  		namespacedServices[namespaceServices.Namespace] = namespaceServices.Services
   130  	}
   131  
   132  	// Sort the namespaces.
   133  	sort.Strings(sortedNamespaces)
   134  
   135  	// The table always starts with the service name.
   136  	outputTable := []string{"Service Name"}
   137  
   138  	// If the request was made using the wildcard namespace, include this in
   139  	// the output.
   140  	if s.Meta.namespace == api.AllNamespacesNamespace {
   141  		outputTable[0] += "|Namespace"
   142  	}
   143  
   144  	// The tags come last and are always present.
   145  	outputTable[0] += "|Tags"
   146  
   147  	for _, ns := range sortedNamespaces {
   148  
   149  		// Grab the services belonging to this namespace.
   150  		services := namespacedServices[ns]
   151  
   152  		// Create objects to hold sorted a sorted service name array and a
   153  		// mapping, so we can perform service tag lookups on a name basis.
   154  		sortedNames := make([]string, len(services))
   155  		serviceTags := make(map[string][]string)
   156  
   157  		for i, service := range services {
   158  			sortedNames[i] = service.ServiceName
   159  			serviceTags[service.ServiceName] = service.Tags
   160  		}
   161  
   162  		// Sort the service names.
   163  		sort.Strings(sortedNames)
   164  
   165  		for _, serviceName := range sortedNames {
   166  
   167  			// Grab the service tags, and sort these for good measure.
   168  			tags := serviceTags[serviceName]
   169  			sort.Strings(tags)
   170  
   171  			// Build the output array entry.
   172  			regOutput := serviceName
   173  
   174  			if s.Meta.namespace == api.AllNamespacesNamespace {
   175  				regOutput += "|" + ns
   176  			}
   177  			regOutput += "|" + fmt.Sprintf("[%s]", strings.Join(tags, ","))
   178  			outputTable = append(outputTable, regOutput)
   179  		}
   180  	}
   181  
   182  	s.Ui.Output(formatList(outputTable))
   183  }