@reyemtech/nimbus 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +399 -0
- package/dist/cjs/aws/cluster.d.ts +32 -0
- package/dist/cjs/aws/cluster.d.ts.map +1 -0
- package/dist/cjs/aws/cluster.js +214 -0
- package/dist/cjs/aws/cluster.js.map +1 -0
- package/dist/cjs/aws/dns.d.ts +22 -0
- package/dist/cjs/aws/dns.d.ts.map +1 -0
- package/dist/cjs/aws/dns.js +95 -0
- package/dist/cjs/aws/dns.js.map +1 -0
- package/dist/cjs/aws/index.d.ts +10 -0
- package/dist/cjs/aws/index.d.ts.map +1 -0
- package/dist/cjs/aws/index.js +17 -0
- package/dist/cjs/aws/index.js.map +1 -0
- package/dist/cjs/aws/network.d.ts +27 -0
- package/dist/cjs/aws/network.d.ts.map +1 -0
- package/dist/cjs/aws/network.js +262 -0
- package/dist/cjs/aws/network.js.map +1 -0
- package/dist/cjs/aws/secrets.d.ts +26 -0
- package/dist/cjs/aws/secrets.d.ts.map +1 -0
- package/dist/cjs/aws/secrets.js +127 -0
- package/dist/cjs/aws/secrets.js.map +1 -0
- package/dist/cjs/azure/cluster.d.ts +44 -0
- package/dist/cjs/azure/cluster.d.ts.map +1 -0
- package/dist/cjs/azure/cluster.js +143 -0
- package/dist/cjs/azure/cluster.js.map +1 -0
- package/dist/cjs/azure/dns.d.ts +28 -0
- package/dist/cjs/azure/dns.d.ts.map +1 -0
- package/dist/cjs/azure/dns.js +169 -0
- package/dist/cjs/azure/dns.js.map +1 -0
- package/dist/cjs/azure/index.d.ts +10 -0
- package/dist/cjs/azure/index.d.ts.map +1 -0
- package/dist/cjs/azure/index.js +17 -0
- package/dist/cjs/azure/index.js.map +1 -0
- package/dist/cjs/azure/network.d.ts +28 -0
- package/dist/cjs/azure/network.d.ts.map +1 -0
- package/dist/cjs/azure/network.js +176 -0
- package/dist/cjs/azure/network.js.map +1 -0
- package/dist/cjs/azure/secrets.d.ts +37 -0
- package/dist/cjs/azure/secrets.d.ts.map +1 -0
- package/dist/cjs/azure/secrets.js +150 -0
- package/dist/cjs/azure/secrets.js.map +1 -0
- package/dist/cjs/cache/index.d.ts +7 -0
- package/dist/cjs/cache/index.d.ts.map +1 -0
- package/dist/cjs/cache/index.js +8 -0
- package/dist/cjs/cache/index.js.map +1 -0
- package/dist/cjs/cache/interfaces.d.ts +60 -0
- package/dist/cjs/cache/interfaces.d.ts.map +1 -0
- package/dist/cjs/cache/interfaces.js +11 -0
- package/dist/cjs/cache/interfaces.js.map +1 -0
- package/dist/cjs/cluster/index.d.ts +7 -0
- package/dist/cjs/cluster/index.d.ts.map +1 -0
- package/dist/cjs/cluster/index.js +8 -0
- package/dist/cjs/cluster/index.js.map +1 -0
- package/dist/cjs/cluster/interfaces.d.ts +120 -0
- package/dist/cjs/cluster/interfaces.d.ts.map +1 -0
- package/dist/cjs/cluster/interfaces.js +12 -0
- package/dist/cjs/cluster/interfaces.js.map +1 -0
- package/dist/cjs/database/index.d.ts +7 -0
- package/dist/cjs/database/index.d.ts.map +1 -0
- package/dist/cjs/database/index.js +8 -0
- package/dist/cjs/database/index.js.map +1 -0
- package/dist/cjs/database/interfaces.d.ts +93 -0
- package/dist/cjs/database/interfaces.d.ts.map +1 -0
- package/dist/cjs/database/interfaces.js +12 -0
- package/dist/cjs/database/interfaces.js.map +1 -0
- package/dist/cjs/dns/index.d.ts +7 -0
- package/dist/cjs/dns/index.d.ts.map +1 -0
- package/dist/cjs/dns/index.js +8 -0
- package/dist/cjs/dns/index.js.map +1 -0
- package/dist/cjs/dns/interfaces.d.ts +55 -0
- package/dist/cjs/dns/interfaces.d.ts.map +1 -0
- package/dist/cjs/dns/interfaces.js +11 -0
- package/dist/cjs/dns/interfaces.js.map +1 -0
- package/dist/cjs/factories/cluster.d.ts +45 -0
- package/dist/cjs/factories/cluster.d.ts.map +1 -0
- package/dist/cjs/factories/cluster.js +90 -0
- package/dist/cjs/factories/cluster.js.map +1 -0
- package/dist/cjs/factories/dns.d.ts +30 -0
- package/dist/cjs/factories/dns.d.ts.map +1 -0
- package/dist/cjs/factories/dns.js +56 -0
- package/dist/cjs/factories/dns.js.map +1 -0
- package/dist/cjs/factories/index.d.ts +15 -0
- package/dist/cjs/factories/index.d.ts.map +1 -0
- package/dist/cjs/factories/index.js +23 -0
- package/dist/cjs/factories/index.js.map +1 -0
- package/dist/cjs/factories/network.d.ts +40 -0
- package/dist/cjs/factories/network.d.ts.map +1 -0
- package/dist/cjs/factories/network.js +85 -0
- package/dist/cjs/factories/network.js.map +1 -0
- package/dist/cjs/factories/secrets.d.ts +38 -0
- package/dist/cjs/factories/secrets.d.ts.map +1 -0
- package/dist/cjs/factories/secrets.js +67 -0
- package/dist/cjs/factories/secrets.js.map +1 -0
- package/dist/cjs/factories/types.d.ts +75 -0
- package/dist/cjs/factories/types.d.ts.map +1 -0
- package/dist/cjs/factories/types.js +28 -0
- package/dist/cjs/factories/types.js.map +1 -0
- package/dist/cjs/global-lb/glb.d.ts +29 -0
- package/dist/cjs/global-lb/glb.d.ts.map +1 -0
- package/dist/cjs/global-lb/glb.js +220 -0
- package/dist/cjs/global-lb/glb.js.map +1 -0
- package/dist/cjs/global-lb/index.d.ts +8 -0
- package/dist/cjs/global-lb/index.d.ts.map +1 -0
- package/dist/cjs/global-lb/index.js +11 -0
- package/dist/cjs/global-lb/index.js.map +1 -0
- package/dist/cjs/global-lb/interfaces.d.ts +62 -0
- package/dist/cjs/global-lb/interfaces.d.ts.map +1 -0
- package/dist/cjs/global-lb/interfaces.js +11 -0
- package/dist/cjs/global-lb/interfaces.js.map +1 -0
- package/dist/cjs/index.d.ts +28 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +72 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/network/cidr.d.ts +92 -0
- package/dist/cjs/network/cidr.d.ts.map +1 -0
- package/dist/cjs/network/cidr.js +189 -0
- package/dist/cjs/network/cidr.js.map +1 -0
- package/dist/cjs/network/index.d.ts +8 -0
- package/dist/cjs/network/index.d.ts.map +1 -0
- package/dist/cjs/network/index.js +17 -0
- package/dist/cjs/network/index.js.map +1 -0
- package/dist/cjs/network/interfaces.d.ts +60 -0
- package/dist/cjs/network/interfaces.d.ts.map +1 -0
- package/dist/cjs/network/interfaces.js +12 -0
- package/dist/cjs/network/interfaces.js.map +1 -0
- package/dist/cjs/platform/index.d.ts +8 -0
- package/dist/cjs/platform/index.d.ts.map +1 -0
- package/dist/cjs/platform/index.js +11 -0
- package/dist/cjs/platform/index.js.map +1 -0
- package/dist/cjs/platform/interfaces.d.ts +86 -0
- package/dist/cjs/platform/interfaces.d.ts.map +1 -0
- package/dist/cjs/platform/interfaces.js +12 -0
- package/dist/cjs/platform/interfaces.js.map +1 -0
- package/dist/cjs/platform/stack.d.ts +32 -0
- package/dist/cjs/platform/stack.d.ts.map +1 -0
- package/dist/cjs/platform/stack.js +258 -0
- package/dist/cjs/platform/stack.js.map +1 -0
- package/dist/cjs/queue/index.d.ts +7 -0
- package/dist/cjs/queue/index.d.ts.map +1 -0
- package/dist/cjs/queue/index.js +8 -0
- package/dist/cjs/queue/index.js.map +1 -0
- package/dist/cjs/queue/interfaces.d.ts +46 -0
- package/dist/cjs/queue/interfaces.d.ts.map +1 -0
- package/dist/cjs/queue/interfaces.js +11 -0
- package/dist/cjs/queue/interfaces.js.map +1 -0
- package/dist/cjs/secrets/index.d.ts +7 -0
- package/dist/cjs/secrets/index.d.ts.map +1 -0
- package/dist/cjs/secrets/index.js +8 -0
- package/dist/cjs/secrets/index.js.map +1 -0
- package/dist/cjs/secrets/interfaces.d.ts +73 -0
- package/dist/cjs/secrets/interfaces.d.ts.map +1 -0
- package/dist/cjs/secrets/interfaces.js +11 -0
- package/dist/cjs/secrets/interfaces.js.map +1 -0
- package/dist/cjs/storage/index.d.ts +7 -0
- package/dist/cjs/storage/index.d.ts.map +1 -0
- package/dist/cjs/storage/index.js +8 -0
- package/dist/cjs/storage/index.js.map +1 -0
- package/dist/cjs/storage/interfaces.d.ts +63 -0
- package/dist/cjs/storage/interfaces.d.ts.map +1 -0
- package/dist/cjs/storage/interfaces.js +11 -0
- package/dist/cjs/storage/interfaces.js.map +1 -0
- package/dist/cjs/types/cloud-target.d.ts +89 -0
- package/dist/cjs/types/cloud-target.d.ts.map +1 -0
- package/dist/cjs/types/cloud-target.js +73 -0
- package/dist/cjs/types/cloud-target.js.map +1 -0
- package/dist/cjs/types/errors.d.ts +96 -0
- package/dist/cjs/types/errors.d.ts.map +1 -0
- package/dist/cjs/types/errors.js +127 -0
- package/dist/cjs/types/errors.js.map +1 -0
- package/dist/cjs/types/index.d.ts +10 -0
- package/dist/cjs/types/index.d.ts.map +1 -0
- package/dist/cjs/types/index.js +33 -0
- package/dist/cjs/types/index.js.map +1 -0
- package/dist/cjs/types/tags.d.ts +53 -0
- package/dist/cjs/types/tags.d.ts.map +1 -0
- package/dist/cjs/types/tags.js +110 -0
- package/dist/cjs/types/tags.js.map +1 -0
- package/dist/cjs/types/validation.d.ts +63 -0
- package/dist/cjs/types/validation.d.ts.map +1 -0
- package/dist/cjs/types/validation.js +158 -0
- package/dist/cjs/types/validation.js.map +1 -0
- package/dist/esm/aws/cluster.d.ts +32 -0
- package/dist/esm/aws/cluster.d.ts.map +1 -0
- package/dist/esm/aws/cluster.js +214 -0
- package/dist/esm/aws/cluster.js.map +1 -0
- package/dist/esm/aws/dns.d.ts +22 -0
- package/dist/esm/aws/dns.d.ts.map +1 -0
- package/dist/esm/aws/dns.js +95 -0
- package/dist/esm/aws/dns.js.map +1 -0
- package/dist/esm/aws/index.d.ts +10 -0
- package/dist/esm/aws/index.d.ts.map +1 -0
- package/dist/esm/aws/index.js +17 -0
- package/dist/esm/aws/index.js.map +1 -0
- package/dist/esm/aws/network.d.ts +27 -0
- package/dist/esm/aws/network.d.ts.map +1 -0
- package/dist/esm/aws/network.js +262 -0
- package/dist/esm/aws/network.js.map +1 -0
- package/dist/esm/aws/secrets.d.ts +26 -0
- package/dist/esm/aws/secrets.d.ts.map +1 -0
- package/dist/esm/aws/secrets.js +127 -0
- package/dist/esm/aws/secrets.js.map +1 -0
- package/dist/esm/azure/cluster.d.ts +44 -0
- package/dist/esm/azure/cluster.d.ts.map +1 -0
- package/dist/esm/azure/cluster.js +143 -0
- package/dist/esm/azure/cluster.js.map +1 -0
- package/dist/esm/azure/dns.d.ts +28 -0
- package/dist/esm/azure/dns.d.ts.map +1 -0
- package/dist/esm/azure/dns.js +169 -0
- package/dist/esm/azure/dns.js.map +1 -0
- package/dist/esm/azure/index.d.ts +10 -0
- package/dist/esm/azure/index.d.ts.map +1 -0
- package/dist/esm/azure/index.js +17 -0
- package/dist/esm/azure/index.js.map +1 -0
- package/dist/esm/azure/network.d.ts +28 -0
- package/dist/esm/azure/network.d.ts.map +1 -0
- package/dist/esm/azure/network.js +176 -0
- package/dist/esm/azure/network.js.map +1 -0
- package/dist/esm/azure/secrets.d.ts +37 -0
- package/dist/esm/azure/secrets.d.ts.map +1 -0
- package/dist/esm/azure/secrets.js +150 -0
- package/dist/esm/azure/secrets.js.map +1 -0
- package/dist/esm/cache/index.d.ts +7 -0
- package/dist/esm/cache/index.d.ts.map +1 -0
- package/dist/esm/cache/index.js +8 -0
- package/dist/esm/cache/index.js.map +1 -0
- package/dist/esm/cache/interfaces.d.ts +60 -0
- package/dist/esm/cache/interfaces.d.ts.map +1 -0
- package/dist/esm/cache/interfaces.js +11 -0
- package/dist/esm/cache/interfaces.js.map +1 -0
- package/dist/esm/cluster/index.d.ts +7 -0
- package/dist/esm/cluster/index.d.ts.map +1 -0
- package/dist/esm/cluster/index.js +8 -0
- package/dist/esm/cluster/index.js.map +1 -0
- package/dist/esm/cluster/interfaces.d.ts +120 -0
- package/dist/esm/cluster/interfaces.d.ts.map +1 -0
- package/dist/esm/cluster/interfaces.js +12 -0
- package/dist/esm/cluster/interfaces.js.map +1 -0
- package/dist/esm/database/index.d.ts +7 -0
- package/dist/esm/database/index.d.ts.map +1 -0
- package/dist/esm/database/index.js +8 -0
- package/dist/esm/database/index.js.map +1 -0
- package/dist/esm/database/interfaces.d.ts +93 -0
- package/dist/esm/database/interfaces.d.ts.map +1 -0
- package/dist/esm/database/interfaces.js +12 -0
- package/dist/esm/database/interfaces.js.map +1 -0
- package/dist/esm/dns/index.d.ts +7 -0
- package/dist/esm/dns/index.d.ts.map +1 -0
- package/dist/esm/dns/index.js +8 -0
- package/dist/esm/dns/index.js.map +1 -0
- package/dist/esm/dns/interfaces.d.ts +55 -0
- package/dist/esm/dns/interfaces.d.ts.map +1 -0
- package/dist/esm/dns/interfaces.js +11 -0
- package/dist/esm/dns/interfaces.js.map +1 -0
- package/dist/esm/factories/cluster.d.ts +45 -0
- package/dist/esm/factories/cluster.d.ts.map +1 -0
- package/dist/esm/factories/cluster.js +90 -0
- package/dist/esm/factories/cluster.js.map +1 -0
- package/dist/esm/factories/dns.d.ts +30 -0
- package/dist/esm/factories/dns.d.ts.map +1 -0
- package/dist/esm/factories/dns.js +56 -0
- package/dist/esm/factories/dns.js.map +1 -0
- package/dist/esm/factories/index.d.ts +15 -0
- package/dist/esm/factories/index.d.ts.map +1 -0
- package/dist/esm/factories/index.js +23 -0
- package/dist/esm/factories/index.js.map +1 -0
- package/dist/esm/factories/network.d.ts +40 -0
- package/dist/esm/factories/network.d.ts.map +1 -0
- package/dist/esm/factories/network.js +85 -0
- package/dist/esm/factories/network.js.map +1 -0
- package/dist/esm/factories/secrets.d.ts +38 -0
- package/dist/esm/factories/secrets.d.ts.map +1 -0
- package/dist/esm/factories/secrets.js +67 -0
- package/dist/esm/factories/secrets.js.map +1 -0
- package/dist/esm/factories/types.d.ts +75 -0
- package/dist/esm/factories/types.d.ts.map +1 -0
- package/dist/esm/factories/types.js +28 -0
- package/dist/esm/factories/types.js.map +1 -0
- package/dist/esm/global-lb/glb.d.ts +29 -0
- package/dist/esm/global-lb/glb.d.ts.map +1 -0
- package/dist/esm/global-lb/glb.js +220 -0
- package/dist/esm/global-lb/glb.js.map +1 -0
- package/dist/esm/global-lb/index.d.ts +8 -0
- package/dist/esm/global-lb/index.d.ts.map +1 -0
- package/dist/esm/global-lb/index.js +11 -0
- package/dist/esm/global-lb/index.js.map +1 -0
- package/dist/esm/global-lb/interfaces.d.ts +62 -0
- package/dist/esm/global-lb/interfaces.d.ts.map +1 -0
- package/dist/esm/global-lb/interfaces.js +11 -0
- package/dist/esm/global-lb/interfaces.js.map +1 -0
- package/dist/esm/index.d.ts +28 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +72 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/network/cidr.d.ts +92 -0
- package/dist/esm/network/cidr.d.ts.map +1 -0
- package/dist/esm/network/cidr.js +189 -0
- package/dist/esm/network/cidr.js.map +1 -0
- package/dist/esm/network/index.d.ts +8 -0
- package/dist/esm/network/index.d.ts.map +1 -0
- package/dist/esm/network/index.js +17 -0
- package/dist/esm/network/index.js.map +1 -0
- package/dist/esm/network/interfaces.d.ts +60 -0
- package/dist/esm/network/interfaces.d.ts.map +1 -0
- package/dist/esm/network/interfaces.js +12 -0
- package/dist/esm/network/interfaces.js.map +1 -0
- package/dist/esm/platform/index.d.ts +8 -0
- package/dist/esm/platform/index.d.ts.map +1 -0
- package/dist/esm/platform/index.js +11 -0
- package/dist/esm/platform/index.js.map +1 -0
- package/dist/esm/platform/interfaces.d.ts +86 -0
- package/dist/esm/platform/interfaces.d.ts.map +1 -0
- package/dist/esm/platform/interfaces.js +12 -0
- package/dist/esm/platform/interfaces.js.map +1 -0
- package/dist/esm/platform/stack.d.ts +32 -0
- package/dist/esm/platform/stack.d.ts.map +1 -0
- package/dist/esm/platform/stack.js +258 -0
- package/dist/esm/platform/stack.js.map +1 -0
- package/dist/esm/queue/index.d.ts +7 -0
- package/dist/esm/queue/index.d.ts.map +1 -0
- package/dist/esm/queue/index.js +8 -0
- package/dist/esm/queue/index.js.map +1 -0
- package/dist/esm/queue/interfaces.d.ts +46 -0
- package/dist/esm/queue/interfaces.d.ts.map +1 -0
- package/dist/esm/queue/interfaces.js +11 -0
- package/dist/esm/queue/interfaces.js.map +1 -0
- package/dist/esm/secrets/index.d.ts +7 -0
- package/dist/esm/secrets/index.d.ts.map +1 -0
- package/dist/esm/secrets/index.js +8 -0
- package/dist/esm/secrets/index.js.map +1 -0
- package/dist/esm/secrets/interfaces.d.ts +73 -0
- package/dist/esm/secrets/interfaces.d.ts.map +1 -0
- package/dist/esm/secrets/interfaces.js +11 -0
- package/dist/esm/secrets/interfaces.js.map +1 -0
- package/dist/esm/storage/index.d.ts +7 -0
- package/dist/esm/storage/index.d.ts.map +1 -0
- package/dist/esm/storage/index.js +8 -0
- package/dist/esm/storage/index.js.map +1 -0
- package/dist/esm/storage/interfaces.d.ts +63 -0
- package/dist/esm/storage/interfaces.d.ts.map +1 -0
- package/dist/esm/storage/interfaces.js +11 -0
- package/dist/esm/storage/interfaces.js.map +1 -0
- package/dist/esm/types/cloud-target.d.ts +89 -0
- package/dist/esm/types/cloud-target.d.ts.map +1 -0
- package/dist/esm/types/cloud-target.js +73 -0
- package/dist/esm/types/cloud-target.js.map +1 -0
- package/dist/esm/types/errors.d.ts +96 -0
- package/dist/esm/types/errors.d.ts.map +1 -0
- package/dist/esm/types/errors.js +127 -0
- package/dist/esm/types/errors.js.map +1 -0
- package/dist/esm/types/index.d.ts +10 -0
- package/dist/esm/types/index.d.ts.map +1 -0
- package/dist/esm/types/index.js +33 -0
- package/dist/esm/types/index.js.map +1 -0
- package/dist/esm/types/tags.d.ts +53 -0
- package/dist/esm/types/tags.d.ts.map +1 -0
- package/dist/esm/types/tags.js +110 -0
- package/dist/esm/types/tags.js.map +1 -0
- package/dist/esm/types/validation.d.ts +63 -0
- package/dist/esm/types/validation.d.ts.map +1 -0
- package/dist/esm/types/validation.js +158 -0
- package/dist/esm/types/validation.js.map +1 -0
- package/package.json +88 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 ReyemTech
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
# @reyemtech/nimbus
|
|
2
|
+
|
|
3
|
+
Cloud-agnostic infrastructure abstractions for [Pulumi](https://www.pulumi.com/). Write IaC once, deploy to AWS, Azure, or GCP. Enables full BCDR: any client environment is fully reproducible from code — cloud migration = change one config value.
|
|
4
|
+
|
|
5
|
+
## Why
|
|
6
|
+
|
|
7
|
+
Every client environment at ReyemTech follows the same pattern: network + cluster + DNS + secrets + platform components. The only difference is the cloud provider. This package extracts that pattern into reusable, type-safe abstractions.
|
|
8
|
+
|
|
9
|
+
**Key benefits:**
|
|
10
|
+
- **Cloud migration in one line** — change `cloud: "aws"` to `cloud: "azure"` and redeploy
|
|
11
|
+
- **Multi-cloud active-active** — deploy to AWS + Azure simultaneously with a Global Load Balancer
|
|
12
|
+
- **Factory pattern** — `createNetwork()`, `createCluster()`, `createDns()`, `createSecrets()` dispatch to the right cloud automatically
|
|
13
|
+
- **Cost-optimized defaults** — fck-nat (~$3/mo vs $32/mo managed NAT), spot instances, Auto Mode
|
|
14
|
+
- **Escape hatches** — every resource exposes its native cloud object via `nativeResource`
|
|
15
|
+
- **Type-safe** — full TypeScript interfaces with discriminated unions for provider-specific config
|
|
16
|
+
|
|
17
|
+
## Install
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install @reyemtech/nimbus
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
**Peer dependency:** `@pulumi/pulumi >= 3.0.0`
|
|
24
|
+
|
|
25
|
+
**Provider SDKs** (install only what you need):
|
|
26
|
+
```bash
|
|
27
|
+
# AWS
|
|
28
|
+
npm install @pulumi/aws @pulumi/eks
|
|
29
|
+
|
|
30
|
+
# Azure
|
|
31
|
+
npm install @pulumi/azure-native
|
|
32
|
+
|
|
33
|
+
# Both (for multi-cloud)
|
|
34
|
+
npm install @pulumi/aws @pulumi/eks @pulumi/azure-native
|
|
35
|
+
|
|
36
|
+
# Platform layer (Helm)
|
|
37
|
+
npm install @pulumi/kubernetes
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Quick Start
|
|
41
|
+
|
|
42
|
+
### Single Cloud (AWS)
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
import { createNetwork, createCluster, createDns, createPlatformStack } from "@reyemtech/nimbus";
|
|
46
|
+
import type { INetwork, ICluster, IDns } from "@reyemtech/nimbus";
|
|
47
|
+
|
|
48
|
+
// Network with fck-nat (~$3/mo)
|
|
49
|
+
const network = createNetwork("prod", {
|
|
50
|
+
cloud: "aws",
|
|
51
|
+
cidr: "10.0.0.0/16",
|
|
52
|
+
natStrategy: "fck-nat",
|
|
53
|
+
}) as INetwork;
|
|
54
|
+
|
|
55
|
+
// EKS cluster with Auto Mode
|
|
56
|
+
const cluster = createCluster("prod", {
|
|
57
|
+
cloud: "aws",
|
|
58
|
+
nodePools: [
|
|
59
|
+
{ name: "system", instanceType: "t4g.small", minNodes: 2, maxNodes: 3 },
|
|
60
|
+
{ name: "workers", instanceType: "c6a.large", minNodes: 1, maxNodes: 10, spot: true },
|
|
61
|
+
],
|
|
62
|
+
providerOptions: { aws: { autoMode: true } },
|
|
63
|
+
}, network) as ICluster;
|
|
64
|
+
|
|
65
|
+
// DNS zone
|
|
66
|
+
const dns = createDns("prod", { cloud: "aws", zoneName: "example.com" }) as IDns;
|
|
67
|
+
|
|
68
|
+
// Platform stack (Traefik, cert-manager, External DNS, ArgoCD, Vault)
|
|
69
|
+
createPlatformStack("prod", {
|
|
70
|
+
cluster,
|
|
71
|
+
domain: "example.com",
|
|
72
|
+
externalDns: { dnsProvider: "route53", domainFilters: ["example.com"] },
|
|
73
|
+
vault: { enabled: true, ingressHost: "vault.example.com" },
|
|
74
|
+
});
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Single Cloud (Azure)
|
|
78
|
+
|
|
79
|
+
```typescript
|
|
80
|
+
import { createNetwork, createCluster, createDns, createPlatformStack } from "@reyemtech/nimbus";
|
|
81
|
+
import type { INetwork, ICluster } from "@reyemtech/nimbus";
|
|
82
|
+
|
|
83
|
+
const providerOptions = { azure: { resourceGroupName: "rg-prod" } };
|
|
84
|
+
|
|
85
|
+
const network = createNetwork("prod", {
|
|
86
|
+
cloud: "azure",
|
|
87
|
+
cidr: "10.1.0.0/16",
|
|
88
|
+
natStrategy: "managed",
|
|
89
|
+
providerOptions,
|
|
90
|
+
}) as INetwork;
|
|
91
|
+
|
|
92
|
+
const cluster = createCluster("prod", {
|
|
93
|
+
cloud: "azure",
|
|
94
|
+
nodePools: [
|
|
95
|
+
{ name: "system", instanceType: "Standard_D2s_v5", minNodes: 2, maxNodes: 3, mode: "system" },
|
|
96
|
+
{ name: "workers", instanceType: "Standard_D4s_v5", minNodes: 1, maxNodes: 10, spot: true, mode: "user" },
|
|
97
|
+
],
|
|
98
|
+
virtualNodes: true,
|
|
99
|
+
providerOptions,
|
|
100
|
+
}, network) as ICluster;
|
|
101
|
+
|
|
102
|
+
createPlatformStack("prod", {
|
|
103
|
+
cluster,
|
|
104
|
+
domain: "example.com",
|
|
105
|
+
externalDns: { dnsProvider: "azure-dns", domainFilters: ["example.com"] },
|
|
106
|
+
});
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Multi-Cloud (AWS + Azure)
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
import { createNetwork, createCluster, createGlobalLoadBalancer } from "@reyemtech/nimbus";
|
|
113
|
+
import type { INetwork, ICluster } from "@reyemtech/nimbus";
|
|
114
|
+
|
|
115
|
+
const providerOptions = {
|
|
116
|
+
aws: { autoMode: true },
|
|
117
|
+
azure: { resourceGroupName: "rg-prod" },
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
// Auto-offsets CIDRs: AWS gets 10.0.0.0/16, Azure gets 10.1.0.0/16
|
|
121
|
+
const networks = createNetwork("prod", {
|
|
122
|
+
cloud: ["aws", "azure"],
|
|
123
|
+
cidr: "10.0.0.0/16",
|
|
124
|
+
natStrategy: "fck-nat",
|
|
125
|
+
providerOptions,
|
|
126
|
+
}) as INetwork[];
|
|
127
|
+
|
|
128
|
+
// Networks auto-matched by provider
|
|
129
|
+
const clusters = createCluster("prod", {
|
|
130
|
+
cloud: ["aws", "azure"],
|
|
131
|
+
nodePools: [
|
|
132
|
+
{ name: "system", instanceType: "t4g.small", minNodes: 2, maxNodes: 3 },
|
|
133
|
+
{ name: "workers", instanceType: "c6a.large", minNodes: 2, maxNodes: 8, spot: true },
|
|
134
|
+
],
|
|
135
|
+
providerOptions,
|
|
136
|
+
}, networks) as ICluster[];
|
|
137
|
+
|
|
138
|
+
// Global Load Balancer — active-active across both clouds
|
|
139
|
+
const glb = createGlobalLoadBalancer("prod", {
|
|
140
|
+
strategy: "active-active",
|
|
141
|
+
clusters,
|
|
142
|
+
domain: "app.example.com",
|
|
143
|
+
healthCheck: { path: "/health", port: 443, protocol: "HTTPS" },
|
|
144
|
+
dnsProvider: "route53",
|
|
145
|
+
});
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## Architecture
|
|
149
|
+
|
|
150
|
+
```
|
|
151
|
+
@reyemtech/nimbus
|
|
152
|
+
├── factories/ # Cloud-agnostic factory functions (primary API)
|
|
153
|
+
├── types/ # CloudProvider, CloudTarget, tags, errors, validation
|
|
154
|
+
├── network/ # VPC (AWS), VNet (Azure) + NAT + CIDR utilities
|
|
155
|
+
├── cluster/ # EKS, AKS (+ Auto Mode, virtual nodes, spot)
|
|
156
|
+
├── dns/ # Route 53, Azure DNS
|
|
157
|
+
├── secrets/ # AWS Secrets Manager, Azure Key Vault
|
|
158
|
+
├── platform/ # Helm: Traefik, cert-manager, External DNS, ArgoCD, Vault, ESO
|
|
159
|
+
├── global-lb/ # DNS-based multi-cloud routing (active-active, failover, geo)
|
|
160
|
+
├── database/ # (interfaces only — RDS, Azure DB, PXC, CNPG)
|
|
161
|
+
├── cache/ # (interfaces only — ElastiCache, Azure Cache, Redis Helm)
|
|
162
|
+
├── storage/ # (interfaces only — S3, Blob, GCS)
|
|
163
|
+
└── queue/ # (interfaces only — SQS, Service Bus, NATS)
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Module Status
|
|
167
|
+
|
|
168
|
+
| Module | AWS | Azure | GCP |
|
|
169
|
+
|--------|-----|-------|-----|
|
|
170
|
+
| **Network** | VPC + fck-nat/managed NAT | VNet + NAT Gateway | Planned |
|
|
171
|
+
| **Cluster** | EKS + Auto Mode | AKS + virtual nodes | Planned |
|
|
172
|
+
| **DNS** | Route 53 | Azure DNS | Planned |
|
|
173
|
+
| **Secrets** | Secrets Manager | Key Vault | Planned |
|
|
174
|
+
| **Platform** | Helm (provider-agnostic) | Helm (provider-agnostic) | Helm (provider-agnostic) |
|
|
175
|
+
| **Global LB** | Route 53 health-checked routing | Planned | — |
|
|
176
|
+
|
|
177
|
+
## API Reference
|
|
178
|
+
|
|
179
|
+
### Factory Functions (Primary API)
|
|
180
|
+
|
|
181
|
+
The factory functions are the recommended way to use this library. They dispatch to the correct cloud-specific implementation based on the `cloud` parameter. Provider-specific options are passed via `providerOptions`.
|
|
182
|
+
|
|
183
|
+
#### `createNetwork(name, config)`
|
|
184
|
+
|
|
185
|
+
Creates a VPC (AWS) or VNet (Azure) with subnets and NAT.
|
|
186
|
+
|
|
187
|
+
| Parameter | Type | Description |
|
|
188
|
+
|-----------|------|-------------|
|
|
189
|
+
| `name` | `string` | Resource name prefix |
|
|
190
|
+
| `config.cloud` | `CloudArg` | `"aws"`, `"azure"`, or `["aws", "azure"]` for multi-cloud |
|
|
191
|
+
| `config.cidr` | `string` | CIDR block (auto-offset for multi-cloud) |
|
|
192
|
+
| `config.natStrategy` | `NatStrategy` | `"managed"`, `"fck-nat"`, or `"none"` |
|
|
193
|
+
| `config.providerOptions` | `IProviderOptions` | Provider-specific options (see below) |
|
|
194
|
+
|
|
195
|
+
Returns: `INetwork` (single cloud) or `INetwork[]` (multi-cloud)
|
|
196
|
+
|
|
197
|
+
#### `createCluster(name, config, networks)`
|
|
198
|
+
|
|
199
|
+
Creates an EKS (AWS) or AKS (Azure) cluster.
|
|
200
|
+
|
|
201
|
+
| Parameter | Type | Description |
|
|
202
|
+
|-----------|------|-------------|
|
|
203
|
+
| `config.nodePools` | `INodePool[]` | Node pool definitions |
|
|
204
|
+
| `config.version` | `string` | Kubernetes version |
|
|
205
|
+
| `config.providerOptions` | `IProviderOptions` | Provider-specific options |
|
|
206
|
+
| `networks` | `INetwork \| INetwork[]` | Network(s) — auto-matched by provider for multi-cloud |
|
|
207
|
+
|
|
208
|
+
Returns: `ICluster` (single cloud) or `ICluster[]` (multi-cloud)
|
|
209
|
+
|
|
210
|
+
#### `createDns(name, config)`
|
|
211
|
+
|
|
212
|
+
Creates a Route 53 (AWS) or Azure DNS zone.
|
|
213
|
+
|
|
214
|
+
Returns: `IDns` (single cloud) or `IDns[]` (multi-cloud)
|
|
215
|
+
|
|
216
|
+
#### `createSecrets(name, config)`
|
|
217
|
+
|
|
218
|
+
Creates an AWS Secrets Manager or Azure Key Vault store.
|
|
219
|
+
|
|
220
|
+
```typescript
|
|
221
|
+
const secrets = createSecrets("prod", { cloud: "aws" }) as ISecrets;
|
|
222
|
+
secrets.putSecret("database", { host: "db.example.com", password: dbPassword });
|
|
223
|
+
const pw = secrets.getSecretRef({ path: "database", key: "password" });
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
Returns: `ISecrets` (single cloud) or `ISecrets[]` (multi-cloud)
|
|
227
|
+
|
|
228
|
+
#### Provider Options
|
|
229
|
+
|
|
230
|
+
```typescript
|
|
231
|
+
providerOptions: {
|
|
232
|
+
aws: {
|
|
233
|
+
// Network
|
|
234
|
+
fckNatInstanceType: "t4g.nano",
|
|
235
|
+
availabilityZoneCount: 2,
|
|
236
|
+
// Cluster
|
|
237
|
+
autoMode: true,
|
|
238
|
+
addons: ["vpc-cni", "coredns"],
|
|
239
|
+
endpointAccess: "both",
|
|
240
|
+
},
|
|
241
|
+
azure: {
|
|
242
|
+
resourceGroupName: "my-rg", // Required for all Azure resources
|
|
243
|
+
// Network
|
|
244
|
+
subnetCount: 2,
|
|
245
|
+
// Cluster
|
|
246
|
+
azureCni: true,
|
|
247
|
+
virtualNodes: false,
|
|
248
|
+
aadTenantId: "...",
|
|
249
|
+
dnsPrefix: "...",
|
|
250
|
+
// Secrets
|
|
251
|
+
tenantId: "...", // Required for Key Vault
|
|
252
|
+
objectId: "...",
|
|
253
|
+
sku: "standard",
|
|
254
|
+
},
|
|
255
|
+
}
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
### Direct Cloud Functions (Escape Hatch)
|
|
259
|
+
|
|
260
|
+
For maximum control, you can still use cloud-specific functions directly:
|
|
261
|
+
|
|
262
|
+
- `createAwsNetwork(name, config, options?)` / `createAzureNetwork(name, config, options)`
|
|
263
|
+
- `createEksCluster(name, config, network, options?)` / `createAksCluster(name, config, network, options)`
|
|
264
|
+
- `createRoute53Dns(name, config)` / `createAzureDns(name, config, options)`
|
|
265
|
+
- `createAwsSecrets(name, config)` / `createAzureSecrets(name, config, options)`
|
|
266
|
+
|
|
267
|
+
### Platform Stack
|
|
268
|
+
|
|
269
|
+
#### `createPlatformStack(name, config)`
|
|
270
|
+
|
|
271
|
+
Deploys Helm-based platform components to one or more clusters.
|
|
272
|
+
|
|
273
|
+
| Component | Default | Chart |
|
|
274
|
+
|-----------|---------|-------|
|
|
275
|
+
| Traefik | Enabled | `traefik/traefik` v34.3.0 |
|
|
276
|
+
| cert-manager | Enabled | `jetstack/cert-manager` v1.17.2 |
|
|
277
|
+
| External DNS | If configured | `kubernetes-sigs/external-dns` v1.16.1 |
|
|
278
|
+
| ArgoCD | Disabled | `argoproj/argo-cd` v7.8.26 |
|
|
279
|
+
| Vault | Disabled | `hashicorp/vault` v0.29.1 |
|
|
280
|
+
| External Secrets | Disabled | `external-secrets/external-secrets` v0.14.4 |
|
|
281
|
+
|
|
282
|
+
### Global Load Balancer
|
|
283
|
+
|
|
284
|
+
#### `createGlobalLoadBalancer(name, config)`
|
|
285
|
+
|
|
286
|
+
Routes traffic across clusters using DNS-based health checks.
|
|
287
|
+
|
|
288
|
+
| Strategy | Behavior |
|
|
289
|
+
|----------|----------|
|
|
290
|
+
| `active-active` | Weighted routing — equal traffic to all healthy clusters |
|
|
291
|
+
| `active-passive` | Failover — primary cluster, secondary on failure |
|
|
292
|
+
| `geo` | Geolocation — route by client continent |
|
|
293
|
+
|
|
294
|
+
### CIDR Utilities
|
|
295
|
+
|
|
296
|
+
```typescript
|
|
297
|
+
import { parseCidr, cidrsOverlap, buildCidrMap, autoOffsetCidrs } from "@reyemtech/nimbus";
|
|
298
|
+
|
|
299
|
+
// Parse CIDR to numeric range
|
|
300
|
+
parseCidr("10.0.0.0/16"); // { network, prefix, size, start, end }
|
|
301
|
+
|
|
302
|
+
// Check overlap
|
|
303
|
+
cidrsOverlap("10.0.0.0/16", "10.0.5.0/24"); // true
|
|
304
|
+
|
|
305
|
+
// Auto-generate non-overlapping CIDRs
|
|
306
|
+
autoOffsetCidrs(3); // ["10.0.0.0/16", "10.1.0.0/16", "10.2.0.0/16"]
|
|
307
|
+
|
|
308
|
+
// Build a cloud-to-CIDR map with conflict detection
|
|
309
|
+
buildCidrMap(["aws", "azure"], { aws: "10.0.0.0/16" });
|
|
310
|
+
// => { aws: "10.0.0.0/16", azure: "10.1.0.0/16" }
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
### Cross-Cloud Validation
|
|
314
|
+
|
|
315
|
+
```typescript
|
|
316
|
+
import { validateMultiCloud, validateResourceName, isFeatureSupported } from "@reyemtech/nimbus";
|
|
317
|
+
|
|
318
|
+
// Validate multi-cloud config (checks duplicates + naming)
|
|
319
|
+
validateMultiCloud([
|
|
320
|
+
{ provider: "aws", region: "us-east-1" },
|
|
321
|
+
{ provider: "azure", region: "canadacentral" },
|
|
322
|
+
], "my-cluster"); // { valid: true, errors: [], warnings: [] }
|
|
323
|
+
|
|
324
|
+
// Check feature availability
|
|
325
|
+
isFeatureSupported("fck-nat", "aws"); // true
|
|
326
|
+
isFeatureSupported("fck-nat", "azure"); // false
|
|
327
|
+
|
|
328
|
+
// Validate resource names per provider
|
|
329
|
+
validateResourceName("MyCluster", "gcp"); // warns about uppercase
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
### Tags
|
|
333
|
+
|
|
334
|
+
```typescript
|
|
335
|
+
import { normalizeTags, mergeWithRequiredTags } from "@reyemtech/nimbus";
|
|
336
|
+
|
|
337
|
+
// GCP label normalization (lowercase, no special chars, max 63)
|
|
338
|
+
normalizeTags({ "Cost Center": "R&D" }, "gcp"); // { "cost-center": "r-d" }
|
|
339
|
+
|
|
340
|
+
// Merge required tags (environment, client, costCenter, managedBy)
|
|
341
|
+
mergeWithRequiredTags(
|
|
342
|
+
{ environment: "prod", client: "acme", costCenter: "eng" },
|
|
343
|
+
{ custom: "value" },
|
|
344
|
+
); // { environment: "prod", client: "acme", costCenter: "eng", managedBy: "nimbus", custom: "value" }
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
## Escape Hatches
|
|
348
|
+
|
|
349
|
+
Every resource exposes its cloud-native object via `nativeResource`:
|
|
350
|
+
|
|
351
|
+
```typescript
|
|
352
|
+
import * as aws from "@pulumi/aws";
|
|
353
|
+
|
|
354
|
+
const cluster = createCluster("prod", { cloud: "aws", ... }, network) as ICluster;
|
|
355
|
+
const eksCluster = cluster.nativeResource as aws.eks.Cluster;
|
|
356
|
+
eksCluster.arn.apply(arn => console.log("EKS ARN:", arn));
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
## Cloud Target Flexibility
|
|
360
|
+
|
|
361
|
+
All factory functions accept flexible cloud arguments:
|
|
362
|
+
|
|
363
|
+
```typescript
|
|
364
|
+
// String shorthand (uses DEFAULT_REGIONS)
|
|
365
|
+
createNetwork("prod", { cloud: "aws", ... });
|
|
366
|
+
|
|
367
|
+
// Explicit target
|
|
368
|
+
createNetwork("prod", { cloud: { provider: "aws", region: "eu-west-1" }, ... });
|
|
369
|
+
|
|
370
|
+
// Multi-cloud array
|
|
371
|
+
createNetwork("prod", { cloud: ["aws", "azure"], ... });
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
## Error Handling
|
|
375
|
+
|
|
376
|
+
All errors extend `AnyCloudError` with typed error codes:
|
|
377
|
+
|
|
378
|
+
| Error | Code | When |
|
|
379
|
+
|-------|------|------|
|
|
380
|
+
| `CloudValidationError` | `CLOUD_VALIDATION` | Invalid provider or target |
|
|
381
|
+
| `CidrError` | `CIDR_OVERLAP` / `CIDR_INVALID` | CIDR conflicts or malformed |
|
|
382
|
+
| `UnsupportedFeatureError` | `UNSUPPORTED_FEATURE` | Feature not available on provider |
|
|
383
|
+
| `ConfigError` | `CONFIG_MISSING` / `CONFIG_INVALID` | Missing or invalid configuration |
|
|
384
|
+
|
|
385
|
+
## Development
|
|
386
|
+
|
|
387
|
+
```bash
|
|
388
|
+
npm install
|
|
389
|
+
npm run typecheck # Type checking
|
|
390
|
+
npm run lint # ESLint
|
|
391
|
+
npm run format # Prettier
|
|
392
|
+
npm test # Vitest (unit tests)
|
|
393
|
+
npm run test:coverage # With coverage thresholds
|
|
394
|
+
npm run build # ESM + CJS dual build
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
## License
|
|
398
|
+
|
|
399
|
+
MIT
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AWS EKS cluster implementation with Auto Mode support.
|
|
3
|
+
*
|
|
4
|
+
* @module aws/cluster
|
|
5
|
+
*/
|
|
6
|
+
import type { ICluster, IClusterConfig } from "../cluster";
|
|
7
|
+
import type { INetwork } from "../network";
|
|
8
|
+
/** AWS-specific EKS options beyond the base config. */
|
|
9
|
+
export interface IEksOptions {
|
|
10
|
+
/** Enable EKS Auto Mode (managed node provisioning). Default: false. */
|
|
11
|
+
readonly autoMode?: boolean;
|
|
12
|
+
/** EKS add-ons to install. Default: vpc-cni, coredns, kube-proxy. */
|
|
13
|
+
readonly addons?: ReadonlyArray<string>;
|
|
14
|
+
/** Endpoint access: "public", "private", or "both". Default: "both". */
|
|
15
|
+
readonly endpointAccess?: "public" | "private" | "both";
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Create an EKS cluster with optional Auto Mode.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```typescript
|
|
22
|
+
* const cluster = createEksCluster("prod", {
|
|
23
|
+
* cloud: "aws",
|
|
24
|
+
* nodePools: [
|
|
25
|
+
* { name: "system", instanceType: "t4g.small", minNodes: 2, maxNodes: 3 },
|
|
26
|
+
* { name: "spot", instanceType: "t4g.medium", minNodes: 1, maxNodes: 10, spot: true },
|
|
27
|
+
* ],
|
|
28
|
+
* }, network, { autoMode: true });
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export declare function createEksCluster(name: string, config: IClusterConfig, network: INetwork, options?: IEksOptions): ICluster;
|
|
32
|
+
//# sourceMappingURL=cluster.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cluster.d.ts","sourceRoot":"","sources":["../../../src/aws/cluster.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC3D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAG3C,uDAAuD;AACvD,MAAM,WAAW,WAAW;IAC1B,wEAAwE;IACxE,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,qEAAqE;IACrE,QAAQ,CAAC,MAAM,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IACxC,wEAAwE;IACxE,QAAQ,CAAC,cAAc,CAAC,EAAE,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC;CACzD;AAID;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE,QAAQ,EACjB,OAAO,CAAC,EAAE,WAAW,GACpB,QAAQ,CA8IV"}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* AWS EKS cluster implementation with Auto Mode support.
|
|
4
|
+
*
|
|
5
|
+
* @module aws/cluster
|
|
6
|
+
*/
|
|
7
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
8
|
+
if (k2 === undefined) k2 = k;
|
|
9
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
10
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
11
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
12
|
+
}
|
|
13
|
+
Object.defineProperty(o, k2, desc);
|
|
14
|
+
}) : (function(o, m, k, k2) {
|
|
15
|
+
if (k2 === undefined) k2 = k;
|
|
16
|
+
o[k2] = m[k];
|
|
17
|
+
}));
|
|
18
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
19
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
20
|
+
}) : function(o, v) {
|
|
21
|
+
o["default"] = v;
|
|
22
|
+
});
|
|
23
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
24
|
+
var ownKeys = function(o) {
|
|
25
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
26
|
+
var ar = [];
|
|
27
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
28
|
+
return ar;
|
|
29
|
+
};
|
|
30
|
+
return ownKeys(o);
|
|
31
|
+
};
|
|
32
|
+
return function (mod) {
|
|
33
|
+
if (mod && mod.__esModule) return mod;
|
|
34
|
+
var result = {};
|
|
35
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
36
|
+
__setModuleDefault(result, mod);
|
|
37
|
+
return result;
|
|
38
|
+
};
|
|
39
|
+
})();
|
|
40
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
41
|
+
exports.createEksCluster = createEksCluster;
|
|
42
|
+
const aws = __importStar(require("@pulumi/aws"));
|
|
43
|
+
const k8s = __importStar(require("@pulumi/kubernetes"));
|
|
44
|
+
const pulumi = __importStar(require("@pulumi/pulumi"));
|
|
45
|
+
const types_1 = require("../types");
|
|
46
|
+
const DEFAULT_ADDONS = ["vpc-cni", "coredns", "kube-proxy"];
|
|
47
|
+
/**
|
|
48
|
+
* Create an EKS cluster with optional Auto Mode.
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```typescript
|
|
52
|
+
* const cluster = createEksCluster("prod", {
|
|
53
|
+
* cloud: "aws",
|
|
54
|
+
* nodePools: [
|
|
55
|
+
* { name: "system", instanceType: "t4g.small", minNodes: 2, maxNodes: 3 },
|
|
56
|
+
* { name: "spot", instanceType: "t4g.medium", minNodes: 1, maxNodes: 10, spot: true },
|
|
57
|
+
* ],
|
|
58
|
+
* }, network, { autoMode: true });
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
function createEksCluster(name, config, network, options) {
|
|
62
|
+
const cloud = Array.isArray(config.cloud) ? (config.cloud[0] ?? "aws") : config.cloud;
|
|
63
|
+
const target = (0, types_1.resolveCloudTarget)(cloud);
|
|
64
|
+
const tags = config.tags ?? {};
|
|
65
|
+
const autoMode = options?.autoMode ?? config.autoMode ?? false;
|
|
66
|
+
const addons = options?.addons ?? DEFAULT_ADDONS;
|
|
67
|
+
const endpointAccess = options?.endpointAccess ?? "both";
|
|
68
|
+
// EKS cluster IAM role
|
|
69
|
+
const clusterRole = new aws.iam.Role(`${name}-cluster-role`, {
|
|
70
|
+
namePrefix: `${name}-eks`,
|
|
71
|
+
assumeRolePolicy: JSON.stringify({
|
|
72
|
+
Version: "2012-10-17",
|
|
73
|
+
Statement: [
|
|
74
|
+
{
|
|
75
|
+
Action: "sts:AssumeRole",
|
|
76
|
+
Effect: "Allow",
|
|
77
|
+
Principal: { Service: "eks.amazonaws.com" },
|
|
78
|
+
},
|
|
79
|
+
],
|
|
80
|
+
}),
|
|
81
|
+
tags,
|
|
82
|
+
});
|
|
83
|
+
new aws.iam.RolePolicyAttachment(`${name}-cluster-policy`, {
|
|
84
|
+
policyArn: "arn:aws:iam::aws:policy/AmazonEKSClusterPolicy",
|
|
85
|
+
role: clusterRole.name,
|
|
86
|
+
});
|
|
87
|
+
// EKS Cluster
|
|
88
|
+
const cluster = new aws.eks.Cluster(`${name}-cluster`, {
|
|
89
|
+
name,
|
|
90
|
+
roleArn: clusterRole.arn,
|
|
91
|
+
version: config.version,
|
|
92
|
+
vpcConfig: {
|
|
93
|
+
subnetIds: pulumi
|
|
94
|
+
.all([network.publicSubnetIds, network.privateSubnetIds])
|
|
95
|
+
.apply(([pub, priv]) => [...pub, ...priv]),
|
|
96
|
+
endpointPrivateAccess: endpointAccess === "private" || endpointAccess === "both",
|
|
97
|
+
endpointPublicAccess: endpointAccess === "public" || endpointAccess === "both",
|
|
98
|
+
},
|
|
99
|
+
computeConfig: autoMode ? { enabled: true } : undefined,
|
|
100
|
+
accessConfig: { authenticationMode: "API_AND_CONFIG_MAP" },
|
|
101
|
+
tags: { ...tags, [`kubernetes.io/cluster/${name}`]: "owned" },
|
|
102
|
+
});
|
|
103
|
+
// Node pools — Auto Mode delegates to EKS, standard uses managed node groups
|
|
104
|
+
const nodeGroups = [];
|
|
105
|
+
if (!autoMode) {
|
|
106
|
+
for (const np of config.nodePools) {
|
|
107
|
+
const nodeRole = createNodeRole(`${name}-${np.name}`, tags);
|
|
108
|
+
nodeGroups.push(new aws.eks.NodeGroup(`${name}-ng-${np.name}`, {
|
|
109
|
+
clusterName: cluster.name,
|
|
110
|
+
nodeGroupName: `${name}-${np.name}`,
|
|
111
|
+
nodeRoleArn: nodeRole.arn,
|
|
112
|
+
instanceTypes: [np.instanceType],
|
|
113
|
+
capacityType: np.spot ? "SPOT" : "ON_DEMAND",
|
|
114
|
+
scalingConfig: {
|
|
115
|
+
desiredSize: np.desiredNodes ?? np.minNodes,
|
|
116
|
+
minSize: np.minNodes,
|
|
117
|
+
maxSize: np.maxNodes,
|
|
118
|
+
},
|
|
119
|
+
subnetIds: network.privateSubnetIds,
|
|
120
|
+
labels: np.labels,
|
|
121
|
+
tags: { ...tags, Name: `${name}-${np.name}` },
|
|
122
|
+
}));
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
const firstNodeGroup = nodeGroups[0];
|
|
126
|
+
// EKS Add-ons
|
|
127
|
+
for (const addon of addons) {
|
|
128
|
+
new aws.eks.Addon(`${name}-addon-${addon}`, {
|
|
129
|
+
clusterName: cluster.name,
|
|
130
|
+
addonName: addon,
|
|
131
|
+
resolveConflictsOnCreate: "OVERWRITE",
|
|
132
|
+
resolveConflictsOnUpdate: "OVERWRITE",
|
|
133
|
+
tags,
|
|
134
|
+
}, firstNodeGroup ? { dependsOn: [firstNodeGroup] } : undefined);
|
|
135
|
+
}
|
|
136
|
+
// K8s provider for this cluster
|
|
137
|
+
const kubeconfig = pulumi
|
|
138
|
+
.all([cluster.endpoint, cluster.certificateAuthority, cluster.name])
|
|
139
|
+
.apply(([endpoint, ca, clusterName]) => JSON.stringify({
|
|
140
|
+
apiVersion: "v1",
|
|
141
|
+
kind: "Config",
|
|
142
|
+
clusters: [
|
|
143
|
+
{
|
|
144
|
+
cluster: {
|
|
145
|
+
server: endpoint,
|
|
146
|
+
"certificate-authority-data": ca.data,
|
|
147
|
+
},
|
|
148
|
+
name: clusterName,
|
|
149
|
+
},
|
|
150
|
+
],
|
|
151
|
+
contexts: [
|
|
152
|
+
{
|
|
153
|
+
context: { cluster: clusterName, user: clusterName },
|
|
154
|
+
name: clusterName,
|
|
155
|
+
},
|
|
156
|
+
],
|
|
157
|
+
"current-context": clusterName,
|
|
158
|
+
users: [
|
|
159
|
+
{
|
|
160
|
+
name: clusterName,
|
|
161
|
+
user: {
|
|
162
|
+
exec: {
|
|
163
|
+
apiVersion: "client.authentication.k8s.io/v1beta1",
|
|
164
|
+
command: "aws",
|
|
165
|
+
args: ["eks", "get-token", "--cluster-name", clusterName],
|
|
166
|
+
},
|
|
167
|
+
},
|
|
168
|
+
},
|
|
169
|
+
],
|
|
170
|
+
}));
|
|
171
|
+
const provider = new k8s.Provider(`${name}-k8s`, {
|
|
172
|
+
kubeconfig,
|
|
173
|
+
});
|
|
174
|
+
return {
|
|
175
|
+
name,
|
|
176
|
+
cloud: target,
|
|
177
|
+
endpoint: cluster.endpoint,
|
|
178
|
+
kubeconfig,
|
|
179
|
+
version: cluster.version,
|
|
180
|
+
nodePools: config.nodePools,
|
|
181
|
+
nativeResource: cluster,
|
|
182
|
+
provider,
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
function createNodeRole(name, tags) {
|
|
186
|
+
const role = new aws.iam.Role(`${name}-node-role`, {
|
|
187
|
+
namePrefix: `${name}-node`,
|
|
188
|
+
assumeRolePolicy: JSON.stringify({
|
|
189
|
+
Version: "2012-10-17",
|
|
190
|
+
Statement: [
|
|
191
|
+
{
|
|
192
|
+
Action: "sts:AssumeRole",
|
|
193
|
+
Effect: "Allow",
|
|
194
|
+
Principal: { Service: "ec2.amazonaws.com" },
|
|
195
|
+
},
|
|
196
|
+
],
|
|
197
|
+
}),
|
|
198
|
+
tags,
|
|
199
|
+
});
|
|
200
|
+
const policies = [
|
|
201
|
+
"arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy",
|
|
202
|
+
"arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy",
|
|
203
|
+
"arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly",
|
|
204
|
+
];
|
|
205
|
+
for (const policyArn of policies) {
|
|
206
|
+
const shortName = policyArn.split("/").pop() ?? policyArn;
|
|
207
|
+
new aws.iam.RolePolicyAttachment(`${name}-${shortName}`, {
|
|
208
|
+
policyArn,
|
|
209
|
+
role: role.name,
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
return role;
|
|
213
|
+
}
|
|
214
|
+
//# sourceMappingURL=cluster.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cluster.js","sourceRoot":"","sources":["../../../src/aws/cluster.ts"],"names":[],"mappings":"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"}
|