summaryrefslogtreecommitdiffstats
path: root/certServiceK8sExternalProvider/src/cmpv2controller/cmpv2_issuer_controller.go
diff options
context:
space:
mode:
authorJan Malkiewicz <jan.malkiewicz@nokia.com>2020-10-16 10:42:57 +0200
committerJan Malkiewicz <jan.malkiewicz@nokia.com>2020-10-19 10:58:15 +0200
commit311cb14d51f5f9b81c5761d815d5d7a5f9b63817 (patch)
treee6610c00d8e5abc1d672dfe388e5e6234ef6cd44 /certServiceK8sExternalProvider/src/cmpv2controller/cmpv2_issuer_controller.go
parentf5fb53b031c2f1c4bc4872de59b9774a559d786f (diff)
[OOM-K8S-CERT-EXTERNAL-PROVIDER] Mock implementaion enhanced (part III)
Code refactoring Added unit tests Issue-ID: OOM-2559 Signed-off-by: Jan Malkiewicz <jan.malkiewicz@nokia.com> Change-Id: I3f3b7b39d739818fa82842993f621c6134816079
Diffstat (limited to 'certServiceK8sExternalProvider/src/cmpv2controller/cmpv2_issuer_controller.go')
-rw-r--r--certServiceK8sExternalProvider/src/cmpv2controller/cmpv2_issuer_controller.go115
1 files changed, 81 insertions, 34 deletions
diff --git a/certServiceK8sExternalProvider/src/cmpv2controller/cmpv2_issuer_controller.go b/certServiceK8sExternalProvider/src/cmpv2controller/cmpv2_issuer_controller.go
index e5b1b196..f57f5677 100644
--- a/certServiceK8sExternalProvider/src/cmpv2controller/cmpv2_issuer_controller.go
+++ b/certServiceK8sExternalProvider/src/cmpv2controller/cmpv2_issuer_controller.go
@@ -31,6 +31,7 @@ import (
"github.com/go-logr/logr"
core "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
+ "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/tools/record"
"k8s.io/utils/clock"
@@ -54,74 +55,120 @@ func (controller *CMPv2IssuerController) Reconcile(req ctrl.Request) (ctrl.Resul
ctx := context.Background()
log := controller.Log.WithValues("cmpv2-issuer-controller", req.NamespacedName)
+ // 1. Load CMPv2Issuer
issuer := new(cmpv2api.CMPv2Issuer)
- if err := controller.Client.Get(ctx, req.NamespacedName, issuer); err != nil {
- log.Error(err, "failed to retrieve CMPv2Issuer resource")
+ if err := controller.loadResource(ctx, req.NamespacedName, issuer); err != nil {
+ handleErrorLoadingCMPv2Issuer(log, err)
return ctrl.Result{}, client.IgnoreNotFound(err)
}
- log.Info("Issuer loaded: ", "issuer", issuer)
+ log.Info("CMPv2Issuer loaded: ", "issuer", issuer)
+ // 2. Validate CMPv2Issuer
statusUpdater := newStatusUpdater(controller, issuer, log)
- if err := validateCMPv2IssuerSpec(issuer.Spec); err != nil {
- log.Error(err, "failed to validate CMPv2Issuer resource")
- statusUpdater.UpdateNoError(ctx, cmpv2api.ConditionFalse, "Validation", "Failed to validate resource: %v", err)
+ if err := validateCMPv2IssuerSpec(issuer.Spec, log); err != nil {
+ handleErrorCMPv2IssuerValidation(ctx, log, err, statusUpdater)
return ctrl.Result{}, err
}
- log.Info("Issuer validated. ")
- // Fetch the provisioner password
+ // 3. Load keystore and truststore information form k8s secret
var secret core.Secret
secretNamespaceName := types.NamespacedName{
Namespace: req.Namespace,
Name: issuer.Spec.KeyRef.Name,
}
- if err := controller.Client.Get(ctx, secretNamespaceName, &secret); err != nil {
- log.Error(err, "failed to retrieve CMPv2Issuer provisioner secret", "namespace", secretNamespaceName.Namespace, "name", secretNamespaceName.Name)
- if apierrors.IsNotFound(err) {
- statusUpdater.UpdateNoError(ctx, cmpv2api.ConditionFalse, "NotFound", "Failed to retrieve provisioner secret: %v", err)
- } else {
- statusUpdater.UpdateNoError(ctx, cmpv2api.ConditionFalse, "Error", "Failed to retrieve provisioner secret: %v", err)
- }
+ if err := controller.loadResource(ctx, secretNamespaceName, &secret); err != nil {
+ handleErrorInvalidSecret(ctx, log, err, statusUpdater, secretNamespaceName)
return ctrl.Result{}, err
}
password, ok := secret.Data[issuer.Spec.KeyRef.Key]
if !ok {
- err := fmt.Errorf("secret %s does not contain key %s", secret.Name, issuer.Spec.KeyRef.Key)
- log.Error(err, "failed to retrieve CMPv2Issuer provisioner secret", "namespace", secretNamespaceName.Namespace, "name", secretNamespaceName.Name)
- statusUpdater.UpdateNoError(ctx, cmpv2api.ConditionFalse, "NotFound", "Failed to retrieve provisioner secret: %v", err)
+ err := handleErrorSecretNotFound(ctx, log, issuer, statusUpdater, secretNamespaceName, secret)
return ctrl.Result{}, err
}
- // Initialize and store the provisioner
+ // 4. Create CMPv2 provisioner and store the instance for further use
provisioner, err := provisioners.New(issuer, password)
if err != nil {
- log.Error(err, "failed to initialize provisioner")
- statusUpdater.UpdateNoError(ctx, cmpv2api.ConditionFalse, "Error", "failed initialize provisioner")
+ handleErrorProvisionerInitialization(ctx, log, err, statusUpdater)
return ctrl.Result{}, err
}
provisioners.Store(req.NamespacedName, provisioner)
- log.Info( "CMPv2Issuer verified. Updating status to Verified...")
- return ctrl.Result{}, statusUpdater.Update(ctx, cmpv2api.ConditionTrue, "Verified", "CMPv2Issuer verified and ready to sign certificates")
+ // 5. Update the status of CMPv2Issuer to 'Validated'
+ if err := updateCMPv2IssuerStatusToVerified(statusUpdater, ctx, log); err != nil {
+ handleErrorUpdatingCMPv2IssuerStatus(log, err)
+ return ctrl.Result{}, err
+ }
+
+ return ctrl.Result{}, nil
}
-// SetupWithManager initializes the CMPv2Issuer controller into the controller
-// runtime.
+
func (controller *CMPv2IssuerController) SetupWithManager(manager ctrl.Manager) error {
return ctrl.NewControllerManagedBy(manager).
For(&cmpv2api.CMPv2Issuer{}).
Complete(controller)
}
-func validateCMPv2IssuerSpec(issuerSpec cmpv2api.CMPv2IssuerSpec) error {
+func (controller *CMPv2IssuerController) loadResource(ctx context.Context, key client.ObjectKey, obj runtime.Object) error {
+ return controller.Client.Get(ctx, key, obj)
+}
+
+
+func validateCMPv2IssuerSpec(issuerSpec cmpv2api.CMPv2IssuerSpec, log logr.Logger) error {
switch {
- case issuerSpec.URL == "":
- return fmt.Errorf("spec.url cannot be empty")
- case issuerSpec.KeyRef.Name == "":
- return fmt.Errorf("spec.keyRef.name cannot be empty")
- case issuerSpec.KeyRef.Key == "":
- return fmt.Errorf("spec.keyRef.key cannot be empty")
- default:
- return nil
+ case issuerSpec.URL == "":
+ return fmt.Errorf("spec.url cannot be empty")
+ case issuerSpec.KeyRef.Name == "":
+ return fmt.Errorf("spec.keyRef.name cannot be empty")
+ case issuerSpec.KeyRef.Key == "":
+ return fmt.Errorf("spec.keyRef.key cannot be empty")
+ default:
+ log.Info("CMPv2Issuer validated. ")
+ return nil
+ }
+}
+
+func updateCMPv2IssuerStatusToVerified(statusUpdater *CMPv2IssuerStatusUpdater, ctx context.Context, log logr.Logger) error {
+ log.Info("CMPv2 provisioner created -> updating status to of CMPv2Issuer resource to: Verified")
+ return statusUpdater.Update(ctx, cmpv2api.ConditionTrue, Verified, "CMPv2Issuer verified and ready to sign certificates")
+}
+
+
+// Error handling
+
+func handleErrorUpdatingCMPv2IssuerStatus(log logr.Logger, err error) {
+ log.Error(err, "Failed to update CMPv2Issuer status")
+}
+
+
+func handleErrorLoadingCMPv2Issuer(log logr.Logger, err error) {
+ log.Error(err, "Failed to retrieve CMPv2Issuer resource")
+}
+
+
+func handleErrorProvisionerInitialization(ctx context.Context, log logr.Logger, err error, statusUpdater *CMPv2IssuerStatusUpdater) {
+ log.Error(err, "Failed to initialize provisioner")
+ statusUpdater.UpdateNoError(ctx, cmpv2api.ConditionFalse, Error, "Failed initialize provisioner")
+}
+
+func handleErrorCMPv2IssuerValidation(ctx context.Context, log logr.Logger, err error, statusUpdater *CMPv2IssuerStatusUpdater) {
+ log.Error(err, "Failed to validate CMPv2Issuer resource")
+ statusUpdater.UpdateNoError(ctx, cmpv2api.ConditionFalse, ValidationFailed, "Failed to validate resource: %v", err)
+}
+
+func handleErrorSecretNotFound(ctx context.Context, log logr.Logger, issuer *cmpv2api.CMPv2Issuer, statusUpdater *CMPv2IssuerStatusUpdater, secretNamespaceName types.NamespacedName, secret core.Secret) error {
+ err := fmt.Errorf("secret %s does not contain key %s", secret.Name, issuer.Spec.KeyRef.Key)
+ log.Error(err, "Failed to retrieve CMPv2Issuer provisioner secret", "namespace", secretNamespaceName.Namespace, "name", secretNamespaceName.Name)
+ statusUpdater.UpdateNoError(ctx, cmpv2api.ConditionFalse, NotFound, "Failed to retrieve provisioner secret: %v", err)
+ return err
+}
+
+func handleErrorInvalidSecret(ctx context.Context, log logr.Logger, err error, statusUpdater *CMPv2IssuerStatusUpdater, secretNamespaceName types.NamespacedName) {
+ log.Error(err, "Failed to retrieve CMPv2Issuer provisioner secret", "namespace", secretNamespaceName.Namespace, "name", secretNamespaceName.Name)
+ if apierrors.IsNotFound(err) {
+ statusUpdater.UpdateNoError(ctx, cmpv2api.ConditionFalse, NotFound, "Failed to retrieve provisioner secret: %v", err)
+ } else {
+ statusUpdater.UpdateNoError(ctx, cmpv2api.ConditionFalse, Error, "Failed to retrieve provisioner secret: %v", err)
}
}