Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add service account resource #588

Closed
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions pkg/resources/serviceaccount/options.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* 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 (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

"knative.dev/reconciler-test/pkg/manifest"
)

var (
WithLabels = manifest.WithLabels
WithAnnotations = manifest.WithAnnotations
)

func WithOwnerReferences(refs []metav1.OwnerReference) manifest.CfgFn {
return func(cfg map[string]interface{}) {
if refs != nil {
cfg["ownerReferences"] = refs
}
}
}
creydr marked this conversation as resolved.
Show resolved Hide resolved
76 changes: 76 additions & 0 deletions pkg/resources/serviceaccount/serviceaccount.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
* 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

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 {
Comment on lines +54 to +56
Copy link
Member

@pierDipi pierDipi Sep 26, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is to very that a given resource like "trigger" has created a service account?

Copy link
Member

@pierDipi pierDipi Sep 26, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally, we don't enter in such implementation details in E2E tests, the contract and therefore the E2E behavior we need to verify is that "the subscriber will receive a JWT token emitted by the k8s configured issuer", the SA is the means we use for that but I think we should verify that the subscriber is receiving such tokens not that a SA is created (that's an implementation detail)

Copy link
Contributor Author

@creydr creydr Sep 26, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is to very that a given resource like "trigger" has created a service account?

Yes.

Ideally, we don't enter in such implementation details in E2E tests

hmmm. I see your point, but how would you check then, that e.g. the trigger reconciler really creates the OIDC SA?

Copy link
Member

@pierDipi pierDipi Sep 26, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would verify that the token you receive in the eventshub subscriber is what you expect (you need to do that anyway since that actually tests everything E2E, data plane included)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

basically, we don't check "The SA is created" but "the token with the SA identity is received" and that's transitively testing that the SA exists

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)
}
}
}
32 changes: 32 additions & 0 deletions pkg/resources/serviceaccount/serviceaccount.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
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 }}
{{ if .ownerReferences }}
ownerReferences:
{{ range .ownerReferences }}
- apiVersion: {{ .APIVersion }}
kind: {{ .Kind }}
name: {{ .Name }}
uid: {{ .UID }}
{{ if .Controller }}
controller: true
{{ end }}
{{ if .BlockOwnerDeletion }}
blockOwnerDeletion: true
{{ end }}
{{ end }}
{{ end }}
107 changes: 107 additions & 0 deletions pkg/resources/serviceaccount/serviceaccount_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*
* 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"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
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",
}

controller := true
opts := []manifest.CfgFn{
serviceaccount.WithLabels(map[string]string{
"color": "green",
}),
serviceaccount.WithAnnotations(map[string]interface{}{
"app.kubernetes.io/name": "app",
}),
serviceaccount.WithOwnerReferences([]metav1.OwnerReference{
{
APIVersion: "eventing.knative.dev/v1",
Kind: "Trigger",
Name: "my-trigger",
UID: "my-trigger-uid",
Controller: &controller,
},
}),
}

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"
// ownerReferences:
// - apiVersion: eventing.knative.dev/v1
// kind: Trigger
// name: my-trigger
// uid: my-trigger-uid
// controller: true
}
Loading