diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml index c5d86c1..f875ab6 100644 --- a/.github/workflows/release-please.yml +++ b/.github/workflows/release-please.yml @@ -54,6 +54,7 @@ jobs: npm run rain env: CDK_RELEASE_VERSION: "${{ steps.release.outputs.major }}.${{ steps.release.outputs.minor }}.${{ steps.release.outputs.patch }}" + CDK_ENVIRONMENT: prod - name: Archive release assets if: ${{ steps.release.outputs.release_created }} diff --git a/cdk.json b/cdk.json index 809af1e..c19bea0 100644 --- a/cdk.json +++ b/cdk.json @@ -7,18 +7,20 @@ }, "context": { "GardenDevClusterStackID": "garden-dev-cluster", - "EKSClusterName": "garden-dev-cluster", "EKSNodeGroupMinSize": 1, "EKSNodeGroupMaxSize": 10, - "ECRRepositories": "api,result,vote,worker", "ECRPrefix": "garden-dev-cluster", - "IAMEKSFullAccessRole": "", "IAMEKSFullAccessPrincipals": "", - "IngressSubdomain": "", - "IngressRoute53HostedZoneId": "" + "IngressRoute53HostedZoneId": "", + "dev": { + "SegmentAPIWriteKey": "7f9LMF7SUiOJHp1DKGGMTWAsMQVATmga" + }, + "prod": { + "SegmentAPIWriteKey": "n28eGgbHFaNYAUe09O0j29hYOXhsCYj7" + } } } diff --git a/package-lock.json b/package-lock.json index 4cf3dd5..0935be2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,21 +10,25 @@ "license": "MPL-2.0", "dependencies": { "@aws-quickstart/eks-blueprints": "=1.6.0", + "@segment/analytics-node": "^1.0.0-beta.26", "@types/aws-lambda": "^8.10.114", "aws-cdk-lib": "=2.66.1", "aws-lambda": "^1.0.7", "cdk": "^2.73.0-alpha.0", "cdk-assets": "^2.73.0-alpha.0", - "constructs": "=10.1.252" + "constructs": "=10.1.252", + "hasha": "^5.2.2", + "pjson": "^1.0.9" }, "devDependencies": { + "@types/analytics-node": "^3.1.11", "ts-node": "^10.9.1" } }, "node_modules/@aws-cdk/asset-awscli-v1": { - "version": "2.2.145", - "resolved": "https://registry.npmjs.org/@aws-cdk/asset-awscli-v1/-/asset-awscli-v1-2.2.145.tgz", - "integrity": "sha512-hcKds6DWRm+xcrI4u5bUBvM7aupF5aGCBPAAuATJpp+w0Zp63TkANDPOCKB4bA79QLzvoQ3YYWnGCysmdaW57Q==" + "version": "2.2.183", + "resolved": "https://registry.npmjs.org/@aws-cdk/asset-awscli-v1/-/asset-awscli-v1-2.2.183.tgz", + "integrity": "sha512-D+E0drcgCjDn43GjsATIpkMeZlFoQFmf86GSlIF0AtNyl0IVrNKsKs/7J4oESrCTTCLL/x9vS7mG9e1ZrKbLpw==" }, "node_modules/@aws-cdk/asset-kubectl-v20": { "version": "2.1.1", @@ -32,9 +36,9 @@ "integrity": "sha512-U1ntiX8XiMRRRH5J1IdC+1t5CE89015cwyt5U63Cpk0GnMlN5+h9WsWMlKlPXZR4rdq/m806JRlBMRpBUB2Dhw==" }, "node_modules/@aws-cdk/asset-node-proxy-agent-v5": { - "version": "2.0.122", - "resolved": "https://registry.npmjs.org/@aws-cdk/asset-node-proxy-agent-v5/-/asset-node-proxy-agent-v5-2.0.122.tgz", - "integrity": "sha512-0xGLWjNIZsmkCAx8gwTbZQh8zzZ40tmAZQccG3Ctu8EB9+wWXBvfszqn0AcUXAhyvAyugzrJi9nG+tU3ACqzZQ==" + "version": "2.0.153", + "resolved": "https://registry.npmjs.org/@aws-cdk/asset-node-proxy-agent-v5/-/asset-node-proxy-agent-v5-2.0.153.tgz", + "integrity": "sha512-EL2XCW6C3szBPHI4XWQsb68pqc719nR+8sfsEhyjzBNn0idgZg2ViujI3/1/jWnJwHPnvMOKQcmr/bOKzCPAgA==" }, "node_modules/@aws-cdk/lambda-layer-kubectl-v22": { "version": "2.0.7", @@ -131,6 +135,25 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "node_modules/@lukeed/csprng": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@lukeed/csprng/-/csprng-1.1.0.tgz", + "integrity": "sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/@lukeed/uuid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@lukeed/uuid/-/uuid-2.0.1.tgz", + "integrity": "sha512-qC72D4+CDdjGqJvkFMMEAtancHUQ7/d/tAiHf64z8MopFDmcrtbcJuerDtFceuAfQJ2pDSfCKCtbqoGBNnwg0w==", + "dependencies": { + "@lukeed/csprng": "^1.1.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/@mapbox/node-pre-gyp": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.10.tgz", @@ -150,6 +173,73 @@ "node-pre-gyp": "bin/node-pre-gyp" } }, + "node_modules/@segment/analytics-core": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@segment/analytics-core/-/analytics-core-1.2.4.tgz", + "integrity": "sha512-M16osD6+z/bQPSVCZdlU+BAhCk968ppi+SGxU2gVa4B196Qr8SEkBPr3NxUCGTSoULo4/T+k8Ea5cF+pXlgf6Q==", + "dependencies": { + "@lukeed/uuid": "^2.0.0", + "dset": "^3.1.2", + "tslib": "^2.4.1" + } + }, + "node_modules/@segment/analytics-node": { + "version": "1.0.0-beta.26", + "resolved": "https://registry.npmjs.org/@segment/analytics-node/-/analytics-node-1.0.0-beta.26.tgz", + "integrity": "sha512-5wIQdSme61k1nIAOaj554ndam0a/13gNhNM2dNBlBHi1HsieDuMg5Qz2e2Hrs1dA4n0psmQmXdBcJxH5BP3jYA==", + "dependencies": { + "@lukeed/uuid": "^2.0.0", + "@segment/analytics-core": "1.2.4", + "buffer": "^6.0.3", + "node-fetch": "^2.6.7", + "tslib": "^2.4.1" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@segment/analytics-node/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/@segment/analytics-node/node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/@tsconfig/node10": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", @@ -174,6 +264,12 @@ "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==", "dev": true }, + "node_modules/@types/analytics-node": { + "version": "3.1.11", + "resolved": "https://registry.npmjs.org/@types/analytics-node/-/analytics-node-3.1.11.tgz", + "integrity": "sha512-CNQVFhaEwL5dEzzV+OtJxt5psRQKJ+XHd0eokdPOM432tpDd4vgB6FzYRCDhDo8uxH0JPXlF6BVA9sbJPpUuug==", + "dev": true + }, "node_modules/@types/assert": { "version": "1.5.6", "resolved": "https://registry.npmjs.org/@types/assert/-/assert-1.5.6.tgz", @@ -1611,6 +1707,14 @@ "node": ">= 6" } }, + "node_modules/dset": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/dset/-/dset-3.1.2.tgz", + "integrity": "sha512-g/M9sqy3oHe477Ar4voQxWtaPIFw1jTdKZuomOjhCcBx9nHUNn0pu6NopuFFrTh/TRZIKEj+76vLWFu9BNKk+Q==", + "engines": { + "node": ">=4" + } + }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -1823,6 +1927,21 @@ "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" }, + "node_modules/hasha": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz", + "integrity": "sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==", + "dependencies": { + "is-stream": "^2.0.0", + "type-fest": "^0.8.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/http-basic": { "version": "8.1.3", "resolved": "https://registry.npmjs.org/http-basic/-/http-basic-8.1.3.tgz", @@ -1929,6 +2048,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-typed-array": { "version": "1.1.10", "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", @@ -2189,6 +2319,11 @@ "node": ">=0.10.0" } }, + "node_modules/pjson": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/pjson/-/pjson-1.0.9.tgz", + "integrity": "sha512-4hRJH3YzkUpOlShRzhyxAmThSNnAaIlWZCAb27hd0pVUAXNUAHAO7XZbsPPvsCYwBFEScTmCCL6DGE8NyZ8BdQ==" + }, "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -2492,6 +2627,11 @@ } } }, + "node_modules/tslib": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + }, "node_modules/tslog": { "version": "4.8.2", "resolved": "https://registry.npmjs.org/tslog/-/tslog-4.8.2.tgz", @@ -2503,6 +2643,14 @@ "url": "https://github.com/fullstack-build/tslog?sponsor=1" } }, + "node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "engines": { + "node": ">=8" + } + }, "node_modules/typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", @@ -2673,9 +2821,9 @@ }, "dependencies": { "@aws-cdk/asset-awscli-v1": { - "version": "2.2.145", - "resolved": "https://registry.npmjs.org/@aws-cdk/asset-awscli-v1/-/asset-awscli-v1-2.2.145.tgz", - "integrity": "sha512-hcKds6DWRm+xcrI4u5bUBvM7aupF5aGCBPAAuATJpp+w0Zp63TkANDPOCKB4bA79QLzvoQ3YYWnGCysmdaW57Q==" + "version": "2.2.183", + "resolved": "https://registry.npmjs.org/@aws-cdk/asset-awscli-v1/-/asset-awscli-v1-2.2.183.tgz", + "integrity": "sha512-D+E0drcgCjDn43GjsATIpkMeZlFoQFmf86GSlIF0AtNyl0IVrNKsKs/7J4oESrCTTCLL/x9vS7mG9e1ZrKbLpw==" }, "@aws-cdk/asset-kubectl-v20": { "version": "2.1.1", @@ -2683,9 +2831,9 @@ "integrity": "sha512-U1ntiX8XiMRRRH5J1IdC+1t5CE89015cwyt5U63Cpk0GnMlN5+h9WsWMlKlPXZR4rdq/m806JRlBMRpBUB2Dhw==" }, "@aws-cdk/asset-node-proxy-agent-v5": { - "version": "2.0.122", - "resolved": "https://registry.npmjs.org/@aws-cdk/asset-node-proxy-agent-v5/-/asset-node-proxy-agent-v5-2.0.122.tgz", - "integrity": "sha512-0xGLWjNIZsmkCAx8gwTbZQh8zzZ40tmAZQccG3Ctu8EB9+wWXBvfszqn0AcUXAhyvAyugzrJi9nG+tU3ACqzZQ==" + "version": "2.0.153", + "resolved": "https://registry.npmjs.org/@aws-cdk/asset-node-proxy-agent-v5/-/asset-node-proxy-agent-v5-2.0.153.tgz", + "integrity": "sha512-EL2XCW6C3szBPHI4XWQsb68pqc719nR+8sfsEhyjzBNn0idgZg2ViujI3/1/jWnJwHPnvMOKQcmr/bOKzCPAgA==" }, "@aws-cdk/lambda-layer-kubectl-v22": { "version": "2.0.7", @@ -2767,6 +2915,19 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "@lukeed/csprng": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@lukeed/csprng/-/csprng-1.1.0.tgz", + "integrity": "sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA==" + }, + "@lukeed/uuid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@lukeed/uuid/-/uuid-2.0.1.tgz", + "integrity": "sha512-qC72D4+CDdjGqJvkFMMEAtancHUQ7/d/tAiHf64z8MopFDmcrtbcJuerDtFceuAfQJ2pDSfCKCtbqoGBNnwg0w==", + "requires": { + "@lukeed/csprng": "^1.1.0" + } + }, "@mapbox/node-pre-gyp": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.10.tgz", @@ -2783,6 +2944,44 @@ "tar": "^6.1.11" } }, + "@segment/analytics-core": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@segment/analytics-core/-/analytics-core-1.2.4.tgz", + "integrity": "sha512-M16osD6+z/bQPSVCZdlU+BAhCk968ppi+SGxU2gVa4B196Qr8SEkBPr3NxUCGTSoULo4/T+k8Ea5cF+pXlgf6Q==", + "requires": { + "@lukeed/uuid": "^2.0.0", + "dset": "^3.1.2", + "tslib": "^2.4.1" + } + }, + "@segment/analytics-node": { + "version": "1.0.0-beta.26", + "resolved": "https://registry.npmjs.org/@segment/analytics-node/-/analytics-node-1.0.0-beta.26.tgz", + "integrity": "sha512-5wIQdSme61k1nIAOaj554ndam0a/13gNhNM2dNBlBHi1HsieDuMg5Qz2e2Hrs1dA4n0psmQmXdBcJxH5BP3jYA==", + "requires": { + "@lukeed/uuid": "^2.0.0", + "@segment/analytics-core": "1.2.4", + "buffer": "^6.0.3", + "node-fetch": "^2.6.7", + "tslib": "^2.4.1" + }, + "dependencies": { + "buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" + } + } + }, "@tsconfig/node10": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", @@ -2807,6 +3006,12 @@ "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==", "dev": true }, + "@types/analytics-node": { + "version": "3.1.11", + "resolved": "https://registry.npmjs.org/@types/analytics-node/-/analytics-node-3.1.11.tgz", + "integrity": "sha512-CNQVFhaEwL5dEzzV+OtJxt5psRQKJ+XHd0eokdPOM432tpDd4vgB6FzYRCDhDo8uxH0JPXlF6BVA9sbJPpUuug==", + "dev": true + }, "@types/assert": { "version": "1.5.6", "resolved": "https://registry.npmjs.org/@types/assert/-/assert-1.5.6.tgz", @@ -4082,6 +4287,11 @@ } } }, + "dset": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/dset/-/dset-3.1.2.tgz", + "integrity": "sha512-g/M9sqy3oHe477Ar4voQxWtaPIFw1jTdKZuomOjhCcBx9nHUNn0pu6NopuFFrTh/TRZIKEj+76vLWFu9BNKk+Q==" + }, "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -4237,6 +4447,15 @@ "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" }, + "hasha": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz", + "integrity": "sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==", + "requires": { + "is-stream": "^2.0.0", + "type-fest": "^0.8.0" + } + }, "http-basic": { "version": "8.1.3", "resolved": "https://registry.npmjs.org/http-basic/-/http-basic-8.1.3.tgz", @@ -4318,6 +4537,11 @@ "has-tostringtag": "^1.0.0" } }, + "is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==" + }, "is-typed-array": { "version": "1.1.10", "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", @@ -4502,6 +4726,11 @@ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" }, + "pjson": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/pjson/-/pjson-1.0.9.tgz", + "integrity": "sha512-4hRJH3YzkUpOlShRzhyxAmThSNnAaIlWZCAb27hd0pVUAXNUAHAO7XZbsPPvsCYwBFEScTmCCL6DGE8NyZ8BdQ==" + }, "process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -4722,11 +4951,21 @@ "yn": "3.1.1" } }, + "tslib": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + }, "tslog": { "version": "4.8.2", "resolved": "https://registry.npmjs.org/tslog/-/tslog-4.8.2.tgz", "integrity": "sha512-eAKIRjxfSKYLs06r1wT7oou6Uv9VN6NW9g0JPidBlqQwPBBl5+84dm7r8zSOPVq1kyfEw1P6B3/FLSpZCorAgA==" }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==" + }, "typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", diff --git a/package.json b/package.json index b1c94fb..839a135 100644 --- a/package.json +++ b/package.json @@ -5,12 +5,15 @@ "main": "src/index.ts", "dependencies": { "@aws-quickstart/eks-blueprints": "=1.6.0", + "@segment/analytics-node": "^1.0.0-beta.26", "@types/aws-lambda": "^8.10.114", "aws-cdk-lib": "=2.66.1", "aws-lambda": "^1.0.7", "cdk": "^2.73.0-alpha.0", "cdk-assets": "^2.73.0-alpha.0", - "constructs": "=10.1.252" + "constructs": "=10.1.252", + "hasha": "^5.2.2", + "pjson": "^1.0.9" }, "scripts": { "test": "echo \"Error: no test specified\" && exit 1", @@ -25,6 +28,7 @@ "license": "MPL-2.0", "homepage": "https://github.com/garden-io/dev-cluster", "devDependencies": { + "@types/analytics-node": "^3.1.11", "ts-node": "^10.9.1" } } diff --git a/src/constructs/garden-addon.ts b/src/constructs/garden-addon.ts index 4caacc3..739304b 100644 --- a/src/constructs/garden-addon.ts +++ b/src/constructs/garden-addon.ts @@ -3,7 +3,9 @@ import * as iam from "aws-cdk-lib/aws-iam"; import * as cdk from "aws-cdk-lib"; import { ECRRepositories } from "./ecr-repositories"; import { EKSCleanupLB } from "./eks-cleanuplb"; +import { TrackUsage } from "./tracking"; import { GardenEKSDevCluster } from "../stacks/garden-dev-cluster"; +var pjson = require("pjson"); export interface GardenAddOnProps { readonly accountId: string @@ -45,6 +47,9 @@ export class GardenAddOn implements ClusterAddOn { // fix cluster deletion this.addCleanupLBHack(clusterInfo) + + //track usage + this.trackUsage(clusterInfo) } private addCleanupLBHack(clusterInfo: ClusterInfo) { @@ -64,6 +69,15 @@ export class GardenAddOn implements ClusterAddOn { }) } + private trackUsage(clusterInfo: ClusterInfo) { + const cluster = clusterInfo.cluster + new TrackUsage(cluster, "TrackUsage", { + account: this.props.accountId, + stackVersion: pjson.version, + parameters: this.props.parameters + }) + } + private createFullAccessIAMRoleIfNeeded(clusterInfo: ClusterInfo) { const cluster = clusterInfo.cluster const parameters = this.props.parameters diff --git a/src/constructs/tracking.ts b/src/constructs/tracking.ts new file mode 100644 index 0000000..6419ddd --- /dev/null +++ b/src/constructs/tracking.ts @@ -0,0 +1,69 @@ +import * as path from 'path'; +import { CustomResource, Stack } from 'aws-cdk-lib'; +import * as lambda from 'aws-cdk-lib/aws-lambda'; +import * as lambdaNodejs from 'aws-cdk-lib/aws-lambda-nodejs'; +import * as cr from 'aws-cdk-lib/custom-resources'; +import { Construct } from 'constructs'; +import * as cdk from "aws-cdk-lib"; +import { PROP_ACCOUNT, PROP_SEGMENT_KEY, PROP_CF_STACK_ARN, PROP_VERSION, PROP_FULL_ACCESS_ROLE, PROP_FULL_ACCESS_PRINCIPALS, PROP_CLUSTER_NAME, PROP_ECR_PREFIX, PROP_ECR_REPO_NAMES, PROP_HOSTEDZONE_ID, PROP_MAX_NODEGROUP_SIZE, PROP_MIN_NODEGROUP_SIZE, PROP_SUBDOMAIN} from '../functions/tracking'; +import { GardenEKSDevCluster} from '../stacks/garden-dev-cluster'; + + +export const cdkEnvironment: string = process.env.CDK_ENVIRONMENT || 'dev'; +interface TrackUsageProps { + stackVersion: string; + account: string; + parameters: typeof GardenEKSDevCluster.parameters; +} + +export class TrackUsage extends Construct { + constructor(scope: Construct, id: string, props: TrackUsageProps) { + super(scope, id); + + new CustomResource(this, 'Resource', { + serviceToken: TrackUsageProvider.getOrCreate(this), + resourceType: 'Custom::TrackUsage', + properties: { + [PROP_SEGMENT_KEY]: this.node.tryGetContext(cdkEnvironment).SegmentAPIWriteKey, + [PROP_VERSION]: props.stackVersion, + [PROP_ACCOUNT]: props.account, + [PROP_CF_STACK_ARN]: cdk.Stack.of(scope).stackId, + [PROP_FULL_ACCESS_ROLE]: props.parameters.fullAccessRole, + [PROP_FULL_ACCESS_PRINCIPALS]: props.parameters.fullAccessPrincipals, + [PROP_ECR_REPO_NAMES]: props.parameters.ecrRepoNames, + [PROP_ECR_PREFIX]: props.parameters.ecrPrefix, + [PROP_SUBDOMAIN]: props.parameters.subdomain, + [PROP_HOSTEDZONE_ID]: props.parameters.hostedZoneID, + [PROP_CLUSTER_NAME]: props.parameters.clusterName, + [PROP_MIN_NODEGROUP_SIZE]: props.parameters.minNodeGroupSize, + [PROP_MAX_NODEGROUP_SIZE]: props.parameters.maxNodeGroupSize + }, + }); + } +} + +class TrackUsageProvider extends Construct { + + /** + * Returns the singleton provider. + */ + public static getOrCreate(scope: Construct) { + const stack = Stack.of(scope); + const id = 'garden.custom-track-usage-provider'; + const x = stack.node.tryFindChild(id) as TrackUsageProvider || new TrackUsageProvider(stack, id); + return x.provider.serviceToken; + } + + private readonly provider: cr.Provider; + + constructor(scope: Construct, id: string) { + super(scope, id); + + this.provider = new cr.Provider(this, 'track-usage-provider', { + onEventHandler: new lambdaNodejs.NodejsFunction(this, 'tracking-on-event', { + runtime: lambda.Runtime.NODEJS_18_X , + entry: path.join(__dirname, '..', 'functions', 'tracking.ts'), + }), + }); + } +} diff --git a/src/functions/ecr-repositories.ts b/src/functions/ecr-repositories.ts index 89bdc83..91d5f1e 100644 --- a/src/functions/ecr-repositories.ts +++ b/src/functions/ecr-repositories.ts @@ -24,11 +24,13 @@ export async function handler(event: AWSCDKAsyncCustomResource.OnEventRequest): // get deleted repos for (const repo of oldRepos.filter((r) => !newRepos.includes(r))) { + console.log(`deleting repo ${prefix}/${repo}`) await deleteRepo(prefix, repo) } for (const repo of newRepos.filter((r) => !oldRepos.includes(r))) { - createRepo(prefix, repo) + console.log(`creating repo ${prefix}/${repo}`) + await createRepo(prefix, repo) } return {} diff --git a/src/functions/tracking.ts b/src/functions/tracking.ts new file mode 100644 index 0000000..4ce4194 --- /dev/null +++ b/src/functions/tracking.ts @@ -0,0 +1,64 @@ +import * as AWSCDKAsyncCustomResource from 'aws-cdk-lib/custom-resources/lib/provider-framework/types'; +import Analytics from "@segment/analytics-node"; +import hasha = require("hasha"); + +export const PROP_SEGMENT_KEY = "segmentApiKey" +export const PROP_VERSION = "gardenDevClusterVersion" +export const PROP_ACCOUNT = "awsAccount" +export const PROP_CF_STACK_ARN = "cloudformationStackArn" +export const PROP_FULL_ACCESS_ROLE = "iamFullAccessRole" +export const PROP_FULL_ACCESS_PRINCIPALS = "iamFullAccessPrincipals" +export const PROP_ECR_REPO_NAMES = "ecrRepoNames" +export const PROP_ECR_PREFIX = "ecrPrefix" +export const PROP_SUBDOMAIN = "subdomain" +export const PROP_HOSTEDZONE_ID = "hostedzoneID" +export const PROP_CLUSTER_NAME = "clusterName" +export const PROP_MIN_NODEGROUP_SIZE = "minNodegroupSize" +export const PROP_MAX_NODEGROUP_SIZE = "maxNodegroupSize" + +export async function handler(event: AWSCDKAsyncCustomResource.OnEventRequest): Promise { + const version: string = event.ResourceProperties[PROP_VERSION] + const accountHash: string = hasha(event.ResourceProperties[PROP_ACCOUNT],{algorithm: "sha512"}) + const cfnStackArnHash: string = hasha(event.ResourceProperties[PROP_CF_STACK_ARN], {algorithm: 'sha512'}).slice(0,64) + const analytics = new Analytics({writeKey: event.ResourceProperties[PROP_SEGMENT_KEY]}) + switch (event.RequestType) { + case 'Create': + analytics.track({ + anonymousId: cfnStackArnHash, + event: "Installed dev-cluster", + properties: { + version: version, + accountHash: accountHash, + platform: "AWS" + }, + }) + await analytics.closeAndFlush() + return {} + + case 'Update': + analytics.track({ + anonymousId: cfnStackArnHash, + event: "Updated dev-cluster", + properties: { + version: version, + accountHash: accountHash, + platform: "AWS" + }, + }) + await analytics.closeAndFlush() + return {} + + case 'Delete': + analytics.track({ + anonymousId: cfnStackArnHash, + event: "Deleted dev-cluster", + properties: { + version: version, + accountHash: accountHash, + platform: "AWS" + }, + }) + await analytics.closeAndFlush() + return {} + } + } \ No newline at end of file