Update impersonatorconfig controller to use new CredentialIssuer update helper.
Signed-off-by: Margo Crawford <margaretc@vmware.com>
This commit is contained in:
parent
e4dd83887a
commit
ec25259901
@ -21,6 +21,7 @@ import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/clock"
|
||||
"k8s.io/apimachinery/pkg/util/errors"
|
||||
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
@ -152,8 +153,13 @@ func NewImpersonatorConfigController(
|
||||
func (c *impersonatorConfigController) Sync(syncCtx controllerlib.Context) error {
|
||||
plog.Debug("Starting impersonatorConfigController Sync")
|
||||
|
||||
strategy, err := c.doSync(syncCtx)
|
||||
// Load the CredentialIssuer that we'll update with status.
|
||||
credIssuer, err := c.credIssuerInformer.Lister().Get(c.credentialIssuerResourceName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not get CredentialIssuer to update: %w", err)
|
||||
}
|
||||
|
||||
strategy, err := c.doSync(syncCtx, credIssuer)
|
||||
if err != nil {
|
||||
strategy = &v1alpha1.CredentialIssuerStrategy{
|
||||
Type: v1alpha1.ImpersonationProxyStrategyType,
|
||||
@ -166,13 +172,12 @@ func (c *impersonatorConfigController) Sync(syncCtx controllerlib.Context) error
|
||||
c.clearSignerCA()
|
||||
}
|
||||
|
||||
updateStrategyErr := c.updateStrategy(syncCtx.Context, strategy)
|
||||
if updateStrategyErr != nil {
|
||||
plog.Error("error while updating the CredentialIssuer status", err)
|
||||
if err == nil {
|
||||
err = updateStrategyErr
|
||||
}
|
||||
}
|
||||
err = utilerrors.NewAggregate([]error{err, issuerconfig.Update(
|
||||
syncCtx.Context,
|
||||
c.pinnipedAPIClient,
|
||||
credIssuer,
|
||||
*strategy,
|
||||
)})
|
||||
|
||||
if err == nil {
|
||||
plog.Debug("Successfully finished impersonatorConfigController Sync")
|
||||
@ -196,10 +201,10 @@ type certNameInfo struct {
|
||||
clientEndpoint string
|
||||
}
|
||||
|
||||
func (c *impersonatorConfigController) doSync(syncCtx controllerlib.Context) (*v1alpha1.CredentialIssuerStrategy, error) {
|
||||
func (c *impersonatorConfigController) doSync(syncCtx controllerlib.Context, credIssuer *v1alpha1.CredentialIssuer) (*v1alpha1.CredentialIssuerStrategy, error) {
|
||||
ctx := syncCtx.Context
|
||||
|
||||
config, err := c.loadImpersonationProxyConfiguration()
|
||||
impersonationSpec, err := c.loadImpersonationProxyConfiguration(credIssuer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -217,7 +222,7 @@ func (c *impersonatorConfigController) doSync(syncCtx controllerlib.Context) (*v
|
||||
plog.Debug("Queried for control plane nodes", "foundControlPlaneNodes", hasControlPlaneNodes)
|
||||
}
|
||||
|
||||
if c.shouldHaveImpersonator(config) {
|
||||
if c.shouldHaveImpersonator(impersonationSpec) {
|
||||
if err = c.ensureImpersonatorIsStarted(syncCtx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -227,8 +232,8 @@ func (c *impersonatorConfigController) doSync(syncCtx controllerlib.Context) (*v
|
||||
}
|
||||
}
|
||||
|
||||
if c.shouldHaveLoadBalancer(config) {
|
||||
if err = c.ensureLoadBalancerIsStarted(ctx, config); err != nil {
|
||||
if c.shouldHaveLoadBalancer(impersonationSpec) {
|
||||
if err = c.ensureLoadBalancerIsStarted(ctx, impersonationSpec); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
@ -237,8 +242,8 @@ func (c *impersonatorConfigController) doSync(syncCtx controllerlib.Context) (*v
|
||||
}
|
||||
}
|
||||
|
||||
if c.shouldHaveClusterIPService(config) {
|
||||
if err = c.ensureClusterIPServiceIsStarted(ctx, config); err != nil {
|
||||
if c.shouldHaveClusterIPService(impersonationSpec) {
|
||||
if err = c.ensureClusterIPServiceIsStarted(ctx, impersonationSpec); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} // else { // TODO test stopping the cluster ip service
|
||||
@ -247,7 +252,7 @@ func (c *impersonatorConfigController) doSync(syncCtx controllerlib.Context) (*v
|
||||
// }
|
||||
//}
|
||||
|
||||
nameInfo, err := c.findDesiredTLSCertificateName(config)
|
||||
nameInfo, err := c.findDesiredTLSCertificateName(impersonationSpec)
|
||||
if err != nil {
|
||||
// Unexpected error while determining the name that should go into the certs, so clear any existing certs.
|
||||
c.tlsServingCertDynamicCertProvider.UnsetCertKeyContent()
|
||||
@ -255,7 +260,7 @@ func (c *impersonatorConfigController) doSync(syncCtx controllerlib.Context) (*v
|
||||
}
|
||||
|
||||
var impersonationCA *certauthority.CA
|
||||
if c.shouldHaveTLSSecret(config) {
|
||||
if c.shouldHaveTLSSecret(impersonationSpec) {
|
||||
if impersonationCA, err = c.ensureCASecretIsCreated(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -266,7 +271,7 @@ func (c *impersonatorConfigController) doSync(syncCtx controllerlib.Context) (*v
|
||||
return nil, err
|
||||
}
|
||||
|
||||
credentialIssuerStrategyResult := c.doSyncResult(nameInfo, config, impersonationCA)
|
||||
credentialIssuerStrategyResult := c.doSyncResult(nameInfo, impersonationSpec, impersonationCA)
|
||||
|
||||
if err = c.loadSignerCA(credentialIssuerStrategyResult.Status); err != nil {
|
||||
return nil, err
|
||||
@ -275,12 +280,7 @@ func (c *impersonatorConfigController) doSync(syncCtx controllerlib.Context) (*v
|
||||
return credentialIssuerStrategyResult, nil
|
||||
}
|
||||
|
||||
func (c *impersonatorConfigController) loadImpersonationProxyConfiguration() (*v1alpha1.ImpersonationProxySpec, error) {
|
||||
credIssuer, err := c.credIssuerInformer.Lister().Get(c.credentialIssuerResourceName)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get %s CredentialIssuer: %w", c.credentialIssuerResourceName, err)
|
||||
}
|
||||
|
||||
func (c *impersonatorConfigController) loadImpersonationProxyConfiguration(credIssuer *v1alpha1.CredentialIssuer) (*v1alpha1.ImpersonationProxySpec, error) {
|
||||
// Make a copy of the spec since we got this object from informer cache.
|
||||
spec := credIssuer.Spec.DeepCopy().ImpersonationProxy
|
||||
if spec == nil {
|
||||
@ -329,11 +329,6 @@ func (c *impersonatorConfigController) shouldHaveTLSSecret(config *v1alpha1.Impe
|
||||
return c.shouldHaveImpersonator(config)
|
||||
}
|
||||
|
||||
func (c *impersonatorConfigController) updateStrategy(ctx context.Context, strategy *v1alpha1.CredentialIssuerStrategy) error {
|
||||
// TODO use informer client rather than api client for reading
|
||||
return issuerconfig.UpdateStrategy(ctx, c.credentialIssuerResourceName, c.labels, c.pinnipedAPIClient, *strategy)
|
||||
}
|
||||
|
||||
func (c *impersonatorConfigController) loadBalancerExists() (bool, error) {
|
||||
_, err := c.servicesInformer.Lister().Services(c.namespace).Get(c.generatedLoadBalancerServiceName)
|
||||
notFound := k8serrors.IsNotFound(err)
|
||||
|
@ -554,14 +554,10 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
controllerlib.TestRunSynchronously(t, subject)
|
||||
}
|
||||
|
||||
var addCredentialIssuerToTracker = func(resourceName string, credIssuerSpec v1alpha1.CredentialIssuerSpec, client *pinnipedfake.Clientset) {
|
||||
t.Logf("adding CredentialIssuer %s to informer clientset", resourceName)
|
||||
r.NoError(client.Tracker().Add(&v1alpha1.CredentialIssuer{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: resourceName,
|
||||
},
|
||||
Spec: credIssuerSpec,
|
||||
}))
|
||||
var addCredentialIssuerToTrackers = func(credIssuer v1alpha1.CredentialIssuer, informerClient *pinnipedfake.Clientset, mainClient *pinnipedfake.Clientset) {
|
||||
t.Logf("adding CredentialIssuer %s to informer and main clientsets", credIssuer.Name)
|
||||
r.NoError(informerClient.Tracker().Add(&credIssuer))
|
||||
r.NoError(mainClient.Tracker().Add(&credIssuer))
|
||||
}
|
||||
|
||||
var newSecretWithData = func(resourceName string, data map[string][]byte) *corev1.Secret {
|
||||
@ -856,7 +852,6 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
// As long as we get the final result that we wanted then we are happy for the purposes
|
||||
// of this test.
|
||||
credentialIssuer := getCredentialIssuer()
|
||||
r.Equal(labels, credentialIssuer.Labels)
|
||||
r.Equal([]v1alpha1.CredentialIssuerStrategy{expectedStrategy}, credentialIssuer.Status.Strategies)
|
||||
}
|
||||
|
||||
@ -1023,7 +1018,7 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
|
||||
it("errors and does nothing else", func() {
|
||||
startInformersAndController()
|
||||
r.EqualError(runControllerSync(), "failed to get some-credential-issuer-resource-name CredentialIssuer: credentialissuer.config.concierge.pinniped.dev \"some-credential-issuer-resource-name\" not found")
|
||||
r.EqualError(runControllerSync(), `could not get CredentialIssuer to update: credentialissuer.config.concierge.pinniped.dev "some-credential-issuer-resource-name" not found`)
|
||||
requireTLSServerWasNeverStarted()
|
||||
r.Len(kubeAPIClient.Actions(), 0)
|
||||
})
|
||||
@ -1033,7 +1028,9 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
when("the configuration is auto mode with an endpoint and service type none", func() {
|
||||
it.Before(func() {
|
||||
addSecretToTrackers(signingCASecret, kubeInformerClient)
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
addCredentialIssuerToTrackers(v1alpha1.CredentialIssuer{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: credentialIssuerResourceName},
|
||||
Spec: v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeAuto,
|
||||
ExternalEndpoint: localhostIP,
|
||||
@ -1041,7 +1038,8 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
Type: v1alpha1.ImpersonationProxyServiceTypeNone,
|
||||
},
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
},
|
||||
}, pinnipedInformerClient, pinnipedAPIClient)
|
||||
})
|
||||
|
||||
when("there are visible control plane nodes", func() {
|
||||
@ -1082,11 +1080,14 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
when("the configuration is auto mode", func() {
|
||||
it.Before(func() {
|
||||
addSecretToTrackers(signingCASecret, kubeInformerClient)
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
addCredentialIssuerToTrackers(v1alpha1.CredentialIssuer{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: credentialIssuerResourceName},
|
||||
Spec: v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeAuto,
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
},
|
||||
}, pinnipedInformerClient, pinnipedAPIClient)
|
||||
})
|
||||
|
||||
when("there are visible control plane nodes", func() {
|
||||
@ -1380,11 +1381,14 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
when("the configuration is disabled mode", func() {
|
||||
it.Before(func() {
|
||||
addSecretToTrackers(signingCASecret, kubeInformerClient)
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
addCredentialIssuerToTrackers(v1alpha1.CredentialIssuer{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: credentialIssuerResourceName},
|
||||
Spec: v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeDisabled,
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
},
|
||||
}, pinnipedInformerClient, pinnipedAPIClient)
|
||||
addNodeWithRoleToTracker("worker", kubeAPIClient)
|
||||
})
|
||||
|
||||
@ -1405,11 +1409,14 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
})
|
||||
when("no load balancer", func() {
|
||||
it.Before(func() {
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
addCredentialIssuerToTrackers(v1alpha1.CredentialIssuer{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: credentialIssuerResourceName},
|
||||
Spec: v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeEnabled,
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
},
|
||||
}, pinnipedInformerClient, pinnipedAPIClient)
|
||||
addNodeWithRoleToTracker("control-plane", kubeAPIClient)
|
||||
})
|
||||
|
||||
@ -1436,11 +1443,14 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
|
||||
when("a loadbalancer already exists", func() {
|
||||
it.Before(func() {
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
addCredentialIssuerToTrackers(v1alpha1.CredentialIssuer{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: credentialIssuerResourceName},
|
||||
Spec: v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeEnabled,
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
},
|
||||
}, pinnipedInformerClient, pinnipedAPIClient)
|
||||
addNodeWithRoleToTracker("worker", kubeAPIClient)
|
||||
addLoadBalancerServiceToTracker(loadBalancerServiceName, kubeInformerClient)
|
||||
addLoadBalancerServiceToTracker(loadBalancerServiceName, kubeAPIClient)
|
||||
@ -1469,11 +1479,14 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
when("a load balancer and a secret already exists", func() {
|
||||
var caCrt []byte
|
||||
it.Before(func() {
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
addCredentialIssuerToTrackers(v1alpha1.CredentialIssuer{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: credentialIssuerResourceName},
|
||||
Spec: v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeEnabled,
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
},
|
||||
}, pinnipedInformerClient, pinnipedAPIClient)
|
||||
addNodeWithRoleToTracker("worker", kubeAPIClient)
|
||||
ca := newCA()
|
||||
caSecret := newActualCASecret(ca, caSecretName)
|
||||
@ -1499,7 +1512,9 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
when("credentialissuer has service type loadbalancer and custom annotations", func() {
|
||||
annotations := map[string]string{"some-annotation-key": "some-annotation-value"}
|
||||
it.Before(func() {
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
addCredentialIssuerToTrackers(v1alpha1.CredentialIssuer{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: credentialIssuerResourceName},
|
||||
Spec: v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeEnabled,
|
||||
Service: v1alpha1.ImpersonationProxyServiceSpec{
|
||||
@ -1507,7 +1522,8 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
Annotations: annotations,
|
||||
},
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
},
|
||||
}, pinnipedInformerClient, pinnipedAPIClient)
|
||||
addNodeWithRoleToTracker("worker", kubeAPIClient)
|
||||
})
|
||||
|
||||
@ -1528,7 +1544,9 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
when("the CredentialIssuer has a hostname specified and service type none", func() {
|
||||
const fakeHostname = "fake.example.com"
|
||||
it.Before(func() {
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
addCredentialIssuerToTrackers(v1alpha1.CredentialIssuer{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: credentialIssuerResourceName},
|
||||
Spec: v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeEnabled,
|
||||
ExternalEndpoint: fakeHostname,
|
||||
@ -1536,7 +1554,8 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
Type: v1alpha1.ImpersonationProxyServiceTypeNone,
|
||||
},
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
},
|
||||
}, pinnipedInformerClient, pinnipedAPIClient)
|
||||
addNodeWithRoleToTracker("worker", kubeAPIClient)
|
||||
})
|
||||
|
||||
@ -1557,7 +1576,9 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
when("the CredentialIssuer has a hostname specified and service type loadbalancer", func() {
|
||||
const fakeHostname = "fake.example.com"
|
||||
it.Before(func() {
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
addCredentialIssuerToTrackers(v1alpha1.CredentialIssuer{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: credentialIssuerResourceName},
|
||||
Spec: v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeEnabled,
|
||||
ExternalEndpoint: fakeHostname,
|
||||
@ -1565,7 +1586,8 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
Type: v1alpha1.ImpersonationProxyServiceTypeLoadBalancer,
|
||||
},
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
},
|
||||
}, pinnipedInformerClient, pinnipedAPIClient)
|
||||
addNodeWithRoleToTracker("worker", kubeAPIClient)
|
||||
})
|
||||
|
||||
@ -1586,14 +1608,17 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
|
||||
when("the CredentialIssuer has a hostname specified and service type clusterip", func() {
|
||||
it.Before(func() {
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
addCredentialIssuerToTrackers(v1alpha1.CredentialIssuer{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: credentialIssuerResourceName},
|
||||
Spec: v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeEnabled,
|
||||
Service: v1alpha1.ImpersonationProxyServiceSpec{
|
||||
Type: v1alpha1.ImpersonationProxyServiceTypeClusterIP,
|
||||
},
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
},
|
||||
}, pinnipedInformerClient, pinnipedAPIClient)
|
||||
addNodeWithRoleToTracker("worker", kubeAPIClient)
|
||||
})
|
||||
|
||||
@ -1614,7 +1639,9 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
when("the CredentialIssuer has a endpoint which is an IP address with a port", func() {
|
||||
const fakeIPWithPort = "127.0.0.1:3000"
|
||||
it.Before(func() {
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
addCredentialIssuerToTrackers(v1alpha1.CredentialIssuer{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: credentialIssuerResourceName},
|
||||
Spec: v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeEnabled,
|
||||
ExternalEndpoint: fakeIPWithPort,
|
||||
@ -1622,7 +1649,8 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
Type: v1alpha1.ImpersonationProxyServiceTypeNone,
|
||||
},
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
},
|
||||
}, pinnipedInformerClient, pinnipedAPIClient)
|
||||
addNodeWithRoleToTracker("worker", kubeAPIClient)
|
||||
})
|
||||
|
||||
@ -1643,7 +1671,9 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
when("the CredentialIssuer has a endpoint which is a hostname with a port, service type none", func() {
|
||||
const fakeHostnameWithPort = "fake.example.com:3000"
|
||||
it.Before(func() {
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
addCredentialIssuerToTrackers(v1alpha1.CredentialIssuer{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: credentialIssuerResourceName},
|
||||
Spec: v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeEnabled,
|
||||
ExternalEndpoint: fakeHostnameWithPort,
|
||||
@ -1651,7 +1681,8 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
Type: v1alpha1.ImpersonationProxyServiceTypeNone,
|
||||
},
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
},
|
||||
}, pinnipedInformerClient, pinnipedAPIClient)
|
||||
addNodeWithRoleToTracker("worker", kubeAPIClient)
|
||||
})
|
||||
|
||||
@ -1672,7 +1703,9 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
when("the CredentialIssuer has a endpoint which is a hostname with a port, service type loadbalancer with loadbalancerip", func() {
|
||||
const fakeHostnameWithPort = "fake.example.com:3000"
|
||||
it.Before(func() {
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
addCredentialIssuerToTrackers(v1alpha1.CredentialIssuer{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: credentialIssuerResourceName},
|
||||
Spec: v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeEnabled,
|
||||
ExternalEndpoint: fakeHostnameWithPort,
|
||||
@ -1681,7 +1714,8 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
LoadBalancerIP: localhostIP,
|
||||
},
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
},
|
||||
}, pinnipedInformerClient, pinnipedAPIClient)
|
||||
addNodeWithRoleToTracker("worker", kubeAPIClient)
|
||||
})
|
||||
|
||||
@ -1725,7 +1759,10 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
}
|
||||
|
||||
it.Before(func() {
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, ipAddressConfig, pinnipedInformerClient)
|
||||
addCredentialIssuerToTrackers(v1alpha1.CredentialIssuer{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: credentialIssuerResourceName},
|
||||
Spec: ipAddressConfig,
|
||||
}, pinnipedInformerClient, pinnipedAPIClient)
|
||||
addNodeWithRoleToTracker("worker", kubeAPIClient)
|
||||
})
|
||||
|
||||
@ -1779,7 +1816,9 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
when("the TLS cert goes missing and needs to be recreated, e.g. when a user manually deleted it", func() {
|
||||
const fakeHostname = "fake.example.com"
|
||||
it.Before(func() {
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
addCredentialIssuerToTrackers(v1alpha1.CredentialIssuer{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: credentialIssuerResourceName},
|
||||
Spec: v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeEnabled,
|
||||
ExternalEndpoint: fakeHostname,
|
||||
@ -1787,7 +1826,8 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
Type: v1alpha1.ImpersonationProxyServiceTypeNone,
|
||||
},
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
},
|
||||
}, pinnipedInformerClient, pinnipedAPIClient)
|
||||
addNodeWithRoleToTracker("worker", kubeAPIClient)
|
||||
startInformersAndController()
|
||||
})
|
||||
@ -1824,7 +1864,9 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
when("the CA cert goes missing and needs to be recreated, e.g. when a user manually deleted it", func() {
|
||||
const fakeHostname = "fake.example.com"
|
||||
it.Before(func() {
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
addCredentialIssuerToTrackers(v1alpha1.CredentialIssuer{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: credentialIssuerResourceName},
|
||||
Spec: v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeEnabled,
|
||||
ExternalEndpoint: fakeHostname,
|
||||
@ -1832,7 +1874,8 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
Type: v1alpha1.ImpersonationProxyServiceTypeNone,
|
||||
},
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
},
|
||||
}, pinnipedInformerClient, pinnipedAPIClient)
|
||||
addNodeWithRoleToTracker("worker", kubeAPIClient)
|
||||
startInformersAndController()
|
||||
})
|
||||
@ -1872,7 +1915,9 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
const fakeHostname = "fake.example.com"
|
||||
var caCrt []byte
|
||||
it.Before(func() {
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
addCredentialIssuerToTrackers(v1alpha1.CredentialIssuer{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: credentialIssuerResourceName},
|
||||
Spec: v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeEnabled,
|
||||
ExternalEndpoint: fakeHostname,
|
||||
@ -1880,7 +1925,8 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
Type: v1alpha1.ImpersonationProxyServiceTypeNone,
|
||||
},
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
},
|
||||
}, pinnipedInformerClient, pinnipedAPIClient)
|
||||
addNodeWithRoleToTracker("worker", kubeAPIClient)
|
||||
startInformersAndController()
|
||||
r.NoError(runControllerSync())
|
||||
@ -1944,11 +1990,14 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
when("the configuration switches from enabled to disabled mode", func() {
|
||||
it.Before(func() {
|
||||
addSecretToTrackers(signingCASecret, kubeInformerClient)
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
addCredentialIssuerToTrackers(v1alpha1.CredentialIssuer{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: credentialIssuerResourceName},
|
||||
Spec: v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeEnabled,
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
},
|
||||
}, pinnipedInformerClient, pinnipedAPIClient)
|
||||
addNodeWithRoleToTracker("worker", kubeAPIClient)
|
||||
})
|
||||
|
||||
@ -2004,7 +2053,9 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
when("the endpoint and mode switch from specified with no service, to not specified, to specified again", func() {
|
||||
it.Before(func() {
|
||||
addSecretToTrackers(signingCASecret, kubeInformerClient)
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
addCredentialIssuerToTrackers(v1alpha1.CredentialIssuer{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: credentialIssuerResourceName},
|
||||
Spec: v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeEnabled,
|
||||
ExternalEndpoint: localhostIP,
|
||||
@ -2012,7 +2063,8 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
Type: v1alpha1.ImpersonationProxyServiceTypeNone,
|
||||
},
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
},
|
||||
}, pinnipedInformerClient, pinnipedAPIClient)
|
||||
addNodeWithRoleToTracker("worker", kubeAPIClient)
|
||||
})
|
||||
|
||||
@ -2099,7 +2151,9 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
when("requesting a load balancer via CredentialIssuer, then updating the annotations", func() {
|
||||
it.Before(func() {
|
||||
addSecretToTrackers(signingCASecret, kubeInformerClient)
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
addCredentialIssuerToTrackers(v1alpha1.CredentialIssuer{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: credentialIssuerResourceName},
|
||||
Spec: v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeEnabled,
|
||||
ExternalEndpoint: localhostIP,
|
||||
@ -2107,7 +2161,8 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
Type: v1alpha1.ImpersonationProxyServiceTypeLoadBalancer,
|
||||
},
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
},
|
||||
}, pinnipedInformerClient, pinnipedAPIClient)
|
||||
addNodeWithRoleToTracker("worker", kubeAPIClient)
|
||||
})
|
||||
|
||||
@ -2157,7 +2212,9 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
when("requesting a load balancer via CredentialIssuer, then adding a static loadBalancerIP to the spec", func() {
|
||||
it.Before(func() {
|
||||
addSecretToTrackers(signingCASecret, kubeInformerClient)
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
addCredentialIssuerToTrackers(v1alpha1.CredentialIssuer{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: credentialIssuerResourceName},
|
||||
Spec: v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeEnabled,
|
||||
ExternalEndpoint: localhostIP,
|
||||
@ -2165,7 +2222,8 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
Type: v1alpha1.ImpersonationProxyServiceTypeLoadBalancer,
|
||||
},
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
},
|
||||
}, pinnipedInformerClient, pinnipedAPIClient)
|
||||
addNodeWithRoleToTracker("worker", kubeAPIClient)
|
||||
})
|
||||
|
||||
@ -2217,11 +2275,14 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
it.Before(func() {
|
||||
addSecretToTrackers(signingCASecret, kubeInformerClient)
|
||||
addNodeWithRoleToTracker("worker", kubeAPIClient)
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
addCredentialIssuerToTrackers(v1alpha1.CredentialIssuer{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: credentialIssuerResourceName},
|
||||
Spec: v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeAuto,
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
},
|
||||
}, pinnipedInformerClient, pinnipedAPIClient)
|
||||
})
|
||||
|
||||
it("only starts the impersonator once and only lists the cluster's nodes once", func() {
|
||||
@ -2335,15 +2396,19 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
|
||||
it.Before(func() {
|
||||
addSecretToTrackers(signingCASecret, kubeInformerClient)
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
addCredentialIssuerToTrackers(v1alpha1.CredentialIssuer{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: credentialIssuerResourceName},
|
||||
Spec: v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeAuto,
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
r.NoError(pinnipedAPIClient.Tracker().Add(&v1alpha1.CredentialIssuer{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: credentialIssuerResourceName},
|
||||
Status: v1alpha1.CredentialIssuerStatus{Strategies: []v1alpha1.CredentialIssuerStrategy{preExistingStrategy}},
|
||||
}))
|
||||
},
|
||||
Status: v1alpha1.CredentialIssuerStatus{
|
||||
Strategies: []v1alpha1.CredentialIssuerStrategy{
|
||||
preExistingStrategy,
|
||||
},
|
||||
},
|
||||
}, pinnipedInformerClient, pinnipedAPIClient)
|
||||
addNodeWithRoleToTracker("worker", kubeAPIClient)
|
||||
})
|
||||
|
||||
@ -2362,11 +2427,14 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
|
||||
when("getting the control plane nodes returns an error, e.g. when there are no nodes", func() {
|
||||
it("returns an error", func() {
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
addCredentialIssuerToTrackers(v1alpha1.CredentialIssuer{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: credentialIssuerResourceName},
|
||||
Spec: v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeAuto,
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
},
|
||||
}, pinnipedInformerClient, pinnipedAPIClient)
|
||||
startInformersAndController()
|
||||
r.EqualError(runControllerSync(), "no nodes found")
|
||||
requireCredentialIssuer(newErrorStrategy("no nodes found"))
|
||||
@ -2379,11 +2447,14 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
it.Before(func() {
|
||||
addNodeWithRoleToTracker("worker", kubeAPIClient)
|
||||
impersonatorFuncReturnedFuncError = errors.New("some immediate impersonator startup error")
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
addCredentialIssuerToTrackers(v1alpha1.CredentialIssuer{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: credentialIssuerResourceName},
|
||||
Spec: v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeAuto,
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
},
|
||||
}, pinnipedInformerClient, pinnipedAPIClient)
|
||||
})
|
||||
|
||||
it("causes an immediate resync, returns an error on that next sync, and then restarts the server in a following sync", func() {
|
||||
@ -2439,11 +2510,14 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
when("the impersonator server dies for no apparent reason after running for a while", func() {
|
||||
it.Before(func() {
|
||||
addNodeWithRoleToTracker("worker", kubeAPIClient)
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
addCredentialIssuerToTrackers(v1alpha1.CredentialIssuer{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: credentialIssuerResourceName},
|
||||
Spec: v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeAuto,
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
},
|
||||
}, pinnipedInformerClient, pinnipedAPIClient)
|
||||
})
|
||||
|
||||
it("causes an immediate resync, returns an error on that next sync, and then restarts the server in a following sync", func() {
|
||||
@ -2495,9 +2569,12 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
|
||||
when("the CredentialIssuer has nil impersonation spec", func() {
|
||||
it.Before(func() {
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
addCredentialIssuerToTrackers(v1alpha1.CredentialIssuer{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: credentialIssuerResourceName},
|
||||
Spec: v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: nil,
|
||||
}, pinnipedInformerClient)
|
||||
},
|
||||
}, pinnipedInformerClient, pinnipedAPIClient)
|
||||
})
|
||||
|
||||
it("returns an error", func() {
|
||||
@ -2512,11 +2589,14 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
|
||||
when("the CredentialIssuer has invalid mode", func() {
|
||||
it.Before(func() {
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
addCredentialIssuerToTrackers(v1alpha1.CredentialIssuer{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: credentialIssuerResourceName},
|
||||
Spec: v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: "not-valid",
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
},
|
||||
}, pinnipedInformerClient, pinnipedAPIClient)
|
||||
})
|
||||
|
||||
it("returns an error", func() {
|
||||
@ -2531,14 +2611,17 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
|
||||
when("the CredentialIssuer has invalid service type", func() {
|
||||
it.Before(func() {
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
addCredentialIssuerToTrackers(v1alpha1.CredentialIssuer{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: credentialIssuerResourceName},
|
||||
Spec: v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeEnabled,
|
||||
Service: v1alpha1.ImpersonationProxyServiceSpec{
|
||||
Type: "not-valid",
|
||||
},
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
},
|
||||
}, pinnipedInformerClient, pinnipedAPIClient)
|
||||
})
|
||||
|
||||
it("returns an error", func() {
|
||||
@ -2553,14 +2636,17 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
|
||||
when("the CredentialIssuer has invalid LoadBalancerIP", func() {
|
||||
it.Before(func() {
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
addCredentialIssuerToTrackers(v1alpha1.CredentialIssuer{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: credentialIssuerResourceName},
|
||||
Spec: v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeEnabled,
|
||||
Service: v1alpha1.ImpersonationProxyServiceSpec{
|
||||
LoadBalancerIP: "invalid-ip-address",
|
||||
},
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
},
|
||||
}, pinnipedInformerClient, pinnipedAPIClient)
|
||||
})
|
||||
|
||||
it("returns an error", func() {
|
||||
@ -2575,12 +2661,15 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
|
||||
when("the CredentialIssuer has invalid ExternalEndpoint", func() {
|
||||
it.Before(func() {
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
addCredentialIssuerToTrackers(v1alpha1.CredentialIssuer{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: credentialIssuerResourceName},
|
||||
Spec: v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeEnabled,
|
||||
ExternalEndpoint: "[invalid",
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
},
|
||||
}, pinnipedInformerClient, pinnipedAPIClient)
|
||||
})
|
||||
|
||||
it("returns an error", func() {
|
||||
@ -2599,11 +2688,14 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
kubeAPIClient.PrependReactor("create", "services", func(action coretesting.Action) (handled bool, ret runtime.Object, err error) {
|
||||
return true, nil, fmt.Errorf("error on create")
|
||||
})
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
addCredentialIssuerToTrackers(v1alpha1.CredentialIssuer{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: credentialIssuerResourceName},
|
||||
Spec: v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeAuto,
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
},
|
||||
}, pinnipedInformerClient, pinnipedAPIClient)
|
||||
})
|
||||
|
||||
it("returns an error", func() {
|
||||
@ -2617,7 +2709,9 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
|
||||
when("there is an error creating the tls secret", func() {
|
||||
it.Before(func() {
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
addCredentialIssuerToTrackers(v1alpha1.CredentialIssuer{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: credentialIssuerResourceName},
|
||||
Spec: v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeEnabled,
|
||||
ExternalEndpoint: "example.com",
|
||||
@ -2625,7 +2719,8 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
Type: v1alpha1.ImpersonationProxyServiceTypeNone,
|
||||
},
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
},
|
||||
}, pinnipedInformerClient, pinnipedAPIClient)
|
||||
addNodeWithRoleToTracker("control-plane", kubeAPIClient)
|
||||
kubeAPIClient.PrependReactor("create", "secrets", func(action coretesting.Action) (handled bool, ret runtime.Object, err error) {
|
||||
createdSecret := action.(coretesting.CreateAction).GetObject().(*corev1.Secret)
|
||||
@ -2651,7 +2746,9 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
|
||||
when("there is an error creating the CA secret", func() {
|
||||
it.Before(func() {
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
addCredentialIssuerToTrackers(v1alpha1.CredentialIssuer{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: credentialIssuerResourceName},
|
||||
Spec: v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeEnabled,
|
||||
ExternalEndpoint: "example.com",
|
||||
@ -2659,7 +2756,8 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
Type: v1alpha1.ImpersonationProxyServiceTypeNone,
|
||||
},
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
},
|
||||
}, pinnipedInformerClient, pinnipedAPIClient)
|
||||
addNodeWithRoleToTracker("control-plane", kubeAPIClient)
|
||||
kubeAPIClient.PrependReactor("create", "secrets", func(action coretesting.Action) (handled bool, ret runtime.Object, err error) {
|
||||
createdSecret := action.(coretesting.CreateAction).GetObject().(*corev1.Secret)
|
||||
@ -2685,7 +2783,9 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
when("the CA secret exists but is invalid while the TLS secret needs to be created", func() {
|
||||
it.Before(func() {
|
||||
addNodeWithRoleToTracker("control-plane", kubeAPIClient)
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
addCredentialIssuerToTrackers(v1alpha1.CredentialIssuer{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: credentialIssuerResourceName},
|
||||
Spec: v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeEnabled,
|
||||
ExternalEndpoint: "example.com",
|
||||
@ -2693,7 +2793,8 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
Type: v1alpha1.ImpersonationProxyServiceTypeNone,
|
||||
},
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
},
|
||||
}, pinnipedInformerClient, pinnipedAPIClient)
|
||||
addSecretToTrackers(newEmptySecret(caSecretName), kubeAPIClient, kubeInformerClient)
|
||||
})
|
||||
|
||||
@ -2715,11 +2816,14 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
addLoadBalancerServiceToTracker(loadBalancerServiceName, kubeInformerClient)
|
||||
addLoadBalancerServiceToTracker(loadBalancerServiceName, kubeAPIClient)
|
||||
addSecretToTrackers(newEmptySecret(tlsSecretName), kubeAPIClient, kubeInformerClient)
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
addCredentialIssuerToTrackers(v1alpha1.CredentialIssuer{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: credentialIssuerResourceName},
|
||||
Spec: v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeAuto,
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
},
|
||||
}, pinnipedInformerClient, pinnipedAPIClient)
|
||||
startInformersAndController()
|
||||
kubeAPIClient.PrependReactor("delete", "secrets", func(action coretesting.Action) (handled bool, ret runtime.Object, err error) {
|
||||
return true, nil, fmt.Errorf("error on delete")
|
||||
@ -2742,11 +2846,14 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
it.Before(func() {
|
||||
addNodeWithRoleToTracker("control-plane", kubeAPIClient)
|
||||
addSecretToTrackers(newEmptySecret(tlsSecretName), kubeInformerClient)
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
addCredentialIssuerToTrackers(v1alpha1.CredentialIssuer{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: credentialIssuerResourceName},
|
||||
Spec: v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeDisabled,
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
},
|
||||
}, pinnipedInformerClient, pinnipedAPIClient)
|
||||
})
|
||||
|
||||
it("does not pass the not found error through", func() {
|
||||
@ -2764,7 +2871,9 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
when("the PEM formatted data in the TLS Secret is not a valid cert", func() {
|
||||
it.Before(func() {
|
||||
addSecretToTrackers(signingCASecret, kubeInformerClient)
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
addCredentialIssuerToTrackers(v1alpha1.CredentialIssuer{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: credentialIssuerResourceName},
|
||||
Spec: v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeEnabled,
|
||||
ExternalEndpoint: localhostIP,
|
||||
@ -2772,7 +2881,8 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
Type: v1alpha1.ImpersonationProxyServiceTypeNone,
|
||||
},
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
},
|
||||
}, pinnipedInformerClient, pinnipedAPIClient)
|
||||
addNodeWithRoleToTracker("worker", kubeAPIClient)
|
||||
tlsSecret := &corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
@ -2827,11 +2937,14 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
var caCrt []byte
|
||||
it.Before(func() {
|
||||
addSecretToTrackers(signingCASecret, kubeInformerClient)
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
addCredentialIssuerToTrackers(v1alpha1.CredentialIssuer{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: credentialIssuerResourceName},
|
||||
Spec: v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeEnabled,
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
},
|
||||
}, pinnipedInformerClient, pinnipedAPIClient)
|
||||
addNodeWithRoleToTracker("worker", kubeAPIClient)
|
||||
ca := newCA()
|
||||
caSecret := newActualCASecret(ca, caSecretName)
|
||||
@ -2890,11 +3003,14 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
addSecretToTrackers(tlsSecret, kubeAPIClient, kubeInformerClient)
|
||||
addLoadBalancerServiceWithIngressToTracker(loadBalancerServiceName, []corev1.LoadBalancerIngress{{IP: localhostIP}}, kubeInformerClient)
|
||||
addLoadBalancerServiceWithIngressToTracker(loadBalancerServiceName, []corev1.LoadBalancerIngress{{IP: localhostIP}}, kubeAPIClient)
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
addCredentialIssuerToTrackers(v1alpha1.CredentialIssuer{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: credentialIssuerResourceName},
|
||||
Spec: v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeAuto,
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
},
|
||||
}, pinnipedInformerClient, pinnipedAPIClient)
|
||||
})
|
||||
|
||||
it("deletes the invalid certs, creates new certs, and starts the impersonator", func() {
|
||||
@ -2935,19 +3051,22 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
it.Before(func() {
|
||||
addSecretToTrackers(signingCASecret, kubeInformerClient)
|
||||
addNodeWithRoleToTracker("worker", kubeAPIClient)
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
addCredentialIssuerToTrackers(v1alpha1.CredentialIssuer{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: credentialIssuerResourceName},
|
||||
Spec: v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeAuto,
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
pinnipedAPIClient.PrependReactor("create", "credentialissuers", func(action coretesting.Action) (handled bool, ret runtime.Object, err error) {
|
||||
return true, nil, fmt.Errorf("error on create")
|
||||
},
|
||||
}, pinnipedInformerClient, pinnipedAPIClient)
|
||||
pinnipedAPIClient.PrependReactor("update", "credentialissuers", func(action coretesting.Action) (handled bool, ret runtime.Object, err error) {
|
||||
return true, nil, fmt.Errorf("error on update")
|
||||
})
|
||||
})
|
||||
|
||||
it("returns the error", func() {
|
||||
startInformersAndController()
|
||||
r.EqualError(runControllerSync(), "could not create or update credentialissuer: create failed: error on create")
|
||||
r.EqualError(runControllerSync(), "failed to update CredentialIssuer status: error on update")
|
||||
})
|
||||
|
||||
when("there is also a more fundamental error while starting the impersonator", func() {
|
||||
@ -2957,9 +3076,9 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
})
|
||||
})
|
||||
|
||||
it("returns the more fundamental error instead of the CredentialIssuer error", func() {
|
||||
it("returns both errors", func() {
|
||||
startInformersAndController()
|
||||
r.EqualError(runControllerSync(), "error on service creation")
|
||||
r.EqualError(runControllerSync(), "[error on service creation, failed to update CredentialIssuer status: error on update]")
|
||||
})
|
||||
})
|
||||
})
|
||||
@ -2967,7 +3086,9 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
when("the impersonator is ready but there is a problem with the signing secret, which should be created by another controller", func() {
|
||||
const fakeHostname = "foo.example.com"
|
||||
it.Before(func() {
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
addCredentialIssuerToTrackers(v1alpha1.CredentialIssuer{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: credentialIssuerResourceName},
|
||||
Spec: v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeEnabled,
|
||||
ExternalEndpoint: fakeHostname,
|
||||
@ -2975,7 +3096,8 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
Type: v1alpha1.ImpersonationProxyServiceTypeNone,
|
||||
},
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
},
|
||||
}, pinnipedInformerClient, pinnipedAPIClient)
|
||||
addNodeWithRoleToTracker("worker", kubeAPIClient)
|
||||
})
|
||||
|
||||
@ -3059,7 +3181,9 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
when("the impersonator is enabled but the service type is none and the external endpoint is empty", func() {
|
||||
it.Before(func() {
|
||||
addSecretToTrackers(signingCASecret, kubeInformerClient)
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
addCredentialIssuerToTrackers(v1alpha1.CredentialIssuer{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: credentialIssuerResourceName},
|
||||
Spec: v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeEnabled,
|
||||
ExternalEndpoint: "",
|
||||
@ -3067,7 +3191,8 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
Type: v1alpha1.ImpersonationProxyServiceTypeNone,
|
||||
},
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
},
|
||||
}, pinnipedInformerClient, pinnipedAPIClient)
|
||||
addNodeWithRoleToTracker("control-plane", kubeAPIClient)
|
||||
})
|
||||
|
||||
@ -3078,7 +3203,7 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
})
|
||||
})
|
||||
})
|
||||
}, spec.Report(report.Terminal{}))
|
||||
}, spec.Report(report.Terminal{})) // TODO: replace the Parallel() call here
|
||||
}
|
||||
|
||||
type testQueue struct {
|
||||
|
@ -1,85 +0,0 @@
|
||||
// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package issuerconfig
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/equality"
|
||||
|
||||
k8serrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/util/retry"
|
||||
|
||||
configv1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/config/v1alpha1"
|
||||
pinnipedclientset "go.pinniped.dev/generated/latest/client/concierge/clientset/versioned"
|
||||
)
|
||||
|
||||
func CreateOrUpdateCredentialIssuerStatus(
|
||||
ctx context.Context,
|
||||
credentialIssuerResourceName string,
|
||||
credentialIssuerLabels map[string]string,
|
||||
pinnipedClient pinnipedclientset.Interface,
|
||||
applyUpdatesToCredentialIssuerFunc func(configToUpdate *configv1alpha1.CredentialIssuerStatus),
|
||||
) error {
|
||||
err := retry.RetryOnConflict(retry.DefaultRetry, func() error {
|
||||
existingCredentialIssuer, err := pinnipedClient.
|
||||
ConfigV1alpha1().
|
||||
CredentialIssuers().
|
||||
Get(ctx, credentialIssuerResourceName, metav1.GetOptions{})
|
||||
|
||||
notFound := k8serrors.IsNotFound(err)
|
||||
if err != nil && !notFound {
|
||||
return fmt.Errorf("get failed: %w", err)
|
||||
}
|
||||
|
||||
credentialIssuersClient := pinnipedClient.ConfigV1alpha1().CredentialIssuers()
|
||||
|
||||
if notFound {
|
||||
// create an empty credential issuer
|
||||
minCredentialIssuer := minimalValidCredentialIssuer(credentialIssuerResourceName, credentialIssuerLabels)
|
||||
|
||||
newCredentialIssuer, err := credentialIssuersClient.Create(ctx, minCredentialIssuer, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("create failed: %w", err)
|
||||
}
|
||||
|
||||
existingCredentialIssuer = newCredentialIssuer
|
||||
}
|
||||
|
||||
// check to see if we need to update the status
|
||||
credentialIssuer := existingCredentialIssuer.DeepCopy()
|
||||
applyUpdatesToCredentialIssuerFunc(&credentialIssuer.Status)
|
||||
|
||||
if equality.Semantic.DeepEqual(existingCredentialIssuer, credentialIssuer) {
|
||||
// Nothing interesting would change as a result of this update, so skip it
|
||||
return nil
|
||||
}
|
||||
|
||||
if _, err := credentialIssuersClient.UpdateStatus(ctx, credentialIssuer, metav1.UpdateOptions{}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not create or update credentialissuer: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func minimalValidCredentialIssuer(
|
||||
credentialIssuerName string,
|
||||
credentialIssuerLabels map[string]string,
|
||||
) *configv1alpha1.CredentialIssuer {
|
||||
return &configv1alpha1.CredentialIssuer{
|
||||
TypeMeta: metav1.TypeMeta{},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: credentialIssuerName,
|
||||
Labels: credentialIssuerLabels,
|
||||
},
|
||||
}
|
||||
}
|
@ -1,301 +0,0 @@
|
||||
// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package issuerconfig
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/sclevine/spec"
|
||||
"github.com/sclevine/spec/report"
|
||||
"github.com/stretchr/testify/require"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
coretesting "k8s.io/client-go/testing"
|
||||
apiregistrationv1 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1"
|
||||
|
||||
configv1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/config/v1alpha1"
|
||||
pinnipedfake "go.pinniped.dev/generated/latest/client/concierge/clientset/versioned/fake"
|
||||
)
|
||||
|
||||
func TestCreateOrUpdateCredentialIssuerStatus(t *testing.T) {
|
||||
spec.Run(t, "specs", func(t *testing.T, when spec.G, it spec.S) {
|
||||
var r *require.Assertions
|
||||
var ctx context.Context
|
||||
var pinnipedAPIClient *pinnipedfake.Clientset
|
||||
var credentialIssuerGVR schema.GroupVersionResource
|
||||
const credentialIssuerResourceName = "some-resource-name"
|
||||
|
||||
it.Before(func() {
|
||||
r = require.New(t)
|
||||
ctx = context.Background()
|
||||
pinnipedAPIClient = pinnipedfake.NewSimpleClientset()
|
||||
credentialIssuerGVR = schema.GroupVersionResource{
|
||||
Group: configv1alpha1.GroupName,
|
||||
Version: configv1alpha1.SchemeGroupVersion.Version,
|
||||
Resource: "credentialissuers",
|
||||
}
|
||||
})
|
||||
|
||||
when("the config does not exist", func() {
|
||||
it("creates a new config and then updates it with the func parameter", func() {
|
||||
err := CreateOrUpdateCredentialIssuerStatus(
|
||||
ctx,
|
||||
credentialIssuerResourceName,
|
||||
map[string]string{
|
||||
"myLabelKey1": "myLabelValue1",
|
||||
"myLabelKey2": "myLabelValue2",
|
||||
},
|
||||
pinnipedAPIClient,
|
||||
func(configToUpdate *configv1alpha1.CredentialIssuerStatus) {
|
||||
configToUpdate.KubeConfigInfo = &configv1alpha1.CredentialIssuerKubeConfigInfo{
|
||||
CertificateAuthorityData: "some-ca-value",
|
||||
}
|
||||
},
|
||||
)
|
||||
r.NoError(err)
|
||||
|
||||
expectedGetAction := coretesting.NewRootGetAction(credentialIssuerGVR, credentialIssuerResourceName)
|
||||
|
||||
expectedCreateAction := coretesting.NewRootCreateAction(
|
||||
credentialIssuerGVR,
|
||||
&configv1alpha1.CredentialIssuer{
|
||||
TypeMeta: metav1.TypeMeta{},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: credentialIssuerResourceName,
|
||||
Labels: map[string]string{
|
||||
"myLabelKey1": "myLabelValue1",
|
||||
"myLabelKey2": "myLabelValue2",
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
expectedUpdateAction := coretesting.NewRootUpdateSubresourceAction(credentialIssuerGVR, "status",
|
||||
&configv1alpha1.CredentialIssuer{
|
||||
TypeMeta: metav1.TypeMeta{},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: credentialIssuerResourceName,
|
||||
Labels: map[string]string{
|
||||
"myLabelKey1": "myLabelValue1",
|
||||
"myLabelKey2": "myLabelValue2",
|
||||
},
|
||||
},
|
||||
Status: configv1alpha1.CredentialIssuerStatus{
|
||||
KubeConfigInfo: &configv1alpha1.CredentialIssuerKubeConfigInfo{
|
||||
Server: "",
|
||||
CertificateAuthorityData: "some-ca-value",
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
r.Equal([]coretesting.Action{expectedGetAction, expectedCreateAction, expectedUpdateAction}, pinnipedAPIClient.Actions())
|
||||
})
|
||||
|
||||
when("there is an unexpected error while creating the existing object", func() {
|
||||
it.Before(func() {
|
||||
pinnipedAPIClient.PrependReactor("create", "credentialissuers", func(_ coretesting.Action) (bool, runtime.Object, error) {
|
||||
return true, nil, fmt.Errorf("error on create")
|
||||
})
|
||||
})
|
||||
|
||||
it("returns an error", func() {
|
||||
err := CreateOrUpdateCredentialIssuerStatus(
|
||||
ctx,
|
||||
credentialIssuerResourceName,
|
||||
map[string]string{},
|
||||
pinnipedAPIClient,
|
||||
func(configToUpdate *configv1alpha1.CredentialIssuerStatus) {},
|
||||
)
|
||||
r.EqualError(err, "could not create or update credentialissuer: create failed: error on create")
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
when("the config already exists", func() {
|
||||
var existingConfig *configv1alpha1.CredentialIssuer
|
||||
|
||||
it.Before(func() {
|
||||
existingConfig = &configv1alpha1.CredentialIssuer{
|
||||
TypeMeta: metav1.TypeMeta{},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: credentialIssuerResourceName,
|
||||
Labels: map[string]string{
|
||||
"myLabelKey1": "myLabelValue1",
|
||||
},
|
||||
},
|
||||
Status: configv1alpha1.CredentialIssuerStatus{
|
||||
Strategies: []configv1alpha1.CredentialIssuerStrategy{
|
||||
{
|
||||
Type: configv1alpha1.KubeClusterSigningCertificateStrategyType,
|
||||
Status: configv1alpha1.SuccessStrategyStatus,
|
||||
Reason: configv1alpha1.FetchedKeyStrategyReason,
|
||||
Message: "initial-message",
|
||||
LastUpdateTime: metav1.Now(),
|
||||
},
|
||||
},
|
||||
KubeConfigInfo: &configv1alpha1.CredentialIssuerKubeConfigInfo{
|
||||
Server: "initial-server-value",
|
||||
CertificateAuthorityData: "initial-ca-value",
|
||||
},
|
||||
},
|
||||
}
|
||||
r.NoError(pinnipedAPIClient.Tracker().Add(existingConfig))
|
||||
})
|
||||
|
||||
it("updates the existing config to only apply the updates made by the func parameter", func() {
|
||||
err := CreateOrUpdateCredentialIssuerStatus(
|
||||
ctx,
|
||||
credentialIssuerResourceName,
|
||||
map[string]string{
|
||||
"myLabelKey1": "myLabelValue1",
|
||||
"myLabelKey2": "myLabelValue2",
|
||||
},
|
||||
pinnipedAPIClient,
|
||||
func(configToUpdate *configv1alpha1.CredentialIssuerStatus) {
|
||||
configToUpdate.KubeConfigInfo.CertificateAuthorityData = "new-ca-value"
|
||||
},
|
||||
)
|
||||
r.NoError(err)
|
||||
|
||||
expectedGetAction := coretesting.NewRootGetAction(credentialIssuerGVR, credentialIssuerResourceName)
|
||||
|
||||
// Only the edited field should be changed.
|
||||
expectedUpdatedConfig := existingConfig.DeepCopy()
|
||||
expectedUpdatedConfig.Status.KubeConfigInfo.CertificateAuthorityData = "new-ca-value"
|
||||
expectedUpdateAction := coretesting.NewRootUpdateSubresourceAction(credentialIssuerGVR, "status", expectedUpdatedConfig)
|
||||
|
||||
r.Equal([]coretesting.Action{expectedGetAction, expectedUpdateAction}, pinnipedAPIClient.Actions())
|
||||
})
|
||||
|
||||
it("avoids the cost of an update if the local updates made by the func parameter did not actually change anything", func() {
|
||||
err := CreateOrUpdateCredentialIssuerStatus(
|
||||
ctx,
|
||||
credentialIssuerResourceName,
|
||||
map[string]string{},
|
||||
pinnipedAPIClient,
|
||||
func(configToUpdate *configv1alpha1.CredentialIssuerStatus) {
|
||||
configToUpdate.KubeConfigInfo.CertificateAuthorityData = "initial-ca-value"
|
||||
|
||||
t := configToUpdate.Strategies[0].LastUpdateTime
|
||||
loc, err := time.LoadLocation("Asia/Shanghai")
|
||||
r.NoError(err)
|
||||
configToUpdate.Strategies[0].LastUpdateTime = metav1.NewTime(t.In(loc))
|
||||
},
|
||||
)
|
||||
r.NoError(err)
|
||||
|
||||
expectedGetAction := coretesting.NewRootGetAction(credentialIssuerGVR, credentialIssuerResourceName)
|
||||
r.Equal([]coretesting.Action{expectedGetAction}, pinnipedAPIClient.Actions())
|
||||
})
|
||||
|
||||
when("there is an unexpected error while getting the existing object", func() {
|
||||
it.Before(func() {
|
||||
pinnipedAPIClient.PrependReactor("get", "credentialissuers", func(_ coretesting.Action) (bool, runtime.Object, error) {
|
||||
return true, nil, fmt.Errorf("error on get")
|
||||
})
|
||||
})
|
||||
|
||||
it("returns an error", func() {
|
||||
err := CreateOrUpdateCredentialIssuerStatus(
|
||||
ctx,
|
||||
credentialIssuerResourceName,
|
||||
map[string]string{},
|
||||
pinnipedAPIClient,
|
||||
func(configToUpdate *configv1alpha1.CredentialIssuerStatus) {},
|
||||
)
|
||||
r.EqualError(err, "could not create or update credentialissuer: get failed: error on get")
|
||||
})
|
||||
})
|
||||
|
||||
when("there is an unexpected error while updating the existing object", func() {
|
||||
it.Before(func() {
|
||||
pinnipedAPIClient.PrependReactor("update", "credentialissuers", func(_ coretesting.Action) (bool, runtime.Object, error) {
|
||||
return true, nil, fmt.Errorf("error on update")
|
||||
})
|
||||
})
|
||||
|
||||
it("returns an error", func() {
|
||||
err := CreateOrUpdateCredentialIssuerStatus(
|
||||
ctx,
|
||||
credentialIssuerResourceName,
|
||||
map[string]string{},
|
||||
pinnipedAPIClient,
|
||||
func(configToUpdate *configv1alpha1.CredentialIssuerStatus) {
|
||||
configToUpdate.KubeConfigInfo.CertificateAuthorityData = "new-ca-value"
|
||||
},
|
||||
)
|
||||
r.EqualError(err, "could not create or update credentialissuer: error on update")
|
||||
})
|
||||
})
|
||||
|
||||
when("there is a conflict error while updating the existing object on the first try and the next try succeeds", func() {
|
||||
var slightlyDifferentExistingConfig *configv1alpha1.CredentialIssuer
|
||||
|
||||
it.Before(func() {
|
||||
hit := false
|
||||
slightlyDifferentExistingConfig = existingConfig.DeepCopy()
|
||||
slightlyDifferentExistingConfig.Status.KubeConfigInfo.Server = "some-other-server-value-from-conflicting-update"
|
||||
|
||||
pinnipedAPIClient.PrependReactor("update", "credentialissuers", func(_ coretesting.Action) (bool, runtime.Object, error) {
|
||||
// Return an error on the first call, then fall through to the default (successful) response.
|
||||
if !hit {
|
||||
// Before the update fails, also change the object that will be returned by the next Get(),
|
||||
// to make sure that the production code does a fresh Get() after detecting a conflict.
|
||||
r.NoError(pinnipedAPIClient.Tracker().Update(credentialIssuerGVR, slightlyDifferentExistingConfig, ""))
|
||||
hit = true
|
||||
return true, nil, apierrors.NewConflict(schema.GroupResource{
|
||||
Group: apiregistrationv1.GroupName,
|
||||
Resource: "credentialissuers",
|
||||
}, "alphav1.pinniped.dev", fmt.Errorf("there was a conflict"))
|
||||
}
|
||||
return false, nil, nil
|
||||
})
|
||||
})
|
||||
|
||||
it("retries updates on conflict", func() {
|
||||
err := CreateOrUpdateCredentialIssuerStatus(
|
||||
ctx,
|
||||
credentialIssuerResourceName,
|
||||
map[string]string{
|
||||
"myLabelKey1": "myLabelValue1",
|
||||
"myLabelKey2": "myLabelValue2",
|
||||
},
|
||||
pinnipedAPIClient,
|
||||
func(configToUpdate *configv1alpha1.CredentialIssuerStatus) {
|
||||
configToUpdate.KubeConfigInfo.CertificateAuthorityData = "new-ca-value"
|
||||
},
|
||||
)
|
||||
r.NoError(err)
|
||||
|
||||
expectedGetAction := coretesting.NewRootGetAction(credentialIssuerGVR, credentialIssuerResourceName)
|
||||
|
||||
// The first attempted update only includes its own edits.
|
||||
firstExpectedUpdatedConfig := existingConfig.DeepCopy()
|
||||
firstExpectedUpdatedConfig.Status.KubeConfigInfo.CertificateAuthorityData = "new-ca-value"
|
||||
firstExpectedUpdateAction := coretesting.NewRootUpdateSubresourceAction(credentialIssuerGVR, "status", firstExpectedUpdatedConfig)
|
||||
|
||||
// Both the edits made by this update and the edits made by the conflicting update should be included.
|
||||
secondExpectedUpdatedConfig := existingConfig.DeepCopy()
|
||||
secondExpectedUpdatedConfig.Status.KubeConfigInfo.Server = "some-other-server-value-from-conflicting-update"
|
||||
secondExpectedUpdatedConfig.Status.KubeConfigInfo.CertificateAuthorityData = "new-ca-value"
|
||||
secondExpectedUpdateAction := coretesting.NewRootUpdateSubresourceAction(credentialIssuerGVR, "status", secondExpectedUpdatedConfig)
|
||||
|
||||
expectedActions := []coretesting.Action{
|
||||
expectedGetAction,
|
||||
firstExpectedUpdateAction,
|
||||
expectedGetAction,
|
||||
secondExpectedUpdateAction,
|
||||
}
|
||||
r.Equal(expectedActions, pinnipedAPIClient.Actions())
|
||||
})
|
||||
})
|
||||
})
|
||||
}, spec.Parallel(), spec.Report(report.Terminal{}))
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
// Copyright 2020 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Package issuerconfig contains controller(s) for reconciling CredentialIssuer's.
|
||||
package issuerconfig
|
@ -1,6 +1,7 @@
|
||||
// Copyright 2021 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Package issuerconfig contains helpers for updating CredentialIssuer status entries.
|
||||
package issuerconfig
|
||||
|
||||
import (
|
||||
@ -15,23 +16,6 @@ import (
|
||||
"go.pinniped.dev/generated/latest/client/concierge/clientset/versioned"
|
||||
)
|
||||
|
||||
// UpdateStrategy creates or updates the desired strategy in the CredentialIssuer status.strategies field.
|
||||
// The CredentialIssuer will be created if it does not already exist.
|
||||
func UpdateStrategy(ctx context.Context,
|
||||
name string,
|
||||
credentialIssuerLabels map[string]string,
|
||||
pinnipedAPIClient versioned.Interface,
|
||||
strategy v1alpha1.CredentialIssuerStrategy,
|
||||
) error {
|
||||
return CreateOrUpdateCredentialIssuerStatus(
|
||||
ctx,
|
||||
name,
|
||||
credentialIssuerLabels,
|
||||
pinnipedAPIClient,
|
||||
func(configToUpdate *v1alpha1.CredentialIssuerStatus) { mergeStrategy(configToUpdate, strategy) },
|
||||
)
|
||||
}
|
||||
|
||||
// Update a strategy on an existing CredentialIssuer, merging into any existing strategy entries.
|
||||
func Update(ctx context.Context, client versioned.Interface, issuer *v1alpha1.CredentialIssuer, strategy v1alpha1.CredentialIssuerStrategy) error {
|
||||
// Update the existing object to merge in the new strategy.
|
Loading…
Reference in New Issue
Block a user