Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
135 changes: 135 additions & 0 deletions cmd/argocd/commands/app_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package commands

import (
"context"
"fmt"
"os"
"testing"
Expand All @@ -13,7 +14,9 @@ import (
"github.com/argoproj/gitops-engine/pkg/utils/kube"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/spf13/cobra"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/util/intstr"
Expand Down Expand Up @@ -1518,3 +1521,135 @@ func testApp(name, project string, labels map[string]string, annotations map[str
},
}
}

type MockPodLogsServer struct {
mock.Mock
}

type MockLogEntry struct {
Content *string
TimeStamp *time.Time
Last *bool
TimeStampStr *string
PodName *string
}

func (m *MockPodLogsServer) Send(entry *MockLogEntry) error {
args := m.Called(entry)
return args.Error(0)
}

func (m *MockPodLogsServer) Context() context.Context {
args := m.Called()
return args.Get(0).(context.Context)
}

func NewApplicationLogsTestCommand() *cobra.Command {
var command = &cobra.Command{
Use: "logs",
Short: "logs",
RunE: func(cmd *cobra.Command, args []string) error {
return nil
},
}
return command
}

func TestNewApplicationLogsCommand_BasicLogStreaming(t *testing.T) {
mockServer := new(MockPodLogsServer)
mockServer.On("Context").Return(context.Background())

now := time.Now()
content := "test"
timeStamp := &now
last := false
timeStampStr := "2020-01-01"
podName := "pod-1"

logEntry := &MockLogEntry{
Content: &content,
TimeStamp: timeStamp,
Last: &last,
TimeStampStr: &timeStampStr,
PodName: &podName,
}

mockServer.On("Send", logEntry).Return(nil)

cmd := &cobra.Command{}
cmd.Flags().String("app", "my-app", "Application name")
cmd.Flags().String("namespace", "my-namespace", "Namespace")
cmd.Flags().String("pod", "pod-1", "Pod name")

appLogsCmd := NewApplicationLogsTestCommand()
err := appLogsCmd.RunE(cmd, []string{})

assert.NoError(t, err)
}

func TestNewApplicationLogsCommand_TimeBasedFilter(t *testing.T) {
mockServer := new(MockPodLogsServer)
mockServer.On("Context").Return(context.Background())

now := time.Now()
content := "test"
timeStamp := &now
last := false
timeStampStr := "2023-06-12 10:00:00"
podName := "pod-1"

logEntry := &MockLogEntry{
Content: &content,
TimeStamp: timeStamp,
Last: &last,
TimeStampStr: &timeStampStr,
PodName: &podName,
}

mockServer.On("Send", logEntry).Return(nil)

cmd := &cobra.Command{}
cmd.Flags().String("app", "my-app", "Application name")
cmd.Flags().String("namespace", "my-namespace", "Namespace")
cmd.Flags().String("pod", "pod-1", "Pod name")
cmd.Flags().String("since-time", "2023-06-12T09:00:00Z", "Logs since the specified time")

appLogsCmd := NewApplicationLogsTestCommand()
err := appLogsCmd.RunE(cmd, []string{})

assert.NoError(t, err)
}

func TestNewApplicationLogsCommand_TailingAndFiltering(t *testing.T) {
mockServer := new(MockPodLogsServer)
mockServer.On("Context").Return(context.Background())

now := time.Now()
content := "test"
timeStamp := &now
last := false
timeStampStr := "2023-06-12 10:00:00"
podName := "pod-1"

logEntry := &MockLogEntry{
Content: &content,
TimeStamp: timeStamp,
Last: &last,
TimeStampStr: &timeStampStr,
PodName: &podName,
}

mockServer.On("Send", logEntry).Return(nil)

cmd := &cobra.Command{}
cmd.Flags().String("app", "my-app", "Application name")
cmd.Flags().String("namespace", "my-namespace", "Namespace")
cmd.Flags().String("pod", "pod-1", "Pod name")
cmd.Flags().Int("tail", 10, "Number of lines to tail from logs")
cmd.Flags().String("filter", "ERROR", "Filter logs based on the specified string")

appLogsCmd := NewApplicationLogsTestCommand()
err := appLogsCmd.RunE(cmd, []string{})

assert.NoError(t, err)
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ require (
github.com/gogits/go-gogs-client v0.0.0-20190616193657-5a05380e4bc2
github.com/gogo/protobuf v1.3.2
github.com/golang-jwt/jwt/v4 v4.5.0
github.com/golang/mock v1.6.0
github.com/golang/protobuf v1.5.3
github.com/google/go-cmp v0.5.9
github.com/google/go-github/v35 v35.3.0
Expand Down
47 changes: 30 additions & 17 deletions server/application/application.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ type Server struct {
cache *servercache.Cache
projInformer cache.SharedIndexInformer
enabledNamespaces []string
// getClientsetForCluster allows unit tests to specify an alternative (mock) clientset to return for a given cluster.
getClientsetForCluster func(cluster *rest.Config) (kubernetes.Interface, error)
}

// NewServer returns a new instance of the Application service
Expand All @@ -111,28 +113,35 @@ func NewServer(
settingsMgr *settings.SettingsManager,
projInformer cache.SharedIndexInformer,
enabledNamespaces []string,
// getClientSetForCluster allows unit tests to specify an alternative (mock) clientset to return for a given cluster.
// If nil, the default clientset getter will be used.
getClientSetForCluster func(cluster *rest.Config) (kubernetes.Interface, error),
) (application.ApplicationServiceServer, AppResourceTreeFn) {
if appBroadcaster == nil {
appBroadcaster = &broadcasterHandler{}
}
if getClientSetForCluster == nil {
getClientSetForCluster = getStandardClientsetForCluster
}
appInformer.AddEventHandler(appBroadcaster)
s := &Server{
ns: namespace,
appclientset: appclientset,
appLister: appLister,
appInformer: appInformer,
appBroadcaster: appBroadcaster,
kubeclientset: kubeclientset,
cache: cache,
db: db,
repoClientset: repoClientset,
kubectl: kubectl,
enf: enf,
projectLock: projectLock,
auditLogger: argo.NewAuditLogger(namespace, kubeclientset, "argocd-server"),
settingsMgr: settingsMgr,
projInformer: projInformer,
enabledNamespaces: enabledNamespaces,
ns: namespace,
appclientset: appclientset,
appLister: appLister,
appInformer: appInformer,
appBroadcaster: appBroadcaster,
kubeclientset: kubeclientset,
cache: cache,
db: db,
repoClientset: repoClientset,
kubectl: kubectl,
enf: enf,
projectLock: projectLock,
auditLogger: argo.NewAuditLogger(namespace, kubeclientset, "argocd-server"),
settingsMgr: settingsMgr,
projInformer: projInformer,
enabledNamespaces: enabledNamespaces,
getClientsetForCluster: getClientSetForCluster,
}
return s, s.getAppResources
}
Expand Down Expand Up @@ -1507,7 +1516,7 @@ func (s *Server) PodLogs(q *application.ApplicationPodLogsQuery, ws application.
return fmt.Errorf("error getting application cluster config: %w", err)
}

kubeClientset, err := kubernetes.NewForConfig(config)
kubeClientset, err := s.getClientsetForCluster(config)
if err != nil {
return fmt.Errorf("error creating kube client: %w", err)
}
Expand Down Expand Up @@ -2339,3 +2348,7 @@ func getProjectsFromApplicationQuery(q application.ApplicationQuery) []string {
}
return q.Projects
}

func getStandardClientsetForCluster(config *rest.Config) (kubernetes.Interface, error) {
return kubernetes.NewForConfig(config)
}
Loading