mirror of
https://github.com/vmware-tanzu/pinniped.git
synced 2026-09-05 23:57:12 +00:00
Rename project
This commit is contained in:
@@ -20,9 +20,9 @@ import (
|
||||
"k8s.io/client-go/pkg/version"
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
"github.com/suzerain-io/placeholder-name/internal/registry/credentialrequest"
|
||||
placeholderapi "github.com/suzerain-io/placeholder-name/kubernetes/1.19/api/apis/placeholder"
|
||||
placeholderv1alpha1 "github.com/suzerain-io/placeholder-name/kubernetes/1.19/api/apis/placeholder/v1alpha1"
|
||||
"github.com/suzerain-io/pinniped/internal/registry/credentialrequest"
|
||||
pinnipedapi "github.com/suzerain-io/pinniped/kubernetes/1.19/api/apis/pinniped"
|
||||
pinnipedv1alpha1 "github.com/suzerain-io/pinniped/kubernetes/1.19/api/apis/pinniped/v1alpha1"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -35,8 +35,8 @@ var (
|
||||
|
||||
//nolint: gochecknoinits
|
||||
func init() {
|
||||
utilruntime.Must(placeholderv1alpha1.AddToScheme(scheme))
|
||||
utilruntime.Must(placeholderapi.AddToScheme(scheme))
|
||||
utilruntime.Must(pinnipedv1alpha1.AddToScheme(scheme))
|
||||
utilruntime.Must(pinnipedapi.AddToScheme(scheme))
|
||||
|
||||
// add the options to empty v1
|
||||
metav1.AddToGroupVersion(scheme, schema.GroupVersion{Version: "v1"})
|
||||
@@ -62,7 +62,7 @@ type ExtraConfig struct {
|
||||
StartControllersPostStartHook func(ctx context.Context)
|
||||
}
|
||||
|
||||
type PlaceHolderServer struct {
|
||||
type PinnipedServer struct {
|
||||
GenericAPIServer *genericapiserver.GenericAPIServer
|
||||
}
|
||||
|
||||
@@ -90,17 +90,17 @@ func (c *Config) Complete() CompletedConfig {
|
||||
}
|
||||
|
||||
// New returns a new instance of AdmissionServer from the given config.
|
||||
func (c completedConfig) New() (*PlaceHolderServer, error) {
|
||||
genericServer, err := c.GenericConfig.New("place-holder-server", genericapiserver.NewEmptyDelegate()) // completion is done in Complete, no need for a second time
|
||||
func (c completedConfig) New() (*PinnipedServer, error) {
|
||||
genericServer, err := c.GenericConfig.New("pinniped-server", genericapiserver.NewEmptyDelegate()) // completion is done in Complete, no need for a second time
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("completion error: %w", err)
|
||||
}
|
||||
|
||||
s := &PlaceHolderServer{
|
||||
s := &PinnipedServer{
|
||||
GenericAPIServer: genericServer,
|
||||
}
|
||||
|
||||
gvr := placeholderv1alpha1.SchemeGroupVersion.WithResource("credentialrequests")
|
||||
gvr := pinnipedv1alpha1.SchemeGroupVersion.WithResource("credentialrequests")
|
||||
|
||||
apiGroupInfo := genericapiserver.APIGroupInfo{
|
||||
PrioritizedVersions: []schema.GroupVersion{gvr.GroupVersion()},
|
||||
|
||||
@@ -24,8 +24,8 @@ import (
|
||||
"k8s.io/client-go/tools/remotecommand"
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
"github.com/suzerain-io/placeholder-name/internal/certauthority"
|
||||
"github.com/suzerain-io/placeholder-name/internal/constable"
|
||||
"github.com/suzerain-io/pinniped/internal/certauthority"
|
||||
"github.com/suzerain-io/pinniped/internal/constable"
|
||||
)
|
||||
|
||||
// ErrNoKubeControllerManagerPod is returned when no kube-controller-manager pod is found on the cluster.
|
||||
|
||||
@@ -23,7 +23,7 @@ import (
|
||||
kubernetesfake "k8s.io/client-go/kubernetes/fake"
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
"github.com/suzerain-io/placeholder-name/internal/testutil"
|
||||
"github.com/suzerain-io/pinniped/internal/testutil"
|
||||
)
|
||||
|
||||
type fakePodExecutor struct {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
}
|
||||
+76
-76
@@ -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
|
||||
}
|
||||
@@ -17,11 +17,11 @@ import (
|
||||
aggregatorclient "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset"
|
||||
|
||||
"github.com/suzerain-io/controller-go"
|
||||
"github.com/suzerain-io/placeholder-name/internal/controller/apicerts"
|
||||
"github.com/suzerain-io/placeholder-name/internal/controller/logindiscovery"
|
||||
"github.com/suzerain-io/placeholder-name/internal/provider"
|
||||
placeholderclientset "github.com/suzerain-io/placeholder-name/kubernetes/1.19/client-go/clientset/versioned"
|
||||
placeholderinformers "github.com/suzerain-io/placeholder-name/kubernetes/1.19/client-go/informers/externalversions"
|
||||
"github.com/suzerain-io/pinniped/internal/controller/apicerts"
|
||||
"github.com/suzerain-io/pinniped/internal/controller/discovery"
|
||||
"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"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -37,25 +37,25 @@ func PrepareControllers(
|
||||
servingCertRotationThreshold float32,
|
||||
) (func(ctx context.Context), error) {
|
||||
// Create k8s clients.
|
||||
k8sClient, aggregatorClient, placeholderClient, err := createClients()
|
||||
k8sClient, aggregatorClient, pinnipedClient, err := createClients()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not create clients for the controllers: %w", err)
|
||||
}
|
||||
|
||||
// Create informers. Don't forget to make sure they get started in the function returned below.
|
||||
kubePublicNamespaceK8sInformers, installationNamespaceK8sInformers, installationNamespacePlaceholderInformers :=
|
||||
createInformers(serverInstallationNamespace, k8sClient, placeholderClient)
|
||||
kubePublicNamespaceK8sInformers, installationNamespaceK8sInformers, installationNamespacePinnipedInformers :=
|
||||
createInformers(serverInstallationNamespace, k8sClient, pinnipedClient)
|
||||
|
||||
// Create controller manager.
|
||||
controllerManager := controller.
|
||||
NewManager().
|
||||
WithController(
|
||||
logindiscovery.NewPublisherController(
|
||||
discovery.NewPublisherController(
|
||||
serverInstallationNamespace,
|
||||
discoveryURLOverride,
|
||||
placeholderClient,
|
||||
pinnipedClient,
|
||||
kubePublicNamespaceK8sInformers.Core().V1().ConfigMaps(),
|
||||
installationNamespacePlaceholderInformers.Crds().V1alpha1().LoginDiscoveryConfigs(),
|
||||
installationNamespacePinnipedInformers.Crd().V1alpha1().PinnipedDiscoveryInfos(),
|
||||
controller.WithInformer,
|
||||
),
|
||||
singletonWorker,
|
||||
@@ -95,7 +95,7 @@ func PrepareControllers(
|
||||
return func(ctx context.Context) {
|
||||
kubePublicNamespaceK8sInformers.Start(ctx.Done())
|
||||
installationNamespaceK8sInformers.Start(ctx.Done())
|
||||
installationNamespacePlaceholderInformers.Start(ctx.Done())
|
||||
installationNamespacePinnipedInformers.Start(ctx.Done())
|
||||
|
||||
go controllerManager.Start(ctx)
|
||||
}, nil
|
||||
@@ -105,7 +105,7 @@ func PrepareControllers(
|
||||
func createClients() (
|
||||
k8sClient *kubernetes.Clientset,
|
||||
aggregatorClient *aggregatorclient.Clientset,
|
||||
placeholderClient *placeholderclientset.Clientset,
|
||||
pinnipedClient *pinnipedclientset.Clientset,
|
||||
err error,
|
||||
) {
|
||||
// Load the Kubernetes client configuration.
|
||||
@@ -129,12 +129,12 @@ func createClients() (
|
||||
return nil, nil, nil, fmt.Errorf("could not initialize Kubernetes client: %w", err)
|
||||
}
|
||||
|
||||
// Connect to the placeholder API.
|
||||
// Connect to the pinniped API.
|
||||
// I think we can't use protobuf encoding here because we are using CRDs
|
||||
// (for which protobuf encoding is not supported).
|
||||
placeholderClient, err = placeholderclientset.NewForConfig(kubeConfig)
|
||||
pinnipedClient, err = pinnipedclientset.NewForConfig(kubeConfig)
|
||||
if err != nil {
|
||||
return nil, nil, nil, fmt.Errorf("could not initialize placeholder client: %w", err)
|
||||
return nil, nil, nil, fmt.Errorf("could not initialize pinniped client: %w", err)
|
||||
}
|
||||
|
||||
//nolint: nakedret
|
||||
@@ -145,26 +145,26 @@ func createClients() (
|
||||
func createInformers(
|
||||
serverInstallationNamespace string,
|
||||
k8sClient *kubernetes.Clientset,
|
||||
placeholderClient *placeholderclientset.Clientset,
|
||||
pinnipedClient *pinnipedclientset.Clientset,
|
||||
) (
|
||||
kubePublicNamespaceK8sInformers k8sinformers.SharedInformerFactory,
|
||||
installationNamespaceK8sInformers k8sinformers.SharedInformerFactory,
|
||||
installationNamespacePlaceholderInformers placeholderinformers.SharedInformerFactory,
|
||||
installationNamespacePinnipedInformers pinnipedinformers.SharedInformerFactory,
|
||||
) {
|
||||
kubePublicNamespaceK8sInformers = k8sinformers.NewSharedInformerFactoryWithOptions(
|
||||
k8sClient,
|
||||
defaultResyncInterval,
|
||||
k8sinformers.WithNamespace(logindiscovery.ClusterInfoNamespace),
|
||||
k8sinformers.WithNamespace(discovery.ClusterInfoNamespace),
|
||||
)
|
||||
installationNamespaceK8sInformers = k8sinformers.NewSharedInformerFactoryWithOptions(
|
||||
k8sClient,
|
||||
defaultResyncInterval,
|
||||
k8sinformers.WithNamespace(serverInstallationNamespace),
|
||||
)
|
||||
installationNamespacePlaceholderInformers = placeholderinformers.NewSharedInformerFactoryWithOptions(
|
||||
placeholderClient,
|
||||
installationNamespacePinnipedInformers = pinnipedinformers.NewSharedInformerFactoryWithOptions(
|
||||
pinnipedClient,
|
||||
defaultResyncInterval,
|
||||
placeholderinformers.WithNamespace(serverInstallationNamespace),
|
||||
pinnipedinformers.WithNamespace(serverInstallationNamespace),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -5,4 +5,4 @@ SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package mockcertissuer
|
||||
|
||||
//go:generate go run -v github.com/golang/mock/mockgen -destination=mockcertissuer.go -package=mockcertissuer -copyright_file=../../../hack/header.txt github.com/suzerain-io/placeholder-name/internal/registry/credentialrequest CertIssuer
|
||||
//go:generate go run -v github.com/golang/mock/mockgen -destination=mockcertissuer.go -package=mockcertissuer -copyright_file=../../../hack/header.txt github.com/suzerain-io/pinniped/internal/registry/credentialrequest CertIssuer
|
||||
|
||||
@@ -3,16 +3,17 @@
|
||||
//
|
||||
|
||||
// Code generated by MockGen. DO NOT EDIT.
|
||||
// Source: github.com/suzerain-io/placeholder-name/internal/registry/credentialrequest (interfaces: CertIssuer)
|
||||
// Source: github.com/suzerain-io/pinniped/internal/registry/credentialrequest (interfaces: CertIssuer)
|
||||
|
||||
// Package mockcertissuer is a generated GoMock package.
|
||||
package mockcertissuer
|
||||
|
||||
import (
|
||||
pkix "crypto/x509/pkix"
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
reflect "reflect"
|
||||
time "time"
|
||||
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
)
|
||||
|
||||
// MockCertIssuer is a mock of CertIssuer interface
|
||||
|
||||
@@ -21,7 +21,7 @@ import (
|
||||
"k8s.io/apiserver/pkg/registry/rest"
|
||||
"k8s.io/utils/trace"
|
||||
|
||||
placeholderapi "github.com/suzerain-io/placeholder-name/kubernetes/1.19/api/apis/placeholder"
|
||||
pinnipedapi "github.com/suzerain-io/pinniped/kubernetes/1.19/api/apis/pinniped"
|
||||
)
|
||||
|
||||
// clientCertificateTTL is the TTL for short-lived client certificates returned by this API.
|
||||
@@ -51,7 +51,7 @@ type REST struct {
|
||||
}
|
||||
|
||||
func (r *REST) New() runtime.Object {
|
||||
return &placeholderapi.CredentialRequest{}
|
||||
return &pinnipedapi.CredentialRequest{}
|
||||
}
|
||||
|
||||
func (r *REST) NamespaceScoped() bool {
|
||||
@@ -107,9 +107,9 @@ func (r *REST) Create(ctx context.Context, obj runtime.Object, createValidation
|
||||
|
||||
traceSuccess(t, authResponse.User, authenticated, true)
|
||||
|
||||
return &placeholderapi.CredentialRequest{
|
||||
Status: placeholderapi.CredentialRequestStatus{
|
||||
Credential: &placeholderapi.CredentialRequestCredential{
|
||||
return &pinnipedapi.CredentialRequest{
|
||||
Status: pinnipedapi.CredentialRequestStatus{
|
||||
Credential: &pinnipedapi.CredentialRequestCredential{
|
||||
ExpirationTimestamp: metav1.NewTime(time.Now().UTC().Add(clientCertificateTTL)),
|
||||
ClientCertificateData: string(certPEM),
|
||||
ClientKeyData: string(keyPEM),
|
||||
@@ -118,8 +118,8 @@ func (r *REST) Create(ctx context.Context, obj runtime.Object, createValidation
|
||||
}, nil
|
||||
}
|
||||
|
||||
func validateRequest(ctx context.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, options *metav1.CreateOptions, t *trace.Trace) (*placeholderapi.CredentialRequest, error) {
|
||||
credentialRequest, ok := obj.(*placeholderapi.CredentialRequest)
|
||||
func validateRequest(ctx context.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, options *metav1.CreateOptions, t *trace.Trace) (*pinnipedapi.CredentialRequest, error) {
|
||||
credentialRequest, ok := obj.(*pinnipedapi.CredentialRequest)
|
||||
if !ok {
|
||||
traceValidationFailure(t, "not a CredentialRequest")
|
||||
return nil, apierrors.NewBadRequest(fmt.Sprintf("not a CredentialRequest: %#v", obj))
|
||||
@@ -128,20 +128,20 @@ func validateRequest(ctx context.Context, obj runtime.Object, createValidation r
|
||||
if len(credentialRequest.Spec.Type) == 0 {
|
||||
traceValidationFailure(t, "type must be supplied")
|
||||
errs := field.ErrorList{field.Required(field.NewPath("spec", "type"), "type must be supplied")}
|
||||
return nil, apierrors.NewInvalid(placeholderapi.Kind(credentialRequest.Kind), credentialRequest.Name, errs)
|
||||
return nil, apierrors.NewInvalid(pinnipedapi.Kind(credentialRequest.Kind), credentialRequest.Name, errs)
|
||||
}
|
||||
|
||||
if credentialRequest.Spec.Type != placeholderapi.TokenCredentialType {
|
||||
if credentialRequest.Spec.Type != pinnipedapi.TokenCredentialType {
|
||||
traceValidationFailure(t, "unrecognized type")
|
||||
errs := field.ErrorList{field.Invalid(field.NewPath("spec", "type"), credentialRequest.Spec.Type, "unrecognized type")}
|
||||
return nil, apierrors.NewInvalid(placeholderapi.Kind(credentialRequest.Kind), credentialRequest.Name, errs)
|
||||
return nil, apierrors.NewInvalid(pinnipedapi.Kind(credentialRequest.Kind), credentialRequest.Name, errs)
|
||||
}
|
||||
|
||||
token := credentialRequest.Spec.Token
|
||||
if token == nil || len(token.Value) == 0 {
|
||||
traceValidationFailure(t, "token must be supplied")
|
||||
errs := field.ErrorList{field.Required(field.NewPath("spec", "token", "value"), "token must be supplied")}
|
||||
return nil, apierrors.NewInvalid(placeholderapi.Kind(credentialRequest.Kind), credentialRequest.Name, errs)
|
||||
return nil, apierrors.NewInvalid(pinnipedapi.Kind(credentialRequest.Kind), credentialRequest.Name, errs)
|
||||
}
|
||||
|
||||
// just a sanity check, not sure how to honor a dry run on a virtual API
|
||||
@@ -149,7 +149,7 @@ func validateRequest(ctx context.Context, obj runtime.Object, createValidation r
|
||||
if len(options.DryRun) != 0 {
|
||||
traceValidationFailure(t, "dryRun not supported")
|
||||
errs := field.ErrorList{field.NotSupported(field.NewPath("dryRun"), options.DryRun, nil)}
|
||||
return nil, apierrors.NewInvalid(placeholderapi.Kind(credentialRequest.Kind), credentialRequest.Name, errs)
|
||||
return nil, apierrors.NewInvalid(pinnipedapi.Kind(credentialRequest.Kind), credentialRequest.Name, errs)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,7 +160,7 @@ func validateRequest(ctx context.Context, obj runtime.Object, createValidation r
|
||||
// they already got the token.
|
||||
if createValidation != nil {
|
||||
requestForValidation := obj.DeepCopyObject()
|
||||
credentialRequestCopy, _ := requestForValidation.(*placeholderapi.CredentialRequest)
|
||||
credentialRequestCopy, _ := requestForValidation.(*pinnipedapi.CredentialRequest)
|
||||
credentialRequestCopy.Spec.Token.Value = ""
|
||||
if err := createValidation(ctx, requestForValidation); err != nil {
|
||||
traceFailureWithError(t, "validation webhook", err)
|
||||
@@ -171,7 +171,7 @@ func validateRequest(ctx context.Context, obj runtime.Object, createValidation r
|
||||
return credentialRequest, nil
|
||||
}
|
||||
|
||||
func traceSuccess(t *trace.Trace, user user.Info, webhookAuthenticated bool, placeholderNameAuthenticated bool) {
|
||||
func traceSuccess(t *trace.Trace, user user.Info, webhookAuthenticated bool, pinnipedAuthenticated bool) {
|
||||
userID := "<none>"
|
||||
if user != nil {
|
||||
userID = user.GetUID()
|
||||
@@ -179,7 +179,7 @@ func traceSuccess(t *trace.Trace, user user.Info, webhookAuthenticated bool, pla
|
||||
t.Step("success",
|
||||
trace.Field{Key: "userID", Value: userID},
|
||||
trace.Field{Key: "idpAuthenticated", Value: webhookAuthenticated},
|
||||
trace.Field{Key: "placeholderNameAuthenticated", Value: placeholderNameAuthenticated},
|
||||
trace.Field{Key: "pinnipedAuthenticated", Value: pinnipedAuthenticated},
|
||||
)
|
||||
}
|
||||
|
||||
@@ -197,10 +197,10 @@ func traceFailureWithError(t *trace.Trace, failureType string, err error) {
|
||||
)
|
||||
}
|
||||
|
||||
func failureResponse() *placeholderapi.CredentialRequest {
|
||||
func failureResponse() *pinnipedapi.CredentialRequest {
|
||||
m := "authentication failed"
|
||||
return &placeholderapi.CredentialRequest{
|
||||
Status: placeholderapi.CredentialRequestStatus{
|
||||
return &pinnipedapi.CredentialRequest{
|
||||
Status: pinnipedapi.CredentialRequestStatus{
|
||||
Credential: nil,
|
||||
Message: &m,
|
||||
},
|
||||
|
||||
@@ -25,9 +25,9 @@ import (
|
||||
"k8s.io/apiserver/pkg/registry/rest"
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
"github.com/suzerain-io/placeholder-name/internal/mocks/mockcertissuer"
|
||||
"github.com/suzerain-io/placeholder-name/internal/testutil"
|
||||
placeholderapi "github.com/suzerain-io/placeholder-name/kubernetes/1.19/api/apis/placeholder"
|
||||
"github.com/suzerain-io/pinniped/internal/mocks/mockcertissuer"
|
||||
"github.com/suzerain-io/pinniped/internal/testutil"
|
||||
pinnipedapi "github.com/suzerain-io/pinniped/kubernetes/1.19/api/apis/pinniped"
|
||||
)
|
||||
|
||||
type contextKey struct{}
|
||||
@@ -105,16 +105,16 @@ func TestCreate(t *testing.T) {
|
||||
response, err := callCreate(context.Background(), storage, validCredentialRequestWithToken(requestToken))
|
||||
|
||||
r.NoError(err)
|
||||
r.IsType(&placeholderapi.CredentialRequest{}, response)
|
||||
r.IsType(&pinnipedapi.CredentialRequest{}, response)
|
||||
|
||||
expires := response.(*placeholderapi.CredentialRequest).Status.Credential.ExpirationTimestamp
|
||||
expires := response.(*pinnipedapi.CredentialRequest).Status.Credential.ExpirationTimestamp
|
||||
r.NotNil(expires)
|
||||
r.InDelta(time.Now().Add(1*time.Hour).Unix(), expires.Unix(), 5)
|
||||
response.(*placeholderapi.CredentialRequest).Status.Credential.ExpirationTimestamp = metav1.Time{}
|
||||
response.(*pinnipedapi.CredentialRequest).Status.Credential.ExpirationTimestamp = metav1.Time{}
|
||||
|
||||
r.Equal(response, &placeholderapi.CredentialRequest{
|
||||
Status: placeholderapi.CredentialRequestStatus{
|
||||
Credential: &placeholderapi.CredentialRequestCredential{
|
||||
r.Equal(response, &pinnipedapi.CredentialRequest{
|
||||
Status: pinnipedapi.CredentialRequestStatus{
|
||||
Credential: &pinnipedapi.CredentialRequestCredential{
|
||||
ExpirationTimestamp: metav1.Time{},
|
||||
ClientCertificateData: "test-cert",
|
||||
ClientKeyData: "test-key",
|
||||
@@ -164,7 +164,7 @@ func TestCreate(t *testing.T) {
|
||||
|
||||
requireSuccessfulResponseWithAuthenticationFailureMessage(t, err, response)
|
||||
r.Equal(requestToken, webhook.calledWithToken)
|
||||
requireOneLogStatement(r, logger, `"success" userID:test-user-uid,idpAuthenticated:false,placeholderNameAuthenticated:false`)
|
||||
requireOneLogStatement(r, logger, `"success" userID:test-user-uid,idpAuthenticated:false,pinnipedAuthenticated:false`)
|
||||
})
|
||||
|
||||
it("CreateSucceedsWithAnUnauthenticatedStatusWhenGivenATokenAndTheWebhookReturnsUnauthenticatedWithNilUser", func() {
|
||||
@@ -179,7 +179,7 @@ func TestCreate(t *testing.T) {
|
||||
|
||||
requireSuccessfulResponseWithAuthenticationFailureMessage(t, err, response)
|
||||
r.Equal(requestToken, webhook.calledWithToken)
|
||||
requireOneLogStatement(r, logger, `"success" userID:<none>,idpAuthenticated:false,placeholderNameAuthenticated:false`)
|
||||
requireOneLogStatement(r, logger, `"success" userID:<none>,idpAuthenticated:false,pinnipedAuthenticated:false`)
|
||||
})
|
||||
|
||||
it("CreateSucceedsWithAnUnauthenticatedStatusWhenWebhookFails", func() {
|
||||
@@ -204,7 +204,7 @@ func TestCreate(t *testing.T) {
|
||||
response, err := callCreate(context.Background(), storage, validCredentialRequest())
|
||||
|
||||
requireSuccessfulResponseWithAuthenticationFailureMessage(t, err, response)
|
||||
requireOneLogStatement(r, logger, `"success" userID:<none>,idpAuthenticated:true,placeholderNameAuthenticated:false`)
|
||||
requireOneLogStatement(r, logger, `"success" userID:<none>,idpAuthenticated:true,pinnipedAuthenticated:false`)
|
||||
})
|
||||
|
||||
it("CreateSucceedsWithAnUnauthenticatedStatusWhenWebhookReturnsAnEmptyUsername", func() {
|
||||
@@ -220,7 +220,7 @@ func TestCreate(t *testing.T) {
|
||||
response, err := callCreate(context.Background(), storage, validCredentialRequest())
|
||||
|
||||
requireSuccessfulResponseWithAuthenticationFailureMessage(t, err, response)
|
||||
requireOneLogStatement(r, logger, `"success" userID:,idpAuthenticated:true,placeholderNameAuthenticated:false`)
|
||||
requireOneLogStatement(r, logger, `"success" userID:,idpAuthenticated:true,pinnipedAuthenticated:false`)
|
||||
})
|
||||
|
||||
it("CreateDoesNotPassAdditionalContextInfoToTheWebhook", func() {
|
||||
@@ -250,49 +250,49 @@ func TestCreate(t *testing.T) {
|
||||
|
||||
it("CreateFailsWhenTokenIsNilInRequest", func() {
|
||||
storage := NewREST(&FakeToken{}, nil)
|
||||
response, err := callCreate(context.Background(), storage, credentialRequest(placeholderapi.CredentialRequestSpec{
|
||||
Type: placeholderapi.TokenCredentialType,
|
||||
response, err := callCreate(context.Background(), storage, credentialRequest(pinnipedapi.CredentialRequestSpec{
|
||||
Type: pinnipedapi.TokenCredentialType,
|
||||
Token: nil,
|
||||
}))
|
||||
|
||||
requireAPIError(t, response, err, apierrors.IsInvalid,
|
||||
`.placeholder.suzerain-io.github.io "request name" is invalid: spec.token.value: Required value: token must be supplied`)
|
||||
`.pinniped.dev "request name" is invalid: spec.token.value: Required value: token must be supplied`)
|
||||
requireOneLogStatement(r, logger, `"failure" failureType:request validation,msg:token must be supplied`)
|
||||
})
|
||||
|
||||
it("CreateFailsWhenTypeInRequestIsMissing", func() {
|
||||
storage := NewREST(&FakeToken{}, nil)
|
||||
response, err := callCreate(context.Background(), storage, credentialRequest(placeholderapi.CredentialRequestSpec{
|
||||
response, err := callCreate(context.Background(), storage, credentialRequest(pinnipedapi.CredentialRequestSpec{
|
||||
Type: "",
|
||||
Token: &placeholderapi.CredentialRequestTokenCredential{Value: "a token"},
|
||||
Token: &pinnipedapi.CredentialRequestTokenCredential{Value: "a token"},
|
||||
}))
|
||||
|
||||
requireAPIError(t, response, err, apierrors.IsInvalid,
|
||||
`.placeholder.suzerain-io.github.io "request name" is invalid: spec.type: Required value: type must be supplied`)
|
||||
`.pinniped.dev "request name" is invalid: spec.type: Required value: type must be supplied`)
|
||||
requireOneLogStatement(r, logger, `"failure" failureType:request validation,msg:type must be supplied`)
|
||||
})
|
||||
|
||||
it("CreateFailsWhenTypeInRequestIsNotLegal", func() {
|
||||
storage := NewREST(&FakeToken{}, nil)
|
||||
response, err := callCreate(context.Background(), storage, credentialRequest(placeholderapi.CredentialRequestSpec{
|
||||
response, err := callCreate(context.Background(), storage, credentialRequest(pinnipedapi.CredentialRequestSpec{
|
||||
Type: "this in an invalid type",
|
||||
Token: &placeholderapi.CredentialRequestTokenCredential{Value: "a token"},
|
||||
Token: &pinnipedapi.CredentialRequestTokenCredential{Value: "a token"},
|
||||
}))
|
||||
|
||||
requireAPIError(t, response, err, apierrors.IsInvalid,
|
||||
`.placeholder.suzerain-io.github.io "request name" is invalid: spec.type: Invalid value: "this in an invalid type": unrecognized type`)
|
||||
`.pinniped.dev "request name" is invalid: spec.type: Invalid value: "this in an invalid type": unrecognized type`)
|
||||
requireOneLogStatement(r, logger, `"failure" failureType:request validation,msg:unrecognized type`)
|
||||
})
|
||||
|
||||
it("CreateFailsWhenTokenValueIsEmptyInRequest", func() {
|
||||
storage := NewREST(&FakeToken{}, nil)
|
||||
response, err := callCreate(context.Background(), storage, credentialRequest(placeholderapi.CredentialRequestSpec{
|
||||
Type: placeholderapi.TokenCredentialType,
|
||||
Token: &placeholderapi.CredentialRequestTokenCredential{Value: ""},
|
||||
response, err := callCreate(context.Background(), storage, credentialRequest(pinnipedapi.CredentialRequestSpec{
|
||||
Type: pinnipedapi.TokenCredentialType,
|
||||
Token: &pinnipedapi.CredentialRequestTokenCredential{Value: ""},
|
||||
}))
|
||||
|
||||
requireAPIError(t, response, err, apierrors.IsInvalid,
|
||||
`.placeholder.suzerain-io.github.io "request name" is invalid: spec.token.value: Required value: token must be supplied`)
|
||||
`.pinniped.dev "request name" is invalid: spec.token.value: Required value: token must be supplied`)
|
||||
requireOneLogStatement(r, logger, `"failure" failureType:request validation,msg:token must be supplied`)
|
||||
})
|
||||
|
||||
@@ -320,7 +320,7 @@ func TestCreate(t *testing.T) {
|
||||
context.Background(),
|
||||
validCredentialRequestWithToken(requestToken),
|
||||
func(ctx context.Context, obj runtime.Object) error {
|
||||
credentialRequest, _ := obj.(*placeholderapi.CredentialRequest)
|
||||
credentialRequest, _ := obj.(*pinnipedapi.CredentialRequest)
|
||||
credentialRequest.Spec.Token.Value = "foobaz"
|
||||
return nil
|
||||
},
|
||||
@@ -342,7 +342,7 @@ func TestCreate(t *testing.T) {
|
||||
context.Background(),
|
||||
validCredentialRequest(),
|
||||
func(ctx context.Context, obj runtime.Object) error {
|
||||
credentialRequest, _ := obj.(*placeholderapi.CredentialRequest)
|
||||
credentialRequest, _ := obj.(*pinnipedapi.CredentialRequest)
|
||||
validationFunctionWasCalled = true
|
||||
validationFunctionSawTokenValue = credentialRequest.Spec.Token.Value
|
||||
return nil
|
||||
@@ -364,7 +364,7 @@ func TestCreate(t *testing.T) {
|
||||
})
|
||||
|
||||
requireAPIError(t, response, err, apierrors.IsInvalid,
|
||||
`.placeholder.suzerain-io.github.io "request name" is invalid: dryRun: Unsupported value: []string{"some dry run flag"}`)
|
||||
`.pinniped.dev "request name" is invalid: dryRun: Unsupported value: []string{"some dry run flag"}`)
|
||||
requireOneLogStatement(r, logger, `"failure" failureType:request validation,msg:dryRun not supported`)
|
||||
})
|
||||
|
||||
@@ -431,7 +431,7 @@ func requireOneLogStatement(r *require.Assertions, logger *testutil.TranscriptLo
|
||||
r.Contains(transcript[0].Message, messageContains)
|
||||
}
|
||||
|
||||
func callCreate(ctx context.Context, storage *REST, credentialRequest *placeholderapi.CredentialRequest) (runtime.Object, error) {
|
||||
func callCreate(ctx context.Context, storage *REST, credentialRequest *pinnipedapi.CredentialRequest) (runtime.Object, error) {
|
||||
return storage.Create(
|
||||
ctx,
|
||||
credentialRequest,
|
||||
@@ -441,19 +441,19 @@ func callCreate(ctx context.Context, storage *REST, credentialRequest *placehold
|
||||
})
|
||||
}
|
||||
|
||||
func validCredentialRequest() *placeholderapi.CredentialRequest {
|
||||
func validCredentialRequest() *pinnipedapi.CredentialRequest {
|
||||
return validCredentialRequestWithToken("some token")
|
||||
}
|
||||
|
||||
func validCredentialRequestWithToken(token string) *placeholderapi.CredentialRequest {
|
||||
return credentialRequest(placeholderapi.CredentialRequestSpec{
|
||||
Type: placeholderapi.TokenCredentialType,
|
||||
Token: &placeholderapi.CredentialRequestTokenCredential{Value: token},
|
||||
func validCredentialRequestWithToken(token string) *pinnipedapi.CredentialRequest {
|
||||
return credentialRequest(pinnipedapi.CredentialRequestSpec{
|
||||
Type: pinnipedapi.TokenCredentialType,
|
||||
Token: &pinnipedapi.CredentialRequestTokenCredential{Value: token},
|
||||
})
|
||||
}
|
||||
|
||||
func credentialRequest(spec placeholderapi.CredentialRequestSpec) *placeholderapi.CredentialRequest {
|
||||
return &placeholderapi.CredentialRequest{
|
||||
func credentialRequest(spec pinnipedapi.CredentialRequestSpec) *pinnipedapi.CredentialRequest {
|
||||
return &pinnipedapi.CredentialRequest{
|
||||
TypeMeta: metav1.TypeMeta{},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "request name",
|
||||
@@ -483,8 +483,8 @@ func requireAPIError(t *testing.T, response runtime.Object, err error, expectedE
|
||||
func requireSuccessfulResponseWithAuthenticationFailureMessage(t *testing.T, err error, response runtime.Object) {
|
||||
t.Helper()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, response, &placeholderapi.CredentialRequest{
|
||||
Status: placeholderapi.CredentialRequestStatus{
|
||||
require.Equal(t, response, &pinnipedapi.CredentialRequest{
|
||||
Status: pinnipedapi.CredentialRequestStatus{
|
||||
Credential: nil,
|
||||
Message: stringPtr("authentication failed"),
|
||||
},
|
||||
|
||||
+17
-17
@@ -3,7 +3,7 @@ Copyright 2020 VMware, Inc.
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
// Package server is the command line entry point for placeholder-name-server.
|
||||
// Package server is the command line entry point for pinniped-server.
|
||||
package server
|
||||
|
||||
import (
|
||||
@@ -21,15 +21,15 @@ import (
|
||||
"k8s.io/client-go/kubernetes"
|
||||
restclient "k8s.io/client-go/rest"
|
||||
|
||||
"github.com/suzerain-io/placeholder-name/internal/apiserver"
|
||||
"github.com/suzerain-io/placeholder-name/internal/certauthority/kubecertauthority"
|
||||
"github.com/suzerain-io/placeholder-name/internal/constable"
|
||||
"github.com/suzerain-io/placeholder-name/internal/controllermanager"
|
||||
"github.com/suzerain-io/placeholder-name/internal/downward"
|
||||
"github.com/suzerain-io/placeholder-name/internal/provider"
|
||||
"github.com/suzerain-io/placeholder-name/internal/registry/credentialrequest"
|
||||
placeholderv1alpha1 "github.com/suzerain-io/placeholder-name/kubernetes/1.19/api/apis/placeholder/v1alpha1"
|
||||
"github.com/suzerain-io/placeholder-name/pkg/config"
|
||||
"github.com/suzerain-io/pinniped/internal/apiserver"
|
||||
"github.com/suzerain-io/pinniped/internal/certauthority/kubecertauthority"
|
||||
"github.com/suzerain-io/pinniped/internal/constable"
|
||||
"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"
|
||||
pinnipedv1alpha1 "github.com/suzerain-io/pinniped/kubernetes/1.19/api/apis/pinniped/v1alpha1"
|
||||
"github.com/suzerain-io/pinniped/pkg/config"
|
||||
)
|
||||
|
||||
type percentageValue struct {
|
||||
@@ -57,7 +57,7 @@ func (p *percentageValue) Type() string {
|
||||
return "percentage"
|
||||
}
|
||||
|
||||
// App is an object that represents the placeholder-name-server application.
|
||||
// App is an object that represents the pinniped-server application.
|
||||
type App struct {
|
||||
cmd *cobra.Command
|
||||
|
||||
@@ -69,7 +69,7 @@ type App struct {
|
||||
|
||||
// This is ignored for now because we turn off etcd storage below, but this is
|
||||
// the right prefix in case we turn it back on.
|
||||
const defaultEtcdPathPrefix = "/registry/" + placeholderv1alpha1.GroupName
|
||||
const defaultEtcdPathPrefix = "/registry/" + pinnipedv1alpha1.GroupName
|
||||
|
||||
// New constructs a new App with command line args, stdout and stderr.
|
||||
func New(ctx context.Context, args []string, stdout, stderr io.Writer) *App {
|
||||
@@ -86,8 +86,8 @@ func (a *App) Run() error {
|
||||
// Create the server command and save it into the App.
|
||||
func (a *App) addServerCommand(ctx context.Context, args []string, stdout, stderr io.Writer) {
|
||||
cmd := &cobra.Command{
|
||||
Use: `placeholder-name-server`,
|
||||
Long: "placeholder-name-server provides a generic API for mapping an external\n" +
|
||||
Use: `pinniped-server`,
|
||||
Long: "pinniped-server provides a generic API for mapping an external\n" +
|
||||
"credential from somewhere to an internal credential to be used for\n" +
|
||||
"authenticating to the Kubernetes API.",
|
||||
RunE: func(cmd *cobra.Command, args []string) error { return a.runServer(ctx) },
|
||||
@@ -108,7 +108,7 @@ func addCommandlineFlagsToCommand(cmd *cobra.Command, app *App) {
|
||||
&app.configPath,
|
||||
"config",
|
||||
"c",
|
||||
"placeholder-name.yaml",
|
||||
"pinniped.yaml",
|
||||
"path to configuration file",
|
||||
)
|
||||
|
||||
@@ -166,7 +166,7 @@ func (a *App) runServer(ctx context.Context) error {
|
||||
// post start hook of the aggregated API server.
|
||||
startControllersFunc, err := controllermanager.PrepareControllers(
|
||||
serverInstallationNamespace,
|
||||
cfg.DiscoveryConfig.URL,
|
||||
cfg.DiscoveryInfo.URL,
|
||||
dynamicCertProvider,
|
||||
a.servingCertRotationThreshold.percentage,
|
||||
)
|
||||
@@ -233,7 +233,7 @@ func getAggregatedAPIServerConfig(
|
||||
) (*apiserver.Config, error) {
|
||||
recommendedOptions := genericoptions.NewRecommendedOptions(
|
||||
defaultEtcdPathPrefix,
|
||||
apiserver.Codecs.LegacyCodec(placeholderv1alpha1.SchemeGroupVersion),
|
||||
apiserver.Codecs.LegacyCodec(pinnipedv1alpha1.SchemeGroupVersion),
|
||||
// TODO we should check to see if all the other default settings are acceptable for us
|
||||
)
|
||||
recommendedOptions.Etcd = nil // turn off etcd storage because we don't need it yet
|
||||
|
||||
@@ -17,17 +17,17 @@ import (
|
||||
)
|
||||
|
||||
const knownGoodUsage = `
|
||||
placeholder-name-server provides a generic API for mapping an external
|
||||
pinniped-server provides a generic API for mapping an external
|
||||
credential from somewhere to an internal credential to be used for
|
||||
authenticating to the Kubernetes API.
|
||||
|
||||
Usage:
|
||||
placeholder-name-server [flags]
|
||||
pinniped-server [flags]
|
||||
|
||||
Flags:
|
||||
-c, --config string path to configuration file (default "placeholder-name.yaml")
|
||||
-c, --config string path to configuration file (default "pinniped.yaml")
|
||||
--downward-api-path string path to Downward API volume mount (default "/etc/podinfo")
|
||||
-h, --help help for placeholder-name-server
|
||||
-h, --help help for pinniped-server
|
||||
--log-flush-frequency duration Maximum number of seconds between log flushes (default 5s)
|
||||
--serving-cert-rotation-threshold percentage real number between 0 and 1 indicating percentage of lifetime before rotation of serving cert (default 70.00%)
|
||||
`
|
||||
@@ -51,7 +51,7 @@ func TestCommand(t *testing.T) {
|
||||
{
|
||||
name: "OneArgFails",
|
||||
args: []string{"tuna"},
|
||||
wantErr: `unknown command "tuna" for "placeholder-name-server"`,
|
||||
wantErr: `unknown command "tuna" for "pinniped-server"`,
|
||||
},
|
||||
{
|
||||
name: "ShortConfigFlagSucceeds",
|
||||
@@ -67,7 +67,7 @@ func TestCommand(t *testing.T) {
|
||||
"--config", "some/path/to/config.yaml",
|
||||
"tuna",
|
||||
},
|
||||
wantErr: `unknown command "tuna" for "placeholder-name-server"`,
|
||||
wantErr: `unknown command "tuna" for "pinniped-server"`,
|
||||
},
|
||||
{
|
||||
name: "PercentageIsNotRealNumber",
|
||||
|
||||
Reference in New Issue
Block a user