mirror of https://github.com/tailscale/tailscale/
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
152 lines
4.5 KiB
Go
152 lines
4.5 KiB
Go
1 week ago
|
// Copyright (c) Tailscale Inc & AUTHORS
|
||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||
|
|
||
|
package kubeclient
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"encoding/json"
|
||
|
"net/http"
|
||
|
"testing"
|
||
|
|
||
|
"github.com/google/go-cmp/cmp"
|
||
|
"tailscale.com/kube/kubeapi"
|
||
|
"tailscale.com/tstest"
|
||
|
)
|
||
|
|
||
|
func Test_client_Event(t *testing.T) {
|
||
|
cl := &tstest.Clock{}
|
||
|
tests := []struct {
|
||
|
name string
|
||
|
typ string
|
||
|
reason string
|
||
|
msg string
|
||
|
argSets []args
|
||
|
wantErr bool
|
||
|
}{
|
||
|
{
|
||
|
name: "new_event_gets_created",
|
||
|
typ: "Normal",
|
||
|
reason: "TestReason",
|
||
|
msg: "TestMessage",
|
||
|
argSets: []args{
|
||
|
{ // request to GET event returns not found
|
||
|
wantsMethod: "GET",
|
||
|
wantsURL: "test-apiserver/api/v1/namespaces/test-ns/events/test-pod.test-uid.testreason",
|
||
|
setErr: &kubeapi.Status{Code: 404},
|
||
|
},
|
||
|
{ // sends POST request to create event
|
||
|
wantsMethod: "POST",
|
||
|
wantsURL: "test-apiserver/api/v1/namespaces/test-ns/events",
|
||
|
wantsIn: &kubeapi.Event{
|
||
|
ObjectMeta: kubeapi.ObjectMeta{
|
||
|
Name: "test-pod.test-uid.testreason",
|
||
|
Namespace: "test-ns",
|
||
|
},
|
||
|
Type: "Normal",
|
||
|
Reason: "TestReason",
|
||
|
Message: "TestMessage",
|
||
|
Source: kubeapi.EventSource{
|
||
|
Component: "test-client",
|
||
|
},
|
||
|
InvolvedObject: kubeapi.ObjectReference{
|
||
|
Name: "test-pod",
|
||
|
UID: "test-uid",
|
||
|
Namespace: "test-ns",
|
||
|
APIVersion: "v1",
|
||
|
Kind: "Pod",
|
||
|
},
|
||
|
FirstTimestamp: cl.Now(),
|
||
|
LastTimestamp: cl.Now(),
|
||
|
Count: 1,
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
name: "existing_event_gets_patched",
|
||
|
typ: "Warning",
|
||
|
reason: "TestReason",
|
||
|
msg: "TestMsg",
|
||
|
argSets: []args{
|
||
|
{ // request to GET event does not error - this is enough to assume that event exists
|
||
|
wantsMethod: "GET",
|
||
|
wantsURL: "test-apiserver/api/v1/namespaces/test-ns/events/test-pod.test-uid.testreason",
|
||
|
setOut: []byte(`{"count":2}`),
|
||
|
},
|
||
|
{ // sends PATCH request to update the event
|
||
|
wantsMethod: "PATCH",
|
||
|
wantsURL: "test-apiserver/api/v1/namespaces/test-ns/events/test-pod.test-uid.testreason",
|
||
|
wantsIn: []JSONPatch{
|
||
|
{Op: "replace", Path: "/count", Value: int32(3)},
|
||
|
{Op: "replace", Path: "/lastTimestamp", Value: cl.Now()},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
}
|
||
|
for _, tt := range tests {
|
||
|
t.Run(tt.name, func(t *testing.T) {
|
||
|
c := &client{
|
||
|
cl: cl,
|
||
|
name: "test-client",
|
||
|
podName: "test-pod",
|
||
|
podUID: "test-uid",
|
||
|
url: "test-apiserver",
|
||
|
ns: "test-ns",
|
||
|
kubeAPIRequest: fakeKubeAPIRequest(t, tt.argSets),
|
||
|
hasEventsPerms: true,
|
||
|
}
|
||
|
if err := c.Event(context.Background(), tt.typ, tt.reason, tt.msg); (err != nil) != tt.wantErr {
|
||
|
t.Errorf("client.Event() error = %v, wantErr %v", err, tt.wantErr)
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// args is a set of values for testing a single call to client.kubeAPIRequest.
|
||
|
type args struct {
|
||
|
// wantsMethod is the expected value of 'method' arg.
|
||
|
wantsMethod string
|
||
|
// wantsURL is the expected value of 'url' arg.
|
||
|
wantsURL string
|
||
|
// wantsIn is the expected value of 'in' arg.
|
||
|
wantsIn any
|
||
|
// setOut can be set to a byte slice representing valid JSON. If set 'out' arg will get set to the unmarshalled
|
||
|
// JSON object.
|
||
|
setOut []byte
|
||
|
// setErr is the error that kubeAPIRequest will return.
|
||
|
setErr error
|
||
|
}
|
||
|
|
||
|
// fakeKubeAPIRequest can be used to test that a series of calls to client.kubeAPIRequest gets called with expected
|
||
|
// values and to set these calls to return preconfigured values. 'argSets' should be set to a slice of expected
|
||
|
// arguments and should-be return values of a series of kubeAPIRequest calls.
|
||
|
func fakeKubeAPIRequest(t *testing.T, argSets []args) kubeAPIRequestFunc {
|
||
|
count := 0
|
||
|
f := func(ctx context.Context, gotMethod, gotUrl string, gotIn, gotOut any, opts ...func(*http.Request)) error {
|
||
|
t.Helper()
|
||
|
if count >= len(argSets) {
|
||
|
t.Fatalf("unexpected call to client.kubeAPIRequest, expected %d calls, but got a %dth call", len(argSets), count+1)
|
||
|
}
|
||
|
a := argSets[count]
|
||
|
if gotMethod != a.wantsMethod {
|
||
|
t.Errorf("[%d] got method %q, wants method %q", count, gotMethod, a.wantsMethod)
|
||
|
}
|
||
|
if gotUrl != a.wantsURL {
|
||
|
t.Errorf("[%d] got URL %q, wants URL %q", count, gotMethod, a.wantsMethod)
|
||
|
}
|
||
|
if d := cmp.Diff(gotIn, a.wantsIn); d != "" {
|
||
|
t.Errorf("[%d] unexpected payload (-want + got):\n%s", count, d)
|
||
|
}
|
||
|
if len(a.setOut) != 0 {
|
||
|
if err := json.Unmarshal(a.setOut, gotOut); err != nil {
|
||
|
t.Fatalf("[%d] error unmarshalling output: %v", count, err)
|
||
|
}
|
||
|
}
|
||
|
count++
|
||
|
return a.setErr
|
||
|
}
|
||
|
return f
|
||
|
}
|