Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
provides a precondition checker determines if encryption controllers …
…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
1 parent
0e395da
commit 345e482
Showing
1 changed file
with
106 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
} |