2022-05-30 10:10:58 +00:00
|
|
|
package logs_test
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"context"
|
2022-06-01 17:19:55 +00:00
|
|
|
"errors"
|
|
|
|
"io"
|
|
|
|
"strings"
|
2022-05-30 10:10:58 +00:00
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"git.netflux.io/rob/kubectl-persistent-logger/logs"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
appsv1 "k8s.io/api/apps/v1"
|
|
|
|
corev1 "k8s.io/api/core/v1"
|
|
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
|
|
"k8s.io/apimachinery/pkg/watch"
|
|
|
|
testclient "k8s.io/client-go/kubernetes/fake"
|
|
|
|
k8stest "k8s.io/client-go/testing"
|
|
|
|
)
|
|
|
|
|
2022-06-01 17:19:55 +00:00
|
|
|
type mockPodWatcher struct{ err error }
|
|
|
|
|
|
|
|
func (m *mockPodWatcher) WatchPods(ctx context.Context) error { return m.err }
|
|
|
|
func (m *mockPodWatcher) Close() {}
|
|
|
|
|
|
|
|
func mockPodwatcherFunc(err error) logs.PodWatcherFunc {
|
|
|
|
return func(logs.KubernetesClient, string, *metav1.LabelSelector, io.Writer) logs.PodWatcherInterface {
|
|
|
|
return &mockPodWatcher{err: err}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestWatcherAllowNonExistent(t *testing.T) {
|
|
|
|
clientset := testclient.NewSimpleClientset()
|
|
|
|
|
|
|
|
var buf bytes.Buffer
|
|
|
|
client := logs.KubernetesClient{Interface: clientset}
|
2022-06-01 20:04:20 +00:00
|
|
|
watcher := logs.NewWatcher("mydeployment", "mycontainer", true, client, mockPodwatcherFunc(nil), &buf)
|
2022-06-01 17:19:55 +00:00
|
|
|
|
|
|
|
err := watcher.Watch(context.Background())
|
|
|
|
assert.EqualError(t, err, `deployments.apps "mydeployment" not found`)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestWatcherPodWatcherError(t *testing.T) {
|
|
|
|
deploymentsWatcher := watch.NewFake()
|
2022-05-30 10:10:58 +00:00
|
|
|
clientset := testclient.NewSimpleClientset(
|
2022-06-01 17:19:55 +00:00
|
|
|
&appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: "mydeployment", Namespace: "default"}},
|
2022-05-30 10:10:58 +00:00
|
|
|
)
|
2022-06-01 17:19:55 +00:00
|
|
|
clientset.PrependWatchReactor("deployments", k8stest.DefaultWatchReactor(deploymentsWatcher, nil))
|
2022-05-30 10:10:58 +00:00
|
|
|
|
2022-06-01 17:19:55 +00:00
|
|
|
var buf bytes.Buffer
|
|
|
|
client := logs.KubernetesClient{Interface: clientset}
|
|
|
|
wantErr := errors.New("foo")
|
2022-06-01 20:04:20 +00:00
|
|
|
watcher := logs.NewWatcher("mydeployment", "mycontainer", true, client, mockPodwatcherFunc(wantErr), &buf)
|
2022-05-30 10:10:58 +00:00
|
|
|
|
|
|
|
go func() {
|
2022-06-01 17:19:55 +00:00
|
|
|
defer deploymentsWatcher.Stop()
|
|
|
|
deployment := &appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: "mydeployment", Namespace: "default"}}
|
|
|
|
deploymentsWatcher.Add(deployment)
|
|
|
|
}()
|
|
|
|
|
|
|
|
err := watcher.Watch(context.Background())
|
|
|
|
assert.EqualError(t, err, wantErr.Error())
|
|
|
|
}
|
|
|
|
|
2022-06-04 00:27:20 +00:00
|
|
|
func TestWatcherClosedChannel(t *testing.T) {
|
|
|
|
deploymentsWatcher := watch.NewFake()
|
|
|
|
clientset := testclient.NewSimpleClientset(
|
|
|
|
&appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: "mydeployment", Namespace: "default"}},
|
|
|
|
)
|
|
|
|
clientset.PrependWatchReactor("deployments", k8stest.DefaultWatchReactor(deploymentsWatcher, nil))
|
|
|
|
|
|
|
|
var buf bytes.Buffer
|
|
|
|
client := logs.KubernetesClient{Interface: clientset}
|
|
|
|
watcher := logs.NewWatcher("mydeployment", "mycontainer", true, client, nil, &buf)
|
|
|
|
go deploymentsWatcher.Stop()
|
|
|
|
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond*500)
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
err := watcher.Watch(ctx)
|
|
|
|
require.Equal(t, context.DeadlineExceeded, err)
|
|
|
|
assert.Equal(t, "", buf.String())
|
|
|
|
}
|
|
|
|
|
2022-06-01 17:19:55 +00:00
|
|
|
func TestWatcherWithPodWatcher(t *testing.T) {
|
2022-06-07 19:14:07 +00:00
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
|
|
|
|
defer cancel()
|
2022-06-01 17:19:55 +00:00
|
|
|
|
|
|
|
deploymentsWatcher := watch.NewFake()
|
2022-06-02 17:23:47 +00:00
|
|
|
defer deploymentsWatcher.Stop()
|
2022-06-01 17:19:55 +00:00
|
|
|
podsWatcher := watch.NewFake()
|
2022-06-02 17:23:47 +00:00
|
|
|
defer podsWatcher.Stop()
|
|
|
|
|
2022-06-01 17:19:55 +00:00
|
|
|
clientset := testclient.NewSimpleClientset()
|
|
|
|
clientset.PrependWatchReactor("pods", k8stest.DefaultWatchReactor(podsWatcher, nil))
|
|
|
|
clientset.PrependWatchReactor("deployments", k8stest.DefaultWatchReactor(deploymentsWatcher, nil))
|
|
|
|
|
|
|
|
go func() {
|
|
|
|
deployment := &appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: "mydeployment", Namespace: "default"}}
|
|
|
|
deploymentsWatcher.Add(deployment)
|
|
|
|
time.Sleep(time.Millisecond * 250)
|
|
|
|
|
|
|
|
pods := []*corev1.Pod{
|
|
|
|
{
|
|
|
|
ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "default"},
|
|
|
|
Status: corev1.PodStatus{Phase: corev1.PodRunning},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
ObjectMeta: metav1.ObjectMeta{Name: "bar", Namespace: "default"},
|
|
|
|
Status: corev1.PodStatus{Phase: corev1.PodRunning},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
ObjectMeta: metav1.ObjectMeta{Name: "baz", Namespace: "default"},
|
|
|
|
Status: corev1.PodStatus{Phase: corev1.PodPending},
|
|
|
|
},
|
|
|
|
}
|
2022-05-30 10:10:58 +00:00
|
|
|
for _, pod := range pods {
|
2022-06-01 17:19:55 +00:00
|
|
|
podsWatcher.Add(pod)
|
|
|
|
time.Sleep(time.Millisecond * 250)
|
2022-05-30 10:10:58 +00:00
|
|
|
}
|
2022-06-01 17:19:55 +00:00
|
|
|
}()
|
2022-05-30 10:10:58 +00:00
|
|
|
|
|
|
|
var buf bytes.Buffer
|
2022-06-01 17:19:55 +00:00
|
|
|
client := logs.KubernetesClient{Interface: clientset}
|
2022-06-01 20:04:20 +00:00
|
|
|
watcher := logs.NewWatcher("mydeployment", "mycontainer", false, client, logs.NewPodWatcher, &buf)
|
2022-05-30 10:10:58 +00:00
|
|
|
|
|
|
|
err := watcher.Watch(ctx)
|
2022-06-07 19:14:07 +00:00
|
|
|
require.EqualError(t, err, context.DeadlineExceeded.Error())
|
|
|
|
lines := bufToLines(&buf)
|
|
|
|
assert.Len(t, lines, 2)
|
|
|
|
assert.ElementsMatch(t, []string{"[foo] fake logs", "[bar] fake logs"}, bufToLines(&buf))
|
2022-06-01 17:19:55 +00:00
|
|
|
}
|
|
|
|
|
2022-06-07 19:14:07 +00:00
|
|
|
func bufToLines(buf *bytes.Buffer) []string {
|
2022-06-01 17:19:55 +00:00
|
|
|
return strings.Split(strings.TrimSpace(buf.String()), "\n")
|
2022-05-30 10:10:58 +00:00
|
|
|
}
|