From a396f529145a6c9d9d2721dec8f2c707952d9320 Mon Sep 17 00:00:00 2001 From: Lina <210383013+lina-semgrep@users.noreply.github.com> Date: Wed, 9 Jul 2025 17:35:25 -0400 Subject: [PATCH 1/3] feat(setup) allow specifying multiple tag pairs for resources --- src/Setup/utils/DataCollectionSetup.py | 40 +++++++++++++++++++------- src/Setup/utils/MemberSetup.py | 36 +++++++++++++++++++++-- 2 files changed, 63 insertions(+), 13 deletions(-) diff --git a/src/Setup/utils/DataCollectionSetup.py b/src/Setup/utils/DataCollectionSetup.py index 5314114..43ec51c 100644 --- a/src/Setup/utils/DataCollectionSetup.py +++ b/src/Setup/utils/DataCollectionSetup.py @@ -6,14 +6,33 @@ # Get Tag def tag(): - # Get the default AWS region from the current session - tag_key = input("Enter the key to tag the stack (Hit enter to use default: 'App'): ") or "App" + """Get multiple tag key-value pairs from user input""" + tags = {} + + # Get the first tag with defaults + tag_key = input("Enter the first tag key (Hit enter to use default: 'App'): ") or "App" tag_value = input(f"Enter the value for '{tag_key}' (Hit enter to use default: 'Heidi'): ") or "Heidi" - return tag_key, tag_value - + tags[tag_key] = tag_value + + # Allow user to add more tags + while True: + add_more = input("Do you want to add another tag? (yes/no): ").lower().strip() + if add_more in ['yes', 'y']: + tag_key = input("Enter tag key: ").strip() + if tag_key: + tag_value = input(f"Enter value for '{tag_key}': ").strip() + tags[tag_key] = tag_value + else: + print("Tag key cannot be empty. Skipping...") + elif add_more in ['no', 'n']: + break + else: + print("Invalid input. Please enter 'yes' or 'no'.") + + return tags -# Call the tag function to get the tag key and value -tag_key, tag_value = tag() +# Call the tag function to get the tags dictionary +tags_dict = tag() #Get Current Region @@ -76,11 +95,11 @@ def create_or_get_s3_bucket(account_id, region): print(f"S3 bucket {bucket_name} has been created") # Add tags to the newly created bucket - tagging = { - 'TagSet': [{'Key': tag_key, 'Value': tag_value},]} + tag_set = [{'Key': key, 'Value': value} for key, value in tags_dict.items()] + tagging = {'TagSet': tag_set} s3_client.put_bucket_tagging(Bucket=bucket_name, Tagging=tagging) - print(f"Tags added to bucket {bucket_name}") + print(f"Tags added to bucket {bucket_name}: {tags_dict}") return bucket_name, bucketkmsarn @@ -355,8 +374,7 @@ def setup(): f"EnableNotificationModule={parameters_dict['EnableNotificationModule']} " #Update tags here - # Call the tag function to get the tag key and value - tags = f"{tag_key}={tag_value} " + tags = " ".join([f"{key}={value}" for key, value in tags_dict.items()]) command= f"sam deploy --stack-name {stack_name} --region {parameters_dict['DataCollectionRegion']} --parameter-overrides {parameters}\ --template-file ../DataCollectionModule/HeidiRoot.yaml --tags {tags} --capabilities CAPABILITY_NAMED_IAM --disable-rollback" diff --git a/src/Setup/utils/MemberSetup.py b/src/Setup/utils/MemberSetup.py index e0ec569..a921184 100644 --- a/src/Setup/utils/MemberSetup.py +++ b/src/Setup/utils/MemberSetup.py @@ -3,6 +3,36 @@ from botocore.exceptions import ClientError import os +# Get Tag +def tag(): + """Get multiple tag key-value pairs from user input""" + tags = {} + + # Get the first tag with defaults + tag_key = input("Enter the first tag key (Hit enter to use default: 'App'): ") or "App" + tag_value = input(f"Enter the value for '{tag_key}' (Hit enter to use default: 'Heidi'): ") or "Heidi" + tags[tag_key] = tag_value + + # Allow user to add more tags + while True: + add_more = input("Do you want to add another tag? (yes/no): ").lower().strip() + if add_more in ['yes', 'y']: + tag_key = input("Enter tag key: ").strip() + if tag_key: + tag_value = input(f"Enter value for '{tag_key}': ").strip() + tags[tag_key] = tag_value + else: + print("Tag key cannot be empty. Skipping...") + elif add_more in ['no', 'n']: + break + else: + print("Invalid input. Please enter 'yes' or 'no'.") + + return tags + +# Call the tag function to get the tags dictionary +tags_dict = tag() + # Get Current Account ID def get_account_id(): # Get the AWS account ID for Unique names @@ -31,7 +61,6 @@ def print_boxed_text(text): print(f' {line.ljust(max_length)} ') print('═' * (max_length + 2)) - # deploy stack def deploy_stack(command): try: @@ -63,10 +92,13 @@ def setup(): DataCollectionRegion={parameters_dict['DataCollectionRegion']} \ ResourcePrefix={parameters_dict['ResourcePrefix']}" + # Format tags for deployment + tags = " ".join([f"{key}={value}" for key, value in tags_dict.items()]) + for region in DeploymentRegionHealth.split(','): stack_name = f"{parameters_dict['ResourcePrefix']}HealthModule-member-{get_account_id()}-{region}" command = f"sam deploy --stack-name {stack_name} --region {region} --parameter-overrides {parameters} \ - --template-file ../HealthModule/HealthModuleCollectionSetup.yaml --capabilities CAPABILITY_NAMED_IAM --disable-rollback" + --template-file ../HealthModule/HealthModuleCollectionSetup.yaml --tags {tags} --capabilities CAPABILITY_NAMED_IAM --disable-rollback" # Deploy Stack deploy_stack(command) From a3f560c0b235fbb6d7b4b8a7c510fe38657dfba2 Mon Sep 17 00:00:00 2001 From: Lina <210383013+lina-semgrep@users.noreply.github.com> Date: Wed, 16 Jul 2025 12:54:06 -0400 Subject: [PATCH 2/3] fix(tags) enable setting tags via OneClickSetup --- src/Setup/utils/DataCollectionSetup.py | 9 ++++++--- src/Setup/utils/MemberSetup.py | 8 ++++++-- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/Setup/utils/DataCollectionSetup.py b/src/Setup/utils/DataCollectionSetup.py index 43ec51c..3c30384 100644 --- a/src/Setup/utils/DataCollectionSetup.py +++ b/src/Setup/utils/DataCollectionSetup.py @@ -31,9 +31,8 @@ def tag(): return tags -# Call the tag function to get the tags dictionary -tags_dict = tag() - +# Initialize tags_dict - will be populated in setup() +tags_dict = {} #Get Current Region def get_default_region(): @@ -332,6 +331,10 @@ def read_parameters(file_path): } def setup(): + # Get tag information from user + global tags_dict + tags_dict = tag() + file_path = 'utils/ParametersDataCollection.txt' if os.path.exists(file_path): diff --git a/src/Setup/utils/MemberSetup.py b/src/Setup/utils/MemberSetup.py index a921184..2d43735 100644 --- a/src/Setup/utils/MemberSetup.py +++ b/src/Setup/utils/MemberSetup.py @@ -30,8 +30,8 @@ def tag(): return tags -# Call the tag function to get the tags dictionary -tags_dict = tag() +# Initialize tags_dict - will be populated in setup() +tags_dict = {} # Get Current Account ID def get_account_id(): @@ -81,6 +81,10 @@ def get_user_input(): # setup def setup(): + # Get tag information from user + global tags_dict + tags_dict = tag() + parameters_dict = {} DataCollectionAccountID, DataCollectionRegion, DeploymentRegionHealth, ResourcePrefix = get_user_input() From 193a60f3af46b2edb6ddf48377d963908f5db916 Mon Sep 17 00:00:00 2001 From: Lina <210383013+lina-semgrep@users.noreply.github.com> Date: Wed, 6 Aug 2025 12:48:11 -0400 Subject: [PATCH 3/3] workaround --- src/DataCollectionModule/DataCollectionModule.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/DataCollectionModule/DataCollectionModule.yaml b/src/DataCollectionModule/DataCollectionModule.yaml index 1803e56..75a3d8a 100644 --- a/src/DataCollectionModule/DataCollectionModule.yaml +++ b/src/DataCollectionModule/DataCollectionModule.yaml @@ -40,7 +40,7 @@ Parameters: Outputs: HeidiQSDataSourceArn: Condition: DeployDataCollectionComponents - Value: !GetAtt HeidiQSDataSource.Arn + Value: !GetAtt HeidiQSDataSourceV2.Arn Export: Name: !Sub ${ResourcePrefix}QSDataSourceArn HeidiDataCollectionDB: @@ -352,7 +352,7 @@ Resources: Description: "Heidi Data Collection Athena DB" # Create an AWS QuickSight DataSource for DataCollection - HeidiQSDataSource: + HeidiQSDataSourceV2: Condition: DeployDataCollectionComponents Type: AWS::QuickSight::DataSource Properties: