This Amazon Web Services (AWS) Solution is used to deploy AWS Migration Hub Refactor Spaces components in the AWS Cloud. For common deployment examples, refer to examples/. The solution is for users who want to deploy Refactor Spaces environments and modernize applications to microservices. Refactor Spaces helps reduce the undifferentiated heavy lifting of building and operating AWS infrastructure for incremental refactoring.
For more information, refer to the AWS Migration Hub Refactor Space documentation.
You pay for the cost of the Refactor Spaces feature and any resources being consumed on AWS. For more information, refer to AWS Migration Hub pricing.
Use this solution to create all AWS Migration Hub Refactor Spaces components as part of a single deployment or to add AWS Migration Hub Refactor Spaces applications or services to an existing AWS Migration Hub Refactor Spaces environment or application (in multi-account deployment scenarios).
Figure 1 shows an example deployment of all AWS Migration Hub Refactor Spaces in a single account.
Figure 1. Example configuration of AWS Migration Hub Refactor Spaces deployed with a monolithic application Unishop with a new AddToCart microservice, running as an AWS Lambda microservice.
As shown in the diagram, the solution in this example sets up the following:
- A highly available architecture that spans two Availability Zones.*
- In one virtual private cloud (VPC):
- Private subnets containing an AWS Transit Gateway attachment. Amazon API Gateway uses this attachment to communicate with workloads deployed in other AWS accounts/VPCs.*
- A Network Load Balancer, which uses the VPC link feature and distributes incoming traffic.*
- In the second VPC:
- Private subnets, which contain an Amazon Elastic Compute Cloud (Amazon EC2) instance that hosts the monolithic Unistore legacy application. Each subnet also contains an AWS Transit Gateway attachment, which is used to provide private connectivity between the API Gateway and the application hosted within the VPC.*
- An Application Load Balancer to forward traffic to the Amazon EC2 instances.*
- In the AWS Migration Hub's Refactor Spaces environment:
- AWS Transit Gateway, provisioned and managed by AWS Migration Hub's Refactor Spaces. If you choose to bring your own AWS Transit Gateway, this can be controlled using an optional input parameter.
- A Refactor Spaces application that manages Amazon API Gateway and two services: Default and AddtoCart. Default acts as the default route for traffic to the Unistore application. AddtoCart sends AddtoCart domain requests to the AWS Lambda function.
- A Lambda function that holds the modernized AddToCart business logic strangled from the Unistore application.
*The Terraform module that deploys this solution does not include the components marked by asterisks. These components, which you would provide as inputs, are depicted to illustrate a real-world deployment scenario.
For example usage, refer to the examples/ directory in this repository.
This Terraform solution is maintained by AWS Solution Architects. It is not part of an AWS service, so the community provides support.
To post feedback, submit feature ideas, or report bugs, use the Issues section of this GitHub repo.
Refer to our developer documentation for guidance on contributing to this solution.
The VPC association failed for a VPC with a vpc-XXXYYYZZZ ID to an environment with a env-XXXYYYXZZ ID
Issue: During a terraform apply
, when you deploy a solution with two or more AWS Migration Hub Refactor Spaces applications defined (see below for example), you encounter the following exception:
Error: AWS SDK Go Service Operation Incomplete
│
│ with module.refactor_spaces_application["XXXX"].awscc_refactorspaces_application.current,
│ on modules\tf-refactor-spaces-application\main.tf line 13, in resource "awscc_refactorspaces_application" "current":
│ 13: resource "awscc_refactorspaces_application" "current" {
│
│ Waiting for Cloud Control API service CreateResource operation completion returned: waiter state transitioned to FAILED. StatusMessage: java.lang.IllegalStateException: Resource of type AWS::RefactorSpaces::Application with identifier app-XXXXX did not stabilize. Details = ErrorResponse(AccountId=XXXXXXX, Code=RESOURCE_CREATION_FAILURE, Message=Vpc Association Failed for Vpc with ID vpc-XXXYYYZZZ to environment with ID env-XXXYYYXZZ., ResourceIdentifier=vpc-XXXYYYZZZ, ResourceType=VPC). ErrorCode: InternalFailure
Example configuration:
module "refactor_spaces" {
source = "aws-ia/refactorspaces/awscc"
version = "0.0.2"
environment_name = "Unicorn"
environment_description = "AWS Migration Hub Refactor Spaces environment for Unicorn Rentals."
provision_network_bridge = true
applications = [
{
application_name = "Unistore"
proxy_type = "REGIONAL"
application_proxy_vpc_id = "vpc-AAABBBBCCC"
apigateway_stage_name = "prod"
},
{
application_name = "Birds"
proxy_type = "REGIONAL"
application_proxy_vpc_id = "vpc-DDDEEEFFF"
apigateway_stage_name = "prod"
}
]
Cause: Terraform attempts to create both Refactor Spaces applications asynchronously; however, concurrent creation/deletion of an application within the same AWS Migration Hub Refactor Spaces environment is not supported.
Workaround: If you are creating multiple applications during a single apply, use the Terraform -parallelism
flag set to 1
(example: terraform apply -parallelism=1
). You can also create the first application and perform the terraform apply
and after execution, add the next application and re-run terraform apply
.
The services forced recreation during every apply when using awscc_refactorspaces_environment
or awscc_refactorspaces_application
data objects in the module input variables
Issue: When using the solution to create AWS Migration Hub Refactor Spaces services and routes as separate module blocks, and using the awscc_refactorspaces_environment
or awscc_refactorspaces_application
data objects as inputs, Terraform forces a re-creation (delete, create) during every apply.
Cause: The attributes application_identifier
and environment_identifier
are marked as (known after apply)
for the service and route resources. This forces a replacement because these attributes are marked in the provider as a forced replacement operation.
Workaround: Use input variables to define the values passed as environment_id
and application_id
to the module.
Issue: When using the solution to create AWS Migration Hub Refactor Spaces components as separate module blocks (one module block to create the environment, one module block to create an application, and one module block to create services) in the same HCL which references the dependent module blocks, you encounter this error:
Error: Invalid count argument
on .terraform\modules\XXXX\main.tf line 6, in module "XXX":
6: count = local.create_environment ? 1 : 0
The "count" value depends on resource attributes that cannot be determined until apply, so Terraform cannot predict how many instances will be created. To work around this, use the -target argument to first apply only the resources that the count depends on.
Cause: The module uses count/foreach blocks to determine if an environment or application needs to be created. During a Terraform plan, as the environment_id
and/or application_id
values are not known until after the apply, Terraform encounters an exception. Terraform currently has a limitation when using computed values in modules containing count and foreach blocks, so the number of objects created must be known before the apply. (See hashicorp/terraform#26078).
Workaround: Use one of the following approaches to workaround this issue:
- If you wish to define multiple module blocks in a single HCL definition, use
terraform apply -target=module.XXX
to create the dependent modules first before callingterraform apply
. You may have to execute several differentapply
actions with this approach. - Deploy each module blocks in different pipelines/projects/folders and read the remote state, or use the relevant data objects to read the inputs.
In a multi-account deployment, service creation/deletion fails with Route Table operation failures, if service tags are removed from objects
Issue: You receive a failure message similar to the following:
Waiting for Cloud Control API service CreateResource operation completion returned: waiter state transitioned to FAILED. StatusMessage: java.lang.IllegalStateException: Resource of type AWS::RefactorSpaces::Service
│ with identifier svc-XXXX did not stabilize. Details = ErrorResponse(AccountId=XXXX, AdditionalDetails={TransitGatewayID=tgw-XXXXX, DestinationCIDRBlock=XX.XX.XX.0/XX,
│ RouteTableID=rtb-XXXX}, Code=RESOURCE_UPDATE_FAILURE, Message=Failed to update Route table rtb-XXXXX to add route from CIDR XX.XX.XX.0/XX to TGW tgw-XXXX,
│ ResourceIdentifier=rtb-XXXXX, ResourceType=ROUTE_TABLE). ErrorCode: InternalFailure
Cause: AWS Migration Hub Refactor Spaces service creates the tags refactor-spaces:environment-id
and refactor-spaces:application-id
on resources that are part of an environment during configuration. The table below provides a list of where each tag is configured as part of the service configuration.
These tags are used by the service and removal/adjustment can cause the service to behave incorrectly. In a multi-account deployment, if these tags are removed from the resources, it causes the AWS Migration Services Refactor Spaces service operations to complete unsuccessfully. This can occur if the objects are managed by AWS Config or Terraform with a configuration to have tags set explicitly to a set of values.
Resource | Tag(s) | Value |
---|---|---|
Environment Transit Gateway | refactor-spaces:environment-id | Refactor Spaces Environment Id |
Environment Resource Share | refactor-spaces:environment-id | Refactor Spaces Environment Id |
Application Amazon API Gateway | refactor-spaces:application-id | Refactor Spaces Application Id |
Network Load Balancer | refactor-spaces:application-id | Refactor Spaces Application Id |
Application Proxy VPC | refactor-spaces:environment-id | Refactor Spaces Environment Id |
Application Proxy VPC Subnet(s) | refactor-spaces:environment-id | Refactor Spaces Environment Id |
Application Proxy VPC Route Table(s) | refactor-spaces:environment-id | Refactor Spaces Environment Id |
Application Proxy VPC Endpoint Service | refactor-spaces:application-id | Refactor Spaces Application Id |
Application Proxy Refactor Spaces Security Group | refactor-spaces:environment-id | Refactor Spaces Environment Id |
Service Endpoint VPC | refactor-spaces:environment-id | Refactor Spaces Environment Id |
Service Endpoint VPC Subnet(s) | refactor-spaces:environment-id | Refactor Spaces Environment Id |
Service Endpoint VPC Route Table(s) | refactor-spaces:environment-id | Refactor Spaces Environment Id |
Service Endpoint Transit GW Attachment | refactor-spaces:environment-id | Refactor Spaces Environment Id |
Service Endpoint Refactor Spaces Security Group | refactor-spaces:environment-id | Refactor Spaces Environment Id |
Workaround: Any of these resources managed by Terraform (including those imported) should include these tags as part of the Terraform resource definition, or explicitly ignore them during applies.
For resources using the aws
provider, add the following to the provider configuration:
ignore_tags {
key_prefixes = ["refactor-spaces:"]
}
For resources managed by the awscc
provider you must add the tags to the resource definitions. A feature request has been opened to add this feature to the awscc
provider, in the future.
Cloud security at AWS is the highest priority. Security is a shared responsibility between AWS and you. For more information on understanding how to apply the shared responsibility model when using AWS Migration Hub Refactor Spaces, please refer to Security in AWS Migration Hub Refactor Spaces.
Name | Version |
---|---|
terraform | >= 1.3.0 |
awscc | >= 0.49.0 |
Name | Version |
---|---|
awscc | >= 0.49.0 |
Name | Source | Version |
---|---|---|
refactor_spaces_application | ./modules/tf-refactor-spaces-application | n/a |
refactor_spaces_environment | ./modules/tf-refactor-spaces-environment | n/a |
refactor_spaces_service_defaults | ./modules/tf-refactor-spaces-service | n/a |
refactor_spaces_service_non_defaults | ./modules/tf-refactor-spaces-service | n/a |
Name | Type |
---|---|
awscc_refactorspaces_application.application | data source |
awscc_refactorspaces_environment.environment | data source |
Name | Description | Type | Default | Required |
---|---|---|---|---|
application_id | AWS Migration Hub Refactor Spaces application ID of an already-deployed application to deploy additional services. var.environment_id must be specified if this value is not null . |
string |
null |
no |
applications | List of AWS Migration Hub Refactor Spaces applications to create. Ignored if var.application_id for an existing application is provided in the module block.Properties: - application_name = (Required|string) The name of the application.- proxy_type = (Optional|string) The proxy type for the application. REGIONAL APIs are publicly accessible in the current Region. PRIVATE APIs are accessible only from VPCs. Default: REGIONAL.- apigateway_stage_name = (Optional|string) The name of the API Gateway stage to use for the application proxy. The name defaults to prod.- application_proxy_vpc_id = (Required|string) The Amazon VPC ID of the VPC to deploy the application's proxy.Example: applications = [ |
list(object({ |
[] |
no |
environment_description | (Optional) Description for AWS Migration Hub Refactor Spaces environment. Ignored if var.environment_id for an existing environment is provided. |
string |
null |
no |
environment_id | AWS Migration Hub Refactor Spaces environment ID of an already-deployed environment to deploy additional applications or services. | string |
null |
no |
environment_name | Name of AWS Migration Hub Refactor Spaces environment to create. Ignored if var.environment_id for an existing environment is provided. |
string |
null |
no |
provision_network_bridge | When true AWS Migration Hub Refactor Spaces creates and manages an AWS Transit Gateway to establish cross-account network connectivity for this environment. Default: false. |
bool |
false |
no |
resource_tags | Tags to set for all resources. | map(string) |
{} |
no |
services | List of AWS Migration Hub Refactor Spaces service specifications and their routing configuration. Properties: - name = (Required|string) The name of the service.- application_name = (Required|string) The name of the application to associate the service.- description = (Optional|string) A description of the service.- endpoint_type = (Required|string) The endpoint type of the service. Allowed type is "URL" or "LAMBDA" .- lambda_arn = (Optional|string) The ARN of the Lambda function to use for the endpoint. Required if endpoint_type = "LAMBDA" .- url_endpoint = (Optional|string) The URL to route traffic to. The URL must be an rfc3986-formatted URL. If the host is a domain name, the name must be resolvable over the public internet. Required if endpoint_type = "URL" .- health_url = (Optional|string) The health check URL of the URL endpoint type. If the URL is a public endpoint, the HealthURL must also be a public endpoint.- vpc_id = (Optional|string) The ID of the VPC hosting the URL to route traffic to.- routes = (Optional|list(object)) A collection of routes to associate with the service.- source_path = (Required|string) (Required|string) The path to use to match traffic. Paths must start with / and are relative to the base of the application. If the route is the default this should be set as '/'.- include_child_paths = (Optional|bool) Indicates whether to match all subpaths of the given source path. If this value is false , requests must match the source path exactly before they are forwarded to this route's service. Default true.- http_verbs = (Optional|list(string)) A list of HTTP methods to match. An empty list matches all values. Default all values.- route_active = (Required|bool) If set to true , traffic is forwarded to this route’s service after the route is created.Example: services = [ |
list(object({ |
[] |
no |
shared_to_principals | Optional list of AWS principals to share the AWS Migration Hub Refactor Spaces environment with. Ignored if var.environment_id for an existing environment is provided.Note: The setting Enable sharing with AWS Organizations under the Resource Access Manager service must be enabled on the master account for your organization to share the organizational unit or to share with the entire organization. For more information, refer to https://docs.aws.amazon.com/ram/latest/userguide/getting-started-sharing.html.Allowed values are: - 12-digit AWS account IDs; - ARN of the organization or; - ARN of the organizational units Example: shared_to_principals = [ |
list(string) |
[] |
no |
Name | Description |
---|---|
applications | Collection of AWS Migration Hub Refactor Spaces application managed by or used. Example: applications = [ |
environment | AWS Migration Hub Refactor Spaces environment resource attributes. Full output of awscc_refactorspaces_environment . |
services | Collection of AWS Migration Hub Refactor Spaces services and associated routes. Example: services = [ |