Skip to content

Commit c0dc39b

Browse files
committed
feat: add cynosdb module
1 parent ce9435c commit c0dc39b

File tree

6 files changed

+366
-32
lines changed

6 files changed

+366
-32
lines changed

__tests__/cynos.test.js

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
const { Cynosdb } = require('../src');
2+
const { getClusterDetail, sleep, generatePwd, PWD_CHARS } = require('../src/modules/cynosdb/utils');
3+
4+
const pwdReg = new RegExp(`[${PWD_CHARS}]{8,64}`);
5+
6+
describe('Cynosdb', () => {
7+
jest.setTimeout(600000);
8+
const credentials = {
9+
SecretId: process.env.TENCENT_SECRET_ID,
10+
SecretKey: process.env.TENCENT_SECRET_KEY,
11+
};
12+
const client = new Cynosdb(credentials, 'ap-guangzhou');
13+
14+
const inputs = {
15+
region: 'ap-guangzhou',
16+
zone: 'ap-guangzhou-4',
17+
vpcConfig: {
18+
vpcId: 'vpc-p2dlmlbj',
19+
subnetId: 'subnet-a1v3k07o',
20+
},
21+
};
22+
23+
test('[generatePwd] should get random password with default length 8', () => {
24+
const res = generatePwd();
25+
expect(typeof res).toBe('string');
26+
expect(res.length).toBe(8);
27+
});
28+
29+
test('[generatePwd] should get random password with customize length 6', () => {
30+
const res = generatePwd(6);
31+
expect(typeof res).toBe('string');
32+
expect(res.length).toBe(6);
33+
});
34+
35+
test('should deploy Cynosdb success', async () => {
36+
const res = await client.deploy(inputs);
37+
expect(res).toEqual({
38+
region: inputs.region,
39+
zone: inputs.zone,
40+
vpcConfig: inputs.vpcConfig,
41+
instanceCount: 2,
42+
adminPassword: expect.stringMatching(pwdReg),
43+
clusterId: expect.stringContaining('cynosdbmysql-'),
44+
connection: {
45+
ip: expect.any(String),
46+
port: 3306,
47+
readList: [
48+
{
49+
ip: expect.any(String),
50+
port: 3306,
51+
},
52+
],
53+
},
54+
});
55+
56+
inputs.clusterId = res.clusterId;
57+
});
58+
59+
test('should remove Cynosdb success', async () => {
60+
await sleep(1000);
61+
const res = await client.remove(inputs);
62+
63+
const detail = await getClusterDetail(client.capi, inputs.clusterId);
64+
expect(res).toEqual(true);
65+
expect(detail).toBeUndefined();
66+
});
67+
});

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@
7474
"semantic-release": "^17.0.4"
7575
},
7676
"dependencies": {
77-
"@tencent-sdk/capi": "^1.1.2",
77+
"@tencent-sdk/capi": "^1.1.4",
7878
"@ygkit/request": "^0.1.1",
7979
"cos-nodejs-sdk-v5": "^2.6.2",
8080
"moment": "^2.25.3",

src/index.js

Lines changed: 16 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,18 @@
1-
const Apigw = require('./modules/apigw');
2-
const Cdn = require('./modules/cdn');
3-
const Cns = require('./modules/cns');
4-
const Cos = require('./modules/cos');
5-
const Domain = require('./modules/domain');
6-
const MultiApigw = require('./modules/multi-apigw');
7-
const MultiScf = require('./modules/multi-scf');
8-
const Scf = require('./modules/scf');
9-
const Tag = require('./modules/tag');
10-
const Postgresql = require('./modules/postgresql');
11-
const Vpc = require('./modules/vpc');
12-
const Cam = require('./modules/cam');
13-
const Metrics = require('./modules/metrics');
14-
const Layer = require('./modules/layer');
15-
const Cfs = require('./modules/cfs');
16-
171
module.exports = {
18-
Apigw,
19-
Cdn,
20-
Cns,
21-
Cos,
22-
Domain,
23-
MultiApigw,
24-
MultiScf,
25-
Scf,
26-
Tag,
27-
Postgresql,
28-
Vpc,
29-
Cam,
30-
Metrics,
31-
Layer,
32-
Cfs,
2+
Apigw: require('./modules/apigw'),
3+
Cdn: require('./modules/cdn'),
4+
Cns: require('./modules/cns'),
5+
Cos: require('./modules/cos'),
6+
Domain: require('./modules/domain'),
7+
MultiApigw: require('./modules/multi-apigw'),
8+
MultiScf: require('./modules/multi-scf'),
9+
Scf: require('./modules/scf'),
10+
Tag: require('./modules/tag'),
11+
Postgresql: require('./modules/postgresql'),
12+
Vpc: require('./modules/vpc'),
13+
Cam: require('./modules/cam'),
14+
Metrics: require('./modules/metrics'),
15+
Layer: require('./modules/layer'),
16+
Cfs: require('./modules/cfs'),
17+
Cynosdb: require('./modules/cynosdb'),
3318
};

src/modules/cynosdb/apis.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
const { ApiFactory } = require('../../utils/api');
2+
3+
const ACTIONS = [
4+
'CreateClusters',
5+
'DescribeClusterDetail',
6+
'IsolateCluster',
7+
'DescribeAccounts',
8+
'ResetAccountPassword',
9+
];
10+
11+
const APIS = ApiFactory({
12+
// debug: true,
13+
serviceType: 'cynosdb',
14+
version: '2019-01-07',
15+
actions: ACTIONS,
16+
});
17+
18+
module.exports = APIS;

src/modules/cynosdb/index.js

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
const { Capi } = require('@tencent-sdk/capi');
2+
const {
3+
createCluster,
4+
getClusterDetail,
5+
deleteCluster,
6+
generatePwd,
7+
formatConnectOutput,
8+
resetPwd,
9+
} = require('./utils');
10+
const { ApiError } = require('../../utils/error');
11+
12+
class Cynosdb {
13+
constructor(credentials = {}, region) {
14+
this.region = region || 'ap-guangzhou';
15+
this.credentials = credentials;
16+
this.capi = new Capi({
17+
Region: this.region,
18+
AppId: this.credentials.AppId,
19+
SecretId: this.credentials.SecretId,
20+
SecretKey: this.credentials.SecretKey,
21+
Token: this.credentials.Token,
22+
});
23+
}
24+
25+
async deploy(inputs = {}) {
26+
const {
27+
clusterId,
28+
region,
29+
zone,
30+
vpcConfig,
31+
projectId = 0,
32+
dbVersion = '5.7',
33+
dbType = 'MYSQL',
34+
port = 3306,
35+
cpu = 1,
36+
memory = 1,
37+
storageLimit = 1000,
38+
instanceCount = 2,
39+
adminPassword,
40+
} = inputs;
41+
42+
const outputs = {
43+
region: region,
44+
zone: zone,
45+
vpcConfig: vpcConfig,
46+
instanceCount,
47+
};
48+
49+
let isExisted = false;
50+
let clusterDetail = null;
51+
if (clusterId) {
52+
clusterDetail = await getClusterDetail(this.capi, clusterId);
53+
if (clusterDetail && clusterDetail.ClusterId) {
54+
isExisted = true;
55+
outputs.clusterId = clusterDetail.ClusterId;
56+
if (adminPassword) {
57+
outputs.adminPassword = adminPassword;
58+
}
59+
}
60+
}
61+
if (!isExisted) {
62+
// not exist, create
63+
const dbInputs = {
64+
Zone: zone,
65+
ProjectId: projectId,
66+
DbType: dbType,
67+
DbVersion: dbVersion,
68+
Port: port,
69+
Cpu: cpu,
70+
Memory: memory,
71+
StorageLimit: storageLimit,
72+
InstanceCount: instanceCount,
73+
PayMode: 0,
74+
AutoVoucher: 1,
75+
RollbackStrategy: 'noneRollback',
76+
OrderSource: 'serverless',
77+
VpcId: vpcConfig.vpcId,
78+
SubnetId: vpcConfig.subnetId,
79+
AdminPassword: adminPassword,
80+
VpcId: vpcConfig.vpcId,
81+
SubnetId: vpcConfig.subnetId,
82+
AdminPassword: adminPassword || generatePwd(),
83+
};
84+
85+
clusterDetail = await createCluster(this.capi, dbInputs);
86+
outputs.clusterId = clusterDetail.ClusterId;
87+
88+
outputs.adminPassword = dbInputs.AdminPassword;
89+
}
90+
91+
outputs.connection = formatConnectOutput(clusterDetail);
92+
93+
return outputs;
94+
}
95+
96+
async remove(inputs = {}) {
97+
const { clusterId } = inputs;
98+
99+
const clusterDetail = await getClusterDetail(this.capi, clusterId);
100+
if (clusterDetail && clusterDetail.ClusterId) {
101+
// need circle for deleting, after host status is 6, then we can delete it
102+
await deleteCluster(this.capi, clusterId);
103+
}
104+
return true;
105+
}
106+
107+
async resetPwd(inputs = {}) {
108+
const { clusterId } = inputs;
109+
110+
const clusterDetail = await getClusterDetail(this.capi, clusterId);
111+
if (clusterDetail && clusterDetail.ClusterId) {
112+
// need circle for deleting, after host status is 6, then we can delete it
113+
await resetPwd(this.capi, inputs);
114+
} else {
115+
throw ApiError({
116+
type: 'PARAMETER_CYNOSDB',
117+
message: `CynosDB cluster id: ${clusterId} not exist.`,
118+
});
119+
}
120+
return true;
121+
}
122+
}
123+
124+
module.exports = Cynosdb;

0 commit comments

Comments
 (0)