def api_resource(): random_suffix = (''.join( random.choice(string.ascii_lowercase) for _ in range(6))) api_resource_name = test_resource_values['API_NAME'] + f'-{random_suffix}' test_resource_values['API_NAME'] = api_resource_name api_ref, api_data = helper.api_ref_and_data( api_resource_name=api_resource_name, replacement_values=test_resource_values) if k8s.get_resource_exists(api_ref): raise Exception( f"expected {api_resource_name} to not exist. Did previous test cleanup?" ) logging.debug( f"http api resource. name: {api_resource_name}, data: {api_data}") k8s.create_custom_resource(api_ref, api_data) cr = k8s.wait_resource_consumed_by_controller(api_ref) assert cr is not None assert k8s.get_resource_exists(api_ref) api_id = cr['status']['apiID'] test_resource_values['API_ID'] = api_id yield api_ref, cr k8s.delete_custom_resource(api_ref)
def route_resource(integration_resource, authorizer_resource): random_suffix = (''.join( random.choice(string.ascii_lowercase) for _ in range(6))) route_resource_name = test_resource_values[ 'ROUTE_NAME'] + f'-{random_suffix}' test_resource_values['ROUTE_NAME'] = route_resource_name route_ref, route_data = helper.route_ref_and_data( route_resource_name=route_resource_name, replacement_values=test_resource_values) if k8s.get_resource_exists(route_ref): raise Exception( f"expected {route_resource_name} to not exist. Did previous test cleanup?" ) logging.debug( f"apigatewayv2 route resource. name: {route_resource_name}, data: {route_data}" ) k8s.create_custom_resource(route_ref, route_data) cr = k8s.wait_resource_consumed_by_controller(route_ref) assert cr is not None assert k8s.get_resource_exists(route_ref) route_id = cr['status']['routeID'] test_resource_values['ROUTE_ID'] = route_id yield route_ref, cr k8s.delete_custom_resource(route_ref)
def stage_resource(route_resource): random_suffix = (''.join( random.choice(string.ascii_lowercase) for _ in range(6))) stage_resource_name = test_resource_values[ 'STAGE_NAME'] + f'-{random_suffix}' test_resource_values['STAGE_NAME'] = stage_resource_name stage_ref, stage_data = helper.stage_ref_and_data( stage_resource_name=stage_resource_name, replacement_values=test_resource_values) if k8s.get_resource_exists(stage_ref): raise Exception( f"expected {stage_resource_name} to not exist. Did previous test cleanup?" ) logging.debug( f"apigatewayv2 stage resource. name: {stage_resource_name}, data: {stage_data}" ) k8s.create_custom_resource(stage_ref, stage_data) cr = k8s.wait_resource_consumed_by_controller(stage_ref) assert cr is not None assert k8s.get_resource_exists(stage_ref) yield stage_ref, cr k8s.delete_custom_resource(stage_ref)
def integration_resource(api_resource): random_suffix = (''.join( random.choice(string.ascii_lowercase) for _ in range(6))) integration_resource_name = test_resource_values[ 'INTEGRATION_NAME'] + f'-{random_suffix}' test_resource_values['INTEGRATION_NAME'] = integration_resource_name integration_ref, integration_data = helper.integration_ref_and_data( integration_resource_name=integration_resource_name, replacement_values=test_resource_values) if k8s.get_resource_exists(integration_ref): raise Exception( f"expected {integration_resource_name} to not exist. Did previous test cleanup?" ) logging.debug( f"apigatewayv2 integration resource. name: {integration_resource_name}, data: {integration_data}" ) k8s.create_custom_resource(integration_ref, integration_data) cr = k8s.wait_resource_consumed_by_controller(integration_ref) assert cr is not None assert k8s.get_resource_exists(integration_ref) integration_id = cr['status']['integrationID'] test_resource_values['INTEGRATION_ID'] = integration_id yield integration_ref, cr k8s.delete_custom_resource(integration_ref)
def test_crud_authorizer(self, api_resource): api_ref, api_cr = api_resource api_id = api_cr['status']['apiID'] test_data = REPLACEMENT_VALUES.copy() authorizer_name = random_suffix_name("ack-test-authorizer", 25) test_data['AUTHORIZER_NAME'] = authorizer_name test_data['AUTHORIZER_TITLE'] = authorizer_name test_data['API_ID'] = api_id test_data['AUTHORIZER_URI'] = f'arn:aws:apigateway:{get_region()}:lambda:path/2015-03-31/functions/{get_bootstrap_resources().AuthorizerFunctionArn}/invocations' authorizer_ref, authorizer_data = helper.authorizer_ref_and_data(authorizer_resource_name=authorizer_name, replacement_values=test_data) logging.debug(f"http api authorizer resource. name: {authorizer_name}, data: {authorizer_data}") # test create k8s.create_custom_resource(authorizer_ref, authorizer_data) time.sleep(CREATE_WAIT_AFTER_SECONDS) assert k8s.wait_on_condition(authorizer_ref, "ACK.ResourceSynced", "True", wait_periods=10) cr = k8s.get_resource(authorizer_ref) assert cr is not None authorizer_id = cr['status']['authorizerID'] # Let's check that the HTTP Api integration appears in Amazon API Gateway apigw_validator.assert_authorizer_is_present(api_id=api_id, authorizer_id=authorizer_id) apigw_validator.assert_authorizer_name( api_id=api_id, authorizer_id=authorizer_id, expected_authorizer_name=authorizer_name ) # test update updated_authorizer_title = 'updated-' + authorizer_name test_data['AUTHORIZER_TITLE'] = updated_authorizer_title updated_authorizer_resource_data = load_apigatewayv2_resource( "authorizer", additional_replacements=test_data, ) logging.debug(f"updated http api authorizer resource: {updated_authorizer_resource_data}") # Update the k8s resource k8s.patch_custom_resource(authorizer_ref, updated_authorizer_resource_data) time.sleep(UPDATE_WAIT_AFTER_SECONDS) condition.assert_synced(authorizer_ref) # Let's check that the HTTP Api authorizer appears in Amazon API Gateway with updated title apigw_validator.assert_authorizer_name( api_id=api_id, authorizer_id=authorizer_id, expected_authorizer_name=updated_authorizer_title ) # test delete k8s.delete_custom_resource(authorizer_ref) time.sleep(DELETE_WAIT_AFTER_SECONDS) assert not k8s.get_resource_exists(authorizer_ref) # HTTP Api authorizer should no longer appear in Amazon API Gateway apigw_validator.assert_authorizer_is_deleted(api_id=api_id, authorizer_id=authorizer_id)
def test_crud_stage(self, api_resource): api_ref, api_cr = api_resource api_id = api_cr['status']['apiID'] test_data = REPLACEMENT_VALUES.copy() random_suffix = (''.join( random.choice(string.ascii_lowercase) for _ in range(6))) stage_name = "ack-test-stage-" + random_suffix test_data['STAGE_NAME'] = stage_name test_data['API_ID'] = api_id stage_ref, stage_data = helper.stage_ref_and_data( stage_resource_name=stage_name, replacement_values=test_data) logging.debug( f"http api stage resource. name: {stage_name}, data: {stage_data}") # test create k8s.create_custom_resource(stage_ref, stage_data) cr = k8s.wait_resource_consumed_by_controller(stage_ref) assert cr is not None assert k8s.get_resource_exists(stage_ref) # Let's check that the HTTP Api integration appears in Amazon API Gateway apigw_validator.assert_stage_is_present(api_id=api_id, stage_name=stage_name) stage_description = test_data['STAGE_DESCRIPTION'] apigw_validator.assert_stage_description( api_id=api_id, stage_name=stage_name, expected_description=stage_description) # test update updated_description = 'updated' + stage_description test_data['STAGE_DESCRIPTION'] = updated_description updated_stage_resource_data = load_apigatewayv2_resource( "stage", additional_replacements=test_data, ) logging.debug( f"updated http api stage resource: {updated_stage_resource_data}") # Update the k8s resource k8s.patch_custom_resource(stage_ref, updated_stage_resource_data) time.sleep(UPDATE_WAIT_AFTER_SECONDS) # Let's check that the HTTP Api stage appears in Amazon API Gateway with updated description apigw_validator.assert_stage_description( api_id=api_id, stage_name=stage_name, expected_description=updated_description) # test delete k8s.delete_custom_resource(stage_ref) time.sleep(DELETE_WAIT_AFTER_SECONDS) assert not k8s.get_resource_exists(stage_ref) # HTTP Api stage should no longer appear in Amazon API Gateway apigw_validator.assert_stage_is_deleted(api_id=api_id, stage_name=stage_name)
def test_smoke(self, lambda_client): resource_name = random_suffix_name("lambda-csc", 24) resources = get_bootstrap_resources() logging.debug(resources) replacements = REPLACEMENT_VALUES.copy() replacements["AWS_REGION"] = get_region() replacements["CODE_SIGNING_CONFIG_NAME"] = resource_name replacements["SIGNING_PROFILE_VERSION_ARN"] = resources.SigningProfileVersionArn # Load Lambda CR resource_data = load_lambda_resource( "code_signing_config", 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) codeSigningConfigARN = cr['status']['ackResourceMetadata']['arn'] time.sleep(CREATE_WAIT_AFTER_SECONDS) # Check Lambda code signing config exists exists = self.code_signing_config_exists(lambda_client, codeSigningConfigARN) assert exists # Update cr cr["spec"]["description"] = "new description" # Patch k8s resource k8s.patch_custom_resource(ref, cr) time.sleep(UPDATE_WAIT_AFTER_SECONDS) # Check code signing config description csc = self.get_code_signing_config(lambda_client, codeSigningConfigARN) assert csc is not None assert csc["Description"] == "new description" # Delete k8s resource _, deleted = k8s.delete_custom_resource(ref) assert deleted time.sleep(DELETE_WAIT_AFTER_SECONDS) # Check Lambda code signing config doesn't exist exists = self.code_signing_config_exists(lambda_client, codeSigningConfigARN) assert not exists
def test_smoke(self, lambda_client, lambda_function): (_, function_resource) = lambda_function lambda_function_name = function_resource["spec"]["name"] resource_name = random_suffix_name("lambda-alias", 24) replacements = REPLACEMENT_VALUES.copy() replacements["AWS_REGION"] = get_region() replacements["ALIAS_NAME"] = resource_name replacements["FUNCTION_NAME"] = lambda_function_name replacements["FUNCTION_VERSION"] = "$LATEST" # Load alias CR resource_data = load_lambda_resource( "alias", 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) # Check alias exists alias = self.alias_exist(lambda_client, resource_name, lambda_function_name) assert alias is not None # Update cr cr["spec"]["description"] = "" # Patch k8s resource k8s.patch_custom_resource(ref, cr) time.sleep(UPDATE_WAIT_AFTER_SECONDS) # Check alias description alias = self.get_alias(lambda_client, resource_name, lambda_function_name) assert alias is not None assert alias["Description"] == "" # Delete k8s resource _, deleted = k8s.delete_custom_resource(ref) assert deleted time.sleep(DELETE_WAIT_AFTER_SECONDS) # Check alias doesn't exist exists = self.get_alias(lambda_client, resource_name, lambda_function_name) assert not exists
def test_create_delete_2az(self, rds_client): resource_name = "my-db-subnet-group" resource_desc = "my-db-subnet-group description" br_resources = get_bootstrap_resources() replacements = REPLACEMENT_VALUES.copy() replacements["DB_SUBNET_GROUP_NAME"] = resource_name replacements["DB_SUBNET_GROUP_DESC"] = resource_desc replacements["SUBNET_AZ1"] = br_resources.SubnetAZ1 replacements["SUBNET_AZ2"] = br_resources.SubnetAZ2 resource_data = load_rds_resource( "db_subnet_group_2az", additional_replacements=replacements, ) logging.debug(resource_data) # Create the 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) # Let's check that the DB subnet group appears in RDS aws_res = rds_client.describe_db_subnet_groups(DBSubnetGroupName=resource_name) assert aws_res is not None assert len(aws_res['DBSubnetGroups']) == 1 now = datetime.datetime.now() timeout = now + datetime.timedelta(seconds=CREATE_TIMEOUT_SECONDS) # TODO(jaypipes): Move this into generic AWS-side waiter while aws_res['DBSubnetGroups'][0]['SubnetGroupStatus'] != "Complete": if datetime.datetime.now() >= timeout: raise Exception("failed to find DB subnet group in Complete status before timeout") time.sleep(CREATE_INTERVAL_SLEEP_SECONDS) aws_res = rds_client.describe_db_subnet_groups(DBSubnetGroupName=resource_name) assert aws_res is not None assert len(aws_res['DBSubnetGroups']) == 1 # Delete the k8s resource on teardown of the module k8s.delete_custom_resource(ref) time.sleep(DELETE_WAIT_AFTER_SECONDS) # DB subnet group should no longer appear in RDS try: aws_res = rds_client.describe_db_subnet_groups(DBSubnetGroupName=resource_name) assert False except rds_client.exceptions.DBSubnetGroupNotFoundFault: pass
def test_repository_lifecycle_policy(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_lifecycle_policy", 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) # Check ECR repository exists repo = self.get_repository(ecr_client, resource_name) assert repo is not None # Check ECR repository lifecycle policy exists lifecycle_policy = self.get_lifecycle_policy(ecr_client, resource_name, repo["registryId"]) assert lifecycle_policy == LIFECYCLE_POLICY_FILTERING_ON_IMAGE_AGE # Remove lifecycle policy cr["spec"]["lifecyclePolicy"] = "" # Patch k8s resource k8s.patch_custom_resource(ref, cr) time.sleep(UPDATE_WAIT_AFTER_SECONDS) lifecycle_policy = self.get_lifecycle_policy(ecr_client, resource_name, repo["registryId"]) assert lifecycle_policy == "" # Delete k8s resource _, deleted = k8s.delete_custom_resource(ref) assert deleted is True time.sleep(DELETE_WAIT_AFTER_SECONDS) # Check ECR repository doesn't exists exists = self.repository_exists(ecr_client, resource_name) assert not exists
def test_crud_integration(self, api_resource): api_ref, api_cr = api_resource api_id = api_cr['status']['apiID'] test_data = REPLACEMENT_VALUES.copy() integration_name = random_suffix_name("ack-test-integration", 25) test_data['INTEGRATION_NAME'] = integration_name test_data['API_ID'] = api_id integration_ref, integration_data = helper.integration_ref_and_data(integration_resource_name=integration_name, replacement_values=test_data) logging.debug(f"http api integration resource. name: {integration_name}, data: {integration_data}") # test create k8s.create_custom_resource(integration_ref, integration_data) time.sleep(CREATE_WAIT_AFTER_SECONDS) assert k8s.wait_on_condition(integration_ref, "ACK.ResourceSynced", "True", wait_periods=10) cr = k8s.get_resource(integration_ref) assert cr is not None integration_id = cr['status']['integrationID'] # Let's check that the HTTP Api integration appears in Amazon API Gateway apigw_validator.assert_integration_is_present(api_id=api_id, integration_id=integration_id) apigw_validator.assert_integration_uri( api_id=api_id, integration_id=integration_id, expected_uri=test_data['INTEGRATION_URI'] ) # test update updated_uri = 'https://httpbin.org/post' test_data['INTEGRATION_URI'] = updated_uri updated_integration_resource_data = load_apigatewayv2_resource( "integration", additional_replacements=test_data, ) logging.debug(f"updated http api integration resource: {updated_integration_resource_data}") # Update the k8s resource k8s.patch_custom_resource(integration_ref, updated_integration_resource_data) time.sleep(UPDATE_WAIT_AFTER_SECONDS) condition.assert_synced(integration_ref) # Let's check that the HTTP Api integration appears in Amazon API Gateway with updated uri apigw_validator.assert_integration_uri( api_id=api_id, integration_id=integration_id, expected_uri=updated_uri ) # test delete k8s.delete_custom_resource(integration_ref) time.sleep(DELETE_WAIT_AFTER_SECONDS) assert not k8s.get_resource_exists(integration_ref) # HTTP Api integration should no longer appear in Amazon API Gateway apigw_validator.assert_integration_is_deleted(api_id=api_id, integration_id=integration_id)
def test_crud_stage(self, api_resource): api_ref, api_cr = api_resource api_id = api_cr['status']['apiID'] test_data = REPLACEMENT_VALUES.copy() stage_name = random_suffix_name("ack-test-stage", 25) test_data['STAGE_NAME'] = stage_name test_data['API_ID'] = api_id stage_ref, stage_data = helper.stage_ref_and_data(stage_resource_name=stage_name, replacement_values=test_data) logging.debug(f"http api stage resource. name: {stage_name}, data: {stage_data}") # test create k8s.create_custom_resource(stage_ref, stage_data) time.sleep(CREATE_WAIT_AFTER_SECONDS) assert k8s.wait_on_condition(stage_ref, "ACK.ResourceSynced", "True", wait_periods=10) cr = k8s.get_resource(stage_ref) assert cr is not None # Let's check that the HTTP Api integration appears in Amazon API Gateway apigw_validator.assert_stage_is_present(api_id=api_id, stage_name=stage_name) stage_description = test_data['STAGE_DESCRIPTION'] apigw_validator.assert_stage_description( api_id=api_id, stage_name=stage_name, expected_description=stage_description ) # test update updated_description = 'updated' + stage_description test_data['STAGE_DESCRIPTION'] = updated_description updated_stage_resource_data = load_apigatewayv2_resource( "stage", additional_replacements=test_data, ) logging.debug(f"updated http api stage resource: {updated_stage_resource_data}") # Update the k8s resource k8s.patch_custom_resource(stage_ref, updated_stage_resource_data) time.sleep(UPDATE_WAIT_AFTER_SECONDS) condition.assert_synced(stage_ref) # Let's check that the HTTP Api stage appears in Amazon API Gateway with updated description apigw_validator.assert_stage_description( api_id=api_id, stage_name=stage_name, expected_description=updated_description ) # test delete k8s.delete_custom_resource(stage_ref) time.sleep(DELETE_WAIT_AFTER_SECONDS) assert not k8s.get_resource_exists(stage_ref) # HTTP Api stage should no longer appear in Amazon API Gateway apigw_validator.assert_stage_is_deleted(api_id=api_id, stage_name=stage_name)
def test_basic_repository(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) # Check ECR repository exists exists = self.repository_exists(ecr_client, resource_name) assert exists # Update CR cr["spec"]["imageScanningConfiguration"]["scanOnPush"] = True # Patch k8s resource k8s.patch_custom_resource(ref, cr) time.sleep(UPDATE_WAIT_AFTER_SECONDS) # Check repository scanOnPush scanning configuration repo = self.get_repository(ecr_client, resource_name) assert repo is not None assert repo["imageScanningConfiguration"]["scanOnPush"] is True # Delete k8s resource _, deleted = k8s.delete_custom_resource(ref) assert deleted is True time.sleep(DELETE_WAIT_AFTER_SECONDS) # Check ECR repository doesn't exists exists = self.repository_exists(ecr_client, resource_name) assert not exists
def test_crud_httpapi_using_import(self): test_data = REPLACEMENT_VALUES.copy() api_name = random_suffix_name("ack-test-importapi", 25) test_data['IMPORT_API_NAME'] = api_name test_data['IMPORT_API_TITLE'] = api_name api_ref, api_data = helper.import_api_ref_and_data(api_resource_name=api_name, replacement_values=test_data) logging.debug(f"imported http api resource. name: {api_name}, data: {api_data}") # test create k8s.create_custom_resource(api_ref, api_data) time.sleep(CREATE_API_WAIT_AFTER_SECONDS) assert k8s.wait_on_condition(api_ref, "ACK.ResourceSynced", "True", wait_periods=10) cr = k8s.get_resource(api_ref) assert cr is not None api_id = cr['status']['apiID'] # Let's check that the imported HTTP Api appears in Amazon API Gateway apigw_validator.assert_api_is_present(api_id=api_id) apigw_validator.assert_api_name( api_id=api_id, expected_api_name=api_name ) # test update updated_api_title = 'updated-' + api_name test_data['IMPORT_API_TITLE'] = updated_api_title updated_api_resource_data = load_apigatewayv2_resource( "import_api", additional_replacements=test_data, ) logging.debug(f"updated import http api resource: {updated_api_resource_data}") # Update the k8s resource k8s.patch_custom_resource(api_ref, updated_api_resource_data) time.sleep(UPDATE_WAIT_AFTER_SECONDS) condition.assert_synced(api_ref) # Let's check that the HTTP Api appears in Amazon API Gateway with updated title apigw_validator.assert_api_name( api_id=api_id, expected_api_name=updated_api_title ) # test delete k8s.delete_custom_resource(api_ref) time.sleep(DELETE_WAIT_AFTER_SECONDS) assert not k8s.get_resource_exists(api_ref) # HTTP Api should no longer appear in Amazon API Gateway apigw_validator.assert_api_is_deleted(api_id=api_id)
def test_smoke(self, dynamodb_client, dynamodb_table): (_, table_resource) = dynamodb_table resource_name = random_suffix_name("backup", 32) table_name = table_resource["spec"]["tableName"] replacements = REPLACEMENT_VALUES.copy() replacements["TABLE_NAME"] = table_name replacements["BACKUP_NAME"] = resource_name # Load Backup CR resource_data = load_dynamodb_resource( "backup", 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) wait_for_cr_status( ref, "backupStatus", "AVAILABLE", 10, 5, ) backupArn = k8s.get_resource_arn(cr) # Check DynamoDB Backup exists exists = self.backup_exists(dynamodb_client, backupArn) assert exists # Delete k8s resource _, deleted = k8s.delete_custom_resource(ref) assert deleted is True time.sleep(DELETE_WAIT_AFTER_SECONDS) # Check DynamoDB Backup doesn't exists exists = self.backup_exists(dynamodb_client, backupArn) assert not exists
def test_crud_httpapi_using_import(self): test_data = REPLACEMENT_VALUES.copy() random_suffix = (''.join( random.choice(string.ascii_lowercase) for _ in range(6))) api_name = "ack-test-importapi-" + random_suffix test_data['API_NAME'] = api_name test_data['API_TITLE'] = api_name api_ref, api_data = helper.import_api_ref_and_data( api_resource_name=api_name, replacement_values=test_data) logging.debug( f"imported http api resource. name: {api_name}, data: {api_data}") # test create k8s.create_custom_resource(api_ref, api_data) cr = k8s.wait_resource_consumed_by_controller(api_ref) assert cr is not None assert k8s.get_resource_exists(api_ref) api_id = cr['status']['apiID'] # Let's check that the imported HTTP Api appears in Amazon API Gateway apigw_validator.assert_api_is_present(api_id=api_id) apigw_validator.assert_api_name(api_id=api_id, expected_api_name=api_name) # test update updated_api_title = 'updated-' + api_name test_data['API_TITLE'] = updated_api_title updated_api_resource_data = load_apigatewayv2_resource( "import_api", additional_replacements=test_data, ) logging.debug( f"updated import http api resource: {updated_api_resource_data}") # Update the k8s resource k8s.patch_custom_resource(api_ref, updated_api_resource_data) time.sleep(UPDATE_WAIT_AFTER_SECONDS) # Let's check that the HTTP Api appears in Amazon API Gateway with updated title apigw_validator.assert_api_name(api_id=api_id, expected_api_name=updated_api_title) # test delete k8s.delete_custom_resource(api_ref) time.sleep(DELETE_WAIT_AFTER_SECONDS) assert not k8s.get_resource_exists(api_ref) # HTTP Api should no longer appear in Amazon API Gateway apigw_validator.assert_api_is_deleted(api_id=api_id)
def test_create_delete(self, dynamodb_client): resource_name = random_suffix_name("table", 32) replacements = REPLACEMENT_VALUES.copy() replacements["TABLE_NAME"] = resource_name # Load Table CR resource_data = load_dynamodb_resource( "table_forums", 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) wait_for_cr_status( ref, "tableStatus", "ACTIVE", 10, 5, ) # Check DynamoDB Table exists exists = self.table_exists(dynamodb_client, resource_name) assert exists # Delete k8s resource _, deleted = k8s.delete_custom_resource(ref) assert deleted is True time.sleep(DELETE_WAIT_AFTER_SECONDS) # Check DynamoDB Table doesn't exists exists = self.table_exists(dynamodb_client, resource_name) assert not exists
def test_smoke(self, dynamodb_client, dynamodb_table): (_, table_resource) = dynamodb_table # Global Tables must have the same name as dynamodb Tables global_table_name = table_resource["spec"]["tableName"] replacements = REPLACEMENT_VALUES.copy() replacements["REGION_NAME"] = get_region() replacements["TABLE_NAME"] = global_table_name replacements["GLOBAL_TABLE_NAME"] = global_table_name # Load GLobal Table CR resource_data = load_dynamodb_resource( "global_table", additional_replacements=replacements, ) logging.debug(resource_data) # Create k8s resource ref = k8s.CustomResourceReference( CRD_GROUP, CRD_VERSION, RESOURCE_PLURAL, global_table_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) wait_for_cr_status( ref, "globalTableStatus", "ACTIVE", 10, 5, ) # Check DynamoDB Global Table exists exists = self.global_table_exists(dynamodb_client, global_table_name) assert exists _, deleted = k8s.delete_custom_resource(ref) assert deleted is True time.sleep(DELETE_WAIT_AFTER_SECONDS) exists = self.global_table_exists(dynamodb_client, global_table_name) assert not exists
def test_create_delete_simple(self, rds_client): resource_name = "my-db-security-group" resource_desc = "my-db-security-group description" br_resources = get_bootstrap_resources() replacements = REPLACEMENT_VALUES.copy() replacements["DB_SECURITY_GROUP_NAME"] = resource_name replacements["DB_SECURITY_GROUP_DESC"] = resource_desc resource_data = load_rds_resource( "db_security_group_simple", additional_replacements=replacements, ) logging.debug(resource_data) # Create the 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) # Let's check that the DB security group appears in RDS aws_res = rds_client.describe_db_security_groups( DBSecurityGroupName=resource_name) assert aws_res is not None assert len(aws_res['DBSecurityGroups']) == 1 # Delete the k8s resource on teardown of the module k8s.delete_custom_resource(ref) time.sleep(DELETE_WAIT_AFTER_SECONDS) # DB security group should no longer appear in RDS try: aws_res = rds_client.describe_db_security_groups( DBSecurityGroupName=resource_name) assert False except rds_client.exceptions.DBSecurityGroupNotFoundFault: pass
def test_create_delete_aurora_mysql5_7(self, rds_client): resource_name = "aurora-mysql-5-7" resource_desc = "Parameters for Aurora MySQL 5.7-compatible" replacements = REPLACEMENT_VALUES.copy() replacements["DB_CLUSTER_PARAMETER_GROUP_NAME"] = resource_name replacements["DB_CLUSTER_PARAMETER_GROUP_DESC"] = resource_desc resource_data = load_rds_resource( "db_cluster_parameter_group_aurora_mysql5.7", additional_replacements=replacements, ) logging.debug(resource_data) # Create the 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) # Let's check that the DB cluster parameter group appears in RDS aws_res = rds_client.describe_db_cluster_parameter_groups( DBClusterParameterGroupName=resource_name, ) assert aws_res is not None assert len(aws_res['DBClusterParameterGroups']) == 1 # Delete the k8s resource on teardown of the module k8s.delete_custom_resource(ref) time.sleep(DELETE_WAIT_AFTER_SECONDS) # DB cluster parameter group should no longer appear in RDS try: aws_res = rds_client.describe_db_cluster_parameter_groups( DBClusterParameterGroupName=resource_name, ) assert False # NOTE(jaypipes): RDS DescribeDBClusterParameterGroups returns # DBParameterGroupNotFoundFault, *not* DBClusterParameterGroupNotFound. except rds_client.exceptions.DBParameterGroupNotFoundFault: pass
def test_create_delete_postgres13_standard(self, rds_client): resource_name = "pg13-standard" resource_desc = "Parameters for PostgreSQL 13" replacements = REPLACEMENT_VALUES.copy() replacements["DB_PARAMETER_GROUP_NAME"] = resource_name replacements["DB_PARAMETER_GROUP_DESC"] = resource_desc resource_data = load_rds_resource( "db_parameter_group_postgres13_standard", additional_replacements=replacements, ) logging.debug(resource_data) # Create the 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) # Let's check that the DB parameter group appears in RDS aws_res = rds_client.describe_db_parameter_groups( DBParameterGroupName=resource_name) assert aws_res is not None assert len(aws_res['DBParameterGroups']) == 1 # Delete the k8s resource on teardown of the module k8s.delete_custom_resource(ref) time.sleep(DELETE_WAIT_AFTER_SECONDS) # DB parameter group should no longer appear in RDS try: aws_res = rds_client.describe_db_parameter_groups( DBParameterGroupName=resource_name) assert False except rds_client.exceptions.DBParameterGroupNotFoundFault: pass
def stage_resource(route_resource): stage_resource_name = random_suffix_name(test_resource_values['STAGE_NAME'], 10) test_resource_values['STAGE_NAME'] = stage_resource_name stage_ref, stage_data = helper.stage_ref_and_data(stage_resource_name=stage_resource_name, replacement_values=test_resource_values) logging.debug(f"apigatewayv2 stage resource. name: {stage_resource_name}, data: {stage_data}") k8s.create_custom_resource(stage_ref, stage_data) time.sleep(CREATE_WAIT_AFTER_SECONDS) assert k8s.wait_on_condition(stage_ref, "ACK.ResourceSynced", "True", wait_periods=10) cr = k8s.get_resource(stage_ref) assert cr is not None yield stage_ref, cr k8s.delete_custom_resource(stage_ref)
def authorizer_resource(api_resource): random_suffix = (''.join( random.choice(string.ascii_lowercase) for _ in range(6))) authorizer_resource_name = test_resource_values[ 'AUTHORIZER_NAME'] + f'-{random_suffix}' test_resource_values['AUTHORIZER_NAME'] = authorizer_resource_name authorizer_uri = f'arn:aws:apigateway:{get_region()}:lambda:path/2015-03-31/functions/{get_bootstrap_resources().AuthorizerFunctionArn}/invocations' test_resource_values["AUTHORIZER_URI"] = authorizer_uri authorizer_ref, authorizer_data = helper.authorizer_ref_and_data( authorizer_resource_name=authorizer_resource_name, replacement_values=test_resource_values) if k8s.get_resource_exists(authorizer_ref): raise Exception( f"expected {authorizer_resource_name} to not exist. Did previous test cleanup?" ) logging.debug( f"apigatewayv2 authorizer resource. name: {authorizer_resource_name}, data: {authorizer_data}" ) k8s.create_custom_resource(authorizer_ref, authorizer_data) cr = k8s.wait_resource_consumed_by_controller(authorizer_ref) assert cr is not None assert k8s.get_resource_exists(authorizer_ref) authorizer_id = cr['status']['authorizerID'] test_resource_values['AUTHORIZER_ID'] = authorizer_id # add permissions for apigateway to invoke authorizer lambda authorizer_arn = "arn:aws:execute-api:{region}:{account}:{api_id}/authorizers/{authorizer_id}".format( region=get_region(), account=get_account_id(), api_id=test_resource_values['API_ID'], authorizer_id=authorizer_id) lambda_client = boto3.client("lambda") lambda_client.add_permission( FunctionName=get_bootstrap_resources().AuthorizerFunctionName, StatementId= f'apigatewayv2-authorizer-invoke-permissions-{random_suffix}', Action='lambda:InvokeFunction', Principal='apigateway.amazonaws.com', SourceArn=authorizer_arn) yield authorizer_ref, cr k8s.delete_custom_resource(authorizer_ref)
def route_resource(integration_resource, authorizer_resource): route_resource_name = random_suffix_name(test_resource_values['ROUTE_NAME'], 25) test_resource_values['ROUTE_NAME'] = route_resource_name route_ref, route_data = helper.route_ref_and_data(route_resource_name=route_resource_name, replacement_values=test_resource_values) k8s.create_custom_resource(route_ref, route_data) time.sleep(CREATE_WAIT_AFTER_SECONDS) assert k8s.wait_on_condition(route_ref, "ACK.ResourceSynced", "True", wait_periods=10) cr = k8s.get_resource(route_ref) assert cr is not None route_id = cr['status']['routeID'] test_resource_values['ROUTE_ID'] = route_id yield route_ref, cr k8s.delete_custom_resource(route_ref)
def lambda_function(): resource_name = random_suffix_name("lambda-function", 24) resources = get_bootstrap_resources() replacements = REPLACEMENT_VALUES.copy() replacements["FUNCTION_NAME"] = resource_name replacements["BUCKET_NAME"] = resources.FunctionsBucketName replacements["LAMBDA_ROLE"] = resources.LambdaESMRoleARN replacements["LAMBDA_FILE_NAME"] = resources.LambdaFunctionFileZip replacements["RESERVED_CONCURRENT_EXECUTIONS"] = "0" replacements["CODE_SIGNING_CONFIG_ARN"] = "" replacements["AWS_REGION"] = get_region() # Load function CR resource_data = load_lambda_resource( "function", additional_replacements=replacements, ) logging.debug(resource_data) # Create k8s resource function_reference = k8s.CustomResourceReference( CRD_GROUP, CRD_VERSION, "functions", resource_name, namespace="default", ) # Create lambda function k8s.create_custom_resource(function_reference, resource_data) function_resource = k8s.wait_resource_consumed_by_controller( function_reference) assert function_resource is not None assert k8s.get_resource_exists(function_reference) time.sleep(CREATE_WAIT_AFTER_SECONDS) yield (function_reference, function_resource) _, deleted = k8s.delete_custom_resource(function_reference) assert deleted
def _make_replication_group(yaml_name, input_dict, rg_name): rg = load_elasticache_resource( yaml_name, additional_replacements=input_dict) logging.debug(rg) reference = k8s.CustomResourceReference( CRD_GROUP, CRD_VERSION, RESOURCE_PLURAL, rg_name, namespace="default") _ = k8s.create_custom_resource(reference, rg) resource = k8s.wait_resource_consumed_by_controller(reference, wait_periods=10) assert resource is not None return (reference, resource)
def api_resource(): api_resource_name = random_suffix_name(test_resource_values['API_NAME'], 20) test_resource_values['API_NAME'] = api_resource_name api_ref, api_data = helper.api_ref_and_data(api_resource_name=api_resource_name, replacement_values=test_resource_values) if k8s.get_resource_exists(api_ref): raise Exception(f"expected {api_resource_name} to not exist. Did previous test cleanup?") logging.debug(f"http api resource. name: {api_resource_name}, data: {api_data}") k8s.create_custom_resource(api_ref, api_data) time.sleep(CREATE_API_WAIT_AFTER_SECONDS) assert k8s.wait_on_condition(api_ref, "ACK.ResourceSynced", "True", wait_periods=10) cr = k8s.get_resource(api_ref) assert cr is not None api_id = cr['status']['apiID'] test_resource_values['API_ID'] = api_id yield api_ref, cr k8s.delete_custom_resource(api_ref)
def dynamodb_table(): resource_name = random_suffix_name("table", 32) replacements = REPLACEMENT_VALUES.copy() replacements["TABLE_NAME"] = resource_name # load resource resource_data = load_dynamodb_resource( "table_forums", additional_replacements=replacements, ) table_reference = k8s.CustomResourceReference( CRD_GROUP, CRD_VERSION, "tables", resource_name, namespace="default", ) # Create table k8s.create_custom_resource(table_reference, resource_data) table_resource = k8s.wait_resource_consumed_by_controller(table_reference) assert table_resource is not None assert k8s.get_resource_exists(table_reference) wait_for_cr_status( table_reference, "tableStatus", "ACTIVE", 10, 30, ) yield (table_reference, table_resource) _, deleted = k8s.delete_custom_resource(table_reference) assert deleted
def code_signing_config(): resource_name = random_suffix_name("lambda-csc", 24) resources = get_bootstrap_resources() logging.debug(resources) replacements = REPLACEMENT_VALUES.copy() replacements["AWS_REGION"] = get_region() replacements["CODE_SIGNING_CONFIG_NAME"] = resource_name replacements[ "SIGNING_PROFILE_VERSION_ARN"] = resources.SigningProfileVersionArn # Load Lambda CR resource_data = load_lambda_resource( "code_signing_config", additional_replacements=replacements, ) logging.debug(resource_data) # Create k8s resource ref = k8s.CustomResourceReference( CRD_GROUP, CRD_VERSION, "codesigningconfigs", 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) yield (ref, cr) _, deleted = k8s.delete_custom_resource(ref) assert deleted
def integration_resource(api_resource): integration_resource_name = random_suffix_name(test_resource_values['INTEGRATION_NAME'], 25) test_resource_values['INTEGRATION_NAME'] = integration_resource_name integration_ref, integration_data = helper.integration_ref_and_data( integration_resource_name=integration_resource_name, replacement_values=test_resource_values) if k8s.get_resource_exists(integration_ref): raise Exception(f"expected {integration_resource_name} to not exist. Did previous test cleanup?") logging.debug(f"apigatewayv2 integration resource. name: {integration_resource_name}, data: {integration_data}") k8s.create_custom_resource(integration_ref, integration_data) time.sleep(CREATE_WAIT_AFTER_SECONDS) assert k8s.wait_on_condition(integration_ref, "ACK.ResourceSynced", "True", wait_periods=10) cr = k8s.get_resource(integration_ref) assert cr is not None integration_id = cr['status']['integrationID'] test_resource_values['INTEGRATION_ID'] = integration_id yield integration_ref, cr k8s.delete_custom_resource(integration_ref)