Skip to content

Commit a85a24f

Browse files
authored
feat: add logs subcommand (#46)
Signed-off-by: loheagn <loheagn@icloud.com>
1 parent 67e3391 commit a85a24f

File tree

3 files changed

+143
-1
lines changed

3 files changed

+143
-1
lines changed

go.sum

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb0
155155
github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c=
156156
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
157157
github.com/OneOfOne/xxhash v1.2.7/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q=
158-
github.com/OpenFunction/OpenFunction v0.6.0 h1:BZZCgr4s6OFadPRhrO+vRKpo4BHznknZMMOHQc/I3hs=
158+
github.com/OpenFunction/OpenFunction v0.6.0 h1:VfIqhLBz3I9DBheWBjKuFHZ2L31NdDvf0ZcAkT+P+70=
159159
github.com/OpenFunction/OpenFunction v0.6.0/go.mod h1:7Ida4Kxst2Y+EnbIh/OELB22JXlJO81+PoXWJnB0sSw=
160160
github.com/ProtonMail/go-crypto v0.0.0-20210329181949-3900d675f39b/go.mod h1:HTM9X7e9oLwn7RiqLG0UVwVRJenLs3wN+tQ0NPAfwMQ=
161161
github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=

pkg/cmd/cmd.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ Find more information at:
5252
cmd.AddCommand(subcommand.NewCmdCreate(kubeConfigFlags, ioStreams))
5353
cmd.AddCommand(subcommand.NewCmdDelete(kubeConfigFlags, ioStreams))
5454
cmd.AddCommand(subcommand.NewCmdGet(kubeConfigFlags, ioStreams))
55+
cmd.AddCommand(subcommand.NewCmdLogs(kubeConfigFlags, ioStreams))
5556
cmd.AddCommand(subcommand.NewCmdInstall(kubeConfigFlags, ioStreams))
5657
cmd.AddCommand(subcommand.NewCmdUninstall(kubeConfigFlags, ioStreams))
5758
cmd.AddCommand(subcommand.NewCmdDemo(kubeConfigFlags, ioStreams))

pkg/cmd/subcommand/logs.go

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
/*
2+
Copyright 2022 The OpenFunction Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package subcommand
18+
19+
import (
20+
"context"
21+
"errors"
22+
"fmt"
23+
"io"
24+
25+
"github.com/OpenFunction/cli/pkg/cmd/util"
26+
cc "github.com/OpenFunction/cli/pkg/cmd/util/client"
27+
client "github.com/openfunction/pkg/client/clientset/versioned"
28+
"github.com/spf13/cobra"
29+
corev1 "k8s.io/api/core/v1"
30+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
31+
"k8s.io/cli-runtime/pkg/genericclioptions"
32+
k8s "k8s.io/client-go/kubernetes"
33+
)
34+
35+
// Logs is the commandline for `logs` sub command
36+
type Logs struct {
37+
*genericclioptions.IOStreams
38+
39+
functionName string
40+
containerName string
41+
namespace string
42+
43+
Follow bool
44+
45+
functionClient client.Interface
46+
clientSet *k8s.Clientset
47+
}
48+
49+
// NewCmdLogs builds the `logs` sub command
50+
func NewCmdLogs(cf *genericclioptions.ConfigFlags, ioStreams genericclioptions.IOStreams) *cobra.Command {
51+
52+
l := &Logs{
53+
IOStreams: &ioStreams,
54+
containerName: "function",
55+
}
56+
57+
cmd := &cobra.Command{
58+
Use: `logs [OPTIONS] FUNCTION_NAME [CONTAINER_NAME]`,
59+
DisableFlagsInUseLine: true,
60+
Short: "Get the logs from the serving pods created by the function",
61+
Long: `Get the logs from the serving pods created by the function`,
62+
Example: `
63+
# Get tht logs from the 'function' container in the serving pods created by the function whose name is 'demo-function'
64+
ofn logs demo-function
65+
66+
# Get tht logs from the 'extra' container (a container whose name is not 'function') in the serving pods created by the function whose name is 'demo-function'
67+
ofn logs demo-function extra
68+
69+
# Begin streaming the logs from the 'function' container in the serving pods created by the function whose name is 'demo-function'
70+
ofn logs -f demo-function
71+
`,
72+
PreRunE: func(cmd *cobra.Command, args []string) (err error) {
73+
return l.preRun(cf, args)
74+
},
75+
Run: func(cmd *cobra.Command, args []string) {
76+
util.CheckErr(l.run())
77+
},
78+
}
79+
cmd.Flags().BoolVarP(&l.Follow, "follow", "f", l.Follow, "Specify if the logs should be streamed")
80+
return cmd
81+
}
82+
83+
func (l *Logs) preRun(cf *genericclioptions.ConfigFlags, args []string) error {
84+
config, clientSet, err := cc.NewKubeConfigClient(cf)
85+
if err != nil {
86+
panic(err)
87+
}
88+
l.clientSet = clientSet
89+
err = cc.SetConfigDefaults(config)
90+
if err != nil {
91+
return err
92+
}
93+
l.functionClient = client.NewForConfigOrDie(config)
94+
95+
if cf.Namespace != nil && *(cf.Namespace) != "" {
96+
l.namespace = *(cf.Namespace)
97+
} else {
98+
if l.namespace, _, err = cf.ToRawKubeConfigLoader().Namespace(); err != nil {
99+
return err
100+
}
101+
}
102+
103+
if len(args) < 1 {
104+
return errors.New("missing argument: FUNCTION_NAME")
105+
}
106+
l.functionName = args[0]
107+
if len(args) > 1 {
108+
l.containerName = args[1]
109+
}
110+
return nil
111+
}
112+
113+
func (l *Logs) run() error {
114+
ctx := context.Background()
115+
f, err := l.functionClient.CoreV1beta1().Functions(l.namespace).Get(ctx, l.functionName, metav1.GetOptions{})
116+
if err != nil {
117+
return err
118+
}
119+
if f.Status.Serving == nil {
120+
return nil
121+
}
122+
serving := f.Status.Serving.ResourceRef
123+
listOpt := metav1.ListOptions{LabelSelector: fmt.Sprintf("openfunction.io/serving=%s", serving)}
124+
podInterface := l.clientSet.CoreV1().Pods(l.namespace)
125+
podList, err := podInterface.List(ctx, listOpt)
126+
if err != nil {
127+
return err
128+
}
129+
readerList := make([]io.Reader, 0, len(podList.Items))
130+
for _, pod := range podList.Items {
131+
logReader, err := podInterface.GetLogs(pod.Name, &corev1.PodLogOptions{Follow: l.Follow, Container: l.containerName}).Stream(ctx)
132+
defer logReader.Close()
133+
if err != nil {
134+
return err
135+
}
136+
readerList = append(readerList, logReader)
137+
}
138+
reader := io.MultiReader(readerList...)
139+
_, err = io.Copy(l.IOStreams.Out, reader)
140+
return err
141+
}

0 commit comments

Comments
 (0)