From ace01c86de7e839b8f31b5318e79b0581be922ff Mon Sep 17 00:00:00 2001 From: Ryan Richard Date: Fri, 21 Aug 2020 09:55:44 -0700 Subject: [PATCH 1/7] Rename PinnipedDiscoveryInfo to CredentialIssuerConfig Signed-off-by: Andrew Keesler --- deploy/crd.yaml | 16 +-- deploy/rbac.yaml | 2 +- internal/controller/discovery/doc.go | 7 -- internal/controller/issuerconfig/doc.go | 7 ++ .../{discovery => issuerconfig}/publisher.go | 68 ++++++------ .../publisher_test.go | 104 +++++++++--------- .../controllermanager/prepare_controllers.go | 8 +- .../api/apis/crdpinniped/v1alpha1/register.go | 4 +- .../api/apis/crdpinniped/v1alpha1/types.go | 10 +- .../v1alpha1/zz_generated.deepcopy.go | 30 ++--- .../generated/openapi/zz_generated.openapi.go | 20 ++-- .../v1alpha1/crdpinniped_client.go | 6 +- .../v1alpha1/fake/fake_crdpinniped_client.go | 4 +- .../fake/fake_pinnipeddiscoveryinfo.go | 68 ++++++------ .../v1alpha1/generated_expansion.go | 2 +- .../v1alpha1/pinnipeddiscoveryinfo.go | 94 ++++++++-------- .../crdpinniped/v1alpha1/interface.go | 10 +- .../v1alpha1/pinnipeddiscoveryinfo.go | 38 +++---- .../informers/externalversions/generic.go | 4 +- .../v1alpha1/expansion_generated.go | 12 +- .../v1alpha1/pinnipeddiscoveryinfo.go | 68 ++++++------ test/integration/api_discovery_test.go | 8 +- .../integration/pinnipeddiscoveryinfo_test.go | 16 +-- 23 files changed, 303 insertions(+), 303 deletions(-) delete mode 100644 internal/controller/discovery/doc.go create mode 100644 internal/controller/issuerconfig/doc.go rename internal/controller/{discovery => issuerconfig}/publisher.go (62%) rename internal/controller/{discovery => issuerconfig}/publisher_test.go (77%) diff --git a/deploy/crd.yaml b/deploy/crd.yaml index 8fb9b6c8..ce85d904 100644 --- a/deploy/crd.yaml +++ b/deploy/crd.yaml @@ -1,11 +1,11 @@ #@ load("@ytt:data", "data") -#! Example of valid PinnipedDiscoveryInfo object: +#! Example of valid CredentialIssuerConfig object: #! --- #! apiVersion: crd.pinniped.dev/v1alpha1 -#! kind: PinnipedDiscoveryInfo +#! kind: CredentialIssuerConfig #! metadata: -#! name: login-discovery +#! name: credential-issuer-config #! namespace: integration #! spec: #! server: https://foo @@ -15,7 +15,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: - name: pinnipeddiscoveryinfos.crd.pinniped.dev + name: credentialissuerconfigs.crd.pinniped.dev spec: group: crd.pinniped.dev versions: @@ -42,8 +42,8 @@ spec: minLength: 1 scope: Namespaced names: - plural: pinnipeddiscoveryinfos - singular: pinnipeddiscoveryinfo - kind: PinnipedDiscoveryInfo + plural: credentialissuerconfigs + singular: credentialissuerconfig + kind: CredentialIssuerConfig shortNames: - - ldc + - cic diff --git a/deploy/rbac.yaml b/deploy/rbac.yaml index d1082f67..fe221862 100644 --- a/deploy/rbac.yaml +++ b/deploy/rbac.yaml @@ -45,7 +45,7 @@ rules: resources: [secrets] verbs: [create, get, list, patch, update, watch, delete] - apiGroups: [crd.pinniped.dev] - resources: [pinnipeddiscoveryinfos] + resources: [credentialissuerconfigs] verbs: [create, get, list, update, watch] --- kind: RoleBinding diff --git a/internal/controller/discovery/doc.go b/internal/controller/discovery/doc.go deleted file mode 100644 index 2d0603e1..00000000 --- a/internal/controller/discovery/doc.go +++ /dev/null @@ -1,7 +0,0 @@ -/* -Copyright 2020 VMware, Inc. -SPDX-License-Identifier: Apache-2.0 -*/ - -// Package discovery contains controller(s) for reconciling PinnipedDiscoveryInfo's. -package discovery diff --git a/internal/controller/issuerconfig/doc.go b/internal/controller/issuerconfig/doc.go new file mode 100644 index 00000000..e972503b --- /dev/null +++ b/internal/controller/issuerconfig/doc.go @@ -0,0 +1,7 @@ +/* +Copyright 2020 VMware, Inc. +SPDX-License-Identifier: Apache-2.0 +*/ + +// Package discovery contains controller(s) for reconciling CredentialIssuerConfig's. +package issuerconfig diff --git a/internal/controller/discovery/publisher.go b/internal/controller/issuerconfig/publisher.go similarity index 62% rename from internal/controller/discovery/publisher.go rename to internal/controller/issuerconfig/publisher.go index 37a10f56..bac6d843 100644 --- a/internal/controller/discovery/publisher.go +++ b/internal/controller/issuerconfig/publisher.go @@ -3,7 +3,7 @@ Copyright 2020 VMware, Inc. SPDX-License-Identifier: Apache-2.0 */ -package discovery +package issuerconfig import ( "context" @@ -33,11 +33,11 @@ const ( ) type publisherController struct { - namespace string - serverOverride *string - pinnipedClient pinnipedclientset.Interface - configMapInformer corev1informers.ConfigMapInformer - pinnipedDiscoveryInfoInformer crdpinnipedv1alpha1informers.PinnipedDiscoveryInfoInformer + namespace string + serverOverride *string + pinnipedClient pinnipedclientset.Interface + configMapInformer corev1informers.ConfigMapInformer + credentialIssuerConfigInformer crdpinnipedv1alpha1informers.CredentialIssuerConfigInformer } func NewPublisherController( @@ -45,18 +45,18 @@ func NewPublisherController( serverOverride *string, pinnipedClient pinnipedclientset.Interface, configMapInformer corev1informers.ConfigMapInformer, - pinnipedDiscoveryInfoInformer crdpinnipedv1alpha1informers.PinnipedDiscoveryInfoInformer, + credentialIssuerConfigInformer crdpinnipedv1alpha1informers.CredentialIssuerConfigInformer, withInformer pinnipedcontroller.WithInformerOptionFunc, ) controller.Controller { return controller.New( controller.Config{ Name: "publisher-controller", Syncer: &publisherController{ - namespace: namespace, - serverOverride: serverOverride, - pinnipedClient: pinnipedClient, - configMapInformer: configMapInformer, - pinnipedDiscoveryInfoInformer: pinnipedDiscoveryInfoInformer, + namespace: namespace, + serverOverride: serverOverride, + pinnipedClient: pinnipedClient, + configMapInformer: configMapInformer, + credentialIssuerConfigInformer: credentialIssuerConfigInformer, }, }, withInformer( @@ -65,7 +65,7 @@ func NewPublisherController( controller.InformerOption{}, ), withInformer( - pinnipedDiscoveryInfoInformer, + credentialIssuerConfigInformer, pinnipedcontroller.NameAndNamespaceExactMatchFilterFactory(configName, namespace), controller.InformerOption{}, ), @@ -109,66 +109,66 @@ func (c *publisherController) Sync(ctx controller.Context) error { server = *c.serverOverride } - discoveryInfo := crdpinnipedv1alpha1.PinnipedDiscoveryInfo{ + credentialIssuerConfig := crdpinnipedv1alpha1.CredentialIssuerConfig{ TypeMeta: metav1.TypeMeta{}, ObjectMeta: metav1.ObjectMeta{ Name: configName, Namespace: c.namespace, }, - Spec: crdpinnipedv1alpha1.PinnipedDiscoveryInfoSpec{ + Spec: crdpinnipedv1alpha1.CredentialIssuerConfigSpec{ Server: server, CertificateAuthorityData: certificateAuthorityData, }, } - if err := c.createOrUpdatePinnipedDiscoveryInfo(ctx.Context, &discoveryInfo); err != nil { + if err := c.createOrUpdateCredentialIssuerConfig(ctx.Context, &credentialIssuerConfig); err != nil { return err } return nil } -func (c *publisherController) createOrUpdatePinnipedDiscoveryInfo( +func (c *publisherController) createOrUpdateCredentialIssuerConfig( ctx context.Context, - discoveryInfo *crdpinnipedv1alpha1.PinnipedDiscoveryInfo, + credentialIssuerConfig *crdpinnipedv1alpha1.CredentialIssuerConfig, ) error { - existingDiscoveryInfo, err := c.pinnipedDiscoveryInfoInformer. + existingCredentialIssuerConfig, err := c.credentialIssuerConfigInformer. Lister(). - PinnipedDiscoveryInfos(c.namespace). - Get(discoveryInfo.Name) + CredentialIssuerConfigs(c.namespace). + Get(credentialIssuerConfig.Name) notFound := k8serrors.IsNotFound(err) if err != nil && !notFound { - return fmt.Errorf("could not get pinnipeddiscoveryinfo: %w", err) + return fmt.Errorf("could not get credentialissuerconfig: %w", err) } - pinnipedDiscoveryInfos := c.pinnipedClient. + credentialIssuerConfigs := c.pinnipedClient. CrdV1alpha1(). - PinnipedDiscoveryInfos(c.namespace) + CredentialIssuerConfigs(c.namespace) if notFound { - if _, err := pinnipedDiscoveryInfos.Create( + if _, err := credentialIssuerConfigs.Create( ctx, - discoveryInfo, + credentialIssuerConfig, metav1.CreateOptions{}, ); err != nil { - return fmt.Errorf("could not create pinnipeddiscoveryinfo: %w", err) + return fmt.Errorf("could not create credentialissuerconfig: %w", err) } - } else if !equal(existingDiscoveryInfo, discoveryInfo) { + } else if !equal(existingCredentialIssuerConfig, credentialIssuerConfig) { // Update just the fields we care about. - existingDiscoveryInfo.Spec.Server = discoveryInfo.Spec.Server - existingDiscoveryInfo.Spec.CertificateAuthorityData = discoveryInfo.Spec.CertificateAuthorityData + existingCredentialIssuerConfig.Spec.Server = credentialIssuerConfig.Spec.Server + existingCredentialIssuerConfig.Spec.CertificateAuthorityData = credentialIssuerConfig.Spec.CertificateAuthorityData - if _, err := pinnipedDiscoveryInfos.Update( + if _, err := credentialIssuerConfigs.Update( ctx, - existingDiscoveryInfo, + existingCredentialIssuerConfig, metav1.UpdateOptions{}, ); err != nil { - return fmt.Errorf("could not update pinnipeddiscoveryinfo: %w", err) + return fmt.Errorf("could not update credentialissuerconfig: %w", err) } } return nil } -func equal(a, b *crdpinnipedv1alpha1.PinnipedDiscoveryInfo) bool { +func equal(a, b *crdpinnipedv1alpha1.CredentialIssuerConfig) bool { return a.Spec.Server == b.Spec.Server && a.Spec.CertificateAuthorityData == b.Spec.CertificateAuthorityData } diff --git a/internal/controller/discovery/publisher_test.go b/internal/controller/issuerconfig/publisher_test.go similarity index 77% rename from internal/controller/discovery/publisher_test.go rename to internal/controller/issuerconfig/publisher_test.go index b8be2ef3..4aefe2f6 100644 --- a/internal/controller/discovery/publisher_test.go +++ b/internal/controller/issuerconfig/publisher_test.go @@ -3,7 +3,7 @@ Copyright 2020 VMware, Inc. SPDX-License-Identifier: Apache-2.0 */ -package discovery +package issuerconfig import ( "context" @@ -37,23 +37,23 @@ func TestInformerFilters(t *testing.T) { var r *require.Assertions var observableWithInformerOption *testutil.ObservableWithInformerOption var configMapInformerFilter controller.Filter - var pinnipedDiscoveryInfoInformerFilter controller.Filter + var credentialIssuerConfigInformerFilter controller.Filter it.Before(func() { r = require.New(t) observableWithInformerOption = testutil.NewObservableWithInformerOption() configMapInformer := kubeinformers.NewSharedInformerFactory(nil, 0).Core().V1().ConfigMaps() - pinnipedDiscoveryInfoInformer := pinnipedinformers.NewSharedInformerFactory(nil, 0).Crd().V1alpha1().PinnipedDiscoveryInfos() + credentialIssuerConfigInformer := pinnipedinformers.NewSharedInformerFactory(nil, 0).Crd().V1alpha1().CredentialIssuerConfigs() _ = NewPublisherController( installedInNamespace, nil, nil, configMapInformer, - pinnipedDiscoveryInfoInformer, + credentialIssuerConfigInformer, observableWithInformerOption.WithInformer, // make it possible to observe the behavior of the Filters ) configMapInformerFilter = observableWithInformerOption.GetFilterForInformer(configMapInformer) - pinnipedDiscoveryInfoInformerFilter = observableWithInformerOption.GetFilterForInformer(pinnipedDiscoveryInfoInformer) + credentialIssuerConfigInformerFilter = observableWithInformerOption.GetFilterForInformer(credentialIssuerConfigInformer) }) when("watching ConfigMap objects", func() { @@ -104,27 +104,27 @@ func TestInformerFilters(t *testing.T) { }) }) - when("watching PinnipedDiscoveryInfo objects", func() { + when("watching CredentialIssuerConfig objects", func() { var subject controller.Filter - var target, wrongNamespace, wrongName, unrelated *crdpinnipedv1alpha1.PinnipedDiscoveryInfo + var target, wrongNamespace, wrongName, unrelated *crdpinnipedv1alpha1.CredentialIssuerConfig it.Before(func() { - subject = pinnipedDiscoveryInfoInformerFilter - target = &crdpinnipedv1alpha1.PinnipedDiscoveryInfo{ + subject = credentialIssuerConfigInformerFilter + target = &crdpinnipedv1alpha1.CredentialIssuerConfig{ ObjectMeta: metav1.ObjectMeta{Name: "pinniped-config", Namespace: installedInNamespace}, } - wrongNamespace = &crdpinnipedv1alpha1.PinnipedDiscoveryInfo{ + wrongNamespace = &crdpinnipedv1alpha1.CredentialIssuerConfig{ ObjectMeta: metav1.ObjectMeta{Name: "pinniped-config", Namespace: "wrong-namespace"}, } - wrongName = &crdpinnipedv1alpha1.PinnipedDiscoveryInfo{ + wrongName = &crdpinnipedv1alpha1.CredentialIssuerConfig{ ObjectMeta: metav1.ObjectMeta{Name: "wrong-name", Namespace: installedInNamespace}, } - unrelated = &crdpinnipedv1alpha1.PinnipedDiscoveryInfo{ + unrelated = &crdpinnipedv1alpha1.CredentialIssuerConfig{ ObjectMeta: metav1.ObjectMeta{Name: "wrong-name", Namespace: "wrong-namespace"}, } }) - when("the target PinnipedDiscoveryInfo changes", func() { + when("the target CredentialIssuerConfig changes", func() { it("returns true to trigger the sync method", func() { r.True(subject.Add(target)) r.True(subject.Update(target, unrelated)) @@ -133,7 +133,7 @@ func TestInformerFilters(t *testing.T) { }) }) - when("a PinnipedDiscoveryInfo from another namespace changes", func() { + when("a CredentialIssuerConfig from another namespace changes", func() { it("returns false to avoid triggering the sync method", func() { r.False(subject.Add(wrongNamespace)) r.False(subject.Update(wrongNamespace, unrelated)) @@ -142,7 +142,7 @@ func TestInformerFilters(t *testing.T) { }) }) - when("a PinnipedDiscoveryInfo with a different name changes", func() { + when("a CredentialIssuerConfig with a different name changes", func() { it("returns false to avoid triggering the sync method", func() { r.False(subject.Add(wrongName)) r.False(subject.Update(wrongName, unrelated)) @@ -151,7 +151,7 @@ func TestInformerFilters(t *testing.T) { }) }) - when("a PinnipedDiscoveryInfo with a different name and a different namespace changes", func() { + when("a CredentialIssuerConfig with a different name and a different namespace changes", func() { it("returns false to avoid triggering the sync method", func() { r.False(subject.Add(unrelated)) r.False(subject.Update(unrelated, unrelated)) @@ -179,23 +179,23 @@ func TestSync(t *testing.T) { var timeoutContextCancel context.CancelFunc var syncContext *controller.Context - var expectedPinnipedDiscoveryInfo = func(expectedNamespace, expectedServerURL, expectedCAData string) (schema.GroupVersionResource, *crdpinnipedv1alpha1.PinnipedDiscoveryInfo) { - expectedPinnipedDiscoveryInfoGVR := schema.GroupVersionResource{ + var expectedCredentialIssuerConfig = func(expectedNamespace, expectedServerURL, expectedCAData string) (schema.GroupVersionResource, *crdpinnipedv1alpha1.CredentialIssuerConfig) { + expectedCredentialIssuerConfigGVR := schema.GroupVersionResource{ Group: crdpinnipedv1alpha1.GroupName, Version: "v1alpha1", - Resource: "pinnipeddiscoveryinfos", + Resource: "credentialissuerconfigs", } - expectedPinnipedDiscoveryInfo := &crdpinnipedv1alpha1.PinnipedDiscoveryInfo{ + expectedCredentialIssuerConfig := &crdpinnipedv1alpha1.CredentialIssuerConfig{ ObjectMeta: metav1.ObjectMeta{ Name: "pinniped-config", Namespace: expectedNamespace, }, - Spec: crdpinnipedv1alpha1.PinnipedDiscoveryInfoSpec{ + Spec: crdpinnipedv1alpha1.CredentialIssuerConfigSpec{ Server: expectedServerURL, CertificateAuthorityData: expectedCAData, }, } - return expectedPinnipedDiscoveryInfoGVR, expectedPinnipedDiscoveryInfo + return expectedCredentialIssuerConfigGVR, expectedCredentialIssuerConfig } // Defer starting the informers until the last possible moment so that the @@ -207,7 +207,7 @@ func TestSync(t *testing.T) { serverOverride, pinnipedAPIClient, kubeInformers.Core().V1().ConfigMaps(), - pinnipedInformers.Crd().V1alpha1().PinnipedDiscoveryInfos(), + pinnipedInformers.Crd().V1alpha1().CredentialIssuerConfigs(), controller.WithInformer, ) @@ -268,13 +268,13 @@ func TestSync(t *testing.T) { r.NoError(err) }) - when("the PinnipedDiscoveryInfo does not already exist", func() { - it("creates a PinnipedDiscoveryInfo", func() { + when("the CredentialIssuerConfig does not already exist", func() { + it("creates a CredentialIssuerConfig", func() { startInformersAndController() err := controller.TestSync(t, subject, *syncContext) r.NoError(err) - expectedPinnipedDiscoveryInfoGVR, expectedPinnipedDiscoveryInfo := expectedPinnipedDiscoveryInfo( + expectedCredentialIssuerConfigGVR, expectedCredentialIssuerConfig := expectedCredentialIssuerConfig( installedInNamespace, kubeServerURL, caData, @@ -283,20 +283,20 @@ func TestSync(t *testing.T) { r.Equal( []coretesting.Action{ coretesting.NewCreateAction( - expectedPinnipedDiscoveryInfoGVR, + expectedCredentialIssuerConfigGVR, installedInNamespace, - expectedPinnipedDiscoveryInfo, + expectedCredentialIssuerConfig, ), }, pinnipedAPIClient.Actions(), ) }) - when("creating the PinnipedDiscoveryInfo fails", func() { + when("creating the CredentialIssuerConfig fails", func() { it.Before(func() { pinnipedAPIClient.PrependReactor( "create", - "pinnipeddiscoveryinfos", + "credentialissuerconfigs", func(_ coretesting.Action) (bool, runtime.Object, error) { return true, nil, errors.New("create failed") }, @@ -306,7 +306,7 @@ func TestSync(t *testing.T) { it("returns the create error", func() { startInformersAndController() err := controller.TestSync(t, subject, *syncContext) - r.EqualError(err, "could not create pinnipeddiscoveryinfo: create failed") + r.EqualError(err, "could not create credentialissuerconfig: create failed") }) }) @@ -319,19 +319,19 @@ func TestSync(t *testing.T) { err := controller.TestSync(t, subject, *syncContext) r.NoError(err) - expectedPinnipedDiscoveryInfoGVR, expectedPinnipedDiscoveryInfo := expectedPinnipedDiscoveryInfo( + expectedCredentialIssuerConfigGVR, expectedCredentialIssuerConfig := expectedCredentialIssuerConfig( installedInNamespace, kubeServerURL, caData, ) - expectedPinnipedDiscoveryInfo.Spec.Server = "https://some-server-override" + expectedCredentialIssuerConfig.Spec.Server = "https://some-server-override" r.Equal( []coretesting.Action{ coretesting.NewCreateAction( - expectedPinnipedDiscoveryInfoGVR, + expectedCredentialIssuerConfigGVR, installedInNamespace, - expectedPinnipedDiscoveryInfo, + expectedCredentialIssuerConfig, ), }, pinnipedAPIClient.Actions(), @@ -340,19 +340,19 @@ func TestSync(t *testing.T) { }) }) - when("the PinnipedDiscoveryInfo already exists", func() { - when("the PinnipedDiscoveryInfo is already up to date according to the data in the ConfigMap", func() { + when("the CredentialIssuerConfig already exists", func() { + when("the CredentialIssuerConfig is already up to date according to the data in the ConfigMap", func() { it.Before(func() { - _, expectedPinnipedDiscoveryInfo := expectedPinnipedDiscoveryInfo( + _, expectedCredentialIssuerConfig := expectedCredentialIssuerConfig( installedInNamespace, kubeServerURL, caData, ) - err := pinnipedInformerClient.Tracker().Add(expectedPinnipedDiscoveryInfo) + err := pinnipedInformerClient.Tracker().Add(expectedCredentialIssuerConfig) r.NoError(err) }) - it("does not update the PinnipedDiscoveryInfo to avoid unnecessary etcd writes/api calls", func() { + it("does not update the CredentialIssuerConfig to avoid unnecessary etcd writes/api calls", func() { startInformersAndController() err := controller.TestSync(t, subject, *syncContext) r.NoError(err) @@ -361,43 +361,43 @@ func TestSync(t *testing.T) { }) }) - when("the PinnipedDiscoveryInfo is stale compared to the data in the ConfigMap", func() { + when("the CredentialIssuerConfig is stale compared to the data in the ConfigMap", func() { it.Before(func() { - _, expectedPinnipedDiscoveryInfo := expectedPinnipedDiscoveryInfo( + _, expectedCredentialIssuerConfig := expectedCredentialIssuerConfig( installedInNamespace, kubeServerURL, caData, ) - expectedPinnipedDiscoveryInfo.Spec.Server = "https://some-other-server" - r.NoError(pinnipedInformerClient.Tracker().Add(expectedPinnipedDiscoveryInfo)) - r.NoError(pinnipedAPIClient.Tracker().Add(expectedPinnipedDiscoveryInfo)) + expectedCredentialIssuerConfig.Spec.Server = "https://some-other-server" + r.NoError(pinnipedInformerClient.Tracker().Add(expectedCredentialIssuerConfig)) + r.NoError(pinnipedAPIClient.Tracker().Add(expectedCredentialIssuerConfig)) }) - it("updates the existing PinnipedDiscoveryInfo", func() { + it("updates the existing CredentialIssuerConfig", func() { startInformersAndController() err := controller.TestSync(t, subject, *syncContext) r.NoError(err) - expectedPinnipedDiscoveryInfoGVR, expectedPinnipedDiscoveryInfo := expectedPinnipedDiscoveryInfo( + expectedCredentialIssuerConfigGVR, expectedCredentialIssuerConfig := expectedCredentialIssuerConfig( installedInNamespace, kubeServerURL, caData, ) expectedActions := []coretesting.Action{ coretesting.NewUpdateAction( - expectedPinnipedDiscoveryInfoGVR, + expectedCredentialIssuerConfigGVR, installedInNamespace, - expectedPinnipedDiscoveryInfo, + expectedCredentialIssuerConfig, ), } r.Equal(expectedActions, pinnipedAPIClient.Actions()) }) - when("updating the PinnipedDiscoveryInfo fails", func() { + when("updating the CredentialIssuerConfig fails", func() { it.Before(func() { pinnipedAPIClient.PrependReactor( "update", - "pinnipeddiscoveryinfos", + "credentialissuerconfigs", func(_ coretesting.Action) (bool, runtime.Object, error) { return true, nil, errors.New("update failed") }, @@ -407,7 +407,7 @@ func TestSync(t *testing.T) { it("returns the update error", func() { startInformersAndController() err := controller.TestSync(t, subject, *syncContext) - r.EqualError(err, "could not update pinnipeddiscoveryinfo: update failed") + r.EqualError(err, "could not update credentialissuerconfig: update failed") }) }) }) diff --git a/internal/controllermanager/prepare_controllers.go b/internal/controllermanager/prepare_controllers.go index 2ba51e16..f279479d 100644 --- a/internal/controllermanager/prepare_controllers.go +++ b/internal/controllermanager/prepare_controllers.go @@ -18,7 +18,7 @@ import ( "github.com/suzerain-io/controller-go" "github.com/suzerain-io/pinniped/internal/controller/apicerts" - "github.com/suzerain-io/pinniped/internal/controller/discovery" + "github.com/suzerain-io/pinniped/internal/controller/issuerconfig" "github.com/suzerain-io/pinniped/internal/provider" pinnipedclientset "github.com/suzerain-io/pinniped/kubernetes/1.19/client-go/clientset/versioned" pinnipedinformers "github.com/suzerain-io/pinniped/kubernetes/1.19/client-go/informers/externalversions" @@ -51,12 +51,12 @@ func PrepareControllers( controllerManager := controller. NewManager(). WithController( - discovery.NewPublisherController( + issuerconfig.NewPublisherController( serverInstallationNamespace, discoveryURLOverride, pinnipedClient, kubePublicNamespaceK8sInformers.Core().V1().ConfigMaps(), - installationNamespacePinnipedInformers.Crd().V1alpha1().PinnipedDiscoveryInfos(), + installationNamespacePinnipedInformers.Crd().V1alpha1().CredentialIssuerConfigs(), controller.WithInformer, ), singletonWorker, @@ -156,7 +156,7 @@ func createInformers( kubePublicNamespaceK8sInformers = k8sinformers.NewSharedInformerFactoryWithOptions( k8sClient, defaultResyncInterval, - k8sinformers.WithNamespace(discovery.ClusterInfoNamespace), + k8sinformers.WithNamespace(issuerconfig.ClusterInfoNamespace), ) installationNamespaceK8sInformers = k8sinformers.NewSharedInformerFactoryWithOptions( k8sClient, diff --git a/kubernetes/1.19/api/apis/crdpinniped/v1alpha1/register.go b/kubernetes/1.19/api/apis/crdpinniped/v1alpha1/register.go index 1210c96f..1a7cd407 100644 --- a/kubernetes/1.19/api/apis/crdpinniped/v1alpha1/register.go +++ b/kubernetes/1.19/api/apis/crdpinniped/v1alpha1/register.go @@ -33,8 +33,8 @@ func init() { // Adds the list of known types to the given scheme. func addKnownTypes(scheme *runtime.Scheme) error { scheme.AddKnownTypes(SchemeGroupVersion, - &PinnipedDiscoveryInfo{}, - &PinnipedDiscoveryInfoList{}, + &CredentialIssuerConfig{}, + &CredentialIssuerConfigList{}, ) metav1.AddToGroupVersion(scheme, SchemeGroupVersion) return nil diff --git a/kubernetes/1.19/api/apis/crdpinniped/v1alpha1/types.go b/kubernetes/1.19/api/apis/crdpinniped/v1alpha1/types.go index 7095ad92..eeefe7c7 100644 --- a/kubernetes/1.19/api/apis/crdpinniped/v1alpha1/types.go +++ b/kubernetes/1.19/api/apis/crdpinniped/v1alpha1/types.go @@ -7,7 +7,7 @@ package v1alpha1 import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -type PinnipedDiscoveryInfoSpec struct { +type CredentialIssuerConfigSpec struct { // The K8s API server URL. Required. Server string `json:"server,omitempty"` @@ -18,18 +18,18 @@ type PinnipedDiscoveryInfoSpec struct { // +genclient // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -type PinnipedDiscoveryInfo struct { +type CredentialIssuerConfig struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` - Spec PinnipedDiscoveryInfoSpec `json:"spec"` + Spec CredentialIssuerConfigSpec `json:"spec"` } // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -type PinnipedDiscoveryInfoList struct { +type CredentialIssuerConfigList struct { metav1.TypeMeta `json:",inline"` metav1.ListMeta `json:"metadata,omitempty"` - Items []PinnipedDiscoveryInfo `json:"items"` + Items []CredentialIssuerConfig `json:"items"` } diff --git a/kubernetes/1.19/api/apis/crdpinniped/v1alpha1/zz_generated.deepcopy.go b/kubernetes/1.19/api/apis/crdpinniped/v1alpha1/zz_generated.deepcopy.go index 6f1ddbdc..00966486 100644 --- a/kubernetes/1.19/api/apis/crdpinniped/v1alpha1/zz_generated.deepcopy.go +++ b/kubernetes/1.19/api/apis/crdpinniped/v1alpha1/zz_generated.deepcopy.go @@ -14,7 +14,7 @@ import ( ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *PinnipedDiscoveryInfo) DeepCopyInto(out *PinnipedDiscoveryInfo) { +func (in *CredentialIssuerConfig) DeepCopyInto(out *CredentialIssuerConfig) { *out = *in out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) @@ -22,18 +22,18 @@ func (in *PinnipedDiscoveryInfo) DeepCopyInto(out *PinnipedDiscoveryInfo) { return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PinnipedDiscoveryInfo. -func (in *PinnipedDiscoveryInfo) DeepCopy() *PinnipedDiscoveryInfo { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CredentialIssuerConfig. +func (in *CredentialIssuerConfig) DeepCopy() *CredentialIssuerConfig { if in == nil { return nil } - out := new(PinnipedDiscoveryInfo) + out := new(CredentialIssuerConfig) in.DeepCopyInto(out) return out } // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *PinnipedDiscoveryInfo) DeepCopyObject() runtime.Object { +func (in *CredentialIssuerConfig) DeepCopyObject() runtime.Object { if c := in.DeepCopy(); c != nil { return c } @@ -41,13 +41,13 @@ func (in *PinnipedDiscoveryInfo) DeepCopyObject() runtime.Object { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *PinnipedDiscoveryInfoList) DeepCopyInto(out *PinnipedDiscoveryInfoList) { +func (in *CredentialIssuerConfigList) DeepCopyInto(out *CredentialIssuerConfigList) { *out = *in out.TypeMeta = in.TypeMeta in.ListMeta.DeepCopyInto(&out.ListMeta) if in.Items != nil { in, out := &in.Items, &out.Items - *out = make([]PinnipedDiscoveryInfo, len(*in)) + *out = make([]CredentialIssuerConfig, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } @@ -55,18 +55,18 @@ func (in *PinnipedDiscoveryInfoList) DeepCopyInto(out *PinnipedDiscoveryInfoList return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PinnipedDiscoveryInfoList. -func (in *PinnipedDiscoveryInfoList) DeepCopy() *PinnipedDiscoveryInfoList { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CredentialIssuerConfigList. +func (in *CredentialIssuerConfigList) DeepCopy() *CredentialIssuerConfigList { if in == nil { return nil } - out := new(PinnipedDiscoveryInfoList) + out := new(CredentialIssuerConfigList) in.DeepCopyInto(out) return out } // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *PinnipedDiscoveryInfoList) DeepCopyObject() runtime.Object { +func (in *CredentialIssuerConfigList) DeepCopyObject() runtime.Object { if c := in.DeepCopy(); c != nil { return c } @@ -74,17 +74,17 @@ func (in *PinnipedDiscoveryInfoList) DeepCopyObject() runtime.Object { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *PinnipedDiscoveryInfoSpec) DeepCopyInto(out *PinnipedDiscoveryInfoSpec) { +func (in *CredentialIssuerConfigSpec) DeepCopyInto(out *CredentialIssuerConfigSpec) { *out = *in return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PinnipedDiscoveryInfoSpec. -func (in *PinnipedDiscoveryInfoSpec) DeepCopy() *PinnipedDiscoveryInfoSpec { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CredentialIssuerConfigSpec. +func (in *CredentialIssuerConfigSpec) DeepCopy() *CredentialIssuerConfigSpec { if in == nil { return nil } - out := new(PinnipedDiscoveryInfoSpec) + out := new(CredentialIssuerConfigSpec) in.DeepCopyInto(out) return out } diff --git a/kubernetes/1.19/api/generated/openapi/zz_generated.openapi.go b/kubernetes/1.19/api/generated/openapi/zz_generated.openapi.go index cde35ada..7ca6dfea 100644 --- a/kubernetes/1.19/api/generated/openapi/zz_generated.openapi.go +++ b/kubernetes/1.19/api/generated/openapi/zz_generated.openapi.go @@ -19,9 +19,9 @@ import ( func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenAPIDefinition { return map[string]common.OpenAPIDefinition{ - "github.com/suzerain-io/pinniped/kubernetes/1.19/api/apis/crdpinniped/v1alpha1.PinnipedDiscoveryInfo": schema_api_apis_crdpinniped_v1alpha1_PinnipedDiscoveryInfo(ref), - "github.com/suzerain-io/pinniped/kubernetes/1.19/api/apis/crdpinniped/v1alpha1.PinnipedDiscoveryInfoList": schema_api_apis_crdpinniped_v1alpha1_PinnipedDiscoveryInfoList(ref), - "github.com/suzerain-io/pinniped/kubernetes/1.19/api/apis/crdpinniped/v1alpha1.PinnipedDiscoveryInfoSpec": schema_api_apis_crdpinniped_v1alpha1_PinnipedDiscoveryInfoSpec(ref), + "github.com/suzerain-io/pinniped/kubernetes/1.19/api/apis/crdpinniped/v1alpha1.CredentialIssuerConfig": schema_api_apis_crdpinniped_v1alpha1_CredentialIssuerConfig(ref), + "github.com/suzerain-io/pinniped/kubernetes/1.19/api/apis/crdpinniped/v1alpha1.CredentialIssuerConfigList": schema_api_apis_crdpinniped_v1alpha1_CredentialIssuerConfigList(ref), + "github.com/suzerain-io/pinniped/kubernetes/1.19/api/apis/crdpinniped/v1alpha1.CredentialIssuerConfigSpec": schema_api_apis_crdpinniped_v1alpha1_CredentialIssuerConfigSpec(ref), "github.com/suzerain-io/pinniped/kubernetes/1.19/api/apis/pinniped/v1alpha1.CredentialRequest": schema_api_apis_pinniped_v1alpha1_CredentialRequest(ref), "github.com/suzerain-io/pinniped/kubernetes/1.19/api/apis/pinniped/v1alpha1.CredentialRequestCredential": schema_api_apis_pinniped_v1alpha1_CredentialRequestCredential(ref), "github.com/suzerain-io/pinniped/kubernetes/1.19/api/apis/pinniped/v1alpha1.CredentialRequestList": schema_api_apis_pinniped_v1alpha1_CredentialRequestList(ref), @@ -83,7 +83,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA } } -func schema_api_apis_crdpinniped_v1alpha1_PinnipedDiscoveryInfo(ref common.ReferenceCallback) common.OpenAPIDefinition { +func schema_api_apis_crdpinniped_v1alpha1_CredentialIssuerConfig(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -110,7 +110,7 @@ func schema_api_apis_crdpinniped_v1alpha1_PinnipedDiscoveryInfo(ref common.Refer }, "spec": { SchemaProps: spec.SchemaProps{ - Ref: ref("github.com/suzerain-io/pinniped/kubernetes/1.19/api/apis/crdpinniped/v1alpha1.PinnipedDiscoveryInfoSpec"), + Ref: ref("github.com/suzerain-io/pinniped/kubernetes/1.19/api/apis/crdpinniped/v1alpha1.CredentialIssuerConfigSpec"), }, }, }, @@ -118,11 +118,11 @@ func schema_api_apis_crdpinniped_v1alpha1_PinnipedDiscoveryInfo(ref common.Refer }, }, Dependencies: []string{ - "github.com/suzerain-io/pinniped/kubernetes/1.19/api/apis/crdpinniped/v1alpha1.PinnipedDiscoveryInfoSpec", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"}, + "github.com/suzerain-io/pinniped/kubernetes/1.19/api/apis/crdpinniped/v1alpha1.CredentialIssuerConfigSpec", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"}, } } -func schema_api_apis_crdpinniped_v1alpha1_PinnipedDiscoveryInfoList(ref common.ReferenceCallback) common.OpenAPIDefinition { +func schema_api_apis_crdpinniped_v1alpha1_CredentialIssuerConfigList(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -153,7 +153,7 @@ func schema_api_apis_crdpinniped_v1alpha1_PinnipedDiscoveryInfoList(ref common.R Items: &spec.SchemaOrArray{ Schema: &spec.Schema{ SchemaProps: spec.SchemaProps{ - Ref: ref("github.com/suzerain-io/pinniped/kubernetes/1.19/api/apis/crdpinniped/v1alpha1.PinnipedDiscoveryInfo"), + Ref: ref("github.com/suzerain-io/pinniped/kubernetes/1.19/api/apis/crdpinniped/v1alpha1.CredentialIssuerConfig"), }, }, }, @@ -164,11 +164,11 @@ func schema_api_apis_crdpinniped_v1alpha1_PinnipedDiscoveryInfoList(ref common.R }, }, Dependencies: []string{ - "github.com/suzerain-io/pinniped/kubernetes/1.19/api/apis/crdpinniped/v1alpha1.PinnipedDiscoveryInfo", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"}, + "github.com/suzerain-io/pinniped/kubernetes/1.19/api/apis/crdpinniped/v1alpha1.CredentialIssuerConfig", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"}, } } -func schema_api_apis_crdpinniped_v1alpha1_PinnipedDiscoveryInfoSpec(ref common.ReferenceCallback) common.OpenAPIDefinition { +func schema_api_apis_crdpinniped_v1alpha1_CredentialIssuerConfigSpec(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ diff --git a/kubernetes/1.19/client-go/clientset/versioned/typed/crdpinniped/v1alpha1/crdpinniped_client.go b/kubernetes/1.19/client-go/clientset/versioned/typed/crdpinniped/v1alpha1/crdpinniped_client.go index 7173d756..1e495ad2 100644 --- a/kubernetes/1.19/client-go/clientset/versioned/typed/crdpinniped/v1alpha1/crdpinniped_client.go +++ b/kubernetes/1.19/client-go/clientset/versioned/typed/crdpinniped/v1alpha1/crdpinniped_client.go @@ -15,7 +15,7 @@ import ( type CrdV1alpha1Interface interface { RESTClient() rest.Interface - PinnipedDiscoveryInfosGetter + CredentialIssuerConfigsGetter } // CrdV1alpha1Client is used to interact with features provided by the crd.pinniped.dev group. @@ -23,8 +23,8 @@ type CrdV1alpha1Client struct { restClient rest.Interface } -func (c *CrdV1alpha1Client) PinnipedDiscoveryInfos(namespace string) PinnipedDiscoveryInfoInterface { - return newPinnipedDiscoveryInfos(c, namespace) +func (c *CrdV1alpha1Client) CredentialIssuerConfigs(namespace string) CredentialIssuerConfigInterface { + return newCredentialIssuerConfigs(c, namespace) } // NewForConfig creates a new CrdV1alpha1Client for the given config. diff --git a/kubernetes/1.19/client-go/clientset/versioned/typed/crdpinniped/v1alpha1/fake/fake_crdpinniped_client.go b/kubernetes/1.19/client-go/clientset/versioned/typed/crdpinniped/v1alpha1/fake/fake_crdpinniped_client.go index cbc91103..f7b3a705 100644 --- a/kubernetes/1.19/client-go/clientset/versioned/typed/crdpinniped/v1alpha1/fake/fake_crdpinniped_client.go +++ b/kubernetes/1.19/client-go/clientset/versioned/typed/crdpinniped/v1alpha1/fake/fake_crdpinniped_client.go @@ -17,8 +17,8 @@ type FakeCrdV1alpha1 struct { *testing.Fake } -func (c *FakeCrdV1alpha1) PinnipedDiscoveryInfos(namespace string) v1alpha1.PinnipedDiscoveryInfoInterface { - return &FakePinnipedDiscoveryInfos{c, namespace} +func (c *FakeCrdV1alpha1) CredentialIssuerConfigs(namespace string) v1alpha1.CredentialIssuerConfigInterface { + return &FakeCredentialIssuerConfigs{c, namespace} } // RESTClient returns a RESTClient that is used to communicate diff --git a/kubernetes/1.19/client-go/clientset/versioned/typed/crdpinniped/v1alpha1/fake/fake_pinnipeddiscoveryinfo.go b/kubernetes/1.19/client-go/clientset/versioned/typed/crdpinniped/v1alpha1/fake/fake_pinnipeddiscoveryinfo.go index f900e1cf..e47d4030 100644 --- a/kubernetes/1.19/client-go/clientset/versioned/typed/crdpinniped/v1alpha1/fake/fake_pinnipeddiscoveryinfo.go +++ b/kubernetes/1.19/client-go/clientset/versioned/typed/crdpinniped/v1alpha1/fake/fake_pinnipeddiscoveryinfo.go @@ -19,31 +19,31 @@ import ( testing "k8s.io/client-go/testing" ) -// FakePinnipedDiscoveryInfos implements PinnipedDiscoveryInfoInterface -type FakePinnipedDiscoveryInfos struct { +// FakeCredentialIssuerConfigs implements CredentialIssuerConfigInterface +type FakeCredentialIssuerConfigs struct { Fake *FakeCrdV1alpha1 ns string } -var pinnipeddiscoveryinfosResource = schema.GroupVersionResource{Group: "crd.pinniped.dev", Version: "v1alpha1", Resource: "pinnipeddiscoveryinfos"} +var credentialissuerconfigsResource = schema.GroupVersionResource{Group: "crd.pinniped.dev", Version: "v1alpha1", Resource: "credentialissuerconfigs"} -var pinnipeddiscoveryinfosKind = schema.GroupVersionKind{Group: "crd.pinniped.dev", Version: "v1alpha1", Kind: "PinnipedDiscoveryInfo"} +var credentialissuerconfigsKind = schema.GroupVersionKind{Group: "crd.pinniped.dev", Version: "v1alpha1", Kind: "CredentialIssuerConfig"} -// Get takes name of the pinnipedDiscoveryInfo, and returns the corresponding pinnipedDiscoveryInfo object, and an error if there is any. -func (c *FakePinnipedDiscoveryInfos) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.PinnipedDiscoveryInfo, err error) { +// Get takes name of the credentialIssuerConfig, and returns the corresponding credentialIssuerConfig object, and an error if there is any. +func (c *FakeCredentialIssuerConfigs) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.CredentialIssuerConfig, err error) { obj, err := c.Fake. - Invokes(testing.NewGetAction(pinnipeddiscoveryinfosResource, c.ns, name), &v1alpha1.PinnipedDiscoveryInfo{}) + Invokes(testing.NewGetAction(credentialissuerconfigsResource, c.ns, name), &v1alpha1.CredentialIssuerConfig{}) if obj == nil { return nil, err } - return obj.(*v1alpha1.PinnipedDiscoveryInfo), err + return obj.(*v1alpha1.CredentialIssuerConfig), err } -// List takes label and field selectors, and returns the list of PinnipedDiscoveryInfos that match those selectors. -func (c *FakePinnipedDiscoveryInfos) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.PinnipedDiscoveryInfoList, err error) { +// List takes label and field selectors, and returns the list of CredentialIssuerConfigs that match those selectors. +func (c *FakeCredentialIssuerConfigs) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.CredentialIssuerConfigList, err error) { obj, err := c.Fake. - Invokes(testing.NewListAction(pinnipeddiscoveryinfosResource, pinnipeddiscoveryinfosKind, c.ns, opts), &v1alpha1.PinnipedDiscoveryInfoList{}) + Invokes(testing.NewListAction(credentialissuerconfigsResource, credentialissuerconfigsKind, c.ns, opts), &v1alpha1.CredentialIssuerConfigList{}) if obj == nil { return nil, err @@ -53,8 +53,8 @@ func (c *FakePinnipedDiscoveryInfos) List(ctx context.Context, opts v1.ListOptio if label == nil { label = labels.Everything() } - list := &v1alpha1.PinnipedDiscoveryInfoList{ListMeta: obj.(*v1alpha1.PinnipedDiscoveryInfoList).ListMeta} - for _, item := range obj.(*v1alpha1.PinnipedDiscoveryInfoList).Items { + list := &v1alpha1.CredentialIssuerConfigList{ListMeta: obj.(*v1alpha1.CredentialIssuerConfigList).ListMeta} + for _, item := range obj.(*v1alpha1.CredentialIssuerConfigList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) } @@ -62,58 +62,58 @@ func (c *FakePinnipedDiscoveryInfos) List(ctx context.Context, opts v1.ListOptio return list, err } -// Watch returns a watch.Interface that watches the requested pinnipedDiscoveryInfos. -func (c *FakePinnipedDiscoveryInfos) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { +// Watch returns a watch.Interface that watches the requested credentialIssuerConfigs. +func (c *FakeCredentialIssuerConfigs) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { return c.Fake. - InvokesWatch(testing.NewWatchAction(pinnipeddiscoveryinfosResource, c.ns, opts)) + InvokesWatch(testing.NewWatchAction(credentialissuerconfigsResource, c.ns, opts)) } -// Create takes the representation of a pinnipedDiscoveryInfo and creates it. Returns the server's representation of the pinnipedDiscoveryInfo, and an error, if there is any. -func (c *FakePinnipedDiscoveryInfos) Create(ctx context.Context, pinnipedDiscoveryInfo *v1alpha1.PinnipedDiscoveryInfo, opts v1.CreateOptions) (result *v1alpha1.PinnipedDiscoveryInfo, err error) { +// Create takes the representation of a credentialIssuerConfig and creates it. Returns the server's representation of the credentialIssuerConfig, and an error, if there is any. +func (c *FakeCredentialIssuerConfigs) Create(ctx context.Context, credentialIssuerConfig *v1alpha1.CredentialIssuerConfig, opts v1.CreateOptions) (result *v1alpha1.CredentialIssuerConfig, err error) { obj, err := c.Fake. - Invokes(testing.NewCreateAction(pinnipeddiscoveryinfosResource, c.ns, pinnipedDiscoveryInfo), &v1alpha1.PinnipedDiscoveryInfo{}) + Invokes(testing.NewCreateAction(credentialissuerconfigsResource, c.ns, credentialIssuerConfig), &v1alpha1.CredentialIssuerConfig{}) if obj == nil { return nil, err } - return obj.(*v1alpha1.PinnipedDiscoveryInfo), err + return obj.(*v1alpha1.CredentialIssuerConfig), err } -// Update takes the representation of a pinnipedDiscoveryInfo and updates it. Returns the server's representation of the pinnipedDiscoveryInfo, and an error, if there is any. -func (c *FakePinnipedDiscoveryInfos) Update(ctx context.Context, pinnipedDiscoveryInfo *v1alpha1.PinnipedDiscoveryInfo, opts v1.UpdateOptions) (result *v1alpha1.PinnipedDiscoveryInfo, err error) { +// Update takes the representation of a credentialIssuerConfig and updates it. Returns the server's representation of the credentialIssuerConfig, and an error, if there is any. +func (c *FakeCredentialIssuerConfigs) Update(ctx context.Context, credentialIssuerConfig *v1alpha1.CredentialIssuerConfig, opts v1.UpdateOptions) (result *v1alpha1.CredentialIssuerConfig, err error) { obj, err := c.Fake. - Invokes(testing.NewUpdateAction(pinnipeddiscoveryinfosResource, c.ns, pinnipedDiscoveryInfo), &v1alpha1.PinnipedDiscoveryInfo{}) + Invokes(testing.NewUpdateAction(credentialissuerconfigsResource, c.ns, credentialIssuerConfig), &v1alpha1.CredentialIssuerConfig{}) if obj == nil { return nil, err } - return obj.(*v1alpha1.PinnipedDiscoveryInfo), err + return obj.(*v1alpha1.CredentialIssuerConfig), err } -// Delete takes name of the pinnipedDiscoveryInfo and deletes it. Returns an error if one occurs. -func (c *FakePinnipedDiscoveryInfos) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { +// Delete takes name of the credentialIssuerConfig and deletes it. Returns an error if one occurs. +func (c *FakeCredentialIssuerConfigs) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { _, err := c.Fake. - Invokes(testing.NewDeleteAction(pinnipeddiscoveryinfosResource, c.ns, name), &v1alpha1.PinnipedDiscoveryInfo{}) + Invokes(testing.NewDeleteAction(credentialissuerconfigsResource, c.ns, name), &v1alpha1.CredentialIssuerConfig{}) return err } // DeleteCollection deletes a collection of objects. -func (c *FakePinnipedDiscoveryInfos) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { - action := testing.NewDeleteCollectionAction(pinnipeddiscoveryinfosResource, c.ns, listOpts) +func (c *FakeCredentialIssuerConfigs) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(credentialissuerconfigsResource, c.ns, listOpts) - _, err := c.Fake.Invokes(action, &v1alpha1.PinnipedDiscoveryInfoList{}) + _, err := c.Fake.Invokes(action, &v1alpha1.CredentialIssuerConfigList{}) return err } -// Patch applies the patch and returns the patched pinnipedDiscoveryInfo. -func (c *FakePinnipedDiscoveryInfos) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.PinnipedDiscoveryInfo, err error) { +// Patch applies the patch and returns the patched credentialIssuerConfig. +func (c *FakeCredentialIssuerConfigs) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.CredentialIssuerConfig, err error) { obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(pinnipeddiscoveryinfosResource, c.ns, name, pt, data, subresources...), &v1alpha1.PinnipedDiscoveryInfo{}) + Invokes(testing.NewPatchSubresourceAction(credentialissuerconfigsResource, c.ns, name, pt, data, subresources...), &v1alpha1.CredentialIssuerConfig{}) if obj == nil { return nil, err } - return obj.(*v1alpha1.PinnipedDiscoveryInfo), err + return obj.(*v1alpha1.CredentialIssuerConfig), err } diff --git a/kubernetes/1.19/client-go/clientset/versioned/typed/crdpinniped/v1alpha1/generated_expansion.go b/kubernetes/1.19/client-go/clientset/versioned/typed/crdpinniped/v1alpha1/generated_expansion.go index 7fc2b8a5..5a27a777 100644 --- a/kubernetes/1.19/client-go/clientset/versioned/typed/crdpinniped/v1alpha1/generated_expansion.go +++ b/kubernetes/1.19/client-go/clientset/versioned/typed/crdpinniped/v1alpha1/generated_expansion.go @@ -7,4 +7,4 @@ SPDX-License-Identifier: Apache-2.0 package v1alpha1 -type PinnipedDiscoveryInfoExpansion interface{} +type CredentialIssuerConfigExpansion interface{} diff --git a/kubernetes/1.19/client-go/clientset/versioned/typed/crdpinniped/v1alpha1/pinnipeddiscoveryinfo.go b/kubernetes/1.19/client-go/clientset/versioned/typed/crdpinniped/v1alpha1/pinnipeddiscoveryinfo.go index a229f15a..7afde8ec 100644 --- a/kubernetes/1.19/client-go/clientset/versioned/typed/crdpinniped/v1alpha1/pinnipeddiscoveryinfo.go +++ b/kubernetes/1.19/client-go/clientset/versioned/typed/crdpinniped/v1alpha1/pinnipeddiscoveryinfo.go @@ -19,45 +19,45 @@ import ( rest "k8s.io/client-go/rest" ) -// PinnipedDiscoveryInfosGetter has a method to return a PinnipedDiscoveryInfoInterface. +// CredentialIssuerConfigsGetter has a method to return a CredentialIssuerConfigInterface. // A group's client should implement this interface. -type PinnipedDiscoveryInfosGetter interface { - PinnipedDiscoveryInfos(namespace string) PinnipedDiscoveryInfoInterface +type CredentialIssuerConfigsGetter interface { + CredentialIssuerConfigs(namespace string) CredentialIssuerConfigInterface } -// PinnipedDiscoveryInfoInterface has methods to work with PinnipedDiscoveryInfo resources. -type PinnipedDiscoveryInfoInterface interface { - Create(ctx context.Context, pinnipedDiscoveryInfo *v1alpha1.PinnipedDiscoveryInfo, opts v1.CreateOptions) (*v1alpha1.PinnipedDiscoveryInfo, error) - Update(ctx context.Context, pinnipedDiscoveryInfo *v1alpha1.PinnipedDiscoveryInfo, opts v1.UpdateOptions) (*v1alpha1.PinnipedDiscoveryInfo, error) +// CredentialIssuerConfigInterface has methods to work with CredentialIssuerConfig resources. +type CredentialIssuerConfigInterface interface { + Create(ctx context.Context, credentialIssuerConfig *v1alpha1.CredentialIssuerConfig, opts v1.CreateOptions) (*v1alpha1.CredentialIssuerConfig, error) + Update(ctx context.Context, credentialIssuerConfig *v1alpha1.CredentialIssuerConfig, opts v1.UpdateOptions) (*v1alpha1.CredentialIssuerConfig, error) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error - Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.PinnipedDiscoveryInfo, error) - List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.PinnipedDiscoveryInfoList, error) + Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.CredentialIssuerConfig, error) + List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.CredentialIssuerConfigList, error) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) - Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.PinnipedDiscoveryInfo, err error) - PinnipedDiscoveryInfoExpansion + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.CredentialIssuerConfig, err error) + CredentialIssuerConfigExpansion } -// pinnipedDiscoveryInfos implements PinnipedDiscoveryInfoInterface -type pinnipedDiscoveryInfos struct { +// credentialIssuerConfigs implements CredentialIssuerConfigInterface +type credentialIssuerConfigs struct { client rest.Interface ns string } -// newPinnipedDiscoveryInfos returns a PinnipedDiscoveryInfos -func newPinnipedDiscoveryInfos(c *CrdV1alpha1Client, namespace string) *pinnipedDiscoveryInfos { - return &pinnipedDiscoveryInfos{ +// newCredentialIssuerConfigs returns a CredentialIssuerConfigs +func newCredentialIssuerConfigs(c *CrdV1alpha1Client, namespace string) *credentialIssuerConfigs { + return &credentialIssuerConfigs{ client: c.RESTClient(), ns: namespace, } } -// Get takes name of the pinnipedDiscoveryInfo, and returns the corresponding pinnipedDiscoveryInfo object, and an error if there is any. -func (c *pinnipedDiscoveryInfos) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.PinnipedDiscoveryInfo, err error) { - result = &v1alpha1.PinnipedDiscoveryInfo{} +// Get takes name of the credentialIssuerConfig, and returns the corresponding credentialIssuerConfig object, and an error if there is any. +func (c *credentialIssuerConfigs) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.CredentialIssuerConfig, err error) { + result = &v1alpha1.CredentialIssuerConfig{} err = c.client.Get(). Namespace(c.ns). - Resource("pinnipeddiscoveryinfos"). + Resource("credentialissuerconfigs"). Name(name). VersionedParams(&options, scheme.ParameterCodec). Do(ctx). @@ -65,16 +65,16 @@ func (c *pinnipedDiscoveryInfos) Get(ctx context.Context, name string, options v return } -// List takes label and field selectors, and returns the list of PinnipedDiscoveryInfos that match those selectors. -func (c *pinnipedDiscoveryInfos) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.PinnipedDiscoveryInfoList, err error) { +// List takes label and field selectors, and returns the list of CredentialIssuerConfigs that match those selectors. +func (c *credentialIssuerConfigs) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.CredentialIssuerConfigList, err error) { var timeout time.Duration if opts.TimeoutSeconds != nil { timeout = time.Duration(*opts.TimeoutSeconds) * time.Second } - result = &v1alpha1.PinnipedDiscoveryInfoList{} + result = &v1alpha1.CredentialIssuerConfigList{} err = c.client.Get(). Namespace(c.ns). - Resource("pinnipeddiscoveryinfos"). + Resource("credentialissuerconfigs"). VersionedParams(&opts, scheme.ParameterCodec). Timeout(timeout). Do(ctx). @@ -82,8 +82,8 @@ func (c *pinnipedDiscoveryInfos) List(ctx context.Context, opts v1.ListOptions) return } -// Watch returns a watch.Interface that watches the requested pinnipedDiscoveryInfos. -func (c *pinnipedDiscoveryInfos) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { +// Watch returns a watch.Interface that watches the requested credentialIssuerConfigs. +func (c *credentialIssuerConfigs) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { var timeout time.Duration if opts.TimeoutSeconds != nil { timeout = time.Duration(*opts.TimeoutSeconds) * time.Second @@ -91,44 +91,44 @@ func (c *pinnipedDiscoveryInfos) Watch(ctx context.Context, opts v1.ListOptions) opts.Watch = true return c.client.Get(). Namespace(c.ns). - Resource("pinnipeddiscoveryinfos"). + Resource("credentialissuerconfigs"). VersionedParams(&opts, scheme.ParameterCodec). Timeout(timeout). Watch(ctx) } -// Create takes the representation of a pinnipedDiscoveryInfo and creates it. Returns the server's representation of the pinnipedDiscoveryInfo, and an error, if there is any. -func (c *pinnipedDiscoveryInfos) Create(ctx context.Context, pinnipedDiscoveryInfo *v1alpha1.PinnipedDiscoveryInfo, opts v1.CreateOptions) (result *v1alpha1.PinnipedDiscoveryInfo, err error) { - result = &v1alpha1.PinnipedDiscoveryInfo{} +// Create takes the representation of a credentialIssuerConfig and creates it. Returns the server's representation of the credentialIssuerConfig, and an error, if there is any. +func (c *credentialIssuerConfigs) Create(ctx context.Context, credentialIssuerConfig *v1alpha1.CredentialIssuerConfig, opts v1.CreateOptions) (result *v1alpha1.CredentialIssuerConfig, err error) { + result = &v1alpha1.CredentialIssuerConfig{} err = c.client.Post(). Namespace(c.ns). - Resource("pinnipeddiscoveryinfos"). + Resource("credentialissuerconfigs"). VersionedParams(&opts, scheme.ParameterCodec). - Body(pinnipedDiscoveryInfo). + Body(credentialIssuerConfig). Do(ctx). Into(result) return } -// Update takes the representation of a pinnipedDiscoveryInfo and updates it. Returns the server's representation of the pinnipedDiscoveryInfo, and an error, if there is any. -func (c *pinnipedDiscoveryInfos) Update(ctx context.Context, pinnipedDiscoveryInfo *v1alpha1.PinnipedDiscoveryInfo, opts v1.UpdateOptions) (result *v1alpha1.PinnipedDiscoveryInfo, err error) { - result = &v1alpha1.PinnipedDiscoveryInfo{} +// Update takes the representation of a credentialIssuerConfig and updates it. Returns the server's representation of the credentialIssuerConfig, and an error, if there is any. +func (c *credentialIssuerConfigs) Update(ctx context.Context, credentialIssuerConfig *v1alpha1.CredentialIssuerConfig, opts v1.UpdateOptions) (result *v1alpha1.CredentialIssuerConfig, err error) { + result = &v1alpha1.CredentialIssuerConfig{} err = c.client.Put(). Namespace(c.ns). - Resource("pinnipeddiscoveryinfos"). - Name(pinnipedDiscoveryInfo.Name). + Resource("credentialissuerconfigs"). + Name(credentialIssuerConfig.Name). VersionedParams(&opts, scheme.ParameterCodec). - Body(pinnipedDiscoveryInfo). + Body(credentialIssuerConfig). Do(ctx). Into(result) return } -// Delete takes name of the pinnipedDiscoveryInfo and deletes it. Returns an error if one occurs. -func (c *pinnipedDiscoveryInfos) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { +// Delete takes name of the credentialIssuerConfig and deletes it. Returns an error if one occurs. +func (c *credentialIssuerConfigs) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { return c.client.Delete(). Namespace(c.ns). - Resource("pinnipeddiscoveryinfos"). + Resource("credentialissuerconfigs"). Name(name). Body(&opts). Do(ctx). @@ -136,14 +136,14 @@ func (c *pinnipedDiscoveryInfos) Delete(ctx context.Context, name string, opts v } // DeleteCollection deletes a collection of objects. -func (c *pinnipedDiscoveryInfos) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { +func (c *credentialIssuerConfigs) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { var timeout time.Duration if listOpts.TimeoutSeconds != nil { timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second } return c.client.Delete(). Namespace(c.ns). - Resource("pinnipeddiscoveryinfos"). + Resource("credentialissuerconfigs"). VersionedParams(&listOpts, scheme.ParameterCodec). Timeout(timeout). Body(&opts). @@ -151,12 +151,12 @@ func (c *pinnipedDiscoveryInfos) DeleteCollection(ctx context.Context, opts v1.D Error() } -// Patch applies the patch and returns the patched pinnipedDiscoveryInfo. -func (c *pinnipedDiscoveryInfos) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.PinnipedDiscoveryInfo, err error) { - result = &v1alpha1.PinnipedDiscoveryInfo{} +// Patch applies the patch and returns the patched credentialIssuerConfig. +func (c *credentialIssuerConfigs) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.CredentialIssuerConfig, err error) { + result = &v1alpha1.CredentialIssuerConfig{} err = c.client.Patch(pt). Namespace(c.ns). - Resource("pinnipeddiscoveryinfos"). + Resource("credentialissuerconfigs"). Name(name). SubResource(subresources...). VersionedParams(&opts, scheme.ParameterCodec). diff --git a/kubernetes/1.19/client-go/informers/externalversions/crdpinniped/v1alpha1/interface.go b/kubernetes/1.19/client-go/informers/externalversions/crdpinniped/v1alpha1/interface.go index ec531821..1b66393d 100644 --- a/kubernetes/1.19/client-go/informers/externalversions/crdpinniped/v1alpha1/interface.go +++ b/kubernetes/1.19/client-go/informers/externalversions/crdpinniped/v1alpha1/interface.go @@ -13,8 +13,8 @@ import ( // Interface provides access to all the informers in this group version. type Interface interface { - // PinnipedDiscoveryInfos returns a PinnipedDiscoveryInfoInformer. - PinnipedDiscoveryInfos() PinnipedDiscoveryInfoInformer + // CredentialIssuerConfigs returns a CredentialIssuerConfigInformer. + CredentialIssuerConfigs() CredentialIssuerConfigInformer } type version struct { @@ -28,7 +28,7 @@ func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakList return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} } -// PinnipedDiscoveryInfos returns a PinnipedDiscoveryInfoInformer. -func (v *version) PinnipedDiscoveryInfos() PinnipedDiscoveryInfoInformer { - return &pinnipedDiscoveryInfoInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +// CredentialIssuerConfigs returns a CredentialIssuerConfigInformer. +func (v *version) CredentialIssuerConfigs() CredentialIssuerConfigInformer { + return &credentialIssuerConfigInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} } diff --git a/kubernetes/1.19/client-go/informers/externalversions/crdpinniped/v1alpha1/pinnipeddiscoveryinfo.go b/kubernetes/1.19/client-go/informers/externalversions/crdpinniped/v1alpha1/pinnipeddiscoveryinfo.go index 624455c1..069ab576 100644 --- a/kubernetes/1.19/client-go/informers/externalversions/crdpinniped/v1alpha1/pinnipeddiscoveryinfo.go +++ b/kubernetes/1.19/client-go/informers/externalversions/crdpinniped/v1alpha1/pinnipeddiscoveryinfo.go @@ -21,59 +21,59 @@ import ( cache "k8s.io/client-go/tools/cache" ) -// PinnipedDiscoveryInfoInformer provides access to a shared informer and lister for -// PinnipedDiscoveryInfos. -type PinnipedDiscoveryInfoInformer interface { +// CredentialIssuerConfigInformer provides access to a shared informer and lister for +// CredentialIssuerConfigs. +type CredentialIssuerConfigInformer interface { Informer() cache.SharedIndexInformer - Lister() v1alpha1.PinnipedDiscoveryInfoLister + Lister() v1alpha1.CredentialIssuerConfigLister } -type pinnipedDiscoveryInfoInformer struct { +type credentialIssuerConfigInformer struct { factory internalinterfaces.SharedInformerFactory tweakListOptions internalinterfaces.TweakListOptionsFunc namespace string } -// NewPinnipedDiscoveryInfoInformer constructs a new informer for PinnipedDiscoveryInfo type. +// NewCredentialIssuerConfigInformer constructs a new informer for CredentialIssuerConfig type. // Always prefer using an informer factory to get a shared informer instead of getting an independent // one. This reduces memory footprint and number of connections to the server. -func NewPinnipedDiscoveryInfoInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { - return NewFilteredPinnipedDiscoveryInfoInformer(client, namespace, resyncPeriod, indexers, nil) +func NewCredentialIssuerConfigInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredCredentialIssuerConfigInformer(client, namespace, resyncPeriod, indexers, nil) } -// NewFilteredPinnipedDiscoveryInfoInformer constructs a new informer for PinnipedDiscoveryInfo type. +// NewFilteredCredentialIssuerConfigInformer constructs a new informer for CredentialIssuerConfig type. // Always prefer using an informer factory to get a shared informer instead of getting an independent // one. This reduces memory footprint and number of connections to the server. -func NewFilteredPinnipedDiscoveryInfoInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { +func NewFilteredCredentialIssuerConfigInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { return cache.NewSharedIndexInformer( &cache.ListWatch{ ListFunc: func(options v1.ListOptions) (runtime.Object, error) { if tweakListOptions != nil { tweakListOptions(&options) } - return client.CrdV1alpha1().PinnipedDiscoveryInfos(namespace).List(context.TODO(), options) + return client.CrdV1alpha1().CredentialIssuerConfigs(namespace).List(context.TODO(), options) }, WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { if tweakListOptions != nil { tweakListOptions(&options) } - return client.CrdV1alpha1().PinnipedDiscoveryInfos(namespace).Watch(context.TODO(), options) + return client.CrdV1alpha1().CredentialIssuerConfigs(namespace).Watch(context.TODO(), options) }, }, - &crdpinnipedv1alpha1.PinnipedDiscoveryInfo{}, + &crdpinnipedv1alpha1.CredentialIssuerConfig{}, resyncPeriod, indexers, ) } -func (f *pinnipedDiscoveryInfoInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { - return NewFilteredPinnipedDiscoveryInfoInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +func (f *credentialIssuerConfigInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredCredentialIssuerConfigInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) } -func (f *pinnipedDiscoveryInfoInformer) Informer() cache.SharedIndexInformer { - return f.factory.InformerFor(&crdpinnipedv1alpha1.PinnipedDiscoveryInfo{}, f.defaultInformer) +func (f *credentialIssuerConfigInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&crdpinnipedv1alpha1.CredentialIssuerConfig{}, f.defaultInformer) } -func (f *pinnipedDiscoveryInfoInformer) Lister() v1alpha1.PinnipedDiscoveryInfoLister { - return v1alpha1.NewPinnipedDiscoveryInfoLister(f.Informer().GetIndexer()) +func (f *credentialIssuerConfigInformer) Lister() v1alpha1.CredentialIssuerConfigLister { + return v1alpha1.NewCredentialIssuerConfigLister(f.Informer().GetIndexer()) } diff --git a/kubernetes/1.19/client-go/informers/externalversions/generic.go b/kubernetes/1.19/client-go/informers/externalversions/generic.go index 040e404f..eb6e0870 100644 --- a/kubernetes/1.19/client-go/informers/externalversions/generic.go +++ b/kubernetes/1.19/client-go/informers/externalversions/generic.go @@ -43,8 +43,8 @@ func (f *genericInformer) Lister() cache.GenericLister { func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) { switch resource { // Group=crd.pinniped.dev, Version=v1alpha1 - case v1alpha1.SchemeGroupVersion.WithResource("pinnipeddiscoveryinfos"): - return &genericInformer{resource: resource.GroupResource(), informer: f.Crd().V1alpha1().PinnipedDiscoveryInfos().Informer()}, nil + case v1alpha1.SchemeGroupVersion.WithResource("credentialissuerconfigs"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Crd().V1alpha1().CredentialIssuerConfigs().Informer()}, nil // Group=pinniped.dev, Version=v1alpha1 case pinnipedv1alpha1.SchemeGroupVersion.WithResource("credentialrequests"): diff --git a/kubernetes/1.19/client-go/listers/crdpinniped/v1alpha1/expansion_generated.go b/kubernetes/1.19/client-go/listers/crdpinniped/v1alpha1/expansion_generated.go index 27899f03..098d329d 100644 --- a/kubernetes/1.19/client-go/listers/crdpinniped/v1alpha1/expansion_generated.go +++ b/kubernetes/1.19/client-go/listers/crdpinniped/v1alpha1/expansion_generated.go @@ -7,10 +7,10 @@ SPDX-License-Identifier: Apache-2.0 package v1alpha1 -// PinnipedDiscoveryInfoListerExpansion allows custom methods to be added to -// PinnipedDiscoveryInfoLister. -type PinnipedDiscoveryInfoListerExpansion interface{} +// CredentialIssuerConfigListerExpansion allows custom methods to be added to +// CredentialIssuerConfigLister. +type CredentialIssuerConfigListerExpansion interface{} -// PinnipedDiscoveryInfoNamespaceListerExpansion allows custom methods to be added to -// PinnipedDiscoveryInfoNamespaceLister. -type PinnipedDiscoveryInfoNamespaceListerExpansion interface{} +// CredentialIssuerConfigNamespaceListerExpansion allows custom methods to be added to +// CredentialIssuerConfigNamespaceLister. +type CredentialIssuerConfigNamespaceListerExpansion interface{} diff --git a/kubernetes/1.19/client-go/listers/crdpinniped/v1alpha1/pinnipeddiscoveryinfo.go b/kubernetes/1.19/client-go/listers/crdpinniped/v1alpha1/pinnipeddiscoveryinfo.go index 47bafd01..316192a4 100644 --- a/kubernetes/1.19/client-go/listers/crdpinniped/v1alpha1/pinnipeddiscoveryinfo.go +++ b/kubernetes/1.19/client-go/listers/crdpinniped/v1alpha1/pinnipeddiscoveryinfo.go @@ -14,75 +14,75 @@ import ( "k8s.io/client-go/tools/cache" ) -// PinnipedDiscoveryInfoLister helps list PinnipedDiscoveryInfos. +// CredentialIssuerConfigLister helps list CredentialIssuerConfigs. // All objects returned here must be treated as read-only. -type PinnipedDiscoveryInfoLister interface { - // List lists all PinnipedDiscoveryInfos in the indexer. +type CredentialIssuerConfigLister interface { + // List lists all CredentialIssuerConfigs in the indexer. // Objects returned here must be treated as read-only. - List(selector labels.Selector) (ret []*v1alpha1.PinnipedDiscoveryInfo, err error) - // PinnipedDiscoveryInfos returns an object that can list and get PinnipedDiscoveryInfos. - PinnipedDiscoveryInfos(namespace string) PinnipedDiscoveryInfoNamespaceLister - PinnipedDiscoveryInfoListerExpansion + List(selector labels.Selector) (ret []*v1alpha1.CredentialIssuerConfig, err error) + // CredentialIssuerConfigs returns an object that can list and get CredentialIssuerConfigs. + CredentialIssuerConfigs(namespace string) CredentialIssuerConfigNamespaceLister + CredentialIssuerConfigListerExpansion } -// pinnipedDiscoveryInfoLister implements the PinnipedDiscoveryInfoLister interface. -type pinnipedDiscoveryInfoLister struct { +// credentialIssuerConfigLister implements the CredentialIssuerConfigLister interface. +type credentialIssuerConfigLister struct { indexer cache.Indexer } -// NewPinnipedDiscoveryInfoLister returns a new PinnipedDiscoveryInfoLister. -func NewPinnipedDiscoveryInfoLister(indexer cache.Indexer) PinnipedDiscoveryInfoLister { - return &pinnipedDiscoveryInfoLister{indexer: indexer} +// NewCredentialIssuerConfigLister returns a new CredentialIssuerConfigLister. +func NewCredentialIssuerConfigLister(indexer cache.Indexer) CredentialIssuerConfigLister { + return &credentialIssuerConfigLister{indexer: indexer} } -// List lists all PinnipedDiscoveryInfos in the indexer. -func (s *pinnipedDiscoveryInfoLister) List(selector labels.Selector) (ret []*v1alpha1.PinnipedDiscoveryInfo, err error) { +// List lists all CredentialIssuerConfigs in the indexer. +func (s *credentialIssuerConfigLister) List(selector labels.Selector) (ret []*v1alpha1.CredentialIssuerConfig, err error) { err = cache.ListAll(s.indexer, selector, func(m interface{}) { - ret = append(ret, m.(*v1alpha1.PinnipedDiscoveryInfo)) + ret = append(ret, m.(*v1alpha1.CredentialIssuerConfig)) }) return ret, err } -// PinnipedDiscoveryInfos returns an object that can list and get PinnipedDiscoveryInfos. -func (s *pinnipedDiscoveryInfoLister) PinnipedDiscoveryInfos(namespace string) PinnipedDiscoveryInfoNamespaceLister { - return pinnipedDiscoveryInfoNamespaceLister{indexer: s.indexer, namespace: namespace} +// CredentialIssuerConfigs returns an object that can list and get CredentialIssuerConfigs. +func (s *credentialIssuerConfigLister) CredentialIssuerConfigs(namespace string) CredentialIssuerConfigNamespaceLister { + return credentialIssuerConfigNamespaceLister{indexer: s.indexer, namespace: namespace} } -// PinnipedDiscoveryInfoNamespaceLister helps list and get PinnipedDiscoveryInfos. +// CredentialIssuerConfigNamespaceLister helps list and get CredentialIssuerConfigs. // All objects returned here must be treated as read-only. -type PinnipedDiscoveryInfoNamespaceLister interface { - // List lists all PinnipedDiscoveryInfos in the indexer for a given namespace. +type CredentialIssuerConfigNamespaceLister interface { + // List lists all CredentialIssuerConfigs in the indexer for a given namespace. // Objects returned here must be treated as read-only. - List(selector labels.Selector) (ret []*v1alpha1.PinnipedDiscoveryInfo, err error) - // Get retrieves the PinnipedDiscoveryInfo from the indexer for a given namespace and name. + List(selector labels.Selector) (ret []*v1alpha1.CredentialIssuerConfig, err error) + // Get retrieves the CredentialIssuerConfig from the indexer for a given namespace and name. // Objects returned here must be treated as read-only. - Get(name string) (*v1alpha1.PinnipedDiscoveryInfo, error) - PinnipedDiscoveryInfoNamespaceListerExpansion + Get(name string) (*v1alpha1.CredentialIssuerConfig, error) + CredentialIssuerConfigNamespaceListerExpansion } -// pinnipedDiscoveryInfoNamespaceLister implements the PinnipedDiscoveryInfoNamespaceLister +// credentialIssuerConfigNamespaceLister implements the CredentialIssuerConfigNamespaceLister // interface. -type pinnipedDiscoveryInfoNamespaceLister struct { +type credentialIssuerConfigNamespaceLister struct { indexer cache.Indexer namespace string } -// List lists all PinnipedDiscoveryInfos in the indexer for a given namespace. -func (s pinnipedDiscoveryInfoNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.PinnipedDiscoveryInfo, err error) { +// List lists all CredentialIssuerConfigs in the indexer for a given namespace. +func (s credentialIssuerConfigNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.CredentialIssuerConfig, err error) { err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { - ret = append(ret, m.(*v1alpha1.PinnipedDiscoveryInfo)) + ret = append(ret, m.(*v1alpha1.CredentialIssuerConfig)) }) return ret, err } -// Get retrieves the PinnipedDiscoveryInfo from the indexer for a given namespace and name. -func (s pinnipedDiscoveryInfoNamespaceLister) Get(name string) (*v1alpha1.PinnipedDiscoveryInfo, error) { +// Get retrieves the CredentialIssuerConfig from the indexer for a given namespace and name. +func (s credentialIssuerConfigNamespaceLister) Get(name string) (*v1alpha1.CredentialIssuerConfig, error) { obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) if err != nil { return nil, err } if !exists { - return nil, errors.NewNotFound(v1alpha1.Resource("pinnipeddiscoveryinfo"), name) + return nil, errors.NewNotFound(v1alpha1.Resource("credentialissuerconfig"), name) } - return obj.(*v1alpha1.PinnipedDiscoveryInfo), nil + return obj.(*v1alpha1.CredentialIssuerConfig), nil } diff --git a/test/integration/api_discovery_test.go b/test/integration/api_discovery_test.go index c0f797c1..55cccd66 100644 --- a/test/integration/api_discovery_test.go +++ b/test/integration/api_discovery_test.go @@ -61,14 +61,14 @@ func TestGetAPIResourceList(t *testing.T) { } expectedLDCAPIResource := metav1.APIResource{ - Name: "pinnipeddiscoveryinfos", - SingularName: "pinnipeddiscoveryinfo", + Name: "credentialissuerconfigs", + SingularName: "credentialissuerconfig", Namespaced: true, - Kind: "PinnipedDiscoveryInfo", + Kind: "CredentialIssuerConfig", Verbs: metav1.Verbs([]string{ "delete", "deletecollection", "get", "list", "patch", "create", "update", "watch", }), - ShortNames: []string{"ldc"}, + ShortNames: []string{"cic"}, StorageVersionHash: "unknown: to be filled in automatically below", } diff --git a/test/integration/pinnipeddiscoveryinfo_test.go b/test/integration/pinnipeddiscoveryinfo_test.go index 59d55512..e8a61b58 100644 --- a/test/integration/pinnipeddiscoveryinfo_test.go +++ b/test/integration/pinnipeddiscoveryinfo_test.go @@ -19,7 +19,7 @@ import ( "github.com/suzerain-io/pinniped/test/library" ) -func TestSuccessfulPinnipedDiscoveryInfo(t *testing.T) { +func TestSuccessfulCredentialIssuerConfig(t *testing.T) { library.SkipUnlessIntegration(t) namespaceName := library.Getenv(t, "PINNIPED_NAMESPACE") @@ -32,14 +32,14 @@ func TestSuccessfulPinnipedDiscoveryInfo(t *testing.T) { expectedLDCSpec := expectedLDCSpec(config) configList, err := client. CrdV1alpha1(). - PinnipedDiscoveryInfos(namespaceName). + CredentialIssuerConfigs(namespaceName). List(ctx, metav1.ListOptions{}) require.NoError(t, err) require.Len(t, configList.Items, 1) require.Equal(t, expectedLDCSpec, &configList.Items[0].Spec) } -func TestReconcilingPinnipedDiscoveryInfo(t *testing.T) { +func TestReconcilingCredentialIssuerConfig(t *testing.T) { library.SkipUnlessIntegration(t) namespaceName := library.Getenv(t, "PINNIPED_NAMESPACE") @@ -50,18 +50,18 @@ func TestReconcilingPinnipedDiscoveryInfo(t *testing.T) { err := client. CrdV1alpha1(). - PinnipedDiscoveryInfos(namespaceName). + CredentialIssuerConfigs(namespaceName). Delete(ctx, "pinniped-config", metav1.DeleteOptions{}) require.NoError(t, err) config := library.NewClientConfig(t) expectedLDCSpec := expectedLDCSpec(config) - var actualLDC *crdpinnipedv1alpha1.PinnipedDiscoveryInfo + var actualLDC *crdpinnipedv1alpha1.CredentialIssuerConfig for i := 0; i < 10; i++ { actualLDC, err = client. CrdV1alpha1(). - PinnipedDiscoveryInfos(namespaceName). + CredentialIssuerConfigs(namespaceName). Get(ctx, "pinniped-config", metav1.GetOptions{}) if err == nil { break @@ -72,8 +72,8 @@ func TestReconcilingPinnipedDiscoveryInfo(t *testing.T) { require.Equal(t, expectedLDCSpec, &actualLDC.Spec) } -func expectedLDCSpec(config *rest.Config) *crdpinnipedv1alpha1.PinnipedDiscoveryInfoSpec { - return &crdpinnipedv1alpha1.PinnipedDiscoveryInfoSpec{ +func expectedLDCSpec(config *rest.Config) *crdpinnipedv1alpha1.CredentialIssuerConfigSpec { + return &crdpinnipedv1alpha1.CredentialIssuerConfigSpec{ Server: config.Host, CertificateAuthorityData: base64.StdEncoding.EncodeToString(config.TLSClientConfig.CAData), } From 6d43d7ba19e849192301fcb498eafe22dd24e2df Mon Sep 17 00:00:00 2001 From: Ryan Richard Date: Fri, 21 Aug 2020 17:00:42 -0700 Subject: [PATCH 2/7] Update the schema of CredentialIssuerConfig - Move the current info from spec to status - Add schema for new stuff that we will use in a future commit to status - Regenerate the generated code --- deploy/crd.yaml | 61 +++-- internal/controller/issuerconfig/publisher.go | 35 +-- .../controller/issuerconfig/publisher_test.go | 13 +- .../api/apis/crdpinniped/v1alpha1/types.go | 19 +- .../v1alpha1/zz_generated.deepcopy.go | 55 ++++- .../generated/openapi/zz_generated.openapi.go | 226 ++++++++++++------ ...overyinfo.go => credentialissuerconfig.go} | 17 ++ ...info.go => fake_credentialissuerconfig.go} | 12 + ...overyinfo.go => credentialissuerconfig.go} | 0 ...overyinfo.go => credentialissuerconfig.go} | 0 ...test.go => credentialissuerconfig_test.go} | 19 +- 11 files changed, 333 insertions(+), 124 deletions(-) rename kubernetes/1.19/client-go/clientset/versioned/typed/crdpinniped/v1alpha1/{pinnipeddiscoveryinfo.go => credentialissuerconfig.go} (88%) rename kubernetes/1.19/client-go/clientset/versioned/typed/crdpinniped/v1alpha1/fake/{fake_pinnipeddiscoveryinfo.go => fake_credentialissuerconfig.go} (89%) rename kubernetes/1.19/client-go/informers/externalversions/crdpinniped/v1alpha1/{pinnipeddiscoveryinfo.go => credentialissuerconfig.go} (100%) rename kubernetes/1.19/client-go/listers/crdpinniped/v1alpha1/{pinnipeddiscoveryinfo.go => credentialissuerconfig.go} (100%) rename test/integration/{pinnipeddiscoveryinfo_test.go => credentialissuerconfig_test.go} (72%) diff --git a/deploy/crd.yaml b/deploy/crd.yaml index ce85d904..6239a56d 100644 --- a/deploy/crd.yaml +++ b/deploy/crd.yaml @@ -7,9 +7,16 @@ #! metadata: #! name: credential-issuer-config #! namespace: integration -#! spec: -#! server: https://foo -#! certificateAuthorityData: bar +#! status: +#! strategies: +#! - type: KubeClusterSigningCertificate +#! lastUpdateTime: 2020-08-21T20:08:18Z +#! status: Error +#! reason: CouldNotFetchKey +#! message: "There was an error getting the signing cert" +#! kubeConfigInfo: +#! server: https://foo +#! certificateAuthorityData: bar --- apiVersion: apiextensions.k8s.io/v1 @@ -20,26 +27,52 @@ spec: group: crd.pinniped.dev versions: #! Any changes to these schemas should also be reflected in the types.go file(s) - #! in https://github.com/suzerain-io/pinniped-api/tree/main/pkg/apis/pinniped - name: v1alpha1 served: true storage: true schema: openAPIV3Schema: type: object - required: [spec] properties: - spec: + status: type: object - required: [server, certificateAuthorityData] properties: - server: - type: string - minLength: 1 - pattern: '^https://|^http://' - certificateAuthorityData: - type: string - minLength: 1 + strategies: + type: array + items: + type: object + required: [ type, status,reason, message, lastUpdateTime ] + properties: + type: #! this property is called "type" + type: string + minLength: 1 + pattern: '^KubeClusterSigningCertificate$' + status: + type: string + minLength: 1 + pattern: '^Success$|^Error$' + reason: + type: string + minLength: 1 + pattern: '^CouldNotFetchKey$|^FetchedKey$' + message: + type: string + minLength: 1 + lastUpdateTime: + type: string + format: date-time + minLength: 1 + kubeConfigInfo: + type: object + required: [ server, certificateAuthorityData ] + properties: + server: + type: string + minLength: 1 + pattern: '^https://|^http://' + certificateAuthorityData: + type: string + minLength: 1 scope: Namespaced names: plural: credentialissuerconfigs diff --git a/internal/controller/issuerconfig/publisher.go b/internal/controller/issuerconfig/publisher.go index bac6d843..a7c2fef8 100644 --- a/internal/controller/issuerconfig/publisher.go +++ b/internal/controller/issuerconfig/publisher.go @@ -115,9 +115,12 @@ func (c *publisherController) Sync(ctx controller.Context) error { Name: configName, Namespace: c.namespace, }, - Spec: crdpinnipedv1alpha1.CredentialIssuerConfigSpec{ - Server: server, - CertificateAuthorityData: certificateAuthorityData, + Status: crdpinnipedv1alpha1.CredentialIssuerConfigStatus{ + Strategies: []crdpinnipedv1alpha1.CredentialIssuerConfigStrategy{}, + KubeConfigInfo: &crdpinnipedv1alpha1.CredentialIssuerConfigKubeConfigInfo{ + Server: server, + CertificateAuthorityData: certificateAuthorityData, + }, }, } if err := c.createOrUpdateCredentialIssuerConfig(ctx.Context, &credentialIssuerConfig); err != nil { @@ -129,34 +132,34 @@ func (c *publisherController) Sync(ctx controller.Context) error { func (c *publisherController) createOrUpdateCredentialIssuerConfig( ctx context.Context, - credentialIssuerConfig *crdpinnipedv1alpha1.CredentialIssuerConfig, + newCredentialIssuerConfig *crdpinnipedv1alpha1.CredentialIssuerConfig, ) error { existingCredentialIssuerConfig, err := c.credentialIssuerConfigInformer. Lister(). CredentialIssuerConfigs(c.namespace). - Get(credentialIssuerConfig.Name) + Get(newCredentialIssuerConfig.Name) notFound := k8serrors.IsNotFound(err) if err != nil && !notFound { return fmt.Errorf("could not get credentialissuerconfig: %w", err) } - credentialIssuerConfigs := c.pinnipedClient. - CrdV1alpha1(). - CredentialIssuerConfigs(c.namespace) + credentialIssuerConfigsClient := c.pinnipedClient.CrdV1alpha1().CredentialIssuerConfigs(c.namespace) if notFound { - if _, err := credentialIssuerConfigs.Create( + if _, err := credentialIssuerConfigsClient.Create( ctx, - credentialIssuerConfig, + newCredentialIssuerConfig, metav1.CreateOptions{}, ); err != nil { return fmt.Errorf("could not create credentialissuerconfig: %w", err) } - } else if !equal(existingCredentialIssuerConfig, credentialIssuerConfig) { + } else if !equal(existingCredentialIssuerConfig, newCredentialIssuerConfig) { // Update just the fields we care about. - existingCredentialIssuerConfig.Spec.Server = credentialIssuerConfig.Spec.Server - existingCredentialIssuerConfig.Spec.CertificateAuthorityData = credentialIssuerConfig.Spec.CertificateAuthorityData + newServer := newCredentialIssuerConfig.Status.KubeConfigInfo.Server + newCA := newCredentialIssuerConfig.Status.KubeConfigInfo.CertificateAuthorityData + existingCredentialIssuerConfig.Status.KubeConfigInfo.Server = newServer + existingCredentialIssuerConfig.Status.KubeConfigInfo.CertificateAuthorityData = newCA - if _, err := credentialIssuerConfigs.Update( + if _, err := credentialIssuerConfigsClient.Update( ctx, existingCredentialIssuerConfig, metav1.UpdateOptions{}, @@ -169,6 +172,6 @@ func (c *publisherController) createOrUpdateCredentialIssuerConfig( } func equal(a, b *crdpinnipedv1alpha1.CredentialIssuerConfig) bool { - return a.Spec.Server == b.Spec.Server && - a.Spec.CertificateAuthorityData == b.Spec.CertificateAuthorityData + return a.Status.KubeConfigInfo.Server == b.Status.KubeConfigInfo.Server && + a.Status.KubeConfigInfo.CertificateAuthorityData == b.Status.KubeConfigInfo.CertificateAuthorityData } diff --git a/internal/controller/issuerconfig/publisher_test.go b/internal/controller/issuerconfig/publisher_test.go index 4aefe2f6..81ca5ebf 100644 --- a/internal/controller/issuerconfig/publisher_test.go +++ b/internal/controller/issuerconfig/publisher_test.go @@ -190,9 +190,12 @@ func TestSync(t *testing.T) { Name: "pinniped-config", Namespace: expectedNamespace, }, - Spec: crdpinnipedv1alpha1.CredentialIssuerConfigSpec{ - Server: expectedServerURL, - CertificateAuthorityData: expectedCAData, + Status: crdpinnipedv1alpha1.CredentialIssuerConfigStatus{ + Strategies: []crdpinnipedv1alpha1.CredentialIssuerConfigStrategy{}, + KubeConfigInfo: &crdpinnipedv1alpha1.CredentialIssuerConfigKubeConfigInfo{ + Server: expectedServerURL, + CertificateAuthorityData: expectedCAData, + }, }, } return expectedCredentialIssuerConfigGVR, expectedCredentialIssuerConfig @@ -324,7 +327,7 @@ func TestSync(t *testing.T) { kubeServerURL, caData, ) - expectedCredentialIssuerConfig.Spec.Server = "https://some-server-override" + expectedCredentialIssuerConfig.Status.KubeConfigInfo.Server = "https://some-server-override" r.Equal( []coretesting.Action{ @@ -368,7 +371,7 @@ func TestSync(t *testing.T) { kubeServerURL, caData, ) - expectedCredentialIssuerConfig.Spec.Server = "https://some-other-server" + expectedCredentialIssuerConfig.Status.KubeConfigInfo.Server = "https://some-other-server" r.NoError(pinnipedInformerClient.Tracker().Add(expectedCredentialIssuerConfig)) r.NoError(pinnipedAPIClient.Tracker().Add(expectedCredentialIssuerConfig)) }) diff --git a/kubernetes/1.19/api/apis/crdpinniped/v1alpha1/types.go b/kubernetes/1.19/api/apis/crdpinniped/v1alpha1/types.go index eeefe7c7..cc45b17a 100644 --- a/kubernetes/1.19/api/apis/crdpinniped/v1alpha1/types.go +++ b/kubernetes/1.19/api/apis/crdpinniped/v1alpha1/types.go @@ -7,7 +7,14 @@ package v1alpha1 import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -type CredentialIssuerConfigSpec struct { +type CredentialIssuerConfigStatus struct { + Strategies []CredentialIssuerConfigStrategy `json:"strategies"` + + // +optional + KubeConfigInfo *CredentialIssuerConfigKubeConfigInfo `json:"kubeConfigInfo,omitempty"` +} + +type CredentialIssuerConfigKubeConfigInfo struct { // The K8s API server URL. Required. Server string `json:"server,omitempty"` @@ -15,6 +22,14 @@ type CredentialIssuerConfigSpec struct { CertificateAuthorityData string `json:"certificateAuthorityData,omitempty"` } +type CredentialIssuerConfigStrategy struct { + Type string `json:"type,omitempty"` + Status string `json:"status,omitempty"` + Reason string `json:"reason,omitempty"` + Message string `json:"message,omitempty"` + LastUpdateTime metav1.Time `json:"lastUpdateTime"` +} + // +genclient // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object @@ -22,7 +37,7 @@ type CredentialIssuerConfig struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` - Spec CredentialIssuerConfigSpec `json:"spec"` + Status CredentialIssuerConfigStatus `json:"status"` } // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object diff --git a/kubernetes/1.19/api/apis/crdpinniped/v1alpha1/zz_generated.deepcopy.go b/kubernetes/1.19/api/apis/crdpinniped/v1alpha1/zz_generated.deepcopy.go index 00966486..a57cd72e 100644 --- a/kubernetes/1.19/api/apis/crdpinniped/v1alpha1/zz_generated.deepcopy.go +++ b/kubernetes/1.19/api/apis/crdpinniped/v1alpha1/zz_generated.deepcopy.go @@ -18,7 +18,7 @@ func (in *CredentialIssuerConfig) DeepCopyInto(out *CredentialIssuerConfig) { *out = *in out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - out.Spec = in.Spec + in.Status.DeepCopyInto(&out.Status) return } @@ -40,6 +40,22 @@ func (in *CredentialIssuerConfig) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CredentialIssuerConfigKubeConfigInfo) DeepCopyInto(out *CredentialIssuerConfigKubeConfigInfo) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CredentialIssuerConfigKubeConfigInfo. +func (in *CredentialIssuerConfigKubeConfigInfo) DeepCopy() *CredentialIssuerConfigKubeConfigInfo { + if in == nil { + return nil + } + out := new(CredentialIssuerConfigKubeConfigInfo) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *CredentialIssuerConfigList) DeepCopyInto(out *CredentialIssuerConfigList) { *out = *in @@ -74,17 +90,46 @@ func (in *CredentialIssuerConfigList) DeepCopyObject() runtime.Object { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *CredentialIssuerConfigSpec) DeepCopyInto(out *CredentialIssuerConfigSpec) { +func (in *CredentialIssuerConfigStatus) DeepCopyInto(out *CredentialIssuerConfigStatus) { *out = *in + if in.Strategies != nil { + in, out := &in.Strategies, &out.Strategies + *out = make([]CredentialIssuerConfigStrategy, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.KubeConfigInfo != nil { + in, out := &in.KubeConfigInfo, &out.KubeConfigInfo + *out = new(CredentialIssuerConfigKubeConfigInfo) + **out = **in + } return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CredentialIssuerConfigSpec. -func (in *CredentialIssuerConfigSpec) DeepCopy() *CredentialIssuerConfigSpec { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CredentialIssuerConfigStatus. +func (in *CredentialIssuerConfigStatus) DeepCopy() *CredentialIssuerConfigStatus { if in == nil { return nil } - out := new(CredentialIssuerConfigSpec) + out := new(CredentialIssuerConfigStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CredentialIssuerConfigStrategy) DeepCopyInto(out *CredentialIssuerConfigStrategy) { + *out = *in + in.LastUpdateTime.DeepCopyInto(&out.LastUpdateTime) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CredentialIssuerConfigStrategy. +func (in *CredentialIssuerConfigStrategy) DeepCopy() *CredentialIssuerConfigStrategy { + if in == nil { + return nil + } + out := new(CredentialIssuerConfigStrategy) in.DeepCopyInto(out) return out } diff --git a/kubernetes/1.19/api/generated/openapi/zz_generated.openapi.go b/kubernetes/1.19/api/generated/openapi/zz_generated.openapi.go index 7ca6dfea..caea9dab 100644 --- a/kubernetes/1.19/api/generated/openapi/zz_generated.openapi.go +++ b/kubernetes/1.19/api/generated/openapi/zz_generated.openapi.go @@ -19,67 +19,69 @@ import ( func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenAPIDefinition { return map[string]common.OpenAPIDefinition{ - "github.com/suzerain-io/pinniped/kubernetes/1.19/api/apis/crdpinniped/v1alpha1.CredentialIssuerConfig": schema_api_apis_crdpinniped_v1alpha1_CredentialIssuerConfig(ref), - "github.com/suzerain-io/pinniped/kubernetes/1.19/api/apis/crdpinniped/v1alpha1.CredentialIssuerConfigList": schema_api_apis_crdpinniped_v1alpha1_CredentialIssuerConfigList(ref), - "github.com/suzerain-io/pinniped/kubernetes/1.19/api/apis/crdpinniped/v1alpha1.CredentialIssuerConfigSpec": schema_api_apis_crdpinniped_v1alpha1_CredentialIssuerConfigSpec(ref), - "github.com/suzerain-io/pinniped/kubernetes/1.19/api/apis/pinniped/v1alpha1.CredentialRequest": schema_api_apis_pinniped_v1alpha1_CredentialRequest(ref), - "github.com/suzerain-io/pinniped/kubernetes/1.19/api/apis/pinniped/v1alpha1.CredentialRequestCredential": schema_api_apis_pinniped_v1alpha1_CredentialRequestCredential(ref), - "github.com/suzerain-io/pinniped/kubernetes/1.19/api/apis/pinniped/v1alpha1.CredentialRequestList": schema_api_apis_pinniped_v1alpha1_CredentialRequestList(ref), - "github.com/suzerain-io/pinniped/kubernetes/1.19/api/apis/pinniped/v1alpha1.CredentialRequestSpec": schema_api_apis_pinniped_v1alpha1_CredentialRequestSpec(ref), - "github.com/suzerain-io/pinniped/kubernetes/1.19/api/apis/pinniped/v1alpha1.CredentialRequestStatus": schema_api_apis_pinniped_v1alpha1_CredentialRequestStatus(ref), - "github.com/suzerain-io/pinniped/kubernetes/1.19/api/apis/pinniped/v1alpha1.CredentialRequestTokenCredential": schema_api_apis_pinniped_v1alpha1_CredentialRequestTokenCredential(ref), - "k8s.io/apimachinery/pkg/apis/meta/v1.APIGroup": schema_pkg_apis_meta_v1_APIGroup(ref), - "k8s.io/apimachinery/pkg/apis/meta/v1.APIGroupList": schema_pkg_apis_meta_v1_APIGroupList(ref), - "k8s.io/apimachinery/pkg/apis/meta/v1.APIResource": schema_pkg_apis_meta_v1_APIResource(ref), - "k8s.io/apimachinery/pkg/apis/meta/v1.APIResourceList": schema_pkg_apis_meta_v1_APIResourceList(ref), - "k8s.io/apimachinery/pkg/apis/meta/v1.APIVersions": schema_pkg_apis_meta_v1_APIVersions(ref), - "k8s.io/apimachinery/pkg/apis/meta/v1.Condition": schema_pkg_apis_meta_v1_Condition(ref), - "k8s.io/apimachinery/pkg/apis/meta/v1.CreateOptions": schema_pkg_apis_meta_v1_CreateOptions(ref), - "k8s.io/apimachinery/pkg/apis/meta/v1.DeleteOptions": schema_pkg_apis_meta_v1_DeleteOptions(ref), - "k8s.io/apimachinery/pkg/apis/meta/v1.Duration": schema_pkg_apis_meta_v1_Duration(ref), - "k8s.io/apimachinery/pkg/apis/meta/v1.ExportOptions": schema_pkg_apis_meta_v1_ExportOptions(ref), - "k8s.io/apimachinery/pkg/apis/meta/v1.FieldsV1": schema_pkg_apis_meta_v1_FieldsV1(ref), - "k8s.io/apimachinery/pkg/apis/meta/v1.GetOptions": schema_pkg_apis_meta_v1_GetOptions(ref), - "k8s.io/apimachinery/pkg/apis/meta/v1.GroupKind": schema_pkg_apis_meta_v1_GroupKind(ref), - "k8s.io/apimachinery/pkg/apis/meta/v1.GroupResource": schema_pkg_apis_meta_v1_GroupResource(ref), - "k8s.io/apimachinery/pkg/apis/meta/v1.GroupVersion": schema_pkg_apis_meta_v1_GroupVersion(ref), - "k8s.io/apimachinery/pkg/apis/meta/v1.GroupVersionForDiscovery": schema_pkg_apis_meta_v1_GroupVersionForDiscovery(ref), - "k8s.io/apimachinery/pkg/apis/meta/v1.GroupVersionKind": schema_pkg_apis_meta_v1_GroupVersionKind(ref), - "k8s.io/apimachinery/pkg/apis/meta/v1.GroupVersionResource": schema_pkg_apis_meta_v1_GroupVersionResource(ref), - "k8s.io/apimachinery/pkg/apis/meta/v1.InternalEvent": schema_pkg_apis_meta_v1_InternalEvent(ref), - "k8s.io/apimachinery/pkg/apis/meta/v1.LabelSelector": schema_pkg_apis_meta_v1_LabelSelector(ref), - "k8s.io/apimachinery/pkg/apis/meta/v1.LabelSelectorRequirement": schema_pkg_apis_meta_v1_LabelSelectorRequirement(ref), - "k8s.io/apimachinery/pkg/apis/meta/v1.List": schema_pkg_apis_meta_v1_List(ref), - "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta": schema_pkg_apis_meta_v1_ListMeta(ref), - "k8s.io/apimachinery/pkg/apis/meta/v1.ListOptions": schema_pkg_apis_meta_v1_ListOptions(ref), - "k8s.io/apimachinery/pkg/apis/meta/v1.ManagedFieldsEntry": schema_pkg_apis_meta_v1_ManagedFieldsEntry(ref), - "k8s.io/apimachinery/pkg/apis/meta/v1.MicroTime": schema_pkg_apis_meta_v1_MicroTime(ref), - "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta": schema_pkg_apis_meta_v1_ObjectMeta(ref), - "k8s.io/apimachinery/pkg/apis/meta/v1.OwnerReference": schema_pkg_apis_meta_v1_OwnerReference(ref), - "k8s.io/apimachinery/pkg/apis/meta/v1.PartialObjectMetadata": schema_pkg_apis_meta_v1_PartialObjectMetadata(ref), - "k8s.io/apimachinery/pkg/apis/meta/v1.PartialObjectMetadataList": schema_pkg_apis_meta_v1_PartialObjectMetadataList(ref), - "k8s.io/apimachinery/pkg/apis/meta/v1.Patch": schema_pkg_apis_meta_v1_Patch(ref), - "k8s.io/apimachinery/pkg/apis/meta/v1.PatchOptions": schema_pkg_apis_meta_v1_PatchOptions(ref), - "k8s.io/apimachinery/pkg/apis/meta/v1.Preconditions": schema_pkg_apis_meta_v1_Preconditions(ref), - "k8s.io/apimachinery/pkg/apis/meta/v1.RootPaths": schema_pkg_apis_meta_v1_RootPaths(ref), - "k8s.io/apimachinery/pkg/apis/meta/v1.ServerAddressByClientCIDR": schema_pkg_apis_meta_v1_ServerAddressByClientCIDR(ref), - "k8s.io/apimachinery/pkg/apis/meta/v1.Status": schema_pkg_apis_meta_v1_Status(ref), - "k8s.io/apimachinery/pkg/apis/meta/v1.StatusCause": schema_pkg_apis_meta_v1_StatusCause(ref), - "k8s.io/apimachinery/pkg/apis/meta/v1.StatusDetails": schema_pkg_apis_meta_v1_StatusDetails(ref), - "k8s.io/apimachinery/pkg/apis/meta/v1.Table": schema_pkg_apis_meta_v1_Table(ref), - "k8s.io/apimachinery/pkg/apis/meta/v1.TableColumnDefinition": schema_pkg_apis_meta_v1_TableColumnDefinition(ref), - "k8s.io/apimachinery/pkg/apis/meta/v1.TableOptions": schema_pkg_apis_meta_v1_TableOptions(ref), - "k8s.io/apimachinery/pkg/apis/meta/v1.TableRow": schema_pkg_apis_meta_v1_TableRow(ref), - "k8s.io/apimachinery/pkg/apis/meta/v1.TableRowCondition": schema_pkg_apis_meta_v1_TableRowCondition(ref), - "k8s.io/apimachinery/pkg/apis/meta/v1.Time": schema_pkg_apis_meta_v1_Time(ref), - "k8s.io/apimachinery/pkg/apis/meta/v1.Timestamp": schema_pkg_apis_meta_v1_Timestamp(ref), - "k8s.io/apimachinery/pkg/apis/meta/v1.TypeMeta": schema_pkg_apis_meta_v1_TypeMeta(ref), - "k8s.io/apimachinery/pkg/apis/meta/v1.UpdateOptions": schema_pkg_apis_meta_v1_UpdateOptions(ref), - "k8s.io/apimachinery/pkg/apis/meta/v1.WatchEvent": schema_pkg_apis_meta_v1_WatchEvent(ref), - "k8s.io/apimachinery/pkg/runtime.RawExtension": schema_k8sio_apimachinery_pkg_runtime_RawExtension(ref), - "k8s.io/apimachinery/pkg/runtime.TypeMeta": schema_k8sio_apimachinery_pkg_runtime_TypeMeta(ref), - "k8s.io/apimachinery/pkg/runtime.Unknown": schema_k8sio_apimachinery_pkg_runtime_Unknown(ref), - "k8s.io/apimachinery/pkg/version.Info": schema_k8sio_apimachinery_pkg_version_Info(ref), + "github.com/suzerain-io/pinniped/kubernetes/1.19/api/apis/crdpinniped/v1alpha1.CredentialIssuerConfig": schema_api_apis_crdpinniped_v1alpha1_CredentialIssuerConfig(ref), + "github.com/suzerain-io/pinniped/kubernetes/1.19/api/apis/crdpinniped/v1alpha1.CredentialIssuerConfigKubeConfigInfo": schema_api_apis_crdpinniped_v1alpha1_CredentialIssuerConfigKubeConfigInfo(ref), + "github.com/suzerain-io/pinniped/kubernetes/1.19/api/apis/crdpinniped/v1alpha1.CredentialIssuerConfigList": schema_api_apis_crdpinniped_v1alpha1_CredentialIssuerConfigList(ref), + "github.com/suzerain-io/pinniped/kubernetes/1.19/api/apis/crdpinniped/v1alpha1.CredentialIssuerConfigStatus": schema_api_apis_crdpinniped_v1alpha1_CredentialIssuerConfigStatus(ref), + "github.com/suzerain-io/pinniped/kubernetes/1.19/api/apis/crdpinniped/v1alpha1.CredentialIssuerConfigStrategy": schema_api_apis_crdpinniped_v1alpha1_CredentialIssuerConfigStrategy(ref), + "github.com/suzerain-io/pinniped/kubernetes/1.19/api/apis/pinniped/v1alpha1.CredentialRequest": schema_api_apis_pinniped_v1alpha1_CredentialRequest(ref), + "github.com/suzerain-io/pinniped/kubernetes/1.19/api/apis/pinniped/v1alpha1.CredentialRequestCredential": schema_api_apis_pinniped_v1alpha1_CredentialRequestCredential(ref), + "github.com/suzerain-io/pinniped/kubernetes/1.19/api/apis/pinniped/v1alpha1.CredentialRequestList": schema_api_apis_pinniped_v1alpha1_CredentialRequestList(ref), + "github.com/suzerain-io/pinniped/kubernetes/1.19/api/apis/pinniped/v1alpha1.CredentialRequestSpec": schema_api_apis_pinniped_v1alpha1_CredentialRequestSpec(ref), + "github.com/suzerain-io/pinniped/kubernetes/1.19/api/apis/pinniped/v1alpha1.CredentialRequestStatus": schema_api_apis_pinniped_v1alpha1_CredentialRequestStatus(ref), + "github.com/suzerain-io/pinniped/kubernetes/1.19/api/apis/pinniped/v1alpha1.CredentialRequestTokenCredential": schema_api_apis_pinniped_v1alpha1_CredentialRequestTokenCredential(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.APIGroup": schema_pkg_apis_meta_v1_APIGroup(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.APIGroupList": schema_pkg_apis_meta_v1_APIGroupList(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.APIResource": schema_pkg_apis_meta_v1_APIResource(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.APIResourceList": schema_pkg_apis_meta_v1_APIResourceList(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.APIVersions": schema_pkg_apis_meta_v1_APIVersions(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.Condition": schema_pkg_apis_meta_v1_Condition(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.CreateOptions": schema_pkg_apis_meta_v1_CreateOptions(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.DeleteOptions": schema_pkg_apis_meta_v1_DeleteOptions(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.Duration": schema_pkg_apis_meta_v1_Duration(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.ExportOptions": schema_pkg_apis_meta_v1_ExportOptions(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.FieldsV1": schema_pkg_apis_meta_v1_FieldsV1(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.GetOptions": schema_pkg_apis_meta_v1_GetOptions(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.GroupKind": schema_pkg_apis_meta_v1_GroupKind(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.GroupResource": schema_pkg_apis_meta_v1_GroupResource(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.GroupVersion": schema_pkg_apis_meta_v1_GroupVersion(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.GroupVersionForDiscovery": schema_pkg_apis_meta_v1_GroupVersionForDiscovery(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.GroupVersionKind": schema_pkg_apis_meta_v1_GroupVersionKind(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.GroupVersionResource": schema_pkg_apis_meta_v1_GroupVersionResource(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.InternalEvent": schema_pkg_apis_meta_v1_InternalEvent(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.LabelSelector": schema_pkg_apis_meta_v1_LabelSelector(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.LabelSelectorRequirement": schema_pkg_apis_meta_v1_LabelSelectorRequirement(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.List": schema_pkg_apis_meta_v1_List(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta": schema_pkg_apis_meta_v1_ListMeta(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.ListOptions": schema_pkg_apis_meta_v1_ListOptions(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.ManagedFieldsEntry": schema_pkg_apis_meta_v1_ManagedFieldsEntry(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.MicroTime": schema_pkg_apis_meta_v1_MicroTime(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta": schema_pkg_apis_meta_v1_ObjectMeta(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.OwnerReference": schema_pkg_apis_meta_v1_OwnerReference(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.PartialObjectMetadata": schema_pkg_apis_meta_v1_PartialObjectMetadata(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.PartialObjectMetadataList": schema_pkg_apis_meta_v1_PartialObjectMetadataList(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.Patch": schema_pkg_apis_meta_v1_Patch(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.PatchOptions": schema_pkg_apis_meta_v1_PatchOptions(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.Preconditions": schema_pkg_apis_meta_v1_Preconditions(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.RootPaths": schema_pkg_apis_meta_v1_RootPaths(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.ServerAddressByClientCIDR": schema_pkg_apis_meta_v1_ServerAddressByClientCIDR(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.Status": schema_pkg_apis_meta_v1_Status(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.StatusCause": schema_pkg_apis_meta_v1_StatusCause(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.StatusDetails": schema_pkg_apis_meta_v1_StatusDetails(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.Table": schema_pkg_apis_meta_v1_Table(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.TableColumnDefinition": schema_pkg_apis_meta_v1_TableColumnDefinition(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.TableOptions": schema_pkg_apis_meta_v1_TableOptions(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.TableRow": schema_pkg_apis_meta_v1_TableRow(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.TableRowCondition": schema_pkg_apis_meta_v1_TableRowCondition(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.Time": schema_pkg_apis_meta_v1_Time(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.Timestamp": schema_pkg_apis_meta_v1_Timestamp(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.TypeMeta": schema_pkg_apis_meta_v1_TypeMeta(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.UpdateOptions": schema_pkg_apis_meta_v1_UpdateOptions(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.WatchEvent": schema_pkg_apis_meta_v1_WatchEvent(ref), + "k8s.io/apimachinery/pkg/runtime.RawExtension": schema_k8sio_apimachinery_pkg_runtime_RawExtension(ref), + "k8s.io/apimachinery/pkg/runtime.TypeMeta": schema_k8sio_apimachinery_pkg_runtime_TypeMeta(ref), + "k8s.io/apimachinery/pkg/runtime.Unknown": schema_k8sio_apimachinery_pkg_runtime_Unknown(ref), + "k8s.io/apimachinery/pkg/version.Info": schema_k8sio_apimachinery_pkg_version_Info(ref), } } @@ -108,17 +110,43 @@ func schema_api_apis_crdpinniped_v1alpha1_CredentialIssuerConfig(ref common.Refe Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"), }, }, - "spec": { + "status": { SchemaProps: spec.SchemaProps{ - Ref: ref("github.com/suzerain-io/pinniped/kubernetes/1.19/api/apis/crdpinniped/v1alpha1.CredentialIssuerConfigSpec"), + Ref: ref("github.com/suzerain-io/pinniped/kubernetes/1.19/api/apis/crdpinniped/v1alpha1.CredentialIssuerConfigStatus"), }, }, }, - Required: []string{"spec"}, + Required: []string{"status"}, }, }, Dependencies: []string{ - "github.com/suzerain-io/pinniped/kubernetes/1.19/api/apis/crdpinniped/v1alpha1.CredentialIssuerConfigSpec", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"}, + "github.com/suzerain-io/pinniped/kubernetes/1.19/api/apis/crdpinniped/v1alpha1.CredentialIssuerConfigStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"}, + } +} + +func schema_api_apis_crdpinniped_v1alpha1_CredentialIssuerConfigKubeConfigInfo(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "server": { + SchemaProps: spec.SchemaProps{ + Description: "The K8s API server URL. Required.", + Type: []string{"string"}, + Format: "", + }, + }, + "certificateAuthorityData": { + SchemaProps: spec.SchemaProps{ + Description: "The K8s API server CA bundle. Required.", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, } } @@ -168,29 +196,79 @@ func schema_api_apis_crdpinniped_v1alpha1_CredentialIssuerConfigList(ref common. } } -func schema_api_apis_crdpinniped_v1alpha1_CredentialIssuerConfigSpec(ref common.ReferenceCallback) common.OpenAPIDefinition { +func schema_api_apis_crdpinniped_v1alpha1_CredentialIssuerConfigStatus(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ Type: []string{"object"}, Properties: map[string]spec.Schema{ - "server": { + "strategies": { SchemaProps: spec.SchemaProps{ - Description: "The K8s API server URL. Required.", - Type: []string{"string"}, - Format: "", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Ref: ref("github.com/suzerain-io/pinniped/kubernetes/1.19/api/apis/crdpinniped/v1alpha1.CredentialIssuerConfigStrategy"), + }, + }, + }, }, }, - "certificateAuthorityData": { + "kubeConfigInfo": { SchemaProps: spec.SchemaProps{ - Description: "The K8s API server CA bundle. Required.", - Type: []string{"string"}, - Format: "", + Ref: ref("github.com/suzerain-io/pinniped/kubernetes/1.19/api/apis/crdpinniped/v1alpha1.CredentialIssuerConfigKubeConfigInfo"), }, }, }, + Required: []string{"strategies"}, }, }, + Dependencies: []string{ + "github.com/suzerain-io/pinniped/kubernetes/1.19/api/apis/crdpinniped/v1alpha1.CredentialIssuerConfigKubeConfigInfo", "github.com/suzerain-io/pinniped/kubernetes/1.19/api/apis/crdpinniped/v1alpha1.CredentialIssuerConfigStrategy"}, + } +} + +func schema_api_apis_crdpinniped_v1alpha1_CredentialIssuerConfigStrategy(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "type": { + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, + "status": { + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, + "reason": { + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, + "message": { + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, + "lastUpdateTime": { + SchemaProps: spec.SchemaProps{ + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"), + }, + }, + }, + Required: []string{"lastUpdateTime"}, + }, + }, + Dependencies: []string{ + "k8s.io/apimachinery/pkg/apis/meta/v1.Time"}, } } diff --git a/kubernetes/1.19/client-go/clientset/versioned/typed/crdpinniped/v1alpha1/pinnipeddiscoveryinfo.go b/kubernetes/1.19/client-go/clientset/versioned/typed/crdpinniped/v1alpha1/credentialissuerconfig.go similarity index 88% rename from kubernetes/1.19/client-go/clientset/versioned/typed/crdpinniped/v1alpha1/pinnipeddiscoveryinfo.go rename to kubernetes/1.19/client-go/clientset/versioned/typed/crdpinniped/v1alpha1/credentialissuerconfig.go index 7afde8ec..fa285269 100644 --- a/kubernetes/1.19/client-go/clientset/versioned/typed/crdpinniped/v1alpha1/pinnipeddiscoveryinfo.go +++ b/kubernetes/1.19/client-go/clientset/versioned/typed/crdpinniped/v1alpha1/credentialissuerconfig.go @@ -29,6 +29,7 @@ type CredentialIssuerConfigsGetter interface { type CredentialIssuerConfigInterface interface { Create(ctx context.Context, credentialIssuerConfig *v1alpha1.CredentialIssuerConfig, opts v1.CreateOptions) (*v1alpha1.CredentialIssuerConfig, error) Update(ctx context.Context, credentialIssuerConfig *v1alpha1.CredentialIssuerConfig, opts v1.UpdateOptions) (*v1alpha1.CredentialIssuerConfig, error) + UpdateStatus(ctx context.Context, credentialIssuerConfig *v1alpha1.CredentialIssuerConfig, opts v1.UpdateOptions) (*v1alpha1.CredentialIssuerConfig, error) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.CredentialIssuerConfig, error) @@ -124,6 +125,22 @@ func (c *credentialIssuerConfigs) Update(ctx context.Context, credentialIssuerCo return } +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *credentialIssuerConfigs) UpdateStatus(ctx context.Context, credentialIssuerConfig *v1alpha1.CredentialIssuerConfig, opts v1.UpdateOptions) (result *v1alpha1.CredentialIssuerConfig, err error) { + result = &v1alpha1.CredentialIssuerConfig{} + err = c.client.Put(). + Namespace(c.ns). + Resource("credentialissuerconfigs"). + Name(credentialIssuerConfig.Name). + SubResource("status"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(credentialIssuerConfig). + Do(ctx). + Into(result) + return +} + // Delete takes name of the credentialIssuerConfig and deletes it. Returns an error if one occurs. func (c *credentialIssuerConfigs) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { return c.client.Delete(). diff --git a/kubernetes/1.19/client-go/clientset/versioned/typed/crdpinniped/v1alpha1/fake/fake_pinnipeddiscoveryinfo.go b/kubernetes/1.19/client-go/clientset/versioned/typed/crdpinniped/v1alpha1/fake/fake_credentialissuerconfig.go similarity index 89% rename from kubernetes/1.19/client-go/clientset/versioned/typed/crdpinniped/v1alpha1/fake/fake_pinnipeddiscoveryinfo.go rename to kubernetes/1.19/client-go/clientset/versioned/typed/crdpinniped/v1alpha1/fake/fake_credentialissuerconfig.go index e47d4030..0aeb9959 100644 --- a/kubernetes/1.19/client-go/clientset/versioned/typed/crdpinniped/v1alpha1/fake/fake_pinnipeddiscoveryinfo.go +++ b/kubernetes/1.19/client-go/clientset/versioned/typed/crdpinniped/v1alpha1/fake/fake_credentialissuerconfig.go @@ -91,6 +91,18 @@ func (c *FakeCredentialIssuerConfigs) Update(ctx context.Context, credentialIssu return obj.(*v1alpha1.CredentialIssuerConfig), err } +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *FakeCredentialIssuerConfigs) UpdateStatus(ctx context.Context, credentialIssuerConfig *v1alpha1.CredentialIssuerConfig, opts v1.UpdateOptions) (*v1alpha1.CredentialIssuerConfig, error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateSubresourceAction(credentialissuerconfigsResource, "status", c.ns, credentialIssuerConfig), &v1alpha1.CredentialIssuerConfig{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.CredentialIssuerConfig), err +} + // Delete takes name of the credentialIssuerConfig and deletes it. Returns an error if one occurs. func (c *FakeCredentialIssuerConfigs) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { _, err := c.Fake. diff --git a/kubernetes/1.19/client-go/informers/externalversions/crdpinniped/v1alpha1/pinnipeddiscoveryinfo.go b/kubernetes/1.19/client-go/informers/externalversions/crdpinniped/v1alpha1/credentialissuerconfig.go similarity index 100% rename from kubernetes/1.19/client-go/informers/externalversions/crdpinniped/v1alpha1/pinnipeddiscoveryinfo.go rename to kubernetes/1.19/client-go/informers/externalversions/crdpinniped/v1alpha1/credentialissuerconfig.go diff --git a/kubernetes/1.19/client-go/listers/crdpinniped/v1alpha1/pinnipeddiscoveryinfo.go b/kubernetes/1.19/client-go/listers/crdpinniped/v1alpha1/credentialissuerconfig.go similarity index 100% rename from kubernetes/1.19/client-go/listers/crdpinniped/v1alpha1/pinnipeddiscoveryinfo.go rename to kubernetes/1.19/client-go/listers/crdpinniped/v1alpha1/credentialissuerconfig.go diff --git a/test/integration/pinnipeddiscoveryinfo_test.go b/test/integration/credentialissuerconfig_test.go similarity index 72% rename from test/integration/pinnipeddiscoveryinfo_test.go rename to test/integration/credentialissuerconfig_test.go index e8a61b58..1b21da76 100644 --- a/test/integration/pinnipeddiscoveryinfo_test.go +++ b/test/integration/credentialissuerconfig_test.go @@ -29,14 +29,14 @@ func TestSuccessfulCredentialIssuerConfig(t *testing.T) { defer cancel() config := library.NewClientConfig(t) - expectedLDCSpec := expectedLDCSpec(config) + expectedLDCStatus := expectedLDCStatus(config) configList, err := client. CrdV1alpha1(). CredentialIssuerConfigs(namespaceName). List(ctx, metav1.ListOptions{}) require.NoError(t, err) require.Len(t, configList.Items, 1) - require.Equal(t, expectedLDCSpec, &configList.Items[0].Spec) + require.Equal(t, expectedLDCStatus, &configList.Items[0].Status) } func TestReconcilingCredentialIssuerConfig(t *testing.T) { @@ -55,7 +55,7 @@ func TestReconcilingCredentialIssuerConfig(t *testing.T) { require.NoError(t, err) config := library.NewClientConfig(t) - expectedLDCSpec := expectedLDCSpec(config) + expectedLDCStatus := expectedLDCStatus(config) var actualLDC *crdpinnipedv1alpha1.CredentialIssuerConfig for i := 0; i < 10; i++ { @@ -69,12 +69,15 @@ func TestReconcilingCredentialIssuerConfig(t *testing.T) { time.Sleep(time.Millisecond * 750) } require.NoError(t, err) - require.Equal(t, expectedLDCSpec, &actualLDC.Spec) + require.Equal(t, expectedLDCStatus, &actualLDC.Status) } -func expectedLDCSpec(config *rest.Config) *crdpinnipedv1alpha1.CredentialIssuerConfigSpec { - return &crdpinnipedv1alpha1.CredentialIssuerConfigSpec{ - Server: config.Host, - CertificateAuthorityData: base64.StdEncoding.EncodeToString(config.TLSClientConfig.CAData), +func expectedLDCStatus(config *rest.Config) *crdpinnipedv1alpha1.CredentialIssuerConfigStatus { + return &crdpinnipedv1alpha1.CredentialIssuerConfigStatus{ + Strategies: []crdpinnipedv1alpha1.CredentialIssuerConfigStrategy{}, + KubeConfigInfo: &crdpinnipedv1alpha1.CredentialIssuerConfigKubeConfigInfo{ + Server: config.Host, + CertificateAuthorityData: base64.StdEncoding.EncodeToString(config.TLSClientConfig.CAData), + }, } } From 6e59596285ac6217f4fb3518d61f41a6a545d89e Mon Sep 17 00:00:00 2001 From: Ryan Richard Date: Mon, 24 Aug 2020 18:07:34 -0700 Subject: [PATCH 3/7] Upon pod startup, update the Status of CredentialIssuerConfig - Indicate the success or failure of the cluster signing key strategy - Also introduce the concept of "capabilities" of an integration test cluster to allow the integration tests to be run against clusters that do or don't allow the borrowing of the cluster signing key - Tests that are not expected to pass on clusters that lack the borrowing of the signing key capability are now ignored by calling the new library.SkipUnlessClusterHasCapability test helper - Rename library.Getenv to library.GetEnv - Add copyrights where they were missing --- deploy/crd.yaml | 19 +-- deploy/deployment.yaml | 3 + deploy/rbac.yaml | 3 + deploy/values.yaml | 3 + hack/get-ldflags.sh | 5 + hack/module.sh | 3 + hack/test-unit.sh | 2 + hack/update.sh | 2 + hack/verify.sh | 2 + internal/controller/issuerconfig/publisher.go | 136 ++++++++++++------ internal/server/server.go | 70 +++++++-- .../api/apis/crdpinniped/v1alpha1/types.go | 24 +++- test/cluster_capabilities/gke.yaml | 8 ++ test/cluster_capabilities/kind.yaml | 8 ++ test/cluster_capabilities/tkgs.yaml | 8 ++ test/go.mod | 1 + test/go.sum | 1 + test/integration/api_discovery_test.go | 7 +- test/integration/api_serving_certs_test.go | 9 +- test/integration/app_availability_test.go | 5 +- test/integration/client_test.go | 3 +- .../credentialissuerconfig_test.go | 109 ++++++++------ test/integration/credentialrequest_test.go | 14 +- test/integration/kubectl_test.go | 1 + test/library/cluster_capabilities.go | 53 +++++++ test/library/env.go | 4 +- 26 files changed, 376 insertions(+), 127 deletions(-) create mode 100644 test/cluster_capabilities/gke.yaml create mode 100644 test/cluster_capabilities/kind.yaml create mode 100644 test/cluster_capabilities/tkgs.yaml create mode 100644 test/library/cluster_capabilities.go diff --git a/deploy/crd.yaml b/deploy/crd.yaml index 6239a56d..0b70bb30 100644 --- a/deploy/crd.yaml +++ b/deploy/crd.yaml @@ -1,4 +1,5 @@ -#@ load("@ytt:data", "data") +#! Copyright 2020 VMware, Inc. +#! SPDX-License-Identifier: Apache-2.0 #! Example of valid CredentialIssuerConfig object: #! --- @@ -8,15 +9,17 @@ #! name: credential-issuer-config #! namespace: integration #! status: -#! strategies: -#! - type: KubeClusterSigningCertificate -#! lastUpdateTime: 2020-08-21T20:08:18Z -#! status: Error -#! reason: CouldNotFetchKey -#! message: "There was an error getting the signing cert" #! kubeConfigInfo: #! server: https://foo #! certificateAuthorityData: bar +#! strategies: +#! - type: KubeClusterSigningCertificate +#! status: Error +#! reason: CouldNotFetchKey +#! message: "There was an error getting the signing cert" +#! lastUpdateTime: 2020-08-21T20:08:18Z + +#@ load("@ytt:data", "data") --- apiVersion: apiextensions.k8s.io/v1 @@ -41,7 +44,7 @@ spec: type: array items: type: object - required: [ type, status,reason, message, lastUpdateTime ] + required: [ type, status, reason, message, lastUpdateTime ] properties: type: #! this property is called "type" type: string diff --git a/deploy/deployment.yaml b/deploy/deployment.yaml index 13712391..9271bc8e 100644 --- a/deploy/deployment.yaml +++ b/deploy/deployment.yaml @@ -1,3 +1,6 @@ +#! Copyright 2020 VMware, Inc. +#! SPDX-License-Identifier: Apache-2.0 + #@ load("@ytt:data", "data") --- diff --git a/deploy/rbac.yaml b/deploy/rbac.yaml index fe221862..c0d5dddc 100644 --- a/deploy/rbac.yaml +++ b/deploy/rbac.yaml @@ -1,3 +1,6 @@ +#! Copyright 2020 VMware, Inc. +#! SPDX-License-Identifier: Apache-2.0 + #@ load("@ytt:data", "data") #! Give permission to various cluster-scoped objects diff --git a/deploy/values.yaml b/deploy/values.yaml index cf91c93e..f422b352 100644 --- a/deploy/values.yaml +++ b/deploy/values.yaml @@ -1,3 +1,6 @@ +#! Copyright 2020 VMware, Inc. +#! SPDX-License-Identifier: Apache-2.0 + #@data/values --- diff --git a/hack/get-ldflags.sh b/hack/get-ldflags.sh index c634e864..520e3a7c 100755 --- a/hack/get-ldflags.sh +++ b/hack/get-ldflags.sh @@ -1,5 +1,10 @@ #!/usr/bin/env bash + +# Copyright 2020 VMware, Inc. +# SPDX-License-Identifier: Apache-2.0 + set -euo pipefail + ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd )" KUBE_ROOT="${ROOT}" # required by `hack/lib/version.sh` diff --git a/hack/module.sh b/hack/module.sh index 43ea49c8..5ad34f6c 100755 --- a/hack/module.sh +++ b/hack/module.sh @@ -1,5 +1,8 @@ #!/usr/bin/env bash +# Copyright 2020 VMware, Inc. +# SPDX-License-Identifier: Apache-2.0 + set -euo pipefail ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" diff --git a/hack/test-unit.sh b/hack/test-unit.sh index 38c0bc8e..a002fd85 100755 --- a/hack/test-unit.sh +++ b/hack/test-unit.sh @@ -2,7 +2,9 @@ # Copyright 2020 VMware, Inc. # SPDX-License-Identifier: Apache-2.0 + set -euo pipefail + ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd )" "$ROOT/hack/module.sh" unittest diff --git a/hack/update.sh b/hack/update.sh index 32345a0e..11cda145 100755 --- a/hack/update.sh +++ b/hack/update.sh @@ -2,7 +2,9 @@ # Copyright 2020 VMware, Inc. # SPDX-License-Identifier: Apache-2.0 + set -euo pipefail + ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd )" "$ROOT/hack/module.sh" tidy diff --git a/hack/verify.sh b/hack/verify.sh index 5f199725..87db0923 100755 --- a/hack/verify.sh +++ b/hack/verify.sh @@ -2,7 +2,9 @@ # Copyright 2020 VMware, Inc. # SPDX-License-Identifier: Apache-2.0 + set -euo pipefail + ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd )" "$ROOT/hack/module.sh" lint diff --git a/internal/controller/issuerconfig/publisher.go b/internal/controller/issuerconfig/publisher.go index a7c2fef8..e9876943 100644 --- a/internal/controller/issuerconfig/publisher.go +++ b/internal/controller/issuerconfig/publisher.go @@ -9,6 +9,7 @@ import ( "context" "encoding/base64" "fmt" + "reflect" k8serrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -109,61 +110,90 @@ func (c *publisherController) Sync(ctx controller.Context) error { server = *c.serverOverride } - credentialIssuerConfig := crdpinnipedv1alpha1.CredentialIssuerConfig{ - TypeMeta: metav1.TypeMeta{}, - ObjectMeta: metav1.ObjectMeta{ - Name: configName, - Namespace: c.namespace, - }, - Status: crdpinnipedv1alpha1.CredentialIssuerConfigStatus{ - Strategies: []crdpinnipedv1alpha1.CredentialIssuerConfigStrategy{}, - KubeConfigInfo: &crdpinnipedv1alpha1.CredentialIssuerConfigKubeConfigInfo{ - Server: server, - CertificateAuthorityData: certificateAuthorityData, - }, - }, - } - if err := c.createOrUpdateCredentialIssuerConfig(ctx.Context, &credentialIssuerConfig); err != nil { - return err - } - - return nil -} - -func (c *publisherController) createOrUpdateCredentialIssuerConfig( - ctx context.Context, - newCredentialIssuerConfig *crdpinnipedv1alpha1.CredentialIssuerConfig, -) error { - existingCredentialIssuerConfig, err := c.credentialIssuerConfigInformer. + existingCredentialIssuerConfigFromInformerCache, err := c.credentialIssuerConfigInformer. Lister(). CredentialIssuerConfigs(c.namespace). - Get(newCredentialIssuerConfig.Name) + Get(configName) + notFound = k8serrors.IsNotFound(err) + if err != nil && !notFound { + return fmt.Errorf("could not get credentialissuerconfig: %w", err) + } + + updateServerAndCAFunc := func(c *crdpinnipedv1alpha1.CredentialIssuerConfig) { + c.Status.KubeConfigInfo = &crdpinnipedv1alpha1.CredentialIssuerConfigKubeConfigInfo{ + Server: server, + CertificateAuthorityData: certificateAuthorityData, + } + } + err = createOrUpdateCredentialIssuerConfig( + ctx.Context, + existingCredentialIssuerConfigFromInformerCache, + notFound, + configName, + c.namespace, + c.pinnipedClient, + updateServerAndCAFunc) + return err +} + +func CreateOrUpdateCredentialIssuerConfig( + ctx context.Context, + credentialIssuerConfigNamespace string, + pinnipedClient pinnipedclientset.Interface, + applyUpdatesToCredentialIssuerConfigFunc func(configToUpdate *crdpinnipedv1alpha1.CredentialIssuerConfig), +) error { + credentialIssuerConfigName := configName + + existingCredentialIssuerConfig, err := pinnipedClient. + CrdV1alpha1(). + CredentialIssuerConfigs(credentialIssuerConfigNamespace). + Get(ctx, credentialIssuerConfigName, metav1.GetOptions{}) + notFound := k8serrors.IsNotFound(err) if err != nil && !notFound { return fmt.Errorf("could not get credentialissuerconfig: %w", err) } - credentialIssuerConfigsClient := c.pinnipedClient.CrdV1alpha1().CredentialIssuerConfigs(c.namespace) + return createOrUpdateCredentialIssuerConfig( + ctx, + existingCredentialIssuerConfig, + notFound, + credentialIssuerConfigName, + credentialIssuerConfigNamespace, + pinnipedClient, + applyUpdatesToCredentialIssuerConfigFunc) +} + +func createOrUpdateCredentialIssuerConfig( + ctx context.Context, + existingCredentialIssuerConfig *crdpinnipedv1alpha1.CredentialIssuerConfig, + notFound bool, + credentialIssuerConfigName string, + credentialIssuerConfigNamespace string, + pinnipedClient pinnipedclientset.Interface, + applyUpdatesToCredentialIssuerConfigFunc func(configToUpdate *crdpinnipedv1alpha1.CredentialIssuerConfig), +) error { + credentialIssuerConfigsClient := pinnipedClient.CrdV1alpha1().CredentialIssuerConfigs(credentialIssuerConfigNamespace) + if notFound { - if _, err := credentialIssuerConfigsClient.Create( - ctx, - newCredentialIssuerConfig, - metav1.CreateOptions{}, - ); err != nil { + // Create it + credentialIssuerConfig := minimalValidCredentialIssuerConfig(credentialIssuerConfigName, credentialIssuerConfigNamespace) + applyUpdatesToCredentialIssuerConfigFunc(credentialIssuerConfig) + + if _, err := credentialIssuerConfigsClient.Create(ctx, credentialIssuerConfig, metav1.CreateOptions{}); err != nil { return fmt.Errorf("could not create credentialissuerconfig: %w", err) } - } else if !equal(existingCredentialIssuerConfig, newCredentialIssuerConfig) { - // Update just the fields we care about. - newServer := newCredentialIssuerConfig.Status.KubeConfigInfo.Server - newCA := newCredentialIssuerConfig.Status.KubeConfigInfo.CertificateAuthorityData - existingCredentialIssuerConfig.Status.KubeConfigInfo.Server = newServer - existingCredentialIssuerConfig.Status.KubeConfigInfo.CertificateAuthorityData = newCA + } else { + // Already exists, so check to see if we need to update it + credentialIssuerConfig := existingCredentialIssuerConfig.DeepCopy() + applyUpdatesToCredentialIssuerConfigFunc(credentialIssuerConfig) - if _, err := credentialIssuerConfigsClient.Update( - ctx, - existingCredentialIssuerConfig, - metav1.UpdateOptions{}, - ); err != nil { + if reflect.DeepEqual(existingCredentialIssuerConfig.Status, credentialIssuerConfig.Status) { + // Nothing interesting would change as a result of this update, so skip it + return nil + } + + if _, err := credentialIssuerConfigsClient.Update(ctx, credentialIssuerConfig, metav1.UpdateOptions{}); err != nil { return fmt.Errorf("could not update credentialissuerconfig: %w", err) } } @@ -171,7 +201,19 @@ func (c *publisherController) createOrUpdateCredentialIssuerConfig( return nil } -func equal(a, b *crdpinnipedv1alpha1.CredentialIssuerConfig) bool { - return a.Status.KubeConfigInfo.Server == b.Status.KubeConfigInfo.Server && - a.Status.KubeConfigInfo.CertificateAuthorityData == b.Status.KubeConfigInfo.CertificateAuthorityData +func minimalValidCredentialIssuerConfig( + credentialIssuerConfigName string, + credentialIssuerConfigNamespace string, +) *crdpinnipedv1alpha1.CredentialIssuerConfig { + return &crdpinnipedv1alpha1.CredentialIssuerConfig{ + TypeMeta: metav1.TypeMeta{}, + ObjectMeta: metav1.ObjectMeta{ + Name: credentialIssuerConfigName, + Namespace: credentialIssuerConfigNamespace, + }, + Status: crdpinnipedv1alpha1.CredentialIssuerConfigStatus{ + Strategies: []crdpinnipedv1alpha1.CredentialIssuerConfigStrategy{}, + KubeConfigInfo: nil, + }, + } } diff --git a/internal/server/server.go b/internal/server/server.go index b6df64a7..b834625f 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -13,19 +13,24 @@ import ( "time" "github.com/spf13/cobra" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" genericapiserver "k8s.io/apiserver/pkg/server" genericoptions "k8s.io/apiserver/pkg/server/options" "k8s.io/apiserver/plugin/pkg/authenticator/token/webhook" "k8s.io/client-go/kubernetes" restclient "k8s.io/client-go/rest" + "k8s.io/klog/v2" "github.com/suzerain-io/pinniped/internal/apiserver" "github.com/suzerain-io/pinniped/internal/certauthority/kubecertauthority" + "github.com/suzerain-io/pinniped/internal/controller/issuerconfig" "github.com/suzerain-io/pinniped/internal/controllermanager" "github.com/suzerain-io/pinniped/internal/downward" "github.com/suzerain-io/pinniped/internal/provider" "github.com/suzerain-io/pinniped/internal/registry/credentialrequest" + crdpinnipedv1alpha1 "github.com/suzerain-io/pinniped/kubernetes/1.19/api/apis/crdpinniped/v1alpha1" pinnipedv1alpha1 "github.com/suzerain-io/pinniped/kubernetes/1.19/api/apis/pinniped/v1alpha1" + pinnipedclientset "github.com/suzerain-io/pinniped/kubernetes/1.19/client-go/clientset/versioned" "github.com/suzerain-io/pinniped/pkg/config" ) @@ -99,8 +104,15 @@ func (a *App) runServer(ctx context.Context) error { return fmt.Errorf("could not load config: %w", err) } + // Discover in which namespace we are installed. + podInfo, err := downward.Load(a.downwardAPIPath) + if err != nil { + return fmt.Errorf("could not read pod metadata: %w", err) + } + serverInstallationNamespace := podInfo.Namespace + // Load the Kubernetes cluster signing CA. - k8sClusterCA, shutdownCA, err := getClusterCASigner() + k8sClusterCA, shutdownCA, err := getClusterCASigner(ctx, serverInstallationNamespace) if err != nil { return err } @@ -112,13 +124,6 @@ func (a *App) runServer(ctx context.Context) error { return fmt.Errorf("could not create webhook client: %w", err) } - // Discover in which namespace we are installed. - podInfo, err := downward.Load(a.downwardAPIPath) - if err != nil { - return fmt.Errorf("could not read pod metadata: %w", err) - } - serverInstallationNamespace := podInfo.Namespace - // This cert provider will provide certs to the API server and will // be mutated by a controller to keep the certs up to date with what // is stored in a k8s Secret. Therefore it also effectively acting as @@ -160,7 +165,7 @@ func (a *App) runServer(ctx context.Context) error { return server.GenericAPIServer.PrepareRun().Run(ctx.Done()) } -func getClusterCASigner() (*kubecertauthority.CA, kubecertauthority.ShutdownFunc, error) { +func getClusterCASigner(ctx context.Context, serverInstallationNamespace string) (*kubecertauthority.CA, kubecertauthority.ShutdownFunc, error) { // Load the Kubernetes client configuration. kubeConfig, err := restclient.InClusterConfig() if err != nil { @@ -173,6 +178,12 @@ func getClusterCASigner() (*kubecertauthority.CA, kubecertauthority.ShutdownFunc return nil, nil, fmt.Errorf("could not initialize Kubernetes client: %w", err) } + // Connect to the pinniped API. + pinnipedClient, err := pinnipedclientset.NewForConfig(kubeConfig) + if err != nil { + return nil, nil, fmt.Errorf("could not initialize pinniped client: %w", err) + } + // Make a clock tick that triggers a periodic refresh. ticker := time.NewTicker(5 * time.Minute) @@ -182,10 +193,51 @@ func getClusterCASigner() (*kubecertauthority.CA, kubecertauthority.ShutdownFunc kubecertauthority.NewPodCommandExecutor(kubeConfig, kubeClient), ticker.C, ) + if err != nil { ticker.Stop() + + updateErr := issuerconfig.CreateOrUpdateCredentialIssuerConfig( + ctx, + serverInstallationNamespace, + pinnipedClient, + func(configToUpdate *crdpinnipedv1alpha1.CredentialIssuerConfig) { + configToUpdate.Status.Strategies = []crdpinnipedv1alpha1.CredentialIssuerConfigStrategy{ + { + Type: crdpinnipedv1alpha1.KubeClusterSigningCertificateStrategyType, + Status: crdpinnipedv1alpha1.ErrorStrategyStatus, + Reason: crdpinnipedv1alpha1.CouldNotFetchKeyStrategyReason, + Message: err.Error(), + LastUpdateTime: metav1.Now(), + }, + } + }, + ) + klog.Errorf("error performing create or update on CredentialIssuerConfig to add strategy error: %w", updateErr) + return nil, nil, fmt.Errorf("could not load cluster signing CA: %w", err) } + + updateErr := issuerconfig.CreateOrUpdateCredentialIssuerConfig( + ctx, + serverInstallationNamespace, + pinnipedClient, + func(configToUpdate *crdpinnipedv1alpha1.CredentialIssuerConfig) { + configToUpdate.Status.Strategies = []crdpinnipedv1alpha1.CredentialIssuerConfigStrategy{ + { + Type: crdpinnipedv1alpha1.KubeClusterSigningCertificateStrategyType, + Status: crdpinnipedv1alpha1.SuccessStrategyStatus, + Reason: crdpinnipedv1alpha1.FetchedKeyStrategyReason, + Message: "Key was fetched successfully", + LastUpdateTime: metav1.Now(), + }, + } + }, + ) + if updateErr != nil { + return nil, nil, fmt.Errorf("error performing create or update on CredentialIssuerConfig to add strategy success: %w", updateErr) + } + return k8sClusterCA, func() { shutdownCA(); ticker.Stop() }, nil } diff --git a/kubernetes/1.19/api/apis/crdpinniped/v1alpha1/types.go b/kubernetes/1.19/api/apis/crdpinniped/v1alpha1/types.go index cc45b17a..1fc6dc9a 100644 --- a/kubernetes/1.19/api/apis/crdpinniped/v1alpha1/types.go +++ b/kubernetes/1.19/api/apis/crdpinniped/v1alpha1/types.go @@ -7,6 +7,20 @@ package v1alpha1 import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +type StrategyType string +type StrategyStatus string +type StrategyReason string + +const ( + KubeClusterSigningCertificateStrategyType = StrategyType("KubeClusterSigningCertificate") + + SuccessStrategyStatus = StrategyStatus("Success") + ErrorStrategyStatus = StrategyStatus("Error") + + CouldNotFetchKeyStrategyReason = StrategyReason("CouldNotFetchKey") + FetchedKeyStrategyReason = StrategyReason("FetchedKey") +) + type CredentialIssuerConfigStatus struct { Strategies []CredentialIssuerConfigStrategy `json:"strategies"` @@ -23,11 +37,11 @@ type CredentialIssuerConfigKubeConfigInfo struct { } type CredentialIssuerConfigStrategy struct { - Type string `json:"type,omitempty"` - Status string `json:"status,omitempty"` - Reason string `json:"reason,omitempty"` - Message string `json:"message,omitempty"` - LastUpdateTime metav1.Time `json:"lastUpdateTime"` + Type StrategyType `json:"type,omitempty"` + Status StrategyStatus `json:"status,omitempty"` + Reason StrategyReason `json:"reason,omitempty"` + Message string `json:"message,omitempty"` + LastUpdateTime metav1.Time `json:"lastUpdateTime"` } // +genclient diff --git a/test/cluster_capabilities/gke.yaml b/test/cluster_capabilities/gke.yaml new file mode 100644 index 00000000..ea12f2c4 --- /dev/null +++ b/test/cluster_capabilities/gke.yaml @@ -0,0 +1,8 @@ +# Copyright 2020 VMware, Inc. +# SPDX-License-Identifier: Apache-2.0 + +# Describe the capabilities of the cluster against which the integration tests will run. +capabilities: + + # Is it possible to borrow the cluster's signing key from the kube API server? + clusterSigningKeyIsAvailable: false diff --git a/test/cluster_capabilities/kind.yaml b/test/cluster_capabilities/kind.yaml new file mode 100644 index 00000000..6201e409 --- /dev/null +++ b/test/cluster_capabilities/kind.yaml @@ -0,0 +1,8 @@ +# Copyright 2020 VMware, Inc. +# SPDX-License-Identifier: Apache-2.0 + +# Describe the capabilities of the cluster against which the integration tests will run. +capabilities: + + # Is it possible to borrow the cluster's signing key from the kube API server? + clusterSigningKeyIsAvailable: true diff --git a/test/cluster_capabilities/tkgs.yaml b/test/cluster_capabilities/tkgs.yaml new file mode 100644 index 00000000..6201e409 --- /dev/null +++ b/test/cluster_capabilities/tkgs.yaml @@ -0,0 +1,8 @@ +# Copyright 2020 VMware, Inc. +# SPDX-License-Identifier: Apache-2.0 + +# Describe the capabilities of the cluster against which the integration tests will run. +capabilities: + + # Is it possible to borrow the cluster's signing key from the kube API server? + clusterSigningKeyIsAvailable: true diff --git a/test/go.mod b/test/go.mod index 20dfd4d6..83ceefef 100644 --- a/test/go.mod +++ b/test/go.mod @@ -4,6 +4,7 @@ go 1.14 require ( github.com/davecgh/go-spew v1.1.1 + github.com/ghodss/yaml v1.0.0 github.com/stretchr/testify v1.6.1 github.com/suzerain-io/pinniped v0.0.0-20200819182107-1b9a70d089f4 github.com/suzerain-io/pinniped/kubernetes/1.19/api v0.0.0-00010101000000-000000000000 diff --git a/test/go.sum b/test/go.sum index 1e03f4e3..b1be2441 100644 --- a/test/go.sum +++ b/test/go.sum @@ -103,6 +103,7 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-critic/go-critic v0.5.0 h1:Ic2p5UCl5fX/2WX2w8nroPpPhxRNsNTMlJzsu/uqwnM= github.com/go-critic/go-critic v0.5.0/go.mod h1:4jeRh3ZAVnRYhuWdOEvwzVqLUpxMSoAT0xZ74JsTPlo= diff --git a/test/integration/api_discovery_test.go b/test/integration/api_discovery_test.go index 55cccd66..dc102bb8 100644 --- a/test/integration/api_discovery_test.go +++ b/test/integration/api_discovery_test.go @@ -16,6 +16,7 @@ import ( func TestGetAPIResourceList(t *testing.T) { library.SkipUnlessIntegration(t) + library.SkipUnlessClusterHasCapability(t, library.ClusterSigningKeyIsAvailable) client := library.NewPinnipedClientset(t) @@ -60,7 +61,7 @@ func TestGetAPIResourceList(t *testing.T) { SingularName: "", } - expectedLDCAPIResource := metav1.APIResource{ + expectedCredentialIssuerConfigResource := metav1.APIResource{ Name: "credentialissuerconfigs", SingularName: "credentialissuerconfig", Namespaced: true, @@ -79,8 +80,8 @@ func TestGetAPIResourceList(t *testing.T) { actualAPIResource := actualCrdPinnipedResources.APIResources[0] // workaround because its hard to predict the storage version hash (e.g. "t/+v41y+3e4=") // so just don't worry about comparing that field - expectedLDCAPIResource.StorageVersionHash = actualAPIResource.StorageVersionHash - require.Equal(t, expectedLDCAPIResource, actualAPIResource) + expectedCredentialIssuerConfigResource.StorageVersionHash = actualAPIResource.StorageVersionHash + require.Equal(t, expectedCredentialIssuerConfigResource, actualAPIResource) } func findGroup(name string, groups []*metav1.APIGroup) *metav1.APIGroup { diff --git a/test/integration/api_serving_certs_test.go b/test/integration/api_serving_certs_test.go index ec1ca3e2..79c96c98 100644 --- a/test/integration/api_serving_certs_test.go +++ b/test/integration/api_serving_certs_test.go @@ -22,6 +22,7 @@ import ( func TestAPIServingCertificateAutoCreationAndRotation(t *testing.T) { library.SkipUnlessIntegration(t) + library.SkipUnlessClusterHasCapability(t, library.ClusterSigningKeyIsAvailable) tests := []struct { name string @@ -74,7 +75,7 @@ func TestAPIServingCertificateAutoCreationAndRotation(t *testing.T) { for _, test := range tests { test := test t.Run(test.name, func(t *testing.T) { - namespaceName := library.Getenv(t, "PINNIPED_NAMESPACE") + namespaceName := library.GetEnv(t, "PINNIPED_NAMESPACE") kubeClient := library.NewClientset(t) aggregatedClient := library.NewAggregatedClientset(t) @@ -108,7 +109,7 @@ func TestAPIServingCertificateAutoCreationAndRotation(t *testing.T) { return err == nil } assert.Eventually(t, secretIsRegenerated, 10*time.Second, 250*time.Millisecond) - require.NoError(t, err) // prints out the error in case of failure + require.NoError(t, err) // prints out the error and stops the test in case of failure regeneratedCACert := secret.Data["caCertificate"] regeneratedPrivateKey := secret.Data["tlsPrivateKey"] regeneratedCertChain := secret.Data["tlsCertificateChain"] @@ -125,7 +126,7 @@ func TestAPIServingCertificateAutoCreationAndRotation(t *testing.T) { return err == nil } assert.Eventually(t, aggregatedAPIUpdated, 10*time.Second, 250*time.Millisecond) - require.NoError(t, err) // prints out the error in case of failure + require.NoError(t, err) // prints out the error and stops the test in case of failure require.Equal(t, regeneratedCACert, apiService.Spec.CABundle) // Check that we can still make requests to the aggregated API through the kube API server, @@ -147,7 +148,7 @@ func TestAPIServingCertificateAutoCreationAndRotation(t *testing.T) { // Unfortunately, although our code changes all the certs immediately, it seems to take ~1 minute for // the API machinery to notice that we updated our serving cert, causing 1 minute of downtime for our endpoint. assert.Eventually(t, aggregatedAPIWorking, 2*time.Minute, 250*time.Millisecond) - require.NoError(t, err) // prints out the error in case of failure + require.NoError(t, err) // prints out the error and stops the test in case of failure }) } } diff --git a/test/integration/app_availability_test.go b/test/integration/app_availability_test.go index e21c1ef2..a0f8430d 100644 --- a/test/integration/app_availability_test.go +++ b/test/integration/app_availability_test.go @@ -20,8 +20,9 @@ import ( func TestGetDeployment(t *testing.T) { library.SkipUnlessIntegration(t) - namespaceName := library.Getenv(t, "PINNIPED_NAMESPACE") - deploymentName := library.Getenv(t, "PINNIPED_APP_NAME") + library.SkipUnlessClusterHasCapability(t, library.ClusterSigningKeyIsAvailable) + namespaceName := library.GetEnv(t, "PINNIPED_NAMESPACE") + deploymentName := library.GetEnv(t, "PINNIPED_APP_NAME") client := library.NewClientset(t) diff --git a/test/integration/client_test.go b/test/integration/client_test.go index 1cb374a3..563ed249 100644 --- a/test/integration/client_test.go +++ b/test/integration/client_test.go @@ -56,7 +56,8 @@ var maskKey = func(s string) string { return strings.ReplaceAll(s, "TESTING KEY" func TestClient(t *testing.T) { library.SkipUnlessIntegration(t) - tmcClusterToken := library.Getenv(t, "PINNIPED_TMC_CLUSTER_TOKEN") + library.SkipUnlessClusterHasCapability(t, library.ClusterSigningKeyIsAvailable) + tmcClusterToken := library.GetEnv(t, "PINNIPED_TMC_CLUSTER_TOKEN") ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() diff --git a/test/integration/credentialissuerconfig_test.go b/test/integration/credentialissuerconfig_test.go index 1b21da76..8e028d54 100644 --- a/test/integration/credentialissuerconfig_test.go +++ b/test/integration/credentialissuerconfig_test.go @@ -11,6 +11,7 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/rest" @@ -19,65 +20,91 @@ import ( "github.com/suzerain-io/pinniped/test/library" ) -func TestSuccessfulCredentialIssuerConfig(t *testing.T) { +func TestCredentialIssuerConfig(t *testing.T) { library.SkipUnlessIntegration(t) - namespaceName := library.Getenv(t, "PINNIPED_NAMESPACE") + namespaceName := library.GetEnv(t, "PINNIPED_NAMESPACE") + config := library.NewClientConfig(t) client := library.NewPinnipedClientset(t) ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() - config := library.NewClientConfig(t) - expectedLDCStatus := expectedLDCStatus(config) - configList, err := client. - CrdV1alpha1(). - CredentialIssuerConfigs(namespaceName). - List(ctx, metav1.ListOptions{}) - require.NoError(t, err) - require.Len(t, configList.Items, 1) - require.Equal(t, expectedLDCStatus, &configList.Items[0].Status) -} + t.Run("test successful CredentialIssuerConfig", func(t *testing.T) { + actualConfigList, err := client. + CrdV1alpha1(). + CredentialIssuerConfigs(namespaceName). + List(ctx, metav1.ListOptions{}) + require.NoError(t, err) + require.Len(t, actualConfigList.Items, 1) -func TestReconcilingCredentialIssuerConfig(t *testing.T) { - library.SkipUnlessIntegration(t) - namespaceName := library.Getenv(t, "PINNIPED_NAMESPACE") + // Verify the published kube config info. + actualStatusKubeConfigInfo := actualConfigList.Items[0].Status.KubeConfigInfo + require.Equal(t, expectedStatusKubeConfigInfo(config), actualStatusKubeConfigInfo) - client := library.NewPinnipedClientset(t) + // Verify the cluster strategy status based on what's expected of the test cluster's ability to share signing keys. + actualStatusStrategies := actualConfigList.Items[0].Status.Strategies + require.Len(t, actualStatusStrategies, 1) + actualStatusStrategy := actualStatusStrategies[0] + require.Equal(t, crdpinnipedv1alpha1.KubeClusterSigningCertificateStrategyType, actualStatusStrategy.Type) - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - defer cancel() + if library.ClusterHasCapability(t, library.ClusterSigningKeyIsAvailable) { + require.Equal(t, crdpinnipedv1alpha1.SuccessStrategyStatus, actualStatusStrategy.Status) + require.Equal(t, crdpinnipedv1alpha1.FetchedKeyStrategyReason, actualStatusStrategy.Reason) + require.Equal(t, "Key was fetched successfully", actualStatusStrategy.Message) + } else { + require.Equal(t, crdpinnipedv1alpha1.ErrorStrategyStatus, actualStatusStrategy.Status) + require.Equal(t, crdpinnipedv1alpha1.CouldNotFetchKeyStrategyReason, actualStatusStrategy.Reason) + require.Contains(t, actualStatusStrategy.Message, "some part of the error message") + } - err := client. - CrdV1alpha1(). - CredentialIssuerConfigs(namespaceName). - Delete(ctx, "pinniped-config", metav1.DeleteOptions{}) - require.NoError(t, err) + require.WithinDuration(t, time.Now(), actualStatusStrategy.LastUpdateTime.Local(), 10*time.Minute) + }) - config := library.NewClientConfig(t) - expectedLDCStatus := expectedLDCStatus(config) + t.Run("reconciling CredentialIssuerConfig", func(t *testing.T) { + library.SkipUnlessClusterHasCapability(t, library.ClusterSigningKeyIsAvailable) - var actualLDC *crdpinnipedv1alpha1.CredentialIssuerConfig - for i := 0; i < 10; i++ { - actualLDC, err = client. + existingConfig, err := client. CrdV1alpha1(). CredentialIssuerConfigs(namespaceName). Get(ctx, "pinniped-config", metav1.GetOptions{}) - if err == nil { - break + require.NoError(t, err) + require.Len(t, existingConfig.Status.Strategies, 1) + initialStrategy := existingConfig.Status.Strategies[0] + + // Mutate the existing object. Don't delete it because that would mess up its `Status.Strategies` array, + // since the reconciling controller is not currently responsible for that field. + existingConfig.Status.KubeConfigInfo.Server = "https://junk" + updatedConfig, err := client. + CrdV1alpha1(). + CredentialIssuerConfigs(namespaceName). + Update(ctx, existingConfig, metav1.UpdateOptions{}) + require.NoError(t, err) + require.Equal(t, "https://junk", updatedConfig.Status.KubeConfigInfo.Server) + + // Expect that the object's mutated field is set back to what matches its source of truth. + var actualCredentialIssuerConfig *crdpinnipedv1alpha1.CredentialIssuerConfig + var getConfig = func() bool { + actualCredentialIssuerConfig, err = client. + CrdV1alpha1(). + CredentialIssuerConfigs(namespaceName). + Get(ctx, "pinniped-config", metav1.GetOptions{}) + return err == nil } - time.Sleep(time.Millisecond * 750) - } - require.NoError(t, err) - require.Equal(t, expectedLDCStatus, &actualLDC.Status) + assert.Eventually(t, getConfig, 5*time.Second, 100*time.Millisecond) + require.NoError(t, err) // prints out the error and stops the test in case of failure + actualStatusKubeConfigInfo := actualCredentialIssuerConfig.Status.KubeConfigInfo + require.Equal(t, expectedStatusKubeConfigInfo(config), actualStatusKubeConfigInfo) + + // The strategies should not have changed during reconciliation. + require.Len(t, actualCredentialIssuerConfig.Status.Strategies, 1) + require.Equal(t, initialStrategy, actualCredentialIssuerConfig.Status.Strategies[0]) + }) } -func expectedLDCStatus(config *rest.Config) *crdpinnipedv1alpha1.CredentialIssuerConfigStatus { - return &crdpinnipedv1alpha1.CredentialIssuerConfigStatus{ - Strategies: []crdpinnipedv1alpha1.CredentialIssuerConfigStrategy{}, - KubeConfigInfo: &crdpinnipedv1alpha1.CredentialIssuerConfigKubeConfigInfo{ - Server: config.Host, - CertificateAuthorityData: base64.StdEncoding.EncodeToString(config.TLSClientConfig.CAData), - }, +func expectedStatusKubeConfigInfo(config *rest.Config) *crdpinnipedv1alpha1.CredentialIssuerConfigKubeConfigInfo { + return &crdpinnipedv1alpha1.CredentialIssuerConfigKubeConfigInfo{ + Server: config.Host, + CertificateAuthorityData: base64.StdEncoding.EncodeToString(config.TLSClientConfig.CAData), } } diff --git a/test/integration/credentialrequest_test.go b/test/integration/credentialrequest_test.go index 69990850..0db47da8 100644 --- a/test/integration/credentialrequest_test.go +++ b/test/integration/credentialrequest_test.go @@ -14,9 +14,8 @@ import ( "time" "github.com/stretchr/testify/assert" - v1 "k8s.io/api/core/v1" - "github.com/stretchr/testify/require" + v1 "k8s.io/api/core/v1" rbacv1 "k8s.io/api/rbac/v1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -63,7 +62,8 @@ func addTestClusterRoleBinding(ctx context.Context, t *testing.T, adminClient ku func TestSuccessfulCredentialRequest(t *testing.T) { library.SkipUnlessIntegration(t) - tmcClusterToken := library.Getenv(t, "PINNIPED_TMC_CLUSTER_TOKEN") + library.SkipUnlessClusterHasCapability(t, library.ClusterSigningKeyIsAvailable) + tmcClusterToken := library.GetEnv(t, "PINNIPED_TMC_CLUSTER_TOKEN") response, err := makeRequest(t, v1alpha1.CredentialRequestSpec{ Type: v1alpha1.TokenCredentialType, @@ -121,7 +121,7 @@ func TestSuccessfulCredentialRequest(t *testing.T) { return err == nil } assert.Eventually(t, canListNamespaces, 3*time.Second, 250*time.Millisecond) - require.NoError(t, err) // prints out the error in case of failure + require.NoError(t, err) // prints out the error and stops the test in case of failure require.NotEmpty(t, listNamespaceResponse.Items) }) @@ -150,13 +150,15 @@ func TestSuccessfulCredentialRequest(t *testing.T) { return err == nil } assert.Eventually(t, canListNamespaces, 3*time.Second, 250*time.Millisecond) - require.NoError(t, err) // prints out the error in case of failure + require.NoError(t, err) // prints out the error and stops the test in case of failure require.NotEmpty(t, listNamespaceResponse.Items) }) } func TestFailedCredentialRequestWhenTheRequestIsValidButTheTokenDoesNotAuthenticateTheUser(t *testing.T) { library.SkipUnlessIntegration(t) + library.SkipUnlessClusterHasCapability(t, library.ClusterSigningKeyIsAvailable) + response, err := makeRequest(t, v1alpha1.CredentialRequestSpec{ Type: v1alpha1.TokenCredentialType, Token: &v1alpha1.CredentialRequestTokenCredential{Value: "not a good token"}, @@ -171,6 +173,8 @@ func TestFailedCredentialRequestWhenTheRequestIsValidButTheTokenDoesNotAuthentic func TestCredentialRequest_ShouldFailWhenRequestDoesNotIncludeToken(t *testing.T) { library.SkipUnlessIntegration(t) + library.SkipUnlessClusterHasCapability(t, library.ClusterSigningKeyIsAvailable) + response, err := makeRequest(t, v1alpha1.CredentialRequestSpec{ Type: v1alpha1.TokenCredentialType, Token: nil, diff --git a/test/integration/kubectl_test.go b/test/integration/kubectl_test.go index c849adef..6923b7cd 100644 --- a/test/integration/kubectl_test.go +++ b/test/integration/kubectl_test.go @@ -15,6 +15,7 @@ import ( "github.com/suzerain-io/pinniped/test/library" ) +// Smoke test to see if the kubeconfig works and the cluster is reachable. func TestGetNodes(t *testing.T) { library.SkipUnlessIntegration(t) cmd := exec.Command("kubectl", "get", "nodes") diff --git a/test/library/cluster_capabilities.go b/test/library/cluster_capabilities.go new file mode 100644 index 00000000..58418b9a --- /dev/null +++ b/test/library/cluster_capabilities.go @@ -0,0 +1,53 @@ +package library + +import ( + "io/ioutil" + "os" + "testing" + + "github.com/ghodss/yaml" + "github.com/stretchr/testify/require" +) + +type TestClusterCapability string + +const ( + ClusterSigningKeyIsAvailable = TestClusterCapability("clusterSigningKeyIsAvailable") +) + +type capabilitiesConfig struct { + Capabilities map[TestClusterCapability]bool `yaml:"capabilities,omitempty"` +} + +func ClusterHasCapability(t *testing.T, capability TestClusterCapability) bool { + t.Helper() + + capabilitiesDescriptionYAML := os.Getenv("PINNIPED_CLUSTER_CAPABILITY_YAML") + capabilitiesDescriptionFile := os.Getenv("PINNIPED_CLUSTER_CAPABILITY_FILE") + require.NotEmptyf(t, + capabilitiesDescriptionYAML+capabilitiesDescriptionFile, + "must specify either PINNIPED_CLUSTER_CAPABILITY_YAML or PINNIPED_CLUSTER_CAPABILITY_FILE env var for integration tests", + ) + + if capabilitiesDescriptionYAML == "" { + bytes, err := ioutil.ReadFile(capabilitiesDescriptionFile) + capabilitiesDescriptionYAML = string(bytes) + require.NoError(t, err) + } + + var capabilities capabilitiesConfig + err := yaml.Unmarshal([]byte(capabilitiesDescriptionYAML), &capabilities) + require.NoError(t, err) + + isCapable, capabilityWasDescribed := capabilities.Capabilities[capability] + require.True(t, capabilityWasDescribed, `the cluster's "%s" capability was not described`, capability) + + return isCapable +} + +func SkipUnlessClusterHasCapability(t *testing.T, capability TestClusterCapability) { + t.Helper() + if !ClusterHasCapability(t, capability) { + t.Skipf(`skipping integration test because cluster lacks the "%s" capability`, capability) + } +} diff --git a/test/library/env.go b/test/library/env.go index db0ff67a..5e19393e 100644 --- a/test/library/env.go +++ b/test/library/env.go @@ -12,9 +12,9 @@ import ( "github.com/stretchr/testify/require" ) -// Getenv gets the environment variable with key and asserts that it is not +// GetEnv gets the environment variable with key and asserts that it is not // empty. It returns the value of the environment variable. -func Getenv(t *testing.T, key string) string { +func GetEnv(t *testing.T, key string) string { t.Helper() value := os.Getenv(key) require.NotEmptyf(t, value, "must specify %s env var for integration tests", key) From 4306599396287926b94e379958937de4a6be0778 Mon Sep 17 00:00:00 2001 From: Andrew Keesler Date: Tue, 25 Aug 2020 08:26:42 -0400 Subject: [PATCH 4/7] Fix linter errors --- internal/server/server.go | 8 +++++--- test/library/cluster_capabilities.go | 5 +++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/internal/server/server.go b/internal/server/server.go index b834625f..3807a4c6 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -197,7 +197,7 @@ func getClusterCASigner(ctx context.Context, serverInstallationNamespace string) if err != nil { ticker.Stop() - updateErr := issuerconfig.CreateOrUpdateCredentialIssuerConfig( + if updateErr := issuerconfig.CreateOrUpdateCredentialIssuerConfig( ctx, serverInstallationNamespace, pinnipedClient, @@ -212,8 +212,9 @@ func getClusterCASigner(ctx context.Context, serverInstallationNamespace string) }, } }, - ) - klog.Errorf("error performing create or update on CredentialIssuerConfig to add strategy error: %w", updateErr) + ); updateErr != nil { + klog.Errorf("error performing create or update on CredentialIssuerConfig to add strategy error: %s", updateErr.Error()) + } return nil, nil, fmt.Errorf("could not load cluster signing CA: %w", err) } @@ -235,6 +236,7 @@ func getClusterCASigner(ctx context.Context, serverInstallationNamespace string) }, ) if updateErr != nil { + //nolint:goerr113 return nil, nil, fmt.Errorf("error performing create or update on CredentialIssuerConfig to add strategy success: %w", updateErr) } diff --git a/test/library/cluster_capabilities.go b/test/library/cluster_capabilities.go index 58418b9a..b606423f 100644 --- a/test/library/cluster_capabilities.go +++ b/test/library/cluster_capabilities.go @@ -1,3 +1,8 @@ +/* +Copyright 2020 VMware, Inc. +SPDX-License-Identifier: Apache-2.0 +*/ + package library import ( From 80153f9a8000d35a21bba9602678c8ecf04f6895 Mon Sep 17 00:00:00 2001 From: Ryan Richard Date: Tue, 25 Aug 2020 18:22:53 -0700 Subject: [PATCH 5/7] Allow app to start despite failing to borrow the cluster signing key - Controller and aggregated API server are allowed to run - Keep retrying to borrow the cluster signing key in case the failure to get it was caused by a transient failure - The CredentialRequest endpoint will always return an authentication failure as long as the cluster signing key cannot be borrowed - Update which integration tests are skipped to reflect what should and should not work based on the cluster's capability under this new behavior - Move CreateOrUpdateCredentialIssuerConfig() and related methods to their own file - Update the CredentialIssuerConfig's Status every time we try to refresh the cluster signing key --- go.sum | 1 + .../kubecertauthority/kubecertauthority.go | 52 +++-- .../kubecertauthority_test.go | 190 ++++++++++++++---- ...eate_or_update_credential_issuer_config.go | 100 +++++++++ internal/controller/issuerconfig/publisher.go | 85 -------- internal/server/server.go | 85 ++++---- internal/testutil/transcript_logger.go | 4 +- test/go.mod | 2 +- test/integration/api_discovery_test.go | 1 - test/integration/api_serving_certs_test.go | 1 - test/integration/app_availability_test.go | 1 - .../credentialissuerconfig_test.go | 13 +- test/integration/credentialrequest_test.go | 99 +++++---- test/library/cluster_capabilities.go | 9 +- 14 files changed, 412 insertions(+), 231 deletions(-) create mode 100644 internal/controller/issuerconfig/create_or_update_credential_issuer_config.go diff --git a/go.sum b/go.sum index ef5017ef..993f4217 100644 --- a/go.sum +++ b/go.sum @@ -106,6 +106,7 @@ github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3 github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153 h1:yUdfgN0XgIJw7foRItutHYUIhlcKzcSf5vDpdhQAKTc= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/emicklei/go-restful v2.9.5+incompatible h1:spTtZBk5DYEvbxMVutUuTyh1Ao2r4iyvLdACqsl/Ljk= diff --git a/internal/certauthority/kubecertauthority/kubecertauthority.go b/internal/certauthority/kubecertauthority/kubecertauthority.go index 3840e748..ecde257d 100644 --- a/internal/certauthority/kubecertauthority/kubecertauthority.go +++ b/internal/certauthority/kubecertauthority/kubecertauthority.go @@ -30,6 +30,7 @@ import ( // ErrNoKubeControllerManagerPod is returned when no kube-controller-manager pod is found on the cluster. const ErrNoKubeControllerManagerPod = constable.Error("did not find kube-controller-manager pod") +const ErrIncapableOfIssuingCertificates = constable.Error("this cluster is not currently capable of issuing certificates") const k8sAPIServerCACertPEMDefaultPath = "/etc/kubernetes/ca/ca.pem" const k8sAPIServerCAKeyPEMDefaultPath = "/etc/kubernetes/ca/ca.key" @@ -86,31 +87,50 @@ type CA struct { shutdown, done chan struct{} + onSuccessfulRefresh SuccessCallback + onFailedRefresh FailureCallback + lock sync.RWMutex activeSigner signer } type ShutdownFunc func() +type SuccessCallback func() +type FailureCallback func(error) -// New creates a new instance of a CA which is has loaded the kube API server's private key -// and is ready to issue certs, or an error. When successful, it also starts a goroutine -// to periodically reload the kube API server's private key in case it changed, and returns -// a function that can be used to shut down that goroutine. -func New(kubeClient kubernetes.Interface, podCommandExecutor PodCommandExecutor, tick <-chan time.Time) (*CA, ShutdownFunc, error) { +// New creates a new instance of a CA. It tries to load the kube API server's private key +// immediately. If that succeeds then it calls the success callback and it is ready to issue certs. +// When it fails to get the kube API server's private key, then it calls the failure callback and +// it will try again on the next tick. It starts a goroutine to periodically reload the kube +// API server's private key in case it failed previously or case the key has changed. It returns +// a function that can be used to shut down that goroutine. Future attempts made by that goroutine +// to get the key will also result in success or failure callbacks. +func New( + kubeClient kubernetes.Interface, + podCommandExecutor PodCommandExecutor, + tick <-chan time.Time, + onSuccessfulRefresh SuccessCallback, + onFailedRefresh FailureCallback, +) (*CA, ShutdownFunc) { signer, err := createSignerWithAPIServerSecret(kubeClient, podCommandExecutor) if err != nil { - // The initial load failed, so give up - return nil, nil, err + klog.Errorf("could not initially fetch the API server's signing key: %s", err) + signer = nil + onFailedRefresh(err) + } else { + onSuccessfulRefresh() } result := &CA{ - kubeClient: kubeClient, - podCommandExecutor: podCommandExecutor, - activeSigner: signer, - shutdown: make(chan struct{}), - done: make(chan struct{}), + kubeClient: kubeClient, + podCommandExecutor: podCommandExecutor, + shutdown: make(chan struct{}), + done: make(chan struct{}), + onSuccessfulRefresh: onSuccessfulRefresh, + onFailedRefresh: onFailedRefresh, + activeSigner: signer, } go result.refreshLoop(tick) - return result, result.shutdownRefresh, nil + return result, result.shutdownRefresh } func createSignerWithAPIServerSecret(kubeClient kubernetes.Interface, podCommandExecutor PodCommandExecutor) (signer, error) { @@ -152,11 +172,13 @@ func (c *CA) updateSigner() { newSigner, err := createSignerWithAPIServerSecret(c.kubeClient, c.podCommandExecutor) if err != nil { klog.Errorf("could not create signer with API server secret: %s", err) + c.onFailedRefresh(err) return } c.lock.Lock() c.activeSigner = newSigner c.lock.Unlock() + c.onSuccessfulRefresh() } func (c *CA) shutdownRefresh() { @@ -171,6 +193,10 @@ func (c *CA) IssuePEM(subject pkix.Name, dnsNames []string, ttl time.Duration) ( signer := c.activeSigner c.lock.RUnlock() + if signer == nil { + return nil, nil, ErrIncapableOfIssuingCertificates + } + return signer.IssuePEM(subject, dnsNames, ttl) } diff --git a/internal/certauthority/kubecertauthority/kubecertauthority_test.go b/internal/certauthority/kubecertauthority/kubecertauthority_test.go index 51276e92..815ecbe2 100644 --- a/internal/certauthority/kubecertauthority/kubecertauthority_test.go +++ b/internal/certauthority/kubecertauthority/kubecertauthority_test.go @@ -9,9 +9,9 @@ import ( "crypto/x509" "crypto/x509/pkix" "encoding/pem" - "errors" "fmt" "io/ioutil" + "sync" "testing" "time" @@ -53,6 +53,46 @@ func (s *fakePodExecutor) Exec(podNamespace string, podName string, commandAndAr return result, nil } +type callbackRecorder struct { + numberOfTimesSuccessCalled int + numberOfTimesFailureCalled int + failureErrors []error + mutex sync.Mutex +} + +func (c *callbackRecorder) OnSuccess() { + c.mutex.Lock() + defer c.mutex.Unlock() + c.numberOfTimesSuccessCalled++ +} + +func (c *callbackRecorder) OnFailure(err error) { + c.mutex.Lock() + defer c.mutex.Unlock() + c.numberOfTimesFailureCalled++ + c.failureErrors = append(c.failureErrors, err) +} + +func (c *callbackRecorder) NumberOfTimesSuccessCalled() int { + c.mutex.Lock() + defer c.mutex.Unlock() + return c.numberOfTimesSuccessCalled +} + +func (c *callbackRecorder) NumberOfTimesFailureCalled() int { + c.mutex.Lock() + defer c.mutex.Unlock() + return c.numberOfTimesFailureCalled +} + +func (c *callbackRecorder) FailureErrors() []error { + c.mutex.Lock() + defer c.mutex.Unlock() + var errs = make([]error, len(c.failureErrors)) + copy(errs, c.failureErrors) + return errs +} + func TestCA(t *testing.T) { spec.Run(t, "CA", func(t *testing.T, when spec.G, it spec.S) { var r *require.Assertions @@ -62,9 +102,29 @@ func TestCA(t *testing.T) { var kubeAPIClient *kubernetesfake.Clientset var fakeExecutor *fakePodExecutor var neverTicker <-chan time.Time - + var callbacks *callbackRecorder var logger *testutil.TranscriptLogger + var requireInitialFailureLogMessage = func(specificErrorMessage string) { + r.Len(logger.Transcript(), 1) + r.Equal( + fmt.Sprintf("could not initially fetch the API server's signing key: %s\n", specificErrorMessage), + logger.Transcript()[0].Message, + ) + r.Equal(logger.Transcript()[0].Level, "error") + } + + var requireNotCapableOfIssuingCerts = func(subject *CA) { + certPEM, keyPEM, err := subject.IssuePEM( + pkix.Name{CommonName: "Test Server"}, + []string{"example.com"}, + 10*time.Minute, + ) + r.Nil(certPEM) + r.Nil(keyPEM) + r.EqualError(err, "this cluster is not currently capable of issuing certificates") + } + it.Before(func() { r = require.New(t) @@ -104,6 +164,8 @@ func TestCA(t *testing.T) { }, } + callbacks = &callbackRecorder{} + logger = testutil.NewTranscriptLogger(t) klog.SetLogger(logger) // this is unfortunately a global logger, so can't run these tests in parallel :( }) @@ -122,9 +184,7 @@ func TestCA(t *testing.T) { it("finds the API server's signing key and uses it to issue certificates", func() { fakeTicker := make(chan time.Time) - subject, shutdownFunc, err := New(kubeAPIClient, fakeExecutor, fakeTicker) - r.NoError(err) - r.NotNil(shutdownFunc) + subject, shutdownFunc := New(kubeAPIClient, fakeExecutor, fakeTicker, callbacks.OnSuccess, callbacks.OnFailure) defer shutdownFunc() r.Equal(2, fakeExecutor.callCount) @@ -137,6 +197,9 @@ func TestCA(t *testing.T) { r.Equal("fake-pod", fakeExecutor.calledWithPodName[1]) r.Equal([]string{"cat", "/etc/kubernetes/ca/ca.key"}, fakeExecutor.calledWithCommandAndArgs[1]) + r.Equal(1, callbacks.NumberOfTimesSuccessCalled()) + r.Equal(0, callbacks.NumberOfTimesFailureCalled()) + // Validate that we can issue a certificate signed by the original API server CA. certPEM, keyPEM, err := subject.IssuePEM( pkix.Name{CommonName: "Test Server"}, @@ -152,6 +215,10 @@ func TestCA(t *testing.T) { // Tick the timer and wait for another refresh loop to complete. fakeTicker <- time.Now() + r.Equal(1, callbacks.NumberOfTimesSuccessCalled()) + r.Equal(0, callbacks.NumberOfTimesFailureCalled()) + + // Eventually it starts issuing certs using the new signing key. var secondCertPEM, secondKeyPEM string r.Eventually(func() bool { certPEM, keyPEM, err := subject.IssuePEM( @@ -191,11 +258,11 @@ func TestCA(t *testing.T) { it("logs an error message", func() { fakeTicker := make(chan time.Time) - subject, shutdownFunc, err := New(kubeAPIClient, fakeExecutor, fakeTicker) - r.NoError(err) - r.NotNil(shutdownFunc) + subject, shutdownFunc := New(kubeAPIClient, fakeExecutor, fakeTicker, callbacks.OnSuccess, callbacks.OnFailure) defer shutdownFunc() r.Equal(2, fakeExecutor.callCount) + r.Equal(1, callbacks.NumberOfTimesSuccessCalled()) + r.Equal(0, callbacks.NumberOfTimesFailureCalled()) // Tick the timer and wait for another refresh loop to complete. fakeTicker <- time.Now() @@ -205,6 +272,10 @@ func TestCA(t *testing.T) { r.Contains(logger.Transcript()[0].Message, "could not create signer with API server secret: some exec error") r.Equal(logger.Transcript()[0].Level, "error") + r.Equal(1, callbacks.NumberOfTimesSuccessCalled()) + r.Equal(1, callbacks.NumberOfTimesFailureCalled()) + r.EqualError(callbacks.FailureErrors()[0], "some exec error") + // Validate that we can still issue a certificate signed by the original API server CA. certPEM, _, err := subject.IssuePEM( pkix.Name{CommonName: "Test Server"}, @@ -216,16 +287,62 @@ func TestCA(t *testing.T) { }) }) + when("the exec commands fail the first time but subsequently returns the API server's keypair", func() { + it.Before(func() { + fakeExecutor.errorsToReturn = []error{fmt.Errorf("some exec error"), nil, nil} + fakeExecutor.resultsToReturn = []string{"", fakeCertPEM, fakeKeyPEM} + }) + + it("logs an error message and fails to issue certs until it can get the API server's keypair", func() { + fakeTicker := make(chan time.Time) + + subject, shutdownFunc := New(kubeAPIClient, fakeExecutor, fakeTicker, callbacks.OnSuccess, callbacks.OnFailure) + defer shutdownFunc() + r.Equal(1, fakeExecutor.callCount) + r.Equal(0, callbacks.NumberOfTimesSuccessCalled()) + r.Equal(1, callbacks.NumberOfTimesFailureCalled()) + r.EqualError(callbacks.FailureErrors()[0], "some exec error") + + requireInitialFailureLogMessage("some exec error") + requireNotCapableOfIssuingCerts(subject) + + // Tick the timer and wait for another refresh loop to complete. + fakeTicker <- time.Now() + + // Wait until it can start to issue certs, and then validate the issued cert. + var certPEM, keyPEM []byte + r.Eventually(func() bool { + var err error + certPEM, keyPEM, err = subject.IssuePEM( + pkix.Name{CommonName: "Test Server"}, + []string{"example.com"}, + 10*time.Minute, + ) + return err == nil + }, 5*time.Second, 10*time.Millisecond) + validCert := testutil.ValidateCertificate(t, fakeCertPEM, string(certPEM)) + validCert.RequireDNSName("example.com") + validCert.RequireLifetime(time.Now(), time.Now().Add(10*time.Minute), 2*time.Minute) + validCert.RequireMatchesPrivateKey(string(keyPEM)) + + r.Equal(1, callbacks.NumberOfTimesSuccessCalled()) + r.Equal(1, callbacks.NumberOfTimesFailureCalled()) + }) + }) + when("the exec commands succeed but return garbage", func() { it.Before(func() { fakeExecutor.resultsToReturn = []string{"not a cert", "not a private key"} }) - it("returns an error", func() { - subject, shutdownFunc, err := New(kubeAPIClient, fakeExecutor, neverTicker) - r.Nil(subject) - r.Nil(shutdownFunc) - r.EqualError(err, "could not load CA: tls: failed to find any PEM data in certificate input") + it("returns a CA who cannot issue certs", func() { + subject, shutdownFunc := New(kubeAPIClient, fakeExecutor, neverTicker, callbacks.OnSuccess, callbacks.OnFailure) + defer shutdownFunc() + requireInitialFailureLogMessage("could not load CA: tls: failed to find any PEM data in certificate input") + requireNotCapableOfIssuingCerts(subject) + r.Equal(0, callbacks.NumberOfTimesSuccessCalled()) + r.Equal(1, callbacks.NumberOfTimesFailureCalled()) + r.EqualError(callbacks.FailureErrors()[0], "could not load CA: tls: failed to find any PEM data in certificate input") }) }) @@ -234,11 +351,14 @@ func TestCA(t *testing.T) { fakeExecutor.errorsToReturn = []error{fmt.Errorf("some error"), nil} }) - it("returns an error", func() { - subject, shutdownFunc, err := New(kubeAPIClient, fakeExecutor, neverTicker) - r.Nil(subject) - r.Nil(shutdownFunc) - r.EqualError(err, "some error") + it("returns a CA who cannot issue certs", func() { + subject, shutdownFunc := New(kubeAPIClient, fakeExecutor, neverTicker, callbacks.OnSuccess, callbacks.OnFailure) + defer shutdownFunc() + requireInitialFailureLogMessage("some error") + requireNotCapableOfIssuingCerts(subject) + r.Equal(0, callbacks.NumberOfTimesSuccessCalled()) + r.Equal(1, callbacks.NumberOfTimesFailureCalled()) + r.EqualError(callbacks.FailureErrors()[0], "some error") }) }) @@ -247,11 +367,14 @@ func TestCA(t *testing.T) { fakeExecutor.errorsToReturn = []error{nil, fmt.Errorf("some error")} }) - it("returns an error", func() { - subject, shutdownFunc, err := New(kubeAPIClient, fakeExecutor, neverTicker) - r.Nil(subject) - r.Nil(shutdownFunc) - r.EqualError(err, "some error") + it("returns a CA who cannot issue certs", func() { + subject, shutdownFunc := New(kubeAPIClient, fakeExecutor, neverTicker, callbacks.OnSuccess, callbacks.OnFailure) + defer shutdownFunc() + requireInitialFailureLogMessage("some error") + requireNotCapableOfIssuingCerts(subject) + r.Equal(0, callbacks.NumberOfTimesSuccessCalled()) + r.Equal(1, callbacks.NumberOfTimesFailureCalled()) + r.EqualError(callbacks.FailureErrors()[0], "some error") }) }) }) @@ -270,9 +393,7 @@ func TestCA(t *testing.T) { }) it("finds the API server's signing key and uses it to issue certificates", func() { - _, shutdownFunc, err := New(kubeAPIClient, fakeExecutor, neverTicker) - r.NoError(err) - r.NotNil(shutdownFunc) + _, shutdownFunc := New(kubeAPIClient, fakeExecutor, neverTicker, callbacks.OnSuccess, callbacks.OnFailure) defer shutdownFunc() r.Equal(2, fakeExecutor.callCount) @@ -300,9 +421,7 @@ func TestCA(t *testing.T) { }) it("finds the API server's signing key and uses it to issue certificates", func() { - _, shutdownFunc, err := New(kubeAPIClient, fakeExecutor, neverTicker) - r.NoError(err) - r.NotNil(shutdownFunc) + _, shutdownFunc := New(kubeAPIClient, fakeExecutor, neverTicker, callbacks.OnSuccess, callbacks.OnFailure) defer shutdownFunc() r.Equal(2, fakeExecutor.callCount) @@ -319,11 +438,14 @@ func TestCA(t *testing.T) { when("the kube-controller-manager pod is not found", func() { it("returns an error", func() { - subject, shutdownFunc, err := New(kubeAPIClient, fakeExecutor, neverTicker) - r.Nil(subject) - r.Nil(shutdownFunc) - r.True(errors.Is(err, ErrNoKubeControllerManagerPod)) + subject, shutdownFunc := New(kubeAPIClient, fakeExecutor, neverTicker, callbacks.OnSuccess, callbacks.OnFailure) + defer shutdownFunc() + requireInitialFailureLogMessage("did not find kube-controller-manager pod") + requireNotCapableOfIssuingCerts(subject) + r.Equal(0, callbacks.NumberOfTimesSuccessCalled()) + r.Equal(1, callbacks.NumberOfTimesFailureCalled()) + r.EqualError(callbacks.FailureErrors()[0], "did not find kube-controller-manager pod") }) }) - }, spec.Report(report.Terminal{})) + }, spec.Sequential(), spec.Report(report.Terminal{})) } diff --git a/internal/controller/issuerconfig/create_or_update_credential_issuer_config.go b/internal/controller/issuerconfig/create_or_update_credential_issuer_config.go new file mode 100644 index 00000000..45a06d5e --- /dev/null +++ b/internal/controller/issuerconfig/create_or_update_credential_issuer_config.go @@ -0,0 +1,100 @@ +/* +Copyright 2020 VMware, Inc. +SPDX-License-Identifier: Apache-2.0 +*/ + +package issuerconfig + +import ( + "context" + "fmt" + "reflect" + + k8serrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + crdpinnipedv1alpha1 "github.com/suzerain-io/pinniped/kubernetes/1.19/api/apis/crdpinniped/v1alpha1" + pinnipedclientset "github.com/suzerain-io/pinniped/kubernetes/1.19/client-go/clientset/versioned" +) + +func CreateOrUpdateCredentialIssuerConfig( + ctx context.Context, + credentialIssuerConfigNamespace string, + pinnipedClient pinnipedclientset.Interface, + applyUpdatesToCredentialIssuerConfigFunc func(configToUpdate *crdpinnipedv1alpha1.CredentialIssuerConfig), +) error { + credentialIssuerConfigName := configName + + existingCredentialIssuerConfig, err := pinnipedClient. + CrdV1alpha1(). + CredentialIssuerConfigs(credentialIssuerConfigNamespace). + Get(ctx, credentialIssuerConfigName, metav1.GetOptions{}) + + notFound := k8serrors.IsNotFound(err) + if err != nil && !notFound { + return fmt.Errorf("could not get credentialissuerconfig: %w", err) + } + + return createOrUpdateCredentialIssuerConfig( + ctx, + existingCredentialIssuerConfig, + notFound, + credentialIssuerConfigName, + credentialIssuerConfigNamespace, + pinnipedClient, + applyUpdatesToCredentialIssuerConfigFunc) +} + +func createOrUpdateCredentialIssuerConfig( + ctx context.Context, + existingCredentialIssuerConfig *crdpinnipedv1alpha1.CredentialIssuerConfig, + notFound bool, + credentialIssuerConfigName string, + credentialIssuerConfigNamespace string, + pinnipedClient pinnipedclientset.Interface, + applyUpdatesToCredentialIssuerConfigFunc func(configToUpdate *crdpinnipedv1alpha1.CredentialIssuerConfig), +) error { + credentialIssuerConfigsClient := pinnipedClient.CrdV1alpha1().CredentialIssuerConfigs(credentialIssuerConfigNamespace) + + if notFound { + // Create it + credentialIssuerConfig := minimalValidCredentialIssuerConfig(credentialIssuerConfigName, credentialIssuerConfigNamespace) + applyUpdatesToCredentialIssuerConfigFunc(credentialIssuerConfig) + + if _, err := credentialIssuerConfigsClient.Create(ctx, credentialIssuerConfig, metav1.CreateOptions{}); err != nil { + return fmt.Errorf("could not create credentialissuerconfig: %w", err) + } + } else { + // Already exists, so check to see if we need to update it + credentialIssuerConfig := existingCredentialIssuerConfig.DeepCopy() + applyUpdatesToCredentialIssuerConfigFunc(credentialIssuerConfig) + + if reflect.DeepEqual(existingCredentialIssuerConfig.Status, credentialIssuerConfig.Status) { + // Nothing interesting would change as a result of this update, so skip it + return nil + } + + if _, err := credentialIssuerConfigsClient.Update(ctx, credentialIssuerConfig, metav1.UpdateOptions{}); err != nil { + return fmt.Errorf("could not update credentialissuerconfig: %w", err) + } + } + + return nil +} + +func minimalValidCredentialIssuerConfig( + credentialIssuerConfigName string, + credentialIssuerConfigNamespace string, +) *crdpinnipedv1alpha1.CredentialIssuerConfig { + return &crdpinnipedv1alpha1.CredentialIssuerConfig{ + TypeMeta: metav1.TypeMeta{}, + ObjectMeta: metav1.ObjectMeta{ + Name: credentialIssuerConfigName, + Namespace: credentialIssuerConfigNamespace, + }, + Status: crdpinnipedv1alpha1.CredentialIssuerConfigStatus{ + Strategies: []crdpinnipedv1alpha1.CredentialIssuerConfigStrategy{}, + KubeConfigInfo: nil, + }, + } +} diff --git a/internal/controller/issuerconfig/publisher.go b/internal/controller/issuerconfig/publisher.go index e9876943..c5c13dc7 100644 --- a/internal/controller/issuerconfig/publisher.go +++ b/internal/controller/issuerconfig/publisher.go @@ -6,13 +6,10 @@ SPDX-License-Identifier: Apache-2.0 package issuerconfig import ( - "context" "encoding/base64" "fmt" - "reflect" k8serrors "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" corev1informers "k8s.io/client-go/informers/core/v1" "k8s.io/client-go/tools/clientcmd" "k8s.io/klog/v2" @@ -135,85 +132,3 @@ func (c *publisherController) Sync(ctx controller.Context) error { updateServerAndCAFunc) return err } - -func CreateOrUpdateCredentialIssuerConfig( - ctx context.Context, - credentialIssuerConfigNamespace string, - pinnipedClient pinnipedclientset.Interface, - applyUpdatesToCredentialIssuerConfigFunc func(configToUpdate *crdpinnipedv1alpha1.CredentialIssuerConfig), -) error { - credentialIssuerConfigName := configName - - existingCredentialIssuerConfig, err := pinnipedClient. - CrdV1alpha1(). - CredentialIssuerConfigs(credentialIssuerConfigNamespace). - Get(ctx, credentialIssuerConfigName, metav1.GetOptions{}) - - notFound := k8serrors.IsNotFound(err) - if err != nil && !notFound { - return fmt.Errorf("could not get credentialissuerconfig: %w", err) - } - - return createOrUpdateCredentialIssuerConfig( - ctx, - existingCredentialIssuerConfig, - notFound, - credentialIssuerConfigName, - credentialIssuerConfigNamespace, - pinnipedClient, - applyUpdatesToCredentialIssuerConfigFunc) -} - -func createOrUpdateCredentialIssuerConfig( - ctx context.Context, - existingCredentialIssuerConfig *crdpinnipedv1alpha1.CredentialIssuerConfig, - notFound bool, - credentialIssuerConfigName string, - credentialIssuerConfigNamespace string, - pinnipedClient pinnipedclientset.Interface, - applyUpdatesToCredentialIssuerConfigFunc func(configToUpdate *crdpinnipedv1alpha1.CredentialIssuerConfig), -) error { - credentialIssuerConfigsClient := pinnipedClient.CrdV1alpha1().CredentialIssuerConfigs(credentialIssuerConfigNamespace) - - if notFound { - // Create it - credentialIssuerConfig := minimalValidCredentialIssuerConfig(credentialIssuerConfigName, credentialIssuerConfigNamespace) - applyUpdatesToCredentialIssuerConfigFunc(credentialIssuerConfig) - - if _, err := credentialIssuerConfigsClient.Create(ctx, credentialIssuerConfig, metav1.CreateOptions{}); err != nil { - return fmt.Errorf("could not create credentialissuerconfig: %w", err) - } - } else { - // Already exists, so check to see if we need to update it - credentialIssuerConfig := existingCredentialIssuerConfig.DeepCopy() - applyUpdatesToCredentialIssuerConfigFunc(credentialIssuerConfig) - - if reflect.DeepEqual(existingCredentialIssuerConfig.Status, credentialIssuerConfig.Status) { - // Nothing interesting would change as a result of this update, so skip it - return nil - } - - if _, err := credentialIssuerConfigsClient.Update(ctx, credentialIssuerConfig, metav1.UpdateOptions{}); err != nil { - return fmt.Errorf("could not update credentialissuerconfig: %w", err) - } - } - - return nil -} - -func minimalValidCredentialIssuerConfig( - credentialIssuerConfigName string, - credentialIssuerConfigNamespace string, -) *crdpinnipedv1alpha1.CredentialIssuerConfig { - return &crdpinnipedv1alpha1.CredentialIssuerConfig{ - TypeMeta: metav1.TypeMeta{}, - ObjectMeta: metav1.ObjectMeta{ - Name: credentialIssuerConfigName, - Namespace: credentialIssuerConfigNamespace, - }, - Status: crdpinnipedv1alpha1.CredentialIssuerConfigStatus{ - Strategies: []crdpinnipedv1alpha1.CredentialIssuerConfigStrategy{}, - KubeConfigInfo: nil, - }, - } -} diff --git a/internal/server/server.go b/internal/server/server.go index 3807a4c6..d96d1146 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -165,7 +165,7 @@ func (a *App) runServer(ctx context.Context) error { return server.GenericAPIServer.PrepareRun().Run(ctx.Done()) } -func getClusterCASigner(ctx context.Context, serverInstallationNamespace string) (*kubecertauthority.CA, kubecertauthority.ShutdownFunc, error) { +func getClusterCASigner(ctx context.Context, serverInstallationNamespace string) (credentialrequest.CertIssuer, kubecertauthority.ShutdownFunc, error) { // Load the Kubernetes client configuration. kubeConfig, err := restclient.InClusterConfig() if err != nil { @@ -188,57 +188,52 @@ func getClusterCASigner(ctx context.Context, serverInstallationNamespace string) ticker := time.NewTicker(5 * time.Minute) // Make a CA which uses the Kubernetes cluster API server's signing certs. - k8sClusterCA, shutdownCA, err := kubecertauthority.New( + k8sClusterCA, shutdownCA := kubecertauthority.New( kubeClient, kubecertauthority.NewPodCommandExecutor(kubeConfig, kubeClient), ticker.C, - ) - - if err != nil { - ticker.Stop() - - if updateErr := issuerconfig.CreateOrUpdateCredentialIssuerConfig( - ctx, - serverInstallationNamespace, - pinnipedClient, - func(configToUpdate *crdpinnipedv1alpha1.CredentialIssuerConfig) { - configToUpdate.Status.Strategies = []crdpinnipedv1alpha1.CredentialIssuerConfigStrategy{ - { - Type: crdpinnipedv1alpha1.KubeClusterSigningCertificateStrategyType, - Status: crdpinnipedv1alpha1.ErrorStrategyStatus, - Reason: crdpinnipedv1alpha1.CouldNotFetchKeyStrategyReason, - Message: err.Error(), - LastUpdateTime: metav1.Now(), - }, - } - }, - ); updateErr != nil { - klog.Errorf("error performing create or update on CredentialIssuerConfig to add strategy error: %s", updateErr.Error()) - } - - return nil, nil, fmt.Errorf("could not load cluster signing CA: %w", err) - } - - updateErr := issuerconfig.CreateOrUpdateCredentialIssuerConfig( - ctx, - serverInstallationNamespace, - pinnipedClient, - func(configToUpdate *crdpinnipedv1alpha1.CredentialIssuerConfig) { - configToUpdate.Status.Strategies = []crdpinnipedv1alpha1.CredentialIssuerConfigStrategy{ - { - Type: crdpinnipedv1alpha1.KubeClusterSigningCertificateStrategyType, - Status: crdpinnipedv1alpha1.SuccessStrategyStatus, - Reason: crdpinnipedv1alpha1.FetchedKeyStrategyReason, - Message: "Key was fetched successfully", - LastUpdateTime: metav1.Now(), + func() { // success callback + err = issuerconfig.CreateOrUpdateCredentialIssuerConfig( + ctx, + serverInstallationNamespace, + pinnipedClient, + func(configToUpdate *crdpinnipedv1alpha1.CredentialIssuerConfig) { + configToUpdate.Status.Strategies = []crdpinnipedv1alpha1.CredentialIssuerConfigStrategy{ + { + Type: crdpinnipedv1alpha1.KubeClusterSigningCertificateStrategyType, + Status: crdpinnipedv1alpha1.SuccessStrategyStatus, + Reason: crdpinnipedv1alpha1.FetchedKeyStrategyReason, + Message: "Key was fetched successfully", + LastUpdateTime: metav1.Now(), + }, + } }, + ) + if err != nil { + klog.Errorf("error performing create or update on CredentialIssuerConfig to add strategy success: %s", err.Error()) + } + }, + func(err error) { // error callback + if updateErr := issuerconfig.CreateOrUpdateCredentialIssuerConfig( + ctx, + serverInstallationNamespace, + pinnipedClient, + func(configToUpdate *crdpinnipedv1alpha1.CredentialIssuerConfig) { + configToUpdate.Status.Strategies = []crdpinnipedv1alpha1.CredentialIssuerConfigStrategy{ + { + Type: crdpinnipedv1alpha1.KubeClusterSigningCertificateStrategyType, + Status: crdpinnipedv1alpha1.ErrorStrategyStatus, + Reason: crdpinnipedv1alpha1.CouldNotFetchKeyStrategyReason, + Message: err.Error(), + LastUpdateTime: metav1.Now(), + }, + } + }, + ); updateErr != nil { + klog.Errorf("error performing create or update on CredentialIssuerConfig to add strategy error: %s", updateErr.Error()) } }, ) - if updateErr != nil { - //nolint:goerr113 - return nil, nil, fmt.Errorf("error performing create or update on CredentialIssuerConfig to add strategy success: %w", updateErr) - } return k8sClusterCA, func() { shutdownCA(); ticker.Stop() }, nil } diff --git a/internal/testutil/transcript_logger.go b/internal/testutil/transcript_logger.go index 41bd4d26..37408960 100644 --- a/internal/testutil/transcript_logger.go +++ b/internal/testutil/transcript_logger.go @@ -47,12 +47,12 @@ func (log *TranscriptLogger) Info(msg string, keysAndValues ...interface{}) { }) } -func (log *TranscriptLogger) Error(err error, msg string, keysAndValues ...interface{}) { +func (log *TranscriptLogger) Error(_ error, msg string, _ ...interface{}) { log.lock.Lock() defer log.lock.Unlock() log.transcript = append(log.transcript, TranscriptLogMessage{ Level: "error", - Message: fmt.Sprintf("%s: %v -- %v", msg, err, keysAndValues), + Message: msg, }) } diff --git a/test/go.mod b/test/go.mod index 83ceefef..aaa14050 100644 --- a/test/go.mod +++ b/test/go.mod @@ -4,7 +4,6 @@ go 1.14 require ( github.com/davecgh/go-spew v1.1.1 - github.com/ghodss/yaml v1.0.0 github.com/stretchr/testify v1.6.1 github.com/suzerain-io/pinniped v0.0.0-20200819182107-1b9a70d089f4 github.com/suzerain-io/pinniped/kubernetes/1.19/api v0.0.0-00010101000000-000000000000 @@ -14,6 +13,7 @@ require ( k8s.io/apimachinery v0.19.0-rc.0 k8s.io/client-go v0.19.0-rc.0 k8s.io/kube-aggregator v0.19.0-rc.0 + sigs.k8s.io/yaml v1.2.0 ) replace ( diff --git a/test/integration/api_discovery_test.go b/test/integration/api_discovery_test.go index dc102bb8..f13e35ae 100644 --- a/test/integration/api_discovery_test.go +++ b/test/integration/api_discovery_test.go @@ -16,7 +16,6 @@ import ( func TestGetAPIResourceList(t *testing.T) { library.SkipUnlessIntegration(t) - library.SkipUnlessClusterHasCapability(t, library.ClusterSigningKeyIsAvailable) client := library.NewPinnipedClientset(t) diff --git a/test/integration/api_serving_certs_test.go b/test/integration/api_serving_certs_test.go index 79c96c98..3e3d4717 100644 --- a/test/integration/api_serving_certs_test.go +++ b/test/integration/api_serving_certs_test.go @@ -22,7 +22,6 @@ import ( func TestAPIServingCertificateAutoCreationAndRotation(t *testing.T) { library.SkipUnlessIntegration(t) - library.SkipUnlessClusterHasCapability(t, library.ClusterSigningKeyIsAvailable) tests := []struct { name string diff --git a/test/integration/app_availability_test.go b/test/integration/app_availability_test.go index a0f8430d..a20438ff 100644 --- a/test/integration/app_availability_test.go +++ b/test/integration/app_availability_test.go @@ -20,7 +20,6 @@ import ( func TestGetDeployment(t *testing.T) { library.SkipUnlessIntegration(t) - library.SkipUnlessClusterHasCapability(t, library.ClusterSigningKeyIsAvailable) namespaceName := library.GetEnv(t, "PINNIPED_NAMESPACE") deploymentName := library.GetEnv(t, "PINNIPED_APP_NAME") diff --git a/test/integration/credentialissuerconfig_test.go b/test/integration/credentialissuerconfig_test.go index 8e028d54..6f41d8dd 100644 --- a/test/integration/credentialissuerconfig_test.go +++ b/test/integration/credentialissuerconfig_test.go @@ -74,24 +74,25 @@ func TestCredentialIssuerConfig(t *testing.T) { // Mutate the existing object. Don't delete it because that would mess up its `Status.Strategies` array, // since the reconciling controller is not currently responsible for that field. - existingConfig.Status.KubeConfigInfo.Server = "https://junk" + updatedServerValue := "https://junk" + existingConfig.Status.KubeConfigInfo.Server = updatedServerValue updatedConfig, err := client. CrdV1alpha1(). CredentialIssuerConfigs(namespaceName). Update(ctx, existingConfig, metav1.UpdateOptions{}) require.NoError(t, err) - require.Equal(t, "https://junk", updatedConfig.Status.KubeConfigInfo.Server) + require.Equal(t, updatedServerValue, updatedConfig.Status.KubeConfigInfo.Server) - // Expect that the object's mutated field is set back to what matches its source of truth. + // Expect that the object's mutated field is set back to what matches its source of truth by the controller. var actualCredentialIssuerConfig *crdpinnipedv1alpha1.CredentialIssuerConfig - var getConfig = func() bool { + var configChangesServerField = func() bool { actualCredentialIssuerConfig, err = client. CrdV1alpha1(). CredentialIssuerConfigs(namespaceName). Get(ctx, "pinniped-config", metav1.GetOptions{}) - return err == nil + return err == nil && actualCredentialIssuerConfig.Status.KubeConfigInfo.Server != updatedServerValue } - assert.Eventually(t, getConfig, 5*time.Second, 100*time.Millisecond) + assert.Eventually(t, configChangesServerField, 10*time.Second, 100*time.Millisecond) require.NoError(t, err) // prints out the error and stops the test in case of failure actualStatusKubeConfigInfo := actualCredentialIssuerConfig.Status.KubeConfigInfo require.Equal(t, expectedStatusKubeConfigInfo(config), actualStatusKubeConfigInfo) diff --git a/test/integration/credentialrequest_test.go b/test/integration/credentialrequest_test.go index 0db47da8..1b0e20f0 100644 --- a/test/integration/credentialrequest_test.go +++ b/test/integration/credentialrequest_test.go @@ -25,51 +25,11 @@ import ( "github.com/suzerain-io/pinniped/test/library" ) -func makeRequest(t *testing.T, spec v1alpha1.CredentialRequestSpec) (*v1alpha1.CredentialRequest, error) { - t.Helper() - - client := library.NewAnonymousPinnipedClientset(t) - - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - defer cancel() - - return client.PinnipedV1alpha1().CredentialRequests().Create(ctx, &v1alpha1.CredentialRequest{ - TypeMeta: metav1.TypeMeta{}, - ObjectMeta: metav1.ObjectMeta{}, - Spec: spec, - }, metav1.CreateOptions{}) -} - -func addTestClusterRoleBinding(ctx context.Context, t *testing.T, adminClient kubernetes.Interface, binding *rbacv1.ClusterRoleBinding) { - _, err := adminClient.RbacV1().ClusterRoleBindings().Get(ctx, binding.Name, metav1.GetOptions{}) - if err != nil { - // "404 not found" errors are acceptable, but others would be unexpected - statusError, isStatus := err.(*errors.StatusError) - require.True(t, isStatus) - require.Equal(t, http.StatusNotFound, int(statusError.Status().Code)) - - _, err = adminClient.RbacV1().ClusterRoleBindings().Create(ctx, binding, metav1.CreateOptions{}) - require.NoError(t, err) - } - - t.Cleanup(func() { - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - defer cancel() - err = adminClient.RbacV1().ClusterRoleBindings().Delete(ctx, binding.Name, metav1.DeleteOptions{}) - require.NoError(t, err, "Test failed to clean up after itself") - }) -} - func TestSuccessfulCredentialRequest(t *testing.T) { library.SkipUnlessIntegration(t) library.SkipUnlessClusterHasCapability(t, library.ClusterSigningKeyIsAvailable) - tmcClusterToken := library.GetEnv(t, "PINNIPED_TMC_CLUSTER_TOKEN") - - response, err := makeRequest(t, v1alpha1.CredentialRequestSpec{ - Type: v1alpha1.TokenCredentialType, - Token: &v1alpha1.CredentialRequestTokenCredential{Value: tmcClusterToken}, - }) + response, err := makeRequest(t, validCredentialRequestSpecWithRealToken(t)) require.NoError(t, err) // Note: If this assertion fails then your TMC token might have expired. Get a fresh one and try again. @@ -194,6 +154,63 @@ func TestCredentialRequest_ShouldFailWhenRequestDoesNotIncludeToken(t *testing.T require.Nil(t, response.Status.Credential) } +func TestCredentialRequest_OtherwiseValidRequestWithRealTokenShouldFailWhenTheClusterIsNotCapable(t *testing.T) { + library.SkipUnlessIntegration(t) + library.SkipWhenClusterHasCapability(t, library.ClusterSigningKeyIsAvailable) + + response, err := makeRequest(t, validCredentialRequestSpecWithRealToken(t)) + + require.NoError(t, err) + + require.Empty(t, response.Spec) + require.Nil(t, response.Status.Credential) + require.Equal(t, stringPtr("authentication failed"), response.Status.Message) +} + +func makeRequest(t *testing.T, spec v1alpha1.CredentialRequestSpec) (*v1alpha1.CredentialRequest, error) { + t.Helper() + + client := library.NewAnonymousPinnipedClientset(t) + + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + + return client.PinnipedV1alpha1().CredentialRequests().Create(ctx, &v1alpha1.CredentialRequest{ + TypeMeta: metav1.TypeMeta{}, + ObjectMeta: metav1.ObjectMeta{}, + Spec: spec, + }, metav1.CreateOptions{}) +} + +func validCredentialRequestSpecWithRealToken(t *testing.T) v1alpha1.CredentialRequestSpec { + tmcClusterToken := library.GetEnv(t, "PINNIPED_TMC_CLUSTER_TOKEN") + + return v1alpha1.CredentialRequestSpec{ + Type: v1alpha1.TokenCredentialType, + Token: &v1alpha1.CredentialRequestTokenCredential{Value: tmcClusterToken}, + } +} + +func addTestClusterRoleBinding(ctx context.Context, t *testing.T, adminClient kubernetes.Interface, binding *rbacv1.ClusterRoleBinding) { + _, err := adminClient.RbacV1().ClusterRoleBindings().Get(ctx, binding.Name, metav1.GetOptions{}) + if err != nil { + // "404 not found" errors are acceptable, but others would be unexpected + statusError, isStatus := err.(*errors.StatusError) + require.True(t, isStatus) + require.Equal(t, http.StatusNotFound, int(statusError.Status().Code)) + + _, err = adminClient.RbacV1().ClusterRoleBindings().Create(ctx, binding, metav1.CreateOptions{}) + require.NoError(t, err) + } + + t.Cleanup(func() { + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + err = adminClient.RbacV1().ClusterRoleBindings().Delete(ctx, binding.Name, metav1.DeleteOptions{}) + require.NoError(t, err, "Test failed to clean up after itself") + }) +} + func stringPtr(s string) *string { return &s } diff --git a/test/library/cluster_capabilities.go b/test/library/cluster_capabilities.go index b606423f..22350fc3 100644 --- a/test/library/cluster_capabilities.go +++ b/test/library/cluster_capabilities.go @@ -10,8 +10,8 @@ import ( "os" "testing" - "github.com/ghodss/yaml" "github.com/stretchr/testify/require" + "sigs.k8s.io/yaml" ) type TestClusterCapability string @@ -56,3 +56,10 @@ func SkipUnlessClusterHasCapability(t *testing.T, capability TestClusterCapabili t.Skipf(`skipping integration test because cluster lacks the "%s" capability`, capability) } } + +func SkipWhenClusterHasCapability(t *testing.T, capability TestClusterCapability) { + t.Helper() + if ClusterHasCapability(t, capability) { + t.Skipf(`skipping integration test because cluster has the "%s" capability`, capability) + } +} From 90fe733f9447bb5feca48cf87894cf373f1fc8fd Mon Sep 17 00:00:00 2001 From: Ryan Richard Date: Wed, 26 Aug 2020 08:49:44 -0700 Subject: [PATCH 6/7] Empty commit to trigger PR CI pipeline From 2629a9c42fb6212d1fe80325fc03b5418c5cfdd4 Mon Sep 17 00:00:00 2001 From: Ryan Richard Date: Wed, 26 Aug 2020 09:17:08 -0700 Subject: [PATCH 7/7] Empty commit to trigger PR CI pipeline