diff --git a/pkg/resources/serviceaccount/serviceaccount.go b/pkg/resources/serviceaccount/serviceaccount.go new file mode 100644 index 00000000..43c8e68a --- /dev/null +++ b/pkg/resources/serviceaccount/serviceaccount.go @@ -0,0 +1,78 @@ +/* + * Copyright 2023 The Knative Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package serviceaccount + +import ( + "context" + "embed" + "time" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/wait" + "knative.dev/pkg/client/injection/kube/client" + "knative.dev/reconciler-test/pkg/environment" + "knative.dev/reconciler-test/pkg/feature" + "knative.dev/reconciler-test/pkg/k8s" + "knative.dev/reconciler-test/pkg/manifest" +) + +//go:embed *.yaml +var yaml embed.FS +var WithLabels = manifest.WithLabels +var WithAnnotations = manifest.WithAnnotations + +func Install(name string, opts ...manifest.CfgFn) feature.StepFn { + cfg := map[string]interface{}{ + "name": name, + } + + for _, fn := range opts { + fn(cfg) + } + + return func(ctx context.Context, t feature.T) { + if _, err := manifest.InstallYamlFS(ctx, yaml, cfg); err != nil { + t.Fatal(err) + } + } +} + +// WaitForBeingAvailable waits until the given service account was created by +// some 3rd party +func WaitForBeingAvailable(name string, timing ...time.Duration) feature.StepFn { + return func(ctx context.Context, t feature.T) { + env := environment.FromContext(ctx) + interval, timeout := k8s.PollTimings(ctx, timing) + var lastErr error + + err := wait.PollImmediate(interval, timeout, func() (bool, error) { + _, err := client.Get(ctx). + CoreV1(). + ServiceAccounts(env.Namespace()). + Get(ctx, name, metav1.GetOptions{}) + if err != nil { + lastErr = err + return false, nil + } + + return true, nil + }) + if err != nil { + t.Fatalf("failed to get service account %s/%s: %v. Last error: %v", name, env.Namespace(), err, lastErr) + } + } +} diff --git a/pkg/resources/serviceaccount/serviceaccount.yaml b/pkg/resources/serviceaccount/serviceaccount.yaml new file mode 100644 index 00000000..61122032 --- /dev/null +++ b/pkg/resources/serviceaccount/serviceaccount.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .name }} + namespace: {{ .namespace }} + {{ if .annotations }} + annotations: + {{ range $key, $value := .annotations }} + {{ $key }}: "{{ $value }}" + {{ end }} + {{ end }} + {{ if .labels }} + labels: + {{ range $key, $value := .labels }} + {{ $key }}: "{{ $value }}" + {{ end }} + {{ end }} diff --git a/pkg/resources/serviceaccount/serviceaccount_test.go b/pkg/resources/serviceaccount/serviceaccount_test.go new file mode 100644 index 00000000..47ed24a8 --- /dev/null +++ b/pkg/resources/serviceaccount/serviceaccount_test.go @@ -0,0 +1,90 @@ +/* + * Copyright 2023 The Knative Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package serviceaccount_test + +import ( + "embed" + "os" + + testlog "knative.dev/reconciler-test/pkg/logging" + "knative.dev/reconciler-test/pkg/manifest" + "knative.dev/reconciler-test/pkg/resources/serviceaccount" +) + +//go:embed *.yaml +var yaml embed.FS + +func Example_min() { + ctx := testlog.NewContext() + images := map[string]string{} + cfg := map[string]interface{}{ + "name": "foo", + "namespace": "bar", + } + + files, err := manifest.ExecuteYAML(ctx, yaml, images, cfg) + if err != nil { + panic(err) + } + + manifest.OutputYAML(os.Stdout, files) + // Output: + // apiVersion: v1 + // kind: ServiceAccount + // metadata: + // name: foo + // namespace: bar +} + +func Example_full() { + ctx := testlog.NewContext() + images := map[string]string{} + cfg := map[string]interface{}{ + "name": "foo", + "namespace": "bar", + } + + opts := []manifest.CfgFn{ + serviceaccount.WithLabels(map[string]string{ + "color": "green", + }), + serviceaccount.WithAnnotations(map[string]interface{}{ + "app.kubernetes.io/name": "app", + }), + } + + for _, opt := range opts { + opt(cfg) + } + + files, err := manifest.ExecuteYAML(ctx, yaml, images, cfg) + if err != nil { + panic(err) + } + + manifest.OutputYAML(os.Stdout, files) + // Output: + // apiVersion: v1 + // kind: ServiceAccount + // metadata: + // name: foo + // namespace: bar + // annotations: + // app.kubernetes.io/name: "app" + // labels: + // color: "green" +}