diff --git a/allowed-breaking-changes.txt b/allowed-breaking-changes.txt index 2f4d77b2757bd..dba2f0f6dc042 100644 --- a/allowed-breaking-changes.txt +++ b/allowed-breaking-changes.txt @@ -188,3 +188,6 @@ removed:aws-cdk-lib.aws_cloudwatch.CfnAlarm.attrId removed:aws-cdk-lib.aws_ec2.CfnNetworkInterface.enablePrimaryIpv6 removed:aws-cdk-lib.aws_ec2.CfnNetworkInterfaceAttachment.attrId removed:aws-cdk-lib.aws_ec2.CfnNetworkInterfaceProps.enablePrimaryIpv6 + +# Changed type from GraphqlApi to IGraphqlApi to support import from a different stack, should not matter. +weakened:aws-cdk-lib.aws_appsync.SourceApi diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/appsync.merged-api-3.graphql b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/appsync.merged-api-3.graphql new file mode 100644 index 0000000000000..9467886128c0b --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/appsync.merged-api-3.graphql @@ -0,0 +1,9 @@ +type thirdTest { + version: String! +} +type Query { + getThirdTests: [thirdTest]! +} +type Mutation { + addThirdTest(version: String!): thirdTest +} diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-merged-api-arn-flag-enabled.js.snapshot/apiDefaultTestDeployAssert018781F2.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-merged-api-arn-flag-enabled.js.snapshot/apiDefaultTestDeployAssert018781F2.assets.json new file mode 100644 index 0000000000000..017cff874641f --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-merged-api-arn-flag-enabled.js.snapshot/apiDefaultTestDeployAssert018781F2.assets.json @@ -0,0 +1,19 @@ +{ + "version": "34.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "apiDefaultTestDeployAssert018781F2.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-merged-api-arn-flag-enabled.js.snapshot/apiDefaultTestDeployAssert018781F2.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-merged-api-arn-flag-enabled.js.snapshot/apiDefaultTestDeployAssert018781F2.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-merged-api-arn-flag-enabled.js.snapshot/apiDefaultTestDeployAssert018781F2.template.json @@ -0,0 +1,36 @@ +{ + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-merged-api-arn-flag-enabled.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-merged-api-arn-flag-enabled.js.snapshot/cdk.out new file mode 100644 index 0000000000000..2313ab5436501 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-merged-api-arn-flag-enabled.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"34.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-merged-api-arn-flag-enabled.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-merged-api-arn-flag-enabled.js.snapshot/integ.json new file mode 100644 index 0000000000000..087c643f2d4b9 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-merged-api-arn-flag-enabled.js.snapshot/integ.json @@ -0,0 +1,12 @@ +{ + "version": "34.0.0", + "testCases": { + "api/DefaultTest": { + "stacks": [ + "stack" + ], + "assertionStack": "api/DefaultTest/DeployAssert", + "assertionStackName": "apiDefaultTestDeployAssert018781F2" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-merged-api-arn-flag-enabled.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-merged-api-arn-flag-enabled.js.snapshot/manifest.json new file mode 100644 index 0000000000000..98c8121fe9fdb --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-merged-api-arn-flag-enabled.js.snapshot/manifest.json @@ -0,0 +1,189 @@ +{ + "version": "34.0.0", + "artifacts": { + "stack.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "stack.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "stack": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "stack.template.json", + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/56930136ed109a6e2bbab108d97daf7201ee4fd652cff93f20eb31cd855e4e47.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "stack.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "stack.assets" + ], + "metadata": { + "/stack/FirstSourceAPI/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "FirstSourceAPIB0DE8D5A" + } + ], + "/stack/FirstSourceAPI/Schema": [ + { + "type": "aws:cdk:logicalId", + "data": "FirstSourceAPISchemaF2FDB692" + } + ], + "/stack/FirstSourceAPI/DefaultApiKey": [ + { + "type": "aws:cdk:logicalId", + "data": "FirstSourceAPIDefaultApiKey9D9AE06D" + } + ], + "/stack/FirstSourceAPI/FirstSourceDS/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "FirstSourceAPIFirstSourceDS6AD299B7" + } + ], + "/stack/SecondSourceAPI/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "SecondSourceAPIE903371D" + } + ], + "/stack/SecondSourceAPI/Schema": [ + { + "type": "aws:cdk:logicalId", + "data": "SecondSourceAPISchema65B7401E" + } + ], + "/stack/SecondSourceAPI/DefaultApiKey": [ + { + "type": "aws:cdk:logicalId", + "data": "SecondSourceAPIDefaultApiKeyCE5A0A64" + } + ], + "/stack/SecondSourceAPI/SecondSourceDS/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "SecondSourceAPISecondSourceDSEA46EBA7" + } + ], + "/stack/MergedAPI/MergedApiExecutionRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MergedAPIMergedApiExecutionRole5F2BCCAD" + } + ], + "/stack/MergedAPI/MergedApiExecutionRole/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MergedAPIMergedApiExecutionRoleDefaultPolicy31A96DBC" + } + ], + "/stack/MergedAPI/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MergedAPI08D3EAD1" + } + ], + "/stack/MergedAPI/FirstSourceAPIAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "MergedAPIFirstSourceAPIAssociationEC781BA9" + } + ], + "/stack/MergedAPI/SecondSourceAPIAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "MergedAPISecondSourceAPIAssociationBD1A08F4" + } + ], + "/stack/MergedAPI/DefaultApiKey": [ + { + "type": "aws:cdk:logicalId", + "data": "MergedAPIDefaultApiKeyAF5EA13C" + } + ], + "/stack/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/stack/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "stack" + }, + "apiDefaultTestDeployAssert018781F2.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "apiDefaultTestDeployAssert018781F2.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "apiDefaultTestDeployAssert018781F2": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "apiDefaultTestDeployAssert018781F2.template.json", + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "apiDefaultTestDeployAssert018781F2.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "apiDefaultTestDeployAssert018781F2.assets" + ], + "metadata": { + "/api/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/api/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "api/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-merged-api-arn-flag-enabled.js.snapshot/stack.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-merged-api-arn-flag-enabled.js.snapshot/stack.assets.json new file mode 100644 index 0000000000000..229acf488872a --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-merged-api-arn-flag-enabled.js.snapshot/stack.assets.json @@ -0,0 +1,19 @@ +{ + "version": "34.0.0", + "files": { + "56930136ed109a6e2bbab108d97daf7201ee4fd652cff93f20eb31cd855e4e47": { + "source": { + "path": "stack.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "56930136ed109a6e2bbab108d97daf7201ee4fd652cff93f20eb31cd855e4e47.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-merged-api-arn-flag-enabled.js.snapshot/stack.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-merged-api-arn-flag-enabled.js.snapshot/stack.template.json new file mode 100644 index 0000000000000..68e5010a4ad4e --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-merged-api-arn-flag-enabled.js.snapshot/stack.template.json @@ -0,0 +1,284 @@ +{ + "Resources": { + "FirstSourceAPIB0DE8D5A": { + "Type": "AWS::AppSync::GraphQLApi", + "Properties": { + "AuthenticationType": "API_KEY", + "Name": "FirstSourceAPI" + } + }, + "FirstSourceAPISchemaF2FDB692": { + "Type": "AWS::AppSync::GraphQLSchema", + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "FirstSourceAPIB0DE8D5A", + "ApiId" + ] + }, + "Definition": "type firstTest {\n version: String!\n}\ntype Query {\n getFirstTests: [firstTest]!\n}\ntype Mutation {\n addFirstTest(version: String!): firstTest\n}\n" + } + }, + "FirstSourceAPIDefaultApiKey9D9AE06D": { + "Type": "AWS::AppSync::ApiKey", + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "FirstSourceAPIB0DE8D5A", + "ApiId" + ] + } + }, + "DependsOn": [ + "FirstSourceAPISchemaF2FDB692" + ] + }, + "FirstSourceAPIFirstSourceDS6AD299B7": { + "Type": "AWS::AppSync::DataSource", + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "FirstSourceAPIB0DE8D5A", + "ApiId" + ] + }, + "Name": "FirstSourceDS", + "Type": "NONE" + } + }, + "SecondSourceAPIE903371D": { + "Type": "AWS::AppSync::GraphQLApi", + "Properties": { + "AuthenticationType": "API_KEY", + "Name": "SecondSourceAPI" + } + }, + "SecondSourceAPISchema65B7401E": { + "Type": "AWS::AppSync::GraphQLSchema", + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SecondSourceAPIE903371D", + "ApiId" + ] + }, + "Definition": "type secondTest {\n version: String!\n}\ntype Query {\n getSecondTests: [secondTest]!\n}\ntype Mutation {\n addSecondTest(version: String!): secondTest\n}\n" + } + }, + "SecondSourceAPIDefaultApiKeyCE5A0A64": { + "Type": "AWS::AppSync::ApiKey", + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SecondSourceAPIE903371D", + "ApiId" + ] + } + }, + "DependsOn": [ + "SecondSourceAPISchema65B7401E" + ] + }, + "SecondSourceAPISecondSourceDSEA46EBA7": { + "Type": "AWS::AppSync::DataSource", + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SecondSourceAPIE903371D", + "ApiId" + ] + }, + "Name": "SecondSourceDS", + "Type": "NONE" + } + }, + "MergedAPIMergedApiExecutionRole5F2BCCAD": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "appsync.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "MergedAPIMergedApiExecutionRoleDefaultPolicy31A96DBC": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": "appsync:SourceGraphQL", + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "MergedAPIFirstSourceAPIAssociationEC781BA9", + "SourceApiArn" + ] + }, + { + "Fn::GetAtt": [ + "MergedAPISecondSourceAPIAssociationBD1A08F4", + "SourceApiArn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "MergedAPIFirstSourceAPIAssociationEC781BA9", + "SourceApiArn" + ] + }, + "/*" + ] + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "MergedAPISecondSourceAPIAssociationBD1A08F4", + "SourceApiArn" + ] + }, + "/*" + ] + ] + } + ] + }, + { + "Action": "appsync:StartSchemaMerge", + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "MergedAPISecondSourceAPIAssociationBD1A08F4", + "AssociationArn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "MergedAPIMergedApiExecutionRoleDefaultPolicy31A96DBC", + "Roles": [ + { + "Ref": "MergedAPIMergedApiExecutionRole5F2BCCAD" + } + ] + } + }, + "MergedAPI08D3EAD1": { + "Type": "AWS::AppSync::GraphQLApi", + "Properties": { + "ApiType": "MERGED", + "AuthenticationType": "API_KEY", + "MergedApiExecutionRoleArn": { + "Fn::GetAtt": [ + "MergedAPIMergedApiExecutionRole5F2BCCAD", + "Arn" + ] + }, + "Name": "MergedAPI" + } + }, + "MergedAPIFirstSourceAPIAssociationEC781BA9": { + "Type": "AWS::AppSync::SourceApiAssociation", + "Properties": { + "MergedApiIdentifier": { + "Fn::GetAtt": [ + "MergedAPI08D3EAD1", + "Arn" + ] + }, + "SourceApiAssociationConfig": { + "MergeType": "MANUAL_MERGE" + }, + "SourceApiIdentifier": { + "Fn::GetAtt": [ + "FirstSourceAPIB0DE8D5A", + "Arn" + ] + } + } + }, + "MergedAPISecondSourceAPIAssociationBD1A08F4": { + "Type": "AWS::AppSync::SourceApiAssociation", + "Properties": { + "MergedApiIdentifier": { + "Fn::GetAtt": [ + "MergedAPI08D3EAD1", + "Arn" + ] + }, + "SourceApiAssociationConfig": { + "MergeType": "AUTO_MERGE" + }, + "SourceApiIdentifier": { + "Fn::GetAtt": [ + "SecondSourceAPIE903371D", + "Arn" + ] + } + } + }, + "MergedAPIDefaultApiKeyAF5EA13C": { + "Type": "AWS::AppSync::ApiKey", + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "MergedAPI08D3EAD1", + "ApiId" + ] + } + } + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-merged-api-arn-flag-enabled.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-merged-api-arn-flag-enabled.js.snapshot/tree.json new file mode 100644 index 0000000000000..811941f6365b2 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-merged-api-arn-flag-enabled.js.snapshot/tree.json @@ -0,0 +1,555 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "stack": { + "id": "stack", + "path": "stack", + "children": { + "FirstSourceAPI": { + "id": "FirstSourceAPI", + "path": "stack/FirstSourceAPI", + "children": { + "Resource": { + "id": "Resource", + "path": "stack/FirstSourceAPI/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::AppSync::GraphQLApi", + "aws:cdk:cloudformation:props": { + "authenticationType": "API_KEY", + "name": "FirstSourceAPI" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appsync.CfnGraphQLApi", + "version": "0.0.0" + } + }, + "Schema": { + "id": "Schema", + "path": "stack/FirstSourceAPI/Schema", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::AppSync::GraphQLSchema", + "aws:cdk:cloudformation:props": { + "apiId": { + "Fn::GetAtt": [ + "FirstSourceAPIB0DE8D5A", + "ApiId" + ] + }, + "definition": "type firstTest {\n version: String!\n}\ntype Query {\n getFirstTests: [firstTest]!\n}\ntype Mutation {\n addFirstTest(version: String!): firstTest\n}\n" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appsync.CfnGraphQLSchema", + "version": "0.0.0" + } + }, + "DefaultApiKey": { + "id": "DefaultApiKey", + "path": "stack/FirstSourceAPI/DefaultApiKey", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::AppSync::ApiKey", + "aws:cdk:cloudformation:props": { + "apiId": { + "Fn::GetAtt": [ + "FirstSourceAPIB0DE8D5A", + "ApiId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appsync.CfnApiKey", + "version": "0.0.0" + } + }, + "LogGroup": { + "id": "LogGroup", + "path": "stack/FirstSourceAPI/LogGroup", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "FirstSourceDS": { + "id": "FirstSourceDS", + "path": "stack/FirstSourceAPI/FirstSourceDS", + "children": { + "Resource": { + "id": "Resource", + "path": "stack/FirstSourceAPI/FirstSourceDS/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::AppSync::DataSource", + "aws:cdk:cloudformation:props": { + "apiId": { + "Fn::GetAtt": [ + "FirstSourceAPIB0DE8D5A", + "ApiId" + ] + }, + "name": "FirstSourceDS", + "type": "NONE" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appsync.CfnDataSource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appsync.NoneDataSource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appsync.GraphqlApi", + "version": "0.0.0" + } + }, + "SecondSourceAPI": { + "id": "SecondSourceAPI", + "path": "stack/SecondSourceAPI", + "children": { + "Resource": { + "id": "Resource", + "path": "stack/SecondSourceAPI/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::AppSync::GraphQLApi", + "aws:cdk:cloudformation:props": { + "authenticationType": "API_KEY", + "name": "SecondSourceAPI" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appsync.CfnGraphQLApi", + "version": "0.0.0" + } + }, + "Schema": { + "id": "Schema", + "path": "stack/SecondSourceAPI/Schema", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::AppSync::GraphQLSchema", + "aws:cdk:cloudformation:props": { + "apiId": { + "Fn::GetAtt": [ + "SecondSourceAPIE903371D", + "ApiId" + ] + }, + "definition": "type secondTest {\n version: String!\n}\ntype Query {\n getSecondTests: [secondTest]!\n}\ntype Mutation {\n addSecondTest(version: String!): secondTest\n}\n" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appsync.CfnGraphQLSchema", + "version": "0.0.0" + } + }, + "DefaultApiKey": { + "id": "DefaultApiKey", + "path": "stack/SecondSourceAPI/DefaultApiKey", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::AppSync::ApiKey", + "aws:cdk:cloudformation:props": { + "apiId": { + "Fn::GetAtt": [ + "SecondSourceAPIE903371D", + "ApiId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appsync.CfnApiKey", + "version": "0.0.0" + } + }, + "LogGroup": { + "id": "LogGroup", + "path": "stack/SecondSourceAPI/LogGroup", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "SecondSourceDS": { + "id": "SecondSourceDS", + "path": "stack/SecondSourceAPI/SecondSourceDS", + "children": { + "Resource": { + "id": "Resource", + "path": "stack/SecondSourceAPI/SecondSourceDS/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::AppSync::DataSource", + "aws:cdk:cloudformation:props": { + "apiId": { + "Fn::GetAtt": [ + "SecondSourceAPIE903371D", + "ApiId" + ] + }, + "name": "SecondSourceDS", + "type": "NONE" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appsync.CfnDataSource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appsync.NoneDataSource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appsync.GraphqlApi", + "version": "0.0.0" + } + }, + "MergedAPI": { + "id": "MergedAPI", + "path": "stack/MergedAPI", + "children": { + "MergedApiExecutionRole": { + "id": "MergedApiExecutionRole", + "path": "stack/MergedAPI/MergedApiExecutionRole", + "children": { + "ImportMergedApiExecutionRole": { + "id": "ImportMergedApiExecutionRole", + "path": "stack/MergedAPI/MergedApiExecutionRole/ImportMergedApiExecutionRole", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "stack/MergedAPI/MergedApiExecutionRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "appsync.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnRole", + "version": "0.0.0" + } + }, + "DefaultPolicy": { + "id": "DefaultPolicy", + "path": "stack/MergedAPI/MergedApiExecutionRole/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "stack/MergedAPI/MergedApiExecutionRole/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": "appsync:SourceGraphQL", + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "MergedAPIFirstSourceAPIAssociationEC781BA9", + "SourceApiArn" + ] + }, + { + "Fn::GetAtt": [ + "MergedAPISecondSourceAPIAssociationBD1A08F4", + "SourceApiArn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "MergedAPIFirstSourceAPIAssociationEC781BA9", + "SourceApiArn" + ] + }, + "/*" + ] + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "MergedAPISecondSourceAPIAssociationBD1A08F4", + "SourceApiArn" + ] + }, + "/*" + ] + ] + } + ] + }, + { + "Action": "appsync:StartSchemaMerge", + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "MergedAPISecondSourceAPIAssociationBD1A08F4", + "AssociationArn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "policyName": "MergedAPIMergedApiExecutionRoleDefaultPolicy31A96DBC", + "roles": [ + { + "Ref": "MergedAPIMergedApiExecutionRole5F2BCCAD" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnPolicy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Policy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Role", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "stack/MergedAPI/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::AppSync::GraphQLApi", + "aws:cdk:cloudformation:props": { + "apiType": "MERGED", + "authenticationType": "API_KEY", + "mergedApiExecutionRoleArn": { + "Fn::GetAtt": [ + "MergedAPIMergedApiExecutionRole5F2BCCAD", + "Arn" + ] + }, + "name": "MergedAPI" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appsync.CfnGraphQLApi", + "version": "0.0.0" + } + }, + "FirstSourceAPIAssociation": { + "id": "FirstSourceAPIAssociation", + "path": "stack/MergedAPI/FirstSourceAPIAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::AppSync::SourceApiAssociation", + "aws:cdk:cloudformation:props": { + "mergedApiIdentifier": { + "Fn::GetAtt": [ + "MergedAPI08D3EAD1", + "Arn" + ] + }, + "sourceApiAssociationConfig": { + "mergeType": "MANUAL_MERGE" + }, + "sourceApiIdentifier": { + "Fn::GetAtt": [ + "FirstSourceAPIB0DE8D5A", + "Arn" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appsync.CfnSourceApiAssociation", + "version": "0.0.0" + } + }, + "SecondSourceAPIAssociation": { + "id": "SecondSourceAPIAssociation", + "path": "stack/MergedAPI/SecondSourceAPIAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::AppSync::SourceApiAssociation", + "aws:cdk:cloudformation:props": { + "mergedApiIdentifier": { + "Fn::GetAtt": [ + "MergedAPI08D3EAD1", + "Arn" + ] + }, + "sourceApiAssociationConfig": { + "mergeType": "AUTO_MERGE" + }, + "sourceApiIdentifier": { + "Fn::GetAtt": [ + "SecondSourceAPIE903371D", + "Arn" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appsync.CfnSourceApiAssociation", + "version": "0.0.0" + } + }, + "DefaultApiKey": { + "id": "DefaultApiKey", + "path": "stack/MergedAPI/DefaultApiKey", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::AppSync::ApiKey", + "aws:cdk:cloudformation:props": { + "apiId": { + "Fn::GetAtt": [ + "MergedAPI08D3EAD1", + "ApiId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appsync.CfnApiKey", + "version": "0.0.0" + } + }, + "LogGroup": { + "id": "LogGroup", + "path": "stack/MergedAPI/LogGroup", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appsync.GraphqlApi", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "stack/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "stack/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + }, + "api": { + "id": "api", + "path": "api", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "api/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "api/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.2.70" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "api/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "api/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "api/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTest", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.2.70" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.App", + "version": "0.0.0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-merged-api-arn-flag-enabled.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-merged-api-arn-flag-enabled.ts new file mode 100644 index 0000000000000..0a77b5752f6f6 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-merged-api-arn-flag-enabled.ts @@ -0,0 +1,52 @@ +import * as path from 'path'; +import * as cdk from 'aws-cdk-lib'; +import { IntegTest } from '@aws-cdk/integ-tests-alpha'; +import * as appsync from 'aws-cdk-lib/aws-appsync'; + +const app = new cdk.App({ + postCliContext: { + [cdk.cx_api.APPSYNC_ENABLE_USE_ARN_IDENTIFIER_SOURCE_API_ASSOCIATION]: true, + }, +}); + +const stack = new cdk.Stack(app, 'stack'); + +const firstApi = new appsync.GraphqlApi(stack, 'FirstSourceAPI', { + name: 'FirstSourceAPI', + definition: appsync.Definition.fromFile(path.join(__dirname, 'appsync.merged-api-1.graphql')), +}); + +firstApi.addNoneDataSource('FirstSourceDS', { + name: cdk.Lazy.string({ produce(): string { return 'FirstSourceDS'; } }), +}); + +const secondApi = new appsync.GraphqlApi(stack, 'SecondSourceAPI', { + name: 'SecondSourceAPI', + definition: appsync.Definition.fromFile(path.join(__dirname, 'appsync.merged-api-2.graphql')), +}); + +secondApi.addNoneDataSource('SecondSourceDS', { + name: cdk.Lazy.string({ produce(): string { return 'SecondSourceDS'; } }), +}); + +new appsync.GraphqlApi(stack, 'MergedAPI', { + name: 'MergedAPI', + definition: appsync.Definition.fromSourceApis({ + sourceApis: [ + { + sourceApi: firstApi, + mergeType: appsync.MergeType.MANUAL_MERGE, + }, + { + sourceApi: secondApi, + mergeType: appsync.MergeType.AUTO_MERGE, + }, + ], + }), +}); + +new IntegTest(app, 'api', { + testCases: [stack], +}); + +app.synth(); \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-merged-api.js.snapshot/apiDefaultTestDeployAssert018781F2.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-merged-api.js.snapshot/apiDefaultTestDeployAssert018781F2.assets.json index 640fdd8085ead..017cff874641f 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-merged-api.js.snapshot/apiDefaultTestDeployAssert018781F2.assets.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-merged-api.js.snapshot/apiDefaultTestDeployAssert018781F2.assets.json @@ -1,5 +1,5 @@ { - "version": "33.0.0", + "version": "34.0.0", "files": { "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { "source": { diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-merged-api.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-merged-api.js.snapshot/cdk.out index 560dae10d018f..2313ab5436501 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-merged-api.js.snapshot/cdk.out +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-merged-api.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"33.0.0"} \ No newline at end of file +{"version":"34.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-merged-api.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-merged-api.js.snapshot/integ.json index 49f9cf6d897f9..087c643f2d4b9 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-merged-api.js.snapshot/integ.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-merged-api.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "33.0.0", + "version": "34.0.0", "testCases": { "api/DefaultTest": { "stacks": [ diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-merged-api.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-merged-api.js.snapshot/manifest.json index 4f442a2e9917e..dde625a443dda 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-merged-api.js.snapshot/manifest.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-merged-api.js.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "33.0.0", + "version": "34.0.0", "artifacts": { "stack.assets": { "type": "cdk:asset-manifest", @@ -17,7 +17,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/227b4b7375fe3e7375a62383a2f862327ab90f469d554dcca064258ce7b2821b.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/c7f75afe322325fc4ced34825c95ad7229c5bd2157dba5f20c58aac8b6cd9c89.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-merged-api.js.snapshot/stack.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-merged-api.js.snapshot/stack.assets.json index 33b89654181f0..9e8f1988fb0c1 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-merged-api.js.snapshot/stack.assets.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-merged-api.js.snapshot/stack.assets.json @@ -1,7 +1,7 @@ { - "version": "33.0.0", + "version": "34.0.0", "files": { - "227b4b7375fe3e7375a62383a2f862327ab90f469d554dcca064258ce7b2821b": { + "c7f75afe322325fc4ced34825c95ad7229c5bd2157dba5f20c58aac8b6cd9c89": { "source": { "path": "stack.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "227b4b7375fe3e7375a62383a2f862327ab90f469d554dcca064258ce7b2821b.json", + "objectKey": "c7f75afe322325fc4ced34825c95ad7229c5bd2157dba5f20c58aac8b6cd9c89.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-merged-api.js.snapshot/stack.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-merged-api.js.snapshot/stack.template.json index f7461097d9297..960ddd398e029 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-merged-api.js.snapshot/stack.template.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-merged-api.js.snapshot/stack.template.json @@ -120,17 +120,55 @@ "Resource": [ { "Fn::GetAtt": [ - "FirstSourceAPIB0DE8D5A", - "Arn" + "MergedAPIFirstSourceAPIAssociationEC781BA9", + "SourceApiArn" ] }, { "Fn::GetAtt": [ - "SecondSourceAPIE903371D", - "Arn" + "MergedAPISecondSourceAPIAssociationBD1A08F4", + "SourceApiArn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "MergedAPIFirstSourceAPIAssociationEC781BA9", + "SourceApiArn" + ] + }, + "/*" + ] + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "MergedAPISecondSourceAPIAssociationBD1A08F4", + "SourceApiArn" + ] + }, + "/*" + ] ] } ] + }, + { + "Action": "appsync:StartSchemaMerge", + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "MergedAPISecondSourceAPIAssociationBD1A08F4", + "AssociationArn" + ] + } } ], "Version": "2012-10-17" diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-merged-api.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-merged-api.js.snapshot/tree.json index bda43203cb492..bd39d059830ee 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-merged-api.js.snapshot/tree.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-merged-api.js.snapshot/tree.json @@ -273,17 +273,55 @@ "Resource": [ { "Fn::GetAtt": [ - "FirstSourceAPIB0DE8D5A", - "Arn" + "MergedAPIFirstSourceAPIAssociationEC781BA9", + "SourceApiArn" ] }, { "Fn::GetAtt": [ - "SecondSourceAPIE903371D", - "Arn" + "MergedAPISecondSourceAPIAssociationBD1A08F4", + "SourceApiArn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "MergedAPIFirstSourceAPIAssociationEC781BA9", + "SourceApiArn" + ] + }, + "/*" + ] + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "MergedAPISecondSourceAPIAssociationBD1A08F4", + "SourceApiArn" + ] + }, + "/*" + ] ] } ] + }, + { + "Action": "appsync:StartSchemaMerge", + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "MergedAPISecondSourceAPIAssociationBD1A08F4", + "AssociationArn" + ] + } } ], "Version": "2012-10-17" @@ -459,7 +497,7 @@ "path": "api/DefaultTest/Default", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.2.69" + "version": "10.2.70" } }, "DeployAssert": { @@ -505,7 +543,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.2.69" + "version": "10.2.70" } } }, diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-merged-api.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-merged-api.ts index 06e3f5fbb9aa3..1e58561f91ca9 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-merged-api.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-merged-api.ts @@ -3,7 +3,12 @@ import * as cdk from 'aws-cdk-lib'; import { IntegTest } from '@aws-cdk/integ-tests-alpha'; import * as appsync from 'aws-cdk-lib/aws-appsync'; -const app = new cdk.App(); +const app = new cdk.App({ + postCliContext: { + [cdk.cx_api.APPSYNC_ENABLE_USE_ARN_IDENTIFIER_SOURCE_API_ASSOCIATION]: false, + }, +}); + const stack = new cdk.Stack(app, 'stack'); const firstApi = new appsync.GraphqlApi(stack, 'FirstSourceAPI', { diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-source-api-association.js.snapshot/Stack.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-source-api-association.js.snapshot/Stack.assets.json new file mode 100644 index 0000000000000..75acbfba5b1e9 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-source-api-association.js.snapshot/Stack.assets.json @@ -0,0 +1,19 @@ +{ + "version": "34.0.0", + "files": { + "0d28049698de9f166ab2500a6a65a1e012fb46df87be49853f2b631a3573c599": { + "source": { + "path": "Stack.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "0d28049698de9f166ab2500a6a65a1e012fb46df87be49853f2b631a3573c599.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-source-api-association.js.snapshot/Stack.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-source-api-association.js.snapshot/Stack.template.json new file mode 100644 index 0000000000000..7668f2ab79710 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-source-api-association.js.snapshot/Stack.template.json @@ -0,0 +1,357 @@ +{ + "Resources": { + "FirstSourceAPIB0DE8D5A": { + "Type": "AWS::AppSync::GraphQLApi", + "Properties": { + "AuthenticationType": "API_KEY", + "Name": "FirstSourceAPI" + } + }, + "FirstSourceAPISchemaF2FDB692": { + "Type": "AWS::AppSync::GraphQLSchema", + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "FirstSourceAPIB0DE8D5A", + "ApiId" + ] + }, + "Definition": "type firstTest {\n version: String!\n}\ntype Query {\n getFirstTests: [firstTest]!\n}\ntype Mutation {\n addFirstTest(version: String!): firstTest\n}\n" + } + }, + "FirstSourceAPIDefaultApiKey9D9AE06D": { + "Type": "AWS::AppSync::ApiKey", + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "FirstSourceAPIB0DE8D5A", + "ApiId" + ] + } + }, + "DependsOn": [ + "FirstSourceAPISchemaF2FDB692" + ] + }, + "FirstSourceAPIFirstSourceDS6AD299B7": { + "Type": "AWS::AppSync::DataSource", + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "FirstSourceAPIB0DE8D5A", + "ApiId" + ] + }, + "Name": "FirstSourceDS", + "Type": "NONE" + } + }, + "SecondSourceAPIE903371D": { + "Type": "AWS::AppSync::GraphQLApi", + "Properties": { + "AuthenticationType": "API_KEY", + "Name": "SecondSourceAPI" + } + }, + "SecondSourceAPISchema65B7401E": { + "Type": "AWS::AppSync::GraphQLSchema", + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SecondSourceAPIE903371D", + "ApiId" + ] + }, + "Definition": "type secondTest {\n version: String!\n}\ntype Query {\n getSecondTests: [secondTest]!\n}\ntype Mutation {\n addSecondTest(version: String!): secondTest\n}\n" + } + }, + "SecondSourceAPIDefaultApiKeyCE5A0A64": { + "Type": "AWS::AppSync::ApiKey", + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SecondSourceAPIE903371D", + "ApiId" + ] + } + }, + "DependsOn": [ + "SecondSourceAPISchema65B7401E" + ] + }, + "SecondSourceAPISecondSourceDSEA46EBA7": { + "Type": "AWS::AppSync::DataSource", + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SecondSourceAPIE903371D", + "ApiId" + ] + }, + "Name": "SecondSourceDS", + "Type": "NONE" + } + }, + "ThirdSourceAPIA5DA856C": { + "Type": "AWS::AppSync::GraphQLApi", + "Properties": { + "AuthenticationType": "API_KEY", + "Name": "ThirdSourceAPI" + } + }, + "ThirdSourceAPISchema5999A853": { + "Type": "AWS::AppSync::GraphQLSchema", + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "ThirdSourceAPIA5DA856C", + "ApiId" + ] + }, + "Definition": "type thirdTest {\n version: String!\n}\ntype Query {\n getThirdTests: [thirdTest]!\n}\ntype Mutation {\n addThirdTest(version: String!): thirdTest\n}\n" + } + }, + "ThirdSourceAPIDefaultApiKey3D5568A7": { + "Type": "AWS::AppSync::ApiKey", + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "ThirdSourceAPIA5DA856C", + "ApiId" + ] + } + }, + "DependsOn": [ + "ThirdSourceAPISchema5999A853" + ] + }, + "MergedApiExecutionRoleA4AA677D": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "appsync.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "MergedApiExecutionRoleDefaultPolicy249A5507": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": "appsync:SourceGraphQL", + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "SourceApiAssociation17B8F97C7", + "SourceApiArn" + ] + }, + { + "Fn::GetAtt": [ + "SourceApiAssociation254340D38", + "SourceApiArn" + ] + }, + { + "Fn::GetAtt": [ + "SourceApiAssociation3F6A7C1BA", + "SourceApiArn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "SourceApiAssociation17B8F97C7", + "SourceApiArn" + ] + }, + "/*" + ] + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "SourceApiAssociation254340D38", + "SourceApiArn" + ] + }, + "/*" + ] + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "SourceApiAssociation3F6A7C1BA", + "SourceApiArn" + ] + }, + "/*" + ] + ] + } + ] + }, + { + "Action": "appsync:StartSchemaMerge", + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "SourceApiAssociation254340D38", + "AssociationArn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "MergedApiExecutionRoleDefaultPolicy249A5507", + "Roles": [ + { + "Ref": "MergedApiExecutionRoleA4AA677D" + } + ] + } + }, + "MergedAPI08D3EAD1": { + "Type": "AWS::AppSync::GraphQLApi", + "Properties": { + "ApiType": "MERGED", + "AuthenticationType": "API_KEY", + "MergedApiExecutionRoleArn": { + "Fn::GetAtt": [ + "MergedApiExecutionRoleA4AA677D", + "Arn" + ] + }, + "Name": "MergedAPI" + } + }, + "MergedAPIDefaultApiKeyAF5EA13C": { + "Type": "AWS::AppSync::ApiKey", + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "MergedAPI08D3EAD1", + "ApiId" + ] + } + } + }, + "SourceApiAssociation17B8F97C7": { + "Type": "AWS::AppSync::SourceApiAssociation", + "Properties": { + "MergedApiIdentifier": { + "Fn::GetAtt": [ + "MergedAPI08D3EAD1", + "Arn" + ] + }, + "SourceApiAssociationConfig": { + "MergeType": "MANUAL_MERGE" + }, + "SourceApiIdentifier": { + "Fn::GetAtt": [ + "FirstSourceAPIB0DE8D5A", + "Arn" + ] + } + } + }, + "SourceApiAssociation254340D38": { + "Type": "AWS::AppSync::SourceApiAssociation", + "Properties": { + "MergedApiIdentifier": { + "Fn::GetAtt": [ + "MergedAPI08D3EAD1", + "Arn" + ] + }, + "SourceApiAssociationConfig": { + "MergeType": "AUTO_MERGE" + }, + "SourceApiIdentifier": { + "Fn::GetAtt": [ + "SecondSourceAPIE903371D", + "Arn" + ] + } + } + }, + "SourceApiAssociation3F6A7C1BA": { + "Type": "AWS::AppSync::SourceApiAssociation", + "Properties": { + "MergedApiIdentifier": { + "Fn::GetAtt": [ + "MergedAPI08D3EAD1", + "Arn" + ] + }, + "SourceApiAssociationConfig": { + "MergeType": "MANUAL_MERGE" + }, + "SourceApiIdentifier": { + "Fn::GetAtt": [ + "ThirdSourceAPIA5DA856C", + "Arn" + ] + } + } + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-source-api-association.js.snapshot/apiDefaultTestDeployAssert018781F2.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-source-api-association.js.snapshot/apiDefaultTestDeployAssert018781F2.assets.json new file mode 100644 index 0000000000000..017cff874641f --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-source-api-association.js.snapshot/apiDefaultTestDeployAssert018781F2.assets.json @@ -0,0 +1,19 @@ +{ + "version": "34.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "apiDefaultTestDeployAssert018781F2.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-source-api-association.js.snapshot/apiDefaultTestDeployAssert018781F2.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-source-api-association.js.snapshot/apiDefaultTestDeployAssert018781F2.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-source-api-association.js.snapshot/apiDefaultTestDeployAssert018781F2.template.json @@ -0,0 +1,36 @@ +{ + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-source-api-association.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-source-api-association.js.snapshot/cdk.out new file mode 100644 index 0000000000000..2313ab5436501 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-source-api-association.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"34.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-source-api-association.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-source-api-association.js.snapshot/integ.json new file mode 100644 index 0000000000000..5cae67ec7d1ba --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-source-api-association.js.snapshot/integ.json @@ -0,0 +1,12 @@ +{ + "version": "34.0.0", + "testCases": { + "api/DefaultTest": { + "stacks": [ + "Stack" + ], + "assertionStack": "api/DefaultTest/DeployAssert", + "assertionStackName": "apiDefaultTestDeployAssert018781F2" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-source-api-association.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-source-api-association.js.snapshot/manifest.json new file mode 100644 index 0000000000000..1412261dd7df0 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-source-api-association.js.snapshot/manifest.json @@ -0,0 +1,213 @@ +{ + "version": "34.0.0", + "artifacts": { + "Stack.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "Stack.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "Stack": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "Stack.template.json", + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/0d28049698de9f166ab2500a6a65a1e012fb46df87be49853f2b631a3573c599.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "Stack.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "Stack.assets" + ], + "metadata": { + "/Stack/FirstSourceAPI/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "FirstSourceAPIB0DE8D5A" + } + ], + "/Stack/FirstSourceAPI/Schema": [ + { + "type": "aws:cdk:logicalId", + "data": "FirstSourceAPISchemaF2FDB692" + } + ], + "/Stack/FirstSourceAPI/DefaultApiKey": [ + { + "type": "aws:cdk:logicalId", + "data": "FirstSourceAPIDefaultApiKey9D9AE06D" + } + ], + "/Stack/FirstSourceAPI/FirstSourceDS/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "FirstSourceAPIFirstSourceDS6AD299B7" + } + ], + "/Stack/SecondSourceAPI/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "SecondSourceAPIE903371D" + } + ], + "/Stack/SecondSourceAPI/Schema": [ + { + "type": "aws:cdk:logicalId", + "data": "SecondSourceAPISchema65B7401E" + } + ], + "/Stack/SecondSourceAPI/DefaultApiKey": [ + { + "type": "aws:cdk:logicalId", + "data": "SecondSourceAPIDefaultApiKeyCE5A0A64" + } + ], + "/Stack/SecondSourceAPI/SecondSourceDS/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "SecondSourceAPISecondSourceDSEA46EBA7" + } + ], + "/Stack/ThirdSourceAPI/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ThirdSourceAPIA5DA856C" + } + ], + "/Stack/ThirdSourceAPI/Schema": [ + { + "type": "aws:cdk:logicalId", + "data": "ThirdSourceAPISchema5999A853" + } + ], + "/Stack/ThirdSourceAPI/DefaultApiKey": [ + { + "type": "aws:cdk:logicalId", + "data": "ThirdSourceAPIDefaultApiKey3D5568A7" + } + ], + "/Stack/MergedApiExecutionRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MergedApiExecutionRoleA4AA677D" + } + ], + "/Stack/MergedApiExecutionRole/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MergedApiExecutionRoleDefaultPolicy249A5507" + } + ], + "/Stack/MergedAPI/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MergedAPI08D3EAD1" + } + ], + "/Stack/MergedAPI/DefaultApiKey": [ + { + "type": "aws:cdk:logicalId", + "data": "MergedAPIDefaultApiKeyAF5EA13C" + } + ], + "/Stack/SourceApiAssociation1/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "SourceApiAssociation17B8F97C7" + } + ], + "/Stack/SourceApiAssociation2/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "SourceApiAssociation254340D38" + } + ], + "/Stack/SourceApiAssociation3/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "SourceApiAssociation3F6A7C1BA" + } + ], + "/Stack/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/Stack/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "Stack" + }, + "apiDefaultTestDeployAssert018781F2.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "apiDefaultTestDeployAssert018781F2.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "apiDefaultTestDeployAssert018781F2": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "apiDefaultTestDeployAssert018781F2.template.json", + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "apiDefaultTestDeployAssert018781F2.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "apiDefaultTestDeployAssert018781F2.assets" + ], + "metadata": { + "/api/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/api/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "api/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-source-api-association.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-source-api-association.js.snapshot/tree.json new file mode 100644 index 0000000000000..3efea755f9277 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-source-api-association.js.snapshot/tree.json @@ -0,0 +1,713 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "Stack": { + "id": "Stack", + "path": "Stack", + "children": { + "FirstSourceAPI": { + "id": "FirstSourceAPI", + "path": "Stack/FirstSourceAPI", + "children": { + "Resource": { + "id": "Resource", + "path": "Stack/FirstSourceAPI/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::AppSync::GraphQLApi", + "aws:cdk:cloudformation:props": { + "authenticationType": "API_KEY", + "name": "FirstSourceAPI" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appsync.CfnGraphQLApi", + "version": "0.0.0" + } + }, + "Schema": { + "id": "Schema", + "path": "Stack/FirstSourceAPI/Schema", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::AppSync::GraphQLSchema", + "aws:cdk:cloudformation:props": { + "apiId": { + "Fn::GetAtt": [ + "FirstSourceAPIB0DE8D5A", + "ApiId" + ] + }, + "definition": "type firstTest {\n version: String!\n}\ntype Query {\n getFirstTests: [firstTest]!\n}\ntype Mutation {\n addFirstTest(version: String!): firstTest\n}\n" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appsync.CfnGraphQLSchema", + "version": "0.0.0" + } + }, + "DefaultApiKey": { + "id": "DefaultApiKey", + "path": "Stack/FirstSourceAPI/DefaultApiKey", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::AppSync::ApiKey", + "aws:cdk:cloudformation:props": { + "apiId": { + "Fn::GetAtt": [ + "FirstSourceAPIB0DE8D5A", + "ApiId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appsync.CfnApiKey", + "version": "0.0.0" + } + }, + "LogGroup": { + "id": "LogGroup", + "path": "Stack/FirstSourceAPI/LogGroup", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "FirstSourceDS": { + "id": "FirstSourceDS", + "path": "Stack/FirstSourceAPI/FirstSourceDS", + "children": { + "Resource": { + "id": "Resource", + "path": "Stack/FirstSourceAPI/FirstSourceDS/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::AppSync::DataSource", + "aws:cdk:cloudformation:props": { + "apiId": { + "Fn::GetAtt": [ + "FirstSourceAPIB0DE8D5A", + "ApiId" + ] + }, + "name": "FirstSourceDS", + "type": "NONE" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appsync.CfnDataSource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appsync.NoneDataSource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appsync.GraphqlApi", + "version": "0.0.0" + } + }, + "SecondSourceAPI": { + "id": "SecondSourceAPI", + "path": "Stack/SecondSourceAPI", + "children": { + "Resource": { + "id": "Resource", + "path": "Stack/SecondSourceAPI/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::AppSync::GraphQLApi", + "aws:cdk:cloudformation:props": { + "authenticationType": "API_KEY", + "name": "SecondSourceAPI" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appsync.CfnGraphQLApi", + "version": "0.0.0" + } + }, + "Schema": { + "id": "Schema", + "path": "Stack/SecondSourceAPI/Schema", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::AppSync::GraphQLSchema", + "aws:cdk:cloudformation:props": { + "apiId": { + "Fn::GetAtt": [ + "SecondSourceAPIE903371D", + "ApiId" + ] + }, + "definition": "type secondTest {\n version: String!\n}\ntype Query {\n getSecondTests: [secondTest]!\n}\ntype Mutation {\n addSecondTest(version: String!): secondTest\n}\n" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appsync.CfnGraphQLSchema", + "version": "0.0.0" + } + }, + "DefaultApiKey": { + "id": "DefaultApiKey", + "path": "Stack/SecondSourceAPI/DefaultApiKey", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::AppSync::ApiKey", + "aws:cdk:cloudformation:props": { + "apiId": { + "Fn::GetAtt": [ + "SecondSourceAPIE903371D", + "ApiId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appsync.CfnApiKey", + "version": "0.0.0" + } + }, + "LogGroup": { + "id": "LogGroup", + "path": "Stack/SecondSourceAPI/LogGroup", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "SecondSourceDS": { + "id": "SecondSourceDS", + "path": "Stack/SecondSourceAPI/SecondSourceDS", + "children": { + "Resource": { + "id": "Resource", + "path": "Stack/SecondSourceAPI/SecondSourceDS/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::AppSync::DataSource", + "aws:cdk:cloudformation:props": { + "apiId": { + "Fn::GetAtt": [ + "SecondSourceAPIE903371D", + "ApiId" + ] + }, + "name": "SecondSourceDS", + "type": "NONE" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appsync.CfnDataSource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appsync.NoneDataSource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appsync.GraphqlApi", + "version": "0.0.0" + } + }, + "ThirdSourceAPI": { + "id": "ThirdSourceAPI", + "path": "Stack/ThirdSourceAPI", + "children": { + "Resource": { + "id": "Resource", + "path": "Stack/ThirdSourceAPI/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::AppSync::GraphQLApi", + "aws:cdk:cloudformation:props": { + "authenticationType": "API_KEY", + "name": "ThirdSourceAPI" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appsync.CfnGraphQLApi", + "version": "0.0.0" + } + }, + "Schema": { + "id": "Schema", + "path": "Stack/ThirdSourceAPI/Schema", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::AppSync::GraphQLSchema", + "aws:cdk:cloudformation:props": { + "apiId": { + "Fn::GetAtt": [ + "ThirdSourceAPIA5DA856C", + "ApiId" + ] + }, + "definition": "type thirdTest {\n version: String!\n}\ntype Query {\n getThirdTests: [thirdTest]!\n}\ntype Mutation {\n addThirdTest(version: String!): thirdTest\n}\n" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appsync.CfnGraphQLSchema", + "version": "0.0.0" + } + }, + "DefaultApiKey": { + "id": "DefaultApiKey", + "path": "Stack/ThirdSourceAPI/DefaultApiKey", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::AppSync::ApiKey", + "aws:cdk:cloudformation:props": { + "apiId": { + "Fn::GetAtt": [ + "ThirdSourceAPIA5DA856C", + "ApiId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appsync.CfnApiKey", + "version": "0.0.0" + } + }, + "LogGroup": { + "id": "LogGroup", + "path": "Stack/ThirdSourceAPI/LogGroup", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appsync.GraphqlApi", + "version": "0.0.0" + } + }, + "MergedApiExecutionRole": { + "id": "MergedApiExecutionRole", + "path": "Stack/MergedApiExecutionRole", + "children": { + "ImportMergedApiExecutionRole": { + "id": "ImportMergedApiExecutionRole", + "path": "Stack/MergedApiExecutionRole/ImportMergedApiExecutionRole", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "Stack/MergedApiExecutionRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "appsync.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnRole", + "version": "0.0.0" + } + }, + "DefaultPolicy": { + "id": "DefaultPolicy", + "path": "Stack/MergedApiExecutionRole/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "Stack/MergedApiExecutionRole/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": "appsync:SourceGraphQL", + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "SourceApiAssociation17B8F97C7", + "SourceApiArn" + ] + }, + { + "Fn::GetAtt": [ + "SourceApiAssociation254340D38", + "SourceApiArn" + ] + }, + { + "Fn::GetAtt": [ + "SourceApiAssociation3F6A7C1BA", + "SourceApiArn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "SourceApiAssociation17B8F97C7", + "SourceApiArn" + ] + }, + "/*" + ] + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "SourceApiAssociation254340D38", + "SourceApiArn" + ] + }, + "/*" + ] + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "SourceApiAssociation3F6A7C1BA", + "SourceApiArn" + ] + }, + "/*" + ] + ] + } + ] + }, + { + "Action": "appsync:StartSchemaMerge", + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "SourceApiAssociation254340D38", + "AssociationArn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "policyName": "MergedApiExecutionRoleDefaultPolicy249A5507", + "roles": [ + { + "Ref": "MergedApiExecutionRoleA4AA677D" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnPolicy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Policy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Role", + "version": "0.0.0" + } + }, + "MergedAPI": { + "id": "MergedAPI", + "path": "Stack/MergedAPI", + "children": { + "Resource": { + "id": "Resource", + "path": "Stack/MergedAPI/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::AppSync::GraphQLApi", + "aws:cdk:cloudformation:props": { + "apiType": "MERGED", + "authenticationType": "API_KEY", + "mergedApiExecutionRoleArn": { + "Fn::GetAtt": [ + "MergedApiExecutionRoleA4AA677D", + "Arn" + ] + }, + "name": "MergedAPI" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appsync.CfnGraphQLApi", + "version": "0.0.0" + } + }, + "DefaultApiKey": { + "id": "DefaultApiKey", + "path": "Stack/MergedAPI/DefaultApiKey", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::AppSync::ApiKey", + "aws:cdk:cloudformation:props": { + "apiId": { + "Fn::GetAtt": [ + "MergedAPI08D3EAD1", + "ApiId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appsync.CfnApiKey", + "version": "0.0.0" + } + }, + "LogGroup": { + "id": "LogGroup", + "path": "Stack/MergedAPI/LogGroup", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appsync.GraphqlApi", + "version": "0.0.0" + } + }, + "SourceApiAssociation1": { + "id": "SourceApiAssociation1", + "path": "Stack/SourceApiAssociation1", + "children": { + "Resource": { + "id": "Resource", + "path": "Stack/SourceApiAssociation1/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::AppSync::SourceApiAssociation", + "aws:cdk:cloudformation:props": { + "mergedApiIdentifier": { + "Fn::GetAtt": [ + "MergedAPI08D3EAD1", + "Arn" + ] + }, + "sourceApiAssociationConfig": { + "mergeType": "MANUAL_MERGE" + }, + "sourceApiIdentifier": { + "Fn::GetAtt": [ + "FirstSourceAPIB0DE8D5A", + "Arn" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appsync.CfnSourceApiAssociation", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appsync.SourceApiAssociation", + "version": "0.0.0" + } + }, + "SourceApiAssociation2": { + "id": "SourceApiAssociation2", + "path": "Stack/SourceApiAssociation2", + "children": { + "Resource": { + "id": "Resource", + "path": "Stack/SourceApiAssociation2/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::AppSync::SourceApiAssociation", + "aws:cdk:cloudformation:props": { + "mergedApiIdentifier": { + "Fn::GetAtt": [ + "MergedAPI08D3EAD1", + "Arn" + ] + }, + "sourceApiAssociationConfig": { + "mergeType": "AUTO_MERGE" + }, + "sourceApiIdentifier": { + "Fn::GetAtt": [ + "SecondSourceAPIE903371D", + "Arn" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appsync.CfnSourceApiAssociation", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appsync.SourceApiAssociation", + "version": "0.0.0" + } + }, + "ImportedThirdApi": { + "id": "ImportedThirdApi", + "path": "Stack/ImportedThirdApi", + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appsync.GraphqlApiBase", + "version": "0.0.0" + } + }, + "SourceApiAssociation3": { + "id": "SourceApiAssociation3", + "path": "Stack/SourceApiAssociation3", + "children": { + "Resource": { + "id": "Resource", + "path": "Stack/SourceApiAssociation3/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::AppSync::SourceApiAssociation", + "aws:cdk:cloudformation:props": { + "mergedApiIdentifier": { + "Fn::GetAtt": [ + "MergedAPI08D3EAD1", + "Arn" + ] + }, + "sourceApiAssociationConfig": { + "mergeType": "MANUAL_MERGE" + }, + "sourceApiIdentifier": { + "Fn::GetAtt": [ + "ThirdSourceAPIA5DA856C", + "Arn" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appsync.CfnSourceApiAssociation", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appsync.SourceApiAssociation", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "Stack/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "Stack/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + }, + "api": { + "id": "api", + "path": "api", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "api/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "api/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.2.70" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "api/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "api/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "api/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTest", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.2.70" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.App", + "version": "0.0.0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-source-api-association.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-source-api-association.ts new file mode 100644 index 0000000000000..2ec33dc0a0171 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-source-api-association.ts @@ -0,0 +1,75 @@ +import * as path from 'path'; +import * as cdk from 'aws-cdk-lib'; +import { IntegTest } from '@aws-cdk/integ-tests-alpha'; +import * as appsync from 'aws-cdk-lib/aws-appsync'; +import * as iam from 'aws-cdk-lib/aws-iam'; + +const app = new cdk.App(); +const stack = new cdk.Stack(app, 'Stack'); + +const firstApi = new appsync.GraphqlApi(stack, 'FirstSourceAPI', { + name: 'FirstSourceAPI', + definition: appsync.Definition.fromFile(path.join(__dirname, 'appsync.merged-api-1.graphql')), +}); + +firstApi.addNoneDataSource('FirstSourceDS', { + name: cdk.Lazy.string({ produce(): string { return 'FirstSourceDS'; } }), +}); + +const secondApi = new appsync.GraphqlApi(stack, 'SecondSourceAPI', { + name: 'SecondSourceAPI', + definition: appsync.Definition.fromFile(path.join(__dirname, 'appsync.merged-api-2.graphql')), +}); + +secondApi.addNoneDataSource('SecondSourceDS', { + name: cdk.Lazy.string({ produce(): string { return 'SecondSourceDS'; } }), +}); + +const thirdApi = new appsync.GraphqlApi(stack, 'ThirdSourceAPI', { + name: 'ThirdSourceAPI', + definition: appsync.Definition.fromFile(path.join(__dirname, 'appsync.merged-api-3.graphql')), +}); + +const mergedApiExecutionRole = new iam.Role(stack, 'MergedApiExecutionRole', { + assumedBy: new iam.ServicePrincipal('appsync.amazonaws.com'), +}); + +const mergedApi = new appsync.GraphqlApi(stack, 'MergedAPI', { + name: 'MergedAPI', + definition: appsync.Definition.fromSourceApis({ + sourceApis: [], + mergedApiExecutionRole: mergedApiExecutionRole, + }), +}); + +new appsync.SourceApiAssociation(stack, 'SourceApiAssociation1', { + sourceApi: firstApi, + mergedApi: mergedApi, + mergeType: appsync.MergeType.MANUAL_MERGE, + mergedApiExecutionRole: mergedApiExecutionRole, +}); + +new appsync.SourceApiAssociation(stack, 'SourceApiAssociation2', { + sourceApi: secondApi, + mergedApi: mergedApi, + mergeType: appsync.MergeType.AUTO_MERGE, + mergedApiExecutionRole: mergedApiExecutionRole, +}); + +const iThirdApi = appsync.GraphqlApi.fromGraphqlApiAttributes(stack, 'ImportedThirdApi', { + graphqlApiId: thirdApi.apiId, + graphqlApiArn: thirdApi.arn, +}); + +new appsync.SourceApiAssociation(stack, 'SourceApiAssociation3', { + sourceApi: iThirdApi, + mergedApi: mergedApi, + mergeType: appsync.MergeType.MANUAL_MERGE, + mergedApiExecutionRole: mergedApiExecutionRole, +}); + +new IntegTest(app, 'api', { + testCases: [stack], +}); + +app.synth(); \ No newline at end of file diff --git a/packages/aws-cdk-lib/aws-appsync/README.md b/packages/aws-cdk-lib/aws-appsync/README.md index 5aa5c01f7b9aa..f672bf1429c60 100644 --- a/packages/aws-cdk-lib/aws-appsync/README.md +++ b/packages/aws-cdk-lib/aws-appsync/README.md @@ -391,7 +391,7 @@ secondApi.addNoneDataSource('SecondSourceDS', { }); // Merged API -new appsync.GraphqlApi(this, 'MergedAPI', { +const mergedApi = new appsync.GraphqlApi(this, 'MergedAPI', { name: 'MergedAPI', definition: appsync.Definition.fromSourceApis({ sourceApis: [ @@ -399,15 +399,35 @@ new appsync.GraphqlApi(this, 'MergedAPI', { sourceApi: firstApi, mergeType: appsync.MergeType.MANUAL_MERGE, }, - { - sourceApi: secondApi, - mergeType: appsync.MergeType.AUTO_MERGE, - }, ], }), }); ``` +## Merged APIs Across Different Stacks + +The SourceApiAssociation construct allows you to define a SourceApiAssociation to a Merged API in a different stack or account. This allows a source API owner the ability to associate it to an existing Merged API itself. + +```ts +const sourceApi = new appsync.GraphqlApi(this, 'FirstSourceAPI', { + name: 'FirstSourceAPI', + definition: appsync.Definition.fromFile(path.join(__dirname, 'appsync.merged-api-1.graphql')), +}); + +const importedMergedApi = appsync.GraphqlApi.fromGraphqlApiAttributes(this, 'ImportedMergedApi', { + graphqlApiId: 'MyApiId', + graphqlApiArn: 'MyApiArn', +}); + +const importedExecutionRole = iam.Role.fromRoleArn(this, 'ExecutionRole', 'arn:aws:iam::ACCOUNT:role/MyExistingRole'); +new appsync.SourceApiAssociation(this, 'SourceApiAssociation2', { + sourceApi: sourceApi, + mergedApi: importedMergedApi, + mergeType: appsync.MergeType.MANUAL_MERGE, + mergedApiExecutionRole: importedExecutionRole, +}); +``` + ## Custom Domain Names For many use cases you may want to associate a custom domain name with your diff --git a/packages/aws-cdk-lib/aws-appsync/lib/graphqlapi.ts b/packages/aws-cdk-lib/aws-appsync/lib/graphqlapi.ts index 62a9f3404b018..1fd051cfe4af3 100644 --- a/packages/aws-cdk-lib/aws-appsync/lib/graphqlapi.ts +++ b/packages/aws-cdk-lib/aws-appsync/lib/graphqlapi.ts @@ -2,12 +2,14 @@ import { Construct } from 'constructs'; import { CfnApiKey, CfnGraphQLApi, CfnGraphQLSchema, CfnDomainName, CfnDomainNameApiAssociation, CfnSourceApiAssociation } from './appsync.generated'; import { IGraphqlApi, GraphqlApiBase } from './graphqlapi-base'; import { ISchema, SchemaFile } from './schema'; +import { MergeType, addSourceApiAutoMergePermission, addSourceGraphQLPermission } from './source-api-association'; import { ICertificate } from '../../aws-certificatemanager'; import { IUserPool } from '../../aws-cognito'; -import { ManagedPolicy, Role, IRole, ServicePrincipal, Grant, IGrantable, PolicyStatement } from '../../aws-iam'; +import { ManagedPolicy, Role, IRole, ServicePrincipal, Grant, IGrantable } from '../../aws-iam'; import { IFunction } from '../../aws-lambda'; import { ILogGroup, LogGroup, LogRetention, RetentionDays } from '../../aws-logs'; -import { ArnFormat, CfnResource, Duration, Expiration, IResolvable, Stack } from '../../core'; +import { ArnFormat, CfnResource, Duration, Expiration, FeatureFlags, IResolvable, Stack } from '../../core'; +import * as cxapi from '../../cx-api'; /** * enum with all possible values for AppSync authorization type @@ -289,22 +291,7 @@ export interface DomainOptions { } /** - * Merge type used to associate the source API - */ -export enum MergeType { - /** - * Manual merge. The merge must be triggered manually when the source API has changed. - */ - MANUAL_MERGE = 'MANUAL_MERGE', - - /** - * Auto merge. The merge is triggered automatically when the source API has changed. - */ - AUTO_MERGE = 'AUTO_MERGE', -} - -/** - * Source API configuration for creating a AppSync Merged API + * Additional API configuration for creating a AppSync Merged API */ export interface SourceApiOptions { /** @@ -327,13 +314,19 @@ export interface SourceApi { /** * Source API that is associated with the merged API */ - readonly sourceApi: GraphqlApi; + readonly sourceApi: IGraphqlApi; + /** * Merging option used to associate the source API to the Merged API * * @default - Auto merge. The merge is triggered automatically when the source API has changed */ readonly mergeType?: MergeType; + + /** + * Description of the Source API asssociation. + */ + readonly description?: string; } /** @@ -603,7 +596,7 @@ export class GraphqlApi extends GraphqlApiBase { private api: CfnGraphQLApi; private apiKeyResource?: CfnApiKey; private domainNameResource?: CfnDomainName; - private mergedApiExecutionRole?: Role; + private mergedApiExecutionRole?: IRole; constructor(scope: Construct, id: string, props: GraphqlApiProps) { super(scope, id); @@ -702,14 +695,35 @@ export class GraphqlApi extends GraphqlApiBase { } private setupSourceApiAssociations() { - this.definition.sourceApiOptions?.sourceApis.forEach(sourceApiOption => { - new CfnSourceApiAssociation(this, `${sourceApiOption.sourceApi.node.id}Association`, { - sourceApiIdentifier: sourceApiOption.sourceApi.apiId, - mergedApiIdentifier: this.api.attrApiId, + this.definition.sourceApiOptions?.sourceApis.forEach(sourceApiConfig => { + const mergeType = sourceApiConfig.mergeType ?? MergeType.AUTO_MERGE; + let sourceApiIdentifier = sourceApiConfig.sourceApi.apiId; + let mergedApiIdentifier = this.apiId; + + // This is protected by a feature flag because if there is an existing source api association that used the api id, + // updating it to use ARN as identifier leads to a resource replacement. ARN is recommended going forward because it allows support + // for both same account and cross account use cases. + if (FeatureFlags.of(this).isEnabled(cxapi.APPSYNC_ENABLE_USE_ARN_IDENTIFIER_SOURCE_API_ASSOCIATION)) { + sourceApiIdentifier = sourceApiConfig.sourceApi.arn; + mergedApiIdentifier = this.arn; + } + + const association = new CfnSourceApiAssociation(this, `${sourceApiConfig.sourceApi.node.id}Association`, { + sourceApiIdentifier: sourceApiIdentifier, + mergedApiIdentifier: mergedApiIdentifier, sourceApiAssociationConfig: { - mergeType: sourceApiOption.mergeType ?? MergeType.AUTO_MERGE, + mergeType: mergeType, }, + description: sourceApiConfig.description, }); + + // Add permissions to merged api execution role + const executionRole = this.mergedApiExecutionRole as IRole; + addSourceGraphQLPermission(association, executionRole); + + if (mergeType === MergeType.AUTO_MERGE) { + addSourceApiAutoMergePermission(association, executionRole); + } }); } @@ -717,17 +731,9 @@ export class GraphqlApi extends GraphqlApiBase { if (sourceApiOptions.mergedApiExecutionRole) { this.mergedApiExecutionRole = sourceApiOptions.mergedApiExecutionRole; } else { - const sourceApiArns = sourceApiOptions.sourceApis?.map(sourceApiOption => { - return sourceApiOption.sourceApi.arn; - }); - this.mergedApiExecutionRole = new Role(this, 'MergedApiExecutionRole', { assumedBy: new ServicePrincipal('appsync.amazonaws.com'), }); - this.mergedApiExecutionRole.addToPolicy(new PolicyStatement({ - resources: sourceApiArns, - actions: ['appsync:SourceGraphQL'], - })); } } diff --git a/packages/aws-cdk-lib/aws-appsync/lib/index.ts b/packages/aws-cdk-lib/aws-appsync/lib/index.ts index 6237b39e1e0e7..4c14170b294d5 100644 --- a/packages/aws-cdk-lib/aws-appsync/lib/index.ts +++ b/packages/aws-cdk-lib/aws-appsync/lib/index.ts @@ -12,3 +12,4 @@ export * from './graphqlapi'; export * from './graphqlapi-base'; export * from './code'; export * from './runtime'; +export * from './source-api-association'; diff --git a/packages/aws-cdk-lib/aws-appsync/lib/source-api-association.ts b/packages/aws-cdk-lib/aws-appsync/lib/source-api-association.ts new file mode 100644 index 0000000000000..4d9ac599800e0 --- /dev/null +++ b/packages/aws-cdk-lib/aws-appsync/lib/source-api-association.ts @@ -0,0 +1,218 @@ +import { Construct } from 'constructs'; +import { CfnSourceApiAssociation } from './appsync.generated'; +import { IGraphqlApi } from './graphqlapi-base'; +import { Effect, IRole, PolicyStatement } from '../../aws-iam'; +import { Fn, IResource, Lazy, Resource } from '../../core'; + +/** + * Merge type used to associate the source API + */ +export enum MergeType { + /** + * Manual merge. The merge must be triggered manually when the source API has changed. + */ + MANUAL_MERGE = 'MANUAL_MERGE', + + /** + * Auto merge. The merge is triggered automatically when the source API has changed. + */ + AUTO_MERGE = 'AUTO_MERGE', +} + +/** + * Interface for AppSync Source Api Association + */ +export interface ISourceApiAssociation extends IResource { + + /** + * The association id. + */ + readonly associationId: string; + + /** + * The association arn. + */ + readonly associationArn: string; + + /** + * The source api in the association. + */ + readonly sourceApi: IGraphqlApi; + + /** + * The merged api in the association. + */ + readonly mergedApi: IGraphqlApi; +} + +/** + * The attributes for imported AppSync Source Api Association. + */ +export interface SourceApiAssociationAttributes { + /** + * The association arn. + */ + readonly associationArn: string; + + /** + * The source api in the association. + */ + readonly sourceApi: IGraphqlApi; + + /** + * The merged api in the association. + */ + readonly mergedApi: IGraphqlApi; +} + +/** +* Properties for SourceApiAssociation which associates an AppSync Source API with an AppSync Merged API +*/ +export interface SourceApiAssociationProps { + + /** + * The source api to associate. + */ + readonly sourceApi: IGraphqlApi; + + /** + * The merged api to associate. + */ + readonly mergedApi: IGraphqlApi; + + /** + * The merged api execution role for adding the access policy for the source api. + */ + readonly mergedApiExecutionRole: IRole; + + /** + * The merge type for the source + * + * @default - AUTO_MERGE + */ + readonly mergeType?: MergeType; + + /** + * The description of the source api association + * + * @default - None + */ + readonly description?: string; +} + +/** + * AppSync SourceApiAssociation which associates an AppSync source API to an AppSync Merged API. + * The initial creation of the SourceApiAssociation merges the source API into the Merged API schema. + */ +export class SourceApiAssociation extends Resource implements ISourceApiAssociation { + + /** + * Import Appsync Source Api Association from source API, merged api, and merge type. + */ + public static fromSourceApiAssociationAttributes(scope: Construct, id: string, attrs: SourceApiAssociationAttributes): ISourceApiAssociation { + class Import extends Resource { + public readonly associationId = Lazy.stringValue({ + produce: () => Fn.select(3, Fn.split('/', attrs.associationArn)), + }); + + public readonly associationArn = attrs.associationArn; + public readonly sourceApi = attrs.sourceApi; + public readonly mergedApi = attrs.mergedApi; + constructor(s: Construct, i: string) { + super(s, i); + } + } + return new Import(scope, id); + } + + /** + * The association id. + */ + readonly associationId: string; + + /** + * The association arn. + */ + readonly associationArn: string; + + /** + * The underlying CFN source api association resource. + */ + public readonly association: CfnSourceApiAssociation; + + /** + * The merged api in the association. + */ + public readonly mergedApi: IGraphqlApi; + + /** + * The source api in the association. + */ + public readonly sourceApi: IGraphqlApi; + + /** + * The merge type for the source api association. + */ + public readonly mergeType: MergeType; + + /** + * The merged api execution role for attaching the access policy. + */ + private readonly mergedApiExecutionRole?: IRole; + + constructor(scope: Construct, id: string, props: SourceApiAssociationProps) { + super(scope, id); + + this.mergeType = props.mergeType ?? MergeType.AUTO_MERGE; + this.mergedApiExecutionRole = props.mergedApiExecutionRole; + this.sourceApi = props.sourceApi; + this.mergedApi = props.mergedApi; + + this.association = new CfnSourceApiAssociation(this, 'Resource', { + sourceApiIdentifier: this.sourceApi.arn, + mergedApiIdentifier: this.mergedApi.arn, + sourceApiAssociationConfig: { + mergeType: this.mergeType, + + }, + description: props.description, + }); + + this.associationId = this.association.attrAssociationId; + this.associationArn = this.association.attrAssociationArn; + + // Add permissions to the merged api execution role. + addSourceGraphQLPermission(this.association, this.mergedApiExecutionRole); + if (this.mergeType === MergeType.AUTO_MERGE) { + addSourceApiAutoMergePermission(this.association, this.mergedApiExecutionRole); + } + } +} + +/** +* Adds an IAM permission to the Merged API execution role for GraphQL access on the source AppSync api. +* +* @param sourceApiAssociation The CfnSourceApiAssociation resource which to add a permission to access at runtime. +* @param mergedApiExecutionRole The merged api execution role on which to add the permission. +*/ +export function addSourceGraphQLPermission(sourceApiAssociation: CfnSourceApiAssociation, mergedApiExecutionRole: IRole) { + return mergedApiExecutionRole.addToPrincipalPolicy(new PolicyStatement({ + effect: Effect.ALLOW, + actions: ['appsync:SourceGraphQL'], + resources: [sourceApiAssociation.attrSourceApiArn, sourceApiAssociation.attrSourceApiArn.concat('/*')], + })); +} + +/** +* Adds an IAM permission to the Merged API execution role for automatically merging the source API metadata whenever +* the source API is updated. +* @param sourceApiAssociation The CfnSourceApiAssociation resource which to add permission to perform merge operations on. +* @param mergedApiExecutionRole The merged api execution role on which to add the permission. +*/ +export function addSourceApiAutoMergePermission(sourceApiAssociation: CfnSourceApiAssociation, mergedApiExecutionRole: IRole) { + return mergedApiExecutionRole.addToPrincipalPolicy(new PolicyStatement({ + effect: Effect.ALLOW, + actions: ['appsync:StartSchemaMerge'], + resources: [sourceApiAssociation.attrAssociationArn], + })); +} \ No newline at end of file diff --git a/packages/aws-cdk-lib/aws-appsync/test/appsync-merged-api.test.ts b/packages/aws-cdk-lib/aws-appsync/test/appsync-merged-api.test.ts index fcef54d40c0ae..57f3f7a2c8dc4 100644 --- a/packages/aws-cdk-lib/aws-appsync/test/appsync-merged-api.test.ts +++ b/packages/aws-cdk-lib/aws-appsync/test/appsync-merged-api.test.ts @@ -2,30 +2,55 @@ import * as path from 'path'; import { Template } from '../../assertions'; import * as iam from '../../aws-iam'; import * as cdk from '../../core'; +import * as cxapi from '../../cx-api'; import * as appsync from '../lib'; let stack: cdk.Stack; +let stackWithFlag: cdk.Stack; let api1: appsync.GraphqlApi; let api2: appsync.GraphqlApi; +let api3: appsync.GraphqlApi; +let api4: appsync.GraphqlApi; beforeEach(() => { stack = new cdk.Stack(); + stackWithFlag = new cdk.Stack(new cdk.App({ + context: { + [cxapi.APPSYNC_ENABLE_USE_ARN_IDENTIFIER_SOURCE_API_ASSOCIATION]: true, + }, + })); + api1 = new appsync.GraphqlApi(stack, 'api1', { authorizationConfig: {}, name: 'api', definition: appsync.Definition.fromFile(path.join(__dirname, 'appsync.test.graphql')), logConfig: {}, }); + api2 = new appsync.GraphqlApi(stack, 'api2', { authorizationConfig: {}, name: 'api', definition: appsync.Definition.fromFile(path.join(__dirname, 'appsync.test.graphql')), logConfig: {}, }); + + api3 = new appsync.GraphqlApi(stackWithFlag, 'api1', { + authorizationConfig: {}, + name: 'api', + definition: appsync.Definition.fromFile(path.join(__dirname, 'appsync.test.graphql')), + logConfig: {}, + }); + + api4 = new appsync.GraphqlApi(stackWithFlag, 'api2', { + authorizationConfig: {}, + name: 'api', + definition: appsync.Definition.fromFile(path.join(__dirname, 'appsync.test.graphql')), + logConfig: {}, + }); }); test('appsync supports merged API', () => { // WHEN - new appsync.GraphqlApi(stack, 'merged-api', { + const mergedApi = new appsync.GraphqlApi(stack, 'merged-api', { name: 'api', definition: appsync.Definition.fromSourceApis({ sourceApis: [ @@ -41,112 +66,30 @@ test('appsync supports merged API', () => { }), }); - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLApi', { - ApiType: 'MERGED', - MergedApiExecutionRoleArn: { - 'Fn::GetAtt': [ - 'mergedapiMergedApiExecutionRole2053D32E', - 'Arn', - ], - }, - }); - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::SourceApiAssociation', { - MergedApiIdentifier: { - 'Fn::GetAtt': [ - 'mergedapiCE4CAF34', - 'ApiId', - ], - }, - SourceApiAssociationConfig: { - MergeType: 'MANUAL_MERGE', - }, - SourceApiIdentifier: { - 'Fn::GetAtt': [ - 'api1A91238E2', - 'ApiId', - ], - }, - }); - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::SourceApiAssociation', { - MergedApiIdentifier: { - 'Fn::GetAtt': [ - 'mergedapiCE4CAF34', - 'ApiId', - ], - }, - SourceApiAssociationConfig: { - MergeType: 'AUTO_MERGE', - }, - SourceApiIdentifier: { - 'Fn::GetAtt': [ - 'api2C4850CEA', - 'ApiId', - ], - }, - }); - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::SourceApiAssociation', { - MergedApiIdentifier: { - 'Fn::GetAtt': [ - 'mergedapiCE4CAF34', - 'ApiId', - ], - }, - SourceApiAssociationConfig: { - MergeType: 'AUTO_MERGE', - }, - SourceApiIdentifier: { - 'Fn::GetAtt': [ - 'api2C4850CEA', - 'ApiId', - ], - }, - }); - Template.fromStack(stack).hasResourceProperties('AWS::IAM::Role', { - AssumeRolePolicyDocument: { - Statement: [ + validateSourceApiAssociations(stack, 'mergedapiMergedApiExecutionRole2053D32E', + 'mergedapiMergedApiExecutionRoleDefaultPolicy6F79FCAF', 'ApiId'); +}); + +test('appsync supports merged API - ARN identifier flag enabled', () => { + // WHEN + const mergedApi = new appsync.GraphqlApi(stackWithFlag, 'merged-api', { + name: 'api', + definition: appsync.Definition.fromSourceApis({ + sourceApis: [ { - Action: 'sts:AssumeRole', - Effect: 'Allow', - Principal: { - Service: 'appsync.amazonaws.com', - }, + sourceApi: api3, + mergeType: appsync.MergeType.MANUAL_MERGE, }, - ], - Version: '2012-10-17', - }, - }); - Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { - PolicyDocument: { - Statement: [ { - Action: 'appsync:SourceGraphQL', - Effect: 'Allow', - Resource: [ - { - 'Fn::GetAtt': [ - 'api1A91238E2', - 'Arn', - ], - }, - { - 'Fn::GetAtt': [ - 'api2C4850CEA', - 'Arn', - ], - }, - ], + sourceApi: api4, + mergeType: appsync.MergeType.AUTO_MERGE, }, ], - Version: '2012-10-17', - }, - PolicyName: 'mergedapiMergedApiExecutionRoleDefaultPolicy6F79FCAF', - Roles: [ - { - Ref: 'mergedapiMergedApiExecutionRole2053D32E', - }, - ], + }), }); + + validateSourceApiAssociations(stackWithFlag, 'mergedapiMergedApiExecutionRole2053D32E', + 'mergedapiMergedApiExecutionRoleDefaultPolicy6F79FCAF', 'Arn'); }); test('appsync supports merged API with default merge type', () => { @@ -205,15 +148,8 @@ test('appsync merged API with custom merged API execution role', () => { }); // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLApi', { - ApiType: 'MERGED', - MergedApiExecutionRoleArn: { - 'Fn::GetAtt': [ - 'CustomMergedApiExecutionRoleB795A9C4', - 'Arn', - ], - }, - }); + validateSourceApiAssociations(stack, 'CustomMergedApiExecutionRoleB795A9C4', + 'CustomMergedApiExecutionRoleDefaultPolicy012408A1', 'ApiId'); }); test('Merged API throws when accessing schema property', () => { @@ -238,4 +174,163 @@ test('Merged API throws when accessing schema property', () => { expect(() => { mergedApi.schema; }).toThrowError('Schema does not exist for AppSync merged APIs.'); -}); \ No newline at end of file +}); + +function validateSourceApiAssociations(stackToValidate: cdk.Stack, + expectedMergedApiExecutionRole: string, + expectedPolicyName: string, + expectedIdentifier: string) { + // THEN + Template.fromStack(stackToValidate).hasResourceProperties('AWS::AppSync::GraphQLApi', { + ApiType: 'MERGED', + MergedApiExecutionRoleArn: { + 'Fn::GetAtt': [ + expectedMergedApiExecutionRole, + 'Arn', + ], + }, + }); + + Template.fromStack(stackToValidate).hasResourceProperties('AWS::AppSync::SourceApiAssociation', { + MergedApiIdentifier: { + 'Fn::GetAtt': [ + 'mergedapiCE4CAF34', + expectedIdentifier, + ], + }, + SourceApiAssociationConfig: { + MergeType: 'MANUAL_MERGE', + }, + SourceApiIdentifier: { + 'Fn::GetAtt': [ + 'api1A91238E2', + expectedIdentifier, + ], + }, + }); + Template.fromStack(stackToValidate).hasResourceProperties('AWS::AppSync::SourceApiAssociation', { + MergedApiIdentifier: { + 'Fn::GetAtt': [ + 'mergedapiCE4CAF34', + expectedIdentifier, + ], + }, + SourceApiAssociationConfig: { + MergeType: 'AUTO_MERGE', + }, + SourceApiIdentifier: { + 'Fn::GetAtt': [ + 'api2C4850CEA', + expectedIdentifier, + ], + }, + }); + Template.fromStack(stackToValidate).hasResourceProperties('AWS::AppSync::SourceApiAssociation', { + MergedApiIdentifier: { + 'Fn::GetAtt': [ + 'mergedapiCE4CAF34', + expectedIdentifier, + ], + }, + SourceApiAssociationConfig: { + MergeType: 'AUTO_MERGE', + }, + SourceApiIdentifier: { + 'Fn::GetAtt': [ + 'api2C4850CEA', + expectedIdentifier, + ], + }, + }); + + Template.fromStack(stackToValidate).hasResourceProperties('AWS::IAM::Role', { + AssumeRolePolicyDocument: { + Statement: [ + { + Action: 'sts:AssumeRole', + Effect: 'Allow', + Principal: { + Service: 'appsync.amazonaws.com', + }, + }, + ], + Version: '2012-10-17', + }, + }); + + Template.fromStack(stackToValidate).hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: [ + { + Action: 'appsync:SourceGraphQL', + Effect: 'Allow', + Resource: [ + { + 'Fn::GetAtt': [ + 'mergedapiapi1Association63F38E0D', + 'SourceApiArn', + ], + }, + { + 'Fn::Join': [ + '', + [ + { + 'Fn::GetAtt': [ + 'mergedapiapi1Association63F38E0D', + 'SourceApiArn', + ], + }, + '/*', + ], + ], + }, + ], + }, + { + Action: 'appsync:SourceGraphQL', + Effect: 'Allow', + Resource: [ + { + 'Fn::GetAtt': [ + 'mergedapiapi2AssociationC4E5E15E', + 'SourceApiArn', + ], + }, + { + 'Fn::Join': [ + '', + [ + { + 'Fn::GetAtt': [ + 'mergedapiapi2AssociationC4E5E15E', + 'SourceApiArn', + ], + }, + '/*', + ], + ], + }, + ], + }, + { + Action: 'appsync:StartSchemaMerge', + Effect: 'Allow', + Resource: { + 'Fn::GetAtt': [ + 'mergedapiapi2AssociationC4E5E15E', + 'AssociationArn', + ], + }, + }, + ], + Version: '2012-10-17', + }, + PolicyName: expectedPolicyName, + Roles: [ + { + Ref: expectedMergedApiExecutionRole, + }, + ], + }); +} \ No newline at end of file diff --git a/packages/aws-cdk-lib/aws-appsync/test/appsync-source-api-association.test.ts b/packages/aws-cdk-lib/aws-appsync/test/appsync-source-api-association.test.ts new file mode 100644 index 0000000000000..9636a26d2b5f7 --- /dev/null +++ b/packages/aws-cdk-lib/aws-appsync/test/appsync-source-api-association.test.ts @@ -0,0 +1,217 @@ +import * as path from 'path'; +import { Template } from '../../assertions'; +import * as iam from '../../aws-iam'; +import * as cdk from '../../core'; +import * as appsync from '../lib'; + +let stack: cdk.Stack; +let api1: appsync.IGraphqlApi; +let api2: appsync.IGraphqlApi; +let mergedApiExecutionRole: iam.Role; +let mergedApi: appsync.IGraphqlApi; +beforeEach(() => { + stack = new cdk.Stack(); + + api1 = new appsync.GraphqlApi(stack, 'api1', { + authorizationConfig: {}, + name: 'api', + definition: appsync.Definition.fromFile(path.join(__dirname, 'appsync.test.graphql')), + logConfig: {}, + }); + + api2 = new appsync.GraphqlApi(stack, 'api2', { + authorizationConfig: {}, + name: 'api', + definition: appsync.Definition.fromFile(path.join(__dirname, 'appsync.test.graphql')), + logConfig: {}, + }); + + mergedApiExecutionRole = new iam.Role(stack, 'MergedApiExecutionRole', { + assumedBy: new iam.ServicePrincipal('appsync.amazonaws.com'), + }); + + mergedApi = new appsync.GraphqlApi(stack, 'merged-api', { + name: 'api', + definition: appsync.Definition.fromSourceApis({ + sourceApis: [], + mergedApiExecutionRole: mergedApiExecutionRole, + }), + }); +}); + +test('Associate with source apis', () => { + const sourceApiAssociation1 = new appsync.SourceApiAssociation(stack, 'SourceApi1', { + sourceApi: api1, + mergedApi: mergedApi, + mergeType: appsync.MergeType.MANUAL_MERGE, + mergedApiExecutionRole: mergedApiExecutionRole, + }); + + new appsync.SourceApiAssociation(stack, 'SourceApi2', { + sourceApi: api2, + mergedApi: mergedApi, + mergeType: appsync.MergeType.AUTO_MERGE, + mergedApiExecutionRole: mergedApiExecutionRole, + }); + + // THEN + verifySourceAssociations(stack, 'Arn'); + verifyMergedApiExecutionRole(stack); +}); + +function verifySourceAssociations(stackToValidate: cdk.Stack, expectedIdentifier: string) { + // THEN + Template.fromStack(stackToValidate).hasResourceProperties('AWS::AppSync::GraphQLApi', { + ApiType: 'MERGED', + MergedApiExecutionRoleArn: { + 'Fn::GetAtt': [ + 'MergedApiExecutionRoleA4AA677D', + 'Arn', + ], + }, + }); + + Template.fromStack(stackToValidate).hasResourceProperties('AWS::AppSync::SourceApiAssociation', { + MergedApiIdentifier: { + 'Fn::GetAtt': [ + 'mergedapiCE4CAF34', + expectedIdentifier, + ], + }, + SourceApiAssociationConfig: { + MergeType: 'MANUAL_MERGE', + }, + SourceApiIdentifier: { + 'Fn::GetAtt': [ + 'api1A91238E2', + expectedIdentifier, + ], + }, + }); + Template.fromStack(stackToValidate).hasResourceProperties('AWS::AppSync::SourceApiAssociation', { + MergedApiIdentifier: { + 'Fn::GetAtt': [ + 'mergedapiCE4CAF34', + expectedIdentifier, + ], + }, + SourceApiAssociationConfig: { + MergeType: 'AUTO_MERGE', + }, + SourceApiIdentifier: { + 'Fn::GetAtt': [ + 'api2C4850CEA', + expectedIdentifier, + ], + }, + }); + + Template.fromStack(stackToValidate).hasResourceProperties('AWS::IAM::Role', { + AssumeRolePolicyDocument: { + Statement: [ + { + Action: 'sts:AssumeRole', + Effect: 'Allow', + Principal: { + Service: 'appsync.amazonaws.com', + }, + }, + ], + Version: '2012-10-17', + }, + }); +} + +function verifyMergedApiExecutionRole(stackToValidate: cdk.Stack) { + Template.fromStack(stackToValidate).hasResourceProperties('AWS::IAM::Role', { + AssumeRolePolicyDocument: { + Statement: [ + { + Action: 'sts:AssumeRole', + Effect: 'Allow', + Principal: { + Service: 'appsync.amazonaws.com', + }, + }, + ], + Version: '2012-10-17', + }, + }); + + Template.fromStack(stackToValidate).hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: [ + { + Action: 'appsync:SourceGraphQL', + Effect: 'Allow', + Resource: [ + { + 'Fn::GetAtt': [ + 'SourceApi19C17DBB7', + 'SourceApiArn', + ], + }, + { + 'Fn::Join': [ + '', + [ + { + 'Fn::GetAtt': [ + 'SourceApi19C17DBB7', + 'SourceApiArn', + ], + }, + '/*', + ], + ], + }, + ], + }, + { + Action: 'appsync:SourceGraphQL', + Effect: 'Allow', + Resource: [ + { + 'Fn::GetAtt': [ + 'SourceApi26424431C', + 'SourceApiArn', + ], + }, + { + 'Fn::Join': [ + '', + [ + { + 'Fn::GetAtt': [ + 'SourceApi26424431C', + 'SourceApiArn', + ], + }, + '/*', + ], + ], + }, + ], + }, + { + Action: 'appsync:StartSchemaMerge', + Effect: 'Allow', + Resource: { + 'Fn::GetAtt': [ + 'SourceApi26424431C', + 'AssociationArn', + ], + }, + }, + ], + Version: '2012-10-17', + }, + PolicyName: 'MergedApiExecutionRoleDefaultPolicy249A5507', + Roles: [ + { + Ref: 'MergedApiExecutionRoleA4AA677D', + }, + ], + }); +} + diff --git a/packages/aws-cdk-lib/cx-api/FEATURE_FLAGS.md b/packages/aws-cdk-lib/cx-api/FEATURE_FLAGS.md index d32a46743e268..db9c02526aa34 100644 --- a/packages/aws-cdk-lib/cx-api/FEATURE_FLAGS.md +++ b/packages/aws-cdk-lib/cx-api/FEATURE_FLAGS.md @@ -59,6 +59,7 @@ Flags come in three types: | [@aws-cdk/aws-efs:denyAnonymousAccess](#aws-cdkaws-efsdenyanonymousaccess) | EFS denies anonymous clients accesses | 2.93.0 | (default) | | [@aws-cdk/aws-efs:mountTargetOrderInsensitiveLogicalId](#aws-cdkaws-efsmounttargetorderinsensitivelogicalid) | When enabled, mount targets will have a stable logicalId that is linked to the associated subnet. | 2.93.0 | (fix) | | [@aws-cdk/aws-lambda-nodejs:useLatestRuntimeVersion](#aws-cdkaws-lambda-nodejsuselatestruntimeversion) | Enables aws-lambda-nodejs.Function to use the latest available NodeJs runtime as the default | 2.93.0 | (default) | +| [@aws-cdk/aws-appsync:useArnForSourceApiAssociationIdentifier](#aws-cdkaws-appsyncusearnforsourceapiassociationidentifier) | When enabled, will always use the arn for identifiers for CfnSourceApiAssociation in the GraphqlApi construct rather than id. | V2NEXT | (fix) | @@ -108,7 +109,8 @@ The following json shows the current recommended set of flags, as `cdk init` wou "@aws-cdk/aws-efs:denyAnonymousAccess": true, "@aws-cdk/aws-opensearchservice:enableOpensearchMultiAzWithStandby": true, "@aws-cdk/aws-lambda-nodejs:useLatestRuntimeVersion": true, - "@aws-cdk/aws-efs:mountTargetOrderInsensitiveLogicalId": true + "@aws-cdk/aws-efs:mountTargetOrderInsensitiveLogicalId": true, + "@aws-cdk/aws-appsync:useArnForSourceApiAssociationIdentifier": true } } ``` @@ -1113,4 +1115,19 @@ shipped as part of the runtime environment. **Compatibility with old behavior:** Pass `runtime: lambda.Runtime.NODEJS_16_X` to `Function` construct to restore the previous behavior. +### @aws-cdk/aws-appsync:useArnForSourceApiAssociationIdentifier + +*When enabled, will always use the arn for identifiers for CfnSourceApiAssociation in the GraphqlApi construct rather than id.* (fix) + +When this feature flag is enabled, we use the IGraphqlApi ARN rather than ID when creating or updating CfnSourceApiAssociation in +the GraphqlApi construct. Using the ARN allows the association to support an association with a source api or merged api in another account. +Note that for existing source api associations created with this flag disabled, enabling the flag will lead to a resource replacement. + + +| Since | Default | Recommended | +| ----- | ----- | ----- | +| (not in v1) | | | +| V2NEXT | `false` | `true` | + + diff --git a/packages/aws-cdk-lib/cx-api/lib/features.ts b/packages/aws-cdk-lib/cx-api/lib/features.ts index 191a49236a5f8..e75f8a81f1b3c 100644 --- a/packages/aws-cdk-lib/cx-api/lib/features.ts +++ b/packages/aws-cdk-lib/cx-api/lib/features.ts @@ -93,6 +93,7 @@ export const EFS_MOUNTTARGET_ORDERINSENSITIVE_LOGICAL_ID = '@aws-cdk/aws-efs:mou export const AUTOSCALING_GENERATE_LAUNCH_TEMPLATE = '@aws-cdk/aws-autoscaling:generateLaunchTemplateInsteadOfLaunchConfig'; export const ENABLE_OPENSEARCH_MULTIAZ_WITH_STANDBY = '@aws-cdk/aws-opensearchservice:enableOpensearchMultiAzWithStandby'; export const LAMBDA_NODEJS_USE_LATEST_RUNTIME = '@aws-cdk/aws-lambda-nodejs:useLatestRuntimeVersion'; +export const APPSYNC_ENABLE_USE_ARN_IDENTIFIER_SOURCE_API_ASSOCIATION = '@aws-cdk/aws-appsync:useArnForSourceApiAssociationIdentifier'; export const FLAGS: Record = { ////////////////////////////////////////////////////////////////////// @@ -908,6 +909,18 @@ export const FLAGS: Record = { recommendedValue: true, }, + ////////////////////////////////////////////////////////////////////// + [APPSYNC_ENABLE_USE_ARN_IDENTIFIER_SOURCE_API_ASSOCIATION]: { + type: FlagType.BugFix, + summary: 'When enabled, will always use the arn for identifiers for CfnSourceApiAssociation in the GraphqlApi construct rather than id.', + detailsMd: ` + When this feature flag is enabled, we use the IGraphqlApi ARN rather than ID when creating or updating CfnSourceApiAssociation in + the GraphqlApi construct. Using the ARN allows the association to support an association with a source api or merged api in another account. + Note that for existing source api associations created with this flag disabled, enabling the flag will lead to a resource replacement. + `, + introducedIn: { v2: 'V2NEXT' }, + recommendedValue: true, + }, }; const CURRENT_MV = 'v2';