From 424350cb2248e40d639245272befeadee98e1217 Mon Sep 17 00:00:00 2001 From: Will Hodge Date: Fri, 30 Apr 2021 08:03:27 -0700 Subject: [PATCH] Adding FlowDefinition to PutIntegration --- .../aws-customerprofiles-integration.json | 518 +++++++++++++++++- aws-customerprofiles-integration/pom.xml | 2 +- .../integration/CreateHandler.java | 111 ++-- .../integration/Translator.java | 40 ++ .../translators/ConnectorTranslator.java | 9 + .../translators/MarketoTranslator.java | 44 ++ .../integration/translators/S3Translator.java | 45 ++ .../translators/SalesforceTranslator.java | 49 ++ .../translators/ServiceNowTranslator.java | 44 ++ .../translators/TaskTranslator.java | 34 ++ .../translators/TriggerConfigTranslator.java | 38 ++ .../translators/ZendeskTranslator.java | 44 ++ .../integration/CreateHandlerTest.java | 92 +++- .../integration/TranslatorTest.java | 33 +- .../translators/MarketoTranslatorTest.java | 59 ++ .../translators/S3TranslatorTest.java | 60 ++ .../translators/SalesforceTranslatorTest.java | 65 +++ .../translators/ServiceNowTranslatorTest.java | 58 ++ .../translators/TaskTranslatorTest.java | 65 +++ .../integration/translators/TestUtils.java | 132 +++++ .../TriggerConfigTranslatorTest.java | 83 +++ .../translators/ZendeskTranslatorTest.java | 59 ++ 22 files changed, 1638 insertions(+), 46 deletions(-) create mode 100644 aws-customerprofiles-integration/src/main/java/software/amazon/customerprofiles/integration/translators/ConnectorTranslator.java create mode 100644 aws-customerprofiles-integration/src/main/java/software/amazon/customerprofiles/integration/translators/MarketoTranslator.java create mode 100644 aws-customerprofiles-integration/src/main/java/software/amazon/customerprofiles/integration/translators/S3Translator.java create mode 100644 aws-customerprofiles-integration/src/main/java/software/amazon/customerprofiles/integration/translators/SalesforceTranslator.java create mode 100644 aws-customerprofiles-integration/src/main/java/software/amazon/customerprofiles/integration/translators/ServiceNowTranslator.java create mode 100644 aws-customerprofiles-integration/src/main/java/software/amazon/customerprofiles/integration/translators/TaskTranslator.java create mode 100644 aws-customerprofiles-integration/src/main/java/software/amazon/customerprofiles/integration/translators/TriggerConfigTranslator.java create mode 100644 aws-customerprofiles-integration/src/main/java/software/amazon/customerprofiles/integration/translators/ZendeskTranslator.java create mode 100644 aws-customerprofiles-integration/src/test/java/software/amazon/customerprofiles/integration/translators/MarketoTranslatorTest.java create mode 100644 aws-customerprofiles-integration/src/test/java/software/amazon/customerprofiles/integration/translators/S3TranslatorTest.java create mode 100644 aws-customerprofiles-integration/src/test/java/software/amazon/customerprofiles/integration/translators/SalesforceTranslatorTest.java create mode 100644 aws-customerprofiles-integration/src/test/java/software/amazon/customerprofiles/integration/translators/ServiceNowTranslatorTest.java create mode 100644 aws-customerprofiles-integration/src/test/java/software/amazon/customerprofiles/integration/translators/TaskTranslatorTest.java create mode 100644 aws-customerprofiles-integration/src/test/java/software/amazon/customerprofiles/integration/translators/TestUtils.java create mode 100644 aws-customerprofiles-integration/src/test/java/software/amazon/customerprofiles/integration/translators/TriggerConfigTranslatorTest.java create mode 100644 aws-customerprofiles-integration/src/test/java/software/amazon/customerprofiles/integration/translators/ZendeskTranslatorTest.java diff --git a/aws-customerprofiles-integration/aws-customerprofiles-integration.json b/aws-customerprofiles-integration/aws-customerprofiles-integration.json index 825d9e4..14791af 100644 --- a/aws-customerprofiles-integration/aws-customerprofiles-integration.json +++ b/aws-customerprofiles-integration/aws-customerprofiles-integration.json @@ -23,6 +23,518 @@ "Key", "Value" ] + }, + "Object": { + "type": "string", + "maxLength": 512, + "pattern": "\\S+", + "additionalProperties": false + }, + "MarketoSourceProperties": { + "type": "object", + "properties": { + "Object": { + "$ref": "#/definitions/Object" + } + }, + "required": [ + "Object" + ], + "additionalProperties": false + }, + "S3SourceProperties": { + "type": "object", + "properties": { + "BucketName": { + "type": "string", + "minLength": 3, + "maxLength": 63, + "pattern": "\\S+" + }, + "BucketPrefix": { + "type": "string", + "maxLength": 512, + "pattern": ".*" + } + }, + "required": [ + "BucketName" + ], + "additionalProperties": false + }, + "SalesforceSourceProperties": { + "type": "object", + "properties": { + "Object": { + "$ref": "#/definitions/Object" + }, + "EnableDynamicFieldUpdate": { + "type": "boolean" + }, + "IncludeDeletedRecords": { + "type": "boolean" + } + }, + "required": [ + "Object" + ], + "additionalProperties": false + }, + "ServiceNowSourceProperties": { + "type": "object", + "properties": { + "Object": { + "$ref": "#/definitions/Object" + } + }, + "required": [ + "Object" + ], + "additionalProperties": false + }, + "ZendeskSourceProperties": { + "type": "object", + "properties": { + "Object": { + "$ref": "#/definitions/Object" + } + }, + "required": [ + "Object" + ], + "additionalProperties": false + }, + "SourceConnectorProperties": { + "type": "object", + "properties": { + "Marketo": { + "$ref": "#/definitions/MarketoSourceProperties" + }, + "S3": { + "$ref": "#/definitions/S3SourceProperties" + }, + "Salesforce": { + "$ref": "#/definitions/SalesforceSourceProperties" + }, + "ServiceNow": { + "$ref": "#/definitions/ServiceNowSourceProperties" + }, + "Zendesk": { + "$ref": "#/definitions/ZendeskSourceProperties" + } + }, + "additionalProperties": false + }, + "ConnectorType": { + "type": "string", + "enum": [ + "Salesforce", + "Marketo", + "ServiceNow", + "Zendesk", + "S3" + ] + }, + "IncrementalPullConfig": { + "type": "object", + "properties": { + "DatetimeTypeFieldName": { + "type": "string", + "maxLength": 256 + } + }, + "additionalProperties": false + }, + "SourceFlowConfig": { + "type": "object", + "properties": { + "ConnectorType": { + "$ref": "#/definitions/ConnectorType" + }, + "ConnectorProfileName": { + "type": "string", + "maxLength": 256, + "pattern": "[\\w/!@#+=.-]+" + }, + "IncrementalPullConfig": { + "$ref": "#/definitions/IncrementalPullConfig" + }, + "SourceConnectorProperties": { + "$ref": "#/definitions/SourceConnectorProperties" + } + }, + "required": [ + "ConnectorType", + "SourceConnectorProperties" + ], + "additionalProperties": false + }, + "ConnectorOperator": { + "type": "object", + "properties": { + "Marketo": { + "$ref": "#/definitions/MarketoConnectorOperator" + }, + "S3": { + "$ref": "#/definitions/S3ConnectorOperator" + }, + "Salesforce": { + "$ref": "#/definitions/SalesforceConnectorOperator" + }, + "ServiceNow": { + "$ref": "#/definitions/ServiceNowConnectorOperator" + }, + "Zendesk": { + "$ref": "#/definitions/ZendeskConnectorOperator" + } + }, + "additionalProperties": false + }, + "Operator": { + "type": "string", + "enum": [ + "PROJECTION", + "LESS_THAN", + "GREATER_THAN", + "CONTAINS", + "BETWEEN", + "LESS_THAN_OR_EQUAL_TO", + "GREATER_THAN_OR_EQUAL_TO", + "EQUAL_TO", + "NOT_EQUAL_TO", + "ADDITION", + "MULTIPLICATION", + "DIVISION", + "SUBTRACTION", + "MASK_ALL", + "MASK_FIRST_N", + "MASK_LAST_N", + "VALIDATE_NON_NULL", + "VALIDATE_NON_ZERO", + "VALIDATE_NON_NEGATIVE", + "VALIDATE_NUMERIC", + "NO_OP" + ] + }, + "MarketoConnectorOperator": { + "type": "string", + "enum": [ + "PROJECTION", + "LESS_THAN", + "GREATER_THAN", + "BETWEEN", + "ADDITION", + "MULTIPLICATION", + "DIVISION", + "SUBTRACTION", + "MASK_ALL", + "MASK_FIRST_N", + "MASK_LAST_N", + "VALIDATE_NON_NULL", + "VALIDATE_NON_ZERO", + "VALIDATE_NON_NEGATIVE", + "VALIDATE_NUMERIC", + "NO_OP" + ] + }, + "S3ConnectorOperator": { + "type": "string", + "enum": [ + "PROJECTION", + "LESS_THAN", + "GREATER_THAN", + "BETWEEN", + "LESS_THAN_OR_EQUAL_TO", + "GREATER_THAN_OR_EQUAL_TO", + "EQUAL_TO", + "NOT_EQUAL_TO", + "ADDITION", + "MULTIPLICATION", + "DIVISION", + "SUBTRACTION", + "MASK_ALL", + "MASK_FIRST_N", + "MASK_LAST_N", + "VALIDATE_NON_NULL", + "VALIDATE_NON_ZERO", + "VALIDATE_NON_NEGATIVE", + "VALIDATE_NUMERIC", + "NO_OP" + ] + }, + "SalesforceConnectorOperator": { + "type": "string", + "enum": [ + "PROJECTION", + "LESS_THAN", + "GREATER_THAN", + "CONTAINS", + "BETWEEN", + "LESS_THAN_OR_EQUAL_TO", + "GREATER_THAN_OR_EQUAL_TO", + "EQUAL_TO", + "NOT_EQUAL_TO", + "ADDITION", + "MULTIPLICATION", + "DIVISION", + "SUBTRACTION", + "MASK_ALL", + "MASK_FIRST_N", + "MASK_LAST_N", + "VALIDATE_NON_NULL", + "VALIDATE_NON_ZERO", + "VALIDATE_NON_NEGATIVE", + "VALIDATE_NUMERIC", + "NO_OP" + ] + }, + "ServiceNowConnectorOperator": { + "type": "string", + "enum": [ + "PROJECTION", + "LESS_THAN", + "GREATER_THAN", + "CONTAINS", + "BETWEEN", + "LESS_THAN_OR_EQUAL_TO", + "GREATER_THAN_OR_EQUAL_TO", + "EQUAL_TO", + "NOT_EQUAL_TO", + "ADDITION", + "MULTIPLICATION", + "DIVISION", + "SUBTRACTION", + "MASK_ALL", + "MASK_FIRST_N", + "MASK_LAST_N", + "VALIDATE_NON_NULL", + "VALIDATE_NON_ZERO", + "VALIDATE_NON_NEGATIVE", + "VALIDATE_NUMERIC", + "NO_OP" + ] + }, + "ZendeskConnectorOperator": { + "type": "string", + "enum": [ + "PROJECTION", + "GREATER_THAN", + "ADDITION", + "MULTIPLICATION", + "DIVISION", + "SUBTRACTION", + "MASK_ALL", + "MASK_FIRST_N", + "MASK_LAST_N", + "VALIDATE_NON_NULL", + "VALIDATE_NON_ZERO", + "VALIDATE_NON_NEGATIVE", + "VALIDATE_NUMERIC", + "NO_OP" + ] + }, + "OperatorPropertiesKeys": { + "type": "string", + "enum": [ + "VALUE", + "VALUES", + "DATA_TYPE", + "UPPER_BOUND", + "LOWER_BOUND", + "SOURCE_DATA_TYPE", + "DESTINATION_DATA_TYPE", + "VALIDATION_ACTION", + "MASK_VALUE", + "MASK_LENGTH", + "TRUNCATE_LENGTH", + "MATH_OPERATION_FIELDS_ORDER", + "CONCAT_FORMAT", + "SUBFIELD_CATEGORY_MAP" + ] + }, + "DestinationField": { + "type": "string", + "maxLength": 256, + "pattern": ".*" + }, + "TaskType": { + "type": "string", + "enum": [ + "Arithmetic", + "Filter", + "Map", + "Mask", + "Merge", + "Truncate", + "Validate" + ] + }, + "TaskPropertiesMap": { + "type": "object", + "properties": { + "OperatorPropertyKey": { + "$ref": "#/definitions/OperatorPropertiesKeys" + }, + "Property": { + "type": "string", + "maxLength": 2048, + "pattern": ".+" + } + }, + "required": [ + "OperatorPropertyKey", + "Property" + ], + "additionalProperties": false + }, + "Task": { + "type": "object", + "properties": { + "ConnectorOperator": { + "$ref": "#/definitions/ConnectorOperator" + }, + "SourceFields": { + "type": "array", + "items": { + "type": "string", + "maxLength": 2048, + "pattern": ".*" + } + }, + "DestinationField": { + "$ref": "#/definitions/DestinationField" + }, + "TaskType": { + "$ref": "#/definitions/TaskType" + }, + "TaskProperties": { + "type": "array", + "items": { + "$ref": "#/definitions/TaskPropertiesMap" + } + } + }, + "required": [ + "SourceFields", + "TaskType" + ], + "additionalProperties": false + }, + "TriggerType": { + "type": "string", + "enum": [ + "Scheduled", + "Event", + "OnDemand" + ] + }, + "Date": { + "type": "number" + }, + "ScheduledTriggerProperties": { + "type": "object", + "properties": { + "ScheduleExpression": { + "type": "string", + "maxLength": 256, + "pattern": ".*" + }, + "DataPullMode": { + "type": "string", + "enum": [ + "Incremental", + "Complete" + ] + }, + "ScheduleStartTime": { + "$ref": "#/definitions/Date" + }, + "ScheduleEndTime": { + "$ref": "#/definitions/Date" + }, + "Timezone": { + "type": "string", + "maxLength": 256, + "pattern": ".*" + }, + "ScheduleOffset": { + "type": "integer", + "minimum": 0, + "maximum": 36000 + }, + "FirstExecutionFrom": { + "$ref": "#/definitions/Date" + } + }, + "required": [ + "ScheduleExpression" + ], + "additionalProperties": false + }, + "TriggerProperties": { + "type": "object", + "properties": { + "Scheduled": { + "$ref": "#/definitions/ScheduledTriggerProperties" + } + }, + "additionalProperties": false + }, + "TriggerConfig": { + "type": "object", + "properties": { + "TriggerType": { + "$ref": "#/definitions/TriggerType" + }, + "TriggerProperties": { + "$ref": "#/definitions/TriggerProperties" + } + }, + "required": [ + "TriggerType" + ], + "additionalProperties": false + }, + "FlowDefinition": { + "type": "object", + "properties": { + "FlowName": { + "type": "string", + "pattern": "[a-zA-Z0-9][\\w!@#.-]+", + "maxLength": 256 + }, + "Description": { + "type": "string", + "pattern": "[\\w!@#\\-.?,\\s]*", + "maxLength": 2048 + }, + "KmsArn": { + "type": "string", + "pattern": "arn:aws:kms:.*:[0-9]+:.*", + "minLength": 20, + "maxLength": 2048 + }, + "Tasks": { + "type": "array", + "items": { + "$ref": "#/definitions/Task" + } + }, + "TriggerConfig": { + "$ref": "#/definitions/TriggerConfig" + }, + "SourceFlowConfig": { + "$ref": "#/definitions/SourceFlowConfig" + } + }, + "required": [ + "FlowName", + "KMSArn", + "Tasks", + "TriggerConfig", + "SourceFlowConfig" + ], + "additionalProperties": false } }, "properties": { @@ -39,6 +551,9 @@ "minLength": 1, "maxLength": 255 }, + "FlowDefinition": { + "$ref": "#/definitions/FlowDefinition" + }, "ObjectTypeName": { "description": "The name of the ObjectType defined for the 3rd party data in Profile Service", "type": "string", @@ -65,7 +580,8 @@ } }, "required": [ - "DomainName" + "DomainName", + "ObjectTypeName" ], "handlers": { "create": { diff --git a/aws-customerprofiles-integration/pom.xml b/aws-customerprofiles-integration/pom.xml index e57523a..54d4d2b 100644 --- a/aws-customerprofiles-integration/pom.xml +++ b/aws-customerprofiles-integration/pom.xml @@ -22,7 +22,7 @@ software.amazon.awssdk customerprofiles - 2.15.38 + 2.16.44 diff --git a/aws-customerprofiles-integration/src/main/java/software/amazon/customerprofiles/integration/CreateHandler.java b/aws-customerprofiles-integration/src/main/java/software/amazon/customerprofiles/integration/CreateHandler.java index 8901342..f32fe0c 100644 --- a/aws-customerprofiles-integration/src/main/java/software/amazon/customerprofiles/integration/CreateHandler.java +++ b/aws-customerprofiles-integration/src/main/java/software/amazon/customerprofiles/integration/CreateHandler.java @@ -2,6 +2,7 @@ import lombok.NoArgsConstructor; import software.amazon.awssdk.services.customerprofiles.CustomerProfilesClient; +import software.amazon.awssdk.services.customerprofiles.model.AccessDeniedException; import software.amazon.awssdk.services.customerprofiles.model.BadRequestException; import software.amazon.awssdk.services.customerprofiles.model.GetIntegrationRequest; import software.amazon.awssdk.services.customerprofiles.model.GetIntegrationResponse; @@ -9,17 +10,21 @@ import software.amazon.awssdk.services.customerprofiles.model.PutIntegrationRequest; import software.amazon.awssdk.services.customerprofiles.model.PutIntegrationResponse; import software.amazon.awssdk.services.customerprofiles.model.ResourceNotFoundException; +import software.amazon.awssdk.services.customerprofiles.model.ThrottlingException; +import software.amazon.cloudformation.exceptions.CfnAccessDeniedException; import software.amazon.cloudformation.exceptions.CfnAlreadyExistsException; import software.amazon.cloudformation.exceptions.CfnGeneralServiceException; import software.amazon.cloudformation.exceptions.CfnInvalidRequestException; import software.amazon.cloudformation.exceptions.CfnNotFoundException; import software.amazon.cloudformation.exceptions.CfnServiceInternalErrorException; +import software.amazon.cloudformation.exceptions.CfnThrottlingException; import software.amazon.cloudformation.proxy.AmazonWebServicesClientProxy; import software.amazon.cloudformation.proxy.Logger; import software.amazon.cloudformation.proxy.ProgressEvent; import software.amazon.cloudformation.proxy.ResourceHandlerRequest; import java.util.Map; +import static software.amazon.customerprofiles.integration.Translator.buildServiceFlowDefinition; @NoArgsConstructor public class CreateHandler extends BaseHandler { @@ -44,6 +49,11 @@ public ProgressEvent handleRequest( final ResourceModel model = request.getDesiredResourceState(); + // calls to GetIntegration without a URI result in a 400 so we can skip calling + if (model.getUri() == null) { + return createIntegration(proxy, request, logger); + } + final GetIntegrationRequest getIntegrationRequest = GetIntegrationRequest.builder() .domainName(model.getDomainName()) .uri(model.getUri()) @@ -56,46 +66,7 @@ public ProgressEvent handleRequest( // 1. BadRequestException will also handled by PutIntegration // 2. ResourceNotFoundException is the exact exception we want before calling PutIntegration // 3. Whatever 5xx error GetIntegration call meet, it should not affect the performance of Create Action - - Map resourceTag; - if (request.getDesiredResourceTags() == null) { - resourceTag = null; - } else if (request.getDesiredResourceTags().isEmpty()) { - resourceTag = null; - } else { - resourceTag = request.getDesiredResourceTags(); - } - final PutIntegrationRequest putIntegrationRequest = PutIntegrationRequest.builder() - .domainName(model.getDomainName()) - .objectTypeName(model.getObjectTypeName()) - .tags(resourceTag) - .uri(model.getUri()) - .build(); - - final PutIntegrationResponse putIntegrationResponse; - try { - putIntegrationResponse = proxy.injectCredentialsAndInvokeV2(putIntegrationRequest, client::putIntegration); - logger.log(String.format("Integration Created with domainName = %s", model.getDomainName())); - } catch (BadRequestException e) { - throw new CfnInvalidRequestException(e); - } catch (InternalServerException e) { - throw new CfnServiceInternalErrorException(e); - } catch (ResourceNotFoundException e) { - throw new CfnNotFoundException(e); - } catch (Exception e) { - throw new CfnGeneralServiceException(e); - } - - final ResourceModel responseModel = ResourceModel.builder() - .createdAt(putIntegrationResponse.createdAt().toString()) - .domainName(putIntegrationResponse.domainName()) - .lastUpdatedAt(putIntegrationResponse.lastUpdatedAt().toString()) - .objectTypeName(putIntegrationResponse.objectTypeName()) - .tags(Translator.mapTagsToList(putIntegrationResponse.tags())) - .uri(putIntegrationResponse.uri()) - .build(); - - return ProgressEvent.defaultSuccessHandler(responseModel); + return createIntegration(proxy, request, logger); } // If GetIntegration Call succeed @@ -109,5 +80,65 @@ public ProgressEvent handleRequest( throw new CfnAlreadyExistsException(e); } + /** + * Creates an integration + * @param proxy + * @param request + * @param logger + * @return + */ + private ProgressEvent createIntegration( + final AmazonWebServicesClientProxy proxy, + final ResourceHandlerRequest request, + final Logger logger + ) { + final ResourceModel model = request.getDesiredResourceState(); + + Map resourceTag; + if (request.getDesiredResourceTags() == null) { + resourceTag = null; + } else if (request.getDesiredResourceTags().isEmpty()) { + resourceTag = null; + } else { + resourceTag = request.getDesiredResourceTags(); + } + PutIntegrationRequest putIntegrationRequest = PutIntegrationRequest.builder() + .domainName(model.getDomainName()) + .objectTypeName(model.getObjectTypeName()) + .tags(resourceTag) + .flowDefinition(buildServiceFlowDefinition(model.getFlowDefinition())) + .uri(model.getUri()) + .build(); + + final PutIntegrationResponse putIntegrationResponse; + try { + putIntegrationResponse = proxy.injectCredentialsAndInvokeV2(putIntegrationRequest, client::putIntegration); + logger.log(String.format("Integration Created with domainName = %s", model.getDomainName())); + } catch (BadRequestException e) { + throw new CfnInvalidRequestException(e); + } catch (AccessDeniedException e) { + throw new CfnAccessDeniedException(e); + } catch (ThrottlingException e) { + throw new CfnThrottlingException(e); + } catch (InternalServerException e) { + throw new CfnServiceInternalErrorException(e); + } catch (ResourceNotFoundException e) { + throw new CfnNotFoundException(e); + } catch (Exception e) { + throw new CfnGeneralServiceException(e); + } + + final ResourceModel responseModel = ResourceModel.builder() + .createdAt(putIntegrationResponse.createdAt().toString()) + .domainName(putIntegrationResponse.domainName()) + .lastUpdatedAt(putIntegrationResponse.lastUpdatedAt().toString()) + .objectTypeName(putIntegrationResponse.objectTypeName()) + .tags(Translator.mapTagsToList(putIntegrationResponse.tags())) + .uri(putIntegrationResponse.uri()) + .build(); + + return ProgressEvent.defaultSuccessHandler(responseModel); + } } + diff --git a/aws-customerprofiles-integration/src/main/java/software/amazon/customerprofiles/integration/Translator.java b/aws-customerprofiles-integration/src/main/java/software/amazon/customerprofiles/integration/Translator.java index a5ed4a1..a54f00c 100644 --- a/aws-customerprofiles-integration/src/main/java/software/amazon/customerprofiles/integration/Translator.java +++ b/aws-customerprofiles-integration/src/main/java/software/amazon/customerprofiles/integration/Translator.java @@ -1,10 +1,21 @@ package software.amazon.customerprofiles.integration; +import com.amazonaws.util.StringUtils; +import com.google.common.collect.ImmutableMap; +import software.amazon.awssdk.services.customerprofiles.model.FlowDefinition; import software.amazon.cloudformation.proxy.ResourceHandlerRequest; import java.util.List; import java.util.Map; import java.util.stream.Collectors; +import software.amazon.customerprofiles.integration.translators.ConnectorTranslator; +import software.amazon.customerprofiles.integration.translators.MarketoTranslator; +import software.amazon.customerprofiles.integration.translators.S3Translator; +import software.amazon.customerprofiles.integration.translators.SalesforceTranslator; +import software.amazon.customerprofiles.integration.translators.ServiceNowTranslator; +import software.amazon.customerprofiles.integration.translators.ZendeskTranslator; +import static software.amazon.customerprofiles.integration.translators.TaskTranslator.toServiceTasks; +import static software.amazon.customerprofiles.integration.translators.TriggerConfigTranslator.toServiceTriggerConfig; public class Translator { @@ -26,4 +37,33 @@ static List mapTagsToList(Map tags) { .collect(Collectors.toList()); } + private static Map connectorTranslators = ImmutableMap.builder() + .put("Salesforce", new SalesforceTranslator()) + .put("Marketo", new MarketoTranslator()) + .put("ServiceNow", new ServiceNowTranslator()) + .put("S3", new S3Translator()) + .put("Zendesk", new ZendeskTranslator()) + .build(); + + public static ConnectorTranslator getTranslator(String connectorType) { + return connectorTranslators.get(connectorType); + } + + public static FlowDefinition buildServiceFlowDefinition(software.amazon.customerprofiles.integration.FlowDefinition model) { + if (model == null) { + return null; + } + + String connectorType = model.getSourceFlowConfig().getConnectorType(); + ConnectorTranslator connector = getTranslator(connectorType); + return FlowDefinition.builder() + .description(!StringUtils.isNullOrEmpty(model.getDescription()) ? model.getDescription() : null) + .flowName(model.getFlowName()) + .kmsArn(model.getKmsArn()) + .sourceFlowConfig(connector.toServiceSourceFlowConfig(model.getSourceFlowConfig())) + .tasks(toServiceTasks(model.getTasks(), connectorType)) + .triggerConfig(toServiceTriggerConfig(model.getTriggerConfig())) + .build(); + } } + diff --git a/aws-customerprofiles-integration/src/main/java/software/amazon/customerprofiles/integration/translators/ConnectorTranslator.java b/aws-customerprofiles-integration/src/main/java/software/amazon/customerprofiles/integration/translators/ConnectorTranslator.java new file mode 100644 index 0000000..b85d52f --- /dev/null +++ b/aws-customerprofiles-integration/src/main/java/software/amazon/customerprofiles/integration/translators/ConnectorTranslator.java @@ -0,0 +1,9 @@ +package software.amazon.customerprofiles.integration.translators; + +import software.amazon.awssdk.services.customerprofiles.model.ConnectorOperator; +import software.amazon.awssdk.services.customerprofiles.model.SourceFlowConfig; + +public interface ConnectorTranslator { + SourceFlowConfig toServiceSourceFlowConfig(software.amazon.customerprofiles.integration.SourceFlowConfig model); + ConnectorOperator toServiceConnectorOperator(software.amazon.customerprofiles.integration.ConnectorOperator model); +} diff --git a/aws-customerprofiles-integration/src/main/java/software/amazon/customerprofiles/integration/translators/MarketoTranslator.java b/aws-customerprofiles-integration/src/main/java/software/amazon/customerprofiles/integration/translators/MarketoTranslator.java new file mode 100644 index 0000000..23f20ab --- /dev/null +++ b/aws-customerprofiles-integration/src/main/java/software/amazon/customerprofiles/integration/translators/MarketoTranslator.java @@ -0,0 +1,44 @@ +package software.amazon.customerprofiles.integration.translators; + +import com.amazonaws.util.StringUtils; +import software.amazon.awssdk.services.customerprofiles.model.ConnectorOperator; +import software.amazon.awssdk.services.customerprofiles.model.IncrementalPullConfig; +import software.amazon.awssdk.services.customerprofiles.model.MarketoSourceProperties; +import software.amazon.awssdk.services.customerprofiles.model.SourceConnectorProperties; +import software.amazon.awssdk.services.customerprofiles.model.SourceFlowConfig; +import software.amazon.customerprofiles.integration.translators.ConnectorTranslator; + +public class MarketoTranslator implements ConnectorTranslator { + + @Override + public SourceFlowConfig toServiceSourceFlowConfig(software.amazon.customerprofiles.integration.SourceFlowConfig model) { + return SourceFlowConfig.builder() + .connectorProfileName(StringUtils.isNullOrEmpty(model.getConnectorProfileName()) ? null : + model.getConnectorProfileName()) + .connectorType(model.getConnectorType()) + .sourceConnectorProperties( + SourceConnectorProperties.builder() + .marketo(toServiceSourceProperties(model + .getSourceConnectorProperties() + .getMarketo())) + .build() + ) + .build(); + } + + private MarketoSourceProperties toServiceSourceProperties(software.amazon.customerprofiles.integration.MarketoSourceProperties model) { + return MarketoSourceProperties.builder() + .object(model.getObject()) + .build(); + } + + @Override + public ConnectorOperator toServiceConnectorOperator(software.amazon.customerprofiles.integration.ConnectorOperator model) { + if (model == null) { + return null; + } + return ConnectorOperator.builder() + .marketo(model.getMarketo()) + .build(); + } +} diff --git a/aws-customerprofiles-integration/src/main/java/software/amazon/customerprofiles/integration/translators/S3Translator.java b/aws-customerprofiles-integration/src/main/java/software/amazon/customerprofiles/integration/translators/S3Translator.java new file mode 100644 index 0000000..d3e1e81 --- /dev/null +++ b/aws-customerprofiles-integration/src/main/java/software/amazon/customerprofiles/integration/translators/S3Translator.java @@ -0,0 +1,45 @@ +package software.amazon.customerprofiles.integration.translators; + +import com.amazonaws.util.StringUtils; +import software.amazon.awssdk.services.customerprofiles.model.ConnectorOperator; +import software.amazon.awssdk.services.customerprofiles.model.IncrementalPullConfig; +import software.amazon.awssdk.services.customerprofiles.model.S3SourceProperties; +import software.amazon.awssdk.services.customerprofiles.model.SourceConnectorProperties; +import software.amazon.awssdk.services.customerprofiles.model.SourceFlowConfig; +import software.amazon.customerprofiles.integration.translators.ConnectorTranslator; + +public class S3Translator implements ConnectorTranslator { + + @Override + public SourceFlowConfig toServiceSourceFlowConfig(software.amazon.customerprofiles.integration.SourceFlowConfig model) { + return SourceFlowConfig.builder() + .connectorProfileName(StringUtils.isNullOrEmpty(model.getConnectorProfileName()) ? null : + model.getConnectorProfileName()) + .connectorType(model.getConnectorType()) + .sourceConnectorProperties( + SourceConnectorProperties.builder() + .s3(toServiceS3SourceProperties(model + .getSourceConnectorProperties() + .getS3())) + .build() + ) + .build(); + } + + private S3SourceProperties toServiceS3SourceProperties(software.amazon.customerprofiles.integration.S3SourceProperties model) { + return S3SourceProperties.builder() + .bucketPrefix(model.getBucketPrefix()) + .bucketName(model.getBucketName()) + .build(); + } + + @Override + public ConnectorOperator toServiceConnectorOperator(software.amazon.customerprofiles.integration.ConnectorOperator model) { + if (model == null) { + return null; + } + return ConnectorOperator.builder() + .s3(model.getS3()) + .build(); + } +} diff --git a/aws-customerprofiles-integration/src/main/java/software/amazon/customerprofiles/integration/translators/SalesforceTranslator.java b/aws-customerprofiles-integration/src/main/java/software/amazon/customerprofiles/integration/translators/SalesforceTranslator.java new file mode 100644 index 0000000..657bb93 --- /dev/null +++ b/aws-customerprofiles-integration/src/main/java/software/amazon/customerprofiles/integration/translators/SalesforceTranslator.java @@ -0,0 +1,49 @@ +package software.amazon.customerprofiles.integration.translators; + +import com.amazonaws.util.StringUtils; +import software.amazon.awssdk.services.customerprofiles.model.ConnectorOperator; +import software.amazon.awssdk.services.customerprofiles.model.IncrementalPullConfig; +import software.amazon.awssdk.services.customerprofiles.model.SalesforceSourceProperties; +import software.amazon.awssdk.services.customerprofiles.model.SourceConnectorProperties; +import software.amazon.awssdk.services.customerprofiles.model.SourceFlowConfig; +import software.amazon.customerprofiles.integration.translators.ConnectorTranslator; + +public class SalesforceTranslator implements ConnectorTranslator { + + @Override + public SourceFlowConfig toServiceSourceFlowConfig(software.amazon.customerprofiles.integration.SourceFlowConfig model) { + return SourceFlowConfig.builder() + .connectorProfileName(StringUtils.isNullOrEmpty(model.getConnectorProfileName()) ? null : + model.getConnectorProfileName()) + .connectorType(model.getConnectorType()) + .incrementalPullConfig(model.getIncrementalPullConfig() == null ? null : IncrementalPullConfig.builder() + .datetimeTypeFieldName(model.getIncrementalPullConfig().getDatetimeTypeFieldName()) + .build()) + .sourceConnectorProperties( + SourceConnectorProperties.builder() + .salesforce(toServiceSourceProperties(model + .getSourceConnectorProperties() + .getSalesforce())) + .build() + ) + .build(); + } + + private SalesforceSourceProperties toServiceSourceProperties(software.amazon.customerprofiles.integration.SalesforceSourceProperties model) { + return SalesforceSourceProperties.builder() + .enableDynamicFieldUpdate(model.getEnableDynamicFieldUpdate()) + .includeDeletedRecords(model.getIncludeDeletedRecords()) + .object(model.getObject()) + .build(); + } + + @Override + public ConnectorOperator toServiceConnectorOperator(software.amazon.customerprofiles.integration.ConnectorOperator model) { + if (model == null) { + return null; + } + return ConnectorOperator.builder() + .salesforce(model.getSalesforce()) + .build(); + } +} diff --git a/aws-customerprofiles-integration/src/main/java/software/amazon/customerprofiles/integration/translators/ServiceNowTranslator.java b/aws-customerprofiles-integration/src/main/java/software/amazon/customerprofiles/integration/translators/ServiceNowTranslator.java new file mode 100644 index 0000000..24dd983 --- /dev/null +++ b/aws-customerprofiles-integration/src/main/java/software/amazon/customerprofiles/integration/translators/ServiceNowTranslator.java @@ -0,0 +1,44 @@ +package software.amazon.customerprofiles.integration.translators; + +import com.amazonaws.util.StringUtils; +import software.amazon.awssdk.services.customerprofiles.model.ConnectorOperator; +import software.amazon.awssdk.services.customerprofiles.model.IncrementalPullConfig; +import software.amazon.awssdk.services.customerprofiles.model.ServiceNowSourceProperties; +import software.amazon.awssdk.services.customerprofiles.model.SourceConnectorProperties; +import software.amazon.awssdk.services.customerprofiles.model.SourceFlowConfig; +import software.amazon.customerprofiles.integration.translators.ConnectorTranslator; + +public class ServiceNowTranslator implements ConnectorTranslator { + + @Override + public SourceFlowConfig toServiceSourceFlowConfig(software.amazon.customerprofiles.integration.SourceFlowConfig model) { + return SourceFlowConfig.builder() + .connectorProfileName(StringUtils.isNullOrEmpty(model.getConnectorProfileName()) ? null : + model.getConnectorProfileName()) + .connectorType(model.getConnectorType()) + .sourceConnectorProperties( + SourceConnectorProperties.builder() + .serviceNow(toServiceServiceNowSourceProperties(model + .getSourceConnectorProperties() + .getServiceNow())) + .build() + ) + .build(); + } + + private ServiceNowSourceProperties toServiceServiceNowSourceProperties(software.amazon.customerprofiles.integration.ServiceNowSourceProperties model) { + return ServiceNowSourceProperties.builder() + .object(model.getObject()) + .build(); + } + + @Override + public ConnectorOperator toServiceConnectorOperator(software.amazon.customerprofiles.integration.ConnectorOperator model) { + if (model == null) { + return null; + } + return ConnectorOperator.builder() + .serviceNow(model.getServiceNow()) + .build(); + } +} diff --git a/aws-customerprofiles-integration/src/main/java/software/amazon/customerprofiles/integration/translators/TaskTranslator.java b/aws-customerprofiles-integration/src/main/java/software/amazon/customerprofiles/integration/translators/TaskTranslator.java new file mode 100644 index 0000000..36b7a2a --- /dev/null +++ b/aws-customerprofiles-integration/src/main/java/software/amazon/customerprofiles/integration/translators/TaskTranslator.java @@ -0,0 +1,34 @@ +package software.amazon.customerprofiles.integration.translators; + +import com.amazonaws.util.CollectionUtils; +import com.amazonaws.util.StringUtils; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; +import software.amazon.awssdk.services.customerprofiles.model.OperatorPropertiesKeys; +import software.amazon.awssdk.services.customerprofiles.model.Task; +import software.amazon.customerprofiles.integration.TaskPropertiesMap; +import static software.amazon.customerprofiles.integration.Translator.getTranslator; + +public class TaskTranslator { + + public static List toServiceTasks(List model, String connectorType) { + return CollectionUtils.isNullOrEmpty(model) + ? Collections.emptyList() + : model.stream().map(t -> toServiceTask(t, connectorType)).collect(Collectors.toList()); + } + + public static Task toServiceTask(software.amazon.customerprofiles.integration.Task model, String connectorType) { + return Task.builder() + .connectorOperator(getTranslator(connectorType).toServiceConnectorOperator(model.getConnectorOperator())) + .destinationField(!StringUtils.isNullOrEmpty(model.getDestinationField()) ? model.getDestinationField() : null) + .sourceFields(model.getSourceFields()) + .taskType(model.getTaskType()) + .taskProperties(CollectionUtils.isNullOrEmpty(model.getTaskProperties()) ? null : + model.getTaskProperties() + .stream() + .collect(Collectors.toMap(t -> OperatorPropertiesKeys.fromValue( + t.getOperatorPropertyKey()), TaskPropertiesMap::getProperty))) + .build(); + } +} diff --git a/aws-customerprofiles-integration/src/main/java/software/amazon/customerprofiles/integration/translators/TriggerConfigTranslator.java b/aws-customerprofiles-integration/src/main/java/software/amazon/customerprofiles/integration/translators/TriggerConfigTranslator.java new file mode 100644 index 0000000..3f42d29 --- /dev/null +++ b/aws-customerprofiles-integration/src/main/java/software/amazon/customerprofiles/integration/translators/TriggerConfigTranslator.java @@ -0,0 +1,38 @@ +package software.amazon.customerprofiles.integration.translators; + +import java.time.Instant; +import software.amazon.awssdk.services.customerprofiles.model.ScheduledTriggerProperties; +import software.amazon.awssdk.services.customerprofiles.model.TriggerConfig; +import software.amazon.awssdk.services.customerprofiles.model.TriggerProperties; + +public class TriggerConfigTranslator { + + public static TriggerConfig toServiceTriggerConfig(software.amazon.customerprofiles.integration.TriggerConfig model) { + return TriggerConfig.builder() + .triggerType(model.getTriggerType()) + .triggerProperties(model.getTriggerProperties() == null ? null : + TriggerProperties.builder() + .scheduled(toServiceScheduledTriggerProperties(model.getTriggerProperties().getScheduled())) + .build()) + .build(); + } + + private static ScheduledTriggerProperties toServiceScheduledTriggerProperties(software.amazon.customerprofiles.integration.ScheduledTriggerProperties model) { + if (model == null) { + return null; + } + + return ScheduledTriggerProperties.builder() + .dataPullMode(model.getDataPullMode()) + .firstExecutionFrom(model.getFirstExecutionFrom() == null ? null : Instant.ofEpochSecond( + model.getFirstExecutionFrom().longValue())) + .scheduleStartTime(model.getScheduleStartTime() == null ? null : Instant.ofEpochSecond( + model.getScheduleStartTime().longValue())) + .scheduleEndTime(model.getScheduleEndTime() == null ? null : Instant.ofEpochSecond( + model.getScheduleEndTime().longValue())) + .scheduleExpression(model.getScheduleExpression()) + .scheduleOffset(model.getScheduleOffset() == null ? null : model.getScheduleOffset().longValue()) + .timezone(model.getTimezone()) + .build(); + } +} diff --git a/aws-customerprofiles-integration/src/main/java/software/amazon/customerprofiles/integration/translators/ZendeskTranslator.java b/aws-customerprofiles-integration/src/main/java/software/amazon/customerprofiles/integration/translators/ZendeskTranslator.java new file mode 100644 index 0000000..fdc16b0 --- /dev/null +++ b/aws-customerprofiles-integration/src/main/java/software/amazon/customerprofiles/integration/translators/ZendeskTranslator.java @@ -0,0 +1,44 @@ +package software.amazon.customerprofiles.integration.translators; + +import com.amazonaws.util.StringUtils; +import software.amazon.awssdk.services.customerprofiles.model.ConnectorOperator; +import software.amazon.awssdk.services.customerprofiles.model.IncrementalPullConfig; +import software.amazon.awssdk.services.customerprofiles.model.ZendeskSourceProperties; +import software.amazon.awssdk.services.customerprofiles.model.SourceConnectorProperties; +import software.amazon.awssdk.services.customerprofiles.model.SourceFlowConfig; +import software.amazon.customerprofiles.integration.translators.ConnectorTranslator; + +public class ZendeskTranslator implements ConnectorTranslator { + + @Override + public SourceFlowConfig toServiceSourceFlowConfig(software.amazon.customerprofiles.integration.SourceFlowConfig model) { + return SourceFlowConfig.builder() + .connectorProfileName(StringUtils.isNullOrEmpty(model.getConnectorProfileName()) ? null : + model.getConnectorProfileName()) + .connectorType(model.getConnectorType()) + .sourceConnectorProperties( + SourceConnectorProperties.builder() + .zendesk(toServiceZendeskSourceProperties(model + .getSourceConnectorProperties() + .getZendesk())) + .build() + ) + .build(); + } + + private ZendeskSourceProperties toServiceZendeskSourceProperties(software.amazon.customerprofiles.integration.ZendeskSourceProperties model) { + return ZendeskSourceProperties.builder() + .object(model.getObject()) + .build(); + } + + @Override + public ConnectorOperator toServiceConnectorOperator(software.amazon.customerprofiles.integration.ConnectorOperator model) { + if (model == null) { + return null; + } + return ConnectorOperator.builder() + .zendesk(model.getZendesk()) + .build(); + } +} diff --git a/aws-customerprofiles-integration/src/test/java/software/amazon/customerprofiles/integration/CreateHandlerTest.java b/aws-customerprofiles-integration/src/test/java/software/amazon/customerprofiles/integration/CreateHandlerTest.java index c2a9119..57b72d4 100644 --- a/aws-customerprofiles-integration/src/test/java/software/amazon/customerprofiles/integration/CreateHandlerTest.java +++ b/aws-customerprofiles-integration/src/test/java/software/amazon/customerprofiles/integration/CreateHandlerTest.java @@ -1,8 +1,12 @@ package software.amazon.customerprofiles.integration; import com.google.common.collect.ImmutableMap; +import java.util.stream.Stream; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; import org.mockito.Mockito; import software.amazon.awssdk.services.customerprofiles.CustomerProfilesClient; +import software.amazon.awssdk.services.customerprofiles.model.AccessDeniedException; import software.amazon.awssdk.services.customerprofiles.model.BadRequestException; import software.amazon.awssdk.services.customerprofiles.model.GetIntegrationRequest; import software.amazon.awssdk.services.customerprofiles.model.GetIntegrationResponse; @@ -11,11 +15,13 @@ import software.amazon.awssdk.services.customerprofiles.model.PutIntegrationResponse; import software.amazon.awssdk.services.customerprofiles.model.ResourceNotFoundException; import software.amazon.awssdk.services.customerprofiles.model.ThrottlingException; +import software.amazon.cloudformation.exceptions.CfnAccessDeniedException; import software.amazon.cloudformation.exceptions.CfnAlreadyExistsException; import software.amazon.cloudformation.exceptions.CfnGeneralServiceException; import software.amazon.cloudformation.exceptions.CfnInvalidRequestException; import software.amazon.cloudformation.exceptions.CfnNotFoundException; import software.amazon.cloudformation.exceptions.CfnServiceInternalErrorException; +import software.amazon.cloudformation.exceptions.CfnThrottlingException; import software.amazon.cloudformation.proxy.AmazonWebServicesClientProxy; import software.amazon.cloudformation.proxy.Logger; import software.amazon.cloudformation.proxy.OperationStatus; @@ -33,6 +39,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.any; +import static software.amazon.customerprofiles.integration.translators.TestUtils.getValidFlowDefinition; @ExtendWith(MockitoExtension.class) public class CreateHandlerTest { @@ -96,6 +103,49 @@ public void handleRequest_SimpleSuccess() { assertThat(response.getErrorCode()).isNull(); } + private static Stream getConnectors() { + return Stream.of("Salesforce", "S3", "Zendesk", "Marketo", "ServiceNow"); + } + + @ParameterizedTest + @MethodSource("getConnectors") + public void handleRequest_withFlowDefinition_Success(String connectorType) { + model = ResourceModel.builder() + .domainName("testDomainName") + .flowDefinition(getValidFlowDefinition(connectorType)) + .objectTypeName("testObjectTypeName") + .build(); + + final CreateHandler handler = new CreateHandler(customerProfilesClient); + + PutIntegrationResponse result = PutIntegrationResponse.builder() + .createdAt(TIME) + .domainName("testDomainName") + .lastUpdatedAt(TIME) + .objectTypeName("testObjectTypeName") + .uri("arn:aws:flow:us-east-1:123456789012:URIOfIntegration1") + .build(); + + Mockito.doReturn(result).when(proxy).injectCredentialsAndInvokeV2( + any(PutIntegrationRequest.class), any()); + + final ResourceHandlerRequest request = ResourceHandlerRequest.builder() + .desiredResourceState(model) + .build(); + + final ProgressEvent response + = handler.handleRequest(proxy, request, null, logger); + + assertThat(response).isNotNull(); + assertThat(response.getStatus()).isEqualTo(OperationStatus.SUCCESS); + assertThat(response.getCallbackContext()).isNull(); + assertThat(response.getCallbackDelaySeconds()).isEqualTo(0); + assertThat(response.getResourceModel().getDomainName()).isEqualTo(request.getDesiredResourceState().getDomainName()); + assertThat(response.getResourceModels()).isNull(); + assertThat(response.getMessage()).isNull(); + assertThat(response.getErrorCode()).isNull(); + } + @Test public void handleRequest_desiredResourceTagIsNotNull() { final CreateHandler handler = new CreateHandler(customerProfilesClient); @@ -234,13 +284,49 @@ public void handleRequest_PutIntegration_InternalServerException() { } @Test - public void handleRequest_PutIntegration_otherException() { + public void handleRequest_PutIntegration_ThrottlingException() { final CreateHandler handler = new CreateHandler(customerProfilesClient); - ThrottlingException exc = ThrottlingException.builder() - .message("ThrottlingException") + ThrottlingException exc = ThrottlingException.builder().build(); + + Mockito.doThrow(exc).when(proxy).injectCredentialsAndInvokeV2( + any(GetIntegrationRequest.class), any()); + + Mockito.doThrow(exc).when(proxy).injectCredentialsAndInvokeV2( + any(PutIntegrationRequest.class), any()); + + final ResourceHandlerRequest request = ResourceHandlerRequest.builder() + .desiredResourceState(model) .build(); + assertThrows(CfnThrottlingException.class, () -> handler.handleRequest(proxy, request, null, logger)); + } + + @Test + public void handleRequest_PutIntegration_AccessDeniedException() { + final CreateHandler handler = new CreateHandler(customerProfilesClient); + + AccessDeniedException exc = AccessDeniedException.builder().build(); + + Mockito.doThrow(exc).when(proxy).injectCredentialsAndInvokeV2( + any(GetIntegrationRequest.class), any()); + + Mockito.doThrow(exc).when(proxy).injectCredentialsAndInvokeV2( + any(PutIntegrationRequest.class), any()); + + final ResourceHandlerRequest request = ResourceHandlerRequest.builder() + .desiredResourceState(model) + .build(); + + assertThrows(CfnAccessDeniedException.class, () -> handler.handleRequest(proxy, request, null, logger)); + } + + @Test + public void handleRequest_PutIntegration_otherException() { + final CreateHandler handler = new CreateHandler(customerProfilesClient); + + RuntimeException exc = new RuntimeException(); + Mockito.doThrow(exc).when(proxy).injectCredentialsAndInvokeV2( any(GetIntegrationRequest.class), any()); diff --git a/aws-customerprofiles-integration/src/test/java/software/amazon/customerprofiles/integration/TranslatorTest.java b/aws-customerprofiles-integration/src/test/java/software/amazon/customerprofiles/integration/TranslatorTest.java index 90305a3..2ad2bb3 100644 --- a/aws-customerprofiles-integration/src/test/java/software/amazon/customerprofiles/integration/TranslatorTest.java +++ b/aws-customerprofiles-integration/src/test/java/software/amazon/customerprofiles/integration/TranslatorTest.java @@ -1,11 +1,14 @@ package software.amazon.customerprofiles.integration; -import com.google.common.collect.ImmutableMap; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.junit.jupiter.MockitoExtension; +import software.amazon.awssdk.services.customerprofiles.model.FlowDefinition; import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static software.amazon.customerprofiles.integration.translators.TestUtils.getValidFlowDefinition; @ExtendWith(MockitoExtension.class) public class TranslatorTest { @@ -13,4 +16,32 @@ public class TranslatorTest { public void test() { assertThat(Translator.mapTagsToList(null)).isNull(); } + + @Test + public void testBuildFlowDefinition() { + FlowDefinition flowDefinition = Translator.buildServiceFlowDefinition(getValidFlowDefinition("Salesforce")); + + assertNotNull(flowDefinition); + assertNotNull(flowDefinition.description()); + assertNotNull(flowDefinition.flowName()); + assertNotNull(flowDefinition.kmsArn()); + assertNotNull(flowDefinition.sourceFlowConfig()); + assertNotNull(flowDefinition.tasks()); + assertNotNull(flowDefinition.triggerConfig()); + } + + @Test + public void testBuildFlowDefinitionEmptyDescription() { + software.amazon.customerprofiles.integration.FlowDefinition model = getValidFlowDefinition("Salesforce"); + model.setDescription(""); + FlowDefinition flowDefinition = Translator.buildServiceFlowDefinition(model); + + assertNotNull(flowDefinition); + assertNull(flowDefinition.description()); + assertNotNull(flowDefinition.flowName()); + assertNotNull(flowDefinition.kmsArn()); + assertNotNull(flowDefinition.sourceFlowConfig()); + assertNotNull(flowDefinition.tasks()); + assertNotNull(flowDefinition.triggerConfig()); + } } diff --git a/aws-customerprofiles-integration/src/test/java/software/amazon/customerprofiles/integration/translators/MarketoTranslatorTest.java b/aws-customerprofiles-integration/src/test/java/software/amazon/customerprofiles/integration/translators/MarketoTranslatorTest.java new file mode 100644 index 0000000..d9fc056 --- /dev/null +++ b/aws-customerprofiles-integration/src/test/java/software/amazon/customerprofiles/integration/translators/MarketoTranslatorTest.java @@ -0,0 +1,59 @@ +package software.amazon.customerprofiles.integration.translators; + +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.services.customerprofiles.model.ConnectorOperator; +import software.amazon.awssdk.services.customerprofiles.model.SourceFlowConfig; +import software.amazon.customerprofiles.integration.IncrementalPullConfig; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static software.amazon.customerprofiles.integration.translators.TestUtils.getValidSourceConnectorProperties; + +public class MarketoTranslatorTest { + + MarketoTranslator translator = new MarketoTranslator(); + + @Test + public void testSourceFlowConfig() { + software.amazon.customerprofiles.integration.SourceFlowConfig model = software.amazon.customerprofiles.integration.SourceFlowConfig.builder() + .connectorProfileName("test name") + .connectorType("Marketo") + .sourceConnectorProperties(getValidSourceConnectorProperties("Marketo")) + .build(); + SourceFlowConfig translated = translator.toServiceSourceFlowConfig(model); + + assertNotNull(translated); + assertNotNull(translated.connectorProfileName()); + assertNotNull(translated.connectorType()); + assertNotNull(translated.sourceConnectorProperties().marketo().object()); + } + + @Test + public void testSourceFlowConfigOnlyRequiredFields() { + software.amazon.customerprofiles.integration.SourceFlowConfig model = software.amazon.customerprofiles.integration.SourceFlowConfig.builder() + .connectorType("Marketo") + .sourceConnectorProperties(getValidSourceConnectorProperties("Marketo")) + .build(); + SourceFlowConfig translated = translator.toServiceSourceFlowConfig(model); + + assertNotNull(translated); + assertNull(translated.connectorProfileName()); + assertNull(translated.incrementalPullConfig()); + } + + @Test + public void testConnectorOperator() { + ConnectorOperator translated = translator.toServiceConnectorOperator( + software.amazon.customerprofiles.integration.ConnectorOperator.builder() + .marketo("test") + .build()); + + assertNotNull(translated); + assertNotNull(translated.marketo()); + } + + @Test + public void testConnectorOperatorNull() { + ConnectorOperator translated = translator.toServiceConnectorOperator(null); + assertNull(translated); + } +} diff --git a/aws-customerprofiles-integration/src/test/java/software/amazon/customerprofiles/integration/translators/S3TranslatorTest.java b/aws-customerprofiles-integration/src/test/java/software/amazon/customerprofiles/integration/translators/S3TranslatorTest.java new file mode 100644 index 0000000..4557fab --- /dev/null +++ b/aws-customerprofiles-integration/src/test/java/software/amazon/customerprofiles/integration/translators/S3TranslatorTest.java @@ -0,0 +1,60 @@ +package software.amazon.customerprofiles.integration.translators; + +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.services.customerprofiles.model.ConnectorOperator; +import software.amazon.awssdk.services.customerprofiles.model.SourceFlowConfig; +import software.amazon.customerprofiles.integration.IncrementalPullConfig; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static software.amazon.customerprofiles.integration.translators.TestUtils.getValidSourceConnectorProperties; + +public class S3TranslatorTest { + + S3Translator translator = new S3Translator(); + + @Test + public void testSourceFlowConfig() { + software.amazon.customerprofiles.integration.SourceFlowConfig model = software.amazon.customerprofiles.integration.SourceFlowConfig.builder() + .connectorProfileName("test name") + .connectorType("S3") + .sourceConnectorProperties(getValidSourceConnectorProperties("S3")) + .build(); + SourceFlowConfig translated = translator.toServiceSourceFlowConfig(model); + + assertNotNull(translated); + assertNotNull(translated.connectorProfileName()); + assertNotNull(translated.connectorType()); + assertNotNull(translated.sourceConnectorProperties().s3().bucketName()); + assertNotNull(translated.sourceConnectorProperties().s3().bucketPrefix()); + } + + @Test + public void testSourceFlowConfigOnlyRequiredFields() { + software.amazon.customerprofiles.integration.SourceFlowConfig model = software.amazon.customerprofiles.integration.SourceFlowConfig.builder() + .connectorType("S3") + .sourceConnectorProperties(getValidSourceConnectorProperties("S3")) + .build(); + SourceFlowConfig translated = translator.toServiceSourceFlowConfig(model); + + assertNotNull(translated); + assertNull(translated.connectorProfileName()); + assertNull(translated.incrementalPullConfig()); + } + + @Test + public void testConnectorOperator() { + ConnectorOperator translated = translator.toServiceConnectorOperator( + software.amazon.customerprofiles.integration.ConnectorOperator.builder() + .s3("test") + .build()); + + assertNotNull(translated); + assertNotNull(translated.s3()); + } + + @Test + public void testConnectorOperatorNull() { + ConnectorOperator translated = translator.toServiceConnectorOperator(null); + assertNull(translated); + } +} diff --git a/aws-customerprofiles-integration/src/test/java/software/amazon/customerprofiles/integration/translators/SalesforceTranslatorTest.java b/aws-customerprofiles-integration/src/test/java/software/amazon/customerprofiles/integration/translators/SalesforceTranslatorTest.java new file mode 100644 index 0000000..1299dcd --- /dev/null +++ b/aws-customerprofiles-integration/src/test/java/software/amazon/customerprofiles/integration/translators/SalesforceTranslatorTest.java @@ -0,0 +1,65 @@ +package software.amazon.customerprofiles.integration.translators; + +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.services.customerprofiles.model.ConnectorOperator; +import software.amazon.awssdk.services.customerprofiles.model.SourceFlowConfig; +import software.amazon.customerprofiles.integration.IncrementalPullConfig; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static software.amazon.customerprofiles.integration.translators.TestUtils.getValidSourceConnectorProperties; + +public class SalesforceTranslatorTest { + + SalesforceTranslator translator = new SalesforceTranslator(); + + @Test + public void testSourceFlowConfig() { + software.amazon.customerprofiles.integration.SourceFlowConfig model = software.amazon.customerprofiles.integration.SourceFlowConfig.builder() + .connectorProfileName("test name") + .connectorType("Salesforce") + .incrementalPullConfig(IncrementalPullConfig.builder() + .datetimeTypeFieldName("LastModifiedDate") + .build()) + .sourceConnectorProperties(getValidSourceConnectorProperties("Salesforce")) + .build(); + SourceFlowConfig translated = translator.toServiceSourceFlowConfig(model); + + assertNotNull(translated); + assertNotNull(translated.connectorProfileName()); + assertNotNull(translated.connectorType()); + assertNotNull(translated.incrementalPullConfig().datetimeTypeFieldName()); + assertNotNull(translated.sourceConnectorProperties().salesforce().object()); + assertNotNull(translated.sourceConnectorProperties().salesforce().enableDynamicFieldUpdate()); + assertNotNull(translated.sourceConnectorProperties().salesforce().includeDeletedRecords()); + } + + @Test + public void testSourceFlowConfigOnlyRequiredFields() { + software.amazon.customerprofiles.integration.SourceFlowConfig model = software.amazon.customerprofiles.integration.SourceFlowConfig.builder() + .connectorType("Salesforce") + .sourceConnectorProperties(getValidSourceConnectorProperties("Salesforce")) + .build(); + SourceFlowConfig translated = translator.toServiceSourceFlowConfig(model); + + assertNotNull(translated); + assertNull(translated.connectorProfileName()); + assertNull(translated.incrementalPullConfig()); + } + + @Test + public void testConnectorOperator() { + ConnectorOperator translated = translator.toServiceConnectorOperator( + software.amazon.customerprofiles.integration.ConnectorOperator.builder() + .salesforce("test") + .build()); + + assertNotNull(translated); + assertNotNull(translated.salesforce()); + } + + @Test + public void testConnectorOperatorNull() { + ConnectorOperator translated = translator.toServiceConnectorOperator(null); + assertNull(translated); + } +} diff --git a/aws-customerprofiles-integration/src/test/java/software/amazon/customerprofiles/integration/translators/ServiceNowTranslatorTest.java b/aws-customerprofiles-integration/src/test/java/software/amazon/customerprofiles/integration/translators/ServiceNowTranslatorTest.java new file mode 100644 index 0000000..f38fed4 --- /dev/null +++ b/aws-customerprofiles-integration/src/test/java/software/amazon/customerprofiles/integration/translators/ServiceNowTranslatorTest.java @@ -0,0 +1,58 @@ +package software.amazon.customerprofiles.integration.translators; + +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.services.customerprofiles.model.ConnectorOperator; +import software.amazon.awssdk.services.customerprofiles.model.SourceFlowConfig; +import software.amazon.customerprofiles.integration.IncrementalPullConfig; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static software.amazon.customerprofiles.integration.translators.TestUtils.getValidSourceConnectorProperties; + +public class ServiceNowTranslatorTest { + ServiceNowTranslator translator = new ServiceNowTranslator(); + + @Test + public void testSourceFlowConfig() { + software.amazon.customerprofiles.integration.SourceFlowConfig model = software.amazon.customerprofiles.integration.SourceFlowConfig.builder() + .connectorProfileName("test name") + .connectorType("ServiceNow") + .sourceConnectorProperties(getValidSourceConnectorProperties("ServiceNow")) + .build(); + SourceFlowConfig translated = translator.toServiceSourceFlowConfig(model); + + assertNotNull(translated); + assertNotNull(translated.connectorProfileName()); + assertNotNull(translated.connectorType()); + assertNotNull(translated.sourceConnectorProperties().serviceNow().object()); + } + + @Test + public void testSourceFlowConfigOnlyRequiredFields() { + software.amazon.customerprofiles.integration.SourceFlowConfig model = software.amazon.customerprofiles.integration.SourceFlowConfig.builder() + .connectorType("ServiceNow") + .sourceConnectorProperties(getValidSourceConnectorProperties("ServiceNow")) + .build(); + SourceFlowConfig translated = translator.toServiceSourceFlowConfig(model); + + assertNotNull(translated); + assertNull(translated.connectorProfileName()); + assertNull(translated.incrementalPullConfig()); + } + + @Test + public void testConnectorOperator() { + ConnectorOperator translated = translator.toServiceConnectorOperator( + software.amazon.customerprofiles.integration.ConnectorOperator.builder() + .serviceNow("test") + .build()); + + assertNotNull(translated); + assertNotNull(translated.serviceNow()); + } + + @Test + public void testConnectorOperatorNull() { + ConnectorOperator translated = translator.toServiceConnectorOperator(null); + assertNull(translated); + } +} diff --git a/aws-customerprofiles-integration/src/test/java/software/amazon/customerprofiles/integration/translators/TaskTranslatorTest.java b/aws-customerprofiles-integration/src/test/java/software/amazon/customerprofiles/integration/translators/TaskTranslatorTest.java new file mode 100644 index 0000000..d64f600 --- /dev/null +++ b/aws-customerprofiles-integration/src/test/java/software/amazon/customerprofiles/integration/translators/TaskTranslatorTest.java @@ -0,0 +1,65 @@ +package software.amazon.customerprofiles.integration.translators; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.stream.Stream; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import software.amazon.awssdk.services.customerprofiles.model.Task; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static software.amazon.customerprofiles.integration.translators.TestUtils.getValidTasks; + +public class TaskTranslatorTest { + + TaskTranslator translator = new TaskTranslator(); + + private static Stream getConnectors() { + return Stream.of("Salesforce", "S3", "Zendesk", "Marketo", "ServiceNow"); + } + + @ParameterizedTest + @MethodSource("getConnectors") + public void testToServiceTasks(String connectorType) { + List modelTasks = getValidTasks(connectorType); + List tasks = TaskTranslator.toServiceTasks(modelTasks, connectorType); + + assertNotNull(tasks); + for (Task t : tasks) { + assertNotNull(t.connectorOperator()); + assertNotNull(t.destinationField()); + } + } + + @Test + public void testToServiceTasksNull() { + List tasks = TaskTranslator.toServiceTasks(null, null); + assertEquals(tasks, Collections.emptyList()); + } + + @Test + public void testTaskNullFields() { + // only TaskType and SourceFields are required non-null values + software.amazon.customerprofiles.integration.Task taskWithNullFields = + software.amazon.customerprofiles.integration.Task.builder() + .taskType("Filter") + .connectorOperator(null) + .destinationField(null) + .sourceFields(Arrays.asList("field")) + .taskProperties(null) + .build(); + + List tasks = TaskTranslator.toServiceTasks(Collections.singletonList(taskWithNullFields), + "Salesforce"); + + for (Task t : tasks) { + assertNull(t.connectorOperator()); + assertNull(t.destinationField()); + assertTrue(t.taskProperties().isEmpty()); + } + } +} diff --git a/aws-customerprofiles-integration/src/test/java/software/amazon/customerprofiles/integration/translators/TestUtils.java b/aws-customerprofiles-integration/src/test/java/software/amazon/customerprofiles/integration/translators/TestUtils.java new file mode 100644 index 0000000..faf34d4 --- /dev/null +++ b/aws-customerprofiles-integration/src/test/java/software/amazon/customerprofiles/integration/translators/TestUtils.java @@ -0,0 +1,132 @@ +package software.amazon.customerprofiles.integration.translators; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import software.amazon.customerprofiles.integration.ConnectorOperator; +import software.amazon.customerprofiles.integration.FlowDefinition; +import software.amazon.customerprofiles.integration.IncrementalPullConfig; +import software.amazon.customerprofiles.integration.MarketoSourceProperties; +import software.amazon.customerprofiles.integration.S3SourceProperties; +import software.amazon.customerprofiles.integration.SalesforceSourceProperties; +import software.amazon.customerprofiles.integration.ScheduledTriggerProperties; +import software.amazon.customerprofiles.integration.ServiceNowSourceProperties; +import software.amazon.customerprofiles.integration.SourceConnectorProperties; +import software.amazon.customerprofiles.integration.SourceFlowConfig; +import software.amazon.customerprofiles.integration.Task; +import software.amazon.customerprofiles.integration.TaskPropertiesMap; +import software.amazon.customerprofiles.integration.TriggerConfig; +import software.amazon.customerprofiles.integration.TriggerProperties; +import software.amazon.customerprofiles.integration.ZendeskSourceProperties; + +public class TestUtils { + + public static FlowDefinition getValidFlowDefinition(String connectorType) { + return FlowDefinition.builder() + .flowName("flow") + .description("description") + .kmsArn("arn") + .sourceFlowConfig(SourceFlowConfig.builder() + .connectorType(connectorType) + .connectorProfileName("test") + .incrementalPullConfig(IncrementalPullConfig.builder() + .datetimeTypeFieldName("LastModifiedDate") + .build()) + .sourceConnectorProperties(getValidSourceConnectorProperties(connectorType)) + .build()) + .triggerConfig(getValidTriggerConfig()) + .tasks(getValidTasks(connectorType)) + .build(); + } + + public static SourceConnectorProperties getValidSourceConnectorProperties(String connectorType) { + switch (connectorType) { + case "Marketo": + return SourceConnectorProperties.builder() + .marketo(MarketoSourceProperties.builder() + .object("testObject") + .build()) + .build(); + case "Salesforce": + return SourceConnectorProperties.builder() + .salesforce(SalesforceSourceProperties.builder() + .enableDynamicFieldUpdate(false) + .includeDeletedRecords(false) + .object("testObject") + .build()) + .build(); + case "S3": + return SourceConnectorProperties.builder() + .s3(S3SourceProperties.builder() + .bucketName("testBucketName") + .bucketPrefix("testBucketPrefix") + .build()) + .build(); + case "ServiceNow": + return SourceConnectorProperties.builder() + .serviceNow(ServiceNowSourceProperties.builder() + .object("testObject") + .build()) + .build(); + case "Zendesk": + return SourceConnectorProperties.builder() + .zendesk(ZendeskSourceProperties.builder() + .object("testObject") + .build()) + .build(); + default: + return SourceConnectorProperties.builder().build(); + } + } + + public static TriggerConfig getValidTriggerConfig() { + return TriggerConfig.builder() + .triggerType("Scheduled") + .triggerProperties( + TriggerProperties.builder() + .scheduled(ScheduledTriggerProperties.builder() + .firstExecutionFrom(Double.valueOf("000")) + .scheduleStartTime(Double.valueOf("123")) + .scheduleEndTime(Double.valueOf("456")) + .dataPullMode("Incremental") + .scheduleExpression("rate(1hours)") + .scheduleOffset(1000) + .timezone("UTC") + .build()) + .build()) + .build(); + } + + public static List getValidTasks(String connectorType) { + return Collections.singletonList( + Task.builder() + .taskType("Filter") + .connectorOperator(getValidConnectorOperator(connectorType)) + .destinationField("destField") + .sourceFields(Arrays.asList("sourceField")) + .taskProperties(Collections.singletonList( + TaskPropertiesMap.builder() + .operatorPropertyKey("SOURCE_DATA_TYPE") + .property("string") + .build())) + .build()); + } + + public static ConnectorOperator getValidConnectorOperator(String connectorType) { + String operator = "PROJECTION"; + switch (connectorType) { + case "Marketo": + return ConnectorOperator.builder().marketo(operator).build(); + case "Salesforce": + return ConnectorOperator.builder().salesforce(operator).build(); + case "S3": + return ConnectorOperator.builder().s3(operator).build(); + case "ServiceNow": + return ConnectorOperator.builder().serviceNow(operator).build(); + case "Zendesk": + return ConnectorOperator.builder().zendesk(operator).build(); + default: + return ConnectorOperator.builder().build(); + } + } +} diff --git a/aws-customerprofiles-integration/src/test/java/software/amazon/customerprofiles/integration/translators/TriggerConfigTranslatorTest.java b/aws-customerprofiles-integration/src/test/java/software/amazon/customerprofiles/integration/translators/TriggerConfigTranslatorTest.java new file mode 100644 index 0000000..64abaea --- /dev/null +++ b/aws-customerprofiles-integration/src/test/java/software/amazon/customerprofiles/integration/translators/TriggerConfigTranslatorTest.java @@ -0,0 +1,83 @@ +package software.amazon.customerprofiles.integration.translators; + +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.services.customerprofiles.model.TriggerConfig; +import software.amazon.awssdk.services.customerprofiles.model.TriggerType; +import software.amazon.awssdk.services.customerprofiles.model.ScheduledTriggerProperties; +import software.amazon.customerprofiles.integration.TriggerProperties; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static software.amazon.customerprofiles.integration.translators.TestUtils.getValidTriggerConfig; + +public class TriggerConfigTranslatorTest { + + @Test + public void testToServiceTriggerConfig() { + software.amazon.customerprofiles.integration.TriggerConfig model = getValidTriggerConfig(); + TriggerConfig translated = TriggerConfigTranslator.toServiceTriggerConfig(model); + + assertNotNull(translated); + assertNotNull(translated.triggerType()); + assertEquals(translated.triggerType(), TriggerType.SCHEDULED); + assertNotNull(translated.triggerProperties()); + assertNotNull(translated.triggerProperties().scheduled()); + } + + @Test + public void testToServiceTriggerConfigNoTriggerProperties() { + software.amazon.customerprofiles.integration.TriggerConfig model = getValidTriggerConfig(); + model.setTriggerProperties(null); + TriggerConfig translated = TriggerConfigTranslator.toServiceTriggerConfig(model); + + assertNotNull(translated); + assertNotNull(translated.triggerType()); + assertEquals(translated.triggerType(), TriggerType.SCHEDULED); + assertNull(translated.triggerProperties()); + } + + @Test + public void testToServiceTriggerConfigNoScheduledTriggerProperties() { + software.amazon.customerprofiles.integration.TriggerConfig model = getValidTriggerConfig(); + + TriggerProperties triggerProperties = TriggerProperties.builder().scheduled(null).build(); + model.setTriggerProperties(triggerProperties); + TriggerConfig translated = TriggerConfigTranslator.toServiceTriggerConfig(model); + + assertNotNull(translated); + assertNotNull(translated.triggerType()); + assertEquals(translated.triggerType(), TriggerType.SCHEDULED); + assertNotNull(translated.triggerProperties()); + assertNull(translated.triggerProperties().scheduled()); + + } + + @Test + public void testToServiceTriggerConfigOnlyRequiredTriggerProperties() { + software.amazon.customerprofiles.integration.TriggerConfig model = getValidTriggerConfig(); + software.amazon.customerprofiles.integration.ScheduledTriggerProperties props = + software.amazon.customerprofiles.integration.ScheduledTriggerProperties.builder() + .firstExecutionFrom(null) + .scheduleStartTime(null) + .scheduleEndTime(null) + .scheduleExpression("rate(1hours)") + .timezone(null) + .dataPullMode(null) + .scheduleOffset(null) + .build(); + + model.setTriggerProperties(software.amazon.customerprofiles.integration.TriggerProperties.builder().scheduled(props).build()); + TriggerConfig translated = TriggerConfigTranslator.toServiceTriggerConfig(model); + + assertNotNull(translated); + assertNotNull(translated.triggerProperties()); + assertNotNull(translated.triggerProperties().scheduled()); + ScheduledTriggerProperties scheduledProps = translated.triggerProperties().scheduled(); + assertNull(scheduledProps.dataPullMode()); + assertNull(scheduledProps.firstExecutionFrom()); + assertNull(scheduledProps.scheduleStartTime()); + assertNull(scheduledProps.scheduleEndTime()); + assertNull(scheduledProps.scheduleOffset()); + assertNull(scheduledProps.timezone()); + } +} diff --git a/aws-customerprofiles-integration/src/test/java/software/amazon/customerprofiles/integration/translators/ZendeskTranslatorTest.java b/aws-customerprofiles-integration/src/test/java/software/amazon/customerprofiles/integration/translators/ZendeskTranslatorTest.java new file mode 100644 index 0000000..3a28da1 --- /dev/null +++ b/aws-customerprofiles-integration/src/test/java/software/amazon/customerprofiles/integration/translators/ZendeskTranslatorTest.java @@ -0,0 +1,59 @@ +package software.amazon.customerprofiles.integration.translators; + +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.services.customerprofiles.model.ConnectorOperator; +import software.amazon.awssdk.services.customerprofiles.model.SourceFlowConfig; +import software.amazon.customerprofiles.integration.IncrementalPullConfig; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static software.amazon.customerprofiles.integration.translators.TestUtils.getValidSourceConnectorProperties; + +public class ZendeskTranslatorTest { + + ZendeskTranslator translator = new ZendeskTranslator(); + + @Test + public void testSourceFlowConfig() { + software.amazon.customerprofiles.integration.SourceFlowConfig model = software.amazon.customerprofiles.integration.SourceFlowConfig.builder() + .connectorProfileName("test name") + .connectorType("Zendesk") + .sourceConnectorProperties(getValidSourceConnectorProperties("Zendesk")) + .build(); + SourceFlowConfig translated = translator.toServiceSourceFlowConfig(model); + + assertNotNull(translated); + assertNotNull(translated.connectorProfileName()); + assertNotNull(translated.connectorType()); + assertNotNull(translated.sourceConnectorProperties().zendesk().object()); + } + + @Test + public void testSourceFlowConfigOnlyRequiredFields() { + software.amazon.customerprofiles.integration.SourceFlowConfig model = software.amazon.customerprofiles.integration.SourceFlowConfig.builder() + .connectorType("Zendesk") + .sourceConnectorProperties(getValidSourceConnectorProperties("Zendesk")) + .build(); + SourceFlowConfig translated = translator.toServiceSourceFlowConfig(model); + + assertNotNull(translated); + assertNull(translated.connectorProfileName()); + assertNull(translated.incrementalPullConfig()); + } + + @Test + public void testConnectorOperator() { + ConnectorOperator translated = translator.toServiceConnectorOperator( + software.amazon.customerprofiles.integration.ConnectorOperator.builder() + .zendesk("test") + .build()); + + assertNotNull(translated); + assertNotNull(translated.zendesk()); + } + + @Test + public void testConnectorOperatorNull() { + ConnectorOperator translated = translator.toServiceConnectorOperator(null); + assertNull(translated); + } +}