Skip to content

Commit

Permalink
Merge pull request #11452 from fabriziopandini/add-v1beta2-conditions…
Browse files Browse the repository at this point in the history
…-to-CABPK

🌱 Add v1beta2 conditions to CABPK
  • Loading branch information
k8s-ci-robot authored Nov 21, 2024
2 parents 15de135 + 18441d7 commit 2b6669b
Show file tree
Hide file tree
Showing 2 changed files with 181 additions and 6 deletions.
38 changes: 33 additions & 5 deletions bootstrap/kubeadm/api/v1beta1/v1beta2_condition_consts.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,44 @@ package v1beta1

import clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"

// Conditions that will be used for the KubeadmConfig object in v1Beta2 API version.
// KubeadmConfig's Ready condition and corresponding reasons that will be used in v1Beta2 API version.
const (
// KubeadmConfigReadyV1Beta2Condition is true if the KubeadmConfig is not deleted,
// and both DataSecretCreated, CertificatesAvailable conditions are true.
KubeadmConfigReadyV1Beta2Condition = clusterv1.ReadyV1Beta2Condition

// CertificatesAvailableV1Beta2Condition documents that cluster certificates required
// KubeadmConfigReadyV1Beta2Reason surfaces when the KubeadmConfig is ready.
KubeadmConfigReadyV1Beta2Reason = clusterv1.ReadyV1Beta2Reason

// KubeadmConfigNotReadyV1Beta2Reason surfaces when the KubeadmConfig is not ready.
KubeadmConfigNotReadyV1Beta2Reason = clusterv1.NotReadyV1Beta2Reason

// KubeadmConfigReadyUnknownV1Beta2Reason surfaces when KubeadmConfig readiness is unknown.
KubeadmConfigReadyUnknownV1Beta2Reason = clusterv1.ReadyUnknownV1Beta2Reason
)

// KubeadmConfig's CertificatesAvailable condition and corresponding reasons that will be used in v1Beta2 API version.
const (
// KubeadmConfigCertificatesAvailableV1Beta2Condition documents that cluster certificates required
// for generating the bootstrap data secret are available.
CertificatesAvailableV1Beta2Condition = "CertificatesAvailable"
KubeadmConfigCertificatesAvailableV1Beta2Condition = "CertificatesAvailable"

// KubeadmConfigCertificatesAvailableV1Beta2Reason surfaces when certificates required for machine bootstrap are is available.
KubeadmConfigCertificatesAvailableV1Beta2Reason = clusterv1.AvailableV1Beta2Reason

// KubeadmConfigCertificatesAvailableInternalErrorV1Beta2Reason surfaces unexpected failures when reading or
// generating certificates required for machine bootstrap.
KubeadmConfigCertificatesAvailableInternalErrorV1Beta2Reason = clusterv1.InternalErrorV1Beta2Reason
)

// KubeadmConfig's DataSecretAvailable condition and corresponding reasons that will be used in v1Beta2 API version.
const (
// KubeadmConfigDataSecretAvailableV1Beta2Condition is true if the bootstrap secret is available.
KubeadmConfigDataSecretAvailableV1Beta2Condition = "DataSecretAvailable"

// KubeadmConfigDataSecretAvailableV1Beta2Reason surfaces when the bootstrap secret is available.
KubeadmConfigDataSecretAvailableV1Beta2Reason = clusterv1.AvailableV1Beta2Reason

// DataSecretAvailableV1Beta2Condition is true if the bootstrap secret is available.
DataSecretAvailableV1Beta2Condition = "DataSecretAvailable"
// KubeadmConfigDataSecretNotAvailableV1Beta2Reason surfaces when the bootstrap secret is not available.
KubeadmConfigDataSecretNotAvailableV1Beta2Reason = clusterv1.NotAvailableV1Beta2Reason
)
149 changes: 148 additions & 1 deletion bootstrap/kubeadm/internal/controllers/kubeadmconfig_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ import (
"sigs.k8s.io/cluster-api/internal/util/taints"
"sigs.k8s.io/cluster-api/util"
"sigs.k8s.io/cluster-api/util/conditions"
v1beta2conditions "sigs.k8s.io/cluster-api/util/conditions/v1beta2"
clog "sigs.k8s.io/cluster-api/util/log"
"sigs.k8s.io/cluster-api/util/patch"
"sigs.k8s.io/cluster-api/util/paused"
Expand Down Expand Up @@ -229,8 +230,39 @@ func (r *KubeadmConfigReconciler) Reconcile(ctx context.Context, req ctrl.Reques
bootstrapv1.CertificatesAvailableCondition,
),
)
if err := v1beta2conditions.SetSummaryCondition(config, config, bootstrapv1.KubeadmConfigReadyV1Beta2Condition,
v1beta2conditions.ForConditionTypes{
bootstrapv1.KubeadmConfigDataSecretAvailableV1Beta2Condition,
bootstrapv1.KubeadmConfigCertificatesAvailableV1Beta2Condition,
},
// Using a custom merge strategy to override reasons applied during merge and to ignore some
// info message so the ready condition aggregation in other resources is less noisy.
v1beta2conditions.CustomMergeStrategy{
MergeStrategy: v1beta2conditions.DefaultMergeStrategy(
// Use custom reasons.
v1beta2conditions.ComputeReasonFunc(v1beta2conditions.GetDefaultComputeMergeReasonFunc(
bootstrapv1.KubeadmConfigNotReadyV1Beta2Reason,
bootstrapv1.KubeadmConfigReadyUnknownV1Beta2Reason,
bootstrapv1.KubeadmConfigReadyV1Beta2Reason,
)),
),
},
); err != nil {
rerr = kerrors.NewAggregate([]error{rerr, err})
}
// Patch ObservedGeneration only if the reconciliation completed successfully
patchOpts := []patch.Option{}
patchOpts := []patch.Option{
patch.WithOwnedConditions{Conditions: []clusterv1.ConditionType{
clusterv1.ReadyCondition,
bootstrapv1.DataSecretAvailableCondition,
bootstrapv1.CertificatesAvailableCondition,
}},
patch.WithOwnedV1Beta2Conditions{Conditions: []string{
bootstrapv1.KubeadmConfigReadyV1Beta2Condition,
bootstrapv1.KubeadmConfigDataSecretAvailableV1Beta2Condition,
bootstrapv1.KubeadmConfigCertificatesAvailableV1Beta2Condition,
}},
}
if rerr == nil {
patchOpts = append(patchOpts, patch.WithStatusObservedGeneration{})
}
Expand Down Expand Up @@ -264,13 +296,24 @@ func (r *KubeadmConfigReconciler) reconcile(ctx context.Context, scope *Scope, c
case !cluster.Status.InfrastructureReady:
log.Info("Cluster infrastructure is not ready, waiting")
conditions.MarkFalse(config, bootstrapv1.DataSecretAvailableCondition, bootstrapv1.WaitingForClusterInfrastructureReason, clusterv1.ConditionSeverityInfo, "")
v1beta2conditions.Set(scope.Config, metav1.Condition{
Type: bootstrapv1.KubeadmConfigDataSecretAvailableV1Beta2Condition,
Status: metav1.ConditionFalse,
Reason: bootstrapv1.KubeadmConfigDataSecretNotAvailableV1Beta2Reason,
Message: "Waiting for Cluster status.infrastructureReady to be true",
})
return ctrl.Result{}, nil
// Reconcile status for machines that already have a secret reference, but our status isn't up to date.
// This case solves the pivoting scenario (or a backup restore) which doesn't preserve the status subresource on objects.
case configOwner.DataSecretName() != nil && (!config.Status.Ready || config.Status.DataSecretName == nil):
config.Status.Ready = true
config.Status.DataSecretName = configOwner.DataSecretName()
conditions.MarkTrue(config, bootstrapv1.DataSecretAvailableCondition)
v1beta2conditions.Set(scope.Config, metav1.Condition{
Type: bootstrapv1.KubeadmConfigDataSecretAvailableV1Beta2Condition,
Status: metav1.ConditionTrue,
Reason: bootstrapv1.KubeadmConfigDataSecretAvailableV1Beta2Reason,
})
return ctrl.Result{}, nil
// Status is ready means a config has been generated.
case config.Status.Ready:
Expand Down Expand Up @@ -402,6 +445,12 @@ func (r *KubeadmConfigReconciler) handleClusterNotInitialized(ctx context.Contex
// using the DataSecretGeneratedFailedReason
if conditions.GetReason(scope.Config, bootstrapv1.DataSecretAvailableCondition) != bootstrapv1.DataSecretGenerationFailedReason {
conditions.MarkFalse(scope.Config, bootstrapv1.DataSecretAvailableCondition, clusterv1.WaitingForControlPlaneAvailableReason, clusterv1.ConditionSeverityInfo, "")
v1beta2conditions.Set(scope.Config, metav1.Condition{
Type: bootstrapv1.KubeadmConfigDataSecretAvailableV1Beta2Condition,
Status: metav1.ConditionFalse,
Reason: bootstrapv1.KubeadmConfigDataSecretNotAvailableV1Beta2Reason,
Message: "Waiting for Cluster control plane to be initialized",
})
}

// if it's NOT a control plane machine, requeue
Expand Down Expand Up @@ -505,10 +554,21 @@ func (r *KubeadmConfigReconciler) handleClusterNotInitialized(ctx context.Contex
}
if err != nil {
conditions.MarkFalse(scope.Config, bootstrapv1.CertificatesAvailableCondition, bootstrapv1.CertificatesGenerationFailedReason, clusterv1.ConditionSeverityWarning, err.Error())
v1beta2conditions.Set(scope.Config, metav1.Condition{
Type: bootstrapv1.KubeadmConfigCertificatesAvailableV1Beta2Condition,
Status: metav1.ConditionUnknown,
Reason: bootstrapv1.KubeadmConfigCertificatesAvailableInternalErrorV1Beta2Reason,
Message: "Please check controller logs for errors",
})
return ctrl.Result{}, err
}

conditions.MarkTrue(scope.Config, bootstrapv1.CertificatesAvailableCondition)
v1beta2conditions.Set(scope.Config, metav1.Condition{
Type: bootstrapv1.KubeadmConfigCertificatesAvailableV1Beta2Condition,
Status: metav1.ConditionTrue,
Reason: bootstrapv1.KubeadmConfigCertificatesAvailableV1Beta2Reason,
})

verbosityFlag := ""
if scope.Config.Spec.Verbosity != nil {
Expand All @@ -518,12 +578,24 @@ func (r *KubeadmConfigReconciler) handleClusterNotInitialized(ctx context.Contex
files, err := r.resolveFiles(ctx, scope.Config)
if err != nil {
conditions.MarkFalse(scope.Config, bootstrapv1.DataSecretAvailableCondition, bootstrapv1.DataSecretGenerationFailedReason, clusterv1.ConditionSeverityWarning, err.Error())
v1beta2conditions.Set(scope.Config, metav1.Condition{
Type: bootstrapv1.KubeadmConfigDataSecretAvailableV1Beta2Condition,
Status: metav1.ConditionFalse,
Reason: bootstrapv1.KubeadmConfigDataSecretNotAvailableV1Beta2Reason,
Message: "Failed to read content from secrets for spec.files",
})
return ctrl.Result{}, err
}

users, err := r.resolveUsers(ctx, scope.Config)
if err != nil {
conditions.MarkFalse(scope.Config, bootstrapv1.DataSecretAvailableCondition, bootstrapv1.DataSecretGenerationFailedReason, clusterv1.ConditionSeverityWarning, err.Error())
v1beta2conditions.Set(scope.Config, metav1.Condition{
Type: bootstrapv1.KubeadmConfigDataSecretAvailableV1Beta2Condition,
Status: metav1.ConditionFalse,
Reason: bootstrapv1.KubeadmConfigDataSecretNotAvailableV1Beta2Reason,
Message: "Failed to read password from secrets for spec.users",
})
return ctrl.Result{}, err
}

Expand Down Expand Up @@ -580,13 +652,30 @@ func (r *KubeadmConfigReconciler) joinWorker(ctx context.Context, scope *Scope)
)
if err != nil {
conditions.MarkFalse(scope.Config, bootstrapv1.CertificatesAvailableCondition, bootstrapv1.CertificatesCorruptedReason, clusterv1.ConditionSeverityError, err.Error())
v1beta2conditions.Set(scope.Config, metav1.Condition{
Type: bootstrapv1.KubeadmConfigCertificatesAvailableV1Beta2Condition,
Status: metav1.ConditionUnknown,
Reason: bootstrapv1.KubeadmConfigCertificatesAvailableInternalErrorV1Beta2Reason,
Message: "Please check controller logs for errors",
})
return ctrl.Result{}, err
}
if err := certificates.EnsureAllExist(); err != nil {
conditions.MarkFalse(scope.Config, bootstrapv1.CertificatesAvailableCondition, bootstrapv1.CertificatesCorruptedReason, clusterv1.ConditionSeverityError, err.Error())
v1beta2conditions.Set(scope.Config, metav1.Condition{
Type: bootstrapv1.KubeadmConfigCertificatesAvailableV1Beta2Condition,
Status: metav1.ConditionUnknown,
Reason: bootstrapv1.KubeadmConfigCertificatesAvailableInternalErrorV1Beta2Reason,
Message: "Please check controller logs for errors",
})
return ctrl.Result{}, err
}
conditions.MarkTrue(scope.Config, bootstrapv1.CertificatesAvailableCondition)
v1beta2conditions.Set(scope.Config, metav1.Condition{
Type: bootstrapv1.KubeadmConfigCertificatesAvailableV1Beta2Condition,
Status: metav1.ConditionTrue,
Reason: bootstrapv1.KubeadmConfigCertificatesAvailableV1Beta2Reason,
})

// Ensure that joinConfiguration.Discovery is properly set for joining node on the current cluster.
if res, err := r.reconcileDiscovery(ctx, scope.Cluster, scope.Config, certificates); err != nil {
Expand Down Expand Up @@ -630,19 +719,37 @@ func (r *KubeadmConfigReconciler) joinWorker(ctx context.Context, scope *Scope)
files, err := r.resolveFiles(ctx, scope.Config)
if err != nil {
conditions.MarkFalse(scope.Config, bootstrapv1.DataSecretAvailableCondition, bootstrapv1.DataSecretGenerationFailedReason, clusterv1.ConditionSeverityWarning, err.Error())
v1beta2conditions.Set(scope.Config, metav1.Condition{
Type: bootstrapv1.KubeadmConfigDataSecretAvailableV1Beta2Condition,
Status: metav1.ConditionFalse,
Reason: bootstrapv1.KubeadmConfigDataSecretNotAvailableV1Beta2Reason,
Message: "Failed to read content from secrets for spec.files",
})
return ctrl.Result{}, err
}

users, err := r.resolveUsers(ctx, scope.Config)
if err != nil {
conditions.MarkFalse(scope.Config, bootstrapv1.DataSecretAvailableCondition, bootstrapv1.DataSecretGenerationFailedReason, clusterv1.ConditionSeverityWarning, err.Error())
v1beta2conditions.Set(scope.Config, metav1.Condition{
Type: bootstrapv1.KubeadmConfigDataSecretAvailableV1Beta2Condition,
Status: metav1.ConditionFalse,
Reason: bootstrapv1.KubeadmConfigDataSecretNotAvailableV1Beta2Reason,
Message: "Failed to read password from secrets for spec.users",
})
return ctrl.Result{}, err
}

if discoveryFile := scope.Config.Spec.JoinConfiguration.Discovery.File; discoveryFile != nil && discoveryFile.KubeConfig != nil {
kubeconfig, err := r.resolveDiscoveryKubeConfig(discoveryFile)
if err != nil {
conditions.MarkFalse(scope.Config, bootstrapv1.DataSecretAvailableCondition, bootstrapv1.DataSecretGenerationFailedReason, clusterv1.ConditionSeverityWarning, err.Error())
v1beta2conditions.Set(scope.Config, metav1.Condition{
Type: bootstrapv1.KubeadmConfigDataSecretAvailableV1Beta2Condition,
Status: metav1.ConditionFalse,
Reason: bootstrapv1.KubeadmConfigDataSecretNotAvailableV1Beta2Reason,
Message: "Failed to create kubeconfig for spec.joinConfiguration.discovery.file",
})
return ctrl.Result{}, err
}
files = append(files, *kubeconfig)
Expand Down Expand Up @@ -709,14 +816,31 @@ func (r *KubeadmConfigReconciler) joinControlplane(ctx context.Context, scope *S
)
if err != nil {
conditions.MarkFalse(scope.Config, bootstrapv1.CertificatesAvailableCondition, bootstrapv1.CertificatesCorruptedReason, clusterv1.ConditionSeverityError, err.Error())
v1beta2conditions.Set(scope.Config, metav1.Condition{
Type: bootstrapv1.KubeadmConfigCertificatesAvailableV1Beta2Condition,
Status: metav1.ConditionUnknown,
Reason: bootstrapv1.KubeadmConfigCertificatesAvailableInternalErrorV1Beta2Reason,
Message: "Please check controller logs for errors",
})
return ctrl.Result{}, err
}
if err := certificates.EnsureAllExist(); err != nil {
conditions.MarkFalse(scope.Config, bootstrapv1.CertificatesAvailableCondition, bootstrapv1.CertificatesCorruptedReason, clusterv1.ConditionSeverityError, err.Error())
v1beta2conditions.Set(scope.Config, metav1.Condition{
Type: bootstrapv1.KubeadmConfigCertificatesAvailableV1Beta2Condition,
Status: metav1.ConditionUnknown,
Reason: bootstrapv1.KubeadmConfigCertificatesAvailableInternalErrorV1Beta2Reason,
Message: "Please check controller logs for errors",
})
return ctrl.Result{}, err
}

conditions.MarkTrue(scope.Config, bootstrapv1.CertificatesAvailableCondition)
v1beta2conditions.Set(scope.Config, metav1.Condition{
Type: bootstrapv1.KubeadmConfigCertificatesAvailableV1Beta2Condition,
Status: metav1.ConditionTrue,
Reason: bootstrapv1.KubeadmConfigCertificatesAvailableV1Beta2Reason,
})

// Ensure that joinConfiguration.Discovery is properly set for joining node on the current cluster.
if res, err := r.reconcileDiscovery(ctx, scope.Cluster, scope.Config, certificates); err != nil {
Expand Down Expand Up @@ -747,19 +871,37 @@ func (r *KubeadmConfigReconciler) joinControlplane(ctx context.Context, scope *S
files, err := r.resolveFiles(ctx, scope.Config)
if err != nil {
conditions.MarkFalse(scope.Config, bootstrapv1.DataSecretAvailableCondition, bootstrapv1.DataSecretGenerationFailedReason, clusterv1.ConditionSeverityWarning, err.Error())
v1beta2conditions.Set(scope.Config, metav1.Condition{
Type: bootstrapv1.KubeadmConfigDataSecretAvailableV1Beta2Condition,
Status: metav1.ConditionFalse,
Reason: bootstrapv1.KubeadmConfigDataSecretNotAvailableV1Beta2Reason,
Message: "Failed to read content from secrets for spec.files",
})
return ctrl.Result{}, err
}

users, err := r.resolveUsers(ctx, scope.Config)
if err != nil {
conditions.MarkFalse(scope.Config, bootstrapv1.DataSecretAvailableCondition, bootstrapv1.DataSecretGenerationFailedReason, clusterv1.ConditionSeverityWarning, err.Error())
v1beta2conditions.Set(scope.Config, metav1.Condition{
Type: bootstrapv1.KubeadmConfigDataSecretAvailableV1Beta2Condition,
Status: metav1.ConditionFalse,
Reason: bootstrapv1.KubeadmConfigDataSecretNotAvailableV1Beta2Reason,
Message: "Failed to read password from secrets for spec.users",
})
return ctrl.Result{}, err
}

if discoveryFile := scope.Config.Spec.JoinConfiguration.Discovery.File; discoveryFile != nil && discoveryFile.KubeConfig != nil {
kubeconfig, err := r.resolveDiscoveryKubeConfig(discoveryFile)
if err != nil {
conditions.MarkFalse(scope.Config, bootstrapv1.DataSecretAvailableCondition, bootstrapv1.DataSecretGenerationFailedReason, clusterv1.ConditionSeverityWarning, err.Error())
v1beta2conditions.Set(scope.Config, metav1.Condition{
Type: bootstrapv1.KubeadmConfigDataSecretAvailableV1Beta2Condition,
Status: metav1.ConditionFalse,
Reason: bootstrapv1.KubeadmConfigDataSecretNotAvailableV1Beta2Reason,
Message: "Failed to create kubeconfig for spec.joinConfiguration.discovery.file",
})
return ctrl.Result{}, err
}
files = append(files, *kubeconfig)
Expand Down Expand Up @@ -1235,6 +1377,11 @@ func (r *KubeadmConfigReconciler) storeBootstrapData(ctx context.Context, scope
scope.Config.Status.DataSecretName = ptr.To(secret.Name)
scope.Config.Status.Ready = true
conditions.MarkTrue(scope.Config, bootstrapv1.DataSecretAvailableCondition)
v1beta2conditions.Set(scope.Config, metav1.Condition{
Type: bootstrapv1.KubeadmConfigDataSecretAvailableV1Beta2Condition,
Status: metav1.ConditionTrue,
Reason: bootstrapv1.KubeadmConfigDataSecretAvailableV1Beta2Reason,
})
return nil
}

Expand Down

0 comments on commit 2b6669b

Please sign in to comment.