diff --git a/doc/custom-domain.md b/doc/custom-domain.md index c376b8a9..2b0e863a 100644 --- a/doc/custom-domain.md +++ b/doc/custom-domain.md @@ -51,6 +51,8 @@ For example, if you want to use blue/green deployments, you might need to associ For more information about managing domains with the CLI, see the [Commands](commands.md#domain) section. +⚠️ The CLI commands resolve values themselves rather than through CloudFormation, so `certificateArn` must be a literal ARN string when using them. CloudFormation intrinsic functions (e.g. `Fn::ImportValue`) are only resolved when the domain is managed by CloudFormation (`useCloudFormation: true`). + ## Ejecting from CloudFormation If you started to manage your domain through CloudFormation and want to eject from it, follow the following steps: diff --git a/src/__tests__/commands.test.ts b/src/__tests__/commands.test.ts index 099876dd..560da647 100644 --- a/src/__tests__/commands.test.ts +++ b/src/__tests__/commands.test.ts @@ -93,6 +93,32 @@ describe('create domain', () => { `); }); + it('should reject an intrinsic-function certificateArn (CLI cannot resolve it)', async () => { + mockSend.mockResolvedValue({}); + + await expect( + runServerless({ + fixture: 'appsync', + command: 'appsync domain create', + configExt: { + appSync: { + domain: { + useCloudFormation: false, + certificateArn: { 'Fn::ImportValue': 'exportedCertArn' }, + }, + }, + }, + }), + ).rejects.toThrow( + /the `appsync domain` CLI commands require a plain ARN string/, + ); + + const createCall = mockSend.mock.calls.find( + ([cmd]) => cmd instanceof CreateDomainNameCommand, + ); + expect(createCall).toBeUndefined(); + }); + it('should create a domain and find a matching certificate, exact match', async () => { mockSend.mockImplementation((cmd) => { if (cmd instanceof ListCertificatesCommand) { diff --git a/src/index.ts b/src/index.ts index f315d889..51aea2ea 100644 --- a/src/index.ts +++ b/src/index.ts @@ -715,6 +715,14 @@ class ServerlessAppsyncPlugin { ); } + if (typeof certificateArn !== 'string') { + throw new this.serverless.classes.Error( + `Invalid \`certificateArn\`: the \`appsync domain\` CLI commands require a plain ARN string. ` + + `CloudFormation intrinsic functions (e.g. Fn::ImportValue) can only be resolved by CloudFormation, not by the CLI. ` + + `Either pass a literal ARN, or manage the domain through CloudFormation (the default, \`domain.useCloudFormation: true\`), where the intrinsic function will be resolved.`, + ); + } + await this.clientFactory.getAppSyncClient().send( new CreateDomainNameCommand({ domainName: domain.name, diff --git a/src/types/common.ts b/src/types/common.ts index b5abedbf..58da4e10 100644 --- a/src/types/common.ts +++ b/src/types/common.ts @@ -119,7 +119,7 @@ export type DomainConfig = { useCloudFormation?: boolean; retain?: boolean; name: string; - certificateArn?: string; + certificateArn?: string | IntrinsicFunction; hostedZoneId?: string; hostedZoneName?: string; route53?: boolean;