This is an automated email from the ASF dual-hosted git repository.

tsato pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-k.git


The following commit(s) were added to refs/heads/main by this push:
     new 8f66a6fbd feat(cli): Add tail flag to the log command
8f66a6fbd is described below

commit 8f66a6fbd6e5de0cc81d6a4710955537d67e382e
Author: Nicolas Filotto <[email protected]>
AuthorDate: Tue Aug 30 17:24:10 2022 +0200

    feat(cli): Add tail flag to the log command
---
 e2e/namespace/install/cli/log_test.go         | 11 +++++++++--
 pkg/cmd/debug.go                              |  2 +-
 pkg/cmd/log.go                                |  9 ++++++++-
 pkg/cmd/run.go                                |  2 +-
 pkg/util/kubernetes/log/annotation_scraper.go |  6 ++++--
 pkg/util/kubernetes/log/pod_scraper.go        |  5 ++++-
 pkg/util/kubernetes/log/util.go               |  8 ++++----
 7 files changed, 31 insertions(+), 12 deletions(-)

diff --git a/e2e/namespace/install/cli/log_test.go 
b/e2e/namespace/install/cli/log_test.go
index 5b696ac68..967128ca9 100644
--- a/e2e/namespace/install/cli/log_test.go
+++ b/e2e/namespace/install/cli/log_test.go
@@ -42,12 +42,19 @@ func TestKamelCLILog(t *testing.T) {
                        Expect(KamelRunWithID(operatorID, ns, 
"../files/yaml.yaml").Execute()).To(Succeed())
                        Eventually(IntegrationPodPhase(ns, "yaml"), 
TestTimeoutLong).Should(Equal(corev1.PodRunning))
                        // first line of the integration logs
-                       logs := strings.Split(IntegrationLogs(ns, "yaml")(), 
"\n")[0]
+                       firstLine := strings.Split(IntegrationLogs(ns, 
"yaml")(), "\n")[0]
                        podName := IntegrationPod(ns, "yaml")().Name
 
                        logsCLI := GetOutputStringAsync(Kamel("log", "yaml", 
"-n", ns))
                        Eventually(logsCLI).Should(ContainSubstring("Monitoring 
pod " + podName))
-                       Eventually(logsCLI).Should(ContainSubstring(logs))
+                       Eventually(logsCLI).Should(ContainSubstring(firstLine))
+
+                       logs := strings.Split(IntegrationLogs(ns, "yaml")(), 
"\n")
+                       lastLine := logs[len(logs)-1]
+
+                       logsCLI = GetOutputStringAsync(Kamel("log", "yaml", 
"-n", ns, "--tail", "5"))
+                       Eventually(logsCLI).Should(ContainSubstring("Monitoring 
pod " + podName))
+                       Eventually(logsCLI).Should(ContainSubstring(lastLine))
                })
        })
 }
diff --git a/pkg/cmd/debug.go b/pkg/cmd/debug.go
index 2913bacae..7d5a1de8f 100644
--- a/pkg/cmd/debug.go
+++ b/pkg/cmd/debug.go
@@ -123,7 +123,7 @@ func (o *debugCmdOptions) run(cmd *cobra.Command, args 
[]string) error {
        selector := 
fmt.Sprintf("camel.apache.org/debug=true,camel.apache.org/integration=%s", name)
 
        go func() {
-               err = k8slog.PrintUsingSelector(o.Context, cmd, cmdClient, 
o.Namespace, "integration", selector, cmd.OutOrStdout())
+               err = k8slog.PrintUsingSelector(o.Context, cmd, cmdClient, 
o.Namespace, "integration", selector, nil, cmd.OutOrStdout())
                if err != nil {
                        fmt.Fprintln(cmd.ErrOrStderr(), err.Error())
                }
diff --git a/pkg/cmd/log.go b/pkg/cmd/log.go
index 9a9efcbf9..6faa19b35 100644
--- a/pkg/cmd/log.go
+++ b/pkg/cmd/log.go
@@ -46,6 +46,8 @@ func newCmdLog(rootCmdOptions *RootCmdOptions) 
(*cobra.Command, *logCmdOptions)
                RunE:    options.run,
        }
 
+       cmd.Flags().Int64("tail", -1, "The number of lines from the end of the 
logs to show. Defaults to -1 to show all the lines.")
+
        // completion support
        configureKnownCompletions(&cmd)
 
@@ -54,6 +56,7 @@ func newCmdLog(rootCmdOptions *RootCmdOptions) 
(*cobra.Command, *logCmdOptions)
 
 type logCmdOptions struct {
        *RootCmdOptions
+       Tail int64 `mapstructure:"tail"`
 }
 
 func (o *logCmdOptions) validate(_ *cobra.Command, args []string) error {
@@ -129,7 +132,11 @@ func (o *logCmdOptions) run(cmd *cobra.Command, args 
[]string) error {
                        // Found the running integration so step over to 
scraping its pod log
                        //
                        fmt.Fprintln(cmd.OutOrStdout(), "Integration 
'"+integrationID+"' is now running. Showing log ...")
-                       if err := k8slog.Print(o.Context, cmd, c, &integration, 
cmd.OutOrStdout()); err != nil {
+                       var tailLines *int64
+                       if o.Tail > 0 {
+                               tailLines = &o.Tail
+                       }
+                       if err := k8slog.Print(o.Context, cmd, c, &integration, 
tailLines, cmd.OutOrStdout()); err != nil {
                                return false, err
                        }
 
diff --git a/pkg/cmd/run.go b/pkg/cmd/run.go
index b1e23aa6e..ac4174ff4 100644
--- a/pkg/cmd/run.go
+++ b/pkg/cmd/run.go
@@ -378,7 +378,7 @@ func (o *runCmdOptions) run(cmd *cobra.Command, args 
[]string) error {
                }
        }
        if o.Logs || o.Dev {
-               err = k8slog.Print(o.Context, cmd, c, integration, 
cmd.OutOrStdout())
+               err = k8slog.Print(o.Context, cmd, c, integration, nil, 
cmd.OutOrStdout())
                if err != nil {
                        return err
                }
diff --git a/pkg/util/kubernetes/log/annotation_scraper.go 
b/pkg/util/kubernetes/log/annotation_scraper.go
index c3cde929d..4c687ad60 100644
--- a/pkg/util/kubernetes/log/annotation_scraper.go
+++ b/pkg/util/kubernetes/log/annotation_scraper.go
@@ -44,16 +44,18 @@ type SelectorScraper struct {
        podScrapers          sync.Map
        counter              uint64
        L                    klog.Logger
+       tailLines            *int64
 }
 
 // NewSelectorScraper creates a new SelectorScraper.
-func NewSelectorScraper(client kubernetes.Interface, namespace string, 
defaultContainerName string, labelSelector string) *SelectorScraper {
+func NewSelectorScraper(client kubernetes.Interface, namespace string, 
defaultContainerName string, labelSelector string, tailLines *int64) 
*SelectorScraper {
        return &SelectorScraper{
                client:               client,
                namespace:            namespace,
                defaultContainerName: defaultContainerName,
                labelSelector:        labelSelector,
                L:                    
klog.WithName("scraper").WithName("label").WithValues("selector", 
labelSelector),
+               tailLines:            tailLines,
        }
 }
 
@@ -130,7 +132,7 @@ func (s *SelectorScraper) synchronize(ctx context.Context, 
out *bufio.Writer) er
 }
 
 func (s *SelectorScraper) addPodScraper(ctx context.Context, podName string, 
out *bufio.Writer) {
-       podScraper := NewPodScraper(s.client, s.namespace, podName, 
s.defaultContainerName)
+       podScraper := NewPodScraper(s.client, s.namespace, podName, 
s.defaultContainerName, s.tailLines)
        podCtx, podCancel := context.WithCancel(ctx)
        id := atomic.AddUint64(&s.counter, 1)
        prefix := "[" + strconv.FormatUint(id, 10) + "] "
diff --git a/pkg/util/kubernetes/log/pod_scraper.go 
b/pkg/util/kubernetes/log/pod_scraper.go
index 494e0501f..a9fb24a89 100644
--- a/pkg/util/kubernetes/log/pod_scraper.go
+++ b/pkg/util/kubernetes/log/pod_scraper.go
@@ -48,16 +48,18 @@ type PodScraper struct {
        defaultContainerName string
        client               kubernetes.Interface
        L                    klog.Logger
+       tailLines            *int64
 }
 
 // NewPodScraper creates a new pod scraper.
-func NewPodScraper(c kubernetes.Interface, namespace string, podName string, 
defaultContainerName string) *PodScraper {
+func NewPodScraper(c kubernetes.Interface, namespace string, podName string, 
defaultContainerName string, tailLines *int64) *PodScraper {
        return &PodScraper{
                namespace:            namespace,
                podName:              podName,
                defaultContainerName: defaultContainerName,
                client:               c,
                L:                    
klog.WithName("scraper").WithName("pod").WithValues("name", podName),
+               tailLines:            tailLines,
        }
 }
 
@@ -83,6 +85,7 @@ func (s *PodScraper) doScrape(ctx context.Context, out 
*bufio.Writer, clientClos
        }
        logOptions := corev1.PodLogOptions{
                Follow:    true,
+               TailLines: s.tailLines,
                Container: containerName,
        }
        byteReader, err := 
s.client.CoreV1().Pods(s.namespace).GetLogs(s.podName, &logOptions).Stream(ctx)
diff --git a/pkg/util/kubernetes/log/util.go b/pkg/util/kubernetes/log/util.go
index 26bd2c158..8dbc08530 100644
--- a/pkg/util/kubernetes/log/util.go
+++ b/pkg/util/kubernetes/log/util.go
@@ -30,13 +30,13 @@ import (
 )
 
 // Print prints integrations logs to the stdout.
-func Print(ctx context.Context, cmd *cobra.Command, client 
kubernetes.Interface, integration *v1.Integration, out io.Writer) error {
-       return PrintUsingSelector(ctx, cmd, client, integration.Namespace, 
integration.Name, v1.IntegrationLabel+"="+integration.Name, out)
+func Print(ctx context.Context, cmd *cobra.Command, client 
kubernetes.Interface, integration *v1.Integration, tailLines *int64, out 
io.Writer) error {
+       return PrintUsingSelector(ctx, cmd, client, integration.Namespace, 
integration.Name, v1.IntegrationLabel+"="+integration.Name, tailLines, out)
 }
 
 // PrintUsingSelector prints pod logs using a selector.
-func PrintUsingSelector(ctx context.Context, cmd *cobra.Command, client 
kubernetes.Interface, namespace, defaultContainerName, selector string, out 
io.Writer) error {
-       scraper := NewSelectorScraper(client, namespace, defaultContainerName, 
selector)
+func PrintUsingSelector(ctx context.Context, cmd *cobra.Command, client 
kubernetes.Interface, namespace, defaultContainerName, selector string, 
tailLines *int64, out io.Writer) error {
+       scraper := NewSelectorScraper(client, namespace, defaultContainerName, 
selector, tailLines)
        reader := scraper.Start(ctx)
 
        if _, err := io.Copy(out, ioutil.NopCloser(reader)); err != nil {

Reply via email to