Commit 2c675b3
* [CASCL-1304] kubectl-datadog: enrich dd-cluster-info ConfigMap
The dd-cluster-info ConfigMap (introduced by #2945) now records:
- the running Karpenter installation (version, namespace, ownership)
under a new `autoscaling` parent that also groups the existing
clusterAutoscaler entry and a new eksAutoMode entry,
- a `managedByDatadog` flag per node-management entity (Fargate
profile, Karpenter NodePool), so a future migration tool can
distinguish Datadog-managed entities to keep from legacy ones to
drain.
Detection helpers `FindKarpenterInstallation` and `IsEKSAutoModeEnabled`
move from `install/guess/` to new `common/karpenter/` and
`common/eksautomode/` packages so the clusterinfo classifier can reuse
them. A generic `commonk8s.FindFirstDeployment` factors out the shared
pager+predicate scan, and `commonk8s.ExtractDeploymentVersion` factors
out the controller-image-tag → label fallback used by both detectors.
Karpenter NodePool ownership uses the broader
`autoscaling.datadoghq.com/created` label only (vs. uninstall's AND-pair
with `app.kubernetes.io/managed-by: kubectl-datadog`) so NodePools
managed by the Datadog cluster agent are also preserved by the
migration tool. Datadog-managed NodePools with no nodes yet (typical
right after install) are seeded into the snapshot with an empty Nodes
list so the migration tool sees the destination NodePools exist.
Fargate profile ownership reads tags via EKS DescribeFargateProfile;
the `managed-by: kubectl-datadog` tag is propagated automatically from
the CloudFormation stack tags, so no infrastructure change is needed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* [CASCL-1304] kubectl-datadog: fix missed call site after merge of #2976
The merge of main into the feature branch (commit 87c6e46) brought in
PR #2976's `update.go`, which referenced `guess.FindKarpenterInstallation`
— the symbol our PR moved to `karpenter.FindInstallation`. The
resolution updated all other call sites but missed this one, so the
build broke on the merge commit.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* [CASCL-1304] kubectl-datadog: pass *Deployment to predicates
The pager-driven scan in commonk8s.FindFirstDeployment yields
*appsv1.Deployment values out of EachListItem, but the predicate
parameter was a value type — forcing a several-hundred-byte struct
copy on every iteration. Switch the predicate signature (and
ExtractDeploymentVersion) to take a pointer, eliminating the copy
in the per-iteration callback.
Container-level predicates (isControllerContainer,
isClusterAutoscalerContainer) keep value semantics because
slices.ContainsFunc requires func(E) bool for []E.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* [CASCL-1304] kubectl-datadog: table-drive FindFirstDeployment tests
Collapse the three predicate-driven tests (NoMatch, ReturnsFirstMatch,
ShortCircuits) into a single table that pins both the returned
Deployment and the predicate-call count per row. The short-circuit
invariant becomes a column rather than a dedicated test, and the row
shape made it cheap to add three previously-uncovered cases (empty
cluster, last deployment matches, multiple matches → first wins).
PropagatesListError stays separate: its setup (PrependReactor) and
assertions (ErrorIs) diverge from the predicate-counting flow.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* [CASCL-1304] kubectl-datadog: centralize managed-by tag constants
The Datadog ownership tag (`managed-by: kubectl-datadog`) is written
on CloudFormation stacks by `aws.buildTags` and propagated by CFN to
the EKS Fargate profile resources. The classifier in clusterinfo reads
those propagated tags to flag Fargate profiles as ManagedByDatadog.
Both ends previously embedded the same string literals; a rename in
buildTags would have silently broken classification. Hoist the pair
to exported constants `aws.ManagedByTag` / `aws.ManagedByTagValue`
and reference them from both writer and reader.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* [CASCL-1304] kubectl-datadog: extract cluster-autoscaler detector to its own package
Mirror the karpenter package's shape — Installation type +
FindInstallation function + private matchesDeployment / matchesContainer
predicates — for the cluster-autoscaler detector, which had stayed
inline in clusterinfo. Both detectors now answer "is the X controller
running on this cluster?" with the same surface and the same package
layout, eliminating the asymmetry that was masking the duplicated
fingerprint pattern.
The unit-level coverage (label variants, image-substring match, version
extraction with image-tag → label fallback, scaled-to-zero treated as
absent) moves to the new common/clusterautoscaler/clusterautoscaler_test.go
table-driven tests. classify_test.go keeps a single integration smoke
test verifying the snapshot wires the detection through.
karpenter.go's predicates are renamed for symmetry: matchesController →
matchesDeployment, isControllerContainer → matchesContainer. Both packages
now expose the same internal vocabulary.
clusterautoscaler.Installation has no IsOwn / InstalledBy /
InstallerVersion fields, on purpose: kubectl-datadog never installs
cluster-autoscaler, only detects it. The asymmetry with karpenter.Installation
reflects an actual behavioural asymmetry.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* [CASCL-1304] kubectl-datadog: list NodePools via the typed client
The kubectl-datadog binary already imports `karpv1 "sigs.k8s.io/karpenter/pkg/apis/v1"`
(via cluster/k8s/nodepool.go and cluster/common/clients/clients.go which
registers `karpv1.NodePool` and `karpv1.NodePoolList` on the controller-runtime
scheme). The justification for going through `unstructured.UnstructuredList`
in `enrichKarpenterOwnership` was therefore wrong — replace it with a typed
`karpv1.NodePoolList` and drop the unstructured import.
The fake controller-runtime client in classify_test.go is updated to mirror
the production scheme (typed NodePool/NodePoolList registration).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* [CASCL-1304] kubectl-datadog: drop redundant empty-bucket guard
`range` over a nil or empty map is a no-op in Go, so the early-return
guard in enrichFargateOwnership was dead code. The function only reads
the bucket (it never initialises it), so no side effect is at risk.
The analogous guard in enrichKarpenterOwnership stays — it prevents
creating an empty NodeManagerKarpenter bucket when no Datadog NodePools
exist, which is a load-bearing semantic.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* [CASCL-1304] kubectl-datadog: gofmt clusterautoscaler_test.go
Struct-field alignment fix that go fmt picked up — the dd-gitlab
check_formatting job runs `make fmt && git diff --exit-code`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* [CASCL-1304] kubectl-datadog: record cluster ARN and AWS region
Per the Slack discussion with Cedric on PR #2980, surface the cluster
identifier in the snapshot so a downstream tool can locate the cluster
unambiguously (the ARN embeds the AWS account, region and short name).
Classify gains a single EKS DescribeCluster call up front, parses the
ARN with aws/arn.Parse to derive the region, and populates two new
fields on ClusterInfo (`clusterArn` / `region`, both `omitempty`). The
EKSDescriber interface grows to expose DescribeCluster alongside the
existing DescribeFargateProfile so the test fake can substitute both.
Best-effort: a DescribeCluster error or a malformed ARN logs a warning
and leaves the fields empty rather than failing the snapshot — same
contract as the other autoscaling detectors.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 47e8393 commit 2c675b3
16 files changed
Lines changed: 1127 additions & 295 deletions
File tree
- cmd/kubectl-datadog/autoscaling/cluster
- apply
- common
- aws
- clusterautoscaler
- clusterinfo
- eksautomode
- k8s
- karpenter
- update
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
21 | 21 | | |
22 | 22 | | |
23 | 23 | | |
| 24 | + | |
24 | 25 | | |
25 | 26 | | |
26 | 27 | | |
| |||
29 | 30 | | |
30 | 31 | | |
31 | 32 | | |
| 33 | + | |
32 | 34 | | |
| 35 | + | |
33 | 36 | | |
34 | 37 | | |
35 | 38 | | |
| |||
107 | 110 | | |
108 | 111 | | |
109 | 112 | | |
110 | | - | |
| 113 | + | |
111 | 114 | | |
112 | 115 | | |
113 | 116 | | |
114 | 117 | | |
115 | 118 | | |
116 | | - | |
| 119 | + | |
117 | 120 | | |
118 | 121 | | |
119 | 122 | | |
| |||
149 | 152 | | |
150 | 153 | | |
151 | 154 | | |
152 | | - | |
| 155 | + | |
153 | 156 | | |
154 | 157 | | |
155 | 158 | | |
| |||
377 | 380 | | |
378 | 381 | | |
379 | 382 | | |
380 | | - | |
| 383 | + | |
381 | 384 | | |
382 | | - | |
383 | | - | |
| 385 | + | |
| 386 | + | |
384 | 387 | | |
385 | 388 | | |
386 | 389 | | |
| |||
463 | 466 | | |
464 | 467 | | |
465 | 468 | | |
466 | | - | |
467 | | - | |
| 469 | + | |
| 470 | + | |
| 471 | + | |
| 472 | + | |
| 473 | + | |
| 474 | + | |
| 475 | + | |
| 476 | + | |
| 477 | + | |
468 | 478 | | |
469 | 479 | | |
470 | 480 | | |
| |||
509 | 519 | | |
510 | 520 | | |
511 | 521 | | |
512 | | - | |
| 522 | + | |
513 | 523 | | |
514 | 524 | | |
515 | 525 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
9 | 9 | | |
10 | 10 | | |
11 | 11 | | |
12 | | - | |
| 12 | + | |
13 | 13 | | |
14 | 14 | | |
15 | 15 | | |
| |||
36 | 36 | | |
37 | 37 | | |
38 | 38 | | |
39 | | - | |
40 | | - | |
41 | | - | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
42 | 42 | | |
43 | 43 | | |
44 | 44 | | |
| |||
102 | 102 | | |
103 | 103 | | |
104 | 104 | | |
105 | | - | |
| 105 | + | |
106 | 106 | | |
107 | 107 | | |
108 | 108 | | |
| |||
Lines changed: 11 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
23 | 23 | | |
24 | 24 | | |
25 | 25 | | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
26 | 36 | | |
27 | 37 | | |
28 | 38 | | |
| |||
54 | 64 | | |
55 | 65 | | |
56 | 66 | | |
57 | | - | |
| 67 | + | |
58 | 68 | | |
59 | 69 | | |
60 | 70 | | |
| |||
Lines changed: 65 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
Lines changed: 143 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
0 commit comments