Skip to content

Commit 7da7a38

Browse files
committed
feat: support image deploy and add tcr module
1 parent 227e643 commit 7da7a38

File tree

11 files changed

+677
-62
lines changed

11 files changed

+677
-62
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,4 @@ package-lock.json
2525
yarn.lock
2626

2727
__tests__/apigw.list.test.ts
28+
__tests__/scf.image.test.ts

__tests__/tcr.test.ts

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
import { Tcr } from '../src';
2+
3+
describe('Tcr', () => {
4+
const credentials = {
5+
SecretId: process.env.TENCENT_SECRET_ID,
6+
SecretKey: process.env.TENCENT_SECRET_KEY,
7+
};
8+
// const client = new Tcr(credentials, process.env.REGION);
9+
const client = new Tcr(credentials, 'ap-chengdu');
10+
11+
describe('Personal', () => {
12+
const namespace = 'sls-scf';
13+
const repositoryName = 'nodejs_test';
14+
const tagName = 'latest';
15+
16+
test('get personal image info', async () => {
17+
const res = await client.getPersonalImageInfo({ namespace, repositoryName, tagName });
18+
expect(res).toEqual({
19+
imageType: 'personal',
20+
imageUrl: `ccr.ccs.tencentyun.com/${namespace}/${repositoryName}`,
21+
imageUri: expect.stringContaining(
22+
`ccr.ccs.tencentyun.com/${namespace}/${repositoryName}:${tagName}@`,
23+
),
24+
tagName,
25+
});
26+
});
27+
28+
test('getPersonalTagDetail', async () => {
29+
const res = await client.getPersonalTagDetail({ namespace, repositoryName, tagName });
30+
expect(res).toEqual({
31+
repositoryName,
32+
namespace,
33+
tagName,
34+
server: 'ccr.ccs.tencentyun.com',
35+
tagId: expect.stringContaining('sha256:'),
36+
imageId: expect.stringContaining('sha256:'),
37+
author: expect.any(String),
38+
os: expect.any(String),
39+
});
40+
});
41+
});
42+
43+
describe('Enterprise', () => {
44+
const registryName = 'serverless';
45+
const registryId = 'tcr-l03rz3ld';
46+
const namespace = 'enterprise';
47+
const repositoryName = 'nodejs_test';
48+
const tagName = 'latest';
49+
50+
test('get enterprise image info', async () => {
51+
const res = await client.getImageInfo({
52+
registryId,
53+
namespace,
54+
repositoryName,
55+
tagName,
56+
});
57+
expect(res).toEqual({
58+
imageType: 'enterprise',
59+
imageUrl: `${registryName}.tencentcloudcr.com/${namespace}/${repositoryName}`,
60+
imageUri: expect.stringContaining(
61+
`${registryName}.tencentcloudcr.com/${namespace}/${repositoryName}:${tagName}@`,
62+
),
63+
tagName,
64+
});
65+
});
66+
67+
test('get enterprise image info by name', async () => {
68+
const res = await client.getImageInfoByName({
69+
registryName,
70+
namespace,
71+
repositoryName,
72+
tagName,
73+
});
74+
expect(res).toEqual({
75+
imageType: 'enterprise',
76+
imageUrl: `${registryName}.tencentcloudcr.com/${namespace}/${repositoryName}`,
77+
imageUri: expect.stringContaining(
78+
`${registryName}.tencentcloudcr.com/${namespace}/${repositoryName}:${tagName}@`,
79+
),
80+
tagName,
81+
});
82+
});
83+
84+
test('getRegistryDetail', async () => {
85+
const res = await client.getRegistryDetail({
86+
registryId,
87+
});
88+
expect(res).toEqual({
89+
registryId,
90+
registryName,
91+
regionName: expect.any(String),
92+
status: 'Running',
93+
registryType: 'basic',
94+
publicDomain: `${registryName}.tencentcloudcr.com`,
95+
internalEndpoint: expect.any(String),
96+
});
97+
});
98+
99+
test('getRegistryDetailByName', async () => {
100+
const res = await client.getRegistryDetailByName({
101+
registryName: 'serverless',
102+
});
103+
expect(res).toEqual({
104+
registryId,
105+
registryName,
106+
regionName: expect.any(String),
107+
status: 'Running',
108+
registryType: 'basic',
109+
publicDomain: `${registryName}.tencentcloudcr.com`,
110+
internalEndpoint: expect.any(String),
111+
});
112+
});
113+
114+
test('getRepositoryDetail', async () => {
115+
const res = await client.getRepositoryDetail({
116+
registryId,
117+
namespace,
118+
repositoryName,
119+
});
120+
expect(res).toEqual({
121+
name: `${namespace}/${repositoryName}`,
122+
namespace,
123+
creationTime: expect.any(String),
124+
updateTime: expect.any(String),
125+
description: expect.any(String),
126+
briefDescription: expect.any(String),
127+
public: false,
128+
});
129+
});
130+
131+
test('getImageTagDetail', async () => {
132+
const res = await client.getImageTagDetail({
133+
registryId,
134+
namespace,
135+
repositoryName,
136+
tagName: 'latest',
137+
});
138+
expect(res).toEqual({
139+
digest: expect.stringContaining('sha256:'),
140+
imageVersion: 'latest',
141+
size: expect.any(Number),
142+
updateTime: expect.any(String),
143+
});
144+
});
145+
});
146+
});

src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,6 @@ export { default as Clb } from './modules/clb';
1717
export { default as Monitor } from './modules/monitor';
1818
export { default as Account } from './modules/account';
1919
export { default as Asw } from './modules/asw';
20+
export { default as Tcr } from './modules/tcr';
2021

2122
export { TriggerManager } from './modules/triggers/manager';

src/modules/interface.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ export enum ApiServiceType {
3636

3737
// asw 状态机
3838
asw = 'asw',
39+
40+
// asw 状态机
41+
tcr = 'tcr',
3942
}
4043

4144
export type RegionType = string;

src/modules/scf/entities/scf.ts

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,13 @@ import { formatInputs } from '../utils';
99

1010
import BaseEntity from './base';
1111

12-
import { ScfCreateFunctionInputs, FunctionInfo, FaasBaseConfig, GetLogOptions } from '../interface';
12+
import {
13+
ScfCreateFunctionInputs,
14+
FunctionInfo,
15+
FaasBaseConfig,
16+
GetLogOptions,
17+
UpdateFunctionCodeOptions,
18+
} from '../interface';
1319

1420
export default class ScfEntity extends BaseEntity {
1521
region: string;
@@ -152,12 +158,13 @@ export default class ScfEntity extends BaseEntity {
152158
async updateCode(inputs: ScfCreateFunctionInputs, funcInfo: FunctionInfo) {
153159
console.log(`Updating function ${inputs.name} code, region ${this.region}`);
154160
const functionInputs = await formatInputs(this.region, inputs);
155-
const reqParams = {
161+
const reqParams: UpdateFunctionCodeOptions = {
156162
Action: 'UpdateFunctionCode' as const,
157163
Handler: functionInputs.Handler || funcInfo.Handler,
158164
FunctionName: functionInputs.FunctionName,
159-
CosBucketName: functionInputs.Code?.CosBucketName,
160-
CosObjectName: functionInputs.Code?.CosObjectName,
165+
// CosBucketName: functionInputs.Code?.CosBucketName,
166+
// CosObjectName: functionInputs.Code?.CosObjectName,
167+
Code: functionInputs.Code,
161168
Namespace: inputs.namespace || funcInfo.Namespace,
162169
InstallDependency: functionInputs.InstallDependency,
163170
};
@@ -188,7 +195,6 @@ export default class ScfEntity extends BaseEntity {
188195
delete reqInputs.Type;
189196
delete reqInputs.Handler;
190197
delete reqInputs.Code;
191-
delete reqInputs.CodeSource;
192198
delete reqInputs.AsyncRunEnable;
193199
delete reqInputs.InstallDependency;
194200
delete reqInputs.DeployMode;
@@ -227,7 +233,7 @@ export default class ScfEntity extends BaseEntity {
227233
} catch (e) {
228234
throw new ApiError({
229235
type: 'API_SCF_DeleteFunction',
230-
message: `Cannot delete function in 2 minutes, (reqId: ${res.RequestId})`,
236+
message: `删除函数是失败:${e.message}, (reqId: ${res.RequestId})`,
231237
});
232238
}
233239
return true;

src/modules/scf/interface.ts

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,60 @@
11
import { RegionType } from './../interface';
22
import { ApigwRemoveInputs } from './../apigw/interface';
33

4+
export interface FunctionCode {
5+
CosBucketName?: string;
6+
CosObjectName?: string;
7+
8+
// 镜像部署代码
9+
ImageConfig?: {
10+
ImageType: string;
11+
ImageUri: string;
12+
RegistryId?: string;
13+
Command?: string;
14+
Args?: string;
15+
};
16+
}
17+
export interface BaseFunctionConfig {
18+
FunctionName: string;
19+
Code?: FunctionCode;
20+
Handler?: string;
21+
Runtime?: string;
22+
Namespace?: string;
23+
Timeout?: number;
24+
InitTimeout?: number;
25+
MemorySize?: number;
26+
Type?: 'HTTP' | 'Event';
27+
DeployMode?: 'code' | 'image';
28+
PublicNetConfig?: {
29+
PublicNetStatus: 'ENABLE' | 'DISABLE';
30+
EipConfig: {
31+
EipStatus: 'ENABLE' | 'DISABLE';
32+
};
33+
};
34+
L5Enable?: 'TRUE' | 'FALSE';
35+
Role?: string;
36+
Description?: string;
37+
ClsLogsetId?: string;
38+
ClsTopicId?: string;
39+
Environment?: { Variables: { Key: string; Value: string }[] };
40+
VpcConfig?: { VpcId?: string; SubnetId?: string };
41+
Layers?: { LayerName: string; LayerVersion: number }[];
42+
DeadLetterConfig?: { Type?: string; Name?: string; FilterType?: string };
43+
CfsConfig?: {
44+
CfsInsList: {
45+
CfsId: string;
46+
MountInsId: string;
47+
LocalMountDir: string;
48+
RemoteMountDir: string;
49+
UserGroupId: string;
50+
UserId: string;
51+
}[];
52+
};
53+
AsyncRunEnable?: 'TRUE' | 'FALSE';
54+
TraceEnable?: 'TRUE' | 'FALSE';
55+
InstallDependency?: 'TRUE' | 'FALSE';
56+
}
57+
458
export interface TriggerType {
559
NeedCreate?: boolean;
660
Type: string;
@@ -141,6 +195,20 @@ export interface ScfCreateFunctionInputs {
141195
asyncRunEnable?: undefined | boolean;
142196
traceEnable?: undefined | boolean;
143197
installDependency?: undefined | boolean;
198+
199+
// 镜像
200+
imageConfig?: {
201+
// 镜像类型:enterprise - 企业版、personal - 个人版
202+
imageType: string;
203+
// 镜像地址
204+
imageUri: string;
205+
// 仓库 ID
206+
registryId?: string;
207+
// 启动命令
208+
command?: string;
209+
// 启动命令参数
210+
args?: string;
211+
};
144212
}
145213

146214
export interface ScfUpdateAliasTrafficInputs {
@@ -257,3 +325,18 @@ export type GetLogOptions = Omit<GetSearchSqlOptions, 'startTime'> & {
257325
// 时间间隔,单位秒,默认为 3600s
258326
interval?: string;
259327
};
328+
329+
export interface UpdateFunctionCodeOptions {
330+
Action: any;
331+
Handler: string;
332+
FunctionName: string;
333+
Namespace: string;
334+
InstallDependency?: string;
335+
336+
// cos 方式
337+
CosBucketName?: string;
338+
CosObjectName?: string;
339+
340+
// image 方式
341+
Code?: FunctionCode;
342+
}

0 commit comments

Comments
 (0)