Skip to content
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

Strip attributes in List resources #802

Merged
merged 3 commits into from
Nov 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 19 additions & 8 deletions flux_local/tool/visitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,23 @@ def update_manifest(self, manifest: Manifest) -> None:
helm_release.images.sort()


def strip_resource_attributes(resource: dict[str, Any], strip_attributes: list[str]) -> None:
"""Strip any annotations from kustomize that contribute to diff noise when objects are re-ordered in the output."""
strip_attrs(resource["metadata"], strip_attributes)
# Remove common noisy labels in commonly used templates
if (
(spec := resource.get("spec"))
and (templ := spec.get("template"))
and (meta := templ.get("metadata"))
):
strip_attrs(meta, strip_attributes)
if resource["kind"] == "List" and (items := resource.get("items")) and isinstance(items, list):
for item in items:
if not (item_meta := item.get("metadata")):
continue
strip_attrs(item_meta, strip_attributes)


class ObjectOutput(ResourceOutput):
"""Resource visitor that builds outputs for objects within the kustomization."""

Expand Down Expand Up @@ -208,14 +225,8 @@ async def call_async(
)
continue
# Remove common noisy labels
strip_attrs(metadata, self.strip_attributes)
# Remove common noisy labels in commonly used templates
if (
(spec := resource.get("spec"))
and (templ := spec.get("template"))
and (meta := templ.get("metadata"))
):
strip_attrs(meta, self.strip_attributes)
strip_resource_attributes(resource, self.strip_attributes)

resource_key = ResourceKey(
kind=kind,
kustomization_path=str(kustomization_path),
Expand Down
250 changes: 250 additions & 0 deletions tests/tool/test_visitor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,250 @@
"""Tests for the visitor module."""

from typing import Any
import yaml

import pytest


from flux_local.tool.visitor import strip_resource_attributes

STRIP_ATTRIBUTES = [
"app.kubernetes.io/version",
"chart",
]


@pytest.mark.parametrize(
("metadata", "expected_metadata"),
[
(
{
"labels": {
"app.kubernetes.io/version": "1.0.0",
"app.kubernetes.io/managed-by": "Helm",
}
},
{
"labels": {
"app.kubernetes.io/managed-by": "Helm",
},
},
),
(
{
"annotations": {
"app.kubernetes.io/version": "1.0.0",
"app.kubernetes.io/managed-by": "Helm",
}
},
{
"annotations": {
"app.kubernetes.io/managed-by": "Helm",
},
},
),
(
{},
{},
),
],
)
def test_strip_resource_attributes(
metadata: dict[str, Any], expected_metadata: dict[str, Any]
) -> None:
"""Test the strip_resource_attributes function."""
resource = {
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": {
"name": "my-configmap",
"namespace": "default",
**metadata,
},
"data": {
"key1": "value1",
"key2": "value2",
},
}
strip_resource_attributes(resource, STRIP_ATTRIBUTES)
assert resource == {
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": {
"name": "my-configmap",
"namespace": "default",
**expected_metadata,
},
"data": {
"key1": "value1",
"key2": "value2",
},
}


def test_strip_deployment_metadata() -> None:
"""Test the strip_resource_attributes function."""
resource = yaml.load(
"""apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
app.kubernetes.io/version: 1.0.0
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
""",
Loader=yaml.Loader,
)

strip_resource_attributes(resource, STRIP_ATTRIBUTES)
assert (
yaml.dump(resource, sort_keys=False)
== """apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
"""
)


def test_strip_list_metadata() -> None:
"""Test the stripping metadata from a list resource."""
resource = yaml.load(
"""apiVersion: v1
items:
- apiVersion: stable.example.com/v1
kind: CronTab
metadata:
annotations:
app: my-cron-tab
app.kubernetes.io/version: 1.0.0
creationTimestamp: '2021-06-20T07:35:27Z'
generation: 1
name: my-new-cron-object
namespace: default
resourceVersion: '1326'
uid: 9aab1d66-628e-41bb-a422-57b8b3b1f5a9
spec:
cronSpec: '* * * * */5'
image: my-awesome-cron-image
kind: List
metadata:
resourceVersion: ''
selfLink: ''

""",
Loader=yaml.Loader,
)

strip_resource_attributes(resource, STRIP_ATTRIBUTES)
assert (
yaml.dump(resource, sort_keys=False)
== """apiVersion: v1
items:
- apiVersion: stable.example.com/v1
kind: CronTab
metadata:
annotations:
app: my-cron-tab
creationTimestamp: '2021-06-20T07:35:27Z'
generation: 1
name: my-new-cron-object
namespace: default
resourceVersion: '1326'
uid: 9aab1d66-628e-41bb-a422-57b8b3b1f5a9
spec:
cronSpec: '* * * * */5'
image: my-awesome-cron-image
kind: List
metadata:
resourceVersion: ''
selfLink: ''
"""
)


def test_strip_list_null_items() -> None:
"""Test corner cases of handling metadata."""
resource = yaml.load(
"""apiVersion: v1
kind: List
metadata:
resourceVersion: ''
selfLink: ''
items:

""",
Loader=yaml.Loader,
)

strip_resource_attributes(resource, STRIP_ATTRIBUTES)
assert (
yaml.dump(resource, sort_keys=False)
== """apiVersion: v1
kind: List
metadata:
resourceVersion: ''
selfLink: ''
items: null
"""
)


def test_strip_list_item_without_metdata() -> None:
"""Test corner cases of handling metadata."""
resource = yaml.load(
"""apiVersion: v1
kind: List
metadata:
resourceVersion: ''
selfLink: ''
items:
- kind: CronTab
""",
Loader=yaml.Loader,
)

strip_resource_attributes(resource, STRIP_ATTRIBUTES)
assert (
yaml.dump(resource, sort_keys=False)
== """apiVersion: v1
kind: List
metadata:
resourceVersion: ''
selfLink: ''
items:
- kind: CronTab
"""
)
Loading