Skip to content
This repository was archived by the owner on Dec 9, 2024. It is now read-only.

Commit b552a39

Browse files
committed
added appsync & distro functions
1 parent b89601d commit b552a39

File tree

8 files changed

+316
-8
lines changed

8 files changed

+316
-8
lines changed

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@serverless/aws-sdk",
3-
"version": "2.0.6",
3+
"version": "3.0.0",
44
"description": "Powerful Serverless Utilities",
55
"main": "src/index.js",
66
"author": "Serverless, Inc.",
@@ -11,6 +11,7 @@
1111
"dependencies": {
1212
"adm-zip": "^0.4.14",
1313
"aws-sdk": "^2.614.0",
14+
"merge-deep": "^3.0.2",
1415
"ramda": "^0.26.1"
1516
},
1617
"scripts": {

src/deployAppSyncApi.js

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,45 @@
1+
const setAuthConfig = (aws, params, createUpdateParams) => {
2+
if (!params.auth || params.auth === 'apiKey') {
3+
// api key auth
4+
createUpdateParams.authenticationType = 'API_KEY'
5+
} else if (params.auth === 'awsIam') {
6+
// iam auth
7+
createUpdateParams.authenticationType = 'AWS_IAM'
8+
} else if (params.auth.userPoolId) {
9+
createUpdateParams.authenticationType = 'AMAZON_COGNITO_USER_POOLS'
10+
createUpdateParams.userPoolConfig = {
11+
// cognito auth config
12+
userPoolId: params.auth.userPoolId,
13+
defaultAction: params.auth.defaultAction || 'ALLOW',
14+
awsRegion: params.auth.region || aws.config.region,
15+
appIdClientRegex: params.auth.appIdClientRegex
16+
}
17+
} else if (params.auth.issuer) {
18+
// open id auth config
19+
createUpdateParams.openIDConnectConfig = {
20+
// cognito auth config
21+
issuer: params.auth.issuer,
22+
authTTL: params.auth.authTTL,
23+
clientId: params.auth.clientId,
24+
iatTTL: params.auth.iatTTL
25+
}
26+
} else {
27+
// set api key for any other case
28+
createUpdateParams.authenticationType = 'API_KEY'
29+
}
30+
31+
return createUpdateParams
32+
}
33+
134
const createAppSyncApi = async (aws, params) => {
235
const appSync = new aws.AppSync()
336

4-
const createGraphqlApiParams = {
5-
name: params.apiName,
6-
authenticationType: params.authenticationType || 'API_KEY'
37+
let createGraphqlApiParams = {
38+
name: params.apiName
739
}
840

41+
createGraphqlApiParams = setAuthConfig(aws, params, createGraphqlApiParams)
42+
943
const { graphqlApi } = await appSync.createGraphqlApi(createGraphqlApiParams).promise()
1044

1145
return graphqlApi
@@ -14,12 +48,13 @@ const createAppSyncApi = async (aws, params) => {
1448
const updateAppSyncApi = async (aws, params) => {
1549
const appSync = new aws.AppSync()
1650

17-
const updateGraphqlApiparams = {
51+
let updateGraphqlApiparams = {
1852
apiId: params.apiId,
19-
name: params.apiName,
20-
authenticationType: params.authenticationType || 'API_KEY'
53+
name: params.apiName
2154
}
2255

56+
updateGraphqlApiparams = setAuthConfig(aws, params, updateGraphqlApiparams)
57+
2358
const { graphqlApi } = await appSync.updateGraphqlApi(updateGraphqlApiparams).promise()
2459

2560
return graphqlApi

src/deployAppSyncDistribution.js

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
module.exports = async (aws, params) => {
2+
const { domain, apiId, apiUrl } = params
3+
4+
if (!apiId) {
5+
throw new Error(`Missing "apiId" param.`)
6+
}
7+
8+
if (!apiUrl) {
9+
throw new Error(`Missing "apiUrl" param.`)
10+
}
11+
12+
const deployDistributionParams = {
13+
domain,
14+
Origins: {
15+
Quantity: 1,
16+
Items: [
17+
{
18+
Id: apiId, // required
19+
DomainName: apiUrl.replace('https://', '').replace('/graphql', ''), // required
20+
OriginPath: '', // required
21+
CustomOriginConfig: {
22+
HTTPPort: 80,
23+
HTTPSPort: 443,
24+
OriginKeepaliveTimeout: 5,
25+
OriginProtocolPolicy: 'https-only',
26+
OriginReadTimeout: 30,
27+
OriginSslProtocols: {
28+
Items: ['SSLv3', 'TLSv1', 'TLSv1.1', 'TLSv1.2'],
29+
Quantity: 4
30+
}
31+
}
32+
}
33+
]
34+
},
35+
DefaultCacheBehavior: {
36+
AllowedMethods: {
37+
Quantity: 7,
38+
Items: ['HEAD', 'GET', 'POST', 'PATCH', 'PUT', 'DELETE', 'OPTIONS']
39+
},
40+
TrustedSigners: {
41+
// required
42+
Enabled: false,
43+
Quantity: 0,
44+
Items: []
45+
},
46+
ViewerProtocolPolicy: 'redirect-to-https', // required
47+
MinTTL: 0, // required
48+
DefaultTTL: 86400,
49+
MaxTTL: 31536000,
50+
SmoothStreaming: false,
51+
TargetOriginId: apiId, // required
52+
ForwardedValues: {
53+
QueryString: false, // required
54+
Cookies: {
55+
// required
56+
Forward: 'none'
57+
}
58+
}
59+
}
60+
}
61+
62+
if (params.distributionId) {
63+
deployDistributionParams.distributionId = params.distributionId
64+
}
65+
66+
const distribution = await aws.utils.deployDistribution(deployDistributionParams)
67+
68+
return distribution
69+
}

src/deployDistribution.js

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
const { mergeDeep } = require('./utils')
2+
3+
const createDistribution = async (aws, params = {}) => {
4+
const cf = new aws.CloudFront()
5+
6+
delete params.distributionId
7+
8+
params.Enabled = params.Enabled || true
9+
params.Comment = params.Comment || ''
10+
params.CallerReference = params.CallerReference || String(Date.now())
11+
12+
const createDistributionParams = {
13+
DistributionConfig: { ...params }
14+
}
15+
16+
if (params.certificateStatus === 'ISSUED') {
17+
createDistributionParams.DistributionConfig.Aliases = {
18+
Quantity: 1,
19+
Items: [params.domain]
20+
}
21+
createDistributionParams.DistributionConfig.ViewerCertificate = {
22+
ACMCertificateArn: params.certificateArn,
23+
SSLSupportMethod: 'sni-only',
24+
MinimumProtocolVersion: 'TLSv1.1_2016',
25+
Certificate: params.certificateArn,
26+
CertificateSource: 'acm'
27+
}
28+
}
29+
30+
delete createDistributionParams.DistributionConfig.domain
31+
delete createDistributionParams.DistributionConfig.certificateArn
32+
delete createDistributionParams.DistributionConfig.certificateStatus
33+
delete createDistributionParams.DistributionConfig.domainHostedZoneId
34+
35+
const res = await cf.createDistribution(createDistributionParams).promise()
36+
37+
return {
38+
distributionId: res.Distribution.Id,
39+
distributionArn: res.Distribution.ARN,
40+
distributionUrl: res.Distribution.DomainName
41+
}
42+
}
43+
44+
const updateDistribution = async (aws, params = {}) => {
45+
const cf = new aws.CloudFront()
46+
try {
47+
const updateDistributionParams = await cf
48+
.getDistributionConfig({ Id: params.distributionId })
49+
.promise()
50+
51+
// 2. then add this property
52+
updateDistributionParams.IfMatch = updateDistributionParams.ETag
53+
54+
// 3. then delete this property
55+
delete updateDistributionParams.ETag
56+
57+
// 4. then set this property
58+
updateDistributionParams.Id = params.distributionId
59+
60+
// 5. then make our changes
61+
updateDistributionParams.DistributionConfig.Enabled = params.Enabled === false ? false : true
62+
63+
if (params.certificateStatus === 'ISSUED') {
64+
updateDistributionParams.DistributionConfig.Aliases = {
65+
Quantity: 1,
66+
Items: [params.domain]
67+
}
68+
updateDistributionParams.DistributionConfig.ViewerCertificate = {
69+
ACMCertificateArn: params.certificateArn,
70+
SSLSupportMethod: 'sni-only',
71+
MinimumProtocolVersion: 'TLSv1.1_2016',
72+
Certificate: params.certificateArn,
73+
CertificateSource: 'acm'
74+
}
75+
}
76+
77+
// these cannot exist in an update operation
78+
delete params.Origins
79+
delete params.CallerReference
80+
81+
// todo this might not scale
82+
updateDistributionParams.DistributionConfig = mergeDeep(
83+
updateDistributionParams.DistributionConfig,
84+
params
85+
)
86+
87+
// make sure aliases match the definition
88+
// deep merging causes a mix
89+
if (!params.domain) {
90+
updateDistributionParams.DistributionConfig.Aliases = params.Aliases
91+
}
92+
93+
// these are invalid CF parameters
94+
delete updateDistributionParams.DistributionConfig.distributionId
95+
delete updateDistributionParams.DistributionConfig.domain
96+
delete updateDistributionParams.DistributionConfig.certificateArn
97+
delete updateDistributionParams.DistributionConfig.certificateStatus
98+
delete updateDistributionParams.DistributionConfig.domainHostedZoneId
99+
100+
// 6. then finally update!
101+
const res = await cf.updateDistribution(updateDistributionParams).promise()
102+
103+
return {
104+
distributionId: res.Distribution.Id,
105+
distributionArn: res.Distribution.ARN,
106+
distributionUrl: res.Distribution.DomainName
107+
}
108+
} catch (e) {
109+
if (e.code === 'NoSuchDistribution') {
110+
const res = await createDistribution(aws, params)
111+
return res
112+
}
113+
throw e
114+
}
115+
}
116+
117+
module.exports = async (aws, params = {}) => {
118+
const { domain } = params
119+
120+
if (domain) {
121+
const deployCertificateParams = {
122+
domain
123+
}
124+
125+
const res = await aws.utils.deployCertificate(deployCertificateParams)
126+
params.certificateArn = res.certificateArn // eslint-disable-line
127+
params.domainHostedZoneId = res.domainHostedZoneId // eslint-disable-line
128+
params.certificateStatus = res.certificateStatus // eslint-disable-line
129+
}
130+
131+
let distribution
132+
if (params.distributionId) {
133+
distribution = await updateDistribution(aws, params)
134+
} else {
135+
distribution = await createDistribution(aws, params)
136+
}
137+
138+
if (domain) {
139+
const deployDistributionDnsParams = {
140+
domain,
141+
distributionUrl: distribution.distributionUrl,
142+
domainHostedZoneId: params.domainHostedZoneId
143+
}
144+
145+
await aws.utils.deployDistributionDns(deployDistributionDnsParams)
146+
147+
distribution.certificateArn = params.certificateArn
148+
distribution.certificateStatus = params.certificateStatus
149+
distribution.certificateStatus = params.certificateStatus
150+
}
151+
152+
return distribution
153+
}

src/disableDistribution.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
module.exports = async (aws, params = {}) => {
2+
const { distributionId } = params
3+
if (!distributionId) {
4+
throw new Error(`Missing "distributionId" param`)
5+
}
6+
7+
const deployDistributionParams = {
8+
distributionId,
9+
Enabled: false,
10+
Aliases: {
11+
Quantity: 0,
12+
Items: []
13+
}
14+
}
15+
16+
return aws.utils.deployDistribution(deployDistributionParams)
17+
}

src/index.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,5 +125,10 @@ aws.utils.getCloudWatchLogGroupArn = (params) => require('./getCloudWatchLogGrou
125125
aws.utils.deleteLambda = (params) => require('./deleteLambda')(aws, params)
126126
aws.utils.deleteAppSyncApi = (params) => require('./deleteAppSyncApi')(aws, params)
127127
aws.utils.deployAppSyncApiKey = (params) => require('./deployAppSyncApiKey')(aws, params)
128+
aws.utils.deployAppSyncDistribution = (params) =>
129+
require('./deployAppSyncDistribution')(aws, params)
130+
aws.utils.deployDistribution = (params) => require('./deployDistribution')(aws, params)
131+
aws.utils.disableDistribution = (params) => require('./disableDistribution')(aws, params)
132+
aws.utils.removeDistribution = (params) => require('./removeDistribution')(aws, params)
128133

129134
module.exports = aws

src/removeDistribution.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
module.exports = async (aws, params = {}) => {
2+
const { distributionId } = params
3+
4+
if (!distributionId) {
5+
throw new Error(`Missing "distributionId" param`)
6+
}
7+
const cf = new aws.CloudFront()
8+
9+
try {
10+
const getDistributionConfigRes = await cf
11+
.getDistributionConfig({ Id: distributionId })
12+
.promise()
13+
14+
const deleteDistributionParams = { Id: distributionId, IfMatch: getDistributionConfigRes.ETag }
15+
await cf.deleteDistribution(deleteDistributionParams).promise()
16+
17+
// todo remove distribtution dns
18+
} catch (e) {
19+
if (e.code === 'DistributionNotDisabled') {
20+
await aws.utils.disableDistribution(params)
21+
} else if (e.code === 'NoSuchDistribution') {
22+
return
23+
} else {
24+
throw e
25+
}
26+
}
27+
}

src/utils.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
const AdmZip = require('adm-zip')
2+
const mergeDeep = require('merge-deep')
23

34
const sleep = async (wait) => new Promise((resolve) => setTimeout(() => resolve(), wait))
45

@@ -29,4 +30,4 @@ const zip = (dirPath) => {
2930
return zipFile
3031
}
3132

32-
module.exports = { sleep, zip, getNakedDomain, shouldConfigureNakedDomain }
33+
module.exports = { mergeDeep, sleep, zip, getNakedDomain, shouldConfigureNakedDomain }

0 commit comments

Comments
 (0)