mirror of
https://github.com/vmware-tanzu/pinniped.git
synced 2026-01-05 13:07:14 +00:00
logindiscovery: add tests for conditional update and error cases
- Also add some log lines for better observability of behavior. Signed-off-by: Andrew Keesler <akeesler@vmware.com>
This commit is contained in:
@@ -6,11 +6,15 @@ 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"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
"github.com/suzerain-io/controller-go"
|
||||
placeholderv1alpha1 "github.com/suzerain-io/placeholder-name-api/pkg/apis/placeholder/v1alpha1"
|
||||
@@ -45,13 +49,27 @@ func NewPublisherController(namespace string, kubeClient kubernetes.Interface, p
|
||||
}
|
||||
|
||||
func (c *publisherController) Sync(ctx controller.Context) error {
|
||||
configMap, err := c.kubeClient.CoreV1().ConfigMaps(clusterInfoNamespace).Get(ctx.Context, clusterInfoName, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return nil // TODO should this return an error? and should it log?
|
||||
configMap, err := c.kubeClient.
|
||||
CoreV1().
|
||||
ConfigMaps(clusterInfoNamespace).
|
||||
Get(ctx.Context, clusterInfoName, metav1.GetOptions{})
|
||||
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 {
|
||||
return nil // TODO should this return an error? and should it log?
|
||||
klog.InfoS("could not find kubeconfig configmap key")
|
||||
return nil
|
||||
}
|
||||
|
||||
config, _ := clientcmd.Load([]byte(kubeConfig))
|
||||
@@ -74,10 +92,57 @@ func (c *publisherController) Sync(ctx controller.Context) error {
|
||||
CertificateAuthorityData: certificateAuthorityData,
|
||||
},
|
||||
}
|
||||
_, _ = c.placeholderClient.
|
||||
PlaceholderV1alpha1().
|
||||
LoginDiscoveryConfigs(c.namespace).
|
||||
Create(ctx.Context, &discoveryConfig, metav1.CreateOptions{})
|
||||
if err := c.createOrUpdateLoginDiscoveryConfig(ctx.Context, &discoveryConfig); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *publisherController) createOrUpdateLoginDiscoveryConfig(
|
||||
ctx context.Context,
|
||||
discoveryConfig *placeholderv1alpha1.LoginDiscoveryConfig,
|
||||
) error {
|
||||
loginDiscoveryConfigs := c.placeholderClient.
|
||||
PlaceholderV1alpha1().
|
||||
LoginDiscoveryConfigs(c.namespace)
|
||||
|
||||
existingDiscoveryConfig, err := loginDiscoveryConfigs.Get(
|
||||
ctx,
|
||||
discoveryConfig.Name,
|
||||
metav1.GetOptions{},
|
||||
)
|
||||
notFound := k8serrors.IsNotFound(err)
|
||||
if err != nil && !notFound {
|
||||
return fmt.Errorf("could not get logindiscoveryconfig: %w", err)
|
||||
}
|
||||
|
||||
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 *placeholderv1alpha1.LoginDiscoveryConfig) bool {
|
||||
return a.Spec.Server == b.Spec.Server &&
|
||||
a.Spec.CertificateAuthorityData == b.Spec.CertificateAuthorityData
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ package logindiscovery
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -16,6 +17,7 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
kubernetesfake "k8s.io/client-go/kubernetes/fake"
|
||||
coretesting "k8s.io/client-go/testing"
|
||||
@@ -106,38 +108,144 @@ func TestRun(t *testing.T) {
|
||||
err := controller.TestSync(t, subject, *controllerContext)
|
||||
r.NoError(err)
|
||||
|
||||
expectedLoginDiscoveryConfigGVR, expectedLoginDiscoveryConfig := expectedLoginDiscoveryConfig(installedInNamespace, kubeServerURL, caData)
|
||||
expectedLoginDiscoveryConfigGVR, expectedLoginDiscoveryConfig := expectedLoginDiscoveryConfig(
|
||||
installedInNamespace,
|
||||
kubeServerURL,
|
||||
caData,
|
||||
)
|
||||
expectedActions := []coretesting.Action{
|
||||
coretesting.NewCreateAction(expectedLoginDiscoveryConfigGVR, installedInNamespace, expectedLoginDiscoveryConfig),
|
||||
coretesting.NewGetAction(
|
||||
expectedLoginDiscoveryConfigGVR,
|
||||
installedInNamespace,
|
||||
expectedLoginDiscoveryConfig.Name,
|
||||
),
|
||||
coretesting.NewCreateAction(
|
||||
expectedLoginDiscoveryConfigGVR,
|
||||
installedInNamespace,
|
||||
expectedLoginDiscoveryConfig,
|
||||
),
|
||||
}
|
||||
|
||||
// Expect a LoginDiscoveryConfig to be created with the fields from the cluster-info ConfigMap
|
||||
actualCreatedObject := placeholderClient.Actions()[0].(coretesting.CreateActionImpl).Object
|
||||
r.Equal(expectedLoginDiscoveryConfig, actualCreatedObject)
|
||||
r.Equal(expectedActions, placeholderClient.Actions())
|
||||
})
|
||||
|
||||
when("creating the LoginDiscoveryConfig fails", func() {
|
||||
it.Before(func() {
|
||||
placeholderClient.PrependReactor(
|
||||
"create",
|
||||
"logindiscoveryconfigs",
|
||||
func(_ coretesting.Action) (bool, runtime.Object, error) {
|
||||
return true, nil, errors.New("create failed")
|
||||
},
|
||||
)
|
||||
})
|
||||
|
||||
it("returns the create error", func() {
|
||||
err := controller.TestSync(t, subject, *controllerContext)
|
||||
r.EqualError(err, "could not create logindiscoveryconfig: create failed")
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
when("the LoginDiscoveryConfig already exists", func() {
|
||||
when("the LoginDiscoveryConfig is already up to date according to the data in the ConfigMap", func() {
|
||||
it.Before(func() {
|
||||
// TODO add a fake LoginDiscoveryConfig to the placeholderClient whose data matches the ConfigMap's data
|
||||
_, expectedLoginDiscoveryConfig := expectedLoginDiscoveryConfig(
|
||||
installedInNamespace,
|
||||
kubeServerURL,
|
||||
caData,
|
||||
)
|
||||
err := placeholderClient.Tracker().Add(expectedLoginDiscoveryConfig)
|
||||
r.NoError(err)
|
||||
})
|
||||
|
||||
it.Pend("does not update the LoginDiscoveryConfig to avoid unnecessary etcd writes", func() {
|
||||
it("does not update the LoginDiscoveryConfig to avoid unnecessary etcd writes/api calls", func() {
|
||||
err := controller.TestSync(t, subject, *controllerContext)
|
||||
r.NoError(err)
|
||||
r.Empty(placeholderClient.Actions())
|
||||
|
||||
expectedLoginDiscoveryConfigGVR, expectedLoginDiscoveryConfig := expectedLoginDiscoveryConfig(
|
||||
installedInNamespace,
|
||||
kubeServerURL,
|
||||
caData,
|
||||
)
|
||||
expectedActions := []coretesting.Action{
|
||||
coretesting.NewGetAction(
|
||||
expectedLoginDiscoveryConfigGVR,
|
||||
installedInNamespace,
|
||||
expectedLoginDiscoveryConfig.Name,
|
||||
),
|
||||
}
|
||||
r.Equal(expectedActions, placeholderClient.Actions())
|
||||
})
|
||||
|
||||
when("getting the LoginDiscoveryConfig fails", func() {
|
||||
it.Before(func() {
|
||||
placeholderClient.PrependReactor(
|
||||
"get",
|
||||
"logindiscoveryconfigs",
|
||||
func(_ coretesting.Action) (bool, runtime.Object, error) {
|
||||
return true, nil, errors.New("get failed")
|
||||
},
|
||||
)
|
||||
})
|
||||
|
||||
it("returns the get error", func() {
|
||||
err := controller.TestSync(t, subject, *controllerContext)
|
||||
r.EqualError(err, "could not get logindiscoveryconfig: get failed")
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
when("the LoginDiscoveryConfig is stale compared to the data in the ConfigMap", func() {
|
||||
it.Before(func() {
|
||||
// TODO add a fake LoginDiscoveryConfig to the placeholderClient whose data does not match the ConfigMap's data
|
||||
_, expectedLoginDiscoveryConfig := expectedLoginDiscoveryConfig(
|
||||
installedInNamespace,
|
||||
kubeServerURL,
|
||||
caData,
|
||||
)
|
||||
expectedLoginDiscoveryConfig.Spec.Server = "https://some-other-server"
|
||||
err := placeholderClient.Tracker().Add(expectedLoginDiscoveryConfig)
|
||||
r.NoError(err)
|
||||
})
|
||||
|
||||
it.Pend("updates the existing LoginDiscoveryConfig", func() {
|
||||
// TODO
|
||||
it("updates the existing LoginDiscoveryConfig", func() {
|
||||
err := controller.TestSync(t, subject, *controllerContext)
|
||||
r.NoError(err)
|
||||
|
||||
expectedLoginDiscoveryConfigGVR, expectedLoginDiscoveryConfig := expectedLoginDiscoveryConfig(
|
||||
installedInNamespace,
|
||||
kubeServerURL,
|
||||
caData,
|
||||
)
|
||||
expectedActions := []coretesting.Action{
|
||||
coretesting.NewGetAction(
|
||||
expectedLoginDiscoveryConfigGVR,
|
||||
installedInNamespace,
|
||||
expectedLoginDiscoveryConfig.Name,
|
||||
),
|
||||
coretesting.NewUpdateAction(
|
||||
expectedLoginDiscoveryConfigGVR,
|
||||
installedInNamespace,
|
||||
expectedLoginDiscoveryConfig,
|
||||
),
|
||||
}
|
||||
r.Equal(expectedActions, placeholderClient.Actions())
|
||||
})
|
||||
|
||||
when("updating the LoginDiscoveryConfig fails", func() {
|
||||
it.Before(func() {
|
||||
placeholderClient.PrependReactor(
|
||||
"update",
|
||||
"logindiscoveryconfigs",
|
||||
func(_ coretesting.Action) (bool, runtime.Object, error) {
|
||||
return true, nil, errors.New("update failed")
|
||||
},
|
||||
)
|
||||
})
|
||||
|
||||
it("returns the update error", func() {
|
||||
err := controller.TestSync(t, subject, *controllerContext)
|
||||
r.EqualError(err, "could not update logindiscoveryconfig: update failed")
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -181,5 +289,22 @@ func TestRun(t *testing.T) {
|
||||
r.Empty(placeholderClient.Actions())
|
||||
})
|
||||
})
|
||||
|
||||
when("getting the cluster-info ConfigMap in the kube-public namespace fails", func() {
|
||||
it.Before(func() {
|
||||
kubeClient.PrependReactor(
|
||||
"get",
|
||||
"configmaps",
|
||||
func(_ coretesting.Action) (bool, runtime.Object, error) {
|
||||
return true, nil, errors.New("get failed")
|
||||
},
|
||||
)
|
||||
})
|
||||
|
||||
it("returns an error", func() {
|
||||
err := controller.TestSync(t, subject, *controllerContext)
|
||||
r.EqualError(err, "failed to get cluster-info configmap: get failed")
|
||||
})
|
||||
})
|
||||
}, spec.Parallel(), spec.Report(report.Terminal{}))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user