From 2383b1ebf0ebe2d012f9ebe867af537a260c0827 Mon Sep 17 00:00:00 2001 From: Joshua Casey Date: Thu, 26 Dec 2024 12:58:00 -0600 Subject: [PATCH 1/6] Extract common prefix from error messages --- ...supervisor_federationdomain_status_test.go | 81 ++++++------------- 1 file changed, 24 insertions(+), 57 deletions(-) diff --git a/test/integration/supervisor_federationdomain_status_test.go b/test/integration/supervisor_federationdomain_status_test.go index 3ea4ea76c..14d209053 100644 --- a/test/integration/supervisor_federationdomain_status_test.go +++ b/test/integration/supervisor_federationdomain_status_test.go @@ -587,9 +587,7 @@ func TestSupervisorFederationDomainCRDValidations_Parallel(t *testing.T) { Issuer: "", }, }, - wantErr: fmt.Sprintf("FederationDomain.config.supervisor.%s %q is invalid: "+ - `spec.issuer: Invalid value: "": spec.issuer in body should be at least 1 chars long`, - env.APIGroupSuffix, objectMeta.Name), + wantErr: `spec.issuer: Invalid value: "": spec.issuer in body should be at least 1 chars long`, }, { name: "IDP display names cannot be empty", @@ -607,10 +605,7 @@ func TestSupervisorFederationDomainCRDValidations_Parallel(t *testing.T) { }, }, }, - wantErr: fmt.Sprintf("FederationDomain.config.supervisor.%s %q is invalid: "+ - `spec.identityProviders[0].displayName: Invalid value: "": `+ - "spec.identityProviders[0].displayName in body should be at least 1 chars long", - env.APIGroupSuffix, objectMeta.Name), + wantErr: `spec.identityProviders[0].displayName: Invalid value: "": spec.identityProviders[0].displayName in body should be at least 1 chars long`, }, { name: "IDP transform constants must have unique names", @@ -634,12 +629,7 @@ func TestSupervisorFederationDomainCRDValidations_Parallel(t *testing.T) { }, }, }, - wantKube23OrOlderErr: fmt.Sprintf("FederationDomain.config.supervisor.%s %q is invalid: "+ - `spec.identityProviders[0].transforms.constants[1]: Duplicate value: map[string]interface {}{"name":"notUnique"}`, - env.APIGroupSuffix, objectMeta.Name), - wantErr: fmt.Sprintf("FederationDomain.config.supervisor.%s %q is invalid: "+ - `spec.identityProviders[0].transforms.constants[1]: Duplicate value: map[string]interface {}{"name":"notUnique"}`, - env.APIGroupSuffix, objectMeta.Name), + wantErr: `spec.identityProviders[0].transforms.constants[1]: Duplicate value: map[string]interface {}{"name":"notUnique"}`, }, { name: "IDP transform constant names cannot be empty", @@ -662,10 +652,7 @@ func TestSupervisorFederationDomainCRDValidations_Parallel(t *testing.T) { }, }, }, - wantErr: fmt.Sprintf("FederationDomain.config.supervisor.%s %q is invalid: "+ - `spec.identityProviders[0].transforms.constants[0].name: Invalid value: "": `+ - `spec.identityProviders[0].transforms.constants[0].name in body should be at least 1 chars long`, - env.APIGroupSuffix, objectMeta.Name), + wantErr: `spec.identityProviders[0].transforms.constants[0].name: Invalid value: "": spec.identityProviders[0].transforms.constants[0].name in body should be at least 1 chars long`, }, { name: "IDP transform constant names cannot be more than 64 characters", @@ -688,16 +675,9 @@ func TestSupervisorFederationDomainCRDValidations_Parallel(t *testing.T) { }, }, }, - wantKube23OrOlderErr: fmt.Sprintf("FederationDomain.config.supervisor.%s %q is invalid: "+ - `spec.identityProviders.transforms.constants.name: Invalid value: "12345678901234567890123456789012345678901234567890123456789012345": `+ - `spec.identityProviders.transforms.constants.name in body should be at most 64 chars long`, - env.APIGroupSuffix, objectMeta.Name), - wantKube24Through31InclusiveErr: fmt.Sprintf("FederationDomain.config.supervisor.%s %q is invalid: "+ - `spec.identityProviders[0].transforms.constants[0].name: Too long: may not be longer than 64`, - env.APIGroupSuffix, objectMeta.Name), - wantKube32OrNewerErr: fmt.Sprintf("FederationDomain.config.supervisor.%s %q is invalid: "+ - `spec.identityProviders[0].transforms.constants[0].name: Too long: may not be more than 64 bytes`, - env.APIGroupSuffix, objectMeta.Name), + wantKube23OrOlderErr: `spec.identityProviders.transforms.constants.name: Invalid value: "12345678901234567890123456789012345678901234567890123456789012345": spec.identityProviders.transforms.constants.name in body should be at most 64 chars long`, + wantKube24Through31InclusiveErr: `spec.identityProviders[0].transforms.constants[0].name: Too long: may not be longer than 64`, + wantKube32OrNewerErr: `spec.identityProviders[0].transforms.constants[0].name: Too long: may not be more than 64 bytes`, }, { name: "IDP transform constant names must be a legal CEL variable name", @@ -724,18 +704,13 @@ func TestSupervisorFederationDomainCRDValidations_Parallel(t *testing.T) { }, }, }, - wantKube23OrOlderErr: fmt.Sprintf("FederationDomain.config.supervisor.%s %q is invalid: "+ - `spec.identityProviders.transforms.constants.name: Invalid value: "cannot have spaces": `+ - `spec.identityProviders.transforms.constants.name in body should match '^[a-zA-Z][_a-zA-Z0-9]*$'`, - env.APIGroupSuffix, objectMeta.Name), - wantErr: fmt.Sprintf("FederationDomain.config.supervisor.%s %q is invalid: "+ - `[spec.identityProviders[0].transforms.constants[0].name: Invalid value: "cannot have spaces": `+ - `spec.identityProviders[0].transforms.constants[0].name in body should match '^[a-zA-Z][_a-zA-Z0-9]*$', `+ - `spec.identityProviders[0].transforms.constants[1].name: Invalid value: "1mustStartWithLetter": `+ - `spec.identityProviders[0].transforms.constants[1].name in body should match '^[a-zA-Z][_a-zA-Z0-9]*$', `+ - `spec.identityProviders[0].transforms.constants[2].name: Invalid value: "_mustStartWithLetter": `+ + wantKube23OrOlderErr: `spec.identityProviders.transforms.constants.name: Invalid value: "cannot have spaces": spec.identityProviders.transforms.constants.name in body should match '^[a-zA-Z][_a-zA-Z0-9]*$'`, + wantErr: `[spec.identityProviders[0].transforms.constants[0].name: Invalid value: "cannot have spaces": ` + + `spec.identityProviders[0].transforms.constants[0].name in body should match '^[a-zA-Z][_a-zA-Z0-9]*$', ` + + `spec.identityProviders[0].transforms.constants[1].name: Invalid value: "1mustStartWithLetter": ` + + `spec.identityProviders[0].transforms.constants[1].name in body should match '^[a-zA-Z][_a-zA-Z0-9]*$', ` + + `spec.identityProviders[0].transforms.constants[2].name: Invalid value: "_mustStartWithLetter": ` + `spec.identityProviders[0].transforms.constants[2].name in body should match '^[a-zA-Z][_a-zA-Z0-9]*$']`, - env.APIGroupSuffix, objectMeta.Name), }, { name: "IDP transform constant types must be one of the allowed enum strings", @@ -760,10 +735,7 @@ func TestSupervisorFederationDomainCRDValidations_Parallel(t *testing.T) { }, }, }, - wantErr: fmt.Sprintf("FederationDomain.config.supervisor.%s %q is invalid: "+ - `spec.identityProviders[0].transforms.constants[0].type: Unsupported value: "this is invalid": `+ - `supported values: "string", "stringList"`, - env.APIGroupSuffix, objectMeta.Name), + wantErr: `spec.identityProviders[0].transforms.constants[0].type: Unsupported value: "this is invalid": supported values: "string", "stringList"`, }, { name: "IDP transform expression types must be one of the allowed enum strings", @@ -789,10 +761,7 @@ func TestSupervisorFederationDomainCRDValidations_Parallel(t *testing.T) { }, }, }, - wantErr: fmt.Sprintf("FederationDomain.config.supervisor.%s %q is invalid: "+ - `spec.identityProviders[0].transforms.expressions[0].type: Unsupported value: "this is invalid": `+ - `supported values: "policy/v1", "username/v1", "groups/v1"`, - env.APIGroupSuffix, objectMeta.Name), + wantErr: `spec.identityProviders[0].transforms.expressions[0].type: Unsupported value: "this is invalid": supported values: "policy/v1", "username/v1", "groups/v1"`, }, { name: "IDP transform expressions cannot be empty", @@ -815,10 +784,7 @@ func TestSupervisorFederationDomainCRDValidations_Parallel(t *testing.T) { }, }, }, - wantErr: fmt.Sprintf("FederationDomain.config.supervisor.%s %q is invalid: "+ - `spec.identityProviders[0].transforms.expressions[0].expression: Invalid value: "": `+ - `spec.identityProviders[0].transforms.expressions[0].expression in body should be at least 1 chars long`, - env.APIGroupSuffix, objectMeta.Name), + wantErr: `spec.identityProviders[0].transforms.expressions[0].expression: Invalid value: "": spec.identityProviders[0].transforms.expressions[0].expression in body should be at least 1 chars long`, }, { name: "IDP transform example usernames cannot be empty", @@ -842,10 +808,7 @@ func TestSupervisorFederationDomainCRDValidations_Parallel(t *testing.T) { }, }, }, - wantErr: fmt.Sprintf("FederationDomain.config.supervisor.%s %q is invalid: "+ - `spec.identityProviders[0].transforms.examples[0].username: Invalid value: "": `+ - `spec.identityProviders[0].transforms.examples[0].username in body should be at least 1 chars long`, - env.APIGroupSuffix, objectMeta.Name), + wantErr: `spec.identityProviders[0].transforms.examples[0].username: Invalid value: "": spec.identityProviders[0].transforms.examples[0].username in body should be at least 1 chars long`, }, { name: "minimum valid", @@ -908,7 +871,7 @@ func TestSupervisorFederationDomainCRDValidations_Parallel(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() - _, createErr := fdClient.Create(ctx, tt.fd, metav1.CreateOptions{}) + _, actualCreateErr := fdClient.Create(ctx, tt.fd, metav1.CreateOptions{}) t.Cleanup(func() { // Delete it if it exists. @@ -924,7 +887,7 @@ func TestSupervisorFederationDomainCRDValidations_Parallel(t *testing.T) { if tt.wantErr == "" && tt.wantKube23OrOlderErr == "" && tt.wantKube24Through31InclusiveErr == "" && tt.wantKube32OrNewerErr == "" { //nolint:nestif // Did not want any error. - require.NoError(t, createErr) + require.NoError(t, actualCreateErr) } else { wantErr := tt.wantErr if usingKubeVersionInCluster23OrOlder { @@ -950,7 +913,11 @@ func TestSupervisorFederationDomainCRDValidations_Parallel(t *testing.T) { // Also allow overriding with an exact expected error for these Kube versions. wantErr = tt.wantKube32OrNewerErr } - require.EqualError(t, createErr, wantErr) + + wantErr = fmt.Sprintf("FederationDomain.config.supervisor.%s %q is invalid: %s", + env.APIGroupSuffix, objectMeta.Name, wantErr) + + require.EqualError(t, actualCreateErr, wantErr) } }) } From 52d34b7071139abbd06e1d073f46236de9efc640 Mon Sep 17 00:00:00 2001 From: Joshua Casey Date: Thu, 26 Dec 2024 13:20:50 -0600 Subject: [PATCH 2/6] Allow for multiple error messages --- ...supervisor_federationdomain_status_test.go | 82 ++++++++++--------- 1 file changed, 44 insertions(+), 38 deletions(-) diff --git a/test/integration/supervisor_federationdomain_status_test.go b/test/integration/supervisor_federationdomain_status_test.go index 14d209053..639ee164a 100644 --- a/test/integration/supervisor_federationdomain_status_test.go +++ b/test/integration/supervisor_federationdomain_status_test.go @@ -570,14 +570,14 @@ func TestSupervisorFederationDomainCRDValidations_Parallel(t *testing.T) { objectMeta := testlib.ObjectMetaWithRandomName(t, "federation-domain") tests := []struct { - name string - fd *supervisorconfigv1alpha1.FederationDomain - wantErr string + name string + fd *supervisorconfigv1alpha1.FederationDomain + wantErrs []string // optionally override wantErr for one or more specific versions of Kube, due to changing validation error text - wantKube23OrOlderErr string - wantKube24Through31InclusiveErr string - wantKube32OrNewerErr string + wantKube23OrOlderErrs []string + wantKube24Through31InclusiveErrs []string + wantKube32OrNewerErrs []string }{ { name: "issuer cannot be empty", @@ -587,7 +587,7 @@ func TestSupervisorFederationDomainCRDValidations_Parallel(t *testing.T) { Issuer: "", }, }, - wantErr: `spec.issuer: Invalid value: "": spec.issuer in body should be at least 1 chars long`, + wantErrs: []string{`spec.issuer: Invalid value: "": spec.issuer in body should be at least 1 chars long`}, }, { name: "IDP display names cannot be empty", @@ -605,7 +605,7 @@ func TestSupervisorFederationDomainCRDValidations_Parallel(t *testing.T) { }, }, }, - wantErr: `spec.identityProviders[0].displayName: Invalid value: "": spec.identityProviders[0].displayName in body should be at least 1 chars long`, + wantErrs: []string{`spec.identityProviders[0].displayName: Invalid value: "": spec.identityProviders[0].displayName in body should be at least 1 chars long`}, }, { name: "IDP transform constants must have unique names", @@ -629,7 +629,7 @@ func TestSupervisorFederationDomainCRDValidations_Parallel(t *testing.T) { }, }, }, - wantErr: `spec.identityProviders[0].transforms.constants[1]: Duplicate value: map[string]interface {}{"name":"notUnique"}`, + wantErrs: []string{`spec.identityProviders[0].transforms.constants[1]: Duplicate value: map[string]interface {}{"name":"notUnique"}`}, }, { name: "IDP transform constant names cannot be empty", @@ -652,7 +652,7 @@ func TestSupervisorFederationDomainCRDValidations_Parallel(t *testing.T) { }, }, }, - wantErr: `spec.identityProviders[0].transforms.constants[0].name: Invalid value: "": spec.identityProviders[0].transforms.constants[0].name in body should be at least 1 chars long`, + wantErrs: []string{`spec.identityProviders[0].transforms.constants[0].name: Invalid value: "": spec.identityProviders[0].transforms.constants[0].name in body should be at least 1 chars long`}, }, { name: "IDP transform constant names cannot be more than 64 characters", @@ -675,9 +675,9 @@ func TestSupervisorFederationDomainCRDValidations_Parallel(t *testing.T) { }, }, }, - wantKube23OrOlderErr: `spec.identityProviders.transforms.constants.name: Invalid value: "12345678901234567890123456789012345678901234567890123456789012345": spec.identityProviders.transforms.constants.name in body should be at most 64 chars long`, - wantKube24Through31InclusiveErr: `spec.identityProviders[0].transforms.constants[0].name: Too long: may not be longer than 64`, - wantKube32OrNewerErr: `spec.identityProviders[0].transforms.constants[0].name: Too long: may not be more than 64 bytes`, + wantKube23OrOlderErrs: []string{`spec.identityProviders.transforms.constants.name: Invalid value: "12345678901234567890123456789012345678901234567890123456789012345": spec.identityProviders.transforms.constants.name in body should be at most 64 chars long`}, + wantKube24Through31InclusiveErrs: []string{`spec.identityProviders[0].transforms.constants[0].name: Too long: may not be longer than 64`}, + wantKube32OrNewerErrs: []string{`spec.identityProviders[0].transforms.constants[0].name: Too long: may not be more than 64 bytes`}, }, { name: "IDP transform constant names must be a legal CEL variable name", @@ -704,13 +704,11 @@ func TestSupervisorFederationDomainCRDValidations_Parallel(t *testing.T) { }, }, }, - wantKube23OrOlderErr: `spec.identityProviders.transforms.constants.name: Invalid value: "cannot have spaces": spec.identityProviders.transforms.constants.name in body should match '^[a-zA-Z][_a-zA-Z0-9]*$'`, - wantErr: `[spec.identityProviders[0].transforms.constants[0].name: Invalid value: "cannot have spaces": ` + - `spec.identityProviders[0].transforms.constants[0].name in body should match '^[a-zA-Z][_a-zA-Z0-9]*$', ` + - `spec.identityProviders[0].transforms.constants[1].name: Invalid value: "1mustStartWithLetter": ` + - `spec.identityProviders[0].transforms.constants[1].name in body should match '^[a-zA-Z][_a-zA-Z0-9]*$', ` + - `spec.identityProviders[0].transforms.constants[2].name: Invalid value: "_mustStartWithLetter": ` + - `spec.identityProviders[0].transforms.constants[2].name in body should match '^[a-zA-Z][_a-zA-Z0-9]*$']`, + wantKube23OrOlderErrs: []string{`spec.identityProviders.transforms.constants.name: Invalid value: "cannot have spaces": spec.identityProviders.transforms.constants.name in body should match '^[a-zA-Z][_a-zA-Z0-9]*$'`}, + wantErrs: []string{ + `spec.identityProviders[0].transforms.constants[0].name: Invalid value: "cannot have spaces": spec.identityProviders[0].transforms.constants[0].name in body should match '^[a-zA-Z][_a-zA-Z0-9]*$'`, + `spec.identityProviders[0].transforms.constants[1].name: Invalid value: "1mustStartWithLetter": spec.identityProviders[0].transforms.constants[1].name in body should match '^[a-zA-Z][_a-zA-Z0-9]*$'`, + `spec.identityProviders[0].transforms.constants[2].name: Invalid value: "_mustStartWithLetter": spec.identityProviders[0].transforms.constants[2].name in body should match '^[a-zA-Z][_a-zA-Z0-9]*$'`}, }, { name: "IDP transform constant types must be one of the allowed enum strings", @@ -735,7 +733,7 @@ func TestSupervisorFederationDomainCRDValidations_Parallel(t *testing.T) { }, }, }, - wantErr: `spec.identityProviders[0].transforms.constants[0].type: Unsupported value: "this is invalid": supported values: "string", "stringList"`, + wantErrs: []string{`spec.identityProviders[0].transforms.constants[0].type: Unsupported value: "this is invalid": supported values: "string", "stringList"`}, }, { name: "IDP transform expression types must be one of the allowed enum strings", @@ -761,7 +759,7 @@ func TestSupervisorFederationDomainCRDValidations_Parallel(t *testing.T) { }, }, }, - wantErr: `spec.identityProviders[0].transforms.expressions[0].type: Unsupported value: "this is invalid": supported values: "policy/v1", "username/v1", "groups/v1"`, + wantErrs: []string{`spec.identityProviders[0].transforms.expressions[0].type: Unsupported value: "this is invalid": supported values: "policy/v1", "username/v1", "groups/v1"`}, }, { name: "IDP transform expressions cannot be empty", @@ -784,7 +782,7 @@ func TestSupervisorFederationDomainCRDValidations_Parallel(t *testing.T) { }, }, }, - wantErr: `spec.identityProviders[0].transforms.expressions[0].expression: Invalid value: "": spec.identityProviders[0].transforms.expressions[0].expression in body should be at least 1 chars long`, + wantErrs: []string{`spec.identityProviders[0].transforms.expressions[0].expression: Invalid value: "": spec.identityProviders[0].transforms.expressions[0].expression in body should be at least 1 chars long`}, }, { name: "IDP transform example usernames cannot be empty", @@ -808,7 +806,7 @@ func TestSupervisorFederationDomainCRDValidations_Parallel(t *testing.T) { }, }, }, - wantErr: `spec.identityProviders[0].transforms.examples[0].username: Invalid value: "": spec.identityProviders[0].transforms.examples[0].username in body should be at least 1 chars long`, + wantErrs: []string{`spec.identityProviders[0].transforms.examples[0].username: Invalid value: "": spec.identityProviders[0].transforms.examples[0].username in body should be at least 1 chars long`}, }, { name: "minimum valid", @@ -881,43 +879,51 @@ func TestSupervisorFederationDomainCRDValidations_Parallel(t *testing.T) { } }) - if tt.wantErr != "" && tt.wantKube23OrOlderErr != "" && tt.wantKube24Through31InclusiveErr != "" && tt.wantKube32OrNewerErr != "" { + if len(tt.wantErrs) > 0 && len(tt.wantKube23OrOlderErrs) > 0 && len(tt.wantKube24Through31InclusiveErrs) > 0 && len(tt.wantKube32OrNewerErrs) > 0 { require.Fail(t, "test setup problem: wanted every possible kind of error, which would cause tt.wantErr to be unused") } - if tt.wantErr == "" && tt.wantKube23OrOlderErr == "" && tt.wantKube24Through31InclusiveErr == "" && tt.wantKube32OrNewerErr == "" { //nolint:nestif + if len(tt.wantErrs) == 0 && len(tt.wantKube23OrOlderErrs) == 0 && len(tt.wantKube24Through31InclusiveErrs) == 0 && len(tt.wantKube32OrNewerErrs) == 0 { //nolint:nestif // Did not want any error. require.NoError(t, actualCreateErr) } else { - wantErr := tt.wantErr + wantErr := tt.wantErrs if usingKubeVersionInCluster23OrOlder { // Old versions of Kubernetes did not show the index where the error occurred in some of the messages, // so remove the indices from the expected messages when running against an old version of Kube. // For the above tests, it should be enough to assume that there will only be indices up to 10. // This is useful when the only difference in the message between old and new is the missing indices. // Otherwise, use wantKube23OrOlderErr to say what the expected message should be for old versions. - for i := range 10 { - wantErr = strings.ReplaceAll(wantErr, fmt.Sprintf("[%d]", i), "") + for i := range wantErr { + for j := range 10 { + wantErr[i] = strings.ReplaceAll(wantErr[i], fmt.Sprintf("[%d]", j), "") + } } } - if usingKubeVersionInCluster23OrOlder && tt.wantKube23OrOlderErr != "" { + if usingKubeVersionInCluster23OrOlder && len(tt.wantKube23OrOlderErrs) > 0 { // Sometimes there are other difference in older Kubernetes messages, so also allow exact // expectation strings for those cases in wantKube23OrOlderErr. When provided, use it on these Kube clusters. - wantErr = tt.wantKube23OrOlderErr + wantErr = tt.wantKube23OrOlderErrs } - if usingKubeVersionInCluster24Through31Inclusive && tt.wantKube24Through31InclusiveErr != "" { + if usingKubeVersionInCluster24Through31Inclusive && len(tt.wantKube24Through31InclusiveErrs) > 0 { // Also allow overriding with an exact expected error for these Kube versions. - wantErr = tt.wantKube24Through31InclusiveErr + wantErr = tt.wantKube24Through31InclusiveErrs } - if usingKubeVersionInCluster32OrNewer && tt.wantKube32OrNewerErr != "" { + if usingKubeVersionInCluster32OrNewer && len(tt.wantKube32OrNewerErrs) > 0 { // Also allow overriding with an exact expected error for these Kube versions. - wantErr = tt.wantKube32OrNewerErr + wantErr = tt.wantKube32OrNewerErrs } - wantErr = fmt.Sprintf("FederationDomain.config.supervisor.%s %q is invalid: %s", - env.APIGroupSuffix, objectMeta.Name, wantErr) + wantErrStr := fmt.Sprintf("FederationDomain.config.supervisor.%s %q is invalid: ", + env.APIGroupSuffix, objectMeta.Name) - require.EqualError(t, actualCreateErr, wantErr) + if len(wantErr) == 1 { + wantErrStr += wantErr[0] + } else { + wantErrStr += "[" + strings.Join(wantErr, ", ") + "]" + } + + require.EqualError(t, actualCreateErr, wantErrStr) } }) } From d94e0036daff3ddcda14b7f196c06363058b6f0e Mon Sep 17 00:00:00 2001 From: Joshua Casey Date: Thu, 26 Dec 2024 14:25:07 -0600 Subject: [PATCH 3/6] FederationDomain.spec.issuer must now be an HTTPS URL --- .../v1alpha1/types_federationdomain.go.tmpl | 1 + ...rvisor.pinniped.dev_federationdomains.yaml | 3 + .../config/v1alpha1/types_federationdomain.go | 1 + ...rvisor.pinniped.dev_federationdomains.yaml | 3 + .../config/v1alpha1/types_federationdomain.go | 1 + ...rvisor.pinniped.dev_federationdomains.yaml | 3 + .../config/v1alpha1/types_federationdomain.go | 1 + ...rvisor.pinniped.dev_federationdomains.yaml | 3 + .../config/v1alpha1/types_federationdomain.go | 1 + ...rvisor.pinniped.dev_federationdomains.yaml | 3 + .../config/v1alpha1/types_federationdomain.go | 1 + ...rvisor.pinniped.dev_federationdomains.yaml | 3 + .../config/v1alpha1/types_federationdomain.go | 1 + ...rvisor.pinniped.dev_federationdomains.yaml | 3 + .../config/v1alpha1/types_federationdomain.go | 1 + ...rvisor.pinniped.dev_federationdomains.yaml | 3 + .../config/v1alpha1/types_federationdomain.go | 1 + ...supervisor_federationdomain_status_test.go | 116 ++++++++++++------ test/integration/supervisor_secrets_test.go | 2 +- 19 files changed, 110 insertions(+), 41 deletions(-) diff --git a/apis/supervisor/config/v1alpha1/types_federationdomain.go.tmpl b/apis/supervisor/config/v1alpha1/types_federationdomain.go.tmpl index d1a6e6278..173725741 100644 --- a/apis/supervisor/config/v1alpha1/types_federationdomain.go.tmpl +++ b/apis/supervisor/config/v1alpha1/types_federationdomain.go.tmpl @@ -209,6 +209,7 @@ type FederationDomainSpec struct { // See // https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.3 for more information. // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:XValidation:message="issuer must be an HTTPS URL",rule="isURL(self) && url(self).getScheme() == 'https'" Issuer string `json:"issuer"` // TLS specifies a secret which will contain Transport Layer Security (TLS) configuration for the FederationDomain. diff --git a/deploy/supervisor/config.supervisor.pinniped.dev_federationdomains.yaml b/deploy/supervisor/config.supervisor.pinniped.dev_federationdomains.yaml index 76bb4509e..83e45dd29 100644 --- a/deploy/supervisor/config.supervisor.pinniped.dev_federationdomains.yaml +++ b/deploy/supervisor/config.supervisor.pinniped.dev_federationdomains.yaml @@ -289,6 +289,9 @@ spec: https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.3 for more information. minLength: 1 type: string + x-kubernetes-validations: + - message: issuer must be an HTTPS URL + rule: isURL(self) && url(self).getScheme() == 'https' tls: description: TLS specifies a secret which will contain Transport Layer Security (TLS) configuration for the FederationDomain. diff --git a/generated/1.25/apis/supervisor/config/v1alpha1/types_federationdomain.go b/generated/1.25/apis/supervisor/config/v1alpha1/types_federationdomain.go index d1a6e6278..173725741 100644 --- a/generated/1.25/apis/supervisor/config/v1alpha1/types_federationdomain.go +++ b/generated/1.25/apis/supervisor/config/v1alpha1/types_federationdomain.go @@ -209,6 +209,7 @@ type FederationDomainSpec struct { // See // https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.3 for more information. // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:XValidation:message="issuer must be an HTTPS URL",rule="isURL(self) && url(self).getScheme() == 'https'" Issuer string `json:"issuer"` // TLS specifies a secret which will contain Transport Layer Security (TLS) configuration for the FederationDomain. diff --git a/generated/1.25/crds/config.supervisor.pinniped.dev_federationdomains.yaml b/generated/1.25/crds/config.supervisor.pinniped.dev_federationdomains.yaml index 964d46283..e994534fc 100644 --- a/generated/1.25/crds/config.supervisor.pinniped.dev_federationdomains.yaml +++ b/generated/1.25/crds/config.supervisor.pinniped.dev_federationdomains.yaml @@ -289,6 +289,9 @@ spec: https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.3 for more information. minLength: 1 type: string + x-kubernetes-validations: + - message: issuer must be an HTTPS URL + rule: isURL(self) && url(self).getScheme() == 'https' tls: description: TLS specifies a secret which will contain Transport Layer Security (TLS) configuration for the FederationDomain. diff --git a/generated/1.26/apis/supervisor/config/v1alpha1/types_federationdomain.go b/generated/1.26/apis/supervisor/config/v1alpha1/types_federationdomain.go index d1a6e6278..173725741 100644 --- a/generated/1.26/apis/supervisor/config/v1alpha1/types_federationdomain.go +++ b/generated/1.26/apis/supervisor/config/v1alpha1/types_federationdomain.go @@ -209,6 +209,7 @@ type FederationDomainSpec struct { // See // https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.3 for more information. // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:XValidation:message="issuer must be an HTTPS URL",rule="isURL(self) && url(self).getScheme() == 'https'" Issuer string `json:"issuer"` // TLS specifies a secret which will contain Transport Layer Security (TLS) configuration for the FederationDomain. diff --git a/generated/1.26/crds/config.supervisor.pinniped.dev_federationdomains.yaml b/generated/1.26/crds/config.supervisor.pinniped.dev_federationdomains.yaml index 964d46283..e994534fc 100644 --- a/generated/1.26/crds/config.supervisor.pinniped.dev_federationdomains.yaml +++ b/generated/1.26/crds/config.supervisor.pinniped.dev_federationdomains.yaml @@ -289,6 +289,9 @@ spec: https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.3 for more information. minLength: 1 type: string + x-kubernetes-validations: + - message: issuer must be an HTTPS URL + rule: isURL(self) && url(self).getScheme() == 'https' tls: description: TLS specifies a secret which will contain Transport Layer Security (TLS) configuration for the FederationDomain. diff --git a/generated/1.27/apis/supervisor/config/v1alpha1/types_federationdomain.go b/generated/1.27/apis/supervisor/config/v1alpha1/types_federationdomain.go index d1a6e6278..173725741 100644 --- a/generated/1.27/apis/supervisor/config/v1alpha1/types_federationdomain.go +++ b/generated/1.27/apis/supervisor/config/v1alpha1/types_federationdomain.go @@ -209,6 +209,7 @@ type FederationDomainSpec struct { // See // https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.3 for more information. // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:XValidation:message="issuer must be an HTTPS URL",rule="isURL(self) && url(self).getScheme() == 'https'" Issuer string `json:"issuer"` // TLS specifies a secret which will contain Transport Layer Security (TLS) configuration for the FederationDomain. diff --git a/generated/1.27/crds/config.supervisor.pinniped.dev_federationdomains.yaml b/generated/1.27/crds/config.supervisor.pinniped.dev_federationdomains.yaml index 964d46283..e994534fc 100644 --- a/generated/1.27/crds/config.supervisor.pinniped.dev_federationdomains.yaml +++ b/generated/1.27/crds/config.supervisor.pinniped.dev_federationdomains.yaml @@ -289,6 +289,9 @@ spec: https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.3 for more information. minLength: 1 type: string + x-kubernetes-validations: + - message: issuer must be an HTTPS URL + rule: isURL(self) && url(self).getScheme() == 'https' tls: description: TLS specifies a secret which will contain Transport Layer Security (TLS) configuration for the FederationDomain. diff --git a/generated/1.28/apis/supervisor/config/v1alpha1/types_federationdomain.go b/generated/1.28/apis/supervisor/config/v1alpha1/types_federationdomain.go index d1a6e6278..173725741 100644 --- a/generated/1.28/apis/supervisor/config/v1alpha1/types_federationdomain.go +++ b/generated/1.28/apis/supervisor/config/v1alpha1/types_federationdomain.go @@ -209,6 +209,7 @@ type FederationDomainSpec struct { // See // https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.3 for more information. // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:XValidation:message="issuer must be an HTTPS URL",rule="isURL(self) && url(self).getScheme() == 'https'" Issuer string `json:"issuer"` // TLS specifies a secret which will contain Transport Layer Security (TLS) configuration for the FederationDomain. diff --git a/generated/1.28/crds/config.supervisor.pinniped.dev_federationdomains.yaml b/generated/1.28/crds/config.supervisor.pinniped.dev_federationdomains.yaml index 964d46283..e994534fc 100644 --- a/generated/1.28/crds/config.supervisor.pinniped.dev_federationdomains.yaml +++ b/generated/1.28/crds/config.supervisor.pinniped.dev_federationdomains.yaml @@ -289,6 +289,9 @@ spec: https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.3 for more information. minLength: 1 type: string + x-kubernetes-validations: + - message: issuer must be an HTTPS URL + rule: isURL(self) && url(self).getScheme() == 'https' tls: description: TLS specifies a secret which will contain Transport Layer Security (TLS) configuration for the FederationDomain. diff --git a/generated/1.29/apis/supervisor/config/v1alpha1/types_federationdomain.go b/generated/1.29/apis/supervisor/config/v1alpha1/types_federationdomain.go index d1a6e6278..173725741 100644 --- a/generated/1.29/apis/supervisor/config/v1alpha1/types_federationdomain.go +++ b/generated/1.29/apis/supervisor/config/v1alpha1/types_federationdomain.go @@ -209,6 +209,7 @@ type FederationDomainSpec struct { // See // https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.3 for more information. // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:XValidation:message="issuer must be an HTTPS URL",rule="isURL(self) && url(self).getScheme() == 'https'" Issuer string `json:"issuer"` // TLS specifies a secret which will contain Transport Layer Security (TLS) configuration for the FederationDomain. diff --git a/generated/1.29/crds/config.supervisor.pinniped.dev_federationdomains.yaml b/generated/1.29/crds/config.supervisor.pinniped.dev_federationdomains.yaml index 964d46283..e994534fc 100644 --- a/generated/1.29/crds/config.supervisor.pinniped.dev_federationdomains.yaml +++ b/generated/1.29/crds/config.supervisor.pinniped.dev_federationdomains.yaml @@ -289,6 +289,9 @@ spec: https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.3 for more information. minLength: 1 type: string + x-kubernetes-validations: + - message: issuer must be an HTTPS URL + rule: isURL(self) && url(self).getScheme() == 'https' tls: description: TLS specifies a secret which will contain Transport Layer Security (TLS) configuration for the FederationDomain. diff --git a/generated/1.30/apis/supervisor/config/v1alpha1/types_federationdomain.go b/generated/1.30/apis/supervisor/config/v1alpha1/types_federationdomain.go index d1a6e6278..173725741 100644 --- a/generated/1.30/apis/supervisor/config/v1alpha1/types_federationdomain.go +++ b/generated/1.30/apis/supervisor/config/v1alpha1/types_federationdomain.go @@ -209,6 +209,7 @@ type FederationDomainSpec struct { // See // https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.3 for more information. // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:XValidation:message="issuer must be an HTTPS URL",rule="isURL(self) && url(self).getScheme() == 'https'" Issuer string `json:"issuer"` // TLS specifies a secret which will contain Transport Layer Security (TLS) configuration for the FederationDomain. diff --git a/generated/1.30/crds/config.supervisor.pinniped.dev_federationdomains.yaml b/generated/1.30/crds/config.supervisor.pinniped.dev_federationdomains.yaml index 76bb4509e..83e45dd29 100644 --- a/generated/1.30/crds/config.supervisor.pinniped.dev_federationdomains.yaml +++ b/generated/1.30/crds/config.supervisor.pinniped.dev_federationdomains.yaml @@ -289,6 +289,9 @@ spec: https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.3 for more information. minLength: 1 type: string + x-kubernetes-validations: + - message: issuer must be an HTTPS URL + rule: isURL(self) && url(self).getScheme() == 'https' tls: description: TLS specifies a secret which will contain Transport Layer Security (TLS) configuration for the FederationDomain. diff --git a/generated/1.31/apis/supervisor/config/v1alpha1/types_federationdomain.go b/generated/1.31/apis/supervisor/config/v1alpha1/types_federationdomain.go index d1a6e6278..173725741 100644 --- a/generated/1.31/apis/supervisor/config/v1alpha1/types_federationdomain.go +++ b/generated/1.31/apis/supervisor/config/v1alpha1/types_federationdomain.go @@ -209,6 +209,7 @@ type FederationDomainSpec struct { // See // https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.3 for more information. // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:XValidation:message="issuer must be an HTTPS URL",rule="isURL(self) && url(self).getScheme() == 'https'" Issuer string `json:"issuer"` // TLS specifies a secret which will contain Transport Layer Security (TLS) configuration for the FederationDomain. diff --git a/generated/1.31/crds/config.supervisor.pinniped.dev_federationdomains.yaml b/generated/1.31/crds/config.supervisor.pinniped.dev_federationdomains.yaml index 76bb4509e..83e45dd29 100644 --- a/generated/1.31/crds/config.supervisor.pinniped.dev_federationdomains.yaml +++ b/generated/1.31/crds/config.supervisor.pinniped.dev_federationdomains.yaml @@ -289,6 +289,9 @@ spec: https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.3 for more information. minLength: 1 type: string + x-kubernetes-validations: + - message: issuer must be an HTTPS URL + rule: isURL(self) && url(self).getScheme() == 'https' tls: description: TLS specifies a secret which will contain Transport Layer Security (TLS) configuration for the FederationDomain. diff --git a/generated/latest/apis/supervisor/config/v1alpha1/types_federationdomain.go b/generated/latest/apis/supervisor/config/v1alpha1/types_federationdomain.go index d1a6e6278..173725741 100644 --- a/generated/latest/apis/supervisor/config/v1alpha1/types_federationdomain.go +++ b/generated/latest/apis/supervisor/config/v1alpha1/types_federationdomain.go @@ -209,6 +209,7 @@ type FederationDomainSpec struct { // See // https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.3 for more information. // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:XValidation:message="issuer must be an HTTPS URL",rule="isURL(self) && url(self).getScheme() == 'https'" Issuer string `json:"issuer"` // TLS specifies a secret which will contain Transport Layer Security (TLS) configuration for the FederationDomain. diff --git a/test/integration/supervisor_federationdomain_status_test.go b/test/integration/supervisor_federationdomain_status_test.go index 639ee164a..9e9b5d160 100644 --- a/test/integration/supervisor_federationdomain_status_test.go +++ b/test/integration/supervisor_federationdomain_status_test.go @@ -567,12 +567,15 @@ func TestSupervisorFederationDomainCRDValidations_Parallel(t *testing.T) { usingKubeVersionInCluster24Through31Inclusive := testutil.KubeServerMinorVersionInBetweenInclusive(t, adminClient.Discovery(), 24, 31) usingKubeVersionInCluster32OrNewer := !usingKubeVersionInCluster23OrOlder && !usingKubeVersionInCluster24Through31Inclusive + performCELTests := testutil.KubeServerMinorVersionAtLeastInclusive(t, adminClient.Discovery(), 27) + objectMeta := testlib.ObjectMetaWithRandomName(t, "federation-domain") tests := []struct { - name string - fd *supervisorconfigv1alpha1.FederationDomain - wantErrs []string + name string + fd *supervisorconfigv1alpha1.FederationDomain + wantErrs []string + wantCELErrs []string // optionally override wantErr for one or more specific versions of Kube, due to changing validation error text wantKube23OrOlderErrs []string @@ -587,7 +590,28 @@ func TestSupervisorFederationDomainCRDValidations_Parallel(t *testing.T) { Issuer: "", }, }, - wantErrs: []string{`spec.issuer: Invalid value: "": spec.issuer in body should be at least 1 chars long`}, + wantErrs: []string{`spec.issuer: Invalid value: "": spec.issuer in body should be at least 1 chars long`}, + wantCELErrs: []string{`spec.issuer: Invalid value: "string": issuer must be an HTTPS URL`}, + }, + { + name: "issuer must be a URL", + fd: &supervisorconfigv1alpha1.FederationDomain{ + ObjectMeta: objectMeta, + Spec: supervisorconfigv1alpha1.FederationDomainSpec{ + Issuer: "foo", + }, + }, + wantCELErrs: []string{`spec.issuer: Invalid value: "string": issuer must be an HTTPS URL`}, + }, + { + name: "issuer URL scheme must be 'https'", + fd: &supervisorconfigv1alpha1.FederationDomain{ + ObjectMeta: objectMeta, + Spec: supervisorconfigv1alpha1.FederationDomainSpec{ + Issuer: "http://example.com", + }, + }, + wantCELErrs: []string{`spec.issuer: Invalid value: "string": issuer must be an HTTPS URL`}, }, { name: "IDP display names cannot be empty", @@ -678,6 +702,7 @@ func TestSupervisorFederationDomainCRDValidations_Parallel(t *testing.T) { wantKube23OrOlderErrs: []string{`spec.identityProviders.transforms.constants.name: Invalid value: "12345678901234567890123456789012345678901234567890123456789012345": spec.identityProviders.transforms.constants.name in body should be at most 64 chars long`}, wantKube24Through31InclusiveErrs: []string{`spec.identityProviders[0].transforms.constants[0].name: Too long: may not be longer than 64`}, wantKube32OrNewerErrs: []string{`spec.identityProviders[0].transforms.constants[0].name: Too long: may not be more than 64 bytes`}, + wantCELErrs: []string{`: Invalid value: "null": some validation rules were not checked because the object was invalid; correct the existing errors to complete validation`}, }, { name: "IDP transform constant names must be a legal CEL variable name", @@ -733,7 +758,8 @@ func TestSupervisorFederationDomainCRDValidations_Parallel(t *testing.T) { }, }, }, - wantErrs: []string{`spec.identityProviders[0].transforms.constants[0].type: Unsupported value: "this is invalid": supported values: "string", "stringList"`}, + wantErrs: []string{`spec.identityProviders[0].transforms.constants[0].type: Unsupported value: "this is invalid": supported values: "string", "stringList"`}, + wantCELErrs: []string{`: Invalid value: "null": some validation rules were not checked because the object was invalid; correct the existing errors to complete validation`}, }, { name: "IDP transform expression types must be one of the allowed enum strings", @@ -759,7 +785,8 @@ func TestSupervisorFederationDomainCRDValidations_Parallel(t *testing.T) { }, }, }, - wantErrs: []string{`spec.identityProviders[0].transforms.expressions[0].type: Unsupported value: "this is invalid": supported values: "policy/v1", "username/v1", "groups/v1"`}, + wantErrs: []string{`spec.identityProviders[0].transforms.expressions[0].type: Unsupported value: "this is invalid": supported values: "policy/v1", "username/v1", "groups/v1"`}, + wantCELErrs: []string{`: Invalid value: "null": some validation rules were not checked because the object was invalid; correct the existing errors to complete validation`}, }, { name: "IDP transform expressions cannot be empty", @@ -883,48 +910,57 @@ func TestSupervisorFederationDomainCRDValidations_Parallel(t *testing.T) { require.Fail(t, "test setup problem: wanted every possible kind of error, which would cause tt.wantErr to be unused") } - if len(tt.wantErrs) == 0 && len(tt.wantKube23OrOlderErrs) == 0 && len(tt.wantKube24Through31InclusiveErrs) == 0 && len(tt.wantKube32OrNewerErrs) == 0 { //nolint:nestif + if len(tt.wantErrs) == 0 && len(tt.wantCELErrs) == 0 && len(tt.wantKube23OrOlderErrs) == 0 && len(tt.wantKube24Through31InclusiveErrs) == 0 && len(tt.wantKube32OrNewerErrs) == 0 { // Did not want any error. require.NoError(t, actualCreateErr) - } else { - wantErr := tt.wantErrs - if usingKubeVersionInCluster23OrOlder { - // Old versions of Kubernetes did not show the index where the error occurred in some of the messages, - // so remove the indices from the expected messages when running against an old version of Kube. - // For the above tests, it should be enough to assume that there will only be indices up to 10. - // This is useful when the only difference in the message between old and new is the missing indices. - // Otherwise, use wantKube23OrOlderErr to say what the expected message should be for old versions. - for i := range wantErr { - for j := range 10 { - wantErr[i] = strings.ReplaceAll(wantErr[i], fmt.Sprintf("[%d]", j), "") - } + return + } + + wantErr := tt.wantErrs + if usingKubeVersionInCluster23OrOlder { + // Old versions of Kubernetes did not show the index where the error occurred in some of the messages, + // so remove the indices from the expected messages when running against an old version of Kube. + // For the above tests, it should be enough to assume that there will only be indices up to 10. + // This is useful when the only difference in the message between old and new is the missing indices. + // Otherwise, use wantKube23OrOlderErr to say what the expected message should be for old versions. + for i := range wantErr { + for j := range 10 { + wantErr[i] = strings.ReplaceAll(wantErr[i], fmt.Sprintf("[%d]", j), "") } } - if usingKubeVersionInCluster23OrOlder && len(tt.wantKube23OrOlderErrs) > 0 { - // Sometimes there are other difference in older Kubernetes messages, so also allow exact - // expectation strings for those cases in wantKube23OrOlderErr. When provided, use it on these Kube clusters. - wantErr = tt.wantKube23OrOlderErrs - } - if usingKubeVersionInCluster24Through31Inclusive && len(tt.wantKube24Through31InclusiveErrs) > 0 { - // Also allow overriding with an exact expected error for these Kube versions. - wantErr = tt.wantKube24Through31InclusiveErrs - } - if usingKubeVersionInCluster32OrNewer && len(tt.wantKube32OrNewerErrs) > 0 { - // Also allow overriding with an exact expected error for these Kube versions. - wantErr = tt.wantKube32OrNewerErrs - } + } + if usingKubeVersionInCluster23OrOlder && len(tt.wantKube23OrOlderErrs) > 0 { + // Sometimes there are other difference in older Kubernetes messages, so also allow exact + // expectation strings for those cases in wantKube23OrOlderErr. When provided, use it on these Kube clusters. + wantErr = tt.wantKube23OrOlderErrs + } + if usingKubeVersionInCluster24Through31Inclusive && len(tt.wantKube24Through31InclusiveErrs) > 0 { + // Also allow overriding with an exact expected error for these Kube versions. + wantErr = tt.wantKube24Through31InclusiveErrs + } + if usingKubeVersionInCluster32OrNewer && len(tt.wantKube32OrNewerErrs) > 0 { + // Also allow overriding with an exact expected error for these Kube versions. + wantErr = tt.wantKube32OrNewerErrs + } - wantErrStr := fmt.Sprintf("FederationDomain.config.supervisor.%s %q is invalid: ", - env.APIGroupSuffix, objectMeta.Name) + if performCELTests { + wantErr = append(wantErr, tt.wantCELErrs...) + } else if len(wantErr) == len(tt.wantCELErrs) { + // on old K8s versions, don't check for errors when all we expect are CEL errors + require.NoError(t, actualCreateErr) + return + } - if len(wantErr) == 1 { - wantErrStr += wantErr[0] - } else { - wantErrStr += "[" + strings.Join(wantErr, ", ") + "]" - } + wantErrStr := fmt.Sprintf("FederationDomain.config.supervisor.%s %q is invalid: ", + env.APIGroupSuffix, objectMeta.Name) - require.EqualError(t, actualCreateErr, wantErrStr) + if len(wantErr) == 1 { + wantErrStr += wantErr[0] + } else { + wantErrStr += "[" + strings.Join(wantErr, ", ") + "]" } + + require.EqualError(t, actualCreateErr, wantErrStr) }) } } diff --git a/test/integration/supervisor_secrets_test.go b/test/integration/supervisor_secrets_test.go index 7a1972f36..95b8026a3 100644 --- a/test/integration/supervisor_secrets_test.go +++ b/test/integration/supervisor_secrets_test.go @@ -31,7 +31,7 @@ func TestSupervisorSecrets_Parallel(t *testing.T) { // Create our FederationDomain under test. federationDomain := testlib.CreateTestFederationDomain(ctx, t, supervisorconfigv1alpha1.FederationDomainSpec{ - Issuer: fmt.Sprintf("http://test-issuer-%s.pinniped.dev", testlib.RandHex(t, 8)), + Issuer: fmt.Sprintf("https://test-issuer-%s.pinniped.dev", testlib.RandHex(t, 8)), }, supervisorconfigv1alpha1.FederationDomainPhaseError, // in phase error until there is an IDP created, but this test does not care ) From d2832e282dc8b5f5aa325e7e5fbe48d5815e9574 Mon Sep 17 00:00:00 2001 From: Joshua Casey Date: Thu, 26 Dec 2024 16:10:48 -0600 Subject: [PATCH 4/6] Remove deprecated CredentialIssuer.status.kubeConfigInfo --- .../v1alpha1/types_credentialissuer.go.tmpl | 18 ---------------- cmd/pinniped/cmd/kubeconfig.go | 17 +++------------ cmd/pinniped/cmd/kubeconfig_test.go | 12 +++++------ ...cierge.pinniped.dev_credentialissuers.yaml | 18 ---------------- generated/1.25/README.adoc | 21 ------------------- .../config/v1alpha1/types_credentialissuer.go | 18 ---------------- .../config/v1alpha1/zz_generated.deepcopy.go | 21 ------------------- ...cierge.pinniped.dev_credentialissuers.yaml | 18 ---------------- generated/1.26/README.adoc | 21 ------------------- .../config/v1alpha1/types_credentialissuer.go | 18 ---------------- .../config/v1alpha1/zz_generated.deepcopy.go | 21 ------------------- ...cierge.pinniped.dev_credentialissuers.yaml | 18 ---------------- generated/1.27/README.adoc | 21 ------------------- .../config/v1alpha1/types_credentialissuer.go | 18 ---------------- .../config/v1alpha1/zz_generated.deepcopy.go | 21 ------------------- ...cierge.pinniped.dev_credentialissuers.yaml | 18 ---------------- generated/1.28/README.adoc | 21 ------------------- .../config/v1alpha1/types_credentialissuer.go | 18 ---------------- .../config/v1alpha1/zz_generated.deepcopy.go | 21 ------------------- ...cierge.pinniped.dev_credentialissuers.yaml | 18 ---------------- generated/1.29/README.adoc | 21 ------------------- .../config/v1alpha1/types_credentialissuer.go | 18 ---------------- .../config/v1alpha1/zz_generated.deepcopy.go | 21 ------------------- ...cierge.pinniped.dev_credentialissuers.yaml | 18 ---------------- generated/1.30/README.adoc | 21 ------------------- .../config/v1alpha1/types_credentialissuer.go | 18 ---------------- .../config/v1alpha1/zz_generated.deepcopy.go | 21 ------------------- ...cierge.pinniped.dev_credentialissuers.yaml | 18 ---------------- generated/1.31/README.adoc | 21 ------------------- .../config/v1alpha1/types_credentialissuer.go | 18 ---------------- .../config/v1alpha1/zz_generated.deepcopy.go | 21 ------------------- ...cierge.pinniped.dev_credentialissuers.yaml | 18 ---------------- generated/latest/README.adoc | 21 ------------------- .../config/v1alpha1/types_credentialissuer.go | 18 ---------------- .../config/v1alpha1/zz_generated.deepcopy.go | 21 ------------------- .../controller/issuerconfig/issuerconfig.go | 8 ------- .../issuerconfig/issuerconfig_test.go | 4 ---- .../concierge_credentialissuer_test.go | 12 ----------- test/integration/kube_api_discovery_test.go | 2 +- 39 files changed, 10 insertions(+), 687 deletions(-) diff --git a/apis/concierge/config/v1alpha1/types_credentialissuer.go.tmpl b/apis/concierge/config/v1alpha1/types_credentialissuer.go.tmpl index de976f5c1..7f80f5178 100644 --- a/apis/concierge/config/v1alpha1/types_credentialissuer.go.tmpl +++ b/apis/concierge/config/v1alpha1/types_credentialissuer.go.tmpl @@ -161,24 +161,6 @@ type ImpersonationProxyServiceSpec struct { type CredentialIssuerStatus struct { // List of integration strategies that were attempted by Pinniped. Strategies []CredentialIssuerStrategy `json:"strategies"` - - // Information needed to form a valid Pinniped-based kubeconfig using this credential issuer. - // This field is deprecated and will be removed in a future version. - // +optional - KubeConfigInfo *CredentialIssuerKubeConfigInfo `json:"kubeConfigInfo,omitempty"` -} - -// CredentialIssuerKubeConfigInfo provides the information needed to form a valid Pinniped-based kubeconfig using this credential issuer. -// This type is deprecated and will be removed in a future version. -type CredentialIssuerKubeConfigInfo struct { - // The K8s API server URL. - // +kubebuilder:validation:MinLength=1 - // +kubebuilder:validation:Pattern=`^https://|^http://` - Server string `json:"server"` - - // The K8s API server CA bundle. - // +kubebuilder:validation:MinLength=1 - CertificateAuthorityData string `json:"certificateAuthorityData"` } // CredentialIssuerStrategy describes the status of an integration strategy that was attempted by Pinniped. diff --git a/cmd/pinniped/cmd/kubeconfig.go b/cmd/pinniped/cmd/kubeconfig.go index 8e536983c..1386873d0 100644 --- a/cmd/pinniped/cmd/kubeconfig.go +++ b/cmd/pinniped/cmd/kubeconfig.go @@ -540,26 +540,15 @@ func getConciergeFrontend(credentialIssuer *conciergeconfigv1alpha1.CredentialIs continue } - // Backfill the .status.strategies[].frontend field from .status.kubeConfigInfo for backwards compatibility. - if strategy.Type == conciergeconfigv1alpha1.KubeClusterSigningCertificateStrategyType && strategy.Frontend == nil && credentialIssuer.Status.KubeConfigInfo != nil { - strategy = *strategy.DeepCopy() - strategy.Frontend = &conciergeconfigv1alpha1.CredentialIssuerFrontend{ - Type: conciergeconfigv1alpha1.TokenCredentialRequestAPIFrontendType, - TokenCredentialRequestAPIInfo: &conciergeconfigv1alpha1.TokenCredentialRequestAPIInfo{ - Server: credentialIssuer.Status.KubeConfigInfo.Server, - CertificateAuthorityData: credentialIssuer.Status.KubeConfigInfo.CertificateAuthorityData, - }, - } - } - - // If the strategy frontend is still nil, skip. + // If the strategy frontend is nil, skip. if strategy.Frontend == nil { continue } // Skip any unknown frontend types. switch strategy.Frontend.Type { - case conciergeconfigv1alpha1.TokenCredentialRequestAPIFrontendType, conciergeconfigv1alpha1.ImpersonationProxyFrontendType: + case conciergeconfigv1alpha1.TokenCredentialRequestAPIFrontendType, + conciergeconfigv1alpha1.ImpersonationProxyFrontendType: default: continue } diff --git a/cmd/pinniped/cmd/kubeconfig_test.go b/cmd/pinniped/cmd/kubeconfig_test.go index 1a99584e1..55d29373c 100644 --- a/cmd/pinniped/cmd/kubeconfig_test.go +++ b/cmd/pinniped/cmd/kubeconfig_test.go @@ -613,18 +613,18 @@ func TestGetKubeconfig(t *testing.T) { &conciergeconfigv1alpha1.CredentialIssuer{ ObjectMeta: metav1.ObjectMeta{Name: "test-credential-issuer"}, Status: conciergeconfigv1alpha1.CredentialIssuerStatus{ - KubeConfigInfo: &conciergeconfigv1alpha1.CredentialIssuerKubeConfigInfo{ - Server: "https://concierge-endpoint", - CertificateAuthorityData: "ZmFrZS1jZXJ0aWZpY2F0ZS1hdXRob3JpdHktZGF0YS12YWx1ZQ==", - }, Strategies: []conciergeconfigv1alpha1.CredentialIssuerStrategy{{ Type: conciergeconfigv1alpha1.KubeClusterSigningCertificateStrategyType, Status: conciergeconfigv1alpha1.SuccessStrategyStatus, Reason: conciergeconfigv1alpha1.FetchedKeyStrategyReason, Message: "Successfully fetched key", LastUpdateTime: metav1.Now(), - // Simulate a previous version of CredentialIssuer that's missing this Frontend field. - Frontend: nil, + Frontend: &conciergeconfigv1alpha1.CredentialIssuerFrontend{ + Type: conciergeconfigv1alpha1.TokenCredentialRequestAPIFrontendType, + TokenCredentialRequestAPIInfo: &conciergeconfigv1alpha1.TokenCredentialRequestAPIInfo{ + Server: "https://concierge-endpoint.example.com", + }, + }, }}, }, }, diff --git a/deploy/concierge/config.concierge.pinniped.dev_credentialissuers.yaml b/deploy/concierge/config.concierge.pinniped.dev_credentialissuers.yaml index 6897b7968..0df5a4fe0 100644 --- a/deploy/concierge/config.concierge.pinniped.dev_credentialissuers.yaml +++ b/deploy/concierge/config.concierge.pinniped.dev_credentialissuers.yaml @@ -134,24 +134,6 @@ spec: status: description: CredentialIssuerStatus describes the status of the Concierge. properties: - kubeConfigInfo: - description: |- - Information needed to form a valid Pinniped-based kubeconfig using this credential issuer. - This field is deprecated and will be removed in a future version. - properties: - certificateAuthorityData: - description: The K8s API server CA bundle. - minLength: 1 - type: string - server: - description: The K8s API server URL. - minLength: 1 - pattern: ^https://|^http:// - type: string - required: - - certificateAuthorityData - - server - type: object strategies: description: List of integration strategies that were attempted by Pinniped. diff --git a/generated/1.25/README.adoc b/generated/1.25/README.adoc index 92794f1b1..87ba13404 100644 --- a/generated/1.25/README.adoc +++ b/generated/1.25/README.adoc @@ -429,25 +429,6 @@ This field is only set when Type is "ImpersonationProxy". + |=== -[id="{anchor_prefix}-go-pinniped-dev-generated-1-25-apis-concierge-config-v1alpha1-credentialissuerkubeconfiginfo"] -==== CredentialIssuerKubeConfigInfo - -CredentialIssuerKubeConfigInfo provides the information needed to form a valid Pinniped-based kubeconfig using this credential issuer. -This type is deprecated and will be removed in a future version. - -.Appears In: -**** -- xref:{anchor_prefix}-go-pinniped-dev-generated-1-25-apis-concierge-config-v1alpha1-credentialissuerstatus[$$CredentialIssuerStatus$$] -**** - -[cols="25a,75a", options="header"] -|=== -| Field | Description -| *`server`* __string__ | The K8s API server URL. + -| *`certificateAuthorityData`* __string__ | The K8s API server CA bundle. + -|=== - - [id="{anchor_prefix}-go-pinniped-dev-generated-1-25-apis-concierge-config-v1alpha1-credentialissuerspec"] @@ -481,8 +462,6 @@ CredentialIssuerStatus describes the status of the Concierge. |=== | Field | Description | *`strategies`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-25-apis-concierge-config-v1alpha1-credentialissuerstrategy[$$CredentialIssuerStrategy$$] array__ | List of integration strategies that were attempted by Pinniped. + -| *`kubeConfigInfo`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-25-apis-concierge-config-v1alpha1-credentialissuerkubeconfiginfo[$$CredentialIssuerKubeConfigInfo$$]__ | Information needed to form a valid Pinniped-based kubeconfig using this credential issuer. + -This field is deprecated and will be removed in a future version. + |=== diff --git a/generated/1.25/apis/concierge/config/v1alpha1/types_credentialissuer.go b/generated/1.25/apis/concierge/config/v1alpha1/types_credentialissuer.go index de976f5c1..7f80f5178 100644 --- a/generated/1.25/apis/concierge/config/v1alpha1/types_credentialissuer.go +++ b/generated/1.25/apis/concierge/config/v1alpha1/types_credentialissuer.go @@ -161,24 +161,6 @@ type ImpersonationProxyServiceSpec struct { type CredentialIssuerStatus struct { // List of integration strategies that were attempted by Pinniped. Strategies []CredentialIssuerStrategy `json:"strategies"` - - // Information needed to form a valid Pinniped-based kubeconfig using this credential issuer. - // This field is deprecated and will be removed in a future version. - // +optional - KubeConfigInfo *CredentialIssuerKubeConfigInfo `json:"kubeConfigInfo,omitempty"` -} - -// CredentialIssuerKubeConfigInfo provides the information needed to form a valid Pinniped-based kubeconfig using this credential issuer. -// This type is deprecated and will be removed in a future version. -type CredentialIssuerKubeConfigInfo struct { - // The K8s API server URL. - // +kubebuilder:validation:MinLength=1 - // +kubebuilder:validation:Pattern=`^https://|^http://` - Server string `json:"server"` - - // The K8s API server CA bundle. - // +kubebuilder:validation:MinLength=1 - CertificateAuthorityData string `json:"certificateAuthorityData"` } // CredentialIssuerStrategy describes the status of an integration strategy that was attempted by Pinniped. diff --git a/generated/1.25/apis/concierge/config/v1alpha1/zz_generated.deepcopy.go b/generated/1.25/apis/concierge/config/v1alpha1/zz_generated.deepcopy.go index 213ff2229..d3cc37e71 100644 --- a/generated/1.25/apis/concierge/config/v1alpha1/zz_generated.deepcopy.go +++ b/generated/1.25/apis/concierge/config/v1alpha1/zz_generated.deepcopy.go @@ -66,22 +66,6 @@ func (in *CredentialIssuerFrontend) DeepCopy() *CredentialIssuerFrontend { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *CredentialIssuerKubeConfigInfo) DeepCopyInto(out *CredentialIssuerKubeConfigInfo) { - *out = *in - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CredentialIssuerKubeConfigInfo. -func (in *CredentialIssuerKubeConfigInfo) DeepCopy() *CredentialIssuerKubeConfigInfo { - if in == nil { - return nil - } - out := new(CredentialIssuerKubeConfigInfo) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *CredentialIssuerList) DeepCopyInto(out *CredentialIssuerList) { *out = *in @@ -146,11 +130,6 @@ func (in *CredentialIssuerStatus) DeepCopyInto(out *CredentialIssuerStatus) { (*in)[i].DeepCopyInto(&(*out)[i]) } } - if in.KubeConfigInfo != nil { - in, out := &in.KubeConfigInfo, &out.KubeConfigInfo - *out = new(CredentialIssuerKubeConfigInfo) - **out = **in - } return } diff --git a/generated/1.25/crds/config.concierge.pinniped.dev_credentialissuers.yaml b/generated/1.25/crds/config.concierge.pinniped.dev_credentialissuers.yaml index 6897b7968..0df5a4fe0 100644 --- a/generated/1.25/crds/config.concierge.pinniped.dev_credentialissuers.yaml +++ b/generated/1.25/crds/config.concierge.pinniped.dev_credentialissuers.yaml @@ -134,24 +134,6 @@ spec: status: description: CredentialIssuerStatus describes the status of the Concierge. properties: - kubeConfigInfo: - description: |- - Information needed to form a valid Pinniped-based kubeconfig using this credential issuer. - This field is deprecated and will be removed in a future version. - properties: - certificateAuthorityData: - description: The K8s API server CA bundle. - minLength: 1 - type: string - server: - description: The K8s API server URL. - minLength: 1 - pattern: ^https://|^http:// - type: string - required: - - certificateAuthorityData - - server - type: object strategies: description: List of integration strategies that were attempted by Pinniped. diff --git a/generated/1.26/README.adoc b/generated/1.26/README.adoc index 2e291f103..9e67d6ebb 100644 --- a/generated/1.26/README.adoc +++ b/generated/1.26/README.adoc @@ -429,25 +429,6 @@ This field is only set when Type is "ImpersonationProxy". + |=== -[id="{anchor_prefix}-go-pinniped-dev-generated-1-26-apis-concierge-config-v1alpha1-credentialissuerkubeconfiginfo"] -==== CredentialIssuerKubeConfigInfo - -CredentialIssuerKubeConfigInfo provides the information needed to form a valid Pinniped-based kubeconfig using this credential issuer. -This type is deprecated and will be removed in a future version. - -.Appears In: -**** -- xref:{anchor_prefix}-go-pinniped-dev-generated-1-26-apis-concierge-config-v1alpha1-credentialissuerstatus[$$CredentialIssuerStatus$$] -**** - -[cols="25a,75a", options="header"] -|=== -| Field | Description -| *`server`* __string__ | The K8s API server URL. + -| *`certificateAuthorityData`* __string__ | The K8s API server CA bundle. + -|=== - - [id="{anchor_prefix}-go-pinniped-dev-generated-1-26-apis-concierge-config-v1alpha1-credentialissuerspec"] @@ -481,8 +462,6 @@ CredentialIssuerStatus describes the status of the Concierge. |=== | Field | Description | *`strategies`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-26-apis-concierge-config-v1alpha1-credentialissuerstrategy[$$CredentialIssuerStrategy$$] array__ | List of integration strategies that were attempted by Pinniped. + -| *`kubeConfigInfo`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-26-apis-concierge-config-v1alpha1-credentialissuerkubeconfiginfo[$$CredentialIssuerKubeConfigInfo$$]__ | Information needed to form a valid Pinniped-based kubeconfig using this credential issuer. + -This field is deprecated and will be removed in a future version. + |=== diff --git a/generated/1.26/apis/concierge/config/v1alpha1/types_credentialissuer.go b/generated/1.26/apis/concierge/config/v1alpha1/types_credentialissuer.go index de976f5c1..7f80f5178 100644 --- a/generated/1.26/apis/concierge/config/v1alpha1/types_credentialissuer.go +++ b/generated/1.26/apis/concierge/config/v1alpha1/types_credentialissuer.go @@ -161,24 +161,6 @@ type ImpersonationProxyServiceSpec struct { type CredentialIssuerStatus struct { // List of integration strategies that were attempted by Pinniped. Strategies []CredentialIssuerStrategy `json:"strategies"` - - // Information needed to form a valid Pinniped-based kubeconfig using this credential issuer. - // This field is deprecated and will be removed in a future version. - // +optional - KubeConfigInfo *CredentialIssuerKubeConfigInfo `json:"kubeConfigInfo,omitempty"` -} - -// CredentialIssuerKubeConfigInfo provides the information needed to form a valid Pinniped-based kubeconfig using this credential issuer. -// This type is deprecated and will be removed in a future version. -type CredentialIssuerKubeConfigInfo struct { - // The K8s API server URL. - // +kubebuilder:validation:MinLength=1 - // +kubebuilder:validation:Pattern=`^https://|^http://` - Server string `json:"server"` - - // The K8s API server CA bundle. - // +kubebuilder:validation:MinLength=1 - CertificateAuthorityData string `json:"certificateAuthorityData"` } // CredentialIssuerStrategy describes the status of an integration strategy that was attempted by Pinniped. diff --git a/generated/1.26/apis/concierge/config/v1alpha1/zz_generated.deepcopy.go b/generated/1.26/apis/concierge/config/v1alpha1/zz_generated.deepcopy.go index 213ff2229..d3cc37e71 100644 --- a/generated/1.26/apis/concierge/config/v1alpha1/zz_generated.deepcopy.go +++ b/generated/1.26/apis/concierge/config/v1alpha1/zz_generated.deepcopy.go @@ -66,22 +66,6 @@ func (in *CredentialIssuerFrontend) DeepCopy() *CredentialIssuerFrontend { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *CredentialIssuerKubeConfigInfo) DeepCopyInto(out *CredentialIssuerKubeConfigInfo) { - *out = *in - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CredentialIssuerKubeConfigInfo. -func (in *CredentialIssuerKubeConfigInfo) DeepCopy() *CredentialIssuerKubeConfigInfo { - if in == nil { - return nil - } - out := new(CredentialIssuerKubeConfigInfo) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *CredentialIssuerList) DeepCopyInto(out *CredentialIssuerList) { *out = *in @@ -146,11 +130,6 @@ func (in *CredentialIssuerStatus) DeepCopyInto(out *CredentialIssuerStatus) { (*in)[i].DeepCopyInto(&(*out)[i]) } } - if in.KubeConfigInfo != nil { - in, out := &in.KubeConfigInfo, &out.KubeConfigInfo - *out = new(CredentialIssuerKubeConfigInfo) - **out = **in - } return } diff --git a/generated/1.26/crds/config.concierge.pinniped.dev_credentialissuers.yaml b/generated/1.26/crds/config.concierge.pinniped.dev_credentialissuers.yaml index 6897b7968..0df5a4fe0 100644 --- a/generated/1.26/crds/config.concierge.pinniped.dev_credentialissuers.yaml +++ b/generated/1.26/crds/config.concierge.pinniped.dev_credentialissuers.yaml @@ -134,24 +134,6 @@ spec: status: description: CredentialIssuerStatus describes the status of the Concierge. properties: - kubeConfigInfo: - description: |- - Information needed to form a valid Pinniped-based kubeconfig using this credential issuer. - This field is deprecated and will be removed in a future version. - properties: - certificateAuthorityData: - description: The K8s API server CA bundle. - minLength: 1 - type: string - server: - description: The K8s API server URL. - minLength: 1 - pattern: ^https://|^http:// - type: string - required: - - certificateAuthorityData - - server - type: object strategies: description: List of integration strategies that were attempted by Pinniped. diff --git a/generated/1.27/README.adoc b/generated/1.27/README.adoc index c92144a04..eea6e51bd 100644 --- a/generated/1.27/README.adoc +++ b/generated/1.27/README.adoc @@ -429,25 +429,6 @@ This field is only set when Type is "ImpersonationProxy". + |=== -[id="{anchor_prefix}-go-pinniped-dev-generated-1-27-apis-concierge-config-v1alpha1-credentialissuerkubeconfiginfo"] -==== CredentialIssuerKubeConfigInfo - -CredentialIssuerKubeConfigInfo provides the information needed to form a valid Pinniped-based kubeconfig using this credential issuer. -This type is deprecated and will be removed in a future version. - -.Appears In: -**** -- xref:{anchor_prefix}-go-pinniped-dev-generated-1-27-apis-concierge-config-v1alpha1-credentialissuerstatus[$$CredentialIssuerStatus$$] -**** - -[cols="25a,75a", options="header"] -|=== -| Field | Description -| *`server`* __string__ | The K8s API server URL. + -| *`certificateAuthorityData`* __string__ | The K8s API server CA bundle. + -|=== - - [id="{anchor_prefix}-go-pinniped-dev-generated-1-27-apis-concierge-config-v1alpha1-credentialissuerspec"] @@ -481,8 +462,6 @@ CredentialIssuerStatus describes the status of the Concierge. |=== | Field | Description | *`strategies`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-27-apis-concierge-config-v1alpha1-credentialissuerstrategy[$$CredentialIssuerStrategy$$] array__ | List of integration strategies that were attempted by Pinniped. + -| *`kubeConfigInfo`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-27-apis-concierge-config-v1alpha1-credentialissuerkubeconfiginfo[$$CredentialIssuerKubeConfigInfo$$]__ | Information needed to form a valid Pinniped-based kubeconfig using this credential issuer. + -This field is deprecated and will be removed in a future version. + |=== diff --git a/generated/1.27/apis/concierge/config/v1alpha1/types_credentialissuer.go b/generated/1.27/apis/concierge/config/v1alpha1/types_credentialissuer.go index de976f5c1..7f80f5178 100644 --- a/generated/1.27/apis/concierge/config/v1alpha1/types_credentialissuer.go +++ b/generated/1.27/apis/concierge/config/v1alpha1/types_credentialissuer.go @@ -161,24 +161,6 @@ type ImpersonationProxyServiceSpec struct { type CredentialIssuerStatus struct { // List of integration strategies that were attempted by Pinniped. Strategies []CredentialIssuerStrategy `json:"strategies"` - - // Information needed to form a valid Pinniped-based kubeconfig using this credential issuer. - // This field is deprecated and will be removed in a future version. - // +optional - KubeConfigInfo *CredentialIssuerKubeConfigInfo `json:"kubeConfigInfo,omitempty"` -} - -// CredentialIssuerKubeConfigInfo provides the information needed to form a valid Pinniped-based kubeconfig using this credential issuer. -// This type is deprecated and will be removed in a future version. -type CredentialIssuerKubeConfigInfo struct { - // The K8s API server URL. - // +kubebuilder:validation:MinLength=1 - // +kubebuilder:validation:Pattern=`^https://|^http://` - Server string `json:"server"` - - // The K8s API server CA bundle. - // +kubebuilder:validation:MinLength=1 - CertificateAuthorityData string `json:"certificateAuthorityData"` } // CredentialIssuerStrategy describes the status of an integration strategy that was attempted by Pinniped. diff --git a/generated/1.27/apis/concierge/config/v1alpha1/zz_generated.deepcopy.go b/generated/1.27/apis/concierge/config/v1alpha1/zz_generated.deepcopy.go index 213ff2229..d3cc37e71 100644 --- a/generated/1.27/apis/concierge/config/v1alpha1/zz_generated.deepcopy.go +++ b/generated/1.27/apis/concierge/config/v1alpha1/zz_generated.deepcopy.go @@ -66,22 +66,6 @@ func (in *CredentialIssuerFrontend) DeepCopy() *CredentialIssuerFrontend { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *CredentialIssuerKubeConfigInfo) DeepCopyInto(out *CredentialIssuerKubeConfigInfo) { - *out = *in - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CredentialIssuerKubeConfigInfo. -func (in *CredentialIssuerKubeConfigInfo) DeepCopy() *CredentialIssuerKubeConfigInfo { - if in == nil { - return nil - } - out := new(CredentialIssuerKubeConfigInfo) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *CredentialIssuerList) DeepCopyInto(out *CredentialIssuerList) { *out = *in @@ -146,11 +130,6 @@ func (in *CredentialIssuerStatus) DeepCopyInto(out *CredentialIssuerStatus) { (*in)[i].DeepCopyInto(&(*out)[i]) } } - if in.KubeConfigInfo != nil { - in, out := &in.KubeConfigInfo, &out.KubeConfigInfo - *out = new(CredentialIssuerKubeConfigInfo) - **out = **in - } return } diff --git a/generated/1.27/crds/config.concierge.pinniped.dev_credentialissuers.yaml b/generated/1.27/crds/config.concierge.pinniped.dev_credentialissuers.yaml index 6897b7968..0df5a4fe0 100644 --- a/generated/1.27/crds/config.concierge.pinniped.dev_credentialissuers.yaml +++ b/generated/1.27/crds/config.concierge.pinniped.dev_credentialissuers.yaml @@ -134,24 +134,6 @@ spec: status: description: CredentialIssuerStatus describes the status of the Concierge. properties: - kubeConfigInfo: - description: |- - Information needed to form a valid Pinniped-based kubeconfig using this credential issuer. - This field is deprecated and will be removed in a future version. - properties: - certificateAuthorityData: - description: The K8s API server CA bundle. - minLength: 1 - type: string - server: - description: The K8s API server URL. - minLength: 1 - pattern: ^https://|^http:// - type: string - required: - - certificateAuthorityData - - server - type: object strategies: description: List of integration strategies that were attempted by Pinniped. diff --git a/generated/1.28/README.adoc b/generated/1.28/README.adoc index 11bab11c0..0dcf179c0 100644 --- a/generated/1.28/README.adoc +++ b/generated/1.28/README.adoc @@ -429,25 +429,6 @@ This field is only set when Type is "ImpersonationProxy". + |=== -[id="{anchor_prefix}-go-pinniped-dev-generated-1-28-apis-concierge-config-v1alpha1-credentialissuerkubeconfiginfo"] -==== CredentialIssuerKubeConfigInfo - -CredentialIssuerKubeConfigInfo provides the information needed to form a valid Pinniped-based kubeconfig using this credential issuer. -This type is deprecated and will be removed in a future version. - -.Appears In: -**** -- xref:{anchor_prefix}-go-pinniped-dev-generated-1-28-apis-concierge-config-v1alpha1-credentialissuerstatus[$$CredentialIssuerStatus$$] -**** - -[cols="25a,75a", options="header"] -|=== -| Field | Description -| *`server`* __string__ | The K8s API server URL. + -| *`certificateAuthorityData`* __string__ | The K8s API server CA bundle. + -|=== - - [id="{anchor_prefix}-go-pinniped-dev-generated-1-28-apis-concierge-config-v1alpha1-credentialissuerspec"] @@ -481,8 +462,6 @@ CredentialIssuerStatus describes the status of the Concierge. |=== | Field | Description | *`strategies`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-28-apis-concierge-config-v1alpha1-credentialissuerstrategy[$$CredentialIssuerStrategy$$] array__ | List of integration strategies that were attempted by Pinniped. + -| *`kubeConfigInfo`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-28-apis-concierge-config-v1alpha1-credentialissuerkubeconfiginfo[$$CredentialIssuerKubeConfigInfo$$]__ | Information needed to form a valid Pinniped-based kubeconfig using this credential issuer. + -This field is deprecated and will be removed in a future version. + |=== diff --git a/generated/1.28/apis/concierge/config/v1alpha1/types_credentialissuer.go b/generated/1.28/apis/concierge/config/v1alpha1/types_credentialissuer.go index de976f5c1..7f80f5178 100644 --- a/generated/1.28/apis/concierge/config/v1alpha1/types_credentialissuer.go +++ b/generated/1.28/apis/concierge/config/v1alpha1/types_credentialissuer.go @@ -161,24 +161,6 @@ type ImpersonationProxyServiceSpec struct { type CredentialIssuerStatus struct { // List of integration strategies that were attempted by Pinniped. Strategies []CredentialIssuerStrategy `json:"strategies"` - - // Information needed to form a valid Pinniped-based kubeconfig using this credential issuer. - // This field is deprecated and will be removed in a future version. - // +optional - KubeConfigInfo *CredentialIssuerKubeConfigInfo `json:"kubeConfigInfo,omitempty"` -} - -// CredentialIssuerKubeConfigInfo provides the information needed to form a valid Pinniped-based kubeconfig using this credential issuer. -// This type is deprecated and will be removed in a future version. -type CredentialIssuerKubeConfigInfo struct { - // The K8s API server URL. - // +kubebuilder:validation:MinLength=1 - // +kubebuilder:validation:Pattern=`^https://|^http://` - Server string `json:"server"` - - // The K8s API server CA bundle. - // +kubebuilder:validation:MinLength=1 - CertificateAuthorityData string `json:"certificateAuthorityData"` } // CredentialIssuerStrategy describes the status of an integration strategy that was attempted by Pinniped. diff --git a/generated/1.28/apis/concierge/config/v1alpha1/zz_generated.deepcopy.go b/generated/1.28/apis/concierge/config/v1alpha1/zz_generated.deepcopy.go index 213ff2229..d3cc37e71 100644 --- a/generated/1.28/apis/concierge/config/v1alpha1/zz_generated.deepcopy.go +++ b/generated/1.28/apis/concierge/config/v1alpha1/zz_generated.deepcopy.go @@ -66,22 +66,6 @@ func (in *CredentialIssuerFrontend) DeepCopy() *CredentialIssuerFrontend { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *CredentialIssuerKubeConfigInfo) DeepCopyInto(out *CredentialIssuerKubeConfigInfo) { - *out = *in - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CredentialIssuerKubeConfigInfo. -func (in *CredentialIssuerKubeConfigInfo) DeepCopy() *CredentialIssuerKubeConfigInfo { - if in == nil { - return nil - } - out := new(CredentialIssuerKubeConfigInfo) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *CredentialIssuerList) DeepCopyInto(out *CredentialIssuerList) { *out = *in @@ -146,11 +130,6 @@ func (in *CredentialIssuerStatus) DeepCopyInto(out *CredentialIssuerStatus) { (*in)[i].DeepCopyInto(&(*out)[i]) } } - if in.KubeConfigInfo != nil { - in, out := &in.KubeConfigInfo, &out.KubeConfigInfo - *out = new(CredentialIssuerKubeConfigInfo) - **out = **in - } return } diff --git a/generated/1.28/crds/config.concierge.pinniped.dev_credentialissuers.yaml b/generated/1.28/crds/config.concierge.pinniped.dev_credentialissuers.yaml index 6897b7968..0df5a4fe0 100644 --- a/generated/1.28/crds/config.concierge.pinniped.dev_credentialissuers.yaml +++ b/generated/1.28/crds/config.concierge.pinniped.dev_credentialissuers.yaml @@ -134,24 +134,6 @@ spec: status: description: CredentialIssuerStatus describes the status of the Concierge. properties: - kubeConfigInfo: - description: |- - Information needed to form a valid Pinniped-based kubeconfig using this credential issuer. - This field is deprecated and will be removed in a future version. - properties: - certificateAuthorityData: - description: The K8s API server CA bundle. - minLength: 1 - type: string - server: - description: The K8s API server URL. - minLength: 1 - pattern: ^https://|^http:// - type: string - required: - - certificateAuthorityData - - server - type: object strategies: description: List of integration strategies that were attempted by Pinniped. diff --git a/generated/1.29/README.adoc b/generated/1.29/README.adoc index 17c21cf5c..31cfffc46 100644 --- a/generated/1.29/README.adoc +++ b/generated/1.29/README.adoc @@ -429,25 +429,6 @@ This field is only set when Type is "ImpersonationProxy". + |=== -[id="{anchor_prefix}-go-pinniped-dev-generated-1-29-apis-concierge-config-v1alpha1-credentialissuerkubeconfiginfo"] -==== CredentialIssuerKubeConfigInfo - -CredentialIssuerKubeConfigInfo provides the information needed to form a valid Pinniped-based kubeconfig using this credential issuer. -This type is deprecated and will be removed in a future version. - -.Appears In: -**** -- xref:{anchor_prefix}-go-pinniped-dev-generated-1-29-apis-concierge-config-v1alpha1-credentialissuerstatus[$$CredentialIssuerStatus$$] -**** - -[cols="25a,75a", options="header"] -|=== -| Field | Description -| *`server`* __string__ | The K8s API server URL. + -| *`certificateAuthorityData`* __string__ | The K8s API server CA bundle. + -|=== - - [id="{anchor_prefix}-go-pinniped-dev-generated-1-29-apis-concierge-config-v1alpha1-credentialissuerspec"] @@ -481,8 +462,6 @@ CredentialIssuerStatus describes the status of the Concierge. |=== | Field | Description | *`strategies`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-29-apis-concierge-config-v1alpha1-credentialissuerstrategy[$$CredentialIssuerStrategy$$] array__ | List of integration strategies that were attempted by Pinniped. + -| *`kubeConfigInfo`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-29-apis-concierge-config-v1alpha1-credentialissuerkubeconfiginfo[$$CredentialIssuerKubeConfigInfo$$]__ | Information needed to form a valid Pinniped-based kubeconfig using this credential issuer. + -This field is deprecated and will be removed in a future version. + |=== diff --git a/generated/1.29/apis/concierge/config/v1alpha1/types_credentialissuer.go b/generated/1.29/apis/concierge/config/v1alpha1/types_credentialissuer.go index de976f5c1..7f80f5178 100644 --- a/generated/1.29/apis/concierge/config/v1alpha1/types_credentialissuer.go +++ b/generated/1.29/apis/concierge/config/v1alpha1/types_credentialissuer.go @@ -161,24 +161,6 @@ type ImpersonationProxyServiceSpec struct { type CredentialIssuerStatus struct { // List of integration strategies that were attempted by Pinniped. Strategies []CredentialIssuerStrategy `json:"strategies"` - - // Information needed to form a valid Pinniped-based kubeconfig using this credential issuer. - // This field is deprecated and will be removed in a future version. - // +optional - KubeConfigInfo *CredentialIssuerKubeConfigInfo `json:"kubeConfigInfo,omitempty"` -} - -// CredentialIssuerKubeConfigInfo provides the information needed to form a valid Pinniped-based kubeconfig using this credential issuer. -// This type is deprecated and will be removed in a future version. -type CredentialIssuerKubeConfigInfo struct { - // The K8s API server URL. - // +kubebuilder:validation:MinLength=1 - // +kubebuilder:validation:Pattern=`^https://|^http://` - Server string `json:"server"` - - // The K8s API server CA bundle. - // +kubebuilder:validation:MinLength=1 - CertificateAuthorityData string `json:"certificateAuthorityData"` } // CredentialIssuerStrategy describes the status of an integration strategy that was attempted by Pinniped. diff --git a/generated/1.29/apis/concierge/config/v1alpha1/zz_generated.deepcopy.go b/generated/1.29/apis/concierge/config/v1alpha1/zz_generated.deepcopy.go index 213ff2229..d3cc37e71 100644 --- a/generated/1.29/apis/concierge/config/v1alpha1/zz_generated.deepcopy.go +++ b/generated/1.29/apis/concierge/config/v1alpha1/zz_generated.deepcopy.go @@ -66,22 +66,6 @@ func (in *CredentialIssuerFrontend) DeepCopy() *CredentialIssuerFrontend { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *CredentialIssuerKubeConfigInfo) DeepCopyInto(out *CredentialIssuerKubeConfigInfo) { - *out = *in - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CredentialIssuerKubeConfigInfo. -func (in *CredentialIssuerKubeConfigInfo) DeepCopy() *CredentialIssuerKubeConfigInfo { - if in == nil { - return nil - } - out := new(CredentialIssuerKubeConfigInfo) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *CredentialIssuerList) DeepCopyInto(out *CredentialIssuerList) { *out = *in @@ -146,11 +130,6 @@ func (in *CredentialIssuerStatus) DeepCopyInto(out *CredentialIssuerStatus) { (*in)[i].DeepCopyInto(&(*out)[i]) } } - if in.KubeConfigInfo != nil { - in, out := &in.KubeConfigInfo, &out.KubeConfigInfo - *out = new(CredentialIssuerKubeConfigInfo) - **out = **in - } return } diff --git a/generated/1.29/crds/config.concierge.pinniped.dev_credentialissuers.yaml b/generated/1.29/crds/config.concierge.pinniped.dev_credentialissuers.yaml index 6897b7968..0df5a4fe0 100644 --- a/generated/1.29/crds/config.concierge.pinniped.dev_credentialissuers.yaml +++ b/generated/1.29/crds/config.concierge.pinniped.dev_credentialissuers.yaml @@ -134,24 +134,6 @@ spec: status: description: CredentialIssuerStatus describes the status of the Concierge. properties: - kubeConfigInfo: - description: |- - Information needed to form a valid Pinniped-based kubeconfig using this credential issuer. - This field is deprecated and will be removed in a future version. - properties: - certificateAuthorityData: - description: The K8s API server CA bundle. - minLength: 1 - type: string - server: - description: The K8s API server URL. - minLength: 1 - pattern: ^https://|^http:// - type: string - required: - - certificateAuthorityData - - server - type: object strategies: description: List of integration strategies that were attempted by Pinniped. diff --git a/generated/1.30/README.adoc b/generated/1.30/README.adoc index 0659827b6..de2770bba 100644 --- a/generated/1.30/README.adoc +++ b/generated/1.30/README.adoc @@ -429,25 +429,6 @@ This field is only set when Type is "ImpersonationProxy". + |=== -[id="{anchor_prefix}-go-pinniped-dev-generated-1-30-apis-concierge-config-v1alpha1-credentialissuerkubeconfiginfo"] -==== CredentialIssuerKubeConfigInfo - -CredentialIssuerKubeConfigInfo provides the information needed to form a valid Pinniped-based kubeconfig using this credential issuer. -This type is deprecated and will be removed in a future version. - -.Appears In: -**** -- xref:{anchor_prefix}-go-pinniped-dev-generated-1-30-apis-concierge-config-v1alpha1-credentialissuerstatus[$$CredentialIssuerStatus$$] -**** - -[cols="25a,75a", options="header"] -|=== -| Field | Description -| *`server`* __string__ | The K8s API server URL. + -| *`certificateAuthorityData`* __string__ | The K8s API server CA bundle. + -|=== - - [id="{anchor_prefix}-go-pinniped-dev-generated-1-30-apis-concierge-config-v1alpha1-credentialissuerspec"] @@ -481,8 +462,6 @@ CredentialIssuerStatus describes the status of the Concierge. |=== | Field | Description | *`strategies`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-30-apis-concierge-config-v1alpha1-credentialissuerstrategy[$$CredentialIssuerStrategy$$] array__ | List of integration strategies that were attempted by Pinniped. + -| *`kubeConfigInfo`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-30-apis-concierge-config-v1alpha1-credentialissuerkubeconfiginfo[$$CredentialIssuerKubeConfigInfo$$]__ | Information needed to form a valid Pinniped-based kubeconfig using this credential issuer. + -This field is deprecated and will be removed in a future version. + |=== diff --git a/generated/1.30/apis/concierge/config/v1alpha1/types_credentialissuer.go b/generated/1.30/apis/concierge/config/v1alpha1/types_credentialissuer.go index de976f5c1..7f80f5178 100644 --- a/generated/1.30/apis/concierge/config/v1alpha1/types_credentialissuer.go +++ b/generated/1.30/apis/concierge/config/v1alpha1/types_credentialissuer.go @@ -161,24 +161,6 @@ type ImpersonationProxyServiceSpec struct { type CredentialIssuerStatus struct { // List of integration strategies that were attempted by Pinniped. Strategies []CredentialIssuerStrategy `json:"strategies"` - - // Information needed to form a valid Pinniped-based kubeconfig using this credential issuer. - // This field is deprecated and will be removed in a future version. - // +optional - KubeConfigInfo *CredentialIssuerKubeConfigInfo `json:"kubeConfigInfo,omitempty"` -} - -// CredentialIssuerKubeConfigInfo provides the information needed to form a valid Pinniped-based kubeconfig using this credential issuer. -// This type is deprecated and will be removed in a future version. -type CredentialIssuerKubeConfigInfo struct { - // The K8s API server URL. - // +kubebuilder:validation:MinLength=1 - // +kubebuilder:validation:Pattern=`^https://|^http://` - Server string `json:"server"` - - // The K8s API server CA bundle. - // +kubebuilder:validation:MinLength=1 - CertificateAuthorityData string `json:"certificateAuthorityData"` } // CredentialIssuerStrategy describes the status of an integration strategy that was attempted by Pinniped. diff --git a/generated/1.30/apis/concierge/config/v1alpha1/zz_generated.deepcopy.go b/generated/1.30/apis/concierge/config/v1alpha1/zz_generated.deepcopy.go index 213ff2229..d3cc37e71 100644 --- a/generated/1.30/apis/concierge/config/v1alpha1/zz_generated.deepcopy.go +++ b/generated/1.30/apis/concierge/config/v1alpha1/zz_generated.deepcopy.go @@ -66,22 +66,6 @@ func (in *CredentialIssuerFrontend) DeepCopy() *CredentialIssuerFrontend { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *CredentialIssuerKubeConfigInfo) DeepCopyInto(out *CredentialIssuerKubeConfigInfo) { - *out = *in - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CredentialIssuerKubeConfigInfo. -func (in *CredentialIssuerKubeConfigInfo) DeepCopy() *CredentialIssuerKubeConfigInfo { - if in == nil { - return nil - } - out := new(CredentialIssuerKubeConfigInfo) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *CredentialIssuerList) DeepCopyInto(out *CredentialIssuerList) { *out = *in @@ -146,11 +130,6 @@ func (in *CredentialIssuerStatus) DeepCopyInto(out *CredentialIssuerStatus) { (*in)[i].DeepCopyInto(&(*out)[i]) } } - if in.KubeConfigInfo != nil { - in, out := &in.KubeConfigInfo, &out.KubeConfigInfo - *out = new(CredentialIssuerKubeConfigInfo) - **out = **in - } return } diff --git a/generated/1.30/crds/config.concierge.pinniped.dev_credentialissuers.yaml b/generated/1.30/crds/config.concierge.pinniped.dev_credentialissuers.yaml index 6897b7968..0df5a4fe0 100644 --- a/generated/1.30/crds/config.concierge.pinniped.dev_credentialissuers.yaml +++ b/generated/1.30/crds/config.concierge.pinniped.dev_credentialissuers.yaml @@ -134,24 +134,6 @@ spec: status: description: CredentialIssuerStatus describes the status of the Concierge. properties: - kubeConfigInfo: - description: |- - Information needed to form a valid Pinniped-based kubeconfig using this credential issuer. - This field is deprecated and will be removed in a future version. - properties: - certificateAuthorityData: - description: The K8s API server CA bundle. - minLength: 1 - type: string - server: - description: The K8s API server URL. - minLength: 1 - pattern: ^https://|^http:// - type: string - required: - - certificateAuthorityData - - server - type: object strategies: description: List of integration strategies that were attempted by Pinniped. diff --git a/generated/1.31/README.adoc b/generated/1.31/README.adoc index ba03e684a..c328a8985 100644 --- a/generated/1.31/README.adoc +++ b/generated/1.31/README.adoc @@ -429,25 +429,6 @@ This field is only set when Type is "ImpersonationProxy". + |=== -[id="{anchor_prefix}-go-pinniped-dev-generated-1-31-apis-concierge-config-v1alpha1-credentialissuerkubeconfiginfo"] -==== CredentialIssuerKubeConfigInfo - -CredentialIssuerKubeConfigInfo provides the information needed to form a valid Pinniped-based kubeconfig using this credential issuer. -This type is deprecated and will be removed in a future version. - -.Appears In: -**** -- xref:{anchor_prefix}-go-pinniped-dev-generated-1-31-apis-concierge-config-v1alpha1-credentialissuerstatus[$$CredentialIssuerStatus$$] -**** - -[cols="25a,75a", options="header"] -|=== -| Field | Description -| *`server`* __string__ | The K8s API server URL. + -| *`certificateAuthorityData`* __string__ | The K8s API server CA bundle. + -|=== - - [id="{anchor_prefix}-go-pinniped-dev-generated-1-31-apis-concierge-config-v1alpha1-credentialissuerspec"] @@ -481,8 +462,6 @@ CredentialIssuerStatus describes the status of the Concierge. |=== | Field | Description | *`strategies`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-31-apis-concierge-config-v1alpha1-credentialissuerstrategy[$$CredentialIssuerStrategy$$] array__ | List of integration strategies that were attempted by Pinniped. + -| *`kubeConfigInfo`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-31-apis-concierge-config-v1alpha1-credentialissuerkubeconfiginfo[$$CredentialIssuerKubeConfigInfo$$]__ | Information needed to form a valid Pinniped-based kubeconfig using this credential issuer. + -This field is deprecated and will be removed in a future version. + |=== diff --git a/generated/1.31/apis/concierge/config/v1alpha1/types_credentialissuer.go b/generated/1.31/apis/concierge/config/v1alpha1/types_credentialissuer.go index de976f5c1..7f80f5178 100644 --- a/generated/1.31/apis/concierge/config/v1alpha1/types_credentialissuer.go +++ b/generated/1.31/apis/concierge/config/v1alpha1/types_credentialissuer.go @@ -161,24 +161,6 @@ type ImpersonationProxyServiceSpec struct { type CredentialIssuerStatus struct { // List of integration strategies that were attempted by Pinniped. Strategies []CredentialIssuerStrategy `json:"strategies"` - - // Information needed to form a valid Pinniped-based kubeconfig using this credential issuer. - // This field is deprecated and will be removed in a future version. - // +optional - KubeConfigInfo *CredentialIssuerKubeConfigInfo `json:"kubeConfigInfo,omitempty"` -} - -// CredentialIssuerKubeConfigInfo provides the information needed to form a valid Pinniped-based kubeconfig using this credential issuer. -// This type is deprecated and will be removed in a future version. -type CredentialIssuerKubeConfigInfo struct { - // The K8s API server URL. - // +kubebuilder:validation:MinLength=1 - // +kubebuilder:validation:Pattern=`^https://|^http://` - Server string `json:"server"` - - // The K8s API server CA bundle. - // +kubebuilder:validation:MinLength=1 - CertificateAuthorityData string `json:"certificateAuthorityData"` } // CredentialIssuerStrategy describes the status of an integration strategy that was attempted by Pinniped. diff --git a/generated/1.31/apis/concierge/config/v1alpha1/zz_generated.deepcopy.go b/generated/1.31/apis/concierge/config/v1alpha1/zz_generated.deepcopy.go index 213ff2229..d3cc37e71 100644 --- a/generated/1.31/apis/concierge/config/v1alpha1/zz_generated.deepcopy.go +++ b/generated/1.31/apis/concierge/config/v1alpha1/zz_generated.deepcopy.go @@ -66,22 +66,6 @@ func (in *CredentialIssuerFrontend) DeepCopy() *CredentialIssuerFrontend { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *CredentialIssuerKubeConfigInfo) DeepCopyInto(out *CredentialIssuerKubeConfigInfo) { - *out = *in - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CredentialIssuerKubeConfigInfo. -func (in *CredentialIssuerKubeConfigInfo) DeepCopy() *CredentialIssuerKubeConfigInfo { - if in == nil { - return nil - } - out := new(CredentialIssuerKubeConfigInfo) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *CredentialIssuerList) DeepCopyInto(out *CredentialIssuerList) { *out = *in @@ -146,11 +130,6 @@ func (in *CredentialIssuerStatus) DeepCopyInto(out *CredentialIssuerStatus) { (*in)[i].DeepCopyInto(&(*out)[i]) } } - if in.KubeConfigInfo != nil { - in, out := &in.KubeConfigInfo, &out.KubeConfigInfo - *out = new(CredentialIssuerKubeConfigInfo) - **out = **in - } return } diff --git a/generated/1.31/crds/config.concierge.pinniped.dev_credentialissuers.yaml b/generated/1.31/crds/config.concierge.pinniped.dev_credentialissuers.yaml index 6897b7968..0df5a4fe0 100644 --- a/generated/1.31/crds/config.concierge.pinniped.dev_credentialissuers.yaml +++ b/generated/1.31/crds/config.concierge.pinniped.dev_credentialissuers.yaml @@ -134,24 +134,6 @@ spec: status: description: CredentialIssuerStatus describes the status of the Concierge. properties: - kubeConfigInfo: - description: |- - Information needed to form a valid Pinniped-based kubeconfig using this credential issuer. - This field is deprecated and will be removed in a future version. - properties: - certificateAuthorityData: - description: The K8s API server CA bundle. - minLength: 1 - type: string - server: - description: The K8s API server URL. - minLength: 1 - pattern: ^https://|^http:// - type: string - required: - - certificateAuthorityData - - server - type: object strategies: description: List of integration strategies that were attempted by Pinniped. diff --git a/generated/latest/README.adoc b/generated/latest/README.adoc index ba03e684a..c328a8985 100644 --- a/generated/latest/README.adoc +++ b/generated/latest/README.adoc @@ -429,25 +429,6 @@ This field is only set when Type is "ImpersonationProxy". + |=== -[id="{anchor_prefix}-go-pinniped-dev-generated-1-31-apis-concierge-config-v1alpha1-credentialissuerkubeconfiginfo"] -==== CredentialIssuerKubeConfigInfo - -CredentialIssuerKubeConfigInfo provides the information needed to form a valid Pinniped-based kubeconfig using this credential issuer. -This type is deprecated and will be removed in a future version. - -.Appears In: -**** -- xref:{anchor_prefix}-go-pinniped-dev-generated-1-31-apis-concierge-config-v1alpha1-credentialissuerstatus[$$CredentialIssuerStatus$$] -**** - -[cols="25a,75a", options="header"] -|=== -| Field | Description -| *`server`* __string__ | The K8s API server URL. + -| *`certificateAuthorityData`* __string__ | The K8s API server CA bundle. + -|=== - - [id="{anchor_prefix}-go-pinniped-dev-generated-1-31-apis-concierge-config-v1alpha1-credentialissuerspec"] @@ -481,8 +462,6 @@ CredentialIssuerStatus describes the status of the Concierge. |=== | Field | Description | *`strategies`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-31-apis-concierge-config-v1alpha1-credentialissuerstrategy[$$CredentialIssuerStrategy$$] array__ | List of integration strategies that were attempted by Pinniped. + -| *`kubeConfigInfo`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-31-apis-concierge-config-v1alpha1-credentialissuerkubeconfiginfo[$$CredentialIssuerKubeConfigInfo$$]__ | Information needed to form a valid Pinniped-based kubeconfig using this credential issuer. + -This field is deprecated and will be removed in a future version. + |=== diff --git a/generated/latest/apis/concierge/config/v1alpha1/types_credentialissuer.go b/generated/latest/apis/concierge/config/v1alpha1/types_credentialissuer.go index de976f5c1..7f80f5178 100644 --- a/generated/latest/apis/concierge/config/v1alpha1/types_credentialissuer.go +++ b/generated/latest/apis/concierge/config/v1alpha1/types_credentialissuer.go @@ -161,24 +161,6 @@ type ImpersonationProxyServiceSpec struct { type CredentialIssuerStatus struct { // List of integration strategies that were attempted by Pinniped. Strategies []CredentialIssuerStrategy `json:"strategies"` - - // Information needed to form a valid Pinniped-based kubeconfig using this credential issuer. - // This field is deprecated and will be removed in a future version. - // +optional - KubeConfigInfo *CredentialIssuerKubeConfigInfo `json:"kubeConfigInfo,omitempty"` -} - -// CredentialIssuerKubeConfigInfo provides the information needed to form a valid Pinniped-based kubeconfig using this credential issuer. -// This type is deprecated and will be removed in a future version. -type CredentialIssuerKubeConfigInfo struct { - // The K8s API server URL. - // +kubebuilder:validation:MinLength=1 - // +kubebuilder:validation:Pattern=`^https://|^http://` - Server string `json:"server"` - - // The K8s API server CA bundle. - // +kubebuilder:validation:MinLength=1 - CertificateAuthorityData string `json:"certificateAuthorityData"` } // CredentialIssuerStrategy describes the status of an integration strategy that was attempted by Pinniped. diff --git a/generated/latest/apis/concierge/config/v1alpha1/zz_generated.deepcopy.go b/generated/latest/apis/concierge/config/v1alpha1/zz_generated.deepcopy.go index 213ff2229..d3cc37e71 100644 --- a/generated/latest/apis/concierge/config/v1alpha1/zz_generated.deepcopy.go +++ b/generated/latest/apis/concierge/config/v1alpha1/zz_generated.deepcopy.go @@ -66,22 +66,6 @@ func (in *CredentialIssuerFrontend) DeepCopy() *CredentialIssuerFrontend { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *CredentialIssuerKubeConfigInfo) DeepCopyInto(out *CredentialIssuerKubeConfigInfo) { - *out = *in - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CredentialIssuerKubeConfigInfo. -func (in *CredentialIssuerKubeConfigInfo) DeepCopy() *CredentialIssuerKubeConfigInfo { - if in == nil { - return nil - } - out := new(CredentialIssuerKubeConfigInfo) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *CredentialIssuerList) DeepCopyInto(out *CredentialIssuerList) { *out = *in @@ -146,11 +130,6 @@ func (in *CredentialIssuerStatus) DeepCopyInto(out *CredentialIssuerStatus) { (*in)[i].DeepCopyInto(&(*out)[i]) } } - if in.KubeConfigInfo != nil { - in, out := &in.KubeConfigInfo, &out.KubeConfigInfo - *out = new(CredentialIssuerKubeConfigInfo) - **out = **in - } return } diff --git a/internal/controller/issuerconfig/issuerconfig.go b/internal/controller/issuerconfig/issuerconfig.go index faea9ad30..7696be103 100644 --- a/internal/controller/issuerconfig/issuerconfig.go +++ b/internal/controller/issuerconfig/issuerconfig.go @@ -49,14 +49,6 @@ func mergeStrategy(configToUpdate *conciergeconfigv1alpha1.CredentialIssuerStatu configToUpdate.Strategies = append(configToUpdate.Strategies, strategy) } sort.Stable(sortableStrategies(configToUpdate.Strategies)) - - // Special case: the "TokenCredentialRequestAPI" data is mirrored into the deprecated status.kubeConfigInfo field. - if strategy.Frontend != nil && strategy.Frontend.Type == conciergeconfigv1alpha1.TokenCredentialRequestAPIFrontendType { - configToUpdate.KubeConfigInfo = &conciergeconfigv1alpha1.CredentialIssuerKubeConfigInfo{ - Server: strategy.Frontend.TokenCredentialRequestAPIInfo.Server, - CertificateAuthorityData: strategy.Frontend.TokenCredentialRequestAPIInfo.CertificateAuthorityData, - } - } } // weights are a set of priorities for each strategy type. diff --git a/internal/controller/issuerconfig/issuerconfig_test.go b/internal/controller/issuerconfig/issuerconfig_test.go index f671c03ea..4ce007878 100644 --- a/internal/controller/issuerconfig/issuerconfig_test.go +++ b/internal/controller/issuerconfig/issuerconfig_test.go @@ -87,10 +87,6 @@ func TestMergeStrategy(t *testing.T) { }, }, }, - KubeConfigInfo: &conciergeconfigv1alpha1.CredentialIssuerKubeConfigInfo{ - Server: "https://test-server", - CertificateAuthorityData: "test-ca-bundle", - }, }, }, { diff --git a/test/integration/concierge_credentialissuer_test.go b/test/integration/concierge_credentialissuer_test.go index 3ebb5de06..a7b401dad 100644 --- a/test/integration/concierge_credentialissuer_test.go +++ b/test/integration/concierge_credentialissuer_test.go @@ -36,7 +36,6 @@ func TestCredentialIssuer(t *testing.T) { require.Len(t, actualConfigList.Items, 1) actualConfig := actualConfigList.Items[0] - actualStatusKubeConfigInfo := actualConfigList.Items[0].Status.KubeConfigInfo for k, v := range env.ConciergeCustomLabels { require.Equalf(t, v, actualConfig.Labels[k], "expected ci to have label `%s: %s`", k, v) @@ -77,22 +76,11 @@ func TestCredentialIssuer(t *testing.T) { CertificateAuthorityData: base64.StdEncoding.EncodeToString(config.TLSClientConfig.CAData), } require.Equal(t, &expectedTokenRequestAPIInfo, actualStatusStrategy.Frontend.TokenCredentialRequestAPIInfo) - - // Verify the published kube config info. - require.Equal( - t, - &conciergeconfigv1alpha1.CredentialIssuerKubeConfigInfo{ - Server: expectedTokenRequestAPIInfo.Server, - CertificateAuthorityData: expectedTokenRequestAPIInfo.CertificateAuthorityData, - }, - actualStatusKubeConfigInfo, - ) } else { require.Equal(t, conciergeconfigv1alpha1.ErrorStrategyStatus, actualStatusStrategy.Status) require.Equal(t, conciergeconfigv1alpha1.CouldNotFetchKeyStrategyReason, actualStatusStrategy.Reason) require.Contains(t, actualStatusStrategy.Message, "could not find a healthy kube-controller-manager pod (0 candidates): "+ "note that this error is the expected behavior for some cluster types, including most cloud provider clusters (e.g. GKE, AKS, EKS)") - require.Nil(t, actualStatusKubeConfigInfo) } }) } diff --git a/test/integration/kube_api_discovery_test.go b/test/integration/kube_api_discovery_test.go index a166e552d..94bc399a3 100644 --- a/test/integration/kube_api_discovery_test.go +++ b/test/integration/kube_api_discovery_test.go @@ -452,7 +452,7 @@ func TestGetAPIResourceList(t *testing.T) { //nolint:gocyclo // each t.Run is pr } // manually update this value whenever you add additional fields to an API resource and then run the generator - totalExpectedAPIFields := 313 + totalExpectedAPIFields := 310 // Because we are parsing text from `kubectl explain` and because the format of that text can change // over time, make a rudimentary assertion that this test exercised the whole tree of all fields of all From c0c88e1268ea71c10a1c95c05b29e0847e5dd349 Mon Sep 17 00:00:00 2001 From: Joshua Casey Date: Fri, 27 Dec 2024 15:41:03 -0600 Subject: [PATCH 5/6] Make sure each FederationDomain has a unique name, and skip CEL tests for old K8s versions --- ...supervisor_federationdomain_status_test.go | 338 ++++++++---------- 1 file changed, 148 insertions(+), 190 deletions(-) diff --git a/test/integration/supervisor_federationdomain_status_test.go b/test/integration/supervisor_federationdomain_status_test.go index 9e9b5d160..46774e315 100644 --- a/test/integration/supervisor_federationdomain_status_test.go +++ b/test/integration/supervisor_federationdomain_status_test.go @@ -569,11 +569,9 @@ func TestSupervisorFederationDomainCRDValidations_Parallel(t *testing.T) { performCELTests := testutil.KubeServerMinorVersionAtLeastInclusive(t, adminClient.Discovery(), 27) - objectMeta := testlib.ObjectMetaWithRandomName(t, "federation-domain") - tests := []struct { name string - fd *supervisorconfigv1alpha1.FederationDomain + spec *supervisorconfigv1alpha1.FederationDomainSpec wantErrs []string wantCELErrs []string @@ -584,47 +582,35 @@ func TestSupervisorFederationDomainCRDValidations_Parallel(t *testing.T) { }{ { name: "issuer cannot be empty", - fd: &supervisorconfigv1alpha1.FederationDomain{ - ObjectMeta: objectMeta, - Spec: supervisorconfigv1alpha1.FederationDomainSpec{ - Issuer: "", - }, + spec: &supervisorconfigv1alpha1.FederationDomainSpec{ + Issuer: "", }, wantErrs: []string{`spec.issuer: Invalid value: "": spec.issuer in body should be at least 1 chars long`}, wantCELErrs: []string{`spec.issuer: Invalid value: "string": issuer must be an HTTPS URL`}, }, { name: "issuer must be a URL", - fd: &supervisorconfigv1alpha1.FederationDomain{ - ObjectMeta: objectMeta, - Spec: supervisorconfigv1alpha1.FederationDomainSpec{ - Issuer: "foo", - }, + spec: &supervisorconfigv1alpha1.FederationDomainSpec{ + Issuer: "foo", }, wantCELErrs: []string{`spec.issuer: Invalid value: "string": issuer must be an HTTPS URL`}, }, { name: "issuer URL scheme must be 'https'", - fd: &supervisorconfigv1alpha1.FederationDomain{ - ObjectMeta: objectMeta, - Spec: supervisorconfigv1alpha1.FederationDomainSpec{ - Issuer: "http://example.com", - }, + spec: &supervisorconfigv1alpha1.FederationDomainSpec{ + Issuer: "http://example.com", }, wantCELErrs: []string{`spec.issuer: Invalid value: "string": issuer must be an HTTPS URL`}, }, { name: "IDP display names cannot be empty", - fd: &supervisorconfigv1alpha1.FederationDomain{ - ObjectMeta: objectMeta, - Spec: supervisorconfigv1alpha1.FederationDomainSpec{ - Issuer: "https://example.com", - IdentityProviders: []supervisorconfigv1alpha1.FederationDomainIdentityProvider{ - { - DisplayName: "", - ObjectRef: corev1.TypedLocalObjectReference{ - APIGroup: ptr.To("required in older versions of Kubernetes for each item in the identityProviders slice"), - }, + spec: &supervisorconfigv1alpha1.FederationDomainSpec{ + Issuer: "https://example.com", + IdentityProviders: []supervisorconfigv1alpha1.FederationDomainIdentityProvider{ + { + DisplayName: "", + ObjectRef: corev1.TypedLocalObjectReference{ + APIGroup: ptr.To("required in older versions of Kubernetes for each item in the identityProviders slice"), }, }, }, @@ -633,21 +619,18 @@ func TestSupervisorFederationDomainCRDValidations_Parallel(t *testing.T) { }, { name: "IDP transform constants must have unique names", - fd: &supervisorconfigv1alpha1.FederationDomain{ - ObjectMeta: objectMeta, - Spec: supervisorconfigv1alpha1.FederationDomainSpec{ - Issuer: "https://example.com", - IdentityProviders: []supervisorconfigv1alpha1.FederationDomainIdentityProvider{ - { - DisplayName: "foo", - ObjectRef: corev1.TypedLocalObjectReference{ - APIGroup: ptr.To("required in older versions of Kubernetes for each item in the identityProviders slice"), - }, - Transforms: supervisorconfigv1alpha1.FederationDomainTransforms{ - Constants: []supervisorconfigv1alpha1.FederationDomainTransformsConstant{ - {Name: "notUnique", Type: "string", StringValue: "foo"}, - {Name: "notUnique", Type: "string", StringValue: "bar"}, - }, + spec: &supervisorconfigv1alpha1.FederationDomainSpec{ + Issuer: "https://example.com", + IdentityProviders: []supervisorconfigv1alpha1.FederationDomainIdentityProvider{ + { + DisplayName: "foo", + ObjectRef: corev1.TypedLocalObjectReference{ + APIGroup: ptr.To("required in older versions of Kubernetes for each item in the identityProviders slice"), + }, + Transforms: supervisorconfigv1alpha1.FederationDomainTransforms{ + Constants: []supervisorconfigv1alpha1.FederationDomainTransformsConstant{ + {Name: "notUnique", Type: "string", StringValue: "foo"}, + {Name: "notUnique", Type: "string", StringValue: "bar"}, }, }, }, @@ -657,20 +640,17 @@ func TestSupervisorFederationDomainCRDValidations_Parallel(t *testing.T) { }, { name: "IDP transform constant names cannot be empty", - fd: &supervisorconfigv1alpha1.FederationDomain{ - ObjectMeta: objectMeta, - Spec: supervisorconfigv1alpha1.FederationDomainSpec{ - Issuer: "https://example.com", - IdentityProviders: []supervisorconfigv1alpha1.FederationDomainIdentityProvider{ - { - DisplayName: "foo", - ObjectRef: corev1.TypedLocalObjectReference{ - APIGroup: ptr.To("required in older versions of Kubernetes for each item in the identityProviders slice"), - }, - Transforms: supervisorconfigv1alpha1.FederationDomainTransforms{ - Constants: []supervisorconfigv1alpha1.FederationDomainTransformsConstant{ - {Name: "", Type: "string"}, - }, + spec: &supervisorconfigv1alpha1.FederationDomainSpec{ + Issuer: "https://example.com", + IdentityProviders: []supervisorconfigv1alpha1.FederationDomainIdentityProvider{ + { + DisplayName: "foo", + ObjectRef: corev1.TypedLocalObjectReference{ + APIGroup: ptr.To("required in older versions of Kubernetes for each item in the identityProviders slice"), + }, + Transforms: supervisorconfigv1alpha1.FederationDomainTransforms{ + Constants: []supervisorconfigv1alpha1.FederationDomainTransformsConstant{ + {Name: "", Type: "string"}, }, }, }, @@ -680,20 +660,17 @@ func TestSupervisorFederationDomainCRDValidations_Parallel(t *testing.T) { }, { name: "IDP transform constant names cannot be more than 64 characters", - fd: &supervisorconfigv1alpha1.FederationDomain{ - ObjectMeta: objectMeta, - Spec: supervisorconfigv1alpha1.FederationDomainSpec{ - Issuer: "https://example.com", - IdentityProviders: []supervisorconfigv1alpha1.FederationDomainIdentityProvider{ - { - DisplayName: "foo", - ObjectRef: corev1.TypedLocalObjectReference{ - APIGroup: ptr.To("required in older versions of Kubernetes for each item in the identityProviders slice"), - }, - Transforms: supervisorconfigv1alpha1.FederationDomainTransforms{ - Constants: []supervisorconfigv1alpha1.FederationDomainTransformsConstant{ - {Name: "12345678901234567890123456789012345678901234567890123456789012345", Type: "string"}, - }, + spec: &supervisorconfigv1alpha1.FederationDomainSpec{ + Issuer: "https://example.com", + IdentityProviders: []supervisorconfigv1alpha1.FederationDomainIdentityProvider{ + { + DisplayName: "foo", + ObjectRef: corev1.TypedLocalObjectReference{ + APIGroup: ptr.To("required in older versions of Kubernetes for each item in the identityProviders slice"), + }, + Transforms: supervisorconfigv1alpha1.FederationDomainTransforms{ + Constants: []supervisorconfigv1alpha1.FederationDomainTransformsConstant{ + {Name: "12345678901234567890123456789012345678901234567890123456789012345", Type: "string"}, }, }, }, @@ -706,24 +683,21 @@ func TestSupervisorFederationDomainCRDValidations_Parallel(t *testing.T) { }, { name: "IDP transform constant names must be a legal CEL variable name", - fd: &supervisorconfigv1alpha1.FederationDomain{ - ObjectMeta: objectMeta, - Spec: supervisorconfigv1alpha1.FederationDomainSpec{ - Issuer: "https://example.com", - IdentityProviders: []supervisorconfigv1alpha1.FederationDomainIdentityProvider{ - { - DisplayName: "foo", - ObjectRef: corev1.TypedLocalObjectReference{ - APIGroup: ptr.To("required in older versions of Kubernetes for each item in the identityProviders slice"), - }, - Transforms: supervisorconfigv1alpha1.FederationDomainTransforms{ - Constants: []supervisorconfigv1alpha1.FederationDomainTransformsConstant{ - {Name: "cannot have spaces", Type: "string"}, - {Name: "1mustStartWithLetter", Type: "string"}, - {Name: "_mustStartWithLetter", Type: "string"}, - {Name: "canOnlyIncludeLettersAndNumbersAnd_", Type: "string"}, - {Name: "CanStart1_withUpperCase", Type: "string"}, - }, + spec: &supervisorconfigv1alpha1.FederationDomainSpec{ + Issuer: "https://example.com", + IdentityProviders: []supervisorconfigv1alpha1.FederationDomainIdentityProvider{ + { + DisplayName: "foo", + ObjectRef: corev1.TypedLocalObjectReference{ + APIGroup: ptr.To("required in older versions of Kubernetes for each item in the identityProviders slice"), + }, + Transforms: supervisorconfigv1alpha1.FederationDomainTransforms{ + Constants: []supervisorconfigv1alpha1.FederationDomainTransformsConstant{ + {Name: "cannot have spaces", Type: "string"}, + {Name: "1mustStartWithLetter", Type: "string"}, + {Name: "_mustStartWithLetter", Type: "string"}, + {Name: "canOnlyIncludeLettersAndNumbersAnd_", Type: "string"}, + {Name: "CanStart1_withUpperCase", Type: "string"}, }, }, }, @@ -737,22 +711,19 @@ func TestSupervisorFederationDomainCRDValidations_Parallel(t *testing.T) { }, { name: "IDP transform constant types must be one of the allowed enum strings", - fd: &supervisorconfigv1alpha1.FederationDomain{ - ObjectMeta: objectMeta, - Spec: supervisorconfigv1alpha1.FederationDomainSpec{ - Issuer: "https://example.com", - IdentityProviders: []supervisorconfigv1alpha1.FederationDomainIdentityProvider{ - { - DisplayName: "foo", - ObjectRef: corev1.TypedLocalObjectReference{ - APIGroup: ptr.To("required in older versions of Kubernetes for each item in the identityProviders slice"), - }, - Transforms: supervisorconfigv1alpha1.FederationDomainTransforms{ - Constants: []supervisorconfigv1alpha1.FederationDomainTransformsConstant{ - {Name: "a", Type: "this is invalid"}, - {Name: "b", Type: "string"}, - {Name: "c", Type: "stringList"}, - }, + spec: &supervisorconfigv1alpha1.FederationDomainSpec{ + Issuer: "https://example.com", + IdentityProviders: []supervisorconfigv1alpha1.FederationDomainIdentityProvider{ + { + DisplayName: "foo", + ObjectRef: corev1.TypedLocalObjectReference{ + APIGroup: ptr.To("required in older versions of Kubernetes for each item in the identityProviders slice"), + }, + Transforms: supervisorconfigv1alpha1.FederationDomainTransforms{ + Constants: []supervisorconfigv1alpha1.FederationDomainTransformsConstant{ + {Name: "a", Type: "this is invalid"}, + {Name: "b", Type: "string"}, + {Name: "c", Type: "stringList"}, }, }, }, @@ -763,23 +734,20 @@ func TestSupervisorFederationDomainCRDValidations_Parallel(t *testing.T) { }, { name: "IDP transform expression types must be one of the allowed enum strings", - fd: &supervisorconfigv1alpha1.FederationDomain{ - ObjectMeta: objectMeta, - Spec: supervisorconfigv1alpha1.FederationDomainSpec{ - Issuer: "https://example.com", - IdentityProviders: []supervisorconfigv1alpha1.FederationDomainIdentityProvider{ - { - DisplayName: "foo", - ObjectRef: corev1.TypedLocalObjectReference{ - APIGroup: ptr.To("required in older versions of Kubernetes for each item in the identityProviders slice"), - }, - Transforms: supervisorconfigv1alpha1.FederationDomainTransforms{ - Expressions: []supervisorconfigv1alpha1.FederationDomainTransformsExpression{ - {Type: "this is invalid", Expression: "foo"}, - {Type: "policy/v1", Expression: "foo"}, - {Type: "username/v1", Expression: "foo"}, - {Type: "groups/v1", Expression: "foo"}, - }, + spec: &supervisorconfigv1alpha1.FederationDomainSpec{ + Issuer: "https://example.com", + IdentityProviders: []supervisorconfigv1alpha1.FederationDomainIdentityProvider{ + { + DisplayName: "foo", + ObjectRef: corev1.TypedLocalObjectReference{ + APIGroup: ptr.To("required in older versions of Kubernetes for each item in the identityProviders slice"), + }, + Transforms: supervisorconfigv1alpha1.FederationDomainTransforms{ + Expressions: []supervisorconfigv1alpha1.FederationDomainTransformsExpression{ + {Type: "this is invalid", Expression: "foo"}, + {Type: "policy/v1", Expression: "foo"}, + {Type: "username/v1", Expression: "foo"}, + {Type: "groups/v1", Expression: "foo"}, }, }, }, @@ -790,20 +758,17 @@ func TestSupervisorFederationDomainCRDValidations_Parallel(t *testing.T) { }, { name: "IDP transform expressions cannot be empty", - fd: &supervisorconfigv1alpha1.FederationDomain{ - ObjectMeta: objectMeta, - Spec: supervisorconfigv1alpha1.FederationDomainSpec{ - Issuer: "https://example.com", - IdentityProviders: []supervisorconfigv1alpha1.FederationDomainIdentityProvider{ - { - DisplayName: "foo", - ObjectRef: corev1.TypedLocalObjectReference{ - APIGroup: ptr.To("required in older versions of Kubernetes for each item in the identityProviders slice"), - }, - Transforms: supervisorconfigv1alpha1.FederationDomainTransforms{ - Expressions: []supervisorconfigv1alpha1.FederationDomainTransformsExpression{ - {Type: "username/v1", Expression: ""}, - }, + spec: &supervisorconfigv1alpha1.FederationDomainSpec{ + Issuer: "https://example.com", + IdentityProviders: []supervisorconfigv1alpha1.FederationDomainIdentityProvider{ + { + DisplayName: "foo", + ObjectRef: corev1.TypedLocalObjectReference{ + APIGroup: ptr.To("required in older versions of Kubernetes for each item in the identityProviders slice"), + }, + Transforms: supervisorconfigv1alpha1.FederationDomainTransforms{ + Expressions: []supervisorconfigv1alpha1.FederationDomainTransformsExpression{ + {Type: "username/v1", Expression: ""}, }, }, }, @@ -813,21 +778,18 @@ func TestSupervisorFederationDomainCRDValidations_Parallel(t *testing.T) { }, { name: "IDP transform example usernames cannot be empty", - fd: &supervisorconfigv1alpha1.FederationDomain{ - ObjectMeta: objectMeta, - Spec: supervisorconfigv1alpha1.FederationDomainSpec{ - Issuer: "https://example.com", - IdentityProviders: []supervisorconfigv1alpha1.FederationDomainIdentityProvider{ - { - DisplayName: "foo", - ObjectRef: corev1.TypedLocalObjectReference{ - APIGroup: ptr.To("required in older versions of Kubernetes for each item in the identityProviders slice"), - }, - Transforms: supervisorconfigv1alpha1.FederationDomainTransforms{ - Examples: []supervisorconfigv1alpha1.FederationDomainTransformsExample{ - {Username: ""}, - {Username: "non-empty"}, - }, + spec: &supervisorconfigv1alpha1.FederationDomainSpec{ + Issuer: "https://example.com", + IdentityProviders: []supervisorconfigv1alpha1.FederationDomainIdentityProvider{ + { + DisplayName: "foo", + ObjectRef: corev1.TypedLocalObjectReference{ + APIGroup: ptr.To("required in older versions of Kubernetes for each item in the identityProviders slice"), + }, + Transforms: supervisorconfigv1alpha1.FederationDomainTransforms{ + Examples: []supervisorconfigv1alpha1.FederationDomainTransformsExample{ + {Username: ""}, + {Username: "non-empty"}, }, }, }, @@ -837,25 +799,19 @@ func TestSupervisorFederationDomainCRDValidations_Parallel(t *testing.T) { }, { name: "minimum valid", - fd: &supervisorconfigv1alpha1.FederationDomain{ - ObjectMeta: testlib.ObjectMetaWithRandomName(t, "fd"), - Spec: supervisorconfigv1alpha1.FederationDomainSpec{ - Issuer: "https://example.com", - }, + spec: &supervisorconfigv1alpha1.FederationDomainSpec{ + Issuer: "https://example.com", }, }, { name: "minimum valid when IDPs are included", - fd: &supervisorconfigv1alpha1.FederationDomain{ - ObjectMeta: testlib.ObjectMetaWithRandomName(t, "fd"), - Spec: supervisorconfigv1alpha1.FederationDomainSpec{ - Issuer: "https://example.com", - IdentityProviders: []supervisorconfigv1alpha1.FederationDomainIdentityProvider{ - { - DisplayName: "foo", - ObjectRef: corev1.TypedLocalObjectReference{ - APIGroup: ptr.To("required in older versions of Kubernetes for each item in the identityProviders slice"), - }, + spec: &supervisorconfigv1alpha1.FederationDomainSpec{ + Issuer: "https://example.com", + IdentityProviders: []supervisorconfigv1alpha1.FederationDomainIdentityProvider{ + { + DisplayName: "foo", + ObjectRef: corev1.TypedLocalObjectReference{ + APIGroup: ptr.To("required in older versions of Kubernetes for each item in the identityProviders slice"), }, }, }, @@ -863,26 +819,23 @@ func TestSupervisorFederationDomainCRDValidations_Parallel(t *testing.T) { }, { name: "minimum valid when IDP has transform constants, expressions, and examples", - fd: &supervisorconfigv1alpha1.FederationDomain{ - ObjectMeta: testlib.ObjectMetaWithRandomName(t, "fd"), - Spec: supervisorconfigv1alpha1.FederationDomainSpec{ - Issuer: "https://example.com", - IdentityProviders: []supervisorconfigv1alpha1.FederationDomainIdentityProvider{ - { - DisplayName: "foo", - ObjectRef: corev1.TypedLocalObjectReference{ - APIGroup: ptr.To("required in older versions of Kubernetes for each item in the identityProviders slice"), + spec: &supervisorconfigv1alpha1.FederationDomainSpec{ + Issuer: "https://example.com", + IdentityProviders: []supervisorconfigv1alpha1.FederationDomainIdentityProvider{ + { + DisplayName: "foo", + ObjectRef: corev1.TypedLocalObjectReference{ + APIGroup: ptr.To("required in older versions of Kubernetes for each item in the identityProviders slice"), + }, + Transforms: supervisorconfigv1alpha1.FederationDomainTransforms{ + Constants: []supervisorconfigv1alpha1.FederationDomainTransformsConstant{ + {Name: "foo", Type: "string"}, }, - Transforms: supervisorconfigv1alpha1.FederationDomainTransforms{ - Constants: []supervisorconfigv1alpha1.FederationDomainTransformsConstant{ - {Name: "foo", Type: "string"}, - }, - Expressions: []supervisorconfigv1alpha1.FederationDomainTransformsExpression{ - {Type: "username/v1", Expression: "foo"}, - }, - Examples: []supervisorconfigv1alpha1.FederationDomainTransformsExample{ - {Username: "foo"}, - }, + Expressions: []supervisorconfigv1alpha1.FederationDomainTransformsExpression{ + {Type: "username/v1", Expression: "foo"}, + }, + Examples: []supervisorconfigv1alpha1.FederationDomainTransformsExample{ + {Username: "foo"}, }, }, }, @@ -896,11 +849,16 @@ func TestSupervisorFederationDomainCRDValidations_Parallel(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() - _, actualCreateErr := fdClient.Create(ctx, tt.fd, metav1.CreateOptions{}) + fd := &supervisorconfigv1alpha1.FederationDomain{ + ObjectMeta: testlib.ObjectMetaWithRandomName(t, "federation-domain"), + Spec: *tt.spec, + } + + _, actualCreateErr := fdClient.Create(ctx, fd, metav1.CreateOptions{}) t.Cleanup(func() { // Delete it if it exists. - delErr := fdClient.Delete(ctx, tt.fd.Name, metav1.DeleteOptions{}) + delErr := fdClient.Delete(ctx, fd.Name, metav1.DeleteOptions{}) if !apierrors.IsNotFound(delErr) { require.NoError(t, delErr) } @@ -917,7 +875,7 @@ func TestSupervisorFederationDomainCRDValidations_Parallel(t *testing.T) { } wantErr := tt.wantErrs - if usingKubeVersionInCluster23OrOlder { + if usingKubeVersionInCluster23OrOlder && tt.name != "IDP transform constants must have unique names" { // Old versions of Kubernetes did not show the index where the error occurred in some of the messages, // so remove the indices from the expected messages when running against an old version of Kube. // For the above tests, it should be enough to assume that there will only be indices up to 10. @@ -945,14 +903,14 @@ func TestSupervisorFederationDomainCRDValidations_Parallel(t *testing.T) { if performCELTests { wantErr = append(wantErr, tt.wantCELErrs...) - } else if len(wantErr) == len(tt.wantCELErrs) { + } else if len(wantErr) == 0 && len(tt.wantCELErrs) > 0 { // on old K8s versions, don't check for errors when all we expect are CEL errors require.NoError(t, actualCreateErr) return } wantErrStr := fmt.Sprintf("FederationDomain.config.supervisor.%s %q is invalid: ", - env.APIGroupSuffix, objectMeta.Name) + env.APIGroupSuffix, fd.Name) if len(wantErr) == 1 { wantErrStr += wantErr[0] From bfbf0c9d03c97e1f24d8e40e3500b969c83c55f4 Mon Sep 17 00:00:00 2001 From: Joshua Casey Date: Fri, 3 Jan 2025 14:15:02 -0600 Subject: [PATCH 6/6] Make sure that CEL errors are checked for the appropriate Kube version --- .../testutil/kube_server_compatibility.go | 10 ++- ...supervisor_federationdomain_status_test.go | 78 ++++++++++--------- 2 files changed, 51 insertions(+), 37 deletions(-) diff --git a/internal/testutil/kube_server_compatibility.go b/internal/testutil/kube_server_compatibility.go index e39bcd9d7..49e1bb635 100644 --- a/internal/testutil/kube_server_compatibility.go +++ b/internal/testutil/kube_server_compatibility.go @@ -1,4 +1,4 @@ -// Copyright 2021-2024 the Pinniped contributors. All Rights Reserved. +// Copyright 2021-2025 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package testutil @@ -45,7 +45,7 @@ func KubeServerMinorVersionAtLeastInclusive(t *testing.T, discoveryClient discov return !KubeServerMinorVersionInBetweenInclusive(t, discoveryClient, 0, min-1) } -func KubeServerMinorVersionInBetweenInclusive(t *testing.T, discoveryClient discovery.DiscoveryInterface, min, max int) bool { +func KubeServerMinorVersion(t *testing.T, discoveryClient discovery.DiscoveryInterface) int { t.Helper() version, err := discoveryClient.ServerVersion() @@ -56,6 +56,12 @@ func KubeServerMinorVersionInBetweenInclusive(t *testing.T, discoveryClient disc minor, err := strconv.Atoi(strings.TrimSuffix(version.Minor, "+")) require.NoError(t, err) + return minor +} + +func KubeServerMinorVersionInBetweenInclusive(t *testing.T, discoveryClient discovery.DiscoveryInterface, min, max int) bool { + minor := KubeServerMinorVersion(t, discoveryClient) + return minor >= min && minor <= max } diff --git a/test/integration/supervisor_federationdomain_status_test.go b/test/integration/supervisor_federationdomain_status_test.go index 46774e315..745076347 100644 --- a/test/integration/supervisor_federationdomain_status_test.go +++ b/test/integration/supervisor_federationdomain_status_test.go @@ -1,4 +1,4 @@ -// Copyright 2023-2024 the Pinniped contributors. All Rights Reserved. +// Copyright 2023-2025 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package integration @@ -563,44 +563,49 @@ func TestSupervisorFederationDomainCRDValidations_Parallel(t *testing.T) { t.Cleanup(cancel) adminClient := testlib.NewKubernetesClientset(t) - usingKubeVersionInCluster23OrOlder := testutil.KubeServerMinorVersionInBetweenInclusive(t, adminClient.Discovery(), 0, 23) - usingKubeVersionInCluster24Through31Inclusive := testutil.KubeServerMinorVersionInBetweenInclusive(t, adminClient.Discovery(), 24, 31) - usingKubeVersionInCluster32OrNewer := !usingKubeVersionInCluster23OrOlder && !usingKubeVersionInCluster24Through31Inclusive - performCELTests := testutil.KubeServerMinorVersionAtLeastInclusive(t, adminClient.Discovery(), 27) + // Certain non-CEL validation failures will prevent CEL validations from running, + // and the Kubernetes API server will return this error message for those cases. + const couldNotRunCELValidationsErrMessage = `: Invalid value: "null": some validation rules were not checked because the object was invalid; correct the existing errors to complete validation` tests := []struct { - name string - spec *supervisorconfigv1alpha1.FederationDomainSpec - wantErrs []string - wantCELErrs []string + name string + spec *supervisorconfigv1alpha1.FederationDomainSpec + wantErrs []string // optionally override wantErr for one or more specific versions of Kube, due to changing validation error text wantKube23OrOlderErrs []string wantKube24Through31InclusiveErrs []string wantKube32OrNewerErrs []string + + // These errors are appended to any other wanted errors when k8sAPIServerSupportsCEL is true + wantCELErrorsForKube25Through28Inclusive []string + wantCELErrorsForKube29OrNewer []string }{ { name: "issuer cannot be empty", spec: &supervisorconfigv1alpha1.FederationDomainSpec{ Issuer: "", }, - wantErrs: []string{`spec.issuer: Invalid value: "": spec.issuer in body should be at least 1 chars long`}, - wantCELErrs: []string{`spec.issuer: Invalid value: "string": issuer must be an HTTPS URL`}, + wantErrs: []string{`spec.issuer: Invalid value: "": spec.issuer in body should be at least 1 chars long`}, + wantCELErrorsForKube25Through28Inclusive: []string{`spec.issuer: Invalid value: "string": issuer must be an HTTPS URL`}, + wantCELErrorsForKube29OrNewer: []string{`spec.issuer: Invalid value: "string": issuer must be an HTTPS URL`}, }, { name: "issuer must be a URL", spec: &supervisorconfigv1alpha1.FederationDomainSpec{ Issuer: "foo", }, - wantCELErrs: []string{`spec.issuer: Invalid value: "string": issuer must be an HTTPS URL`}, + wantCELErrorsForKube25Through28Inclusive: []string{`spec.issuer: Invalid value: "string": issuer must be an HTTPS URL`}, + wantCELErrorsForKube29OrNewer: []string{`spec.issuer: Invalid value: "string": issuer must be an HTTPS URL`}, }, { name: "issuer URL scheme must be 'https'", spec: &supervisorconfigv1alpha1.FederationDomainSpec{ Issuer: "http://example.com", }, - wantCELErrs: []string{`spec.issuer: Invalid value: "string": issuer must be an HTTPS URL`}, + wantCELErrorsForKube25Through28Inclusive: []string{`spec.issuer: Invalid value: "string": issuer must be an HTTPS URL`}, + wantCELErrorsForKube29OrNewer: []string{`spec.issuer: Invalid value: "string": issuer must be an HTTPS URL`}, }, { name: "IDP display names cannot be empty", @@ -636,7 +641,9 @@ func TestSupervisorFederationDomainCRDValidations_Parallel(t *testing.T) { }, }, }, - wantErrs: []string{`spec.identityProviders[0].transforms.constants[1]: Duplicate value: map[string]interface {}{"name":"notUnique"}`}, + // For some unknown reason, Kubernetes versions 1.23 and older return errors *with indices* for this test case only. + wantKube23OrOlderErrs: []string{`spec.identityProviders[0].transforms.constants[1]: Duplicate value: map[string]interface {}{"name":"notUnique"}`}, + wantErrs: []string{`spec.identityProviders[0].transforms.constants[1]: Duplicate value: map[string]interface {}{"name":"notUnique"}`}, }, { name: "IDP transform constant names cannot be empty", @@ -676,10 +683,11 @@ func TestSupervisorFederationDomainCRDValidations_Parallel(t *testing.T) { }, }, }, - wantKube23OrOlderErrs: []string{`spec.identityProviders.transforms.constants.name: Invalid value: "12345678901234567890123456789012345678901234567890123456789012345": spec.identityProviders.transforms.constants.name in body should be at most 64 chars long`}, - wantKube24Through31InclusiveErrs: []string{`spec.identityProviders[0].transforms.constants[0].name: Too long: may not be longer than 64`}, - wantKube32OrNewerErrs: []string{`spec.identityProviders[0].transforms.constants[0].name: Too long: may not be more than 64 bytes`}, - wantCELErrs: []string{`: Invalid value: "null": some validation rules were not checked because the object was invalid; correct the existing errors to complete validation`}, + wantKube23OrOlderErrs: []string{`spec.identityProviders.transforms.constants.name: Invalid value: "12345678901234567890123456789012345678901234567890123456789012345": spec.identityProviders.transforms.constants.name in body should be at most 64 chars long`}, + wantKube24Through31InclusiveErrs: []string{`spec.identityProviders[0].transforms.constants[0].name: Too long: may not be longer than 64`}, + wantKube32OrNewerErrs: []string{`spec.identityProviders[0].transforms.constants[0].name: Too long: may not be more than 64 bytes`}, + wantCELErrorsForKube25Through28Inclusive: []string{couldNotRunCELValidationsErrMessage}, + wantCELErrorsForKube29OrNewer: []string{couldNotRunCELValidationsErrMessage}, }, { name: "IDP transform constant names must be a legal CEL variable name", @@ -729,8 +737,8 @@ func TestSupervisorFederationDomainCRDValidations_Parallel(t *testing.T) { }, }, }, - wantErrs: []string{`spec.identityProviders[0].transforms.constants[0].type: Unsupported value: "this is invalid": supported values: "string", "stringList"`}, - wantCELErrs: []string{`: Invalid value: "null": some validation rules were not checked because the object was invalid; correct the existing errors to complete validation`}, + wantErrs: []string{`spec.identityProviders[0].transforms.constants[0].type: Unsupported value: "this is invalid": supported values: "string", "stringList"`}, + wantCELErrorsForKube29OrNewer: []string{couldNotRunCELValidationsErrMessage}, // this should not be checked on kind 1.25, 1.26, 1.27, 1.28 }, { name: "IDP transform expression types must be one of the allowed enum strings", @@ -753,8 +761,8 @@ func TestSupervisorFederationDomainCRDValidations_Parallel(t *testing.T) { }, }, }, - wantErrs: []string{`spec.identityProviders[0].transforms.expressions[0].type: Unsupported value: "this is invalid": supported values: "policy/v1", "username/v1", "groups/v1"`}, - wantCELErrs: []string{`: Invalid value: "null": some validation rules were not checked because the object was invalid; correct the existing errors to complete validation`}, + wantErrs: []string{`spec.identityProviders[0].transforms.expressions[0].type: Unsupported value: "this is invalid": supported values: "policy/v1", "username/v1", "groups/v1"`}, + wantCELErrorsForKube29OrNewer: []string{couldNotRunCELValidationsErrMessage}, // this should not be checked on kind 1.25, 1.26, 1.27, 1.28 }, { name: "IDP transform expressions cannot be empty", @@ -868,14 +876,10 @@ func TestSupervisorFederationDomainCRDValidations_Parallel(t *testing.T) { require.Fail(t, "test setup problem: wanted every possible kind of error, which would cause tt.wantErr to be unused") } - if len(tt.wantErrs) == 0 && len(tt.wantCELErrs) == 0 && len(tt.wantKube23OrOlderErrs) == 0 && len(tt.wantKube24Through31InclusiveErrs) == 0 && len(tt.wantKube32OrNewerErrs) == 0 { - // Did not want any error. - require.NoError(t, actualCreateErr) - return - } + minor := testutil.KubeServerMinorVersion(t, adminClient.Discovery()) wantErr := tt.wantErrs - if usingKubeVersionInCluster23OrOlder && tt.name != "IDP transform constants must have unique names" { + if minor <= 23 { // Old versions of Kubernetes did not show the index where the error occurred in some of the messages, // so remove the indices from the expected messages when running against an old version of Kube. // For the above tests, it should be enough to assume that there will only be indices up to 10. @@ -887,24 +891,28 @@ func TestSupervisorFederationDomainCRDValidations_Parallel(t *testing.T) { } } } - if usingKubeVersionInCluster23OrOlder && len(tt.wantKube23OrOlderErrs) > 0 { + if minor <= 23 && len(tt.wantKube23OrOlderErrs) > 0 { // Sometimes there are other difference in older Kubernetes messages, so also allow exact // expectation strings for those cases in wantKube23OrOlderErr. When provided, use it on these Kube clusters. wantErr = tt.wantKube23OrOlderErrs } - if usingKubeVersionInCluster24Through31Inclusive && len(tt.wantKube24Through31InclusiveErrs) > 0 { + if minor >= 24 && minor <= 31 && len(tt.wantKube24Through31InclusiveErrs) > 0 { // Also allow overriding with an exact expected error for these Kube versions. wantErr = tt.wantKube24Through31InclusiveErrs } - if usingKubeVersionInCluster32OrNewer && len(tt.wantKube32OrNewerErrs) > 0 { + if minor >= 32 && len(tt.wantKube32OrNewerErrs) > 0 { // Also allow overriding with an exact expected error for these Kube versions. wantErr = tt.wantKube32OrNewerErrs } - if performCELTests { - wantErr = append(wantErr, tt.wantCELErrs...) - } else if len(wantErr) == 0 && len(tt.wantCELErrs) > 0 { - // on old K8s versions, don't check for errors when all we expect are CEL errors + if minor >= 25 && minor <= 28 && len(tt.wantCELErrorsForKube25Through28Inclusive) > 0 { + wantErr = append(wantErr, tt.wantCELErrorsForKube25Through28Inclusive...) + } else if minor >= 29 && len(tt.wantCELErrorsForKube29OrNewer) > 0 { + wantErr = append(wantErr, tt.wantCELErrorsForKube29OrNewer...) + } + + // Did not want any error. + if len(wantErr) == 0 { require.NoError(t, actualCreateErr) return }