ContainerImage.Pinniped/internal/controller/supervisorconfig/dynamic_config_watcher.go
Andrew Keesler fd6a7f5892
supervisor-oidc: hoist OIDC discovery handler for testing
Signed-off-by: Andrew Keesler <akeesler@vmware.com>
2020-10-06 11:16:57 -04:00

113 lines
3.1 KiB
Go

// Copyright 2020 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package supervisorconfig
import (
"fmt"
k8serrors "k8s.io/apimachinery/pkg/api/errors"
corev1informers "k8s.io/client-go/informers/core/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/klog/v2"
pinnipedcontroller "go.pinniped.dev/internal/controller"
"go.pinniped.dev/internal/controllerlib"
)
const (
issuerConfigMapKey = "issuer"
)
// IssuerSetter can be notified of a valid issuer with its SetIssuer function. If there is no
// longer any valid issuer, then nil can be passed to this interface.
//
// Implementations of this type should be thread-safe to support calls from multiple goroutines.
type IssuerSetter interface {
SetIssuer(issuer *string)
}
type dynamicConfigWatcherController struct {
configMapName string
configMapNamespace string
issuerSetter IssuerSetter
k8sClient kubernetes.Interface
configMapInformer corev1informers.ConfigMapInformer
}
func NewDynamicConfigWatcherController(
serverInstallationNamespace string,
configMapName string,
issuerObserver IssuerSetter,
k8sClient kubernetes.Interface,
configMapInformer corev1informers.ConfigMapInformer,
withInformer pinnipedcontroller.WithInformerOptionFunc,
) controllerlib.Controller {
return controllerlib.New(
controllerlib.Config{
Name: "DynamicConfigWatcherController",
Syncer: &dynamicConfigWatcherController{
configMapNamespace: serverInstallationNamespace,
configMapName: configMapName,
issuerSetter: issuerObserver,
k8sClient: k8sClient,
configMapInformer: configMapInformer,
},
},
withInformer(
configMapInformer,
pinnipedcontroller.NameAndNamespaceExactMatchFilterFactory(configMapName, serverInstallationNamespace),
controllerlib.InformerOption{},
),
)
}
// Sync implements controllerlib.Syncer.
func (c *dynamicConfigWatcherController) Sync(ctx controllerlib.Context) error {
// TODO Watch the configmap to find the issuer name, ingress url, etc.
// TODO Update some kind of in-memory representation of the configuration so the discovery endpoint can use it.
// TODO The discovery endpoint would return an error until all missing configuration options are
// filled in.
configMap, err := c.configMapInformer.
Lister().
ConfigMaps(c.configMapNamespace).
Get(c.configMapName)
notFound := k8serrors.IsNotFound(err)
if err != nil && !notFound {
return fmt.Errorf("failed to get %s/%s secret: %w", c.configMapNamespace, c.configMapName, err)
}
if notFound {
klog.InfoS(
"dynamicConfigWatcherController Sync found no configmap",
"configmap",
klog.KRef(c.configMapNamespace, c.configMapName),
)
c.issuerSetter.SetIssuer(nil)
return nil
}
issuer, ok := configMap.Data[issuerConfigMapKey]
if !ok {
klog.InfoS(
"dynamicConfigWatcherController Sync found no issuer",
"configmap",
klog.KObj(configMap),
)
c.issuerSetter.SetIssuer(nil)
return nil
}
klog.InfoS(
"dynamicConfigWatcherController Sync issuer",
"configmap",
klog.KObj(configMap),
"issuer",
issuer,
)
c.issuerSetter.SetIssuer(&issuer)
return nil
}