Skip to content

Commit eb7d989

Browse files
authored
Use new object oriented bootstrapping resource in e2e tests (#147)
Issue #, if available: aws-controllers-k8s/test-infra#63 Description of changes: - Pointing to new version of acktest old method of using bootstrapping is replaced - Updating existing methods to use the new OOP style By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
1 parent 50dc2a3 commit eb7d989

File tree

5 files changed

+50
-140
lines changed

5 files changed

+50
-140
lines changed

test/e2e/bootstrap_resources.py

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,27 +15,30 @@
1515
"""
1616

1717
from dataclasses import dataclass
18-
from acktest.resources import read_bootstrap_config
18+
from acktest.bootstrapping import Resources
19+
from acktest.bootstrapping.iam import Role
20+
from acktest.bootstrapping.s3 import Bucket
1921
from e2e import bootstrap_directory
2022

2123
SAGEMAKER_SOURCE_DATA_BUCKET = "source-data-bucket-592697580195-us-west-2"
2224

2325

2426
@dataclass
25-
class TestBootstrapResources:
26-
DataBucketName: str
27-
ExecutionRoleARN: str
27+
class TestBootstrapResources(Resources):
28+
DataBucket: Bucket
29+
ExecutionRole: Role
2830

2931

3032
_bootstrap_resources = None
3133

3234

33-
def get_bootstrap_resources(bootstrap_file_name: str = "bootstrap.yaml"):
35+
def get_bootstrap_resources(
36+
bootstrap_file_name: str = "bootstrap.pkl",
37+
) -> TestBootstrapResources:
38+
global _bootstrap_resources
3439
global _bootstrap_resources
3540
if _bootstrap_resources is None:
36-
_bootstrap_resources = TestBootstrapResources(
37-
**read_bootstrap_config(
38-
bootstrap_directory, bootstrap_file_name=bootstrap_file_name
39-
),
41+
_bootstrap_resources = TestBootstrapResources.deserialize(
42+
bootstrap_directory, bootstrap_file_name=bootstrap_file_name
4043
)
4144
return _bootstrap_resources

test/e2e/replacement_values.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,12 +181,12 @@
181181
}
182182

183183
REPLACEMENT_VALUES = {
184-
"SAGEMAKER_DATA_BUCKET": get_bootstrap_resources().DataBucketName,
184+
"SAGEMAKER_DATA_BUCKET": get_bootstrap_resources().DataBucket.name,
185185
"XGBOOST_IMAGE_URI": f"{XGBOOST_IMAGE_URIS[get_region()]}/sagemaker-xgboost:1.0-1-cpu-py3",
186186
"DEBUGGER_IMAGE_URI": f"{DEBUGGER_IMAGE_URIS[get_region()]}/sagemaker-debugger-rules:latest",
187187
"XGBOOST_V1_IMAGE_URI": f"{XGBOOST_V1_IMAGE_URIS[get_region()]}/xgboost:latest",
188188
"PYTORCH_TRAIN_IMAGE_URI": f"{PYTORCH_TRAIN_IMAGE_URIS[get_region()]}/pytorch-training:1.5.0-cpu-py36-ubuntu16.04",
189-
"SAGEMAKER_EXECUTION_ROLE_ARN": get_bootstrap_resources().ExecutionRoleARN,
189+
"SAGEMAKER_EXECUTION_ROLE_ARN": get_bootstrap_resources().ExecutionRole.arn,
190190
"MODEL_MONITOR_ANALYZER_IMAGE_URI": f"{MODEL_MONITOR_IMAGE_URIS[get_region()]}/sagemaker-model-monitor-analyzer",
191191
"CLARIFY_IMAGE_URI": f"{CLARIFY_IMAGE_URIS[get_region()]}/sagemaker-clarify-processing:1.0",
192192
"ENDPOINT_INSTANCE_TYPE": ENDPOINT_INSTANCE_TYPES.get(get_region(), "ml.c5.large"),

test/e2e/requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
acktest @ git+https://github.com/aws-controllers-k8s/test-infra.git@6045316542f9699db4aba2829fa0c394eebae8e8
1+
acktest @ git+https://github.com/aws-controllers-k8s/test-infra.git@835781dcbb39e2220e68a659dd771ce4bd9b1ac0
22
black==20.8b1

test/e2e/service_bootstrap.py

Lines changed: 29 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -21,76 +21,18 @@
2121
import random
2222

2323
from acktest import resources
24+
from acktest.bootstrapping import Resources, BootstrapFailureException
25+
from acktest.bootstrapping.iam import Role
26+
from acktest.bootstrapping.s3 import Bucket
2427
from acktest.aws.identity import get_region, get_account_id
2528
from acktest.aws.s3 import duplicate_bucket_contents
2629
from e2e import bootstrap_directory
2730
from e2e.bootstrap_resources import TestBootstrapResources, SAGEMAKER_SOURCE_DATA_BUCKET
2831

2932

30-
def create_execution_role() -> str:
33+
def sync_data_bucket(bucket) -> str:
34+
bucket_name = bucket.name
3135
region = get_region()
32-
role_name = resources.random_suffix_name(f"ack-sagemaker-execution-role", 63)
33-
iam = boto3.client("iam", region_name=region)
34-
35-
iam.create_role(
36-
RoleName=role_name,
37-
AssumeRolePolicyDocument=json.dumps(
38-
{
39-
"Version": "2012-10-17",
40-
"Statement": [
41-
{
42-
"Effect": "Allow",
43-
"Principal": {"Service": "sagemaker.amazonaws.com"},
44-
"Action": "sts:AssumeRole",
45-
}
46-
],
47-
}
48-
),
49-
Description="SageMaker execution role for ACK integration and canary tests",
50-
)
51-
52-
# random sleep to prevent throttling
53-
time.sleep(random.randrange(1, 3))
54-
iam.attach_role_policy(
55-
RoleName=role_name,
56-
PolicyArn="arn:aws:iam::aws:policy/AmazonSageMakerFullAccess",
57-
)
58-
59-
# random sleep to prevent throttling
60-
time.sleep(random.randrange(1, 3))
61-
iam.attach_role_policy(
62-
RoleName=role_name, PolicyArn="arn:aws:iam::aws:policy/AmazonS3FullAccess"
63-
)
64-
65-
iam_resource = iam.get_role(RoleName=role_name)
66-
resource_arn = iam_resource["Role"]["Arn"]
67-
68-
# There appears to be a delay in role availability after role creation
69-
# resulting in failure that role is not present. So adding a delay
70-
# to allow for the role to become available
71-
time.sleep(10)
72-
logging.info(f"Created SageMaker execution role {resource_arn}")
73-
74-
return resource_arn
75-
76-
77-
def create_data_bucket() -> str:
78-
region = get_region()
79-
account_id = get_account_id()
80-
bucket_name = resources.random_suffix_name(
81-
f"ack-data-bucket-{region}-{account_id}", 63
82-
)
83-
84-
s3 = boto3.client("s3", region_name=region)
85-
if region == "us-east-1":
86-
s3.create_bucket(Bucket=bucket_name)
87-
else:
88-
s3.create_bucket(
89-
Bucket=bucket_name, CreateBucketConfiguration={"LocationConstraint": region}
90-
)
91-
92-
logging.info(f"Created SageMaker data bucket {bucket_name}")
93-
9436
s3_resource = boto3.resource("s3", region_name=region)
9537

9638
source_bucket = s3_resource.Bucket(SAGEMAKER_SOURCE_DATA_BUCKET)
@@ -122,18 +64,35 @@ def create_data_bucket() -> str:
12264

12365
logging.info(f"Synced data bucket")
12466

125-
return bucket_name
67+
return bucket
12668

12769

128-
def service_bootstrap() -> dict:
70+
def service_bootstrap() -> Resources:
12971
logging.getLogger().setLevel(logging.INFO)
130-
131-
return TestBootstrapResources(
132-
create_data_bucket(), create_execution_role(),
133-
).__dict__
72+
region = get_region()
73+
account_id = get_account_id()
74+
bucket_name = f"ack-data-bucket-{region}-{account_id}"
75+
76+
resources = TestBootstrapResources(
77+
DataBucket=Bucket(bucket_name),
78+
ExecutionRole=Role(
79+
"ack-sagemaker-execution-role",
80+
"sagemaker.amazonaws.com",
81+
managed_policies=[
82+
"arn:aws:iam::aws:policy/AmazonSageMakerFullAccess",
83+
"arn:aws:iam::aws:policy/AmazonS3FullAccess",
84+
],
85+
),
86+
)
87+
try:
88+
resources.bootstrap()
89+
sync_data_bucket(resources.DataBucket)
90+
except BootstrapFailureException as ex:
91+
exit(254)
92+
return resources
13493

13594

13695
if __name__ == "__main__":
13796
config = service_bootstrap()
13897
# Write config to current directory by default
139-
resources.write_bootstrap_config(config, bootstrap_directory)
98+
config.serialize(bootstrap_directory)

test/e2e/service_cleanup.py

Lines changed: 6 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -13,72 +13,20 @@
1313
"""Cleans up the resources created by the SageMaker bootstrapping process.
1414
"""
1515

16-
import re
17-
import boto3
16+
1817
import logging
1918

20-
from acktest import resources
21-
from acktest.aws.identity import get_region
19+
from acktest.bootstrapping import Resources
2220

2321
from e2e import bootstrap_directory
24-
from e2e.bootstrap_resources import TestBootstrapResources
25-
26-
# Regex to match the role name from a role ARN
27-
IAM_ROLE_ARN_REGEX = r"^arn:aws:iam::\d{12}:(?:root|user|role\/([A-Za-z0-9-]+))$"
28-
29-
30-
def delete_execution_role(role_arn: str):
31-
region = get_region()
32-
iam = boto3.client("iam", region_name=region)
33-
34-
role_name = re.match(IAM_ROLE_ARN_REGEX, role_arn).group(1)
35-
managedPolicy = iam.list_attached_role_policies(RoleName=role_name)
36-
for each in managedPolicy["AttachedPolicies"]:
37-
iam.detach_role_policy(RoleName=role_name, PolicyArn=each["PolicyArn"])
38-
39-
inlinePolicy = iam.list_role_policies(RoleName=role_name)
40-
for each in inlinePolicy["PolicyNames"]:
41-
iam.delete_role_policy(RoleName=role_name, PolicyName=each)
42-
43-
instanceProfiles = iam.list_instance_profiles_for_role(RoleName=role_name)
44-
for each in instanceProfiles["InstanceProfiles"]:
45-
iam.remove_role_from_instance_profile(
46-
RoleName=role_name, InstanceProfileName=each["InstanceProfileName"]
47-
)
48-
iam.delete_role(RoleName=role_name)
4922

50-
logging.info(f"Deleted SageMaker execution role {role_name}")
5123

52-
53-
def delete_data_bucket(bucket_name: str):
54-
region = get_region()
55-
s3_resource = boto3.resource("s3", region_name=region)
56-
57-
bucket = s3_resource.Bucket(bucket_name)
58-
bucket.objects.all().delete()
59-
bucket.delete()
60-
61-
logging.info(f"Deleted data bucket {bucket_name}")
62-
63-
64-
def service_cleanup(config: dict):
24+
def service_cleanup():
6525
logging.getLogger().setLevel(logging.INFO)
6626

67-
resources = TestBootstrapResources(**config)
68-
69-
try:
70-
delete_data_bucket(resources.DataBucketName)
71-
except:
72-
logging.exception(f"Unable to delete data bucket {resources.DataBucketName}")
73-
74-
try:
75-
delete_execution_role(resources.ExecutionRoleARN)
76-
except:
77-
logging.exception(
78-
f"Unable to delete execution role {resources.ExecutionRoleARN}"
79-
)
27+
resources = Resources.deserialize(bootstrap_directory)
28+
resources.cleanup()
8029

8130

8231
if __name__ == "__main__":
83-
bootstrap_config = resources.read_bootstrap_config(bootstrap_directory)
84-
service_cleanup(bootstrap_config)
32+
service_cleanup()

0 commit comments

Comments
 (0)