Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 43 additions & 4 deletions __tests__/apigw.test.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import { ApigwDeployInputs, ApigwDeployOutputs } from './../src/modules/apigw/interface';
import { Apigw } from '../src';

const deepClone = (obj) => {
function deepClone<T>(obj: T): T {
return JSON.parse(JSON.stringify(obj));
};
}

describe('apigw', () => {
const credentials = {
SecretId: process.env.TENCENT_SECRET_ID,
SecretKey: process.env.TENCENT_SECRET_KEY,
};
const inputs = {
const inputs: ApigwDeployInputs = {
protocols: ['http', 'https'],
serviceName: 'serverless_test',
environment: 'release',
Expand Down Expand Up @@ -145,7 +146,7 @@ describe('apigw', () => {
],
};
const apigw = new Apigw(credentials, process.env.REGION);
let outputs;
let outputs: ApigwDeployOutputs;

test('[Environment UsagePlan] should deploy a apigw success', async () => {
const apigwInputs = deepClone(inputs);
Expand Down Expand Up @@ -377,4 +378,42 @@ describe('apigw', () => {

expect(detail).toBeNull();
});

test.only('[Apigw] Bind CustomDomain success', async () => {
const apigwInputs = deepClone(inputs);
apigwInputs.customDomains = [
{
domain: 'test-1.sls.plus',
// certificateId: 'cWOJJjax',
isDefaultMapping: false,
pathMappingSet: [
{
path: '/',
environment: 'release',
},
],
protocols: ['http'],
isForcedHttps: true,
},
{
domain: 'test-2.sls.plus',
// certificateId: 'cWOJJjax',
isDefaultMapping: false,
pathMappingSet: [
{
path: '/',
environment: 'release',
},
],
protocols: ['http'],
isForcedHttps: true,
},
];
const deployOutputs = await apigw.deploy(inputs);

const deployOutputsAgain = await apigw.deploy(inputs);

console.log({ deployOutputs, deployOutputsAgain });
await apigw.remove(deployOutputs);
});
});
4 changes: 3 additions & 1 deletion __tests__/scf.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ describe('Scf', () => {
// },
};

const events = Object.entries(triggers).map(([, value]) => value);

const inputs: ScfDeployInputs = {
name: `serverless-test-${Date.now()}`,
code: {
Expand All @@ -100,7 +102,7 @@ describe('Scf', () => {
},
eip: true,
vpcConfig: vpcConfig,
events: Object.entries(triggers).map(([, value]) => value),
events,
};

const cfsInputs = {
Expand Down
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export { default as Tag } from './modules/tag';
export { default as Postgresql } from './modules/postgresql';
export { default as Vpc } from './modules/vpc';
export { default as Cam } from './modules/cam';
export { default as Metrics } from './modules/metrics';
export { default as Metrics } from './modules/metrics/index';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这一样改动有啥影响吗?

export { default as Layer } from './modules/layer';
export { default as Cfs } from './modules/cfs';
export { default as Cynosdb } from './modules/cynosdb';
Expand Down
73 changes: 39 additions & 34 deletions src/modules/apigw/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -485,7 +485,7 @@ export default class Apigw {

const unboundSecretIds = await this.getUnboundSecretIds({
usagePlanId: usagePlan.usagePlanId,
secretIds: secrets.secretIds,
secretIds: secrets.secretIds!,
});

if (unboundSecretIds.length > 0) {
Expand Down Expand Up @@ -654,7 +654,7 @@ export default class Apigw {
path,
method,
}: {
serviceId: string;
serviceId?: string;
path: string;
method: string;
}) {
Expand Down Expand Up @@ -704,42 +704,47 @@ export default class Apigw {

async createOrUpdateApi({ serviceId, endpoint, environment, created }: CreateOrUpdateApiInputs) {
// compatibility for secret auth config depends on auth & usagePlan
const authType = endpoint.auth ? 'SECRET' : endpoint.authType || 'NONE';
const businessType = endpoint.businessType || 'NORMAL';
const authType = endpoint?.auth ? 'SECRET' : endpoint?.authType ?? 'NONE';
const businessType = endpoint?.businessType ?? 'NORMAL';
const output: ApiDeployerOutputs = {
path: endpoint.path,
method: endpoint.method,
apiName: endpoint.apiName || 'index',
path: endpoint?.path,
method: endpoint?.method,
apiName: endpoint?.apiName || 'index',
created: true,
authType: authType,
businessType: businessType,
isBase64Encoded: endpoint.isBase64Encoded === true,
isBase64Encoded: endpoint?.isBase64Encoded === true,
};
if (endpoint.authRelationApiId) {
if (endpoint?.authRelationApiId) {
output.authRelationApiId = endpoint.authRelationApiId;
}

const apiInputs = {
protocol: endpoint.protocol || 'HTTP',
protocol: endpoint?.protocol ?? 'HTTP',
serviceId: serviceId,
apiName: endpoint.apiName || 'index',
apiDesc: endpoint.description,
apiName: endpoint?.apiName ?? 'index',
apiDesc: endpoint?.description,
apiType: 'NORMAL',
authType: authType,
apiBusinessType: endpoint.businessType || 'NORMAL',
serviceType: endpoint.serviceType || 'SCF',
apiBusinessType: endpoint?.businessType ?? 'NORMAL',
serviceType: endpoint?.serviceType ?? 'SCF',
requestConfig: {
path: endpoint.path,
method: endpoint.method,
path: endpoint?.path,
method: endpoint?.method,
},
serviceTimeout: endpoint.serviceTimeout || 15,
responseType: endpoint.responseType || 'HTML',
enableCORS: endpoint.enableCORS === true,
isBase64Encoded: endpoint.isBase64Encoded === true,
serviceTimeout: endpoint?.serviceTimeout ?? 15,
responseType: endpoint?.responseType ?? 'HTML',
enableCORS: endpoint?.enableCORS === true,
isBase64Encoded: endpoint?.isBase64Encoded === true,
isBase64Trigger: undefined as undefined | boolean,
base64EncodedTriggerRules: undefined as undefined | string[],
oauthConfig: endpoint.oauthConfig,
authRelationApiId: endpoint.authRelationApiId,
base64EncodedTriggerRules: undefined as
| undefined
| {
name: string;
value: string[];
}[],
oauthConfig: endpoint?.oauthConfig,
authRelationApiId: endpoint?.authRelationApiId,
};

this.marshalApiInput(endpoint, apiInputs);
Expand All @@ -749,20 +754,20 @@ export default class Apigw {
InternalDomain?: string;
};

if (endpoint.apiId) {
apiDetail = await this.getApiById({ serviceId, apiId: endpoint.apiId });
if (endpoint?.apiId) {
apiDetail = await this.getApiById({ serviceId: serviceId!, apiId: endpoint.apiId });
}

if (!apiDetail!) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

后面的 ! 符号没必要

apiDetail = await this.getApiByPathAndMethod({
serviceId,
path: endpoint.path,
method: endpoint.method,
serviceId: serviceId!,
path: endpoint?.path!,
method: endpoint?.method!,
});
}

if (apiDetail) {
console.log(`Api method ${endpoint.method}, path ${endpoint.path} already exist`);
if (apiDetail && endpoint) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

看看试着把 endpoint 参数改为必须

console.log(`Api method ${endpoint?.method}, path ${endpoint?.path} already exist`);
endpoint.apiId = apiDetail.ApiId;

if (endpoint.isBase64Encoded && endpoint.isBase64Trigger) {
Expand Down Expand Up @@ -796,7 +801,7 @@ export default class Apigw {
});
output.internalDomain = apiDetail.InternalDomain || '';

if (endpoint.isBase64Encoded && endpoint.isBase64Trigger) {
if (endpoint?.isBase64Encoded && endpoint.isBase64Trigger) {
apiInputs.isBase64Trigger = endpoint.isBase64Trigger;
apiInputs.base64EncodedTriggerRules = endpoint.base64EncodedTriggerRules;
}
Expand All @@ -810,7 +815,7 @@ export default class Apigw {

output.apiName = apiInputs.apiName;

if (endpoint.usagePlan) {
if (endpoint?.usagePlan) {
const usagePlan = await this.bindUsagePlan({
apiId: output.apiId,
serviceId,
Expand All @@ -837,7 +842,7 @@ export default class Apigw {
// if exist in state list, set created to be true
const [exist] = oldList.filter(
(item) =>
item.method.toLowerCase() === apiConfig.method.toLowerCase() &&
item?.method?.toLowerCase() === apiConfig?.method?.toLowerCase() &&
item.path === apiConfig.path,
);

Expand All @@ -855,7 +860,7 @@ export default class Apigw {
if (authRelationApi) {
const [relativeApi] = apiList.filter(
(item) =>
item.method.toLowerCase() === authRelationApi.method.toLowerCase() &&
item.method?.toLowerCase() === authRelationApi.method.toLowerCase() &&
item.path === authRelationApi.path,
);
if (relativeApi) {
Expand Down
61 changes: 39 additions & 22 deletions src/modules/apigw/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,16 @@ export interface ApigwSetupUsagePlanInputs {

created?: boolean;

secrets?: { secretIds: string[]; created: boolean };
secrets?: { secretIds?: string[]; created: boolean };
}

export interface ApigwSetupUsagePlanOutputs extends ApigwSetupUsagePlanInputs {}

export interface ApigwSetupUsagePlanSecretInputs {
/** 要使用的密钥 id 列表 */
secretIds: string[];
secretIds?: string[];
/** 用户自定义的密钥名 */
secretName: string;
secretName?: string;
created?: boolean;
}
export interface ApigwBindUsagePlanInputs {
Expand All @@ -38,42 +38,59 @@ export interface ApigwBindUsagePlanInputs {
export interface ApigwBindUsagePlanOutputs extends ApigwBindUsagePlanInputs {}

export interface ApiEndpoint {
created: boolean;
created?: boolean;
apiId?: string;
usagePlan?: ApigwSetupUsagePlanInputs;
auth?: ApigwSetupUsagePlanSecretInputs;
authType?: 'NONE' | string;
businessType?: 'NORMAL' | string;
path: string;
method: string;
path?: string;
method?: string;
apiName?: string;
protocol?: 'HTTP' | 'HTTPS';
protocol?: 'HTTP' | 'HTTPS' | 'WEBSOCKET';
description?: string;
serviceType?: 'SCF' | string;
serviceTimeout?: 15;
responseType?: 'HTML' | string;
enableCORS?: boolean;
oauthConfig?: string;
authRelationApiId?: string;
authRelationApi?: {
method: string;
path: string;
};
function?: {
functionName?: string;
functionNamespace?: string;
functionQualifier?: string;
transportFunctionName?: string;
registerFunctionName?: string;
};
internalDomain?: string;
isBase64Encoded?: boolean;
isBase64Trigger?: boolean;
base64EncodedTriggerRules?: string[];
base64EncodedTriggerRules?: { name: string; value: string[] }[];
serviceMockReturnMessage?: string;
serviceConfig?: {
url?: string;
path?: string;
method?: string;
};
oauthConfig?: {
loginRedirectUrl: string;
publicKey: string;
tokenLocation: string;
};
}

export interface ApigwBindCustomDomainInputs {
customDomains?: {
domain: string;
protocols: ('http' | 'https')[];
protocols?: ('http' | 'https')[];

certificateId: string;
certificateId?: string;
isDefaultMapping?: boolean;
pathMappingSet: [];
netType: string;
pathMappingSet: { path: string; environment: string }[];
netType?: string;

isForcedHttps: boolean;

Expand All @@ -90,7 +107,7 @@ export interface ApigwCreateOrUpdateServiceInputs {
netTypes?: string[];
serviceName?: string;
serviceDesc?: string;
serviceId: string;
serviceId?: string;

usagePlan?: ApigwSetupUsagePlanInputs;
auth?: ApigwSetupUsagePlanSecretInputs;
Expand All @@ -99,10 +116,10 @@ export interface ApigwCreateOrUpdateServiceInputs {
export type ApiDeployerOutputs = ApiEndpoint;

export interface CreateOrUpdateApiInputs {
serviceId: string;
endpoint: ApiEndpoint;
environment: EnviromentType;
created: boolean;
serviceId?: string;
endpoint?: ApiEndpoint;
environment?: EnviromentType;
created?: boolean;
}

export interface ApiDeployerInputs {
Expand All @@ -117,11 +134,11 @@ export interface ApiDeployerInputs {
export interface ApigwDeployInputs
extends ApigwCreateOrUpdateServiceInputs,
ApigwBindCustomDomainInputs {
region: RegionType;
oldState: any;
region?: RegionType;
oldState?: any;
environment?: EnviromentType;

endpoints: ApiEndpoint[];
endpoints?: ApiEndpoint[];
}

export interface ApigwBindCustomDomainOutputs {
Expand Down Expand Up @@ -164,7 +181,7 @@ export interface ApigwApiRemoverInputs {
}

export interface ApigwRemoveInputs {
created: boolean;
created?: boolean;
environment: EnviromentType;
serviceId: string;
apiList: ApiEndpoint[];
Expand Down
Loading