Skip to content

Commit

Permalink
Add e2e test that adopts bucket created in cloudformation
Browse files Browse the repository at this point in the history
This test expects the ACK controller to always ignore AWS tags.
It also attempts updating the tags and ensures the AWS tags injected
by cloudformation are still ignored.
  • Loading branch information
michaelhtm committed Feb 15, 2025
1 parent b6698d9 commit 73c5a51
Show file tree
Hide file tree
Showing 11 changed files with 223 additions and 7 deletions.
6 changes: 3 additions & 3 deletions apis/v1alpha1/ack-generate-metadata.yaml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
ack_generate_info:
build_date: "2025-02-06T03:32:53Z"
build_hash: 8762917215d9902b2011a2b0b1b0c776855a683e
build_date: "2025-02-15T00:08:47Z"
build_hash: 7582c002da6abe3628e68caf482c705cff6e24f9
go_version: go1.23.5
version: v0.42.0
version: v0.42.0-2-g7582c00-dirty
api_directory_checksum: 12d59cc27a5fc11bf285d7735d81240e980b1046
api_version: v1alpha1
aws_sdk_go_version: v1.32.6
Expand Down
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,5 @@ require (
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
sigs.k8s.io/yaml v1.4.0 // indirect
)

replace github.com/aws-controllers-k8s/runtime => github.com/michaelhtm/ack-runtime v0.42.1-0.20250215000609-2748a4eb9ea8
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
github.com/aws-controllers-k8s/runtime v0.42.0 h1:fVb3cOwUtn0ZwTSedapES+Rspb97S8BTxMqXJt6R5uM=
github.com/aws-controllers-k8s/runtime v0.42.0/go.mod h1:Oy0JKvDxZMZ+SVupm4NZVqP00KLIIAMfk93KnOwlt5c=
github.com/aws/aws-sdk-go v1.49.0 h1:g9BkW1fo9GqKfwg2+zCD+TW/D36Ux+vtfJ8guF4AYmY=
github.com/aws/aws-sdk-go v1.49.0/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go-v2 v1.34.0 h1:9iyL+cjifckRGEVpRKZP3eIxVlL06Qk1Tk13vreaVQU=
Expand Down Expand Up @@ -118,6 +116,8 @@ github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/michaelhtm/ack-runtime v0.42.1-0.20250215000609-2748a4eb9ea8 h1:idU0A8cUjDBwVkDDa9gEgxHCgj+U/7NR0Gxo3W3IdCY=
github.com/michaelhtm/ack-runtime v0.42.1-0.20250215000609-2748a4eb9ea8/go.mod h1:Oy0JKvDxZMZ+SVupm4NZVqP00KLIIAMfk93KnOwlt5c=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
Expand Down
56 changes: 56 additions & 0 deletions pkg/resource/bucket/manager.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

43 changes: 43 additions & 0 deletions pkg/resource/bucket/tags.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions test/e2e/bootstrap_resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from acktest.bootstrapping.iam import Role
from acktest.bootstrapping.s3 import Bucket
from acktest.bootstrapping.sns import Topic
from acktest.bootstrapping.cloudformation import Stack
from e2e import bootstrap_directory

@dataclass
Expand All @@ -28,6 +29,7 @@ class BootstrapResources(Resources):
AdoptionBucket: Bucket
ReplicationRole: Role
NotificationTopic: Topic
StackBucket: Stack

_bootstrap_resources = None

Expand Down
1 change: 1 addition & 0 deletions test/e2e/replacement_values.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,5 @@
"ADOPTION_BUCKET_NAME": get_bootstrap_resources().AdoptionBucket.name,
"REPLICATION_BUCKET_NAME": get_bootstrap_resources().ReplicationBucket.name,
"NOTIFICATION_TOPIC_ARN": get_bootstrap_resources().NotificationTopic.arn,
"STACK_BUCKET_NAME": get_bootstrap_resources().StackBucket.template["Resources"]["MyS3Bucket"]["Properties"]["BucketName"],
}
2 changes: 1 addition & 1 deletion test/e2e/requirements.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
acktest @ git+https://github.com/aws-controllers-k8s/test-infra.git@38ce32256cc2552ab54e190cc8a8618e93af9e0c
acktest @ git+https://github.com/aws-controllers-k8s/test-infra.git@a49300708a1a5586fec36fd28a2494d9cb2288ab
8 changes: 8 additions & 0 deletions test/e2e/resources/bucket_adoption_stack.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
apiVersion: s3.services.k8s.aws/v1alpha1
kind: Bucket
metadata:
name: $STACK_BUCKET_NAME
annotations:
services.k8s.aws/adoption-policy: $ADOPTION_POLICY
services.k8s.aws/adoption-fields: "$ADOPTION_FIELDS"
services.k8s.aws/deletion-policy: retain
21 changes: 20 additions & 1 deletion test/e2e/service_bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@
import json
from pathlib import Path

from acktest.resources import random_suffix_name
from acktest.bootstrapping import Resources, BootstrapFailureException
from acktest.bootstrapping.iam import Role, UserPolicies
from acktest.bootstrapping.s3 import Bucket
from acktest.bootstrapping.sns import Topic
from acktest.bootstrapping.cloudformation import Stack
from e2e import bootstrap_directory
from e2e.bootstrap_resources import BootstrapResources

Expand Down Expand Up @@ -62,13 +64,30 @@ def service_bootstrap() -> Resources:
]
})

stack_bucket_name = random_suffix_name("stack-bucket", 24)
template = {
"AWSTemplateFormatVersion": "2010-09-09",
"Resources": {
"MyS3Bucket": {
"Type": "AWS::S3::Bucket",
"Properties": {
"BucketName": stack_bucket_name,
"VersioningConfiguration": {
"Status": "Enabled"
}
}
}
}
}

resources = BootstrapResources(
ReplicationBucket=Bucket("ack-s3-replication", enable_versioning=True),
AdoptionBucket=Bucket("ack-s3-annotation-adoption", enable_versioning=True),
ReplicationRole=Role("ack-s3-replication-role", "s3.amazonaws.com",
user_policies=UserPolicies("ack-s3-replication-policy", [replication_policy])
),
NotificationTopic=Topic("ack-s3-notification", policy=notification_policy)
NotificationTopic=Topic("ack-s3-notification", policy=notification_policy),
StackBucket=Stack(name_prefix=stack_bucket_name, template=template)
)

try:
Expand Down
85 changes: 85 additions & 0 deletions test/e2e/tests/test_bucket_adoption_policy.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
CREATE_WAIT_AFTER_SECONDS = 10
MODIFY_WAIT_AFTER_SECONDS = 10
DELETE_WAIT_AFTER_SECONDS = 10
ACK_SYSTEM_TAG_PREFIX = "services.k8s.aws/"
AWS_SYSTEM_TAG_PREFIX = "aws:"

class AdoptionPolicy(str, Enum):
NONE = ""
Expand Down Expand Up @@ -66,6 +68,36 @@ def adoption_policy_adopt_bucket(s3_client):
_, deleted = k8s.delete_custom_resource(ref, DELETE_WAIT_AFTER_SECONDS)
assert deleted

@pytest.fixture(scope="module")
def adopt_stack_bucket(s3_client):
replacements = REPLACEMENT_VALUES.copy()
bucket_name = replacements["STACK_BUCKET_NAME"]
replacements["ADOPTION_POLICY"] = AdoptionPolicy.ADOPT
replacements["ADOPTION_FIELDS"] = f'{{\\\"name\\\": \\\"{bucket_name}\\\"}}'

resource_data = load_s3_resource(
"bucket_adoption_stack",
additional_replacements=replacements,
)

# Create k8s resource
ref = k8s.CustomResourceReference(
CRD_GROUP, CRD_VERSION, "buckets",
bucket_name, namespace="default")
k8s.create_custom_resource(ref, resource_data)

time.sleep(CREATE_WAIT_AFTER_SECONDS)
cr = k8s.wait_resource_consumed_by_controller(ref)

assert cr is not None
assert k8s.get_resource_exists(ref)

yield (ref, cr)

_, deleted = k8s.delete_custom_resource(ref, DELETE_WAIT_AFTER_SECONDS)
assert deleted


@service_marker
@pytest.mark.canary
class TestAdoptionPolicyBucket:
Expand Down Expand Up @@ -101,4 +133,57 @@ def test_adoption_policy(
versioning = latest.Versioning()
assert versioning.status == status

def test_adoption_update_tags(
self, s3_client, adopt_stack_bucket, s3_resource
):
(ref, cr) = adopt_stack_bucket

# Spec will be added by controller
assert 'spec' in cr
assert 'name' in cr['spec']
assert 'tagSet' not in cr['spec']['tagging']
bucket_name = cr['spec']['name']

updates = {
"spec": {
"tagging": {
"tagSet": [
{"key": "newKey", "value": "newVal"}
]
}
}
}

k8s.patch_custom_resource(ref, updates)
time.sleep(MODIFY_WAIT_AFTER_SECONDS)

cr = k8s.wait_resource_consumed_by_controller(ref)
assert cr is not None
assert 'spec' in cr
assert 'tagging' in cr['spec']
assert 'tagSet' in cr['spec']['tagging']

latest = get_bucket(s3_resource, bucket_name)
assert latest is not None
tagging = latest.Tagging()

latest = cleanTags(tagging.tag_set)
# +2 here because we want to see if we're also filtering
# through the aws tags, besides just the ack tags
assert len(tagging.tag_set) > len(latest) + 2
desired = cr['spec']['tagging']['tagSet']
for i in range(1):
assert desired[i]["key"] == latest[i]["Key"]
assert desired[i]["value"] == latest[i]["Value"]


def cleanTags(tags: list,
key_member_name: str = 'Key',
) -> list:
if isinstance(tags, list):
return [
t for t in tags if not t[key_member_name].startswith(AWS_SYSTEM_TAG_PREFIX)
and not t[key_member_name].startswith(ACK_SYSTEM_TAG_PREFIX)
]
else:
raise RuntimeError('tags parameter can only be list type')

0 comments on commit 73c5a51

Please sign in to comment.