-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathserverless.js
145 lines (117 loc) · 3.51 KB
/
serverless.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
const { Component } = require("@serverless/core");
const { equals, difference } = require("ramda");
const AWS = require("aws-sdk");
const {
createGlobalTable,
updateGlobalTable,
getDeployedRegions
} = require("./utils");
class GlobalDynamoDBTableComponent extends Component {
get client() {
return new AWS.DynamoDB({
credentials: this.context.credentials.aws,
// any region here works
region: "eu-west-1"
});
}
createTableInRegions(
globalTableName,
regions,
attributeDefinitions,
keySchema,
localSecondaryIndexes,
globalSecondaryIndexes = []
) {
const createTables = regions.map(async region => {
const dynamodb = await this.load(
"@serverless/aws-dynamodb",
`${globalTableName}_${region}`
);
this.context.debug(`Creating new table in region ${region}`);
return dynamodb({
name: globalTableName,
region,
attributeDefinitions,
keySchema,
localSecondaryIndexes,
globalSecondaryIndexes,
stream: true
});
});
return Promise.all(createTables);
}
deleteTableFromRegions(globalTableName, regions) {
const deleteTables = regions.map(async region => {
const dynamodb = await this.load(
"@serverless/aws-dynamodb",
`${globalTableName}_${region}`
);
this.context.debug(`Deleting table from region ${region}`);
return dynamodb.remove();
});
return Promise.all(deleteTables);
}
validateInputs(inputs) {
const inputTableName = inputs.tableName;
const stateTableName = this.state.tableName;
if (stateTableName) {
if (inputTableName !== stateTableName) {
throw new Error(
`Can't rename Global Table. Use serverless remove to delete '${stateTableName}' first.`
);
}
}
}
async default(inputs = {}) {
const inputRegions = inputs.replicationGroup.sort();
const inputTableName = inputs.tableName;
this.validateInputs(inputs);
let deployedRegions = [];
let globalTableDoesNotExist = false;
try {
deployedRegions = await getDeployedRegions(this.client, inputTableName);
this.context.debug("Global table provisioned.");
} catch (err) {
this.context.debug("Global table not provisioned.");
globalTableDoesNotExist = true;
}
if (equals(deployedRegions, inputRegions)) {
return;
}
const addRegions = difference(inputRegions, deployedRegions);
const deleteRegions = difference(deployedRegions, inputRegions);
await this.createTableInRegions(
inputTableName,
addRegions,
inputs.attributeDefinitions,
inputs.keySchema,
inputs.localSecondaryIndexes,
inputs.globalSecondaryIndexes
);
await this.deleteTableFromRegions(inputTableName, deleteRegions);
if (globalTableDoesNotExist) {
await createGlobalTable(this.client, inputTableName, inputRegions);
} else {
await updateGlobalTable(
this.client,
inputTableName,
addRegions,
deleteRegions
);
}
this.state.tableName = inputTableName;
await this.save();
}
async remove() {
const tableName = this.state.tableName;
if (!tableName) {
this.context.debug("Table name not found in state. Aborting!");
return;
}
const regions = await getDeployedRegions(this.client, tableName);
await this.deleteTableFromRegions(tableName, regions);
this.state = {};
await this.save();
}
}
module.exports = GlobalDynamoDBTableComponent;