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 requirement to ClusterExtension #1011

Merged
merged 2 commits into from
Jul 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
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
13 changes: 13 additions & 0 deletions api/v1alpha1/clusterextension_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,19 @@ type ClusterExtensionSpec struct {
//+kubebuilder:Optional
// Preflight defines the configuration of preflight checks.
Preflight *PreflightConfig `json:"preflight,omitempty"`

// ServiceAccount is used to install and manage resources.
// The service account is expected to exist in the InstallNamespace.
ServiceAccount ServiceAccountReference `json:"serviceAccount"`
everettraven marked this conversation as resolved.
Show resolved Hide resolved
}

// ServiceAccountReference references a serviceAccount.
type ServiceAccountReference struct {
// name is the metadata.name of the referenced serviceAccount object.
//+kubebuilder:validation:MaxLength:=253
//+kubebuilder:validation:Pattern:=^[a-z0-9]+([.|-][a-z0-9]+)*$
//+kubebuilder:validation:XValidation:rule="self == oldSelf",message="name is immutable"
Name string `json:"name"`
}

// PreflightConfig holds the configuration for the preflight checks.
Expand Down
16 changes: 16 additions & 0 deletions api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,23 @@ spec:
type: boolean
type: object
type: object
serviceAccount:
description: |-
ServiceAccount is used to install and manage resources.
The service account is expected to exist in the InstallNamespace.
properties:
name:
description: name is the metadata.name of the referenced serviceAccount
object.
maxLength: 253
pattern: ^[a-z0-9]+([.|-][a-z0-9]+)*$
type: string
x-kubernetes-validations:
- message: name is immutable
rule: self == oldSelf
required:
- name
type: object
upgradeConstraintPolicy:
default: Enforce
description: Defines the policy for how to handle upgrade constraints
Expand All @@ -93,6 +110,7 @@ spec:
required:
- installNamespace
- packageName
- serviceAccount
type: object
status:
description: ClusterExtensionStatus defines the observed state of ClusterExtension
Expand Down
2 changes: 2 additions & 0 deletions config/samples/olm_v1alpha1_clusterextension.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@ spec:
installNamespace: default
packageName: argocd-operator
version: 0.6.0
serviceAccount:
name: argocd-installer
60 changes: 60 additions & 0 deletions internal/controllers/clusterextension_admission_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ func TestClusterExtensionAdmissionPackageName(t *testing.T) {
err := cl.Create(context.Background(), buildClusterExtension(ocv1alpha1.ClusterExtensionSpec{
PackageName: tc.pkgName,
InstallNamespace: "default",
ServiceAccount: ocv1alpha1.ServiceAccountReference{
Name: "default",
},
}))
if tc.errMsg == "" {
require.NoError(t, err, "unexpected error for package name %q: %w", tc.pkgName, err)
Expand Down Expand Up @@ -134,6 +137,9 @@ func TestClusterExtensionAdmissionVersion(t *testing.T) {
PackageName: "package",
Version: tc.version,
InstallNamespace: "default",
ServiceAccount: ocv1alpha1.ServiceAccountReference{
Name: "default",
},
}))
if tc.errMsg == "" {
require.NoError(t, err, "unexpected error for version %q: %w", tc.version, err)
Expand Down Expand Up @@ -179,6 +185,9 @@ func TestClusterExtensionAdmissionChannel(t *testing.T) {
PackageName: "package",
Channel: tc.channelName,
InstallNamespace: "default",
ServiceAccount: ocv1alpha1.ServiceAccountReference{
Name: "default",
},
}))
if tc.errMsg == "" {
require.NoError(t, err, "unexpected error for channel %q: %w", tc.channelName, err)
Expand Down Expand Up @@ -224,6 +233,9 @@ func TestClusterExtensionAdmissionInstallNamespace(t *testing.T) {
err := cl.Create(context.Background(), buildClusterExtension(ocv1alpha1.ClusterExtensionSpec{
PackageName: "package",
InstallNamespace: tc.installNamespace,
ServiceAccount: ocv1alpha1.ServiceAccountReference{
Name: "default",
},
}))
if tc.errMsg == "" {
require.NoError(t, err, "unexpected error for installNamespace %q: %w", tc.installNamespace, err)
Expand All @@ -235,6 +247,54 @@ func TestClusterExtensionAdmissionInstallNamespace(t *testing.T) {
}
}

func TestClusterExtensionAdmissionServiceAccount(t *testing.T) {
tooLongError := "spec.serviceAccount.name: Too long: may not be longer than 253"
regexMismatchError := "spec.serviceAccount.name in body should match"

testCases := []struct {
name string
serviceAccount string
errMsg string
}{
{"just alphanumeric", "justalphanumeric1", ""},
{"hypen-separated", "hyphenated-name", ""},
{"dot-separated", "dotted.name", ""},
{"longest valid service account name", strings.Repeat("x", 253), ""},
{"too long service account name", strings.Repeat("x", 254), tooLongError},
{"no service account name", "", regexMismatchError},
{"spaces", "spaces spaces", regexMismatchError},
{"capitalized", "Capitalized", regexMismatchError},
{"camel case", "camelCase", regexMismatchError},
{"invalid characters", "many/invalid$characters+in_name", regexMismatchError},
{"starts with hyphen", "-start-with-hyphen", regexMismatchError},
{"ends with hyphen", "end-with-hyphen-", regexMismatchError},
{"starts with period", ".start-with-period", regexMismatchError},
{"ends with period", "end-with-period.", regexMismatchError},
}

t.Parallel()
for _, tc := range testCases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
cl := newClient(t)
err := cl.Create(context.Background(), buildClusterExtension(ocv1alpha1.ClusterExtensionSpec{
PackageName: "package",
InstallNamespace: "default",
ServiceAccount: ocv1alpha1.ServiceAccountReference{
Name: tc.serviceAccount,
},
}))
if tc.errMsg == "" {
require.NoError(t, err, "unexpected error for service account name %q: %w", tc.serviceAccount, err)
} else {
require.Error(t, err)
require.Contains(t, err.Error(), tc.errMsg)
}
})
}
}

func buildClusterExtension(spec ocv1alpha1.ClusterExtensionSpec) *ocv1alpha1.ClusterExtension {
return &ocv1alpha1.ClusterExtension{
ObjectMeta: metav1.ObjectMeta{
Expand Down
47 changes: 47 additions & 0 deletions internal/controllers/clusterextension_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ func TestClusterExtensionNonExistentPackage(t *testing.T) {
Spec: ocv1alpha1.ClusterExtensionSpec{
PackageName: pkgName,
InstallNamespace: "default",
ServiceAccount: ocv1alpha1.ServiceAccountReference{
Name: "default",
},
},
}
require.NoError(t, cl.Create(ctx, clusterExtension))
Expand Down Expand Up @@ -98,6 +101,9 @@ func TestClusterExtensionNonExistentVersion(t *testing.T) {
PackageName: pkgName,
Version: "0.50.0", // this version of the package does not exist
InstallNamespace: "default",
ServiceAccount: ocv1alpha1.ServiceAccountReference{
Name: "default",
},
},
}
require.NoError(t, cl.Create(ctx, clusterExtension))
Expand Down Expand Up @@ -147,6 +153,7 @@ func TestClusterExtensionChannelVersionExists(t *testing.T) {
pkgVer := "1.0.0"
pkgChan := "beta"
installNamespace := fmt.Sprintf("test-ns-%s", rand.String(8))
serviceAccount := fmt.Sprintf("test-sa-%s", rand.String(8))

clusterExtension := &ocv1alpha1.ClusterExtension{
ObjectMeta: metav1.ObjectMeta{Name: extKey.Name},
Expand All @@ -155,6 +162,9 @@ func TestClusterExtensionChannelVersionExists(t *testing.T) {
Version: pkgVer,
Channel: pkgChan,
InstallNamespace: installNamespace,
ServiceAccount: ocv1alpha1.ServiceAccountReference{
Name: serviceAccount,
},
},
}
err := cl.Create(ctx, clusterExtension)
Expand Down Expand Up @@ -206,13 +216,18 @@ func TestClusterExtensionChannelExistsNoVersion(t *testing.T) {
pkgVer := ""
pkgChan := "beta"
installNamespace := fmt.Sprintf("test-ns-%s", rand.String(8))
serviceAccount := fmt.Sprintf("test-sa-%s", rand.String(8))

clusterExtension := &ocv1alpha1.ClusterExtension{
ObjectMeta: metav1.ObjectMeta{Name: extKey.Name},
Spec: ocv1alpha1.ClusterExtensionSpec{
PackageName: pkgName,
Version: pkgVer,
Channel: pkgChan,
InstallNamespace: installNamespace,
ServiceAccount: ocv1alpha1.ServiceAccountReference{
Name: serviceAccount,
},
},
}
err := cl.Create(ctx, clusterExtension)
Expand Down Expand Up @@ -265,6 +280,9 @@ func TestClusterExtensionVersionNoChannel(t *testing.T) {
Version: pkgVer,
Channel: pkgChan,
InstallNamespace: "default",
ServiceAccount: ocv1alpha1.ServiceAccountReference{
Name: "default",
},
},
}
require.NoError(t, cl.Create(ctx, clusterExtension))
Expand Down Expand Up @@ -313,6 +331,9 @@ func TestClusterExtensionNoChannel(t *testing.T) {
PackageName: pkgName,
Channel: pkgChan,
InstallNamespace: "default",
ServiceAccount: ocv1alpha1.ServiceAccountReference{
Name: "default",
},
},
}
require.NoError(t, cl.Create(ctx, clusterExtension))
Expand Down Expand Up @@ -363,6 +384,9 @@ func TestClusterExtensionNoVersion(t *testing.T) {
Version: pkgVer,
Channel: pkgChan,
InstallNamespace: "default",
ServiceAccount: ocv1alpha1.ServiceAccountReference{
Name: "default",
},
},
}
require.NoError(t, cl.Create(ctx, clusterExtension))
Expand Down Expand Up @@ -443,6 +467,7 @@ func TestClusterExtensionUpgrade(t *testing.T) {
pkgVer := "1.0.0"
pkgChan := "beta"
installNamespace := fmt.Sprintf("test-ns-%s", rand.String(8))
serviceAccount := fmt.Sprintf("test-sa-%s", rand.String(8))
extKey := types.NamespacedName{Name: fmt.Sprintf("cluster-extension-test-%s", rand.String(8))}
clusterExtension := &ocv1alpha1.ClusterExtension{
ObjectMeta: metav1.ObjectMeta{Name: extKey.Name},
Expand All @@ -451,6 +476,9 @@ func TestClusterExtensionUpgrade(t *testing.T) {
Version: pkgVer,
Channel: pkgChan,
InstallNamespace: installNamespace,
ServiceAccount: ocv1alpha1.ServiceAccountReference{
Name: serviceAccount,
},
},
}
// Create a cluster extension
Expand Down Expand Up @@ -543,6 +571,7 @@ func TestClusterExtensionUpgrade(t *testing.T) {
pkgVer := "1.0.0"
pkgChan := "beta"
installNamespace := fmt.Sprintf("test-ns-%s", rand.String(8))
serviceAccount := fmt.Sprintf("test-sa-%s", rand.String(8))
extKey := types.NamespacedName{Name: fmt.Sprintf("cluster-extension-test-%s", rand.String(8))}
clusterExtension := &ocv1alpha1.ClusterExtension{
ObjectMeta: metav1.ObjectMeta{Name: extKey.Name},
Expand All @@ -551,6 +580,9 @@ func TestClusterExtensionUpgrade(t *testing.T) {
Version: pkgVer,
Channel: pkgChan,
InstallNamespace: installNamespace,
ServiceAccount: ocv1alpha1.ServiceAccountReference{
Name: serviceAccount,
},
},
}
// Create a cluster extension
Expand Down Expand Up @@ -654,6 +686,7 @@ func TestClusterExtensionUpgrade(t *testing.T) {
}()

installNamespace := fmt.Sprintf("test-ns-%s", rand.String(8))
serviceAccount := fmt.Sprintf("test-sa-%s", rand.String(8))
extKey := types.NamespacedName{Name: fmt.Sprintf("cluster-extension-test-%s", rand.String(8))}
clusterExtension := &ocv1alpha1.ClusterExtension{
ObjectMeta: metav1.ObjectMeta{Name: extKey.Name},
Expand All @@ -663,6 +696,9 @@ func TestClusterExtensionUpgrade(t *testing.T) {
Channel: "beta",
UpgradeConstraintPolicy: ocv1alpha1.UpgradeConstraintPolicyIgnore,
InstallNamespace: installNamespace,
ServiceAccount: ocv1alpha1.ServiceAccountReference{
Name: serviceAccount,
},
},
}
// Create a cluster extension
Expand Down Expand Up @@ -754,6 +790,7 @@ func TestClusterExtensionDowngrade(t *testing.T) {
}()

installNamespace := fmt.Sprintf("test-ns-%s", rand.String(8))
serviceAccount := fmt.Sprintf("test-sa-%s", rand.String(8))
extKey := types.NamespacedName{Name: fmt.Sprintf("cluster-extension-test-%s", rand.String(8))}
clusterExtension := &ocv1alpha1.ClusterExtension{
ObjectMeta: metav1.ObjectMeta{Name: extKey.Name},
Expand All @@ -762,6 +799,9 @@ func TestClusterExtensionDowngrade(t *testing.T) {
Version: "1.0.1",
Channel: "beta",
InstallNamespace: installNamespace,
ServiceAccount: ocv1alpha1.ServiceAccountReference{
Name: serviceAccount,
},
},
}
// Create a cluster extension
Expand Down Expand Up @@ -842,6 +882,7 @@ func TestClusterExtensionDowngrade(t *testing.T) {
}()

installNamespace := fmt.Sprintf("test-ns-%s", rand.String(8))
serviceAccount := fmt.Sprintf("test-sa-%s", rand.String(8))
extKey := types.NamespacedName{Name: fmt.Sprintf("cluster-extension-test-%s", rand.String(8))}
clusterExtension := &ocv1alpha1.ClusterExtension{
ObjectMeta: metav1.ObjectMeta{Name: extKey.Name},
Expand All @@ -851,6 +892,9 @@ func TestClusterExtensionDowngrade(t *testing.T) {
Channel: "beta",
UpgradeConstraintPolicy: ocv1alpha1.UpgradeConstraintPolicyIgnore,
InstallNamespace: installNamespace,
ServiceAccount: ocv1alpha1.ServiceAccountReference{
Name: serviceAccount,
},
},
}
// Create a cluster extension
Expand Down Expand Up @@ -1461,6 +1505,9 @@ func TestClusterExtensionErrorGettingBundles(t *testing.T) {
Spec: ocv1alpha1.ClusterExtensionSpec{
PackageName: "prometheus",
InstallNamespace: "default",
ServiceAccount: ocv1alpha1.ServiceAccountReference{
Name: "default",
},
},
}
require.NoError(t, cl.Create(ctx, clusterExtension))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,12 +121,16 @@ func TestClusterExtensionRegistryV1DisallowDependencies(t *testing.T) {
}

installNamespace := fmt.Sprintf("test-ns-%s", rand.String(8))
serviceAccount := fmt.Sprintf("test-sa-%s", rand.String(8))
extKey := types.NamespacedName{Name: fmt.Sprintf("cluster-extension-test-%s", rand.String(8))}
clusterExtension := &ocv1alpha1.ClusterExtension{
ObjectMeta: metav1.ObjectMeta{Name: extKey.Name},
Spec: ocv1alpha1.ClusterExtensionSpec{
PackageName: tt.bundle.Package,
InstallNamespace: installNamespace,
ServiceAccount: ocv1alpha1.ServiceAccountReference{
Name: serviceAccount,
},
},
}
require.NoError(t, cl.Create(ctx, clusterExtension))
Expand Down
Loading
Loading