From cd0a58790b583da4dd6cac1e81bf7dea486560b5 Mon Sep 17 00:00:00 2001 From: seven Date: Sat, 21 Sep 2024 16:46:08 +0800 Subject: [PATCH] feat: deployment action calling aliyun ok Signed-off-by: seven --- package-lock.json | 334 +++++++++++++++++++++++++++++++++++- package.json | 2 + src/commands/deploy.ts | 10 +- src/commands/index.ts | 14 +- src/commands/validate.ts | 4 +- src/common/actionContext.ts | 25 +++ src/common/index.ts | 1 + src/common/rosClient.ts | 102 +++++++++++ src/iac/parse.ts | 10 +- src/stack/deploy.ts | 29 +++- src/types.ts | 10 ++ 11 files changed, 513 insertions(+), 28 deletions(-) create mode 100644 src/common/actionContext.ts create mode 100644 src/common/rosClient.ts diff --git a/package-lock.json b/package-lock.json index 67d9b99b..fab15d54 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,8 +9,10 @@ "version": "0.0.1", "license": "Apache-2.0", "dependencies": { + "@alicloud/openapi-client": "^0.4.11", "@alicloud/ros-cdk-core": "^1.2.0", "@alicloud/ros-cdk-fc": "^1.2.0", + "@alicloud/ros20190910": "^3.4.3", "ajv": "^8.17.1", "chalk": "^4.1.2", "commander": "^11.1.0", @@ -47,6 +49,59 @@ "node": ">=0.10.0" } }, + "node_modules/@alicloud/credentials": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@alicloud/credentials/-/credentials-2.3.1.tgz", + "integrity": "sha512-FK8N1YNVqUGOl7qOFn8h3zTwv2Tj8ON3459XXnJkAa08YBECj8o/V81D/ubxpX0yZub4RVKjknxNSHEbrASc+A==", + "dependencies": { + "@alicloud/tea-typescript": "^1.5.3", + "httpx": "^2.2.0", + "ini": "^1.3.5", + "kitx": "^2.0.0" + } + }, + "node_modules/@alicloud/endpoint-util": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/@alicloud/endpoint-util/-/endpoint-util-0.0.1.tgz", + "integrity": "sha512-+pH7/KEXup84cHzIL6UJAaPqETvln4yXlD9JzlrqioyCSaWxbug5FUobsiI6fuUOpw5WwoB3fWAtGbFnJ1K3Yg==", + "dependencies": { + "@alicloud/tea-typescript": "^1.5.1", + "kitx": "^2.0.0" + } + }, + "node_modules/@alicloud/gateway-spi": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@alicloud/gateway-spi/-/gateway-spi-0.0.8.tgz", + "integrity": "sha512-KM7fu5asjxZPmrz9sJGHJeSU+cNQNOxW+SFmgmAIrITui5hXL2LB+KNRuzWmlwPjnuA2X3/keq9h6++S9jcV5g==", + "dependencies": { + "@alicloud/credentials": "^2", + "@alicloud/tea-typescript": "^1.7.1" + } + }, + "node_modules/@alicloud/openapi-client": { + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/@alicloud/openapi-client/-/openapi-client-0.4.11.tgz", + "integrity": "sha512-WEDGbfSx4Lcjj7ij3fv+6HBDua3l0tMGott6jaFO+pI42ctTJlK/y/AcyjFGwrf1UCQneauI2gEo6+5hHbv4Bg==", + "dependencies": { + "@alicloud/credentials": "^2", + "@alicloud/gateway-spi": "^0.0.8", + "@alicloud/openapi-util": "^0.3.2", + "@alicloud/tea-typescript": "^1.7.1", + "@alicloud/tea-util": "^1.4.9", + "@alicloud/tea-xml": "0.0.3" + } + }, + "node_modules/@alicloud/openapi-util": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@alicloud/openapi-util/-/openapi-util-0.3.2.tgz", + "integrity": "sha512-EC2JvxdcOgMlBAEG0+joOh2IB1um8CPz9EdYuRfTfd1uP8Yc9D8QRUWVGjP6scnj6fWSOaHFlit9H6PrJSyFow==", + "dependencies": { + "@alicloud/tea-typescript": "^1.7.1", + "@alicloud/tea-util": "^1.3.0", + "kitx": "^2.1.0", + "sm3": "^1.0.3" + } + }, "node_modules/@alicloud/ros-cdk-assembly-schema": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@alicloud/ros-cdk-assembly-schema/-/ros-cdk-assembly-schema-1.2.0.tgz", @@ -1074,6 +1129,51 @@ "node": ">=0.4" } }, + "node_modules/@alicloud/ros20190910": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/@alicloud/ros20190910/-/ros20190910-3.4.3.tgz", + "integrity": "sha512-8RLydC/GrS9UqOlLcTTr+RXzvGXE86Ql0Von4wTJc8uQs0sKyuphNerVLNwO7rH1EAdtlyUStFxL3o686wtfVw==", + "dependencies": { + "@alicloud/endpoint-util": "^0.0.1", + "@alicloud/openapi-client": "^0.4.11", + "@alicloud/openapi-util": "^0.3.2", + "@alicloud/tea-typescript": "^1.7.1", + "@alicloud/tea-util": "^1.4.9" + } + }, + "node_modules/@alicloud/tea-typescript": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@alicloud/tea-typescript/-/tea-typescript-1.8.0.tgz", + "integrity": "sha512-CWXWaquauJf0sW30mgJRVu9aaXyBth5uMBCUc+5vKTK1zlgf3hIqRUjJZbjlwHwQ5y9anwcu18r48nOZb7l2QQ==", + "dependencies": { + "@types/node": "^12.0.2", + "httpx": "^2.2.6" + } + }, + "node_modules/@alicloud/tea-typescript/node_modules/@types/node": { + "version": "12.20.55", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", + "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==" + }, + "node_modules/@alicloud/tea-util": { + "version": "1.4.9", + "resolved": "https://registry.npmjs.org/@alicloud/tea-util/-/tea-util-1.4.9.tgz", + "integrity": "sha512-S0wz76rGtoPKskQtRTGqeuqBHFj8BqUn0Vh+glXKun2/9UpaaaWmuJwcmtImk6bJZfLYEShDF/kxDmDJoNYiTw==", + "dependencies": { + "@alicloud/tea-typescript": "^1.5.1", + "kitx": "^2.0.0" + } + }, + "node_modules/@alicloud/tea-xml": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@alicloud/tea-xml/-/tea-xml-0.0.3.tgz", + "integrity": "sha512-+/9GliugjrLglsXVrd1D80EqqKgGpyA0eQ6+1ZdUOYCaRguaSwz44trX3PaxPu/HhIPJg9PsGQQ3cSLXWZjbAA==", + "dependencies": { + "@alicloud/tea-typescript": "^1", + "@types/xml2js": "^0.4.5", + "xml2js": "^0.6.0" + } + }, "node_modules/@ampproject/remapping": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", @@ -2552,7 +2652,6 @@ "version": "20.11.5", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.5.tgz", "integrity": "sha512-g557vgQjUUfN76MZAN/dt1z3dzcUsimuysco0KeluHgrPdJXkP/XdAURgyO2W9fZWHRtRBiVKzKn8vyOAwlG+w==", - "dev": true, "dependencies": { "undici-types": "~5.26.4" } @@ -2569,6 +2668,14 @@ "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", "dev": true }, + "node_modules/@types/xml2js": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/@types/xml2js/-/xml2js-0.4.14.tgz", + "integrity": "sha512-4YnrRemBShWRO2QjvUin8ESA41rH+9nQGLUGZV/1IDhi3SL9OhdpNC/MrulTWuptXKwhx/aDxE7toV0f/ypIXQ==", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/yargs": { "version": "17.0.32", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", @@ -4158,6 +4265,15 @@ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, + "node_modules/httpx": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/httpx/-/httpx-2.3.2.tgz", + "integrity": "sha512-ZG7QArW/BB/opy+XVp/zSJYdiPD9FTmPb3VfMnPdAknKFJq2OiIXS9D4oBeDJvWnZnJAzXDy9J/JKATXkJ7qlw==", + "dependencies": { + "@types/node": "^20", + "debug": "^4.1.1" + } + }, "node_modules/human-signals": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", @@ -4289,6 +4405,11 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -5062,6 +5183,19 @@ "node": ">=6" } }, + "node_modules/kitx": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/kitx/-/kitx-2.1.0.tgz", + "integrity": "sha512-C/5v9MtIX7aHGOjwn5BmrrbNkJSf7i0R5mRzmh13GSAdRqQ7bYQo/Su2pTYNylFicqKNTVX3HML9k1u8k51+pQ==", + "dependencies": { + "@types/node": "^12.0.2" + } + }, + "node_modules/kitx/node_modules/@types/node": { + "version": "12.20.55", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", + "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==" + }, "node_modules/kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", @@ -5893,6 +6027,11 @@ "node": ">=10" } }, + "node_modules/sax": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", + "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==" + }, "node_modules/semver": { "version": "7.5.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", @@ -5950,6 +6089,11 @@ "node": ">=8" } }, + "node_modules/sm3": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sm3/-/sm3-1.0.3.tgz", + "integrity": "sha512-KyFkIfr8QBlFG3uc3NaljaXdYcsbRy1KrSfc4tsQV8jW68jAktGeOcifu530Vx/5LC+PULHT0Rv8LiI8Gw+c1g==" + }, "node_modules/sonic-boom": { "version": "3.8.0", "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.8.0.tgz", @@ -6336,8 +6480,7 @@ "node_modules/undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" }, "node_modules/update-browserslist-db": { "version": "1.0.13", @@ -6458,6 +6601,26 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, + "node_modules/xml2js": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz", + "integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "engines": { + "node": ">=4.0" + } + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -6540,6 +6703,59 @@ "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", "dev": true }, + "@alicloud/credentials": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@alicloud/credentials/-/credentials-2.3.1.tgz", + "integrity": "sha512-FK8N1YNVqUGOl7qOFn8h3zTwv2Tj8ON3459XXnJkAa08YBECj8o/V81D/ubxpX0yZub4RVKjknxNSHEbrASc+A==", + "requires": { + "@alicloud/tea-typescript": "^1.5.3", + "httpx": "^2.2.0", + "ini": "^1.3.5", + "kitx": "^2.0.0" + } + }, + "@alicloud/endpoint-util": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/@alicloud/endpoint-util/-/endpoint-util-0.0.1.tgz", + "integrity": "sha512-+pH7/KEXup84cHzIL6UJAaPqETvln4yXlD9JzlrqioyCSaWxbug5FUobsiI6fuUOpw5WwoB3fWAtGbFnJ1K3Yg==", + "requires": { + "@alicloud/tea-typescript": "^1.5.1", + "kitx": "^2.0.0" + } + }, + "@alicloud/gateway-spi": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@alicloud/gateway-spi/-/gateway-spi-0.0.8.tgz", + "integrity": "sha512-KM7fu5asjxZPmrz9sJGHJeSU+cNQNOxW+SFmgmAIrITui5hXL2LB+KNRuzWmlwPjnuA2X3/keq9h6++S9jcV5g==", + "requires": { + "@alicloud/credentials": "^2", + "@alicloud/tea-typescript": "^1.7.1" + } + }, + "@alicloud/openapi-client": { + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/@alicloud/openapi-client/-/openapi-client-0.4.11.tgz", + "integrity": "sha512-WEDGbfSx4Lcjj7ij3fv+6HBDua3l0tMGott6jaFO+pI42ctTJlK/y/AcyjFGwrf1UCQneauI2gEo6+5hHbv4Bg==", + "requires": { + "@alicloud/credentials": "^2", + "@alicloud/gateway-spi": "^0.0.8", + "@alicloud/openapi-util": "^0.3.2", + "@alicloud/tea-typescript": "^1.7.1", + "@alicloud/tea-util": "^1.4.9", + "@alicloud/tea-xml": "0.0.3" + } + }, + "@alicloud/openapi-util": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@alicloud/openapi-util/-/openapi-util-0.3.2.tgz", + "integrity": "sha512-EC2JvxdcOgMlBAEG0+joOh2IB1um8CPz9EdYuRfTfd1uP8Yc9D8QRUWVGjP6scnj6fWSOaHFlit9H6PrJSyFow==", + "requires": { + "@alicloud/tea-typescript": "^1.7.1", + "@alicloud/tea-util": "^1.3.0", + "kitx": "^2.1.0", + "sm3": "^1.0.3" + } + }, "@alicloud/ros-cdk-assembly-schema": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@alicloud/ros-cdk-assembly-schema/-/ros-cdk-assembly-schema-1.2.0.tgz", @@ -7215,6 +7431,53 @@ } } }, + "@alicloud/ros20190910": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/@alicloud/ros20190910/-/ros20190910-3.4.3.tgz", + "integrity": "sha512-8RLydC/GrS9UqOlLcTTr+RXzvGXE86Ql0Von4wTJc8uQs0sKyuphNerVLNwO7rH1EAdtlyUStFxL3o686wtfVw==", + "requires": { + "@alicloud/endpoint-util": "^0.0.1", + "@alicloud/openapi-client": "^0.4.11", + "@alicloud/openapi-util": "^0.3.2", + "@alicloud/tea-typescript": "^1.7.1", + "@alicloud/tea-util": "^1.4.9" + } + }, + "@alicloud/tea-typescript": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@alicloud/tea-typescript/-/tea-typescript-1.8.0.tgz", + "integrity": "sha512-CWXWaquauJf0sW30mgJRVu9aaXyBth5uMBCUc+5vKTK1zlgf3hIqRUjJZbjlwHwQ5y9anwcu18r48nOZb7l2QQ==", + "requires": { + "@types/node": "^12.0.2", + "httpx": "^2.2.6" + }, + "dependencies": { + "@types/node": { + "version": "12.20.55", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", + "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==" + } + } + }, + "@alicloud/tea-util": { + "version": "1.4.9", + "resolved": "https://registry.npmjs.org/@alicloud/tea-util/-/tea-util-1.4.9.tgz", + "integrity": "sha512-S0wz76rGtoPKskQtRTGqeuqBHFj8BqUn0Vh+glXKun2/9UpaaaWmuJwcmtImk6bJZfLYEShDF/kxDmDJoNYiTw==", + "requires": { + "@alicloud/tea-typescript": "^1.5.1", + "kitx": "^2.0.0" + } + }, + "@alicloud/tea-xml": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@alicloud/tea-xml/-/tea-xml-0.0.3.tgz", + "integrity": "sha512-+/9GliugjrLglsXVrd1D80EqqKgGpyA0eQ6+1ZdUOYCaRguaSwz44trX3PaxPu/HhIPJg9PsGQQ3cSLXWZjbAA==", + "requires": { + "@alicloud/tea-typescript": "^1", + "@types/xml2js": "^0.4.5", + "xml2js": "^0.6.0" + } + }, "@ampproject/remapping": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", @@ -8396,7 +8659,6 @@ "version": "20.11.5", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.5.tgz", "integrity": "sha512-g557vgQjUUfN76MZAN/dt1z3dzcUsimuysco0KeluHgrPdJXkP/XdAURgyO2W9fZWHRtRBiVKzKn8vyOAwlG+w==", - "dev": true, "requires": { "undici-types": "~5.26.4" } @@ -8413,6 +8675,14 @@ "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", "dev": true }, + "@types/xml2js": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/@types/xml2js/-/xml2js-0.4.14.tgz", + "integrity": "sha512-4YnrRemBShWRO2QjvUin8ESA41rH+9nQGLUGZV/1IDhi3SL9OhdpNC/MrulTWuptXKwhx/aDxE7toV0f/ypIXQ==", + "requires": { + "@types/node": "*" + } + }, "@types/yargs": { "version": "17.0.32", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", @@ -9505,6 +9775,15 @@ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, + "httpx": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/httpx/-/httpx-2.3.2.tgz", + "integrity": "sha512-ZG7QArW/BB/opy+XVp/zSJYdiPD9FTmPb3VfMnPdAknKFJq2OiIXS9D4oBeDJvWnZnJAzXDy9J/JKATXkJ7qlw==", + "requires": { + "@types/node": "^20", + "debug": "^4.1.1" + } + }, "human-signals": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", @@ -9583,6 +9862,11 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -10170,6 +10454,21 @@ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true }, + "kitx": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/kitx/-/kitx-2.1.0.tgz", + "integrity": "sha512-C/5v9MtIX7aHGOjwn5BmrrbNkJSf7i0R5mRzmh13GSAdRqQ7bYQo/Su2pTYNylFicqKNTVX3HML9k1u8k51+pQ==", + "requires": { + "@types/node": "^12.0.2" + }, + "dependencies": { + "@types/node": { + "version": "12.20.55", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", + "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==" + } + } + }, "kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", @@ -10753,6 +11052,11 @@ "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz", "integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==" }, + "sax": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", + "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==" + }, "semver": { "version": "7.5.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", @@ -10795,6 +11099,11 @@ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true }, + "sm3": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sm3/-/sm3-1.0.3.tgz", + "integrity": "sha512-KyFkIfr8QBlFG3uc3NaljaXdYcsbRy1KrSfc4tsQV8jW68jAktGeOcifu530Vx/5LC+PULHT0Rv8LiI8Gw+c1g==" + }, "sonic-boom": { "version": "3.8.0", "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.8.0.tgz", @@ -11053,8 +11362,7 @@ "undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" }, "update-browserslist-db": { "version": "1.0.13", @@ -11137,6 +11445,20 @@ "signal-exit": "^3.0.7" } }, + "xml2js": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz", + "integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==", + "requires": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + } + }, + "xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==" + }, "y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", diff --git a/package.json b/package.json index f902b156..528bfcc7 100644 --- a/package.json +++ b/package.json @@ -49,8 +49,10 @@ "function" ], "dependencies": { + "@alicloud/openapi-client": "^0.4.11", "@alicloud/ros-cdk-core": "^1.2.0", "@alicloud/ros-cdk-fc": "^1.2.0", + "@alicloud/ros20190910": "^3.4.3", "ajv": "^8.17.1", "chalk": "^4.1.2", "commander": "^11.1.0", diff --git a/src/commands/deploy.ts b/src/commands/deploy.ts index 7224178c..d2c81fb1 100644 --- a/src/commands/deploy.ts +++ b/src/commands/deploy.ts @@ -1,13 +1,17 @@ import { deployStack } from '../stack'; import { printer } from '../common'; import { parseYaml } from '../iac'; +import { constructActionContext } from '../common/actionContext'; -export const deploy = (location?: string) => { +export const deploy = async (stackName: string, options: { location: string }) => { + const context = constructActionContext({ location: options.location }); + printer.info(`Deploying stack context: ${JSON.stringify(context)}...`); printer.info('Validating yaml...'); - const iac = parseYaml(location); + const iac = parseYaml(context.iacLocation); printer.success('Yaml is valid! 🎉'); printer.info('Deploying stack...'); - deployStack(iac); + await deployStack(stackName, iac, context); + printer.success('Stack deployed! 🎉'); }; diff --git a/src/commands/index.ts b/src/commands/index.ts index dc9b1126..fcba92e7 100644 --- a/src/commands/index.ts +++ b/src/commands/index.ts @@ -23,19 +23,21 @@ program }); program - .command('validate [location]') + .command('validate [stackName]') .description('validate serverless Iac yaml') - .action((location) => { + .option('-f, --file ', 'specify the yaml file') + .action((stackName, options) => { logger.debug('log command info'); - validate(location); + validate(options.file); }); program - .command('deploy [location]') + .command('deploy ') .description('deploy serverless Iac yaml') - .action((location) => { + .option('-f, --file ', 'specify the yaml file') + .action(async (stackName, options) => { logger.debug('log command info'); - deploy(location); + await deploy(stackName, { location: options.file }); }); program.parse(); diff --git a/src/commands/validate.ts b/src/commands/validate.ts index b8392bef..c63eb1b2 100644 --- a/src/commands/validate.ts +++ b/src/commands/validate.ts @@ -1,7 +1,9 @@ import { parseYaml } from '../iac'; import { printer } from '../common'; +import { constructActionContext } from '../common/actionContext'; export const validate = (location?: string) => { - parseYaml(location); + const context = constructActionContext({ location }); + parseYaml(context.iacLocation); printer.success('Yaml is valid! 🎉'); }; diff --git a/src/common/actionContext.ts b/src/common/actionContext.ts new file mode 100644 index 00000000..012d7494 --- /dev/null +++ b/src/common/actionContext.ts @@ -0,0 +1,25 @@ +import { ActionContext } from '../types'; +import path from 'node:path'; + +export const constructActionContext = (config?: { + region?: string; + account?: string; + accessKeyId?: string; + accessKeySecret?: string; + securityToken?: string; + location?: string; +}): ActionContext => { + return { + region: + config?.region ?? process.env.ROS_REGION_ID ?? process.env.ALIYUN_REGION ?? 'cn-hangzhou', + accessKeyId: config?.accessKeyId ?? (process.env.ALIYUN_ACCESS_KEY_ID as string), + accessKeySecret: config?.accessKeySecret ?? (process.env.ALIYUN_ACCESS_KEY_SECRET as string), + securityToken: config?.securityToken ?? process.env.ALIYUN_SECURITY_TOKEN, + iacLocation: (() => { + const projectRoot = path.resolve(process.cwd()); + return config?.location + ? path.resolve(projectRoot, config?.location) + : path.resolve(projectRoot, 'serverless-insight.yml'); + })(), + }; +}; diff --git a/src/common/index.ts b/src/common/index.ts index 2b2da2a2..dd7f9bad 100644 --- a/src/common/index.ts +++ b/src/common/index.ts @@ -2,3 +2,4 @@ export * from './printer'; export * from './provider'; export * from './logger'; export * from './getVersion'; +export * from './rosClient'; diff --git a/src/common/rosClient.ts b/src/common/rosClient.ts new file mode 100644 index 00000000..dc04c28e --- /dev/null +++ b/src/common/rosClient.ts @@ -0,0 +1,102 @@ +import Util from '@alicloud/tea-util'; +import ROS20190910, { + CreateStackRequest, + CreateStackRequestParameters, + CreateStackRequestTags, + ListStacksRequest, +} from '@alicloud/ros20190910'; +import { Config } from '@alicloud/openapi-client'; +import { ActionContext } from '../types'; +import { printer } from './printer'; + +const client = new ROS20190910( + new Config({ + accessKeyId: process.env.ALIYUN_ACCESS_KEY_ID, + accessKeySecret: process.env.ALIYUN_ACCESS_KEY_SECRET, + regionId: process.env.ALIYUN_REGION, + disableRollback: false, + }), +); + +const createStack = async (stackName: string, templateBody: unknown, context: ActionContext) => { + const parameters = context.parameters?.map( + (parameter) => + new CreateStackRequestParameters({ + parameterKey: Util.assertAsString(parameter.key), + parameterValue: Util.assertAsString(parameter.value), + }), + ); + + const createStackRequest = new CreateStackRequest({ + regionId: context.region, + stackName, + templateBody: JSON.stringify(templateBody), + parameters, + tags: context.tags?.map((tag) => new CreateStackRequestTags(tag)), + }); + + console.log('createStackRequest:', createStackRequest); + + const response = await client.createStack(createStackRequest); + console.log(`创建中,资源栈ID:${response.body?.stackId}`); + return response.body?.stackId; +}; + +const updateStack = async (stackName: string, templateBody: unknown, context: ActionContext) => { + const parameters = context.parameters?.map( + (parameter) => + new CreateStackRequestParameters({ + parameterKey: Util.assertAsString(parameter.key), + parameterValue: Util.assertAsString(parameter.value), + }), + ); + + const createStackRequest = new CreateStackRequest({ + stackName, + templateBody, + parameters, + }); + + const response = await client.updateStack(createStackRequest); + console.log(`更新中,资源栈ID:${response.body?.stackId}`); + return response.body?.stackId; +}; + +const getStackByName = async (stackName: string, region: string) => { + const result = await client.listStacks( + new ListStacksRequest({ + regionId: region, + pageSize: 10, + pageNumber: 1, + stackName: [stackName], + }), + ); + + if (result.statusCode === 200) { + return result.body?.stacks?.[0]; + } else { + return null; + } +}; + +export const rosStackDeploy = async ( + stackName: string, + templateBody: unknown, + context: ActionContext, +) => { + const stackInfo = await getStackByName(stackName, context.region); + if (stackInfo) { + const { Status: stackStatus } = stackInfo; + if (stackStatus?.indexOf('IN_PROGRESS') >= 0) { + printer.error(`fail to update stack, because stack status is ${stackStatus}`); + throw new Error(`fail to update stack, because stack status is ${stackStatus}`); + } + + printer.info(`Update stack: ${stackName} deploying... `); + return await updateStack(stackName, templateBody, context); + } else { + // create stack + printer.info(`Create stack: ${stackName} deploying... `); + return await createStack(stackName, templateBody, context); + } +}; diff --git a/src/iac/parse.ts b/src/iac/parse.ts index 798b73e9..ea1d59e0 100644 --- a/src/iac/parse.ts +++ b/src/iac/parse.ts @@ -1,8 +1,7 @@ import { parse } from 'yaml'; import { existsSync, readFileSync } from 'node:fs'; -import { IacFunction, RawServerlessIac, ServerlessIac, Event } from '../types'; +import { Event, IacFunction, RawServerlessIac, ServerlessIac } from '../types'; import { validateYaml } from './iacSchema'; -import path from 'node:path'; const mapToArr = (obj: Record | string>) => { return Object.entries(obj).map(([key, value]) => @@ -29,12 +28,7 @@ const transformYaml = (iacJson: RawServerlessIac): ServerlessIac => { }; }; -export const parseYaml = (location?: string): ServerlessIac => { - const projectRoot = path.resolve(process.cwd()); - const yamlPath = location - ? path.resolve(projectRoot, location) - : path.resolve(projectRoot, 'serverless-insight.yml'); - +export const parseYaml = (yamlPath: string): ServerlessIac => { validateExistence(yamlPath); const yamlContent = readFileSync(yamlPath, 'utf8'); diff --git a/src/stack/deploy.ts b/src/stack/deploy.ts index 71781e2d..50088144 100644 --- a/src/stack/deploy.ts +++ b/src/stack/deploy.ts @@ -1,6 +1,7 @@ import * as ros from '@alicloud/ros-cdk-core'; import * as fc from '@alicloud/ros-cdk-fc'; -import { ServerlessIac } from '../types'; +import { ActionContext, ServerlessIac } from '../types'; +import { printer, rosStackDeploy } from '../common'; export class IacStack extends ros.Stack { constructor(scope: ros.Construct, iac: ServerlessIac, props?: ros.StackProps) { @@ -30,9 +31,29 @@ export class IacStack extends ros.Stack { } } -export const deployStack = (iac: ServerlessIac) => { - console.log(`Deploying stack... ${JSON.stringify(iac)}`); +const generateStackTemplate = (stackName: string, iac: ServerlessIac) => { const app = new ros.App(); new IacStack(app, iac); - app.synth(); + + const assembly = app.synth(); + const stackArtifact = assembly.getStackByName(stackName); + const parameters = Object.entries(stackArtifact.parameters).map(([key, value]) => ({ + key, + value, + })); + + return { template: stackArtifact.template, parameters }; +}; + +export const deployStack = async ( + stackName: string, + iac: ServerlessIac, + context: ActionContext, +) => { + printer.info(`Deploying stack... ${JSON.stringify(iac)}`); + + const { template, parameters } = generateStackTemplate(stackName, iac); + console.log('Generated ROS YAML:', JSON.stringify({ template, parameters })); + await rosStackDeploy(stackName, template, { ...context, parameters }); + printer.info(`Stack deployed! 🎉`); }; diff --git a/src/types.ts b/src/types.ts index bca84a30..345c35c3 100644 --- a/src/types.ts +++ b/src/types.ts @@ -64,3 +64,13 @@ export type ServerlessIac = { functions: Array; events: Array; }; + +export type ActionContext = { + region: string; + accessKeyId: string; + accessKeySecret: string; + securityToken?: string; + iacLocation: string; + parameters?: Array<{ key: string; value: string }>; + tags?: Array<{ key: string; value: string }>; +};