diff --git a/package-lock.json b/package-lock.json index 3add265..adde186 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,8 +13,10 @@ "@alicloud/openapi-client": "^0.4.12", "@alicloud/ros-cdk-apigateway": "^1.6.0", "@alicloud/ros-cdk-core": "^1.6.0", + "@alicloud/ros-cdk-ecs": "^1.6.0", "@alicloud/ros-cdk-elasticsearchserverless": "^1.6.0", "@alicloud/ros-cdk-fc3": "^1.6.0", + "@alicloud/ros-cdk-nas": "^1.6.0", "@alicloud/ros-cdk-oss": "^1.6.0", "@alicloud/ros-cdk-ossdeployment": "^1.6.0", "@alicloud/ros-cdk-ram": "^1.6.0", @@ -316,6 +318,19 @@ "node": ">=10" } }, + "node_modules/@alicloud/ros-cdk-ecs": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@alicloud/ros-cdk-ecs/-/ros-cdk-ecs-1.6.0.tgz", + "integrity": "sha512-gHizE/xASbErEd3QW8KKrLy8f9BVjZrlALRbtvoScXcgb6CZCA/7Tl0m7u1SeuHZp6gPG0Fb7sbwg6zqx7zy2w==", + "dependencies": { + "@alicloud/ros-cdk-core": "^1.0.27", + "constructs": "^3.0.4" + }, + "peerDependencies": { + "@alicloud/ros-cdk-core": "^1.0.27", + "constructs": "^3.0.4" + } + }, "node_modules/@alicloud/ros-cdk-elasticsearchserverless": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/@alicloud/ros-cdk-elasticsearchserverless/-/ros-cdk-elasticsearchserverless-1.6.0.tgz", @@ -359,6 +374,19 @@ "constructs": "^3.0.4" } }, + "node_modules/@alicloud/ros-cdk-nas": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@alicloud/ros-cdk-nas/-/ros-cdk-nas-1.6.0.tgz", + "integrity": "sha512-ZEIapB61MflrJz+4rNs7uzpXnp+0JAWgKOZZNxySWxHhauEnnRGlk/yiij1vEIqWI5fqahjOz8w3/wrn7WRU1g==", + "dependencies": { + "@alicloud/ros-cdk-core": "^1.0.27", + "constructs": "^3.0.4" + }, + "peerDependencies": { + "@alicloud/ros-cdk-core": "^1.0.27", + "constructs": "^3.0.4" + } + }, "node_modules/@alicloud/ros-cdk-oss": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/@alicloud/ros-cdk-oss/-/ros-cdk-oss-1.6.0.tgz", @@ -4440,7 +4468,8 @@ "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true }, "node_modules/boolean": { "version": "3.2.0", @@ -4456,6 +4485,7 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -4627,6 +4657,7 @@ "version": "3.9.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, "funding": [ { "type": "github", @@ -4707,7 +4738,8 @@ "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true }, "node_modules/constructs": { "version": "3.4.344", @@ -5569,7 +5601,8 @@ "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true }, "node_modules/fsevents": { "version": "2.3.3", @@ -5664,6 +5697,7 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -5717,7 +5751,8 @@ "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true }, "node_modules/graphemer": { "version": "1.4.0", @@ -5729,6 +5764,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, "engines": { "node": ">=8" } @@ -5915,6 +5951,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -6039,7 +6076,8 @@ "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true }, "node_modules/isstream": { "version": "0.1.2", @@ -6977,7 +7015,8 @@ "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true }, "node_modules/json-schema-traverse": { "version": "1.0.0", @@ -7228,6 +7267,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -9967,6 +10007,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -10485,6 +10526,7 @@ "version": "7.6.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, "bin": { "semver": "bin/semver.js" }, @@ -10782,6 +10824,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -11176,6 +11219,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, "dependencies": { "isexe": "^2.0.0" }, @@ -11529,6 +11573,15 @@ } } }, + "@alicloud/ros-cdk-ecs": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@alicloud/ros-cdk-ecs/-/ros-cdk-ecs-1.6.0.tgz", + "integrity": "sha512-gHizE/xASbErEd3QW8KKrLy8f9BVjZrlALRbtvoScXcgb6CZCA/7Tl0m7u1SeuHZp6gPG0Fb7sbwg6zqx7zy2w==", + "requires": { + "@alicloud/ros-cdk-core": "^1.0.27", + "constructs": "^3.0.4" + } + }, "@alicloud/ros-cdk-elasticsearchserverless": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/@alicloud/ros-cdk-elasticsearchserverless/-/ros-cdk-elasticsearchserverless-1.6.0.tgz", @@ -11558,6 +11611,15 @@ "constructs": "^3.0.4" } }, + "@alicloud/ros-cdk-nas": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@alicloud/ros-cdk-nas/-/ros-cdk-nas-1.6.0.tgz", + "integrity": "sha512-ZEIapB61MflrJz+4rNs7uzpXnp+0JAWgKOZZNxySWxHhauEnnRGlk/yiij1vEIqWI5fqahjOz8w3/wrn7WRU1g==", + "requires": { + "@alicloud/ros-cdk-core": "^1.0.27", + "constructs": "^3.0.4" + } + }, "@alicloud/ros-cdk-oss": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/@alicloud/ros-cdk-oss/-/ros-cdk-oss-1.6.0.tgz", @@ -14508,7 +14570,8 @@ "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true }, "boolean": { "version": "3.2.0", @@ -14524,6 +14587,7 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -14629,7 +14693,8 @@ "ci-info": { "version": "3.9.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==" + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true }, "cjs-module-lexer": { "version": "1.2.3", @@ -14688,7 +14753,8 @@ "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true }, "constructs": { "version": "3.4.344", @@ -15317,7 +15383,8 @@ "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true }, "fsevents": { "version": "2.3.3", @@ -15381,6 +15448,7 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -15413,7 +15481,8 @@ "graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true }, "graphemer": { "version": "1.4.0", @@ -15424,7 +15493,8 @@ "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true }, "has-symbols": { "version": "1.1.0", @@ -15556,6 +15626,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, "requires": { "once": "^1.3.0", "wrappy": "1" @@ -15653,7 +15724,8 @@ "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true }, "isstream": { "version": "0.1.2", @@ -16367,7 +16439,8 @@ "json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true }, "json-schema-traverse": { "version": "1.0.0", @@ -16569,6 +16642,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, "requires": { "brace-expansion": "^1.1.7" } @@ -18335,7 +18409,8 @@ "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true }, "path-key": { "version": "3.1.1", @@ -18711,7 +18786,8 @@ "semver": { "version": "7.6.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==" + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true }, "setimmediate": { "version": "1.0.5", @@ -18933,6 +19009,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "requires": { "has-flag": "^4.0.0" } @@ -19189,6 +19266,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, "requires": { "isexe": "^2.0.0" } diff --git a/package.json b/package.json index 3540a72..0d1a947 100644 --- a/package.json +++ b/package.json @@ -53,8 +53,10 @@ "@alicloud/openapi-client": "^0.4.12", "@alicloud/ros-cdk-apigateway": "^1.6.0", "@alicloud/ros-cdk-core": "^1.6.0", + "@alicloud/ros-cdk-ecs": "^1.6.0", "@alicloud/ros-cdk-elasticsearchserverless": "^1.6.0", "@alicloud/ros-cdk-fc3": "^1.6.0", + "@alicloud/ros-cdk-nas": "^1.6.0", "@alicloud/ros-cdk-oss": "^1.6.0", "@alicloud/ros-cdk-ossdeployment": "^1.6.0", "@alicloud/ros-cdk-ram": "^1.6.0", diff --git a/samples/aliyun-poc-fc-gpu.yml b/samples/aliyun-poc-fc-gpu.yml new file mode 100644 index 0000000..a19a7d0 --- /dev/null +++ b/samples/aliyun-poc-fc-gpu.yml @@ -0,0 +1,58 @@ +version: 0.0.1 +provider: + name: aliyun + region: cn-chengdu + +vars: + testv: testVarValue + handler: index.handler + +stages: + default: + node_env: default + dev: + node_env: development + prod: + region: cn-shanghai + +service: insight-poc-gpu + +tags: + owner: geek-fun + +functions: + insight_poc_fn: + name: insight-poc-gpu-fns + code: + runtime: nodejs18 + handler: ${vars.handler} + path: tests/fixtures/artifacts/artifact.zip + container: + image: registry.cn-hangzhou.aliyuncs.com/aliyunfc/runtime/nodejs18:1.8.0 + command: [node, index.handler] + entrypoint: [node] + port: 9000 + memory: 512 + timeout: 10 + network: + vpc_id: vpc-2vc8v9btc8470laqui9bk + subnet_ids: + - vsw-2vc9zrs5mojkxd14yo3zw + - vsw-2vceshdo0xjp9q9t0oyt0 + security_group: + name: insight-poc-gpu-fn-sg + ingress: + - TCP:0.0.0.0/0:80 + - TCP:0.0.0.0/0:443 + - TCP:0.0.0.0/0:22/22 + - ICMP:0.0.0.0/0:ALL + egress: + - ALL:0.0.0.0/0:ALL + storage: + nas: + - mount_path: /mnt/nas + storage_class: STANDARD_CAPACITY + environment: + NODE_ENV: ${stages.node_env} + TEST_VAR: ${vars.testv} + TEST_VAR_EXTRA: abcds-${vars.testv}-andyou diff --git a/src/parser/functionParser.ts b/src/parser/functionParser.ts index bfeafeb..82064f1 100644 --- a/src/parser/functionParser.ts +++ b/src/parser/functionParser.ts @@ -1,4 +1,4 @@ -import { FunctionDomain, FunctionRaw } from '../types'; +import { FunctionDomain, FunctionRaw, NasStorageClassEnum } from '../types'; import { isEmpty } from 'lodash'; export const parseFunction = (functions?: { @@ -17,5 +17,13 @@ export const parseFunction = (functions?: { environment: func.environment, code: func.code, log: func.log, + network: func.network, + storage: { + disk: func.storage?.disk, + nas: func.storage?.nas?.map((nasItem) => ({ + mount_path: nasItem.mount_path, + storage_class: nasItem.storage_class as NasStorageClassEnum, + })), + }, })); }; diff --git a/src/stack/rosStack/function.ts b/src/stack/rosStack/function.ts index aa57dc1..73331d8 100644 --- a/src/stack/rosStack/function.ts +++ b/src/stack/rosStack/function.ts @@ -1,6 +1,7 @@ -import { ActionContext, FunctionDomain, ServerlessIac } from '../../types'; +import { ActionContext, FunctionDomain, NasStorageClassEnum, ServerlessIac } from '../../types'; import { CODE_ZIP_SIZE_LIMIT, + encodeBase64ForRosId, getFileSource, readCodeSize, replaceReference, @@ -11,8 +12,43 @@ import { isEmpty } from 'lodash'; import * as ossDeployment from '@alicloud/ros-cdk-ossdeployment'; import * as ros from '@alicloud/ros-cdk-core'; import * as sls from '@alicloud/ros-cdk-sls'; +import * as nas from '@alicloud/ros-cdk-nas'; +import * as ecs from '@alicloud/ros-cdk-ecs'; import { RosFunction } from '@alicloud/ros-cdk-fc3/lib/fc3.generated'; +const storageClassMap = { + [NasStorageClassEnum.STANDARD_CAPACITY]: { fileSystemType: 'standard', storageType: 'Capacity' }, + [NasStorageClassEnum.STANDARD_PERFORMANCE]: { + fileSystemType: 'standard', + storageType: 'Performance', + }, + [NasStorageClassEnum.EXTREME_STANDARD]: { fileSystemType: 'extreme', storageType: 'standard' }, + [NasStorageClassEnum.EXTREME_ADVANCE]: { fileSystemType: 'extreme', storageType: 'advance' }, +}; +const securityGroupRangeMap: { [key: string]: string } = { + TCP: '1/65535', + UDP: '1/65535', + ICMP: '-1/-1', + GRE: '-1/-1', + ALL: '-1/-1', +}; +const transformSecurityRules = (rules: Array, ruleType: 'INGRESS' | 'EGRESS') => { + return rules.map((rule) => { + const [protocol, cidrIp, portRange] = rule.split(':'); + + return { + ipProtocol: protocol.toLowerCase(), + portRange: + portRange.toUpperCase() === 'ALL' + ? securityGroupRangeMap[protocol.toUpperCase()] + : portRange.includes('/') + ? portRange + : `${portRange}/${portRange}`, + [ruleType === 'INGRESS' ? 'sourceCidrIp' : 'destCidrIp']: cidrIp, + }; + }); +}; + export const resolveFunctions = ( scope: ros.Construct, functions: Array | undefined, @@ -102,6 +138,79 @@ export const resolveFunctions = ( )?.objectKey, }; } + + let vpcConfig: fc.RosFunction.VpcConfigProperty | undefined = undefined; + if (fnc.network) { + const securityGroup = new ecs.SecurityGroup( + scope, + `${fnc.key}_security_group`, + { + securityGroupName: fnc.network.security_group.name, + vpcId: replaceReference(fnc.network.vpc_id, context), + tags: replaceReference(tags, context), + securityGroupIngress: transformSecurityRules( + fnc.network.security_group.ingress, + 'INGRESS', + ), + securityGroupEgress: transformSecurityRules(fnc.network.security_group.egress, 'EGRESS'), + }, + true, + ); + + vpcConfig = { + vpcId: replaceReference(fnc.network.vpc_id, context), + vSwitchIds: replaceReference(fnc.network.subnet_ids, context), + securityGroupId: securityGroup.attrSecurityGroupId, + }; + } + + let fcNas: + | Array<{ nas: nas.FileSystem; nasMount: nas.MountTarget; mountDir: string }> + | undefined; + if (fnc.storage?.nas) { + fcNas = fnc.storage.nas.map((nasItem) => { + const { fileSystemType, storageType } = storageClassMap[nasItem.storage_class]; + const accessGroup = new nas.AccessGroup( + scope, + `${fnc.key}_nas_access_${encodeBase64ForRosId(nasItem.mount_path)}`, + { + accessGroupName: `${fnc.name}-nas-access-${encodeBase64ForRosId(nasItem.mount_path)}`, + accessGroupType: 'Vpc', + }, + true, + ); + + const nasResource = new nas.FileSystem( + scope, + `${fnc.key}_nas_${encodeBase64ForRosId(nasItem.mount_path)}`, + { + fileSystemType, + storageType, + protocolType: 'NFS', + tags: [ + ...(replaceReference(tags, context) ?? []), + { key: 'function-name', value: fnc.name }, + ], + }, + true, + ); + const nasMountTarget = new nas.MountTarget( + scope, + `${fnc.key}_nas_mount_${encodeBase64ForRosId(nasItem.mount_path)}`, + { + fileSystemId: nasResource.attrFileSystemId, + networkType: 'Vpc', + accessGroupName: accessGroup.attrAccessGroupName, + vpcId: fnc.network!.vpc_id, + vSwitchId: fnc.network!.subnet_ids[0], + }, + true, + ); + + return { nas: nasResource, nasMount: nasMountTarget, mountDir: nasItem.mount_path }; + }); + } + const fcn = new fc.RosFunction( scope, fnc.key, @@ -111,9 +220,19 @@ export const resolveFunctions = ( runtime: replaceReference(fnc.runtime, context), memorySize: replaceReference(fnc.memory, context), timeout: replaceReference(fnc.timeout, context), + diskSize: fnc.storage?.disk, environmentVariables: replaceReference(fnc.environment, context), code, logConfig, + vpcConfig, + nasConfig: fcNas?.length + ? { + mountPoints: fcNas?.map(({ nasMount, mountDir }) => ({ + mountDir, + serverAddr: `${nasMount.attrMountTargetDomain}:/`, + })), + } + : undefined, }, true, ); @@ -126,5 +245,10 @@ export const resolveFunctions = ( if (storeInBucket) { fcn.addRosDependency(`${service}_artifacts_code_deployment`); } + if (fcNas?.length) { + fcNas.forEach((nasItem) => { + fcn.addRosDependency(`${fnc.key}_nas_mount_${encodeBase64ForRosId(nasItem.mountDir)}`); + }); + } }); }; diff --git a/src/types/domains/function.ts b/src/types/domains/function.ts index 4b85eef..0ac0492 100644 --- a/src/types/domains/function.ts +++ b/src/types/domains/function.ts @@ -9,8 +9,57 @@ export type FunctionRaw = { environment?: { [key: string]: string; }; + network?: { + vpc_id: string; + subnet_ids: Array; + security_group: { + name: string; + ingress: Array; + egress: Array; + }; + }; + storage?: { + disk?: number; + nas?: Array<{ + mount_path: string; + storage_class: string; + }>; + }; }; -export type FunctionDomain = FunctionRaw & { +export type FunctionDomain = { key: string; + name: string; + runtime: string; + handler: string; + code: string; + memory: number; + timeout: number; + log?: boolean; + environment?: { + [key: string]: string; + }; + network?: { + vpc_id: string; + subnet_ids: Array; + security_group: { + name: string; + ingress: Array; + egress: Array; + }; + }; + storage: { + disk?: number; + nas?: Array<{ + mount_path: string; + storage_class: NasStorageClassEnum; + }>; + }; }; + +export enum NasStorageClassEnum { + STANDARD_PERFORMANCE = 'STANDARD_PERFORMANCE', + STANDARD_CAPACITY = 'STANDARD_CAPACITY', + EXTREME_STANDARD = 'EXTREME_STANDARD', + EXTREME_ADVANCE = 'EXTREME_ADVANCE', +} diff --git a/src/validator/functionSchema.ts b/src/validator/functionSchema.ts index 0fd976c..8c1d10a 100644 --- a/src/validator/functionSchema.ts +++ b/src/validator/functionSchema.ts @@ -37,6 +37,50 @@ export const functionSchema = { type: ['string', 'number', 'boolean'], }, }, + network: { + type: 'object', + properties: { + vpc_id: { type: 'string' }, + subnet_ids: { type: 'array', items: { type: 'string' } }, + security_group: { + type: 'object', + properties: { + name: { type: 'string' }, + ingress: { type: 'array', items: { type: 'string' } }, + egress: { type: 'array', items: { type: 'string' } }, + }, + required: ['name', 'ingress'], + additionalProperties: false, + }, + }, + required: ['vpc_id', 'subnet_ids', 'security_group'], + }, + storage: { + type: 'object', + properties: { + disk: { type: 'number' }, + nas: { + type: 'array', + items: { + type: 'object', + properties: { + mount_path: { type: 'string' }, + storage_class: { + type: 'string', + enum: [ + 'STANDARD_PERFORMANCE', + 'STANDARD_CAPACITY', + 'EXTREME_STANDARD', + 'EXTREME_ADVANCE', + ], + }, + additionalProperties: false, + }, + required: ['mount_path', 'storage_class'], + }, + }, + }, + }, }, additionalProperties: false, }, diff --git a/tests/fixtures/deployFixture.ts b/tests/fixtures/deployFixture.ts index da541f2..adac1e7 100644 --- a/tests/fixtures/deployFixture.ts +++ b/tests/fixtures/deployFixture.ts @@ -31,6 +31,7 @@ export const oneFcOneGatewayIac = { environment: { NODE_ENV: 'production', }, + storage: {}, }, ], events: [ @@ -552,6 +553,7 @@ export const oneFcIac = { environment: { NODE_ENV: 'production', }, + storage: {}, }, ], tags: [ @@ -656,6 +658,162 @@ export const oneFcRos = { }, }; +export const oneFcIacWithNas = { + ...oneFcIac, + functions: [ + { + ...((oneFcIac.functions && oneFcIac.functions[0]) ?? {}), + network: { + vpc_id: 'vpc-123456', + subnet_ids: ['subnet-123456', 'subnet-67890', 'subnet-98765'], + security_group: { + name: 'my-security-group', + ingress: [ + 'TCP:0.0.0.0/0:80', + 'TCP:0.0.0.0/0:443', + 'TCP:0.0.0.0/0:22/22', + 'ICMP:0.0.0.0/0:ALL', + ], + egress: ['ALL:0.0.0.0/0:ALL'], + }, + }, + storage: { + nas: [ + { + mount_path: '/mnt/nas', + storage_class: 'STANDARD_CAPACITY', + }, + ], + }, + }, + ], +} as ServerlessIac; +export const oneFcIacWithNasRos = { + ...oneFcRos, + Resources: { + ...oneFcRos.Resources, + hello_fn: { + Type: 'ALIYUN::FC3::Function', + Properties: { + ...oneFcRos.Resources.hello_fn.Properties, + NasConfig: { + MountPoints: [ + { + MountDir: '/mnt/nas', + ServerAddr: { + 'Fn::Join': [ + '', + [ + { + 'Fn::GetAtt': ['hello_fn_nas_mount_L21udC9uYXM', 'MountTargetDomain'], + }, + ':/', + ], + ], + }, + }, + ], + }, + VpcConfig: { + SecurityGroupId: { + 'Fn::GetAtt': ['hello_fn_security_group', 'SecurityGroupId'], + }, + VSwitchIds: ['subnet-123456', 'subnet-67890', 'subnet-98765'], + VpcId: 'vpc-123456', + }, + }, + DependsOn: [ + 'my-demo-service_sls', + 'my-demo-service_sls_logstore', + 'my-demo-service_sls_index', + 'hello_fn_nas_mount_L21udC9uYXM', + ], + }, + hello_fn_nas_L21udC9uYXM: { + Properties: { + DeletionForce: false, + FileSystemType: 'standard', + ProtocolType: 'NFS', + StorageType: 'Capacity', + Tags: [ + { + Key: 'owner', + Value: 'geek-fun', + }, + { + Key: 'function-name', + Value: 'hello_fn', + }, + ], + }, + Type: 'ALIYUN::NAS::FileSystem', + }, + hello_fn_nas_access_L21udC9uYXM: { + Properties: { + AccessGroupName: 'hello_fn-nas-access-L21udC9uYXM', + AccessGroupType: 'Vpc', + FileSystemType: 'standard', + }, + Type: 'ALIYUN::NAS::AccessGroup', + }, + hello_fn_nas_mount_L21udC9uYXM: { + Properties: { + AccessGroupName: { + 'Fn::GetAtt': ['hello_fn_nas_access_L21udC9uYXM', 'AccessGroupName'], + }, + FileSystemId: { + 'Fn::GetAtt': ['hello_fn_nas_L21udC9uYXM', 'FileSystemId'], + }, + NetworkType: 'Vpc', + VSwitchId: 'subnet-123456', + VpcId: 'vpc-123456', + }, + Type: 'ALIYUN::NAS::MountTarget', + }, + hello_fn_security_group: { + Properties: { + SecurityGroupEgress: [ + { + DestCidrIp: '0.0.0.0/0', + IpProtocol: 'all', + PortRange: '-1/-1', + }, + ], + SecurityGroupIngress: [ + { + IpProtocol: 'tcp', + PortRange: '80/80', + SourceCidrIp: '0.0.0.0/0', + }, + { + IpProtocol: 'tcp', + PortRange: '443/443', + SourceCidrIp: '0.0.0.0/0', + }, + { + IpProtocol: 'tcp', + PortRange: '22/22', + SourceCidrIp: '0.0.0.0/0', + }, + { + IpProtocol: 'icmp', + PortRange: '-1/-1', + SourceCidrIp: '0.0.0.0/0', + }, + ], + SecurityGroupName: 'my-security-group', + Tags: [ + { + Key: 'owner', + Value: 'geek-fun', + }, + ], + VpcId: 'vpc-123456', + }, + Type: 'ALIYUN::ECS::SecurityGroup', + }, + }, +}; export const oneFcIacWithStage = { service: 'my-demo-service', version: '0.0.1', @@ -689,6 +847,7 @@ export const oneFcIacWithStage = { environment: { NODE_ENV: '${stages.node_env}', }, + storage: {}, }, ], tags: [ diff --git a/tests/stack/deploy.test.ts b/tests/stack/deploy.test.ts index 9096a51..f6e2289 100644 --- a/tests/stack/deploy.test.ts +++ b/tests/stack/deploy.test.ts @@ -11,6 +11,8 @@ import { minimumIac, minimumRos, oneFcIac, + oneFcIacWithNas, + oneFcIacWithNasRos, oneFcIacWithStage, oneFcOneGatewayIac, oneFcOneGatewayRos, @@ -212,4 +214,20 @@ describe('Unit tests for stack deployment', () => { ]); }); }); + + describe('unit test for function nas attachment', () => { + it('should deploy function with nas when nas field is provided', async () => { + const stackName = 'my-demo-stack-with-nas'; + mockedRosStackDeploy.mockResolvedValue(stackName); + + await deployStack(stackName, oneFcIacWithNas, { stackName } as ActionContext); + + expect(mockedRosStackDeploy).toHaveBeenCalledTimes(2); + expect(mockedRosStackDeploy.mock.calls[1]).toEqual([ + stackName, + oneFcIacWithNasRos, + { stackName }, + ]); + }); + }); });