-
Notifications
You must be signed in to change notification settings - Fork 84
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
mockkubeapiserver: Support stringData when creating a secret
This is an edge case in the kube apiserver, but there is special handling for the stringData field of a secret, that is mapped to base64 data. Co-authored-by: Tomas Aschan <1550920+tomasaschan@users.noreply.github.com>
- Loading branch information
1 parent
a248ed1
commit 7a17600
Showing
9 changed files
with
278 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
package applier | ||
|
||
import ( | ||
"context" | ||
"net/http" | ||
"path/filepath" | ||
"testing" | ||
|
||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
"k8s.io/client-go/dynamic" | ||
"k8s.io/client-go/rest" | ||
"k8s.io/klog/v2" | ||
"sigs.k8s.io/kubebuilder-declarative-pattern/mockkubeapiserver" | ||
"sigs.k8s.io/kubebuilder-declarative-pattern/pkg/patterns/declarative/pkg/manifest" | ||
"sigs.k8s.io/kubebuilder-declarative-pattern/pkg/restmapper" | ||
"sigs.k8s.io/kubebuilder-declarative-pattern/pkg/test/httprecorder" | ||
"sigs.k8s.io/kubebuilder-declarative-pattern/pkg/test/testharness" | ||
) | ||
|
||
func TestGoldenTests(t *testing.T) { | ||
testharness.RunGoldenTests(t, "testdata", func(h *testharness.Harness, testdir string) { | ||
ctx := context.Background() | ||
|
||
k8s, err := mockkubeapiserver.NewMockKubeAPIServer(":0") | ||
if err != nil { | ||
t.Fatalf("error building mock kube-apiserver: %v", err) | ||
} | ||
defer func() { | ||
if err := k8s.Stop(); err != nil { | ||
t.Fatalf("error closing mock kube-apiserver: %v", err) | ||
} | ||
}() | ||
|
||
addr, err := k8s.StartServing() | ||
if err != nil { | ||
t.Errorf("error starting mock kube-apiserver: %v", err) | ||
} | ||
|
||
klog.Infof("mock kubeapiserver will listen on %v", addr) | ||
|
||
var requestLog httprecorder.RequestLog | ||
wrapTransport := func(rt http.RoundTripper) http.RoundTripper { | ||
return httprecorder.NewRecorder(rt, &requestLog) | ||
} | ||
restConfig := &rest.Config{ | ||
Host: addr.String(), | ||
WrapTransport: wrapTransport, | ||
} | ||
|
||
httpClient := &http.Client{} | ||
|
||
httpClient.Transport = wrapTransport(http.DefaultTransport) | ||
|
||
// var apiserverRequestLog httprecorder.RequestLog | ||
// if interceptHTTPServer { | ||
// k8s.AddHook(&logKubeRequestsHook{log: &apiserverRequestLog}) | ||
// } | ||
|
||
p := filepath.Join(testdir, "manifest.yaml") | ||
manifestYAML := string(h.MustReadFile(p)) | ||
objects, err := manifest.ParseObjects(ctx, manifestYAML) | ||
if err != nil { | ||
t.Errorf("error parsing manifest %q: %v", p, err) | ||
} | ||
|
||
restMapper, err := restmapper.NewForTest(restConfig) | ||
if err != nil { | ||
t.Fatalf("error from controllerrestmapper.NewForTest: %v", err) | ||
} | ||
|
||
dynamicClient, err := dynamic.NewForConfigAndClient(restConfig, httpClient) | ||
if err != nil { | ||
t.Fatalf("building dynamic client: %v", err) | ||
} | ||
for _, obj := range objects.GetItems() { | ||
gvk := obj.GroupVersionKind() | ||
restMapping, err := restMapper.RESTMapping(gvk.GroupKind(), gvk.Version) | ||
if err != nil { | ||
t.Errorf("error getting restmapping for %v: %v", gvk, err) | ||
} | ||
|
||
var applyOptions metav1.ApplyOptions | ||
applyOptions.FieldManager = "test" | ||
resource := dynamicClient.Resource(restMapping.Resource).Namespace(obj.GetNamespace()) | ||
|
||
if _, err := resource.Apply(ctx, obj.GetName(), obj.UnstructuredObject(), applyOptions); err != nil { | ||
t.Fatalf("error applying resource %v: %v", gvk, err) | ||
} | ||
} | ||
|
||
t.Logf("replacing old url prefix %q", "http://"+restConfig.Host) | ||
requestLog.ReplaceURLPrefix("http://"+restConfig.Host, "http://kube-apiserver") | ||
requestLog.RemoveUserAgent() | ||
requestLog.SortGETs() | ||
|
||
requests := requestLog.FormatHTTP() | ||
h.CompareGoldenFile(filepath.Join(testdir, "expected.yaml"), requests) | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
GET http://kube-apiserver/api/v1 | ||
Accept: application/json, */* | ||
|
||
200 OK | ||
Cache-Control: no-cache, private | ||
Content-Length: 1820 | ||
Content-Type: application/json | ||
Date: (removed) | ||
|
||
{"kind":"APIResourceList","apiVersion":"v1","groupVersion":"v1","resources":[{"name":"componentstatuses","singularName":"","namespaced":false,"version":"v1","kind":"ComponentStatus","verbs":null},{"name":"configmaps","singularName":"","namespaced":true,"version":"v1","kind":"ConfigMap","verbs":null},{"name":"endpoints","singularName":"","namespaced":true,"version":"v1","kind":"Endpoints","verbs":null},{"name":"events","singularName":"","namespaced":true,"version":"v1","kind":"Event","verbs":null},{"name":"limitranges","singularName":"","namespaced":true,"version":"v1","kind":"LimitRange","verbs":null},{"name":"namespaces","singularName":"","namespaced":false,"version":"v1","kind":"Namespace","verbs":null},{"name":"nodes","singularName":"","namespaced":false,"version":"v1","kind":"Node","verbs":null},{"name":"persistentvolumes","singularName":"","namespaced":false,"version":"v1","kind":"PersistentVolume","verbs":null},{"name":"persistentvolumeclaims","singularName":"","namespaced":true,"version":"v1","kind":"PersistentVolumeClaim","verbs":null},{"name":"pods","singularName":"","namespaced":true,"version":"v1","kind":"Pod","verbs":null},{"name":"podtemplates","singularName":"","namespaced":true,"version":"v1","kind":"PodTemplate","verbs":null},{"name":"replicationcontrollers","singularName":"","namespaced":true,"version":"v1","kind":"ReplicationController","verbs":null},{"name":"resourcequotas","singularName":"","namespaced":true,"version":"v1","kind":"ResourceQuota","verbs":null},{"name":"secrets","singularName":"","namespaced":true,"version":"v1","kind":"Secret","verbs":null},{"name":"services","singularName":"","namespaced":true,"version":"v1","kind":"Service","verbs":null},{"name":"serviceaccounts","singularName":"","namespaced":true,"version":"v1","kind":"ServiceAccount","verbs":null}]} | ||
|
||
--- | ||
|
||
PATCH http://kube-apiserver/api/v1/namespaces/default?fieldManager=test&force=false | ||
Accept: application/json | ||
Content-Type: application/apply-patch+yaml | ||
|
||
{"apiVersion":"v1","kind":"Namespace","metadata":{"name":"default"}} | ||
|
||
|
||
200 OK | ||
Cache-Control: no-cache, private | ||
Content-Length: 294 | ||
Content-Type: application/json | ||
Date: (removed) | ||
|
||
{"apiVersion":"v1","kind":"Namespace","metadata":{"creationTimestamp":"2022-01-01T00:00:00Z","labels":{"kubernetes.io/metadata.name":"default"},"name":"default","resourceVersion":"1","uid":"00000000-0000-0000-0000-000000000001"},"spec":{"finalizers":["kubernetes"]},"status":{"phase":"Active"}} | ||
|
||
--- | ||
|
||
PATCH http://kube-apiserver/api/v1/namespaces/default/configmaps/config?fieldManager=test&force=false | ||
Accept: application/json | ||
Content-Type: application/apply-patch+yaml | ||
|
||
{"apiVersion":"v1","data":{"foo":"bar"},"kind":"ConfigMap","metadata":{"name":"config","namespace":"default"}} | ||
|
||
|
||
200 OK | ||
Cache-Control: no-cache, private | ||
Content-Length: 220 | ||
Content-Type: application/json | ||
Date: (removed) | ||
|
||
{"apiVersion":"v1","data":{"foo":"bar"},"kind":"ConfigMap","metadata":{"creationTimestamp":"2022-01-01T00:00:01Z","name":"config","namespace":"default","resourceVersion":"2","uid":"00000000-0000-0000-0000-000000000002"}} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
kind: Namespace | ||
apiVersion: v1 | ||
metadata: | ||
name: default | ||
|
||
--- | ||
|
||
kind: ConfigMap | ||
apiVersion: v1 | ||
metadata: | ||
name: config | ||
namespace: default | ||
data: | ||
foo: bar |
44 changes: 44 additions & 0 deletions
44
mockkubeapiserver/tests/testdata/secrets_stringdata/expected.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
GET http://kube-apiserver/api/v1 | ||
Accept: application/json, */* | ||
|
||
200 OK | ||
Cache-Control: no-cache, private | ||
Content-Length: 1820 | ||
Content-Type: application/json | ||
Date: (removed) | ||
|
||
{"kind":"APIResourceList","apiVersion":"v1","groupVersion":"v1","resources":[{"name":"componentstatuses","singularName":"","namespaced":false,"version":"v1","kind":"ComponentStatus","verbs":null},{"name":"configmaps","singularName":"","namespaced":true,"version":"v1","kind":"ConfigMap","verbs":null},{"name":"endpoints","singularName":"","namespaced":true,"version":"v1","kind":"Endpoints","verbs":null},{"name":"events","singularName":"","namespaced":true,"version":"v1","kind":"Event","verbs":null},{"name":"limitranges","singularName":"","namespaced":true,"version":"v1","kind":"LimitRange","verbs":null},{"name":"namespaces","singularName":"","namespaced":false,"version":"v1","kind":"Namespace","verbs":null},{"name":"nodes","singularName":"","namespaced":false,"version":"v1","kind":"Node","verbs":null},{"name":"persistentvolumes","singularName":"","namespaced":false,"version":"v1","kind":"PersistentVolume","verbs":null},{"name":"persistentvolumeclaims","singularName":"","namespaced":true,"version":"v1","kind":"PersistentVolumeClaim","verbs":null},{"name":"pods","singularName":"","namespaced":true,"version":"v1","kind":"Pod","verbs":null},{"name":"podtemplates","singularName":"","namespaced":true,"version":"v1","kind":"PodTemplate","verbs":null},{"name":"replicationcontrollers","singularName":"","namespaced":true,"version":"v1","kind":"ReplicationController","verbs":null},{"name":"resourcequotas","singularName":"","namespaced":true,"version":"v1","kind":"ResourceQuota","verbs":null},{"name":"secrets","singularName":"","namespaced":true,"version":"v1","kind":"Secret","verbs":null},{"name":"services","singularName":"","namespaced":true,"version":"v1","kind":"Service","verbs":null},{"name":"serviceaccounts","singularName":"","namespaced":true,"version":"v1","kind":"ServiceAccount","verbs":null}]} | ||
|
||
--- | ||
|
||
PATCH http://kube-apiserver/api/v1/namespaces/default?fieldManager=test&force=false | ||
Accept: application/json | ||
Content-Type: application/apply-patch+yaml | ||
|
||
{"apiVersion":"v1","kind":"Namespace","metadata":{"name":"default"}} | ||
|
||
|
||
200 OK | ||
Cache-Control: no-cache, private | ||
Content-Length: 294 | ||
Content-Type: application/json | ||
Date: (removed) | ||
|
||
{"apiVersion":"v1","kind":"Namespace","metadata":{"creationTimestamp":"2022-01-01T00:00:00Z","labels":{"kubernetes.io/metadata.name":"default"},"name":"default","resourceVersion":"1","uid":"00000000-0000-0000-0000-000000000001"},"spec":{"finalizers":["kubernetes"]},"status":{"phase":"Active"}} | ||
|
||
--- | ||
|
||
PATCH http://kube-apiserver/api/v1/namespaces/default/secrets/secret?fieldManager=test&force=false | ||
Accept: application/json | ||
Content-Type: application/apply-patch+yaml | ||
|
||
{"apiVersion":"v1","kind":"Secret","metadata":{"name":"secret","namespace":"default"},"stringData":{"foo":"bar","foo2":"bar2"},"type":"Opaque"} | ||
|
||
|
||
200 OK | ||
Cache-Control: no-cache, private | ||
Content-Length: 252 | ||
Content-Type: application/json | ||
Date: (removed) | ||
|
||
{"apiVersion":"v1","data":{"foo":"YmFy","foo2":"YmFyMg=="},"kind":"Secret","metadata":{"creationTimestamp":"2022-01-01T00:00:01Z","name":"secret","namespace":"default","resourceVersion":"2","uid":"00000000-0000-0000-0000-000000000002"},"type":"Opaque"} |
16 changes: 16 additions & 0 deletions
16
mockkubeapiserver/tests/testdata/secrets_stringdata/manifest.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
kind: Namespace | ||
apiVersion: v1 | ||
metadata: | ||
name: default | ||
|
||
--- | ||
|
||
kind: Secret | ||
apiVersion: v1 | ||
metadata: | ||
name: secret | ||
namespace: default | ||
type: Opaque | ||
stringData: | ||
foo: bar | ||
foo2: bar2 |