From 6c437e0679d858cac27aa501f9c3596bb532bf06 Mon Sep 17 00:00:00 2001 From: michaelhtm <98621731+michaelhtm@users.noreply.github.com> Date: Sun, 23 Nov 2025 13:30:24 -0800 Subject: [PATCH] test: repository adopt-or-create Add adopt-or-create test for ECR repository --- test/e2e/resources/repository.yaml | 2 + .../resources/repository_adopt_or_create.yaml | 15 ++ test/e2e/tests/test_repository.py | 168 ++++++++++++------ 3 files changed, 128 insertions(+), 57 deletions(-) create mode 100644 test/e2e/resources/repository_adopt_or_create.yaml diff --git a/test/e2e/resources/repository.yaml b/test/e2e/resources/repository.yaml index 394d363..cdaae36 100644 --- a/test/e2e/resources/repository.yaml +++ b/test/e2e/resources/repository.yaml @@ -2,6 +2,8 @@ apiVersion: ecr.services.k8s.aws/v1alpha1 kind: Repository metadata: name: $REPOSITORY_NAME + annotations: + services.k8s.aws/deletion-policy: $DELETION_POLICY spec: name: $REPOSITORY_NAME imageScanningConfiguration: diff --git a/test/e2e/resources/repository_adopt_or_create.yaml b/test/e2e/resources/repository_adopt_or_create.yaml new file mode 100644 index 0000000..f279a13 --- /dev/null +++ b/test/e2e/resources/repository_adopt_or_create.yaml @@ -0,0 +1,15 @@ +apiVersion: ecr.services.k8s.aws/v1alpha1 +kind: Repository +metadata: + name: $REPOSITORY_NAME + annotations: + services.k8s.aws/adoption-policy: adopt-or-create +spec: + name: $REPOSITORY_NAME + imageScanningConfiguration: + scanOnPush: false + imageTagMutability: MUTABLE + tags: + # ensure we update after adoption + - key: key + value: val \ No newline at end of file diff --git a/test/e2e/tests/test_repository.py b/test/e2e/tests/test_repository.py index 95acc88..0c1d88a 100644 --- a/test/e2e/tests/test_repository.py +++ b/test/e2e/tests/test_repository.py @@ -21,6 +21,7 @@ from acktest import tags as tagutil from acktest.resources import random_suffix_name +from acktest import tags as tags from acktest.aws.identity import get_region, get_account_id from acktest.k8s import resource as k8s from e2e import service_marker, CRD_GROUP, CRD_VERSION, load_ecr_resource @@ -43,6 +44,85 @@ def minify_json_string(json_string: str) -> str: return json_string.replace("\n", "").replace(" ", "") +@pytest.fixture +def repository(request): + resource_name = random_suffix_name("ecr-repository", 24) + replacements = REPLACEMENT_VALUES.copy() + replacements["REPOSITORY_NAME"] = resource_name + replacements["DELETION_POLICY"] = "delete" + # Load ECR CR + resource_data = load_ecr_resource( + "repository", + additional_replacements=replacements, + ) + logging.debug(resource_data) + # Create k8s resource + ref = k8s.CustomResourceReference( + CRD_GROUP, CRD_VERSION, RESOURCE_PLURAL, + resource_name, namespace="default", + ) + k8s.create_custom_resource(ref, resource_data) + cr = k8s.wait_resource_consumed_by_controller(ref) + assert cr is not None + assert k8s.get_resource_exists(ref) + + yield (ref, cr) + + if k8s.get_resource_exists(ref): + # Delete k8s resource + _, deleted = k8s.delete_custom_resource(ref) + assert deleted is True + +@pytest.fixture +def repository_adopt_or_create(request): + resource_name = random_suffix_name("ecr-repository", 24) + replacements = REPLACEMENT_VALUES.copy() + replacements["REPOSITORY_NAME"] = resource_name + replacements["DELETION_POLICY"] = "retain" + # Load ECR CR + resource_data = load_ecr_resource( + "repository", + additional_replacements=replacements, + ) + logging.debug(resource_data) + # Create k8s resource + ref = k8s.CustomResourceReference( + CRD_GROUP, CRD_VERSION, RESOURCE_PLURAL, + resource_name, namespace="default", + ) + k8s.create_custom_resource(ref, resource_data) + cr = k8s.wait_resource_consumed_by_controller(ref) + assert cr is not None + assert k8s.get_resource_exists(ref) + assert k8s.wait_on_condition(ref, "ACK.ResourceSynced", "True", wait_periods=5) + + # Delete k8s resource + _, deleted = k8s.delete_custom_resource(ref) + assert deleted is True + + resource_data = load_ecr_resource( + "repository_adopt_or_create", + additional_replacements=replacements, + ) + logging.debug(resource_data) + # Create k8s resource + ref = k8s.CustomResourceReference( + CRD_GROUP, CRD_VERSION, RESOURCE_PLURAL, + resource_name, namespace="default", + ) + k8s.create_custom_resource(ref, resource_data) + + cr = k8s.wait_resource_consumed_by_controller(ref) + assert cr is not None + assert k8s.get_resource_exists(ref) + yield (ref, cr) + + # Delete k8s resource + _, deleted = k8s.delete_custom_resource(ref) + assert deleted is True + + + @service_marker @pytest.mark.canary class TestRepository: @@ -99,33 +179,14 @@ def get_resource_tags(self, ecr_client, resource_arn: str): def repository_exists(self, ecr_client, repository_name: str) -> bool: return self.get_repository(ecr_client, repository_name) is not None - def test_basic_repository(self, ecr_client): - resource_name = random_suffix_name("ecr-repository", 24) + def test_basic_repository(self, ecr_client, repository): + (ref, cr) = repository - replacements = REPLACEMENT_VALUES.copy() - replacements["REPOSITORY_NAME"] = resource_name - # Load ECR CR - resource_data = load_ecr_resource( - "repository", - additional_replacements=replacements, - ) - logging.debug(resource_data) + assert k8s.wait_on_condition(ref, "ACK.ResourceSynced", "True", wait_periods=5) - # Create k8s resource - ref = k8s.CustomResourceReference( - CRD_GROUP, CRD_VERSION, RESOURCE_PLURAL, - resource_name, namespace="default", - ) - k8s.create_custom_resource(ref, resource_data) - cr = k8s.wait_resource_consumed_by_controller(ref) - - assert cr is not None - assert k8s.get_resource_exists(ref) - - time.sleep(CREATE_WAIT_AFTER_SECONDS) - - # Get latest repository CR - cr = k8s.wait_resource_consumed_by_controller(ref) + assert 'spec' in cr + assert 'name' in cr['spec'] + resource_name = cr['spec']['name'] # Check ECR repository exists exists = self.repository_exists(ecr_client, resource_name) @@ -142,16 +203,28 @@ def test_basic_repository(self, ecr_client): repo = self.get_repository(ecr_client, resource_name) assert repo is not None assert repo["imageScanningConfiguration"]["scanOnPush"] is True + + def test_adopt_or_create_repository(self, ecr_client, repository_adopt_or_create): + (ref, cr) = repository_adopt_or_create + assert k8s.wait_on_condition(ref, "ACK.ResourceSynced", "True", wait_periods=5) - # Delete k8s resource - _, deleted = k8s.delete_custom_resource(ref) - assert deleted is True + assert 'spec' in cr + assert 'name' in cr['spec'] + resource_name = cr['spec']['name'] - time.sleep(DELETE_WAIT_AFTER_SECONDS) - - # Check ECR repository doesn't exists + # Check ECR repository exists exists = self.repository_exists(ecr_client, resource_name) - assert not exists + assert exists + + # ensure status fields are populated + assert 'status' in cr + assert 'repositoryURI' in cr['status'] + + # Ensure we update tags after adoption + repository_tags = tagutil.clean(self.get_resource_tags(ecr_client, cr["status"]["ackResourceMetadata"]["arn"])) + desired_tags = cr['spec']['tags'] + assert repository_tags[0]['Key'] == desired_tags[0]['key'] + assert repository_tags[0]['Value'] == desired_tags[0]['value'] def test_repository_lifecycle_policy(self, ecr_client): resource_name = random_suffix_name("ecr-repository", 24) @@ -209,32 +282,13 @@ def test_repository_lifecycle_policy(self, ecr_client): exists = self.repository_exists(ecr_client, resource_name) assert not exists - def test_repository_tags(self, ecr_client): - resource_name = random_suffix_name("ecr-repository", 24) - - replacements = REPLACEMENT_VALUES.copy() - replacements["REPOSITORY_NAME"] = resource_name - # Load ECR CR - resource_data = load_ecr_resource( - "repository", - additional_replacements=replacements, - ) - logging.debug(resource_data) - - # Create k8s resource - ref = k8s.CustomResourceReference( - CRD_GROUP, CRD_VERSION, RESOURCE_PLURAL, - resource_name, namespace="default", - ) - k8s.create_custom_resource(ref, resource_data) - cr = k8s.wait_resource_consumed_by_controller(ref) - - assert cr is not None - assert k8s.get_resource_exists(ref) - - time.sleep(CREATE_WAIT_AFTER_SECONDS) + def test_repository_tags(self, ecr_client, repository): + (ref, cr) = repository + assert k8s.wait_on_condition(ref, "ACK.ResourceSynced", "True", wait_periods=5) - cr = k8s.wait_resource_consumed_by_controller(ref) + assert 'spec' in cr + assert 'name' in cr['spec'] + resource_name = cr['spec']['name'] # Check ECR repository exists exists = self.repository_exists(ecr_client, resource_name)