Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Reconcile Kubernetes class type objects in a dedicated stage #720

Merged
merged 1 commit into from
Sep 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 47 additions & 14 deletions controllers/kustomization_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -715,10 +715,14 @@ func (r *KustomizationReconciler) apply(ctx context.Context, manager *ssa.Resour
}

// contains only CRDs and Namespaces
var stageOne []*unstructured.Unstructured
var defStage []*unstructured.Unstructured

// contains all objects except for CRDs and Namespaces
var stageTwo []*unstructured.Unstructured
// contains only Kubernetes Class types e.g.: RuntimeClass, PriorityClass,
// StorageClas, VolumeSnapshotClass, IngressClass, GatewayClass, ClusterClass, etc
var classStage []*unstructured.Unstructured

// contains all objects except for CRDs, Namespaces and Class type objects
var resStage []*unstructured.Unstructured

// contains the objects' metadata after apply
resultSet := ssa.NewChangeSet()
Expand All @@ -730,33 +734,62 @@ func (r *KustomizationReconciler) apply(ctx context.Context, manager *ssa.Resour
ssa.FmtUnstructured(u))
}

if ssa.IsClusterDefinition(u) {
stageOne = append(stageOne, u)
} else {
stageTwo = append(stageTwo, u)
switch {
case ssa.IsClusterDefinition(u):
defStage = append(defStage, u)
case strings.HasSuffix(u.GetKind(), "Class"):
classStage = append(classStage, u)
default:
resStage = append(resStage, u)
}

}

var changeSetLog strings.Builder

// validate, apply and wait for CRDs and Namespaces to register
if len(stageOne) > 0 {
changeSet, err := manager.ApplyAll(ctx, stageOne, applyOpts)
if len(defStage) > 0 {
changeSet, err := manager.ApplyAll(ctx, defStage, applyOpts)
if err != nil {
return false, nil, err
}
resultSet.Append(changeSet.Entries)

if changeSet != nil && len(changeSet.Entries) > 0 {
log.Info("server-side apply completed", "output", changeSet.ToMap())
log.Info("server-side apply for cluster definitions completed", "output", changeSet.ToMap())
for _, change := range changeSet.Entries {
if change.Action != string(ssa.UnchangedAction) {
changeSetLog.WriteString(change.String() + "\n")
}
}
}

if err := manager.Wait(defStage, ssa.WaitOptions{
Interval: 2 * time.Second,
Timeout: kustomization.GetTimeout(),
}); err != nil {
return false, nil, err
}
}

// validate, apply and wait for Class type objects to register
if len(classStage) > 0 {
changeSet, err := manager.ApplyAll(ctx, classStage, applyOpts)
if err != nil {
return false, nil, err
}
resultSet.Append(changeSet.Entries)

if changeSet != nil && len(changeSet.Entries) > 0 {
log.Info("server-side apply for cluster class types completed", "output", changeSet.ToMap())
for _, change := range changeSet.Entries {
if change.Action != string(ssa.UnchangedAction) {
changeSetLog.WriteString(change.String() + "\n")
}
}
}

if err := manager.Wait(stageOne, ssa.WaitOptions{
if err := manager.Wait(classStage, ssa.WaitOptions{
Interval: 2 * time.Second,
Timeout: kustomization.GetTimeout(),
}); err != nil {
Expand All @@ -765,9 +798,9 @@ func (r *KustomizationReconciler) apply(ctx context.Context, manager *ssa.Resour
}

// sort by kind, validate and apply all the others objects
sort.Sort(ssa.SortableUnstructureds(stageTwo))
if len(stageTwo) > 0 {
changeSet, err := manager.ApplyAll(ctx, stageTwo, applyOpts)
sort.Sort(ssa.SortableUnstructureds(resStage))
if len(resStage) > 0 {
changeSet, err := manager.ApplyAll(ctx, resStage, applyOpts)
if err != nil {
return false, nil, fmt.Errorf("%w\n%s", err, changeSetLog.String())
}
Expand Down
5 changes: 2 additions & 3 deletions controllers/kustomization_fetcher_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package controllers
import (
"context"
"fmt"
"strings"
"testing"
"time"

Expand Down Expand Up @@ -135,10 +136,8 @@ stringData:
g.Eventually(func() bool {
_ = k8sClient.Get(context.Background(), client.ObjectKeyFromObject(kustomization), resultK)
ready := apimeta.FindStatusCondition(resultK.Status.Conditions, meta.ReadyCondition)
return ready.Reason == meta.ProgressingReason
return strings.Contains(ready.Message, "artifact not found")
}, timeout, time.Second).Should(BeTrue())

g.Expect(apimeta.FindStatusCondition(resultK.Status.Conditions, meta.ReadyCondition).Message).To(ContainSubstring("artifact not found"))
})

t.Run("recovers after not found errors", func(t *testing.T) {
Expand Down