Skip to content

Commit c8d46b2

Browse files
authored
Merge pull request #7845 from knabben/drop-cluster-topo-field
⚠️ Drop ClusterTopologyManagedFieldsAnnotation field from v1beta1
2 parents ed25742 + 331a8a1 commit c8d46b2

File tree

5 files changed

+5
-133
lines changed

5 files changed

+5
-133
lines changed

.golangci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ issues:
222222
# Specific exclude rules for deprecated fields that are still part of the codebase. These should be removed as the referenced deprecated item is removed from the project.
223223
- linters:
224224
- staticcheck
225-
text: "SA1019: (bootstrapv1.ClusterStatus|clusterv1.ClusterTopologyManagedFieldsAnnotation|scope.Config.Spec.UseExperimentalRetryJoin|DockerMachine.Spec.Bootstrapped|machineStatus.Bootstrapped) is deprecated"
225+
text: "SA1019: (bootstrapv1.ClusterStatus|scope.Config.Spec.UseExperimentalRetryJoin|DockerMachine.Spec.Bootstrapped|machineStatus.Bootstrapped) is deprecated"
226226
- linters:
227227
- revive
228228
text: "exported: exported method .*\\.(Reconcile|SetupWithManager|SetupWebhookWithManager) should have comment or be unexported"

api/v1beta1/common_types.go

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -29,22 +29,6 @@ const (
2929
// ClusterTopologyOwnedLabel is the label set on all the object which are managed as part of a ClusterTopology.
3030
ClusterTopologyOwnedLabel = "topology.cluster.x-k8s.io/owned"
3131

32-
// ClusterTopologyManagedFieldsAnnotation is the annotation used to store the list of paths managed
33-
// by the topology controller; changes to those paths will be considered authoritative.
34-
// NOTE: Managed field depends on the last reconciliation of a managed object; this list can
35-
// change during the lifecycle of an object, depending on how the corresponding template + patch/variable
36-
// changes over time.
37-
// NOTE: The topology controller is only concerned about managed paths in the spec; given that
38-
// we are dropping spec. from the result to reduce verbosity of the generated annotation.
39-
// NOTE: Managed paths are relevant only for unstructured objects where it is not possible
40-
// to easily discover which fields have been set by templates + patches/variables at a given reconcile;
41-
// instead, it is not necessary to store managed paths for typed objets (e.g. Cluster, MachineDeployments)
42-
// given that the topology controller explicitly sets a well-known, immutable list of fields at every reconcile.
43-
//
44-
// Deprecated: Topology controller is now using server side apply and this annotation will be removed in a future release.
45-
// When removing also remove from staticcheck exclude-rules for SA1019 in golangci.yml.
46-
ClusterTopologyManagedFieldsAnnotation = "topology.cluster.x-k8s.io/managed-field-paths"
47-
4832
// ClusterTopologyMachineDeploymentNameLabel is the label set on the generated MachineDeployment objects
4933
// to track the name of the MachineDeployment topology it represents.
5034
ClusterTopologyMachineDeploymentNameLabel = "topology.cluster.x-k8s.io/deployment-name"

docs/book/src/developer/providers/v1.3-to-v1.4.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,12 @@ maintainers of providers and consumers of our Go API.
2121
### Removals
2222

2323
- `clusterctl backup` has been removed.
24-
- `MachineHealthCheckSuccededCondition` condition type has been removed.
25-
- `CloneTemplate` and `CloneTemplateInput` has been removed.
26-
- The option `--list-images` from `init` subcommand has been removed.
24+
- `api/v1beta1.MachineHealthCheckSuccededCondition` condition type has been removed.
25+
- `controller/external/util.CloneTemplate` and `controllers/external/util.CloneTemplateInput` has been removed.
26+
- The option `--list-images` from `clusterctl init` subcommand has been removed.
2727
- `exp/runtime/server.NewServer` has been removed.
2828
- `--disable-no-echo` option from `clusterctl describe cluster` subcommand has been removed
29+
- `api/v1beta1.ClusterTopologyManagedFieldsAnnotation` field has been removed.
2930

3031
### API Changes
3132

internal/controllers/topology/cluster/structuredmerge/serversidepathhelper.go

Lines changed: 0 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,12 @@ package structuredmerge
1818

1919
import (
2020
"context"
21-
"encoding/json"
2221

2322
"github.com/pkg/errors"
24-
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2523
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
2624
ctrl "sigs.k8s.io/controller-runtime"
2725
"sigs.k8s.io/controller-runtime/pkg/client"
2826

29-
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
3027
"sigs.k8s.io/cluster-api/util"
3128
)
3229

@@ -59,13 +56,6 @@ func NewServerSidePatchHelper(ctx context.Context, original, modified client.Obj
5956
return nil, errors.Wrap(err, "failed to convert original object to Unstructured")
6057
}
6158
}
62-
63-
// If the object has been created with previous custom approach for tracking managed fields, cleanup the object.
64-
if _, ok := original.GetAnnotations()[clusterv1.ClusterTopologyManagedFieldsAnnotation]; ok {
65-
if err := cleanupLegacyManagedFields(ctx, originalUnstructured, c); err != nil {
66-
return nil, errors.Wrap(err, "failed to cleanup legacy managed fields from original object")
67-
}
68-
}
6959
}
7060

7161
modifiedUnstructured := &unstructured.Unstructured{}
@@ -149,55 +139,3 @@ func (h *serverSidePatchHelper) Patch(ctx context.Context) error {
149139
}
150140
return h.client.Patch(ctx, h.modified, client.Apply, options...)
151141
}
152-
153-
// cleanupLegacyManagedFields cleanups managed field management in place before introducing SSA.
154-
// NOTE: this operation can trigger a machine rollout, but this is considered acceptable given that ClusterClass is still alpha
155-
// and SSA adoption align the topology controller with K8s recommended solution for many controllers authoring the same object.
156-
func cleanupLegacyManagedFields(ctx context.Context, obj *unstructured.Unstructured, c client.Client) error {
157-
base := obj.DeepCopyObject().(*unstructured.Unstructured)
158-
159-
// Remove the topology.cluster.x-k8s.io/managed-field-paths annotation
160-
annotations := obj.GetAnnotations()
161-
delete(annotations, clusterv1.ClusterTopologyManagedFieldsAnnotation)
162-
obj.SetAnnotations(annotations)
163-
164-
// Remove managedFieldEntry for manager=manager and operation=update to prevent having two managers holding values set by the topology controller.
165-
originalManagedFields := obj.GetManagedFields()
166-
managedFields := make([]metav1.ManagedFieldsEntry, 0, len(originalManagedFields))
167-
for i := range originalManagedFields {
168-
if originalManagedFields[i].Manager == "manager" &&
169-
originalManagedFields[i].Operation == metav1.ManagedFieldsOperationUpdate {
170-
continue
171-
}
172-
managedFields = append(managedFields, originalManagedFields[i])
173-
}
174-
175-
// Add a seeding managedFieldEntry for SSA executed by the management controller, to prevent SSA to create/infer
176-
// a default managedFieldEntry when the first SSA is applied.
177-
// More specifically, if an existing object doesn't have managedFields when applying the first SSA the API server
178-
// creates an entry with operation=Update (kind of guessing where the object comes from), but this entry ends up
179-
// acting as a co-ownership and we want to prevent this.
180-
// NOTE: fieldV1Map cannot be empty, so we add metadata.name which will be cleaned up at the first SSA patch.
181-
fieldV1Map := map[string]interface{}{
182-
"f:metadata": map[string]interface{}{
183-
"f:name": map[string]interface{}{},
184-
},
185-
}
186-
fieldV1, err := json.Marshal(fieldV1Map)
187-
if err != nil {
188-
return errors.Wrap(err, "failed to create seeding fieldV1Map for cleaning up legacy managed fields")
189-
}
190-
now := metav1.Now()
191-
managedFields = append(managedFields, metav1.ManagedFieldsEntry{
192-
Manager: TopologyManagerName,
193-
Operation: metav1.ManagedFieldsOperationApply,
194-
APIVersion: obj.GetAPIVersion(),
195-
Time: &now,
196-
FieldsType: "FieldsV1",
197-
FieldsV1: &metav1.FieldsV1{Raw: fieldV1},
198-
})
199-
200-
obj.SetManagedFields(managedFields)
201-
202-
return c.Patch(ctx, obj, client.MergeFrom(base))
203-
}

internal/controllers/topology/cluster/structuredmerge/serversidepathhelper_test.go

Lines changed: 0 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -487,57 +487,6 @@ func TestServerSideApply(t *testing.T) {
487487
})
488488
}
489489

490-
func TestServerSideApply_CleanupLegacyManagedFields(t *testing.T) {
491-
g := NewWithT(t)
492-
// Create a namespace for running the test
493-
ns, err := env.CreateNamespace(ctx, "ssa")
494-
g.Expect(err).ToNot(HaveOccurred())
495-
496-
// Build the test object to work with.
497-
obj := builder.TestInfrastructureCluster(ns.Name, "obj1").WithSpecFields(map[string]interface{}{
498-
"spec.foo": "",
499-
}).Build()
500-
obj.SetAnnotations(map[string]string{clusterv1.ClusterTopologyManagedFieldsAnnotation: "foo"})
501-
502-
t.Run("Server side apply cleanups legacy managed fields", func(t *testing.T) {
503-
g := NewWithT(t)
504-
505-
// Create the object simulating reconcile with legacy managed fields
506-
g.Expect(env.CreateAndWait(ctx, obj.DeepCopy(), client.FieldOwner("manager")))
507-
508-
// Gets the object and create SSA patch helper triggering cleanup.
509-
original := builder.TestInfrastructureCluster("", "").Build()
510-
g.Expect(env.GetAPIReader().Get(ctx, client.ObjectKeyFromObject(obj), original)).To(Succeed())
511-
512-
modified := obj.DeepCopy()
513-
_, err := NewServerSidePatchHelper(ctx, original, modified, env.GetClient())
514-
g.Expect(err).ToNot(HaveOccurred())
515-
516-
// Get created object after cleanup
517-
got := builder.TestInfrastructureCluster("", "").Build()
518-
g.Expect(env.GetAPIReader().Get(ctx, client.ObjectKeyFromObject(obj), got)).To(Succeed())
519-
520-
// Check annotation has been removed
521-
g.Expect(got.GetAnnotations()).ToNot(HaveKey(clusterv1.ClusterTopologyManagedFieldsAnnotation))
522-
523-
// Check managed fields has been fixed
524-
gotManagedFields := got.GetManagedFields()
525-
gotLegacyManager, gotSSAManager := false, false
526-
for i := range gotManagedFields {
527-
if gotManagedFields[i].Manager == "manager" &&
528-
gotManagedFields[i].Operation == metav1.ManagedFieldsOperationUpdate {
529-
gotLegacyManager = true
530-
}
531-
if gotManagedFields[i].Manager == TopologyManagerName &&
532-
gotManagedFields[i].Operation == metav1.ManagedFieldsOperationApply {
533-
gotSSAManager = true
534-
}
535-
}
536-
g.Expect(gotLegacyManager).To(BeFalse())
537-
g.Expect(gotSSAManager).To(BeTrue())
538-
})
539-
}
540-
541490
// getTopologyManagedFields returns metadata.managedFields entry tracking
542491
// server side apply operations for the topology controller.
543492
func getTopologyManagedFields(original client.Object) map[string]interface{} {

0 commit comments

Comments
 (0)