diff --git a/__tests__/ut/resources_acr_test.ts b/__tests__/ut/resources_acr_test.ts index fb8d17ba..557c6a79 100644 --- a/__tests__/ut/resources_acr_test.ts +++ b/__tests__/ut/resources_acr_test.ts @@ -241,10 +241,12 @@ describe('replaceFunction', () => { instanceLifecycleConfig: { initializer: { handler: '', + command: [], timeout: 3, }, preStop: { handler: '', + command: [], timeout: 3, }, }, diff --git a/package-lock.json b/package-lock.json index 43f165b6..c8989fb0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,15 +11,15 @@ "license": "ISC", "dependencies": { "@alicloud/fc2": "^2.6.6", - "@alicloud/fc20230330": "4.3.2", + "@alicloud/fc20230330": "4.3.3", "@alicloud/pop-core": "^1.8.0", "@serverless-cd/srm-aliyun-pop-core": "^0.0.7-beta.21", "@serverless-cd/srm-aliyun-ram20150501": "^0.0.2-beta.9", "@serverless-cd/srm-aliyun-sls20201230": "0.0.5-beta.3", "@serverless-devs/diff": "^0.0.3-beta.6", - "@serverless-devs/downloads": "^0.0.6", - "@serverless-devs/load-component": "^0.0.8", - "@serverless-devs/utils": "^0.0.16", + "@serverless-devs/downloads": "^0.0.7", + "@serverless-devs/load-component": "^0.0.9", + "@serverless-devs/utils": "^0.0.17", "@serverless-devs/zip": "^0.0.3-beta.8", "ajv": "^8.17.1", "ali-oss": "6.18.1", @@ -201,9 +201,9 @@ } }, "node_modules/@alicloud/fc20230330": { - "version": "4.3.2", - "resolved": "https://registry.npmmirror.com/@alicloud/fc20230330/-/fc20230330-4.3.2.tgz", - "integrity": "sha512-svXf6mbNgLtvCRHM/Z2P8VJXZGoQhyWoosYmFeasMBeNRDaPgGzYOpmY6FedL/4nzSn6Z6gV5DQT4EGz/AKq4Q==", + "version": "4.3.3", + "resolved": "https://registry.npmmirror.com/@alicloud/fc20230330/-/fc20230330-4.3.3.tgz", + "integrity": "sha512-WuKkefJ0oul7+oWuJrCSqRohsNoX2nMt4f+/NnN9UduF77KuDMYP9YvMQXzlZeNf0eot/cc0V4YNQ6zlQihRKg==", "dependencies": { "@alicloud/openapi-core": "^1.0.0", "@darabonba/typescript": "^1.0.0" @@ -2730,20 +2730,20 @@ } }, "node_modules/@serverless-devs/downloads": { - "version": "0.0.6", - "resolved": "https://registry.npmmirror.com/@serverless-devs/downloads/-/downloads-0.0.6.tgz", - "integrity": "sha512-lZahfq+nrxVrjyY9eG3Uu+P0oTnb5JzwLA+5bw0VyBaUAvVmPYD2b6MZprkXMxjJk8AWvNzNsg40wwydnZEUSg==", + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/@serverless-devs/downloads/-/downloads-0.0.7.tgz", + "integrity": "sha512-B0cyHfencRmw+ogA2/pEewFazJNFmf6io9dcDO+BDFG2mIXXlQF0OGJ3vGCtJSf7aycFBnw+I2Prykr0/osoYg==", "dependencies": { - "@serverless-devs/utils": "^0.0.14", + "@serverless-devs/utils": "^0.0.18", "chalk": "^4.1.2", "decompress": "^4.2.1", "fs-extra": "^11.1.0" } }, "node_modules/@serverless-devs/downloads/node_modules/@serverless-devs/utils": { - "version": "0.0.14", - "resolved": "https://registry.npmmirror.com/@serverless-devs/utils/-/utils-0.0.14.tgz", - "integrity": "sha512-E+vlcgwdIeRrSb2z20fD8jOANMyHrzS6mHJFwiAv6eKJX0UuH1um3dKqlrYwpjKzamERs4pT4IzGp/KB7jgXfw==", + "version": "0.0.18", + "resolved": "https://registry.npmjs.org/@serverless-devs/utils/-/utils-0.0.18.tgz", + "integrity": "sha512-zLfQFt8OtfNG6nZ3yWvKI4mU8W6X1CHNKmP+j9bW8+3rH98HXA9UOgmB/8YQjRLI7rZV50IghSorIeUZYStDoQ==", "dependencies": { "js-yaml": "^4.1.0", "lodash": "^4.17.21", @@ -2774,19 +2774,31 @@ } }, "node_modules/@serverless-devs/load-component": { - "version": "0.0.8", - "resolved": "https://registry.npmmirror.com/@serverless-devs/load-component/-/load-component-0.0.8.tgz", - "integrity": "sha512-T6lkB1rLcpHuIobL7KJw27uJ2RLUbBUzp535MyV6uChTsE0b0OmLkAC0P7fha4mwLBbIokcAGwSUhbUANVrxPQ==", + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/@serverless-devs/load-component/-/load-component-0.0.9.tgz", + "integrity": "sha512-uqBF4QwPtgzOt9/5yg7Rlgv2n8PSuaOH3eDlZTZjpIpovK+jypqk9keIvxe0+x/dxPT98xmkirMENZxKlqkMpQ==", "dependencies": { "@serverless-cd/debug": "^4.3.4", - "@serverless-devs/downloads": "^0.0.6", - "@serverless-devs/utils": "^0.0.16", + "@serverless-devs/downloads": "^0.0.7", + "@serverless-devs/utils": "^0.0.18", "axios": "^1.4.0", "fs-extra": "^11.1.0", "lodash": "^4.17.21", "semver": "^7.5.4" } }, + "node_modules/@serverless-devs/load-component/node_modules/@serverless-devs/utils": { + "version": "0.0.18", + "resolved": "https://registry.npmjs.org/@serverless-devs/utils/-/utils-0.0.18.tgz", + "integrity": "sha512-zLfQFt8OtfNG6nZ3yWvKI4mU8W6X1CHNKmP+j9bW8+3rH98HXA9UOgmB/8YQjRLI7rZV50IghSorIeUZYStDoQ==", + "dependencies": { + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "md5": "^2.3.0", + "minimist": "^1.2.8", + "random-string": "^0.2.0" + } + }, "node_modules/@serverless-devs/load-component/node_modules/axios": { "version": "1.8.4", "resolved": "https://packages.aliyun.com/670e108663cd360abfe4be65/npm/npm-registry/axios/-/axios-1.8.4.tgz", @@ -2838,9 +2850,9 @@ } }, "node_modules/@serverless-devs/utils": { - "version": "0.0.16", - "resolved": "https://registry.npmmirror.com/@serverless-devs/utils/-/utils-0.0.16.tgz", - "integrity": "sha512-ngiRbIG/yDe2UPtCG3w3dcwVjO76Kq27otroTem5CU3wWNGRBusKCWd0wRdmnY5eVjpnl7vYjTIWb5IgpPWWEA==", + "version": "0.0.17", + "resolved": "https://registry.npmjs.org/@serverless-devs/utils/-/utils-0.0.17.tgz", + "integrity": "sha512-PTkjZyOyZ/ktCe94dWzM2KReH/ne1oDjqR9nZTu8SJ+Rn91GT8V9uPSWe32YJm+4F0UH23KvKYstpAVgS2acEA==", "dependencies": { "js-yaml": "^4.1.0", "lodash": "^4.17.21", @@ -16067,9 +16079,9 @@ } }, "@alicloud/fc20230330": { - "version": "4.3.2", - "resolved": "https://registry.npmmirror.com/@alicloud/fc20230330/-/fc20230330-4.3.2.tgz", - "integrity": "sha512-svXf6mbNgLtvCRHM/Z2P8VJXZGoQhyWoosYmFeasMBeNRDaPgGzYOpmY6FedL/4nzSn6Z6gV5DQT4EGz/AKq4Q==", + "version": "4.3.3", + "resolved": "https://registry.npmmirror.com/@alicloud/fc20230330/-/fc20230330-4.3.3.tgz", + "integrity": "sha512-WuKkefJ0oul7+oWuJrCSqRohsNoX2nMt4f+/NnN9UduF77KuDMYP9YvMQXzlZeNf0eot/cc0V4YNQ6zlQihRKg==", "requires": { "@alicloud/openapi-core": "^1.0.0", "@darabonba/typescript": "^1.0.0" @@ -17946,20 +17958,20 @@ } }, "@serverless-devs/downloads": { - "version": "0.0.6", - "resolved": "https://registry.npmmirror.com/@serverless-devs/downloads/-/downloads-0.0.6.tgz", - "integrity": "sha512-lZahfq+nrxVrjyY9eG3Uu+P0oTnb5JzwLA+5bw0VyBaUAvVmPYD2b6MZprkXMxjJk8AWvNzNsg40wwydnZEUSg==", + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/@serverless-devs/downloads/-/downloads-0.0.7.tgz", + "integrity": "sha512-B0cyHfencRmw+ogA2/pEewFazJNFmf6io9dcDO+BDFG2mIXXlQF0OGJ3vGCtJSf7aycFBnw+I2Prykr0/osoYg==", "requires": { - "@serverless-devs/utils": "^0.0.14", + "@serverless-devs/utils": "^0.0.18", "chalk": "^4.1.2", "decompress": "^4.2.1", "fs-extra": "^11.1.0" }, "dependencies": { "@serverless-devs/utils": { - "version": "0.0.14", - "resolved": "https://registry.npmmirror.com/@serverless-devs/utils/-/utils-0.0.14.tgz", - "integrity": "sha512-E+vlcgwdIeRrSb2z20fD8jOANMyHrzS6mHJFwiAv6eKJX0UuH1um3dKqlrYwpjKzamERs4pT4IzGp/KB7jgXfw==", + "version": "0.0.18", + "resolved": "https://registry.npmjs.org/@serverless-devs/utils/-/utils-0.0.18.tgz", + "integrity": "sha512-zLfQFt8OtfNG6nZ3yWvKI4mU8W6X1CHNKmP+j9bW8+3rH98HXA9UOgmB/8YQjRLI7rZV50IghSorIeUZYStDoQ==", "requires": { "js-yaml": "^4.1.0", "lodash": "^4.17.21", @@ -17989,19 +18001,31 @@ } }, "@serverless-devs/load-component": { - "version": "0.0.8", - "resolved": "https://registry.npmmirror.com/@serverless-devs/load-component/-/load-component-0.0.8.tgz", - "integrity": "sha512-T6lkB1rLcpHuIobL7KJw27uJ2RLUbBUzp535MyV6uChTsE0b0OmLkAC0P7fha4mwLBbIokcAGwSUhbUANVrxPQ==", + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/@serverless-devs/load-component/-/load-component-0.0.9.tgz", + "integrity": "sha512-uqBF4QwPtgzOt9/5yg7Rlgv2n8PSuaOH3eDlZTZjpIpovK+jypqk9keIvxe0+x/dxPT98xmkirMENZxKlqkMpQ==", "requires": { "@serverless-cd/debug": "^4.3.4", - "@serverless-devs/downloads": "^0.0.6", - "@serverless-devs/utils": "^0.0.16", + "@serverless-devs/downloads": "^0.0.7", + "@serverless-devs/utils": "^0.0.18", "axios": "^1.4.0", "fs-extra": "^11.1.0", "lodash": "^4.17.21", "semver": "^7.5.4" }, "dependencies": { + "@serverless-devs/utils": { + "version": "0.0.18", + "resolved": "https://registry.npmjs.org/@serverless-devs/utils/-/utils-0.0.18.tgz", + "integrity": "sha512-zLfQFt8OtfNG6nZ3yWvKI4mU8W6X1CHNKmP+j9bW8+3rH98HXA9UOgmB/8YQjRLI7rZV50IghSorIeUZYStDoQ==", + "requires": { + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "md5": "^2.3.0", + "minimist": "^1.2.8", + "random-string": "^0.2.0" + } + }, "axios": { "version": "1.8.4", "resolved": "https://packages.aliyun.com/670e108663cd360abfe4be65/npm/npm-registry/axios/-/axios-1.8.4.tgz", @@ -18053,9 +18077,9 @@ } }, "@serverless-devs/utils": { - "version": "0.0.16", - "resolved": "https://registry.npmmirror.com/@serverless-devs/utils/-/utils-0.0.16.tgz", - "integrity": "sha512-ngiRbIG/yDe2UPtCG3w3dcwVjO76Kq27otroTem5CU3wWNGRBusKCWd0wRdmnY5eVjpnl7vYjTIWb5IgpPWWEA==", + "version": "0.0.17", + "resolved": "https://registry.npmjs.org/@serverless-devs/utils/-/utils-0.0.17.tgz", + "integrity": "sha512-PTkjZyOyZ/ktCe94dWzM2KReH/ne1oDjqR9nZTu8SJ+Rn91GT8V9uPSWe32YJm+4F0UH23KvKYstpAVgS2acEA==", "requires": { "js-yaml": "^4.1.0", "lodash": "^4.17.21", diff --git a/package.json b/package.json index f9ec91b9..7ba171be 100644 --- a/package.json +++ b/package.json @@ -23,15 +23,15 @@ "license": "ISC", "dependencies": { "@alicloud/fc2": "^2.6.6", - "@alicloud/fc20230330": "4.3.2", + "@alicloud/fc20230330": "4.3.3", "@alicloud/pop-core": "^1.8.0", "@serverless-cd/srm-aliyun-pop-core": "^0.0.7-beta.21", "@serverless-cd/srm-aliyun-ram20150501": "^0.0.2-beta.9", "@serverless-cd/srm-aliyun-sls20201230": "0.0.5-beta.3", "@serverless-devs/diff": "^0.0.3-beta.6", - "@serverless-devs/downloads": "^0.0.6", - "@serverless-devs/load-component": "^0.0.8", - "@serverless-devs/utils": "^0.0.16", + "@serverless-devs/downloads": "^0.0.7", + "@serverless-devs/load-component": "^0.0.9", + "@serverless-devs/utils": "^0.0.17", "@serverless-devs/zip": "^0.0.3-beta.8", "ajv": "^8.17.1", "aliyun-sdk": "^1.12.10", diff --git a/src/interface/function.ts b/src/interface/function.ts index 819ff85a..ba0749c5 100644 --- a/src/interface/function.ts +++ b/src/interface/function.ts @@ -5,6 +5,7 @@ export type IRuntime = `${Runtime}`; export interface ILifecycleHook { handler?: string; timeout?: number; + command?: string[]; } export interface IHealthCheckConfig { @@ -125,6 +126,7 @@ export interface IFunction { memorySize?: number; timeout?: number; sessionAffinity?: string; + enableLongLiving?: boolean; logConfig?: 'auto' | ILogConfig; nasConfig?: 'auto' | INasConfig; diff --git a/src/resources/fc/impl/replace-function-config.ts b/src/resources/fc/impl/replace-function-config.ts index 4a21dcb5..304a1959 100644 --- a/src/resources/fc/impl/replace-function-config.ts +++ b/src/resources/fc/impl/replace-function-config.ts @@ -92,50 +92,86 @@ export default function (_local: any, _remote: any) { // 适配钩子函数配置 if (!(_.isEmpty(local?.instanceLifecycleConfig) && _.isEmpty(remote?.instanceLifecycleConfig))) { const { initializer, preStop } = local.instanceLifecycleConfig || {}; + if (initializer?.handler && initializer?.command) { + throw new Error( + 'fc3 pre check: command and handler can not be set at the same time in lifecycle Lifecycle.Initializer', + ); + } + if (preStop?.handler && preStop?.command) { + throw new Error( + 'fc3 pre check: command and handler can not be set at the same time in lifecycle Lifecycle.PreStop', + ); + } const initializerTimeout = _.get(remote, 'instanceLifecycleConfig.initializer.timeout', 3); if ( remote?.instanceLifecycleConfig?.initializer?.handler || + remote?.instanceLifecycleConfig?.initializer?.command || remote?.instanceLifecycleConfig?.initializer?.timeout ) { - if (initializer?.handler) { + if (initializer?.handler || initializer?.command) { + if (remote?.instanceLifecycleConfig?.initializer?.handler && initializer?.command) { + _.set(local, 'instanceLifecycleConfig.initializer.handler', ''); + } + if (remote?.instanceLifecycleConfig?.initializer?.command && initializer?.handler) { + _.set(local, 'instanceLifecycleConfig.initializer.command', []); + } if (!initializer.timeout) { _.set(local, 'instanceLifecycleConfig.initializer.timeout', initializerTimeout); } } else { _.set(local, 'instanceLifecycleConfig.initializer.handler', ''); + _.set(local, 'instanceLifecycleConfig.initializer.command', []); _.set(local, 'instanceLifecycleConfig.initializer.timeout', 3); } - } else if (initializer?.handler && !initializer.timeout) { + } else if ((initializer?.command || initializer?.handler) && !initializer.timeout) { _.set(local, 'instanceLifecycleConfig.initializer.timeout', initializerTimeout); } const preStopTimeout = _.get(remote, 'instanceLifecycleConfig.preStop.timeout', 3); if ( remote?.instanceLifecycleConfig?.preStop?.handler || + remote?.instanceLifecycleConfig?.preStop?.command || remote?.instanceLifecycleConfig?.preStop?.timeout ) { - if (preStop?.handler) { + if (preStop?.handler || preStop?.command) { + if (remote?.instanceLifecycleConfig?.preStop?.handler && preStop?.command) { + _.set(local, 'instanceLifecycleConfig.preStop.handler', ''); + } + if (remote?.instanceLifecycleConfig?.preStop?.command && preStop?.handler) { + _.set(local, 'instanceLifecycleConfig.preStop.command', []); + } if (!preStop.timeout) { _.set(local, 'instanceLifecycleConfig.preStop.timeout', preStopTimeout); } } else { _.set(local, 'instanceLifecycleConfig.preStop.handler', ''); + _.set(local, 'instanceLifecycleConfig.preStop.command', []); _.set(local, 'instanceLifecycleConfig.preStop.timeout', 3); } - } else if (preStop?.handler && !preStop.timeout) { + } else if ((preStop?.command || preStop?.handler) && !preStop.timeout) { _.set(local, 'instanceLifecycleConfig.preStop.timeout', preStopTimeout); } } - // 如果 local 和 remote 都是 handler 为 '', 则从 props 中删除 + // 如果 local 和 remote 都是 handler 和 command 为 '', 则从 props 中删除 if (local?.instanceLifecycleConfig && remote?.instanceLifecycleConfig) { const { initializer: initializerL, preStop: preStopL } = local.instanceLifecycleConfig || {}; const { initializer: initializerR, preStop: preStopR } = remote.instanceLifecycleConfig || {}; - if (initializerL?.handler === initializerR?.handler && initializerL?.handler === '') { + if ( + initializerL?.handler === initializerR?.handler && + initializerL?.handler === '' && + _.isEqual(initializerL?.command, initializerR?.command) && + _.isEmpty(initializerL?.command) + ) { _.unset(local, 'instanceLifecycleConfig.initializer'); _.unset(remote, 'instanceLifecycleConfig.initializer'); } - if (preStopL?.handler === preStopR?.handler && preStopL?.handler === '') { + if ( + preStopL?.handler === preStopR?.handler && + preStopL?.handler === '' && + _.isEqual(preStopL?.command, preStopR?.command) && + _.isEmpty(preStopL?.command) + ) { _.unset(local, 'instanceLifecycleConfig.preStop'); _.unset(remote, 'instanceLifecycleConfig.preStop'); } diff --git a/src/schema.json b/src/schema.json index 0fff8c56..c2c0e880 100644 --- a/src/schema.json +++ b/src/schema.json @@ -509,6 +509,12 @@ }, "ILifecycleHook": { "properties": { + "command": { + "items": { + "type": "string" + }, + "type": "array" + }, "handler": { "type": "string" }, @@ -1148,6 +1154,9 @@ ], "type": "number" }, + "enableLongLiving": { + "type": "boolean" + }, "endpoint": { "type": "string" }, diff --git a/src/subCommands/deploy/impl/function.ts b/src/subCommands/deploy/impl/function.ts index 0915f9cb..38493727 100644 --- a/src/subCommands/deploy/impl/function.ts +++ b/src/subCommands/deploy/impl/function.ts @@ -138,6 +138,10 @@ export default class Service extends Base { return; } + if (_.get(this.remote, 'disableOndemand') === false) { + _.unset(this.remote, 'disableOndemand'); + } + _.unset(this.local, 'endpoint'); const { code } = this.local; _.unset(this.local, 'code'); diff --git a/src/subCommands/plan/index.ts b/src/subCommands/plan/index.ts index 6fee3a67..cdfc9c50 100644 --- a/src/subCommands/plan/index.ts +++ b/src/subCommands/plan/index.ts @@ -115,7 +115,9 @@ export default class Plan { _.unset(local, 'concurrencyConfig'); _.unset(local, 'customContainerConfig.registryConfig'); _.unset(remote, 'functionArn'); - + if (_.get(remote, 'disableOndemand') === false) { + _.unset(remote, 'disableOndemand'); + } const config = FC.replaceFunctionConfig(local, remote); return diffConvertPlanYaml(config.remote, config.local, { deep: 0, complete: true }); }