...
1 package logs
2
3 import (
4 "context"
5 "errors"
6 "fmt"
7 "io"
8
9 "github.com/redhat-developer/odo/pkg/kclient"
10 odolabels "github.com/redhat-developer/odo/pkg/labels"
11 "github.com/redhat-developer/odo/pkg/podman"
12
13 "github.com/redhat-developer/odo/pkg/log"
14
15 "github.com/redhat-developer/odo/pkg/devfile/location"
16 "github.com/redhat-developer/odo/pkg/odo/commonflags"
17 fcontext "github.com/redhat-developer/odo/pkg/odo/commonflags/context"
18 "github.com/redhat-developer/odo/pkg/odo/util"
19 odoutil "github.com/redhat-developer/odo/pkg/odo/util"
20
21 "github.com/spf13/cobra"
22 ktemplates "k8s.io/kubectl/pkg/util/templates"
23
24 "github.com/redhat-developer/odo/pkg/odo/cmdline"
25 odocontext "github.com/redhat-developer/odo/pkg/odo/context"
26 "github.com/redhat-developer/odo/pkg/odo/genericclioptions"
27 "github.com/redhat-developer/odo/pkg/odo/genericclioptions/clientset"
28 )
29
30 const RecommendedCommandName = "logs"
31
32 type LogsOptions struct {
33
34 clientset *clientset.Clientset
35
36
37 out io.Writer
38
39
40 devMode bool
41 deployMode bool
42 follow bool
43 }
44
45 var _ genericclioptions.Runnable = (*LogsOptions)(nil)
46 var _ genericclioptions.SignalHandler = (*LogsOptions)(nil)
47
48 type logsMode string
49
50 const (
51 DevMode logsMode = "dev"
52 DeployMode logsMode = "deploy"
53 )
54
55 func NewLogsOptions() *LogsOptions {
56 return &LogsOptions{
57 out: log.GetStdout(),
58 }
59 }
60
61 var logsExample = ktemplates.Examples(`
62 # Show logs of all containers
63 %[1]s
64 `)
65
66 func (o *LogsOptions) SetClientset(clientset *clientset.Clientset) {
67 o.clientset = clientset
68 }
69
70 func (o *LogsOptions) Complete(ctx context.Context, cmdline cmdline.Cmdline, _ []string) error {
71 var err error
72 workingDir := odocontext.GetWorkingDirectory(ctx)
73 isEmptyDir, err := location.DirIsEmpty(o.clientset.FS, workingDir)
74 if err != nil {
75 return err
76 }
77 if isEmptyDir {
78 return errors.New("this command cannot run in an empty directory, run the command in a directory containing source code or initialize using 'odo init'")
79 }
80
81 devfileObj := odocontext.GetEffectiveDevfileObj(ctx)
82 if devfileObj == nil {
83 return genericclioptions.NewNoDevfileError(odocontext.GetWorkingDirectory(ctx))
84 }
85 return nil
86 }
87
88 func (o *LogsOptions) Validate(ctx context.Context) error {
89
90 switch fcontext.GetPlatform(ctx, commonflags.PlatformCluster) {
91 case commonflags.PlatformCluster:
92 if o.clientset.KubernetesClient == nil {
93 return kclient.NewNoConnectionError()
94 }
95 case commonflags.PlatformPodman:
96 if o.clientset.PodmanClient == nil {
97 return podman.NewPodmanNotFoundError(nil)
98 }
99 }
100
101 if o.devMode && o.deployMode {
102 return errors.New("pass only one of --dev or --deploy flags; pass no flag to see logs for both modes")
103 }
104 return nil
105 }
106
107 func (o *LogsOptions) Run(ctx context.Context) error {
108 var logMode logsMode
109
110 componentName := odocontext.GetComponentName(ctx)
111
112 if o.devMode {
113 logMode = DevMode
114 } else if o.deployMode {
115 logMode = DeployMode
116 }
117
118 var mode string
119 switch logMode {
120 case DevMode:
121 mode = odolabels.ComponentDevMode
122 case DeployMode:
123 mode = odolabels.ComponentDeployMode
124 default:
125 mode = odolabels.ComponentAnyMode
126 }
127
128 ns := ""
129 if o.clientset.KubernetesClient != nil {
130 ns = odocontext.GetNamespace(ctx)
131 }
132
133 return o.clientset.LogsClient.DisplayLogs(
134 ctx,
135 mode,
136 componentName,
137 ns,
138 o.follow,
139 o.out,
140 )
141 }
142
143 func (o *LogsOptions) HandleSignal(ctx context.Context, cancelFunc context.CancelFunc) error {
144 cancelFunc()
145 select {}
146 }
147
148 func NewCmdLogs(name, fullname string, testClientset clientset.Clientset) *cobra.Command {
149 o := NewLogsOptions()
150 logsCmd := &cobra.Command{
151 Use: name,
152 Short: "Show logs of all containers of the component",
153 Long: `odo logs shows logs of all containers of the component.
154 By default it shows logs of all containers running in both Dev and Deploy mode. It prefixes each log message with the container name.`,
155 Example: fmt.Sprintf(logsExample, fullname),
156 Args: cobra.MaximumNArgs(0),
157 RunE: func(cmd *cobra.Command, args []string) error {
158 return genericclioptions.GenericRun(o, testClientset, cmd, args)
159 },
160 }
161 logsCmd.Flags().BoolVar(&o.devMode, string(DevMode), false, "Show logs for containers running only in Dev mode")
162 logsCmd.Flags().BoolVar(&o.deployMode, string(DeployMode), false, "Show logs for containers running only in Deploy mode")
163 logsCmd.Flags().BoolVar(&o.follow, "follow", false, "Follow/tail the logs of the pods")
164
165 clientset.Add(logsCmd, clientset.LOGS, clientset.FILESYSTEM)
166 util.SetCommandGroup(logsCmd, util.MainGroup)
167 logsCmd.SetUsageTemplate(odoutil.CmdUsageTemplate)
168 commonflags.UsePlatformFlag(logsCmd)
169 return logsCmd
170 }
171
View as plain text