Implement resource pruning in k8s plugin#5455
Conversation
Signed-off-by: Shinnosuke Sawada-Dazai <shin@warashi.dev>
Signed-off-by: Shinnosuke Sawada-Dazai <shin@warashi.dev>
Signed-off-by: Shinnosuke Sawada-Dazai <shin@warashi.dev>
Signed-off-by: Shinnosuke Sawada-Dazai <shin@warashi.dev>
Signed-off-by: Shinnosuke Sawada-Dazai <shin@warashi.dev>
Signed-off-by: Shinnosuke Sawada-Dazai <shin@warashi.dev>
Signed-off-by: Shinnosuke Sawada-Dazai <shin@warashi.dev>
Signed-off-by: Shinnosuke Sawada-Dazai <shin@warashi.dev>
Signed-off-by: Shinnosuke Sawada-Dazai <shin@warashi.dev>
Signed-off-by: Shinnosuke Sawada-Dazai <shin@warashi.dev>
Signed-off-by: Shinnosuke Sawada-Dazai <shin@warashi.dev>
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #5455 +/- ##
==========================================
+ Coverage 26.15% 26.19% +0.04%
==========================================
Files 456 457 +1
Lines 48992 49303 +311
==========================================
+ Hits 12814 12916 +102
- Misses 35156 35362 +206
- Partials 1022 1025 +3 ☔ View full report in Codecov by Sentry. |
Signed-off-by: Shinnosuke Sawada-Dazai <shin@warashi.dev>
Signed-off-by: Shinnosuke Sawada-Dazai <shin@warashi.dev>
| // Set the namespace for all manifests. | ||
| manifests[i].body.SetNamespace(input.Namespace) |
There was a problem hiding this comment.
We need this to ensure the loaded manifests' namespaces are matched with applied resource.
There was a problem hiding this comment.
Oops, we have to check the input.Namespace is empty or not.
| // Add builtin labels and annotations for tracking application live state. | ||
| manifests[i].AddLabels(map[string]string{ | ||
| LabelManagedBy: ManagedByPiped, | ||
| LabelPiped: input.PipedID, | ||
| LabelApplication: input.AppID, | ||
| LabelCommitHash: input.CommitHash, | ||
| }) |
There was a problem hiding this comment.
I want these labels to retrieve live resources when pruning the resources.
Signed-off-by: Shinnosuke Sawada-Dazai <shin@warashi.dev>
ffjlabo
left a comment
There was a problem hiding this comment.
I haven't seen everything yet, but I left some comments 🙏
| // getAPIResources retrieves the list of available API resources from the Kubernetes cluster. | ||
| // It runs the `kubectl api-resources` command with the specified kubeconfig and returns the | ||
| // names of the resources that support the "list", "get", and "delete" verbs. | ||
| func (c *Kubectl) getAPIResources(ctx context.Context, kubeconfig string) ([]string, error) { | ||
| args := []string{"api-resources", "--namespaced=false", "--verbs=list,get,delete", "--output=name"} |
There was a problem hiding this comment.
[nit] How about fixing the name as getClusterScopedAPIResources?
It seems that the method calls kubectl api-resources --namespaced=false.
| groupKind schema.GroupKind | ||
| namespace string | ||
| name string |
There was a problem hiding this comment.
It would be nice to comment on why piped identifies these three values. 🙏
| if namespace == "" { | ||
| args = append(args, "--all-namespaces") |
There was a problem hiding this comment.
[ask] In this case, does the result include the cluster scoped resources?
There was a problem hiding this comment.
The result does not include the cluster scoped resources.
I checked with the kubectl v1.32.0.
$ kubectl version
Client Version: v1.32.0
Kustomize Version: v5.5.0
Server Version: v1.31.0
$ kubectl get all --all-namespaces
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system pod/coredns-6f6b679f8f-czgq7 1/1 Running 0 2d5h
kube-system pod/coredns-6f6b679f8f-j7vcr 1/1 Running 0 2d5h
kube-system pod/etcd-kind-control-plane 1/1 Running 0 2d5h
kube-system pod/kindnet-rxcpn 1/1 Running 0 2d5h
kube-system pod/kube-apiserver-kind-control-plane 1/1 Running 0 2d5h
kube-system pod/kube-controller-manager-kind-control-plane 1/1 Running 0 2d5h
kube-system pod/kube-proxy-58jbg 1/1 Running 0 2d5h
kube-system pod/kube-scheduler-kind-control-plane 1/1 Running 0 2d5h
local-path-storage pod/local-path-provisioner-57c5987fd4-52wtm 1/1 Running 0 2d5h
NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
default service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 2d5h
kube-system service/kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 2d5h
NAMESPACE NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
kube-system daemonset.apps/kindnet 1 1 1 1 1 kubernetes.io/os=linux 2d5h
kube-system daemonset.apps/kube-proxy 1 1 1 1 1 kubernetes.io/os=linux 2d5h
NAMESPACE NAME READY UP-TO-DATE AVAILABLE AGE
kube-system deployment.apps/coredns 2/2 2 2 2d5h
local-path-storage deployment.apps/local-path-provisioner 1/1 1 1 2d5h
NAMESPACE NAME DESIRED CURRENT READY AGE
kube-system replicaset.apps/coredns-6f6b679f8f 2 2 2 2d5h
local-path-storage replicaset.apps/local-path-provisioner-57c5987fd4 1 1 1 2d5h
| nomalizeKey := func(k ResourceKey) ResourceKey { | ||
| // Ignoring APIVersion because user can upgrade to the new APIVersion for the same workload. | ||
| k.apiVersion = "" | ||
| // Normalize the key by removing the default namespace. |
There was a problem hiding this comment.
Can we use k.normalize() or k.normalizeNamespace() ?
There was a problem hiding this comment.
I fixed to use k.normalize() on this commit.
48c0fb3
Signed-off-by: Shinnosuke Sawada-Dazai <shin@warashi.dev>
Signed-off-by: Shinnosuke Sawada-Dazai <shin@warashi.dev>
Signed-off-by: Shinnosuke Sawada-Dazai <shin@warashi.dev>
ffjlabo
left a comment
There was a problem hiding this comment.
Sorry for the more comments 🙏
| return model.StageStatus_STAGE_FAILURE | ||
| } | ||
|
|
||
| clusterLiveResources, err := kubectl.GetAllClusterScoped(ctx, deployTargetConfig.KubeConfigPath, |
There was a problem hiding this comment.
[nit] clusterLiveResources -> clusterScopedLiveResources
| ) | ||
|
|
||
| { | ||
| keys := make(map[ResourceKey]struct{}, len(manifests)) |
There was a problem hiding this comment.
[IMO] How about changing keys -> normalizedKeys to distinguish the original key?
| } | ||
|
|
||
| { | ||
| keys := make(map[ResourceKey]struct{}, len(manifests)) |
There was a problem hiding this comment.
[IMO] How about changing keys -> normalizedKeys to distinguish the original key?
Same as above
| { | ||
| keys := make(map[ResourceKey]struct{}, len(manifests)) | ||
| for _, m := range manifests { | ||
| keys[m.Key().normalize().withoutNamespace()] = struct{}{} |
There was a problem hiding this comment.
[nit] It would be nice to add comment to show why using withoutNamespace()
| func normalizeGroupKind(gk schema.GroupKind) schema.GroupKind { | ||
| gk.Group = strings.ToLower(gk.Group) | ||
| gk.Kind = strings.ToLower(gk.Kind) | ||
| return gk | ||
| } |
There was a problem hiding this comment.
[imo] How about unifying to normalize to avoid using only this method in other code?
Co-authored-by: Yoshiki Fujikane <40124947+ffjlabo@users.noreply.github.com> Signed-off-by: Shinnosuke Sawada-Dazai <shin@warashi.dev>
Signed-off-by: Shinnosuke Sawada-Dazai <shin@warashi.dev>
Signed-off-by: Shinnosuke Sawada-Dazai <shin@warashi.dev>
Signed-off-by: Shinnosuke Sawada-Dazai <shin@warashi.dev>
Signed-off-by: Shinnosuke Sawada-Dazai <shin@warashi.dev>
|
|
||
| running := filepath.Join("./", "testdata", "prune", "running") | ||
|
|
||
| // read the running application config from the example file |
There was a problem hiding this comment.
| // read the running application config from the example file | |
| // read the running application config from the testdata file |
|
|
||
| target := filepath.Join("./", "testdata", "prune", "target") | ||
|
|
||
| // read the running application config from the example file |
There was a problem hiding this comment.
| // read the running application config from the example file | |
| // read the running application config from the testdata file |
| } | ||
|
|
||
| func TestDeploymentService_executeK8sSyncStage(t *testing.T) { | ||
| t.Parallel() |
There was a problem hiding this comment.
[imo] It might not be set to avoid operation collision for each tests. WDYT>
There was a problem hiding this comment.
I think the operation collision does not occur because the envtest's dummy cluster is launched in each test.
There was a problem hiding this comment.
I see. It is in setupTestPluginConfigAndDynamicClient. Thanks, I got your point.
|
|
||
| // The service should be created in the new namespace | ||
| service, err = dynamicClient.Resource(schema.GroupVersionResource{Group: "", Version: "v1", Resource: "services"}).Namespace("test-2").Get(context.Background(), "simple", metav1.GetOptions{}) | ||
| require.NoError(t, err) |
There was a problem hiding this comment.
[imo] If possible, it would be nice to check the error is not found. (I'm not sure about the spec for the dynamic client 🙏
There was a problem hiding this comment.
Thank you. I added the assertion on this commit.
b12e317
| require.Equal(t, "piped", service.GetLabels()["pipecd.dev/managed-by"]) | ||
| require.Equal(t, "piped-id", service.GetLabels()["pipecd.dev/piped"]) | ||
| require.Equal(t, "app-id", service.GetLabels()["pipecd.dev/application"]) | ||
| require.Equal(t, "0012345678", service.GetLabels()["pipecd.dev/commit-hash"]) |
There was a problem hiding this comment.
[imo] In addition to them, we need to check the resource key to check whether the namespace has changed correcty.
There was a problem hiding this comment.
Thank you. I added resource key assertion on this commit.
d75fd94
|
Also imo about the test 🙏
That's all for now 🙏 |
Signed-off-by: Shinnosuke Sawada-Dazai <shin@warashi.dev>
Signed-off-by: Shinnosuke Sawada-Dazai <shin@warashi.dev>
Signed-off-by: Shinnosuke Sawada-Dazai <shin@warashi.dev>
Signed-off-by: Shinnosuke Sawada-Dazai <shin@warashi.dev>
Signed-off-by: Shinnosuke Sawada-Dazai <shin@warashi.dev>
|
@ffjlabo Thanks.
I fixed the tests on this commit.
I added v1beta1 pruning assertions in the cluster-scoped test because it already uses the custom resources. |
|
@Warashi Thank you for the great contribution! Those fixes look good! BTW, I noticed that it might also be nice to add a test case when updating the resource's API version and deleting it (e.g., HPA autoscaling/v1 -> autoscaling/v2, and later remove the resource). |
|
@ffjlabo Thank you!
This PR is already large, so I want to do it on another PR. |
|
@Warashi OK! Thanks! |
What this PR does:
as title
Why we need it:
to prune the resources which removed in the git repository
Which issue(s) this PR fixes:
Part of #4980
Does this PR introduce a user-facing change?: No