From 2db8753fc7a65776712ba948b288160020ab0a63 Mon Sep 17 00:00:00 2001 From: Tomas Tulka Date: Fri, 6 Aug 2021 17:58:35 +0200 Subject: [PATCH] logs since tests Signed-off-by: Tomas Tulka --- cmd/flux/logs.go | 14 +++------ cmd/flux/logs_test.go | 64 +++++++++++++++++++++++++++++++++++++++++ cmd/flux/main_test.go | 13 +++++++-- internal/utils/utils.go | 16 +++++++++++ 4 files changed, 95 insertions(+), 12 deletions(-) create mode 100644 cmd/flux/logs_test.go diff --git a/cmd/flux/logs.go b/cmd/flux/logs.go index 62643303..7fb68b2d 100644 --- a/cmd/flux/logs.go +++ b/cmd/flux/logs.go @@ -36,7 +36,6 @@ import ( "k8s.io/kubectl/pkg/util" "github.com/fluxcd/flux2/internal/flags" - "github.com/fluxcd/flux2/internal/utils" ) var logsCmd = &cobra.Command{ @@ -96,13 +95,7 @@ func logsCmdRun(cmd *cobra.Command, args []string) error { ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) defer cancel() - var pods []corev1.Pod - cfg, err := utils.KubeConfig(rootArgs.kubeconfig, rootArgs.kubecontext) - if err != nil { - return err - } - - clientset, err := kubernetes.NewForConfig(cfg) + clientset, err := rootCtx.kubeManager.NewClientset(rootArgs.kubeconfig, rootArgs.kubecontext) if err != nil { return err } @@ -111,6 +104,7 @@ func logsCmdRun(cmd *cobra.Command, args []string) error { return fmt.Errorf("no argument required") } + var pods []corev1.Pod pods, err = getPods(ctx, clientset, fluxSelector) if err != nil { return err @@ -131,7 +125,7 @@ func logsCmdRun(cmd *cobra.Command, args []string) error { if len(logsArgs.sinceTime) > 0 { t, err := util.ParseRFC3339(logsArgs.sinceTime, metav1.Now) if err != nil { - return err + return fmt.Errorf("%s is not a valid (RFC3339) time", logsArgs.sinceTime) } logOpts.SinceTime = &t } @@ -155,7 +149,7 @@ func logsCmdRun(cmd *cobra.Command, args []string) error { return podLogs(ctx, requests) } -func getPods(ctx context.Context, c *kubernetes.Clientset, label string) ([]corev1.Pod, error) { +func getPods(ctx context.Context, c kubernetes.Interface, label string) ([]corev1.Pod, error) { var ret []corev1.Pod opts := metav1.ListOptions{ diff --git a/cmd/flux/logs_test.go b/cmd/flux/logs_test.go new file mode 100644 index 00000000..cea2d5e0 --- /dev/null +++ b/cmd/flux/logs_test.go @@ -0,0 +1,64 @@ +package main + +import ( + "testing" +) + +func TestLogsNoArgs(t *testing.T) { + cmd := cmdTestCase{ + args: "logs", + wantError: false, + } + cmd.runTestCmd(t) +} + +func TestLogsAllNamespaces(t *testing.T) { + cmd := cmdTestCase{ + args: "logs --all-namespaces", + wantError: false, + } + cmd.runTestCmd(t) +} + +func TestLogsSince(t *testing.T) { + cmd := cmdTestCase{ + args: "logs --since=2m", + wantError: false, + } + cmd.runTestCmd(t) +} + +func TestLogsSinceInvalid(t *testing.T) { + cmd := cmdTestCase{ + args: "logs --since=XXX", + wantError: true, + goldenValue: `invalid argument "XXX" for "--since" flag: time: invalid duration "XXX"`, + } + cmd.runTestCmd(t) +} + +func TestLogsSinceTime(t *testing.T) { + cmd := cmdTestCase{ + args: "logs --since-time=2021-08-06T14:26:25.546Z", + wantError: false, + } + cmd.runTestCmd(t) +} + +func TestLogsSinceTimeInvalid(t *testing.T) { + cmd := cmdTestCase{ + args: "logs --since-time=XXX", + wantError: true, + goldenValue: "XXX is not a valid (RFC3339) time", + } + cmd.runTestCmd(t) +} + +func TestLogsSinceOnlyOneAllowed(t *testing.T) { + cmd := cmdTestCase{ + args: "logs --since=2m --since-time=2021-08-06T14:26:25.546Z", + wantError: true, + goldenValue: "at most one of `sinceTime` or `sinceSeconds` may be specified", + } + cmd.runTestCmd(t) +} diff --git a/cmd/flux/main_test.go b/cmd/flux/main_test.go index 832fb84b..a7897471 100644 --- a/cmd/flux/main_test.go +++ b/cmd/flux/main_test.go @@ -13,6 +13,8 @@ import ( "github.com/mattn/go-shellwords" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" k8syaml "k8s.io/apimachinery/pkg/util/yaml" + "k8s.io/client-go/kubernetes" + fakeclientset "k8s.io/client-go/kubernetes/fake" "sigs.k8s.io/controller-runtime/pkg/client" fakeclient "sigs.k8s.io/controller-runtime/pkg/client/fake" ) @@ -50,13 +52,18 @@ func readYamlObjects(objectFile string) ([]client.Object, error) { // A KubeManager that can create objects that are subject to a test. type fakeKubeManager struct { - fakeClient client.WithWatch + fakeClient client.WithWatch + fakeClientset kubernetes.Interface } func (m *fakeKubeManager) NewClient(kubeconfig string, kubecontext string) (client.WithWatch, error) { return m.fakeClient, nil } +func (m *fakeKubeManager) NewClientset(kubeconfig string, kubecontext string) (kubernetes.Interface, error) { + return m.fakeClientset, nil +} + func (m *fakeKubeManager) CreateObjects(clientObjects []client.Object) error { for _, obj := range clientObjects { err := m.fakeClient.Create(context.Background(), obj) @@ -69,8 +76,10 @@ func (m *fakeKubeManager) CreateObjects(clientObjects []client.Object) error { func NewFakeKubeManager() *fakeKubeManager { c := fakeclient.NewClientBuilder().WithScheme(utils.NewScheme()).Build() + cs := fakeclientset.NewSimpleClientset() return &fakeKubeManager{ - fakeClient: c, + fakeClient: c, + fakeClientset: cs, } } diff --git a/internal/utils/utils.go b/internal/utils/utils.go index db323b4c..61fde204 100644 --- a/internal/utils/utils.go +++ b/internal/utils/utils.go @@ -37,6 +37,7 @@ import ( apiruntime "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" sigyaml "k8s.io/apimachinery/pkg/util/yaml" + "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" "k8s.io/client-go/tools/clientcmd" "sigs.k8s.io/controller-runtime/pkg/client" @@ -135,6 +136,7 @@ func KubeConfig(kubeConfigPath string, kubeContext string) (*rest.Config, error) // facilitate unit testing and provide a fake client. type KubeManager interface { NewClient(string, string) (client.WithWatch, error) + NewClientset(string, string) (kubernetes.Interface, error) } type defaultKubeManager struct{} @@ -161,6 +163,20 @@ func (m defaultKubeManager) NewClient(kubeConfigPath string, kubeContext string) return kubeClient, nil } +func (m defaultKubeManager) NewClientset(kubeConfigPath string, kubeContext string) (kubernetes.Interface, error) { + cfg, err := KubeConfig(kubeConfigPath, kubeContext) + if err != nil { + return nil, fmt.Errorf("kubernetes clientset initialization failed: %w", err) + } + + clientset, err := kubernetes.NewForConfig(cfg) + if err != nil { + return nil, fmt.Errorf("kubernetes clientset initialization failed: %w", err) + } + + return clientset, nil +} + // Create the Scheme, methods for serializing and deserializing API objects // which can be shared by tests. func NewScheme() *apiruntime.Scheme {