-
Notifications
You must be signed in to change notification settings - Fork 156
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement resource pruning in k8s plugin #5455
Conversation
Signed-off-by: Shinnosuke Sawada-Dazai <[email protected]>
Signed-off-by: Shinnosuke Sawada-Dazai <[email protected]>
Signed-off-by: Shinnosuke Sawada-Dazai <[email protected]>
Signed-off-by: Shinnosuke Sawada-Dazai <[email protected]>
Signed-off-by: Shinnosuke Sawada-Dazai <[email protected]>
Signed-off-by: Shinnosuke Sawada-Dazai <[email protected]>
Signed-off-by: Shinnosuke Sawada-Dazai <[email protected]>
Signed-off-by: Shinnosuke Sawada-Dazai <[email protected]>
Signed-off-by: Shinnosuke Sawada-Dazai <[email protected]>
Signed-off-by: Shinnosuke Sawada-Dazai <[email protected]>
Signed-off-by: Shinnosuke Sawada-Dazai <[email protected]>
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 <[email protected]>
Signed-off-by: Shinnosuke Sawada-Dazai <[email protected]>
// Set the namespace for all manifests. | ||
manifests[i].body.SetNamespace(input.Namespace) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need this to ensure the loaded manifests' namespaces are matched with applied resource.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I want these labels to retrieve live resources when pruning the resources.
Signed-off-by: Shinnosuke Sawada-Dazai <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nit] How about fixing the name as getClusterScopedAPIResources
?
It seems that the method calls kubectl api-resources --namespaced=false
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I fixed this on this commit.
c2a747f
groupKind schema.GroupKind | ||
namespace string | ||
name string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be nice to comment on why piped identifies these three values. 🙏
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added comments on this commit.
6fb0aab
if namespace == "" { | ||
args = append(args, "--all-namespaces") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[ask] In this case, does the result include the cluster scoped resources?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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
@@ -171,8 +200,7 @@ func FindSameManifests(olds, news []Manifest) []WorkloadPair { | |||
pairs := make([]WorkloadPair, 0) | |||
oldMap := make(map[ResourceKey]Manifest, len(olds)) | |||
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we use k.normalize()
or k.normalizeNamespace()
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I fixed to use k.normalize()
on this commit.
48c0fb3
Signed-off-by: Shinnosuke Sawada-Dazai <[email protected]>
Signed-off-by: Shinnosuke Sawada-Dazai <[email protected]>
Signed-off-by: Shinnosuke Sawada-Dazai <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for the more comments 🙏
return model.StageStatus_STAGE_FAILURE | ||
} | ||
|
||
clusterLiveResources, err := kubectl.GetAllClusterScoped(ctx, deployTargetConfig.KubeConfigPath, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nit] clusterLiveResources -> clusterScopedLiveResources
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
applied on this commit
6392bca
) | ||
|
||
{ | ||
keys := make(map[ResourceKey]struct{}, len(manifests)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[IMO] How about changing keys
-> normalizedKeys
to distinguish the original key?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
applied on this commit
e1dec97
} | ||
|
||
{ | ||
keys := make(map[ResourceKey]struct{}, len(manifests)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[IMO] How about changing keys -> normalizedKeys to distinguish the original key?
Same as above
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
applied on this commit
e1dec97
{ | ||
keys := make(map[ResourceKey]struct{}, len(manifests)) | ||
for _, m := range manifests { | ||
keys[m.Key().normalize().withoutNamespace()] = struct{}{} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nit] It would be nice to add comment to show why using withoutNamespace()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added comments on this commit.
e1dec97
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[imo] How about unifying to normalize
to avoid using only this method in other code?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
applied on this commit.
bcfd121
Co-authored-by: Yoshiki Fujikane <[email protected]> Signed-off-by: Shinnosuke Sawada-Dazai <[email protected]>
Signed-off-by: Shinnosuke Sawada-Dazai <[email protected]>
Signed-off-by: Shinnosuke Sawada-Dazai <[email protected]>
Signed-off-by: Shinnosuke Sawada-Dazai <[email protected]>
Signed-off-by: Shinnosuke Sawada-Dazai <[email protected]>
|
||
running := filepath.Join("./", "testdata", "prune", "running") | ||
|
||
// read the running application config from the example file |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// read the running application config from the example file | |
// read the running application config from the testdata file |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you. applied on this commit.
f47da4b
|
||
target := filepath.Join("./", "testdata", "prune", "target") | ||
|
||
// read the running application config from the example file |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// read the running application config from the example file | |
// read the running application config from the testdata file |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you. applied on this commit.
f47da4b
@@ -136,6 +136,8 @@ func setupTestPluginConfigAndDynamicClient(t *testing.T) (*config.PipedPlugin, d | |||
} | |||
|
|||
func TestDeploymentService_executeK8sSyncStage(t *testing.T) { | |||
t.Parallel() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[imo] It might not be set to avoid operation collision for each tests. WDYT>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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 <[email protected]>
Signed-off-by: Shinnosuke Sawada-Dazai <[email protected]>
Signed-off-by: Shinnosuke Sawada-Dazai <[email protected]>
Signed-off-by: Shinnosuke Sawada-Dazai <[email protected]>
Signed-off-by: Shinnosuke Sawada-Dazai <[email protected]>
@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! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGreatTM 👍
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