Skip to content

Commit

Permalink
provides a precondition checker determines if encryption controllers …
Browse files Browse the repository at this point in the history
…should synchronise

Synchronizing encryption controllers is expensive because they pull data directly from the servers to get the most recent data.
This PR provides a checker that uses the cache for gathering enough data to determine if there is some work to be done.
This helps to avoid sending requests to the API servers if there is no work to do.
  • Loading branch information
p0lyn0mial committed Apr 27, 2021
1 parent 0e395da commit 345e482
Showing 1 changed file with 106 additions and 0 deletions.
106 changes: 106 additions & 0 deletions pkg/operator/encryption/preconditions.go
@@ -0,0 +1,106 @@
package encryption

import (
"fmt"

"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/labels"
corev1listers "k8s.io/client-go/listers/core/v1"

configv1informers "github.com/openshift/client-go/config/informers/externalversions/config/v1"
configv1listers "github.com/openshift/client-go/config/listers/config/v1"
"github.com/openshift/library-go/pkg/operator/encryption/encryptionconfig"
"github.com/openshift/library-go/pkg/operator/encryption/state"
operatorv1helpers "github.com/openshift/library-go/pkg/operator/v1helpers"
)

// PreconditionProvider determines if encryption controllers should synchronise.
type PreconditionProvider interface {
// PreconditionFulfilled a method that indicates whether all prerequisites are met and we can Sync.
PreconditionFulfilled() (bool, error)
}

type PreconditionChecker struct {
component string

encryptionSecretSelector labels.Selector

secretLister corev1listers.SecretNamespaceLister
apiServerConfigLister configv1listers.APIServerLister
}

// NewPreconditionChecker determines if encryption controllers should synchronise.
// It uses the cache for gathering data to avoid sending requests to the API servers.
func NewPreconditionChecker(apiServerConfigInformer configv1informers.APIServerInformer, kubeInformersForNamespaces operatorv1helpers.KubeInformersForNamespaces, encryptionSecretSelectorString string) (*PreconditionChecker, error) {
encryptionSecretSelector, err := labels.Parse(encryptionSecretSelectorString)
if err != nil {
return nil, err
}
return &PreconditionChecker{
encryptionSecretSelector: encryptionSecretSelector,
secretLister: kubeInformersForNamespaces.SecretLister().Secrets("openshift-config-managed"),
apiServerConfigLister: apiServerConfigInformer.Lister(),
}, nil
}

// PreconditionFulfilled a method that indicates whether all prerequisites are met and we can Sync.
func (pc *PreconditionChecker) PreconditionFulfilled() (bool, error) {
encryptionNeverEnabled, err := pc.encryptionNeverEnabled()
if err != nil {
return false, err // got an error, report it and run the sync loops
}
if encryptionNeverEnabled {
return false, nil // encryption hasn't been enabled - no work to do
}

// TODO: add a step that would determine if encryption is disabled on previously encrypted clusters that would require:
// having the current mode set to Identity
// having all servers on the same revision
// having desired and actual encryption configuration aligned
// having all resources migrated

// at this point we know that encryption has been previously enabled on this cluster

// since rolling out a new version is a slow process, for kas it takes about ~20 min
// and the encryption controllers must wait until all servers converge on the same revision before they can act
// we have work to do if all api servers are on the same revision
if !pc.areServersOnTheSameRevision() {
return false, nil
}

return true, nil // we might have work to do
}

// encryptionNeverEnabled checks whether encryption hasn't been enabled on a cluster
// it hasn't been enabled when:
// the current mode is set to identity
// AND the encryption configuration in the managed namespace doesn't exists AND we don't have encryption secrets
func (pc *PreconditionChecker) encryptionNeverEnabled() (bool, error) {
apiServerConfig, err := pc.apiServerConfigLister.Get("cluster")
if err != nil {
if !errors.IsNotFound(err) {
return false, err // unknown error
}
return true, nil
}
if currentMode := state.Mode(apiServerConfig.Spec.Encryption.Type); currentMode != state.Identity {
return false, nil
}

encryptionConfiguration, err := pc.secretLister.Get(fmt.Sprintf("%s-%s", encryptionconfig.EncryptionConfSecretName, pc.component))
if err != nil && !errors.IsNotFound(err) {
return false, err // unknown error
}

encryptionSecrets, err := pc.secretLister.List(pc.encryptionSecretSelector)
if err != nil && !errors.IsNotFound(err) {
return false, err // unknown error
}

return encryptionConfiguration == nil && len(encryptionSecrets) == 0, nil
}

func (pc *PreconditionChecker) areServersOnTheSameRevision() bool {
// TODO
return true
}

0 comments on commit 345e482

Please sign in to comment.