Skip to content

Implement functions to find referencing ConfigMaps and Secrets in Kubernetes manifests#5409

Merged
Warashi merged 1 commit intomasterfrom
k8s-plugin-find-ref
Dec 12, 2024
Merged

Implement functions to find referencing ConfigMaps and Secrets in Kubernetes manifests#5409
Warashi merged 1 commit intomasterfrom
k8s-plugin-find-ref

Conversation

@Warashi
Copy link
Member

@Warashi Warashi commented Dec 11, 2024

What this PR does:

as title

Why we need it:

I want to implement annotateConfigHash in the k8s plugin.
To implement this, we need to find the configmap and secrets referenced in the deployments.

// annotateConfigHash appends a hash annotation into the workload manifests.
// The hash value is calculated by hashing the content of all configmaps/secrets
// that are referenced by the workload.
// This appending ensures that the workload should be restarted when
// one of its configurations changed.
func annotateConfigHash(manifests []provider.Manifest) error {

Which issue(s) this PR fixes:

Part of #4980

Does this PR introduce a user-facing change?: No

  • How are users affected by this change:
  • Is this breaking change:
  • How to migrate (if breaking change):

…ernetes manifests

Signed-off-by: Shinnosuke Sawada-Dazai <shin@warashi.dev>
@codecov
Copy link

codecov bot commented Dec 11, 2024

Codecov Report

Attention: Patch coverage is 82.35294% with 12 lines in your changes missing coverage. Please review.

Project coverage is 25.81%. Comparing base (e276b89) to head (52a8371).
Report is 2 commits behind head on master.

Files with missing lines Patch % Lines
...p/pipedv1/plugin/kubernetes/provider/deployment.go 82.35% 8 Missing and 4 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #5409      +/-   ##
==========================================
+ Coverage   25.74%   25.81%   +0.06%     
==========================================
  Files         449      450       +1     
  Lines       48452    48520      +68     
==========================================
+ Hits        12474    12524      +50     
- Misses      35005    35019      +14     
- Partials      973      977       +4     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

}
}

func TestFindReferencingConfigMaps(t *testing.T) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test is mainly copied from below

func TestFindReferencingConfigMapsInDeployment(t *testing.T) {

}
}

func TestFindReferencingSecrets(t *testing.T) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this test is mainly copied from below

func TestFindReferencingSecretsInDeployment(t *testing.T) {

// - spec.template.spec.initContainers.envFrom.configMapRef.name
// - spec.template.spec.containers.env.valueFrom.configMapKeyRef.name
// - spec.template.spec.containers.envFrom.configMapRef.name
func FindReferencingConfigMaps(m *unstructured.Unstructured) []string {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I implemented this function with the reference below.

func FindReferencingConfigMapsInDeployment(d *appsv1.Deployment) []string {

// - spec.template.spec.initContainers.envFrom.secretRef.name
// - spec.template.spec.containers.env.valueFrom.secretKeyRef.name
// - spec.template.spec.containers.envFrom.secretRef.name
func FindReferencingSecrets(m *unstructured.Unstructured) []string {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I implemented this function with the reference below.

func FindReferencingSecretsInDeployment(d *appsv1.Deployment) []string {

Comment on lines +93 to +96
// nestedStringSlice extracts a string slice from the given object by following the fields.
// It returns the extracted string slice.
// If there is []map[string]any in the middle of the fields, it will be flattened.
func nestedStringSlice(obj any, fields ...string) []string {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't want to convert the unstructured.Unstructured to appsv1.Deployment or something, so I implemented this.
We cannot use unstructured.NestedStringSlice because it handles the []map[string]any differently.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Warashi
[Ask]

We cannot use unstructured.NestedStringSlice because it handles the []map[string]any differently.

What's the difference between unstructured.NestedStringSlice and nestedStringSlice ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ffjlabo
unstructured.NestedStringSlice returns an error when there is []map[string]any in the middle of the fields. On the other hand, nestedStringSlice flattens it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Warashi
I got your point. I tried to use unstructured.NestedStringSlice with the data below.
We can't find and flatten slices in the []interface{}{map[string]interface{}{}}.

	obj := map[string]interface{}{
		"spec": map[string]interface{}{
			"template": map[string]interface{}{
				"spec": map[string]interface{}{
					"volumes": []interface{}{
						map[string]interface{}{
							"configMap": map[string]interface{}{
								"name": "canary-by-config-change",
							},
						},
					},
				},
			},
		},
	}

	res, exists, err := unstructured.NestedStringSlice(obj, "spec", "template", "spec", "volumes[]", "configMap", "name")
	assert.True(t, exists)
	assert.NoError(t, err)
	assert.Equal(t, res, []string{"canary-by-config-change"})
=== RUN   Test
        	Error:      	Should be true
        	Error:      	Received unexpected error:
        	            	.spec.template.spec.volumes.configMap accessor error: [map[configMap:map[name:canary-by-config-change]]] is of the type []interface {}, expected map[string]interface{}
        	Error:      	Not equal:
        	            	expected: []string(nil)
        	            	actual  : []string{"canary-by-config-change"}

        	            	Diff:
        	            	--- Expected
        	            	+++ Actual
        	            	@@ -1,2 +1,4 @@
        	            	-([]string) <nil>
        	            	+([]string) (len=1) {
        	            	+ (string) (len=23) "canary-by-config-change"
        	            	+}

        	Test:       	Test

The test for unstructured.NestedFieldNoCopy (used in the unstructured.NestedStringSlice) shows it.
https://github.com/kubernetes/apimachinery/blob/master/pkg/apis/meta/v1/unstructured/helpers_test.go#L122

@Warashi Warashi marked this pull request as ready for review December 11, 2024 01:09
Copy link
Member

@khanhtc1202 khanhtc1202 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍

Copy link
Member

@ffjlabo ffjlabo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 🙆‍♂️

@Warashi Warashi merged commit 6b63206 into master Dec 12, 2024
@Warashi Warashi deleted the k8s-plugin-find-ref branch December 12, 2024 07:50
@github-actions github-actions bot mentioned this pull request Jan 21, 2025
@github-actions github-actions bot mentioned this pull request Mar 25, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants