github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/swarmkit/cmd/swarmctl/service/inspect.go (about)

     1  package service
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"io"
     7  	"os"
     8  	"sort"
     9  	"strings"
    10  	"text/tabwriter"
    11  
    12  	"github.com/docker/swarmkit/api"
    13  	"github.com/docker/swarmkit/api/genericresource"
    14  	"github.com/docker/swarmkit/cmd/swarmctl/common"
    15  	"github.com/docker/swarmkit/cmd/swarmctl/task"
    16  	"github.com/dustin/go-humanize"
    17  	gogotypes "github.com/gogo/protobuf/types"
    18  	"github.com/spf13/cobra"
    19  )
    20  
    21  func printServiceSummary(service *api.Service, running int) {
    22  	w := tabwriter.NewWriter(os.Stdout, 8, 8, 8, ' ', 0)
    23  	defer w.Flush()
    24  
    25  	task := service.Spec.Task
    26  	common.FprintfIfNotEmpty(w, "ID\t: %s\n", service.ID)
    27  	common.FprintfIfNotEmpty(w, "Name\t: %s\n", service.Spec.Annotations.Name)
    28  	if len(service.Spec.Annotations.Labels) > 0 {
    29  		fmt.Fprintln(w, "Labels\t")
    30  		for k, v := range service.Spec.Annotations.Labels {
    31  			fmt.Fprintf(w, "  %s\t: %s\n", k, v)
    32  		}
    33  	}
    34  	common.FprintfIfNotEmpty(w, "Replicas\t: %s\n", getServiceReplicasTxt(service, running))
    35  
    36  	if service.UpdateStatus != nil {
    37  		fmt.Fprintln(w, "Update Status\t")
    38  		fmt.Fprintln(w, " State\t:", service.UpdateStatus.State)
    39  		started, err := gogotypes.TimestampFromProto(service.UpdateStatus.StartedAt)
    40  		if err == nil {
    41  			fmt.Fprintln(w, " Started\t:", humanize.Time(started))
    42  		}
    43  		if service.UpdateStatus.State == api.UpdateStatus_COMPLETED {
    44  			completed, err := gogotypes.TimestampFromProto(service.UpdateStatus.CompletedAt)
    45  			if err == nil {
    46  				fmt.Fprintln(w, " Completed\t:", humanize.Time(completed))
    47  			}
    48  		}
    49  		fmt.Fprintln(w, " Message\t:", service.UpdateStatus.Message)
    50  	}
    51  
    52  	fmt.Fprintln(w, "Template\t")
    53  	fmt.Fprintln(w, " Container\t")
    54  	ctr := service.Spec.Task.GetContainer()
    55  	common.FprintfIfNotEmpty(w, "  Image\t: %s\n", ctr.Image)
    56  	common.FprintfIfNotEmpty(w, "  Command\t: %q\n", strings.Join(ctr.Command, " "))
    57  	common.FprintfIfNotEmpty(w, "  Args\t: [%s]\n", strings.Join(ctr.Args, ", "))
    58  	common.FprintfIfNotEmpty(w, "  Env\t: [%s]\n", strings.Join(ctr.Env, ", "))
    59  	if task.Placement != nil {
    60  		common.FprintfIfNotEmpty(w, "  Constraints\t: %s\n", strings.Join(task.Placement.Constraints, ", "))
    61  	}
    62  
    63  	if task.Resources != nil {
    64  		res := task.Resources
    65  		fmt.Fprintln(w, "  Resources\t")
    66  		printResources := func(w io.Writer, r *api.Resources) {
    67  			if r.NanoCPUs != 0 {
    68  				fmt.Fprintf(w, "      CPU\t: %g\n", float64(r.NanoCPUs)/1e9)
    69  			}
    70  			if r.MemoryBytes != 0 {
    71  				fmt.Fprintf(w, "      Memory\t: %s\n", humanize.IBytes(uint64(r.MemoryBytes)))
    72  			}
    73  			if len(r.Generic) != 0 {
    74  				fmt.Fprintln(w, "      Generic Resources\t")
    75  			}
    76  
    77  			for _, r := range r.Generic {
    78  				k := genericresource.Kind(r)
    79  				v := genericresource.Value(r)
    80  				fmt.Fprintf(w, "        %s\t: %s\n", k, v)
    81  			}
    82  
    83  		}
    84  		if res.Reservations != nil {
    85  			fmt.Fprintln(w, "    Reservations:\t")
    86  			printResources(w, res.Reservations)
    87  		}
    88  		if res.Limits != nil {
    89  			fmt.Fprintln(w, "    Limits:\t")
    90  			printResources(w, res.Limits)
    91  		}
    92  	}
    93  	if len(service.Spec.Task.Networks) > 0 {
    94  		fmt.Fprint(w, "  Networks:")
    95  		for _, n := range service.Spec.Task.Networks {
    96  			fmt.Fprintf(w, " %s", n.Target)
    97  		}
    98  	}
    99  
   100  	if service.Endpoint != nil && len(service.Endpoint.Ports) > 0 {
   101  		fmt.Fprintln(w, "\nPorts:")
   102  		for _, port := range service.Endpoint.Ports {
   103  			fmt.Fprintf(w, "    - Name\t= %s\n", port.Name)
   104  			fmt.Fprintf(w, "      Protocol\t= %s\n", port.Protocol)
   105  			fmt.Fprintf(w, "      Port\t= %d\n", port.TargetPort)
   106  			fmt.Fprintf(w, "      SwarmPort\t= %d\n", port.PublishedPort)
   107  		}
   108  	}
   109  
   110  	if len(ctr.Mounts) > 0 {
   111  		fmt.Fprintln(w, "  Mounts:")
   112  		for _, v := range ctr.Mounts {
   113  			fmt.Fprintf(w, "    - target = %s\n", v.Target)
   114  			fmt.Fprintf(w, "      source = %s\n", v.Source)
   115  			fmt.Fprintf(w, "      readonly = %v\n", v.ReadOnly)
   116  			fmt.Fprintf(w, "      type = %v\n", strings.ToLower(v.Type.String()))
   117  		}
   118  	}
   119  
   120  	if len(ctr.Secrets) > 0 {
   121  		fmt.Fprintln(w, "  Secrets:")
   122  		for _, sr := range ctr.Secrets {
   123  			var targetName, mode string
   124  			if sr.GetFile() != nil {
   125  				targetName = sr.GetFile().Name
   126  				mode = "FILE"
   127  			}
   128  			fmt.Fprintf(w, "    [%s] %s@%s:%s\n", mode, sr.SecretName, sr.SecretID, targetName)
   129  		}
   130  	}
   131  
   132  	if len(ctr.Configs) > 0 {
   133  		fmt.Fprintln(w, "  Configs:")
   134  		for _, cr := range ctr.Configs {
   135  			var targetName, mode string
   136  			if cr.GetFile() != nil {
   137  				targetName = cr.GetFile().Name
   138  				mode = "FILE"
   139  			}
   140  			fmt.Fprintf(w, "    [%s] %s@%s:%s\n", mode, cr.ConfigName, cr.ConfigID, targetName)
   141  		}
   142  	}
   143  
   144  	if task.LogDriver != nil {
   145  		fmt.Fprintf(w, "  LogDriver\t: %s\n", task.LogDriver.Name)
   146  		var keys []string
   147  
   148  		if task.LogDriver.Options != nil {
   149  			for k := range task.LogDriver.Options {
   150  				keys = append(keys, k)
   151  			}
   152  			sort.Strings(keys)
   153  
   154  			for _, k := range keys {
   155  				v := task.LogDriver.Options[k]
   156  				if v != "" {
   157  					fmt.Fprintf(w, "    %s\t: %s\n", k, v)
   158  				} else {
   159  					fmt.Fprintf(w, "    %s\t\n", k)
   160  
   161  				}
   162  			}
   163  		}
   164  	}
   165  }
   166  
   167  var (
   168  	inspectCmd = &cobra.Command{
   169  		Use:   "inspect <service ID>",
   170  		Short: "Inspect a service",
   171  		RunE: func(cmd *cobra.Command, args []string) error {
   172  			if len(args) == 0 {
   173  				return errors.New("service ID missing")
   174  			}
   175  
   176  			if len(args) > 1 {
   177  				return errors.New("inspect command takes exactly 1 argument")
   178  			}
   179  
   180  			flags := cmd.Flags()
   181  
   182  			all, err := flags.GetBool("all")
   183  			if err != nil {
   184  				return err
   185  			}
   186  
   187  			c, err := common.Dial(cmd)
   188  			if err != nil {
   189  				return err
   190  			}
   191  
   192  			res := common.NewResolver(cmd, c)
   193  
   194  			service, err := getService(common.Context(cmd), c, args[0])
   195  			if err != nil {
   196  				return err
   197  			}
   198  
   199  			r, err := c.ListTasks(common.Context(cmd),
   200  				&api.ListTasksRequest{
   201  					Filters: &api.ListTasksRequest_Filters{
   202  						ServiceIDs: []string{service.ID},
   203  					},
   204  				})
   205  			if err != nil {
   206  				return err
   207  			}
   208  			var running int
   209  			for _, t := range r.Tasks {
   210  				if t.Status.State == api.TaskStateRunning {
   211  					running++
   212  				}
   213  			}
   214  
   215  			printServiceSummary(service, running)
   216  			if len(r.Tasks) > 0 {
   217  				fmt.Println()
   218  				task.Print(r.Tasks, all, res)
   219  			}
   220  
   221  			return nil
   222  		},
   223  	}
   224  )
   225  
   226  func init() {
   227  	inspectCmd.Flags().BoolP("all", "a", false, "Show all tasks (default shows just running)")
   228  }