mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-28 14:07:14 +00:00
fed: Abstract secret controller interaction with the secret type
This change uses an adapter class to abstracts the interaction of the secret controller with the secret api type. This is the first step to creating a generic controller that can target any type for which an adapter exists.
This commit is contained in:
parent
27cf62ac29
commit
82e73efe83
@ -18,6 +18,7 @@ go_library(
|
|||||||
"//federation/pkg/federation-controller/util:go_default_library",
|
"//federation/pkg/federation-controller/util:go_default_library",
|
||||||
"//federation/pkg/federation-controller/util/deletionhelper:go_default_library",
|
"//federation/pkg/federation-controller/util/deletionhelper:go_default_library",
|
||||||
"//federation/pkg/federation-controller/util/eventsink:go_default_library",
|
"//federation/pkg/federation-controller/util/eventsink:go_default_library",
|
||||||
|
"//federation/pkg/typeadapters:go_default_library",
|
||||||
"//pkg/api:go_default_library",
|
"//pkg/api:go_default_library",
|
||||||
"//pkg/api/v1:go_default_library",
|
"//pkg/api/v1:go_default_library",
|
||||||
"//pkg/client/clientset_generated/clientset:go_default_library",
|
"//pkg/client/clientset_generated/clientset:go_default_library",
|
||||||
|
@ -18,6 +18,7 @@ package secret
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/api/errors"
|
"k8s.io/apimachinery/pkg/api/errors"
|
||||||
@ -36,6 +37,7 @@ import (
|
|||||||
"k8s.io/kubernetes/federation/pkg/federation-controller/util"
|
"k8s.io/kubernetes/federation/pkg/federation-controller/util"
|
||||||
"k8s.io/kubernetes/federation/pkg/federation-controller/util/deletionhelper"
|
"k8s.io/kubernetes/federation/pkg/federation-controller/util/deletionhelper"
|
||||||
"k8s.io/kubernetes/federation/pkg/federation-controller/util/eventsink"
|
"k8s.io/kubernetes/federation/pkg/federation-controller/util/eventsink"
|
||||||
|
"k8s.io/kubernetes/federation/pkg/typeadapters"
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
apiv1 "k8s.io/kubernetes/pkg/api/v1"
|
apiv1 "k8s.io/kubernetes/pkg/api/v1"
|
||||||
kubeclientset "k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
|
kubeclientset "k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
|
||||||
@ -72,9 +74,6 @@ type SecretController struct {
|
|||||||
// Informer controller for secrets that should be federated.
|
// Informer controller for secrets that should be federated.
|
||||||
secretInformerController cache.Controller
|
secretInformerController cache.Controller
|
||||||
|
|
||||||
// Client to federated api server.
|
|
||||||
federatedApiClient federationclientset.Interface
|
|
||||||
|
|
||||||
// Backoff manager for secrets
|
// Backoff manager for secrets
|
||||||
secretBackoff *flowcontrol.Backoff
|
secretBackoff *flowcontrol.Backoff
|
||||||
|
|
||||||
@ -87,6 +86,8 @@ type SecretController struct {
|
|||||||
clusterAvailableDelay time.Duration
|
clusterAvailableDelay time.Duration
|
||||||
smallDelay time.Duration
|
smallDelay time.Duration
|
||||||
updateTimeout time.Duration
|
updateTimeout time.Duration
|
||||||
|
|
||||||
|
adapter typeadapters.FederatedTypeAdapter
|
||||||
}
|
}
|
||||||
|
|
||||||
// StartSecretController starts a new secret controller
|
// StartSecretController starts a new secret controller
|
||||||
@ -103,18 +104,20 @@ func StartSecretController(config *restclient.Config, stopChan <-chan struct{},
|
|||||||
|
|
||||||
// newSecretController returns a new secret controller
|
// newSecretController returns a new secret controller
|
||||||
func newSecretController(client federationclientset.Interface) *SecretController {
|
func newSecretController(client federationclientset.Interface) *SecretController {
|
||||||
|
adapter := typeadapters.NewSecretAdapter(client)
|
||||||
|
|
||||||
broadcaster := record.NewBroadcaster()
|
broadcaster := record.NewBroadcaster()
|
||||||
broadcaster.StartRecordingToSink(eventsink.NewFederatedEventSink(client))
|
broadcaster.StartRecordingToSink(eventsink.NewFederatedEventSink(client))
|
||||||
recorder := broadcaster.NewRecorder(api.Scheme, clientv1.EventSource{Component: "federated-secrets-controller"})
|
recorder := broadcaster.NewRecorder(api.Scheme, clientv1.EventSource{Component: fmt.Sprintf("federated-%v-controller", adapter.Kind())})
|
||||||
|
|
||||||
secretcontroller := &SecretController{
|
secretcontroller := &SecretController{
|
||||||
federatedApiClient: client,
|
|
||||||
secretReviewDelay: time.Second * 10,
|
secretReviewDelay: time.Second * 10,
|
||||||
clusterAvailableDelay: time.Second * 20,
|
clusterAvailableDelay: time.Second * 20,
|
||||||
smallDelay: time.Second * 3,
|
smallDelay: time.Second * 3,
|
||||||
updateTimeout: time.Second * 30,
|
updateTimeout: time.Second * 30,
|
||||||
secretBackoff: flowcontrol.NewBackOff(5*time.Second, time.Minute),
|
secretBackoff: flowcontrol.NewBackOff(5*time.Second, time.Minute),
|
||||||
eventRecorder: recorder,
|
eventRecorder: recorder,
|
||||||
|
adapter: adapter,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build delivereres for triggering reconciliations.
|
// Build delivereres for triggering reconciliations.
|
||||||
@ -125,13 +128,13 @@ func newSecretController(client federationclientset.Interface) *SecretController
|
|||||||
secretcontroller.secretInformerStore, secretcontroller.secretInformerController = cache.NewInformer(
|
secretcontroller.secretInformerStore, secretcontroller.secretInformerController = cache.NewInformer(
|
||||||
&cache.ListWatch{
|
&cache.ListWatch{
|
||||||
ListFunc: func(options metav1.ListOptions) (pkgruntime.Object, error) {
|
ListFunc: func(options metav1.ListOptions) (pkgruntime.Object, error) {
|
||||||
return client.Core().Secrets(metav1.NamespaceAll).List(options)
|
return adapter.FedList(metav1.NamespaceAll, options)
|
||||||
},
|
},
|
||||||
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
|
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
|
||||||
return client.Core().Secrets(metav1.NamespaceAll).Watch(options)
|
return adapter.FedWatch(metav1.NamespaceAll, options)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
&apiv1.Secret{},
|
adapter.ObjectType(),
|
||||||
controller.NoResyncPeriodFunc(),
|
controller.NoResyncPeriodFunc(),
|
||||||
util.NewTriggerOnAllChanges(func(obj pkgruntime.Object) { secretcontroller.deliverSecretObj(obj, 0, false) }))
|
util.NewTriggerOnAllChanges(func(obj pkgruntime.Object) { secretcontroller.deliverSecretObj(obj, 0, false) }))
|
||||||
|
|
||||||
@ -142,13 +145,13 @@ func newSecretController(client federationclientset.Interface) *SecretController
|
|||||||
return cache.NewInformer(
|
return cache.NewInformer(
|
||||||
&cache.ListWatch{
|
&cache.ListWatch{
|
||||||
ListFunc: func(options metav1.ListOptions) (pkgruntime.Object, error) {
|
ListFunc: func(options metav1.ListOptions) (pkgruntime.Object, error) {
|
||||||
return targetClient.Core().Secrets(metav1.NamespaceAll).List(options)
|
return adapter.ClusterList(targetClient, metav1.NamespaceAll, options)
|
||||||
},
|
},
|
||||||
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
|
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
|
||||||
return targetClient.Core().Secrets(metav1.NamespaceAll).Watch(options)
|
return adapter.ClusterWatch(targetClient, metav1.NamespaceAll, options)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
&apiv1.Secret{},
|
adapter.ObjectType(),
|
||||||
controller.NoResyncPeriodFunc(),
|
controller.NoResyncPeriodFunc(),
|
||||||
// Trigger reconciliation whenever something in federated cluster is changed. In most cases it
|
// Trigger reconciliation whenever something in federated cluster is changed. In most cases it
|
||||||
// would be just confirmation that some secret operation succeeded.
|
// would be just confirmation that some secret operation succeeded.
|
||||||
@ -170,19 +173,17 @@ func newSecretController(client federationclientset.Interface) *SecretController
|
|||||||
// Federated updeater along with Create/Update/Delete operations.
|
// Federated updeater along with Create/Update/Delete operations.
|
||||||
secretcontroller.federatedUpdater = util.NewFederatedUpdater(secretcontroller.secretFederatedInformer,
|
secretcontroller.federatedUpdater = util.NewFederatedUpdater(secretcontroller.secretFederatedInformer,
|
||||||
func(client kubeclientset.Interface, obj pkgruntime.Object) error {
|
func(client kubeclientset.Interface, obj pkgruntime.Object) error {
|
||||||
secret := obj.(*apiv1.Secret)
|
_, err := adapter.ClusterCreate(client, obj)
|
||||||
_, err := client.Core().Secrets(secret.Namespace).Create(secret)
|
|
||||||
return err
|
return err
|
||||||
},
|
},
|
||||||
func(client kubeclientset.Interface, obj pkgruntime.Object) error {
|
func(client kubeclientset.Interface, obj pkgruntime.Object) error {
|
||||||
secret := obj.(*apiv1.Secret)
|
_, err := adapter.ClusterUpdate(client, obj)
|
||||||
_, err := client.Core().Secrets(secret.Namespace).Update(secret)
|
|
||||||
return err
|
return err
|
||||||
},
|
},
|
||||||
func(client kubeclientset.Interface, obj pkgruntime.Object) error {
|
func(client kubeclientset.Interface, obj pkgruntime.Object) error {
|
||||||
secret := obj.(*apiv1.Secret)
|
namespacedName := adapter.NamespacedName(obj)
|
||||||
orphanDependents := false
|
orphanDependents := false
|
||||||
err := client.Core().Secrets(secret.Namespace).Delete(secret.Name, &metav1.DeleteOptions{OrphanDependents: &orphanDependents})
|
err := adapter.ClusterDelete(client, namespacedName, &metav1.DeleteOptions{OrphanDependents: &orphanDependents})
|
||||||
return err
|
return err
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -192,8 +193,7 @@ func newSecretController(client federationclientset.Interface) *SecretController
|
|||||||
secretcontroller.addFinalizerFunc,
|
secretcontroller.addFinalizerFunc,
|
||||||
// objNameFunc
|
// objNameFunc
|
||||||
func(obj pkgruntime.Object) string {
|
func(obj pkgruntime.Object) string {
|
||||||
secret := obj.(*apiv1.Secret)
|
return adapter.ObjectMeta(obj).Name
|
||||||
return secret.Name
|
|
||||||
},
|
},
|
||||||
secretcontroller.updateTimeout,
|
secretcontroller.updateTimeout,
|
||||||
secretcontroller.eventRecorder,
|
secretcontroller.eventRecorder,
|
||||||
@ -214,9 +214,9 @@ func (secretcontroller *SecretController) minimizeLatency() {
|
|||||||
|
|
||||||
// Returns true if the given object has the given finalizer in its ObjectMeta.
|
// Returns true if the given object has the given finalizer in its ObjectMeta.
|
||||||
func (secretcontroller *SecretController) hasFinalizerFunc(obj pkgruntime.Object, finalizer string) bool {
|
func (secretcontroller *SecretController) hasFinalizerFunc(obj pkgruntime.Object, finalizer string) bool {
|
||||||
secret := obj.(*apiv1.Secret)
|
meta := secretcontroller.adapter.ObjectMeta(obj)
|
||||||
for i := range secret.ObjectMeta.Finalizers {
|
for i := range meta.Finalizers {
|
||||||
if string(secret.ObjectMeta.Finalizers[i]) == finalizer {
|
if string(meta.Finalizers[i]) == finalizer {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -226,12 +226,13 @@ func (secretcontroller *SecretController) hasFinalizerFunc(obj pkgruntime.Object
|
|||||||
// Removes the finalizers from the given objects ObjectMeta.
|
// Removes the finalizers from the given objects ObjectMeta.
|
||||||
// Assumes that the given object is a secret.
|
// Assumes that the given object is a secret.
|
||||||
func (secretcontroller *SecretController) removeFinalizerFunc(obj pkgruntime.Object, finalizers []string) (pkgruntime.Object, error) {
|
func (secretcontroller *SecretController) removeFinalizerFunc(obj pkgruntime.Object, finalizers []string) (pkgruntime.Object, error) {
|
||||||
secret := obj.(*apiv1.Secret)
|
adapter := secretcontroller.adapter
|
||||||
|
meta := adapter.ObjectMeta(obj)
|
||||||
newFinalizers := []string{}
|
newFinalizers := []string{}
|
||||||
hasFinalizer := false
|
hasFinalizer := false
|
||||||
for i := range secret.ObjectMeta.Finalizers {
|
for i := range meta.Finalizers {
|
||||||
if !deletionhelper.ContainsString(finalizers, secret.ObjectMeta.Finalizers[i]) {
|
if !deletionhelper.ContainsString(finalizers, meta.Finalizers[i]) {
|
||||||
newFinalizers = append(newFinalizers, secret.ObjectMeta.Finalizers[i])
|
newFinalizers = append(newFinalizers, meta.Finalizers[i])
|
||||||
} else {
|
} else {
|
||||||
hasFinalizer = true
|
hasFinalizer = true
|
||||||
}
|
}
|
||||||
@ -240,10 +241,10 @@ func (secretcontroller *SecretController) removeFinalizerFunc(obj pkgruntime.Obj
|
|||||||
// Nothing to do.
|
// Nothing to do.
|
||||||
return obj, nil
|
return obj, nil
|
||||||
}
|
}
|
||||||
secret.ObjectMeta.Finalizers = newFinalizers
|
meta.Finalizers = newFinalizers
|
||||||
secret, err := secretcontroller.federatedApiClient.Core().Secrets(secret.Namespace).Update(secret)
|
secret, err := secretcontroller.adapter.FedUpdate(obj)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to remove finalizers %v from secret %s: %v", finalizers, secret.Name, err)
|
return nil, fmt.Errorf("failed to remove finalizers %v from %s %s: %v", finalizers, adapter.Kind(), meta.Name, err)
|
||||||
}
|
}
|
||||||
return secret, nil
|
return secret, nil
|
||||||
}
|
}
|
||||||
@ -251,11 +252,12 @@ func (secretcontroller *SecretController) removeFinalizerFunc(obj pkgruntime.Obj
|
|||||||
// Adds the given finalizers to the given objects ObjectMeta.
|
// Adds the given finalizers to the given objects ObjectMeta.
|
||||||
// Assumes that the given object is a secret.
|
// Assumes that the given object is a secret.
|
||||||
func (secretcontroller *SecretController) addFinalizerFunc(obj pkgruntime.Object, finalizers []string) (pkgruntime.Object, error) {
|
func (secretcontroller *SecretController) addFinalizerFunc(obj pkgruntime.Object, finalizers []string) (pkgruntime.Object, error) {
|
||||||
secret := obj.(*apiv1.Secret)
|
adapter := secretcontroller.adapter
|
||||||
secret.ObjectMeta.Finalizers = append(secret.ObjectMeta.Finalizers, finalizers...)
|
meta := adapter.ObjectMeta(obj)
|
||||||
secret, err := secretcontroller.federatedApiClient.Core().Secrets(secret.Namespace).Update(secret)
|
meta.Finalizers = append(meta.Finalizers, finalizers...)
|
||||||
|
secret, err := secretcontroller.adapter.FedUpdate(obj)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to add finalizers %v to secret %s: %v", finalizers, secret.Name, err)
|
return nil, fmt.Errorf("failed to add finalizers %v to %s %s: %v", finalizers, adapter.Kind(), meta.Name, err)
|
||||||
}
|
}
|
||||||
return secret, nil
|
return secret, nil
|
||||||
}
|
}
|
||||||
@ -277,9 +279,9 @@ func (secretcontroller *SecretController) Run(stopChan <-chan struct{}) {
|
|||||||
util.StartBackoffGC(secretcontroller.secretBackoff, stopChan)
|
util.StartBackoffGC(secretcontroller.secretBackoff, stopChan)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (secretcontroller *SecretController) deliverSecretObj(obj interface{}, delay time.Duration, failed bool) {
|
func (secretcontroller *SecretController) deliverSecretObj(obj pkgruntime.Object, delay time.Duration, failed bool) {
|
||||||
secret := obj.(*apiv1.Secret)
|
namespacedName := secretcontroller.adapter.NamespacedName(obj)
|
||||||
secretcontroller.deliverSecret(types.NamespacedName{Namespace: secret.Namespace, Name: secret.Name}, delay, failed)
|
secretcontroller.deliverSecret(namespacedName, delay, failed)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adds backoff to delay if this delivery is related to some failure. Resets backoff if there was no failure.
|
// Adds backoff to delay if this delivery is related to some failure. Resets backoff if there was no failure.
|
||||||
@ -318,12 +320,15 @@ func (secretcontroller *SecretController) reconcileSecretsOnClusterChange() {
|
|||||||
secretcontroller.clusterDeliverer.DeliverAt(allClustersKey, nil, time.Now().Add(secretcontroller.clusterAvailableDelay))
|
secretcontroller.clusterDeliverer.DeliverAt(allClustersKey, nil, time.Now().Add(secretcontroller.clusterAvailableDelay))
|
||||||
}
|
}
|
||||||
for _, obj := range secretcontroller.secretInformerStore.List() {
|
for _, obj := range secretcontroller.secretInformerStore.List() {
|
||||||
secret := obj.(*apiv1.Secret)
|
namespacedName := secretcontroller.adapter.NamespacedName(obj.(pkgruntime.Object))
|
||||||
secretcontroller.deliverSecret(types.NamespacedName{Namespace: secret.Namespace, Name: secret.Name}, secretcontroller.smallDelay, false)
|
secretcontroller.deliverSecret(namespacedName, secretcontroller.smallDelay, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (secretcontroller *SecretController) reconcileSecret(secret types.NamespacedName) {
|
func (secretcontroller *SecretController) reconcileSecret(secret types.NamespacedName) {
|
||||||
|
adapter := secretcontroller.adapter
|
||||||
|
kind := adapter.Kind()
|
||||||
|
|
||||||
if !secretcontroller.isSynced() {
|
if !secretcontroller.isSynced() {
|
||||||
secretcontroller.deliverSecret(secret, secretcontroller.clusterAvailableDelay, false)
|
secretcontroller.deliverSecret(secret, secretcontroller.clusterAvailableDelay, false)
|
||||||
return
|
return
|
||||||
@ -332,7 +337,7 @@ func (secretcontroller *SecretController) reconcileSecret(secret types.Namespace
|
|||||||
key := secret.String()
|
key := secret.String()
|
||||||
baseSecretObjFromStore, exist, err := secretcontroller.secretInformerStore.GetByKey(key)
|
baseSecretObjFromStore, exist, err := secretcontroller.secretInformerStore.GetByKey(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Errorf("Failed to query main secret store for %v: %v", key, err)
|
glog.Errorf("Failed to query main %s store for %v: %v", kind, key, err)
|
||||||
secretcontroller.deliverSecret(secret, 0, true)
|
secretcontroller.deliverSecret(secret, 0, true)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -345,35 +350,42 @@ func (secretcontroller *SecretController) reconcileSecret(secret types.Namespace
|
|||||||
// Create a copy before modifying the obj to prevent race condition with
|
// Create a copy before modifying the obj to prevent race condition with
|
||||||
// other readers of obj from store.
|
// other readers of obj from store.
|
||||||
baseSecretObj, err := api.Scheme.DeepCopy(baseSecretObjFromStore)
|
baseSecretObj, err := api.Scheme.DeepCopy(baseSecretObjFromStore)
|
||||||
baseSecret, ok := baseSecretObj.(*apiv1.Secret)
|
if err != nil {
|
||||||
if err != nil || !ok {
|
glog.Errorf("Error in retrieving obj from store: %v", err)
|
||||||
glog.Errorf("Error in retrieving obj from store: %v, %v", ok, err)
|
|
||||||
secretcontroller.deliverSecret(secret, 0, true)
|
secretcontroller.deliverSecret(secret, 0, true)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if baseSecret.DeletionTimestamp != nil {
|
if !adapter.IsExpectedType(baseSecretObj) {
|
||||||
if err := secretcontroller.delete(baseSecret); err != nil {
|
glog.Errorf("Object is not the expected type: %v", baseSecretObj)
|
||||||
glog.Errorf("Failed to delete %s: %v", secret, err)
|
secretcontroller.deliverSecret(secret, 0, true)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
baseSecret := baseSecretObj.(pkgruntime.Object)
|
||||||
|
meta := adapter.ObjectMeta(baseSecret)
|
||||||
|
|
||||||
|
if meta.DeletionTimestamp != nil {
|
||||||
|
if err := secretcontroller.delete(baseSecret, secret); err != nil {
|
||||||
|
glog.Errorf("Failed to delete %s %s: %v", kind, secret, err)
|
||||||
secretcontroller.eventRecorder.Eventf(baseSecret, api.EventTypeNormal, "DeleteFailed",
|
secretcontroller.eventRecorder.Eventf(baseSecret, api.EventTypeNormal, "DeleteFailed",
|
||||||
"Secret delete failed: %v", err)
|
"%s delete failed: %v", strings.ToTitle(kind), err)
|
||||||
secretcontroller.deliverSecret(secret, 0, true)
|
secretcontroller.deliverSecret(secret, 0, true)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
glog.V(3).Infof("Ensuring delete object from underlying clusters finalizer for secret: %s",
|
glog.V(3).Infof("Ensuring delete object from underlying clusters finalizer for %s: %s",
|
||||||
baseSecret.Name)
|
kind, secret)
|
||||||
// Add the required finalizers before creating a secret in underlying clusters.
|
// Add the required finalizers before creating a secret in underlying clusters.
|
||||||
updatedSecretObj, err := secretcontroller.deletionHelper.EnsureFinalizers(baseSecret)
|
baseSecret, err = secretcontroller.deletionHelper.EnsureFinalizers(baseSecret)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Errorf("Failed to ensure delete object from underlying clusters finalizer in secret %s: %v",
|
glog.Errorf("Failed to ensure delete object from underlying clusters finalizer in %s %s: %v",
|
||||||
baseSecret.Name, err)
|
kind, secret, err)
|
||||||
secretcontroller.deliverSecret(secret, 0, false)
|
secretcontroller.deliverSecret(secret, 0, false)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
baseSecret = updatedSecretObj.(*apiv1.Secret)
|
|
||||||
|
|
||||||
glog.V(3).Infof("Syncing secret %s in underlying clusters", baseSecret.Name)
|
glog.V(3).Infof("Syncing %s %s in underlying clusters", kind, secret)
|
||||||
|
|
||||||
clusters, err := secretcontroller.secretFederatedInformer.GetReadyClusters()
|
clusters, err := secretcontroller.secretFederatedInformer.GetReadyClusters()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -392,15 +404,11 @@ func (secretcontroller *SecretController) reconcileSecret(secret types.Namespace
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The data should not be modified.
|
// The data should not be modified.
|
||||||
desiredSecret := &apiv1.Secret{
|
desiredSecret := adapter.Copy(baseSecret)
|
||||||
ObjectMeta: util.DeepCopyRelevantObjectMeta(baseSecret.ObjectMeta),
|
|
||||||
Data: baseSecret.Data,
|
|
||||||
Type: baseSecret.Type,
|
|
||||||
}
|
|
||||||
|
|
||||||
if !found {
|
if !found {
|
||||||
secretcontroller.eventRecorder.Eventf(baseSecret, api.EventTypeNormal, "CreateInCluster",
|
secretcontroller.eventRecorder.Eventf(baseSecret, api.EventTypeNormal, "CreateInCluster",
|
||||||
"Creating secret in cluster %s", cluster.Name)
|
"Creating %s in cluster %s", kind, cluster.Name)
|
||||||
|
|
||||||
operations = append(operations, util.FederatedOperation{
|
operations = append(operations, util.FederatedOperation{
|
||||||
Type: util.OperationTypeAdd,
|
Type: util.OperationTypeAdd,
|
||||||
@ -408,13 +416,12 @@ func (secretcontroller *SecretController) reconcileSecret(secret types.Namespace
|
|||||||
ClusterName: cluster.Name,
|
ClusterName: cluster.Name,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
clusterSecret := clusterSecretObj.(*apiv1.Secret)
|
clusterSecret := clusterSecretObj.(pkgruntime.Object)
|
||||||
|
|
||||||
// Update existing secret, if needed.
|
// Update existing secret, if needed.
|
||||||
if !util.SecretEquivalent(*desiredSecret, *clusterSecret) {
|
if !adapter.Equivalent(desiredSecret, clusterSecret) {
|
||||||
|
|
||||||
secretcontroller.eventRecorder.Eventf(baseSecret, api.EventTypeNormal, "UpdateInCluster",
|
secretcontroller.eventRecorder.Eventf(baseSecret, api.EventTypeNormal, "UpdateInCluster",
|
||||||
"Updating secret in cluster %s", cluster.Name)
|
"Updating %s in cluster %s", kind, cluster.Name)
|
||||||
operations = append(operations, util.FederatedOperation{
|
operations = append(operations, util.FederatedOperation{
|
||||||
Type: util.OperationTypeUpdate,
|
Type: util.OperationTypeUpdate,
|
||||||
Obj: desiredSecret,
|
Obj: desiredSecret,
|
||||||
@ -431,7 +438,7 @@ func (secretcontroller *SecretController) reconcileSecret(secret types.Namespace
|
|||||||
err = secretcontroller.federatedUpdater.UpdateWithOnError(operations, secretcontroller.updateTimeout,
|
err = secretcontroller.federatedUpdater.UpdateWithOnError(operations, secretcontroller.updateTimeout,
|
||||||
func(op util.FederatedOperation, operror error) {
|
func(op util.FederatedOperation, operror error) {
|
||||||
secretcontroller.eventRecorder.Eventf(baseSecret, api.EventTypeNormal, "UpdateInClusterFailed",
|
secretcontroller.eventRecorder.Eventf(baseSecret, api.EventTypeNormal, "UpdateInClusterFailed",
|
||||||
"Secret update in cluster %s failed: %v", op.ClusterName, operror)
|
"%s update in cluster %s failed: %v", strings.ToTitle(kind), op.ClusterName, operror)
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -445,20 +452,21 @@ func (secretcontroller *SecretController) reconcileSecret(secret types.Namespace
|
|||||||
}
|
}
|
||||||
|
|
||||||
// delete deletes the given secret or returns error if the deletion was not complete.
|
// delete deletes the given secret or returns error if the deletion was not complete.
|
||||||
func (secretcontroller *SecretController) delete(secret *apiv1.Secret) error {
|
func (secretcontroller *SecretController) delete(obj pkgruntime.Object, namespacedName types.NamespacedName) error {
|
||||||
glog.V(3).Infof("Handling deletion of secret: %v", *secret)
|
kind := secretcontroller.adapter.Kind()
|
||||||
_, err := secretcontroller.deletionHelper.HandleObjectInUnderlyingClusters(secret)
|
glog.V(3).Infof("Handling deletion of %s: %v", kind, namespacedName)
|
||||||
|
_, err := secretcontroller.deletionHelper.HandleObjectInUnderlyingClusters(obj)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = secretcontroller.federatedApiClient.Core().Secrets(secret.Namespace).Delete(secret.Name, nil)
|
err = secretcontroller.adapter.FedDelete(namespacedName, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Its all good if the error is not found error. That means it is deleted already and we do not have to do anything.
|
// Its all good if the error is not found error. That means it is deleted already and we do not have to do anything.
|
||||||
// This is expected when we are processing an update as a result of secret finalizer deletion.
|
// This is expected when we are processing an update as a result of secret finalizer deletion.
|
||||||
// The process that deleted the last finalizer is also going to delete the secret and we do not have to do anything.
|
// The process that deleted the last finalizer is also going to delete the secret and we do not have to do anything.
|
||||||
if !errors.IsNotFound(err) {
|
if !errors.IsNotFound(err) {
|
||||||
return fmt.Errorf("failed to delete secret: %v", err)
|
return fmt.Errorf("failed to delete %s: %v", kind, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -22,6 +22,7 @@ go_library(
|
|||||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||||
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
||||||
"//vendor:k8s.io/apimachinery/pkg/types",
|
"//vendor:k8s.io/apimachinery/pkg/types",
|
||||||
|
"//vendor:k8s.io/apimachinery/pkg/watch",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -20,8 +20,9 @@ import (
|
|||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
pkgruntime "k8s.io/apimachinery/pkg/runtime"
|
pkgruntime "k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
|
"k8s.io/apimachinery/pkg/watch"
|
||||||
federationclientset "k8s.io/kubernetes/federation/client/clientset_generated/federation_clientset"
|
federationclientset "k8s.io/kubernetes/federation/client/clientset_generated/federation_clientset"
|
||||||
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
|
kubeclientset "k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
|
||||||
)
|
)
|
||||||
|
|
||||||
// FederatedTypeAdapter defines operations for interacting with a
|
// FederatedTypeAdapter defines operations for interacting with a
|
||||||
@ -31,18 +32,28 @@ type FederatedTypeAdapter interface {
|
|||||||
SetClient(client federationclientset.Interface)
|
SetClient(client federationclientset.Interface)
|
||||||
|
|
||||||
Kind() string
|
Kind() string
|
||||||
|
ObjectType() pkgruntime.Object
|
||||||
|
IsExpectedType(obj interface{}) bool
|
||||||
|
Copy(obj pkgruntime.Object) pkgruntime.Object
|
||||||
Equivalent(obj1, obj2 pkgruntime.Object) bool
|
Equivalent(obj1, obj2 pkgruntime.Object) bool
|
||||||
ObjectMeta(obj pkgruntime.Object) *metav1.ObjectMeta
|
|
||||||
NamespacedName(obj pkgruntime.Object) types.NamespacedName
|
NamespacedName(obj pkgruntime.Object) types.NamespacedName
|
||||||
|
ObjectMeta(obj pkgruntime.Object) *metav1.ObjectMeta
|
||||||
|
|
||||||
// Fed* operations target the federation control plane
|
// Fed* operations target the federation control plane
|
||||||
FedCreate(obj pkgruntime.Object) (pkgruntime.Object, error)
|
FedCreate(obj pkgruntime.Object) (pkgruntime.Object, error)
|
||||||
FedGet(namespacedName types.NamespacedName) (pkgruntime.Object, error)
|
|
||||||
FedUpdate(obj pkgruntime.Object) (pkgruntime.Object, error)
|
|
||||||
FedDelete(namespacedName types.NamespacedName, options *metav1.DeleteOptions) error
|
FedDelete(namespacedName types.NamespacedName, options *metav1.DeleteOptions) error
|
||||||
|
FedGet(namespacedName types.NamespacedName) (pkgruntime.Object, error)
|
||||||
|
FedList(namespace string, options metav1.ListOptions) (pkgruntime.Object, error)
|
||||||
|
FedUpdate(obj pkgruntime.Object) (pkgruntime.Object, error)
|
||||||
|
FedWatch(namespace string, options metav1.ListOptions) (watch.Interface, error)
|
||||||
|
|
||||||
// The following operations are intended to target a cluster that is a member of a federation
|
// The following operations are intended to target a cluster that is a member of a federation
|
||||||
ClusterGet(client clientset.Interface, namespacedName types.NamespacedName) (pkgruntime.Object, error)
|
ClusterCreate(client kubeclientset.Interface, obj pkgruntime.Object) (pkgruntime.Object, error)
|
||||||
|
ClusterDelete(client kubeclientset.Interface, nsName types.NamespacedName, options *metav1.DeleteOptions) error
|
||||||
|
ClusterGet(client kubeclientset.Interface, namespacedName types.NamespacedName) (pkgruntime.Object, error)
|
||||||
|
ClusterList(client kubeclientset.Interface, namespace string, options metav1.ListOptions) (pkgruntime.Object, error)
|
||||||
|
ClusterUpdate(client kubeclientset.Interface, obj pkgruntime.Object) (pkgruntime.Object, error)
|
||||||
|
ClusterWatch(client kubeclientset.Interface, namespace string, options metav1.ListOptions) (watch.Interface, error)
|
||||||
|
|
||||||
NewTestObject(namespace string) pkgruntime.Object
|
NewTestObject(namespace string) pkgruntime.Object
|
||||||
}
|
}
|
||||||
|
@ -20,10 +20,11 @@ import (
|
|||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
pkgruntime "k8s.io/apimachinery/pkg/runtime"
|
pkgruntime "k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
|
"k8s.io/apimachinery/pkg/watch"
|
||||||
federationclientset "k8s.io/kubernetes/federation/client/clientset_generated/federation_clientset"
|
federationclientset "k8s.io/kubernetes/federation/client/clientset_generated/federation_clientset"
|
||||||
"k8s.io/kubernetes/federation/pkg/federation-controller/util"
|
"k8s.io/kubernetes/federation/pkg/federation-controller/util"
|
||||||
apiv1 "k8s.io/kubernetes/pkg/api/v1"
|
apiv1 "k8s.io/kubernetes/pkg/api/v1"
|
||||||
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
|
kubeclientset "k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
|
||||||
)
|
)
|
||||||
|
|
||||||
type SecretAdapter struct {
|
type SecretAdapter struct {
|
||||||
@ -42,43 +43,91 @@ func (a *SecretAdapter) Kind() string {
|
|||||||
return "secret"
|
return "secret"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *SecretAdapter) ObjectType() pkgruntime.Object {
|
||||||
|
return &apiv1.Secret{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *SecretAdapter) IsExpectedType(obj interface{}) bool {
|
||||||
|
_, ok := obj.(*apiv1.Secret)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *SecretAdapter) Copy(obj pkgruntime.Object) pkgruntime.Object {
|
||||||
|
secret := obj.(*apiv1.Secret)
|
||||||
|
return &apiv1.Secret{
|
||||||
|
ObjectMeta: util.DeepCopyRelevantObjectMeta(secret.ObjectMeta),
|
||||||
|
Data: secret.Data,
|
||||||
|
Type: secret.Type,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (a *SecretAdapter) Equivalent(obj1, obj2 pkgruntime.Object) bool {
|
func (a *SecretAdapter) Equivalent(obj1, obj2 pkgruntime.Object) bool {
|
||||||
secret1 := obj1.(*apiv1.Secret)
|
secret1 := obj1.(*apiv1.Secret)
|
||||||
secret2 := obj2.(*apiv1.Secret)
|
secret2 := obj2.(*apiv1.Secret)
|
||||||
return util.SecretEquivalent(*secret1, *secret2)
|
return util.SecretEquivalent(*secret1, *secret2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *SecretAdapter) ObjectMeta(obj pkgruntime.Object) *metav1.ObjectMeta {
|
|
||||||
return &obj.(*apiv1.Secret).ObjectMeta
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *SecretAdapter) NamespacedName(obj pkgruntime.Object) types.NamespacedName {
|
func (a *SecretAdapter) NamespacedName(obj pkgruntime.Object) types.NamespacedName {
|
||||||
secret := obj.(*apiv1.Secret)
|
secret := obj.(*apiv1.Secret)
|
||||||
return types.NamespacedName{Namespace: secret.Namespace, Name: secret.Name}
|
return types.NamespacedName{Namespace: secret.Namespace, Name: secret.Name}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *SecretAdapter) ObjectMeta(obj pkgruntime.Object) *metav1.ObjectMeta {
|
||||||
|
return &obj.(*apiv1.Secret).ObjectMeta
|
||||||
|
}
|
||||||
|
|
||||||
func (a *SecretAdapter) FedCreate(obj pkgruntime.Object) (pkgruntime.Object, error) {
|
func (a *SecretAdapter) FedCreate(obj pkgruntime.Object) (pkgruntime.Object, error) {
|
||||||
secret := obj.(*apiv1.Secret)
|
secret := obj.(*apiv1.Secret)
|
||||||
return a.client.CoreV1().Secrets(secret.Namespace).Create(secret)
|
return a.client.CoreV1().Secrets(secret.Namespace).Create(secret)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *SecretAdapter) FedDelete(namespacedName types.NamespacedName, options *metav1.DeleteOptions) error {
|
||||||
|
return a.client.CoreV1().Secrets(namespacedName.Namespace).Delete(namespacedName.Name, options)
|
||||||
|
}
|
||||||
|
|
||||||
func (a *SecretAdapter) FedGet(namespacedName types.NamespacedName) (pkgruntime.Object, error) {
|
func (a *SecretAdapter) FedGet(namespacedName types.NamespacedName) (pkgruntime.Object, error) {
|
||||||
return a.client.CoreV1().Secrets(namespacedName.Namespace).Get(namespacedName.Name, metav1.GetOptions{})
|
return a.client.CoreV1().Secrets(namespacedName.Namespace).Get(namespacedName.Name, metav1.GetOptions{})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *SecretAdapter) FedList(namespace string, options metav1.ListOptions) (pkgruntime.Object, error) {
|
||||||
|
return a.client.CoreV1().Secrets(namespace).List(options)
|
||||||
|
}
|
||||||
|
|
||||||
func (a *SecretAdapter) FedUpdate(obj pkgruntime.Object) (pkgruntime.Object, error) {
|
func (a *SecretAdapter) FedUpdate(obj pkgruntime.Object) (pkgruntime.Object, error) {
|
||||||
secret := obj.(*apiv1.Secret)
|
secret := obj.(*apiv1.Secret)
|
||||||
return a.client.CoreV1().Secrets(secret.Namespace).Update(secret)
|
return a.client.CoreV1().Secrets(secret.Namespace).Update(secret)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *SecretAdapter) FedDelete(namespacedName types.NamespacedName, options *metav1.DeleteOptions) error {
|
func (a *SecretAdapter) FedWatch(namespace string, options metav1.ListOptions) (watch.Interface, error) {
|
||||||
return a.client.CoreV1().Secrets(namespacedName.Namespace).Delete(namespacedName.Name, options)
|
return a.client.CoreV1().Secrets(namespace).Watch(options)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *SecretAdapter) ClusterGet(client clientset.Interface, namespacedName types.NamespacedName) (pkgruntime.Object, error) {
|
func (a *SecretAdapter) ClusterCreate(client kubeclientset.Interface, obj pkgruntime.Object) (pkgruntime.Object, error) {
|
||||||
|
secret := obj.(*apiv1.Secret)
|
||||||
|
return client.CoreV1().Secrets(secret.Namespace).Create(secret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *SecretAdapter) ClusterDelete(client kubeclientset.Interface, nsName types.NamespacedName, options *metav1.DeleteOptions) error {
|
||||||
|
return client.CoreV1().Secrets(nsName.Namespace).Delete(nsName.Name, options)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *SecretAdapter) ClusterGet(client kubeclientset.Interface, namespacedName types.NamespacedName) (pkgruntime.Object, error) {
|
||||||
return client.CoreV1().Secrets(namespacedName.Namespace).Get(namespacedName.Name, metav1.GetOptions{})
|
return client.CoreV1().Secrets(namespacedName.Namespace).Get(namespacedName.Name, metav1.GetOptions{})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *SecretAdapter) ClusterList(client kubeclientset.Interface, namespace string, options metav1.ListOptions) (pkgruntime.Object, error) {
|
||||||
|
return client.CoreV1().Secrets(namespace).List(options)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *SecretAdapter) ClusterUpdate(client kubeclientset.Interface, obj pkgruntime.Object) (pkgruntime.Object, error) {
|
||||||
|
secret := obj.(*apiv1.Secret)
|
||||||
|
return client.CoreV1().Secrets(secret.Namespace).Update(secret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *SecretAdapter) ClusterWatch(client kubeclientset.Interface, namespace string, options metav1.ListOptions) (watch.Interface, error) {
|
||||||
|
return client.CoreV1().Secrets(namespace).Watch(options)
|
||||||
|
}
|
||||||
|
|
||||||
func (a *SecretAdapter) NewTestObject(namespace string) pkgruntime.Object {
|
func (a *SecretAdapter) NewTestObject(namespace string) pkgruntime.Object {
|
||||||
return &apiv1.Secret{
|
return &apiv1.Secret{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Loading…
Reference in New Issue
Block a user