Rename project

This commit is contained in:
Ryan Richard
2020-08-20 10:54:15 -07:00
parent 43888e9e0a
commit 3929fa672e
121 changed files with 1641 additions and 1652 deletions
@@ -19,8 +19,8 @@ import (
"k8s.io/klog/v2"
"github.com/suzerain-io/controller-go"
"github.com/suzerain-io/placeholder-name/internal/constable"
placeholdernamecontroller "github.com/suzerain-io/placeholder-name/internal/controller"
"github.com/suzerain-io/pinniped/internal/constable"
pinnipedcontroller "github.com/suzerain-io/pinniped/internal/controller"
)
type certsExpirerController struct {
@@ -44,7 +44,7 @@ func NewCertsExpirerController(
namespace string,
k8sClient kubernetes.Interface,
secretInformer corev1informers.SecretInformer,
withInformer placeholdernamecontroller.WithInformerOptionFunc,
withInformer pinnipedcontroller.WithInformerOptionFunc,
ageThreshold float32,
) controller.Controller {
return controller.New(
@@ -59,7 +59,7 @@ func NewCertsExpirerController(
},
withInformer(
secretInformer,
placeholdernamecontroller.NameAndNamespaceExactMatchFilterFactory(certsSecretName, namespace),
pinnipedcontroller.NameAndNamespaceExactMatchFilterFactory(certsSecretName, namespace),
controller.InformerOption{},
),
)
@@ -24,7 +24,7 @@ import (
kubetesting "k8s.io/client-go/testing"
"github.com/suzerain-io/controller-go"
"github.com/suzerain-io/placeholder-name/internal/testutil"
"github.com/suzerain-io/pinniped/internal/testutil"
)
func TestExpirerControllerFilters(t *testing.T) {
@@ -19,8 +19,8 @@ import (
aggregatorclient "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset"
"github.com/suzerain-io/controller-go"
"github.com/suzerain-io/placeholder-name/internal/certauthority"
placeholdernamecontroller "github.com/suzerain-io/placeholder-name/internal/controller"
"github.com/suzerain-io/pinniped/internal/certauthority"
pinnipedcontroller "github.com/suzerain-io/pinniped/internal/controller"
)
const (
@@ -43,8 +43,8 @@ func NewCertsManagerController(
k8sClient kubernetes.Interface,
aggregatorClient aggregatorclient.Interface,
secretInformer corev1informers.SecretInformer,
withInformer placeholdernamecontroller.WithInformerOptionFunc,
withInitialEvent placeholdernamecontroller.WithInitialEventOptionFunc,
withInformer pinnipedcontroller.WithInformerOptionFunc,
withInitialEvent pinnipedcontroller.WithInitialEventOptionFunc,
) controller.Controller {
return controller.New(
controller.Config{
@@ -58,7 +58,7 @@ func NewCertsManagerController(
},
withInformer(
secretInformer,
placeholdernamecontroller.NameAndNamespaceExactMatchFilterFactory(certsSecretName, namespace),
pinnipedcontroller.NameAndNamespaceExactMatchFilterFactory(certsSecretName, namespace),
controller.InformerOption{},
),
// Be sure to run once even if the Secret that the informer is watching doesn't exist.
@@ -82,13 +82,13 @@ func (c *certsManagerController) Sync(ctx controller.Context) error {
}
// Create a CA.
aggregatedAPIServerCA, err := certauthority.New(pkix.Name{CommonName: "Placeholder CA"})
aggregatedAPIServerCA, err := certauthority.New(pkix.Name{CommonName: "Pinniped CA"})
if err != nil {
return fmt.Errorf("could not initialize CA: %w", err)
}
// This string must match the name of the Service declared in the deployment yaml.
const serviceName = "placeholder-name-api"
const serviceName = "pinniped-api"
// Using the CA from above, create a TLS server cert for the aggregated API server to use.
serviceEndpoint := serviceName + "." + c.namespace + ".svc"
@@ -25,8 +25,8 @@ import (
aggregatorfake "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/fake"
"github.com/suzerain-io/controller-go"
"github.com/suzerain-io/placeholder-name/internal/testutil"
placeholderv1alpha1 "github.com/suzerain-io/placeholder-name/kubernetes/1.19/api/apis/placeholder/v1alpha1"
"github.com/suzerain-io/pinniped/internal/testutil"
pinnipedv1alpha1 "github.com/suzerain-io/pinniped/kubernetes/1.19/api/apis/pinniped/v1alpha1"
)
func TestManagerControllerOptions(t *testing.T) {
@@ -187,7 +187,7 @@ func TestManagerControllerSync(t *testing.T) {
it.Before(func() {
apiService := &apiregistrationv1.APIService{
ObjectMeta: metav1.ObjectMeta{
Name: placeholderv1alpha1.SchemeGroupVersion.Version + "." + placeholderv1alpha1.GroupName,
Name: pinnipedv1alpha1.SchemeGroupVersion.Version + "." + pinnipedv1alpha1.GroupName,
},
Spec: apiregistrationv1.APIServiceSpec{
CABundle: nil,
@@ -220,14 +220,14 @@ func TestManagerControllerSync(t *testing.T) {
// Validate the created cert using the CA, and also validate the cert's hostname
validCert := testutil.ValidateCertificate(t, actualCACert, actualCertChain)
validCert.RequireDNSName("placeholder-name-api." + installedInNamespace + ".svc")
validCert.RequireDNSName("pinniped-api." + installedInNamespace + ".svc")
validCert.RequireLifetime(time.Now(), time.Now().Add(24*365*time.Hour), 2*time.Minute)
validCert.RequireMatchesPrivateKey(actualPrivateKey)
// Make sure we updated the APIService caBundle and left it otherwise unchanged
r.Len(aggregatorAPIClient.Actions(), 2)
r.Equal("get", aggregatorAPIClient.Actions()[0].GetVerb())
expectedAPIServiceName := placeholderv1alpha1.SchemeGroupVersion.Version + "." + placeholderv1alpha1.GroupName
expectedAPIServiceName := pinnipedv1alpha1.SchemeGroupVersion.Version + "." + pinnipedv1alpha1.GroupName
expectedUpdateAction := coretesting.NewUpdateAction(
schema.GroupVersionResource{
Group: apiregistrationv1.GroupName,
@@ -13,8 +13,8 @@ import (
"k8s.io/klog/v2"
"github.com/suzerain-io/controller-go"
placeholdernamecontroller "github.com/suzerain-io/placeholder-name/internal/controller"
"github.com/suzerain-io/placeholder-name/internal/provider"
pinnipedcontroller "github.com/suzerain-io/pinniped/internal/controller"
"github.com/suzerain-io/pinniped/internal/provider"
)
type certsObserverController struct {
@@ -27,7 +27,7 @@ func NewCertsObserverController(
namespace string,
dynamicCertProvider provider.DynamicTLSServingCertProvider,
secretInformer corev1informers.SecretInformer,
withInformer placeholdernamecontroller.WithInformerOptionFunc,
withInformer pinnipedcontroller.WithInformerOptionFunc,
) controller.Controller {
return controller.New(
controller.Config{
@@ -40,7 +40,7 @@ func NewCertsObserverController(
},
withInformer(
secretInformer,
placeholdernamecontroller.NameAndNamespaceExactMatchFilterFactory(certsSecretName, namespace),
pinnipedcontroller.NameAndNamespaceExactMatchFilterFactory(certsSecretName, namespace),
controller.InformerOption{},
),
)
@@ -19,8 +19,8 @@ import (
kubernetesfake "k8s.io/client-go/kubernetes/fake"
"github.com/suzerain-io/controller-go"
"github.com/suzerain-io/placeholder-name/internal/provider"
"github.com/suzerain-io/placeholder-name/internal/testutil"
"github.com/suzerain-io/pinniped/internal/provider"
"github.com/suzerain-io/pinniped/internal/testutil"
)
func TestObserverControllerInformerFilters(t *testing.T) {
@@ -13,13 +13,13 @@ import (
"k8s.io/client-go/util/retry"
aggregatorclient "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset"
placeholderv1alpha1 "github.com/suzerain-io/placeholder-name/kubernetes/1.19/api/apis/placeholder/v1alpha1"
pinnipedv1alpha1 "github.com/suzerain-io/pinniped/kubernetes/1.19/api/apis/pinniped/v1alpha1"
)
// UpdateAPIService updates the APIService's CA bundle.
func UpdateAPIService(ctx context.Context, aggregatorClient aggregatorclient.Interface, aggregatedAPIServerCA []byte) error {
apiServices := aggregatorClient.ApiregistrationV1().APIServices()
apiServiceName := placeholderv1alpha1.SchemeGroupVersion.Version + "." + placeholderv1alpha1.GroupName
apiServiceName := pinnipedv1alpha1.SchemeGroupVersion.Version + "." + pinnipedv1alpha1.GroupName
if err := retry.RetryOnConflict(retry.DefaultRetry, func() error {
// Retrieve the latest version of the Service before attempting update.
@@ -21,7 +21,7 @@ import (
)
func TestUpdateAPIService(t *testing.T) {
const apiServiceName = "v1alpha1.placeholder.suzerain-io.github.io"
const apiServiceName = "v1alpha1.pinniped.dev"
tests := []struct {
name string
+7
View File
@@ -0,0 +1,7 @@
/*
Copyright 2020 VMware, Inc.
SPDX-License-Identifier: Apache-2.0
*/
// Package discovery contains controller(s) for reconciling PinnipedDiscoveryInfo's.
package discovery
+174
View File
@@ -0,0 +1,174 @@
/*
Copyright 2020 VMware, Inc.
SPDX-License-Identifier: Apache-2.0
*/
package discovery
import (
"context"
"encoding/base64"
"fmt"
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"
"github.com/suzerain-io/controller-go"
pinnipedcontroller "github.com/suzerain-io/pinniped/internal/controller"
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"
crdpinnipedv1alpha1informers "github.com/suzerain-io/pinniped/kubernetes/1.19/client-go/informers/externalversions/crdpinniped/v1alpha1"
)
const (
ClusterInfoNamespace = "kube-public"
clusterInfoName = "cluster-info"
clusterInfoConfigMapKey = "kubeconfig"
configName = "pinniped-config"
)
type publisherController struct {
namespace string
serverOverride *string
pinnipedClient pinnipedclientset.Interface
configMapInformer corev1informers.ConfigMapInformer
pinnipedDiscoveryInfoInformer crdpinnipedv1alpha1informers.PinnipedDiscoveryInfoInformer
}
func NewPublisherController(
namespace string,
serverOverride *string,
pinnipedClient pinnipedclientset.Interface,
configMapInformer corev1informers.ConfigMapInformer,
pinnipedDiscoveryInfoInformer crdpinnipedv1alpha1informers.PinnipedDiscoveryInfoInformer,
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,
},
},
withInformer(
configMapInformer,
pinnipedcontroller.NameAndNamespaceExactMatchFilterFactory(clusterInfoName, ClusterInfoNamespace),
controller.InformerOption{},
),
withInformer(
pinnipedDiscoveryInfoInformer,
pinnipedcontroller.NameAndNamespaceExactMatchFilterFactory(configName, namespace),
controller.InformerOption{},
),
)
}
func (c *publisherController) Sync(ctx controller.Context) error {
configMap, err := c.configMapInformer.
Lister().
ConfigMaps(ClusterInfoNamespace).
Get(clusterInfoName)
notFound := k8serrors.IsNotFound(err)
if err != nil && !notFound {
return fmt.Errorf("failed to get %s configmap: %w", clusterInfoName, err)
}
if notFound {
klog.InfoS(
"could not find config map",
"configmap",
klog.KRef(ClusterInfoNamespace, clusterInfoName),
)
return nil
}
kubeConfig, kubeConfigPresent := configMap.Data[clusterInfoConfigMapKey]
if !kubeConfigPresent {
klog.InfoS("could not find kubeconfig configmap key")
return nil
}
config, _ := clientcmd.Load([]byte(kubeConfig))
var certificateAuthorityData, server string
for _, v := range config.Clusters {
certificateAuthorityData = base64.StdEncoding.EncodeToString(v.CertificateAuthorityData)
server = v.Server
break
}
if c.serverOverride != nil {
server = *c.serverOverride
}
discoveryInfo := crdpinnipedv1alpha1.PinnipedDiscoveryInfo{
TypeMeta: metav1.TypeMeta{},
ObjectMeta: metav1.ObjectMeta{
Name: configName,
Namespace: c.namespace,
},
Spec: crdpinnipedv1alpha1.PinnipedDiscoveryInfoSpec{
Server: server,
CertificateAuthorityData: certificateAuthorityData,
},
}
if err := c.createOrUpdatePinnipedDiscoveryInfo(ctx.Context, &discoveryInfo); err != nil {
return err
}
return nil
}
func (c *publisherController) createOrUpdatePinnipedDiscoveryInfo(
ctx context.Context,
discoveryInfo *crdpinnipedv1alpha1.PinnipedDiscoveryInfo,
) error {
existingDiscoveryInfo, err := c.pinnipedDiscoveryInfoInformer.
Lister().
PinnipedDiscoveryInfos(c.namespace).
Get(discoveryInfo.Name)
notFound := k8serrors.IsNotFound(err)
if err != nil && !notFound {
return fmt.Errorf("could not get pinnipeddiscoveryinfo: %w", err)
}
pinnipedDiscoveryInfos := c.pinnipedClient.
CrdV1alpha1().
PinnipedDiscoveryInfos(c.namespace)
if notFound {
if _, err := pinnipedDiscoveryInfos.Create(
ctx,
discoveryInfo,
metav1.CreateOptions{},
); err != nil {
return fmt.Errorf("could not create pinnipeddiscoveryinfo: %w", err)
}
} else if !equal(existingDiscoveryInfo, discoveryInfo) {
// Update just the fields we care about.
existingDiscoveryInfo.Spec.Server = discoveryInfo.Spec.Server
existingDiscoveryInfo.Spec.CertificateAuthorityData = discoveryInfo.Spec.CertificateAuthorityData
if _, err := pinnipedDiscoveryInfos.Update(
ctx,
existingDiscoveryInfo,
metav1.UpdateOptions{},
); err != nil {
return fmt.Errorf("could not update pinnipeddiscoveryinfo: %w", err)
}
}
return nil
}
func equal(a, b *crdpinnipedv1alpha1.PinnipedDiscoveryInfo) bool {
return a.Spec.Server == b.Spec.Server &&
a.Spec.CertificateAuthorityData == b.Spec.CertificateAuthorityData
}
@@ -3,7 +3,7 @@ Copyright 2020 VMware, Inc.
SPDX-License-Identifier: Apache-2.0
*/
package logindiscovery
package discovery
import (
"context"
@@ -24,10 +24,10 @@ import (
coretesting "k8s.io/client-go/testing"
"github.com/suzerain-io/controller-go"
"github.com/suzerain-io/placeholder-name/internal/testutil"
crdsplaceholderv1alpha1 "github.com/suzerain-io/placeholder-name/kubernetes/1.19/api/apis/crdsplaceholder/v1alpha1"
placeholderfake "github.com/suzerain-io/placeholder-name/kubernetes/1.19/client-go/clientset/versioned/fake"
placeholderinformers "github.com/suzerain-io/placeholder-name/kubernetes/1.19/client-go/informers/externalversions"
"github.com/suzerain-io/pinniped/internal/testutil"
crdpinnipedv1alpha1 "github.com/suzerain-io/pinniped/kubernetes/1.19/api/apis/crdpinniped/v1alpha1"
pinnipedfake "github.com/suzerain-io/pinniped/kubernetes/1.19/client-go/clientset/versioned/fake"
pinnipedinformers "github.com/suzerain-io/pinniped/kubernetes/1.19/client-go/informers/externalversions"
)
func TestInformerFilters(t *testing.T) {
@@ -37,23 +37,23 @@ func TestInformerFilters(t *testing.T) {
var r *require.Assertions
var observableWithInformerOption *testutil.ObservableWithInformerOption
var configMapInformerFilter controller.Filter
var loginDiscoveryConfigInformerFilter controller.Filter
var pinnipedDiscoveryInfoInformerFilter controller.Filter
it.Before(func() {
r = require.New(t)
observableWithInformerOption = testutil.NewObservableWithInformerOption()
configMapInformer := kubeinformers.NewSharedInformerFactory(nil, 0).Core().V1().ConfigMaps()
loginDiscoveryConfigInformer := placeholderinformers.NewSharedInformerFactory(nil, 0).Crds().V1alpha1().LoginDiscoveryConfigs()
pinnipedDiscoveryInfoInformer := pinnipedinformers.NewSharedInformerFactory(nil, 0).Crd().V1alpha1().PinnipedDiscoveryInfos()
_ = NewPublisherController(
installedInNamespace,
nil,
nil,
configMapInformer,
loginDiscoveryConfigInformer,
pinnipedDiscoveryInfoInformer,
observableWithInformerOption.WithInformer, // make it possible to observe the behavior of the Filters
)
configMapInformerFilter = observableWithInformerOption.GetFilterForInformer(configMapInformer)
loginDiscoveryConfigInformerFilter = observableWithInformerOption.GetFilterForInformer(loginDiscoveryConfigInformer)
pinnipedDiscoveryInfoInformerFilter = observableWithInformerOption.GetFilterForInformer(pinnipedDiscoveryInfoInformer)
})
when("watching ConfigMap objects", func() {
@@ -104,27 +104,27 @@ func TestInformerFilters(t *testing.T) {
})
})
when("watching LoginDiscoveryConfig objects", func() {
when("watching PinnipedDiscoveryInfo objects", func() {
var subject controller.Filter
var target, wrongNamespace, wrongName, unrelated *crdsplaceholderv1alpha1.LoginDiscoveryConfig
var target, wrongNamespace, wrongName, unrelated *crdpinnipedv1alpha1.PinnipedDiscoveryInfo
it.Before(func() {
subject = loginDiscoveryConfigInformerFilter
target = &crdsplaceholderv1alpha1.LoginDiscoveryConfig{
ObjectMeta: metav1.ObjectMeta{Name: "placeholder-name-config", Namespace: installedInNamespace},
subject = pinnipedDiscoveryInfoInformerFilter
target = &crdpinnipedv1alpha1.PinnipedDiscoveryInfo{
ObjectMeta: metav1.ObjectMeta{Name: "pinniped-config", Namespace: installedInNamespace},
}
wrongNamespace = &crdsplaceholderv1alpha1.LoginDiscoveryConfig{
ObjectMeta: metav1.ObjectMeta{Name: "placeholder-name-config", Namespace: "wrong-namespace"},
wrongNamespace = &crdpinnipedv1alpha1.PinnipedDiscoveryInfo{
ObjectMeta: metav1.ObjectMeta{Name: "pinniped-config", Namespace: "wrong-namespace"},
}
wrongName = &crdsplaceholderv1alpha1.LoginDiscoveryConfig{
wrongName = &crdpinnipedv1alpha1.PinnipedDiscoveryInfo{
ObjectMeta: metav1.ObjectMeta{Name: "wrong-name", Namespace: installedInNamespace},
}
unrelated = &crdsplaceholderv1alpha1.LoginDiscoveryConfig{
unrelated = &crdpinnipedv1alpha1.PinnipedDiscoveryInfo{
ObjectMeta: metav1.ObjectMeta{Name: "wrong-name", Namespace: "wrong-namespace"},
}
})
when("the target LoginDiscoveryConfig changes", func() {
when("the target PinnipedDiscoveryInfo 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 LoginDiscoveryConfig from another namespace changes", func() {
when("a PinnipedDiscoveryInfo 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 LoginDiscoveryConfig with a different name changes", func() {
when("a PinnipedDiscoveryInfo 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 LoginDiscoveryConfig with a different name and a different namespace changes", func() {
when("a PinnipedDiscoveryInfo 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))
@@ -171,31 +171,31 @@ func TestSync(t *testing.T) {
var subject controller.Controller
var serverOverride *string
var kubeInformerClient *kubernetesfake.Clientset
var placeholderInformerClient *placeholderfake.Clientset
var pinnipedInformerClient *pinnipedfake.Clientset
var kubeInformers kubeinformers.SharedInformerFactory
var placeholderInformers placeholderinformers.SharedInformerFactory
var placeholderAPIClient *placeholderfake.Clientset
var pinnipedInformers pinnipedinformers.SharedInformerFactory
var pinnipedAPIClient *pinnipedfake.Clientset
var timeoutContext context.Context
var timeoutContextCancel context.CancelFunc
var syncContext *controller.Context
var expectedLoginDiscoveryConfig = func(expectedNamespace, expectedServerURL, expectedCAData string) (schema.GroupVersionResource, *crdsplaceholderv1alpha1.LoginDiscoveryConfig) {
expectedLoginDiscoveryConfigGVR := schema.GroupVersionResource{
Group: crdsplaceholderv1alpha1.GroupName,
var expectedPinnipedDiscoveryInfo = func(expectedNamespace, expectedServerURL, expectedCAData string) (schema.GroupVersionResource, *crdpinnipedv1alpha1.PinnipedDiscoveryInfo) {
expectedPinnipedDiscoveryInfoGVR := schema.GroupVersionResource{
Group: crdpinnipedv1alpha1.GroupName,
Version: "v1alpha1",
Resource: "logindiscoveryconfigs",
Resource: "pinnipeddiscoveryinfos",
}
expectedLoginDiscoveryConfig := &crdsplaceholderv1alpha1.LoginDiscoveryConfig{
expectedPinnipedDiscoveryInfo := &crdpinnipedv1alpha1.PinnipedDiscoveryInfo{
ObjectMeta: metav1.ObjectMeta{
Name: "placeholder-name-config",
Name: "pinniped-config",
Namespace: expectedNamespace,
},
Spec: crdsplaceholderv1alpha1.LoginDiscoveryConfigSpec{
Spec: crdpinnipedv1alpha1.PinnipedDiscoveryInfoSpec{
Server: expectedServerURL,
CertificateAuthorityData: expectedCAData,
},
}
return expectedLoginDiscoveryConfigGVR, expectedLoginDiscoveryConfig
return expectedPinnipedDiscoveryInfoGVR, expectedPinnipedDiscoveryInfo
}
// Defer starting the informers until the last possible moment so that the
@@ -205,9 +205,9 @@ func TestSync(t *testing.T) {
subject = NewPublisherController(
installedInNamespace,
serverOverride,
placeholderAPIClient,
pinnipedAPIClient,
kubeInformers.Core().V1().ConfigMaps(),
placeholderInformers.Crds().V1alpha1().LoginDiscoveryConfigs(),
pinnipedInformers.Crd().V1alpha1().PinnipedDiscoveryInfos(),
controller.WithInformer,
)
@@ -223,7 +223,7 @@ func TestSync(t *testing.T) {
// Must start informers before calling TestRunSynchronously()
kubeInformers.Start(timeoutContext.Done())
placeholderInformers.Start(timeoutContext.Done())
pinnipedInformers.Start(timeoutContext.Done())
controller.TestRunSynchronously(t, subject)
}
@@ -234,9 +234,9 @@ func TestSync(t *testing.T) {
kubeInformerClient = kubernetesfake.NewSimpleClientset()
kubeInformers = kubeinformers.NewSharedInformerFactory(kubeInformerClient, 0)
placeholderAPIClient = placeholderfake.NewSimpleClientset()
placeholderInformerClient = placeholderfake.NewSimpleClientset()
placeholderInformers = placeholderinformers.NewSharedInformerFactory(placeholderInformerClient, 0)
pinnipedAPIClient = pinnipedfake.NewSimpleClientset()
pinnipedInformerClient = pinnipedfake.NewSimpleClientset()
pinnipedInformers = pinnipedinformers.NewSharedInformerFactory(pinnipedInformerClient, 0)
})
it.After(func() {
@@ -268,13 +268,13 @@ func TestSync(t *testing.T) {
r.NoError(err)
})
when("the LoginDiscoveryConfig does not already exist", func() {
it("creates a LoginDiscoveryConfig", func() {
when("the PinnipedDiscoveryInfo does not already exist", func() {
it("creates a PinnipedDiscoveryInfo", func() {
startInformersAndController()
err := controller.TestSync(t, subject, *syncContext)
r.NoError(err)
expectedLoginDiscoveryConfigGVR, expectedLoginDiscoveryConfig := expectedLoginDiscoveryConfig(
expectedPinnipedDiscoveryInfoGVR, expectedPinnipedDiscoveryInfo := expectedPinnipedDiscoveryInfo(
installedInNamespace,
kubeServerURL,
caData,
@@ -283,20 +283,20 @@ func TestSync(t *testing.T) {
r.Equal(
[]coretesting.Action{
coretesting.NewCreateAction(
expectedLoginDiscoveryConfigGVR,
expectedPinnipedDiscoveryInfoGVR,
installedInNamespace,
expectedLoginDiscoveryConfig,
expectedPinnipedDiscoveryInfo,
),
},
placeholderAPIClient.Actions(),
pinnipedAPIClient.Actions(),
)
})
when("creating the LoginDiscoveryConfig fails", func() {
when("creating the PinnipedDiscoveryInfo fails", func() {
it.Before(func() {
placeholderAPIClient.PrependReactor(
pinnipedAPIClient.PrependReactor(
"create",
"logindiscoveryconfigs",
"pinnipeddiscoveryinfos",
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 logindiscoveryconfig: create failed")
r.EqualError(err, "could not create pinnipeddiscoveryinfo: create failed")
})
})
@@ -319,85 +319,85 @@ func TestSync(t *testing.T) {
err := controller.TestSync(t, subject, *syncContext)
r.NoError(err)
expectedLoginDiscoveryConfigGVR, expectedLoginDiscoveryConfig := expectedLoginDiscoveryConfig(
expectedPinnipedDiscoveryInfoGVR, expectedPinnipedDiscoveryInfo := expectedPinnipedDiscoveryInfo(
installedInNamespace,
kubeServerURL,
caData,
)
expectedLoginDiscoveryConfig.Spec.Server = "https://some-server-override"
expectedPinnipedDiscoveryInfo.Spec.Server = "https://some-server-override"
r.Equal(
[]coretesting.Action{
coretesting.NewCreateAction(
expectedLoginDiscoveryConfigGVR,
expectedPinnipedDiscoveryInfoGVR,
installedInNamespace,
expectedLoginDiscoveryConfig,
expectedPinnipedDiscoveryInfo,
),
},
placeholderAPIClient.Actions(),
pinnipedAPIClient.Actions(),
)
})
})
})
when("the LoginDiscoveryConfig already exists", func() {
when("the LoginDiscoveryConfig is already up to date according to the data in the ConfigMap", func() {
when("the PinnipedDiscoveryInfo already exists", func() {
when("the PinnipedDiscoveryInfo is already up to date according to the data in the ConfigMap", func() {
it.Before(func() {
_, expectedLoginDiscoveryConfig := expectedLoginDiscoveryConfig(
_, expectedPinnipedDiscoveryInfo := expectedPinnipedDiscoveryInfo(
installedInNamespace,
kubeServerURL,
caData,
)
err := placeholderInformerClient.Tracker().Add(expectedLoginDiscoveryConfig)
err := pinnipedInformerClient.Tracker().Add(expectedPinnipedDiscoveryInfo)
r.NoError(err)
})
it("does not update the LoginDiscoveryConfig to avoid unnecessary etcd writes/api calls", func() {
it("does not update the PinnipedDiscoveryInfo to avoid unnecessary etcd writes/api calls", func() {
startInformersAndController()
err := controller.TestSync(t, subject, *syncContext)
r.NoError(err)
r.Empty(placeholderAPIClient.Actions())
r.Empty(pinnipedAPIClient.Actions())
})
})
when("the LoginDiscoveryConfig is stale compared to the data in the ConfigMap", func() {
when("the PinnipedDiscoveryInfo is stale compared to the data in the ConfigMap", func() {
it.Before(func() {
_, expectedLoginDiscoveryConfig := expectedLoginDiscoveryConfig(
_, expectedPinnipedDiscoveryInfo := expectedPinnipedDiscoveryInfo(
installedInNamespace,
kubeServerURL,
caData,
)
expectedLoginDiscoveryConfig.Spec.Server = "https://some-other-server"
r.NoError(placeholderInformerClient.Tracker().Add(expectedLoginDiscoveryConfig))
r.NoError(placeholderAPIClient.Tracker().Add(expectedLoginDiscoveryConfig))
expectedPinnipedDiscoveryInfo.Spec.Server = "https://some-other-server"
r.NoError(pinnipedInformerClient.Tracker().Add(expectedPinnipedDiscoveryInfo))
r.NoError(pinnipedAPIClient.Tracker().Add(expectedPinnipedDiscoveryInfo))
})
it("updates the existing LoginDiscoveryConfig", func() {
it("updates the existing PinnipedDiscoveryInfo", func() {
startInformersAndController()
err := controller.TestSync(t, subject, *syncContext)
r.NoError(err)
expectedLoginDiscoveryConfigGVR, expectedLoginDiscoveryConfig := expectedLoginDiscoveryConfig(
expectedPinnipedDiscoveryInfoGVR, expectedPinnipedDiscoveryInfo := expectedPinnipedDiscoveryInfo(
installedInNamespace,
kubeServerURL,
caData,
)
expectedActions := []coretesting.Action{
coretesting.NewUpdateAction(
expectedLoginDiscoveryConfigGVR,
expectedPinnipedDiscoveryInfoGVR,
installedInNamespace,
expectedLoginDiscoveryConfig,
expectedPinnipedDiscoveryInfo,
),
}
r.Equal(expectedActions, placeholderAPIClient.Actions())
r.Equal(expectedActions, pinnipedAPIClient.Actions())
})
when("updating the LoginDiscoveryConfig fails", func() {
when("updating the PinnipedDiscoveryInfo fails", func() {
it.Before(func() {
placeholderAPIClient.PrependReactor(
pinnipedAPIClient.PrependReactor(
"update",
"logindiscoveryconfigs",
"pinnipeddiscoveryinfos",
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 logindiscoveryconfig: update failed")
r.EqualError(err, "could not update pinnipeddiscoveryinfo: update failed")
})
})
})
@@ -430,7 +430,7 @@ func TestSync(t *testing.T) {
startInformersAndController()
err := controller.TestSync(t, subject, *syncContext)
r.NoError(err)
r.Empty(placeholderAPIClient.Actions())
r.Empty(pinnipedAPIClient.Actions())
})
})
})
@@ -451,7 +451,7 @@ func TestSync(t *testing.T) {
startInformersAndController()
err := controller.TestSync(t, subject, *syncContext)
r.NoError(err)
r.Empty(placeholderAPIClient.Actions())
r.Empty(pinnipedAPIClient.Actions())
})
})
}, spec.Parallel(), spec.Report(report.Terminal{}))
@@ -1,7 +0,0 @@
/*
Copyright 2020 VMware, Inc.
SPDX-License-Identifier: Apache-2.0
*/
// Package logindiscovery contains controller(s) for reconciling LoginDiscoveryConfig's.
package logindiscovery
@@ -1,174 +0,0 @@
/*
Copyright 2020 VMware, Inc.
SPDX-License-Identifier: Apache-2.0
*/
package logindiscovery
import (
"context"
"encoding/base64"
"fmt"
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"
"github.com/suzerain-io/controller-go"
placeholdernamecontroller "github.com/suzerain-io/placeholder-name/internal/controller"
crdsplaceholderv1alpha1 "github.com/suzerain-io/placeholder-name/kubernetes/1.19/api/apis/crdsplaceholder/v1alpha1"
placeholderclientset "github.com/suzerain-io/placeholder-name/kubernetes/1.19/client-go/clientset/versioned"
crdsplaceholderv1alpha1informers "github.com/suzerain-io/placeholder-name/kubernetes/1.19/client-go/informers/externalversions/crdsplaceholder/v1alpha1"
)
const (
ClusterInfoNamespace = "kube-public"
clusterInfoName = "cluster-info"
clusterInfoConfigMapKey = "kubeconfig"
configName = "placeholder-name-config"
)
type publisherController struct {
namespace string
serverOverride *string
placeholderClient placeholderclientset.Interface
configMapInformer corev1informers.ConfigMapInformer
loginDiscoveryConfigInformer crdsplaceholderv1alpha1informers.LoginDiscoveryConfigInformer
}
func NewPublisherController(
namespace string,
serverOverride *string,
placeholderClient placeholderclientset.Interface,
configMapInformer corev1informers.ConfigMapInformer,
loginDiscoveryConfigInformer crdsplaceholderv1alpha1informers.LoginDiscoveryConfigInformer,
withInformer placeholdernamecontroller.WithInformerOptionFunc,
) controller.Controller {
return controller.New(
controller.Config{
Name: "publisher-controller",
Syncer: &publisherController{
namespace: namespace,
serverOverride: serverOverride,
placeholderClient: placeholderClient,
configMapInformer: configMapInformer,
loginDiscoveryConfigInformer: loginDiscoveryConfigInformer,
},
},
withInformer(
configMapInformer,
placeholdernamecontroller.NameAndNamespaceExactMatchFilterFactory(clusterInfoName, ClusterInfoNamespace),
controller.InformerOption{},
),
withInformer(
loginDiscoveryConfigInformer,
placeholdernamecontroller.NameAndNamespaceExactMatchFilterFactory(configName, namespace),
controller.InformerOption{},
),
)
}
func (c *publisherController) Sync(ctx controller.Context) error {
configMap, err := c.configMapInformer.
Lister().
ConfigMaps(ClusterInfoNamespace).
Get(clusterInfoName)
notFound := k8serrors.IsNotFound(err)
if err != nil && !notFound {
return fmt.Errorf("failed to get %s configmap: %w", clusterInfoName, err)
}
if notFound {
klog.InfoS(
"could not find config map",
"configmap",
klog.KRef(ClusterInfoNamespace, clusterInfoName),
)
return nil
}
kubeConfig, kubeConfigPresent := configMap.Data[clusterInfoConfigMapKey]
if !kubeConfigPresent {
klog.InfoS("could not find kubeconfig configmap key")
return nil
}
config, _ := clientcmd.Load([]byte(kubeConfig))
var certificateAuthorityData, server string
for _, v := range config.Clusters {
certificateAuthorityData = base64.StdEncoding.EncodeToString(v.CertificateAuthorityData)
server = v.Server
break
}
if c.serverOverride != nil {
server = *c.serverOverride
}
discoveryConfig := crdsplaceholderv1alpha1.LoginDiscoveryConfig{
TypeMeta: metav1.TypeMeta{},
ObjectMeta: metav1.ObjectMeta{
Name: configName,
Namespace: c.namespace,
},
Spec: crdsplaceholderv1alpha1.LoginDiscoveryConfigSpec{
Server: server,
CertificateAuthorityData: certificateAuthorityData,
},
}
if err := c.createOrUpdateLoginDiscoveryConfig(ctx.Context, &discoveryConfig); err != nil {
return err
}
return nil
}
func (c *publisherController) createOrUpdateLoginDiscoveryConfig(
ctx context.Context,
discoveryConfig *crdsplaceholderv1alpha1.LoginDiscoveryConfig,
) error {
existingDiscoveryConfig, err := c.loginDiscoveryConfigInformer.
Lister().
LoginDiscoveryConfigs(c.namespace).
Get(discoveryConfig.Name)
notFound := k8serrors.IsNotFound(err)
if err != nil && !notFound {
return fmt.Errorf("could not get logindiscoveryconfig: %w", err)
}
loginDiscoveryConfigs := c.placeholderClient.
CrdsV1alpha1().
LoginDiscoveryConfigs(c.namespace)
if notFound {
if _, err := loginDiscoveryConfigs.Create(
ctx,
discoveryConfig,
metav1.CreateOptions{},
); err != nil {
return fmt.Errorf("could not create logindiscoveryconfig: %w", err)
}
} else if !equal(existingDiscoveryConfig, discoveryConfig) {
// Update just the fields we care about.
existingDiscoveryConfig.Spec.Server = discoveryConfig.Spec.Server
existingDiscoveryConfig.Spec.CertificateAuthorityData = discoveryConfig.Spec.CertificateAuthorityData
if _, err := loginDiscoveryConfigs.Update(
ctx,
existingDiscoveryConfig,
metav1.UpdateOptions{},
); err != nil {
return fmt.Errorf("could not update logindiscoveryconfig: %w", err)
}
}
return nil
}
func equal(a, b *crdsplaceholderv1alpha1.LoginDiscoveryConfig) bool {
return a.Spec.Server == b.Spec.Server &&
a.Spec.CertificateAuthorityData == b.Spec.CertificateAuthorityData
}