github.com/olli-ai/jx/v2@v2.0.400-0.20210921045218-14731b4dd448/pkg/cmd/logs.go (about)

     1  package cmd
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/olli-ai/jx/v2/pkg/cmd/helper"
     7  
     8  	"github.com/olli-ai/jx/v2/pkg/cmd/opts"
     9  	"github.com/olli-ai/jx/v2/pkg/cmd/templates"
    10  	"github.com/olli-ai/jx/v2/pkg/kube"
    11  	"github.com/olli-ai/jx/v2/pkg/util"
    12  	"github.com/spf13/cobra"
    13  
    14  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    15  )
    16  
    17  type LogsOptions struct {
    18  	*opts.CommonOptions
    19  
    20  	Container       string
    21  	Namespace       string
    22  	Environment     string
    23  	Filter          string
    24  	Label           string
    25  	EditEnvironment bool
    26  }
    27  
    28  var (
    29  	logs_long = templates.LongDesc(`
    30  		Tails the logs of the newest pod for a Deployment.
    31  
    32  `)
    33  
    34  	logs_example = templates.Examples(`
    35  		# Tails the log of the latest pod in deployment myapp
    36  		jx logs myapp
    37  
    38  		# Tails the log of the container foo in the latest pod in deployment myapp
    39  		jx logs myapp -c foo
    40  `)
    41  )
    42  
    43  func NewCmdLogs(commonOpts *opts.CommonOptions) *cobra.Command {
    44  	options := &LogsOptions{
    45  		CommonOptions: commonOpts,
    46  	}
    47  	cmd := &cobra.Command{
    48  		Use:     "logs [deployment]",
    49  		Short:   "Tails the log of the latest pod for a deployment",
    50  		Long:    logs_long,
    51  		Example: logs_example,
    52  		Aliases: []string{"log"},
    53  		Run: func(cmd *cobra.Command, args []string) {
    54  			options.Cmd = cmd
    55  			options.Args = args
    56  			err := options.Run()
    57  			helper.CheckErr(err)
    58  		},
    59  	}
    60  	cmd.Flags().StringVarP(&options.Container, "container", "c", "", "The name of the container to log")
    61  	cmd.Flags().StringVarP(&options.Namespace, "namespace", "n", "", "the namespace to look for the Deployment. Defaults to the current namespace")
    62  	cmd.Flags().StringVarP(&options.Environment, "env", "e", "", "the Environment to look for the Deployment. Defaults to the current environment")
    63  	cmd.Flags().StringVarP(&options.Filter, "filter", "f", "", "Filters the available deployments if no deployment argument is provided")
    64  	cmd.Flags().StringVarP(&options.Label, "label", "l", "", "The label to filter the pods if no deployment argument is provided")
    65  	cmd.Flags().BoolVarP(&options.EditEnvironment, "edit", "d", false, "Use my Edit Environment to look for the Deployment pods")
    66  	return cmd
    67  }
    68  
    69  func (o *LogsOptions) Run() error {
    70  	args := o.Args
    71  
    72  	client, curNs, err := o.KubeClientAndNamespace()
    73  	if err != nil {
    74  		return err
    75  	}
    76  	jxClient, devNs, err := o.JXClientAndDevNamespace()
    77  	if err != nil {
    78  		return err
    79  	}
    80  
    81  	ns := o.Namespace
    82  	if ns == "" {
    83  		env := o.Environment
    84  		if env != "" {
    85  			ns, err = kube.GetEnvironmentNamespace(jxClient, devNs, env)
    86  			if err != nil {
    87  				return err
    88  			}
    89  		}
    90  		if ns == "" && o.EditEnvironment {
    91  			ns, err = kube.GetEditEnvironmentNamespace(jxClient, devNs)
    92  			if err != nil {
    93  				return err
    94  			}
    95  		}
    96  	}
    97  	if ns == "" {
    98  		ns = curNs
    99  	}
   100  	names, err := kube.GetDeploymentNames(client, ns, o.Filter)
   101  	if err != nil {
   102  		return fmt.Errorf("Could not find deployments in namespace %s with filter %s: %s", ns, o.Filter, err)
   103  	}
   104  	if len(names) == 0 {
   105  		if o.Filter == "" {
   106  			return fmt.Errorf("There are no Deployments")
   107  		} else {
   108  			return fmt.Errorf("There are no Deployments matching filter: " + o.Filter)
   109  		}
   110  	}
   111  	name := ""
   112  	if len(args) == 0 {
   113  		if o.Label == "" {
   114  			n, err := util.PickName(names, "Pick Deployment:", "", o.GetIOFileHandles())
   115  			if err != nil {
   116  				return err
   117  			}
   118  			name = n
   119  		}
   120  	} else {
   121  		name = args[0]
   122  		if util.StringArrayIndex(names, name) < 0 {
   123  			return util.InvalidArg(name, names)
   124  		}
   125  	}
   126  
   127  	for {
   128  		pod := ""
   129  		if o.Label != "" {
   130  			selector, err := parseSelector(o.Label)
   131  			if err != nil {
   132  				return err
   133  			}
   134  			pod, err = o.WaitForReadyPodForSelectorLabels(client, ns, selector, false)
   135  			if err != nil {
   136  				return err
   137  			}
   138  			if pod == "" {
   139  				return fmt.Errorf("No pod found for namespace %s with selector %s", ns, o.Label)
   140  			}
   141  		} else {
   142  			pod, err = o.WaitForReadyPodForDeployment(client, ns, name, names, false)
   143  			if err != nil {
   144  				return err
   145  			}
   146  			if pod == "" {
   147  				return fmt.Errorf("No pod found for namespace %s with name %s", ns, name)
   148  			}
   149  		}
   150  		err = o.TailLogs(ns, pod, o.Container)
   151  		if err != nil {
   152  			return nil
   153  		}
   154  	}
   155  }
   156  
   157  func parseSelector(selectorText string) (map[string]string, error) {
   158  	selector, err := metav1.ParseToLabelSelector(selectorText)
   159  	if err != nil {
   160  		return nil, err
   161  	}
   162  	return selector.MatchLabels, nil
   163  }