client-go: make fake Pods.GetLogs honor reactors

Kubernetes-commit: 3d41b434c0e88e9f74e38fe654d7b5bfd77090d0
This commit is contained in:
dhruv7539
2026-02-22 14:47:29 -08:00
committed by Kubernetes Publisher
parent efbad1b7ed
commit e8eab37058
2 changed files with 95 additions and 10 deletions

View File

@@ -17,16 +17,17 @@ limitations under the License.
package fake
import (
"bytes"
"context"
"fmt"
"io"
"net/http"
"strings"
v1 "k8s.io/api/core/v1"
policyv1 "k8s.io/api/policy/v1"
policyv1beta1 "k8s.io/api/policy/v1beta1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/kubernetes/scheme"
restclient "k8s.io/client-go/rest"
fakerest "k8s.io/client-go/rest/fake"
@@ -55,20 +56,45 @@ func (c *fakePods) GetBinding(name string) (result *v1.Binding, err error) {
return obj.(*v1.Binding), err
}
func (c *fakePods) GetLogs(name string, opts *v1.PodLogOptions) *restclient.Request {
action := core.GenericActionImpl{}
action.Verb = "get"
action.Namespace = c.Namespace()
action.Resource = c.Resource()
action.Subresource = "log"
action.Value = opts
// getPodLogsActionImpl carries the standard get action shape (including pod name)
// along with pod log options so reactors can inspect both.
type getPodLogsActionImpl struct {
core.GetActionImpl
Value interface{}
}
func (a getPodLogsActionImpl) GetValue() interface{} {
return a.Value
}
func (a getPodLogsActionImpl) DeepCopy() core.Action {
return getPodLogsActionImpl{
GetActionImpl: a.GetActionImpl.DeepCopy().(core.GetActionImpl),
// Keep existing fake GenericAction semantics for value copying.
Value: a.Value,
}
}
func (c *fakePods) GetLogs(name string, opts *v1.PodLogOptions) *restclient.Request {
action := getPodLogsActionImpl{
GetActionImpl: core.NewGetSubresourceAction(c.Resource(), c.Namespace(), "log", name),
Value: opts,
}
obj, err := c.Fake.Invokes(action, &runtime.Unknown{Raw: []byte("fake logs")})
logs := []byte("fake logs")
if unknown, ok := obj.(*runtime.Unknown); ok && unknown != nil {
logs = unknown.Raw
}
_, _ = c.Fake.Invokes(action, &v1.Pod{})
fakeClient := &fakerest.RESTClient{
Client: fakerest.CreateHTTPClient(func(request *http.Request) (*http.Response, error) {
if err != nil {
return nil, err
}
resp := &http.Response{
StatusCode: http.StatusOK,
Body: io.NopCloser(strings.NewReader("fake logs")),
Body: io.NopCloser(bytes.NewReader(logs)),
}
return resp, nil
}),

View File

@@ -19,10 +19,12 @@ package fake
import (
"bytes"
"context"
"errors"
"io"
"testing"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
cgtesting "k8s.io/client-go/testing"
)
@@ -46,3 +48,60 @@ func TestFakePodsGetLogs(t *testing.T) {
t.Fatal("Close response body:", err)
}
}
func TestFakePodsGetLogsReactorError(t *testing.T) {
fake := &cgtesting.Fake{}
fp := newFakePods(&FakeCoreV1{Fake: fake}, "default")
expectedErr := errors.New("reactor get logs failure")
fake.PrependReactor("get", "pods/log", func(action cgtesting.Action) (bool, runtime.Object, error) {
getAction, ok := action.(cgtesting.GetAction)
if !ok {
t.Fatalf("expected GetAction, got %T", action)
}
if getAction.GetName() != "foo" {
t.Fatalf("expected pod name foo, got %q", getAction.GetName())
}
genericAction, ok := action.(cgtesting.GenericAction)
if !ok {
t.Fatalf("expected GenericAction, got %T", action)
}
opts, ok := genericAction.GetValue().(*corev1.PodLogOptions)
if !ok {
t.Fatalf("expected *corev1.PodLogOptions, got %T", genericAction.GetValue())
}
if opts.Container != "ctr" {
t.Fatalf("expected container ctr, got %q", opts.Container)
}
return true, nil, expectedErr
})
req := fp.GetLogs("foo", &corev1.PodLogOptions{Container: "ctr"})
_, err := req.Stream(context.Background())
if !errors.Is(err, expectedErr) {
t.Fatalf("expected stream error %v, got %v", expectedErr, err)
}
}
func TestFakePodsGetLogsReactorResponse(t *testing.T) {
fake := &cgtesting.Fake{}
fp := newFakePods(&FakeCoreV1{Fake: fake}, "default")
expectedLogs := "reactor logs"
fake.PrependReactor("get", "pods/log", func(action cgtesting.Action) (bool, runtime.Object, error) {
return true, &runtime.Unknown{Raw: []byte(expectedLogs)}, nil
})
req := fp.GetLogs("foo", &corev1.PodLogOptions{})
body, err := req.Stream(context.Background())
if err != nil {
t.Fatalf("Stream pod logs: %v", err)
}
defer body.Close()
logs, err := io.ReadAll(body)
if err != nil {
t.Fatalf("Read pod logs: %v", err)
}
if string(logs) != expectedLogs {
t.Fatalf("expected logs %q, got %q", expectedLogs, string(logs))
}
}