Skip to content

Commit 98d6944

Browse files
v24.4.0 (#36)
* feat(aws): add db subnets * feat: up/down/get-bastion commands * feat: improve up/down commands * feat(aws): repositories * feat(do): registry * feat(aws): domains + cerificates * feat(aws): rebase * feat(aws): bump versions * feat: set version to 24.1.0 * feat(aws): provider,group,network,managed layers + docker registry, dns zones * feat(aws): run on macos * feat(aws): provider layer * feat(aws): group layer * feat(aws): managed layer * feat(aws): one domain name per group * feat(aws): app layer postrges dbs * feat(aws): v24.4.0-rc.1 * Update README.md * Update README.md * feat(aws): v24.4.0-rc.2
1 parent 7946ed5 commit 98d6944

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+1127
-453
lines changed

.env.template

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,3 @@
1-
TF_VAR_org_id=
2-
TF_VAR_project_id=
3-
TF_VAR_group_id=
4-
TF_VAR_env_id=
5-
TF_VAR_tenant_id=
6-
71
#TF_TOKEN_app_terraform_io=
82

93
#TF_VAR_backend_pg_conn_str=
@@ -13,3 +7,18 @@ TF_VAR_tenant_id=
137
#TF_VAR_backend_s3_region=
148
#TF_VAR_backend_s3_bucket=
159
#TF_VAR_backend_s3_dynamodb_table=
10+
11+
TF_VAR_org_id=
12+
TF_VAR_project_id=
13+
TF_VAR_group_id=
14+
TF_VAR_env_id=
15+
TF_VAR_tenant_id=
16+
17+
#TF_VAR_registry=
18+
#TF_VAR_repositories=
19+
20+
TF_VAR_domain_name=myproject.dev
21+
TF_VAR_dns_records=myproject.dev,api,admin
22+
23+
TF_VAR_rds_pg_db_size=db.t3.micro
24+
TF_VAR_databases={ "user" = { owner = "admin", password = "admin" }, "auth" = { owner = "admin", password = "admin" } }

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,5 @@
2424
**/backend.tf
2525

2626
# ignore .pem
27-
*.pem
27+
*.pem
28+
*.addr

.tln.conf

Lines changed: 68 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -109,30 +109,42 @@ const getScript = (env, reverse) => {
109109
});
110110
}
111111

112+
const getTerraformOpts = (env) => {
113+
const i = env.TLN_CLOUDS_INIT?' --init':'';
114+
const p = env.TLN_CLOUDS_PLAN?' --plan':'';
115+
const a = env.TLN_CLOUDS_APPLY?' --apply':'';
116+
const aa = env.TLN_CLOUDS_AUTO_APPROVE?' -auto-approve':'';
117+
return `${i}${p}${a}${aa}`;
118+
}
119+
112120
module.exports = {
113121
options: async (tln, args) => {
114122
args
115123
.prefix('TLN_CLOUDS')
116124
.option('backend', { describe: 'Defines which backend provider should be used (cloud, pg)', default: null, type: 'string' })
117125
.option('tenant', { describe: 'Tenant Id', default: null, type: 'string' })
118-
.option('state', { describe: 'Defines how store name will be built: project,provider,group,env,layer,tenant,<custom_string>', default: 'project,provider,group,env,layer', type: 'string' })
126+
.option('state', { describe: 'Defines how store name will be built: project,provider,group,env,layer,tenant,<custom_string>', default: null, type: 'string' })
119127
.option('init', { describe: 'Run Terraform init', default: false, type: 'boolean' })
120128
.option('upgrade', { describe: 'Run Terraform upgrade mode for init', default: false, type: 'boolean' })
121129
.option('plan', { describe: 'Run Terraform plan', default: false, type: 'boolean' })
122130
.option('apply', { describe: 'Run Terraform apply', default: false, type: 'boolean' })
123131
.option('auto-approve', { describe: 'Tun on auto approve for apply & destroy', default: false, type: 'boolean' })
124-
.option('layers', { describe: 'Select which layers will be included', default: "network,managed", type: 'string' })
132+
.option('layers', { describe: 'Select which layers will be included', default: null, type: 'string' })
125133
.option('bastion', { describe: 'Bastion address in form user@ip', default: null, type: 'string' })
126-
.option('bridge-port', { describe: 'Local port for bridge to bastion ', default: '8888', type: 'string' })
127134
.option('deamon', { describe: 'Deamon mode for SSH connection', default: false, type: 'boolean' })
135+
.option('ci', { describe: 'CI mode', default: false, type: 'boolean' })
136+
/*
137+
DEPRIECATED
138+
.option('bridge-port', { describe: 'Local port for bridge to bastion ', default: '8888', type: 'string' })
139+
*/
128140
;
129141
},
130142
env: async (tln, env) => {
131143
if (env.TLN_CLOUDS_TENANT) {
132144
env.TF_VAR_tenant_id = env.TLN_CLOUDS_TENANT;
133145
}
134146
},
135-
dotenvs: async (tln) => ['.env'],
147+
dotenvs: async (tln) => { if (fs.existsSync('.env')) return ['.env']; else return [] },
136148
inherits: async (tln) => [],
137149
depends: async (tln) => [],
138150
steps: async (tln) => [
@@ -145,16 +157,15 @@ module.exports = {
145157
}
146158
},
147159
{ id: 'get-bastion', builder: async (tln, script) => {
148-
script.set([
149-
`tln exec -c 'cd network && terraform output bastion_remote_address'`,
150-
]);
160+
script.set([`cat './network/${script.env.TF_VAR_env_id}-bastion.addr'`]);
151161
}},
152-
{ id: 'bridge', builder: async (tln, script) => {
153-
const port = script.env.TLN_CLOUDS_BRIDGE_PORT;
162+
{ id: 'sshuttle', builder: async (tln, script) => {
163+
const daemon = script.env.TLN_CLOUDS_DEAMON ? ' --daemon' : '';
164+
const ci = script.env.TLN_CLOUDS_CI ? ' -q -o CheckHostIP=no -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null' : '';
154165
switch (script.env.TLN_COMPONENT_ID) {
155166
case 'aws':
156167
script.set([`
157-
ssh -i ./network/${script.env.TF_VAR_env_id}-bastion-ssh-key.pem -L${port}:127.0.0.1:${port} ${script.env.TLN_CLOUDS_BASTION}
168+
sshuttle --dns${daemon} -vr ${script.env.TLN_CLOUDS_BASTION} 0/0 --ssh-cmd 'ssh${ci} -i ./network/${script.env.TF_VAR_env_id}-bastion-ssh-key.pem'
158169
`]);
159170
break;
160171
case 'azure':
@@ -165,27 +176,68 @@ ssh -i ./network/${script.env.TF_VAR_env_id}-bastion-ssh-key.pem -L${port}:127.0
165176
}
166177
},
167178
{ id: 'connect', builder: async (tln, script) => {
179+
script.set([
180+
`tln sshuttle -- --bastion $(tln get-bastion)`
181+
]);
182+
}
183+
},
184+
{ id: 'up', builder: async (tln, script) => {
185+
const opts = getTerraformOpts(script.env);
186+
script.set([`
187+
tln construct -- --backend cloud${opts} --layers provider --state project,provider
188+
tln construct -- --backend cloud${opts} --layers group --state project,provider,group
189+
tln construct -- --backend cloud${opts} --layers network,managed --state project,provider,group,env,layer
190+
${script.env.TLN_CLOUDS_CI ? 'tln sshuttle -- --bastion \$(tln get-bastion) --deamon' : ''}
191+
tln construct -- --backend cloud${opts} --layers app --state project,provider,group,env,layer
192+
`].concat(
193+
(script.env.TF_VAR_tenant_id) ? [
194+
`tln construct -- --backend cloud${opts} --layers tenant --state project,provider,group,env,tenant --tenant ${script.env.TF_VAR_tenant_id}`
195+
]:[]
196+
));
197+
}
198+
},
199+
{ id: 'down', builder: async (tln, script) => {
200+
const opts = getTerraformOpts(script.env);
201+
script.set([
202+
`${script.env.TLN_CLOUDS_CI ? 'tln sshuttle -- --bastion \$(tln get-bastion) --deamon' : ''}`,
203+
].concat((
204+
(script.env.TF_VAR_tenant_id) ? [
205+
`tln deconstruct -- --backend cloud${opts} --layers tenant --state project,provider,group,env,tenant --tenant ${script.env.TF_VAR_tenant_id}`,
206+
]:[]
207+
)).concat([`
208+
tln deconstruct -- --backend cloud${opts} --layers network,managed,app --state project,provider,group,env,layer
209+
tln deconstruct -- --backend cloud${opts} --layers group --state project,provider,group
210+
tln deconstruct -- --backend cloud${opts} --layers provider --state project,provider
211+
`]
212+
));
213+
}
214+
},
215+
/*
216+
DEPRIECATED
217+
{ id: 'bridge', builder: async (tln, script) => {
168218
const port = script.env.TLN_CLOUDS_BRIDGE_PORT;
169219
switch (script.env.TLN_COMPONENT_ID) {
170220
case 'aws':
171221
script.set([`
172-
export HTTPS_PROXY=127.0.0.1:${port}
173-
tln shell
222+
ssh -i ./network/${script.env.TF_VAR_env_id}-bastion-ssh-key.pem -L${port}:127.0.0.1:${port} ${script.env.TLN_CLOUDS_BASTION}
174223
`]);
175224
break;
176225
case 'azure':
177226
break;
178227
case 'gcp':
179228
break;
229+
case 'do':
230+
break;
180231
}
181232
}
182233
},
183-
{ id: 'sshuttle', builder: async (tln, script) => {
184-
const daemon = script.env.TLN_CLOUDS_DEAMON ? ' --daemon' : '';
234+
{ id: 'connect', builder: async (tln, script) => {
235+
const port = script.env.TLN_CLOUDS_BRIDGE_PORT;
185236
switch (script.env.TLN_COMPONENT_ID) {
186237
case 'aws':
187238
script.set([`
188-
sshuttle --dns${daemon} -vr ${script.env.TLN_CLOUDS_BASTION} 0/0 --ssh-cmd 'ssh -i ./network/${script.env.TF_VAR_env_id}-bastion-ssh-key.pem'
239+
export HTTPS_PROXY=127.0.0.1:${port}
240+
tln shell
189241
`]);
190242
break;
191243
case 'azure':
@@ -195,30 +247,7 @@ sshuttle --dns${daemon} -vr ${script.env.TLN_CLOUDS_BASTION} 0/0 --ssh-cmd 'ssh
195247
}
196248
}
197249
},
198-
{ id: 'up', builder: async (tln, script) => {
199-
const tenant = (script.env.TF_VAR_tenant_id) ? `tln construct -- --backend cloud --init --apply --layers tenant --state project,provider,group,env,tenant --tenant ${script.env.TF_VAR_tenant_id}` : '';
200-
script.set([`
201-
tln construct -- --backend cloud --init --apply --layers provider --state project,provider
202-
tln construct -- --backend cloud --init --apply --layers group --state project,provider,group
203-
tln construct -- --backend cloud --init --apply --layers network
204-
#tln sshuttle -- --bastion user@ip --deamon
205-
tln construct -- --backend cloud --init --apply --layers managed,app
206-
${tenant}
207-
`]);
208-
}
209-
},
210-
{ id: 'down', builder: async (tln, script) => {
211-
const tenant = (script.env.TF_VAR_tenant_id) ? `tln deconstruct -- --backend cloud --init --apply --layers tenant --state project,provider,group,env,tenant --tenant ${script.env.TF_VAR_tenant_id}` : ''
212-
script.set([`
213-
#tln sshuttle -- --bastion user@ip --deamon
214-
${tenant}
215-
tln deconstruct -- --backend cloud --init --apply --layers network,managed,app
216-
tln deconstruct -- --backend cloud --init --apply --layers group --state project,provider,group
217-
tln deconstruct -- --backend cloud --init --apply --layers provider --state project,provider
218-
`]);
219-
}
220-
},
221-
250+
*/
222251
],
223252
components: async (tln) => []
224253
}

README.md

Lines changed: 83 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* supports AWS, DO (Azure, GCP - in progress)
77
* provides Multi-tenancy feature via layers architecture (provider, group, network, managed, app, tenant)
88
* implements easy-to-construct multiple environment approach, controls by single environment variable - **TF_VAR_env_id**
9-
* IaC via Terraform
9+
* IaC via Terraform and Helm
1010
* supports multiple backend providers - Local, Cloud, PG (S3 - in progress)
1111

1212
## Infrastructure Instance layers
@@ -16,33 +16,40 @@
1616
* Install [tln](https://www.npmjs.com/package/tln-cli)
1717
* Goto **projects** folder from tln-cli installation above and clone repository
1818
```
19-
git clone --depth 1 --branch v23.11.1 git@github.com:project-talan/tln-clouds.git && cd tln-clouds
19+
git clone --depth 1 --branch v24.4.0 git@github.com:project-talan/tln-clouds.git && cd tln-clouds
2020
```
2121
> Important<br>
22-
> Commands below assume that Terraform Cloud is used as a storage for states<br/>
23-
> By skipping **--backend cloud** local backend will be used
22+
> * Commands below assume that Terraform Cloud is used as a storage for states<br/>
23+
> * By skipping **--backend cloud** local backend will be used<br/>
24+
> * You will need **domain name** to configure all layers (myproject.io as an example below)
2425
* Use **.env.template** file as an examples and fill it with actual values
2526
* root .env
2627
```
28+
TF_TOKEN_app_terraform_io=<your_terraform_cloud_token>
29+
2730
TF_VAR_org_id=<your_terraform_cloud_org>
28-
TF_VAR_project_id=tln-clouds
31+
TF_VAR_project_id=myproject
2932
TF_VAR_group_id=dev
3033
TF_VAR_env_id=dev01
31-
TF_VAR_tenant_id=
34+
TF_VAR_tenant_id=balenciaga
35+
36+
TF_VAR_repositories=io.myproject.services.api,io.myproject.web.landing
3237
33-
TF_TOKEN_app_terraform_io=<your_terraform_cloud_token>
38+
TF_VAR_domain_name=myproject.io
39+
TF_VAR_dns_records=myproject.io,api
40+
41+
TF_VAR_rds_pg_db_size=db.t3.micro
42+
TF_VAR_databases={ "user" = { owner = "admin", password = "admin" }, "auth" = { owner = "admin", password = "admin" } }
3443
```
3544
3645
### AWS
3746
* Create **aws/.env** file using **aws/.env.template** as an example
3847
```
3948
AWS_ACCESS_KEY_ID=<your_aws_id>
4049
AWS_SECRET_ACCESS_KEY=<your_aws_key>
41-
AWS_SESSION_TOKEN=
42-
4350
AWS_DEFAULT_REGION=eu-central-1
4451
45-
TF_VAR_aws_k8s_version=1.28
52+
TF_VAR_aws_k8s_version=1.29
4653
TF_VAR_aws_k8s_nodes_min=1
4754
TF_VAR_aws_k8s_nodes_desired=2
4855
TF_VAR_aws_k8s_nodes_max=3
@@ -53,40 +60,75 @@
5360
```
5461
tln install aws --depends
5562
```
56-
* Construct AWS Dev infrastructure instance
63+
* Construct four AWS Dev infrastructure instance layers
64+
65+
(1) Provider layer - ERC
5766
```
58-
tln construct aws -- --backend cloud --init --plan --apply
67+
tln construct aws -- --backend cloud --init --apply --layers provider --state project,provider
5968
```
60-
* Verify access to the k8s cluster and install/uninstall ingress
61-
* Open separate terminal and establish connection with bastion, use **user@ip** from previous command output (bastion_remote_address)
62-
```
63-
tln bridge aws -- --bastion user@ip
64-
```
65-
* Switch back to the original terminal and initiate session for kubectl
66-
```
67-
tln connect aws
68-
```
69-
```
70-
tln nginx-ingress-install@k8s -- --ver 4.8.3
71-
```
72-
```
73-
kubectl get pods --all-namespaces
74-
```
75-
```
76-
tln nginx-ingress-status@k8s
77-
```
78-
* Use DNS address name from command output above to check access to the cluster using browser/curl
79-
* Uninstall Ingress
80-
```
81-
tln nginx-ingress-uninstall@k8s
82-
```
83-
* Close both terminals
84-
```
85-
^d
86-
```
87-
* Deconstruct AWS Dev infrastructure instance
69+
(2) Groupr layer - domain name, certificate & validation. You will need to modify DNS nameservers at your registrar side
70+
```
71+
tln construct aws -- --backend cloud --init --apply --layers group --state project,provider,group
72+
```
73+
(3,4) Network and Managed layers - VPC, Bastion, K8s
74+
```
75+
tln construct aws -- --backend cloud --init --apply --layers network,managed --state project,provider,group,env,layer
76+
```
77+
* At this point you have ready to use cloud infrastructure with K8s and secure access via bastion
78+
79+
(1) Initiate sshuttle connection to the cluster via bastion (first terminal)
80+
```
81+
tln connect aws
82+
```
83+
(2) Open shell with necessary environment variables (second terminal)
84+
```
85+
tln shell aws
86+
```
87+
(3) Check cluster (second terminal)
88+
```
89+
kubectl get pods -A
90+
```
91+
(4) Close shell (second terminal)
92+
```
93+
^D
94+
```
95+
(5) Close sshuttle connection (first terminal)
96+
```
97+
^C
98+
```
99+
* You can go extra mile and deploy your SaaS-specific resources
100+
101+
(1) Start secure sshuttle connection (first terminal)
102+
```
103+
tln connect aws
104+
```
105+
(2) Deploy App layer - Nginx ingress, Postgres DBs, DNS records (second terminal)
106+
```
107+
tln construct aws -- --backend cloud --init --apply --layers app --state project,provider,group,env,layer
108+
```
109+
(3) You can check endpoints availability in browser https://myprojecy.io & https://api.myproject.io
110+
111+
* Now you can deconstruct all layers and free all Cloud resources
112+
113+
(1) Undeploy App layer (second terminal)
114+
```
115+
tln deconstruct aws -- --backend cloud --init --apply --layers app --state project,provider,group,env,layer
116+
```
117+
(2) Close sshuttle connection (first terminal)
118+
```
119+
^C
120+
```
121+
(3,4) Delete Network and Managed layers
122+
```
123+
tln deconstruct aws -- --backend cloud --init --apply --layers network,managed --state project,provider,group,env,layer
124+
```
125+
(5) Delete Groupr layer
126+
```
127+
tln deconstruct aws -- --backend cloud --init --apply --layers group --state project,provider,group
128+
```
129+
(6) Delete Provider layer
88130
```
89-
tln deconstruct aws -- --backend cloud --plan --apply
131+
tln deconstruct aws -- --backend cloud --init --apply --layers provider --state project,provider
90132
```
91133
92134
### Digital Ocean

aws/.env.template

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ AWS_ACCESS_KEY_ID=
22
AWS_SECRET_ACCESS_KEY=
33
AWS_DEFAULT_REGION=eu-central-1
44

5-
TF_VAR_aws_k8s_version=1.28
5+
TF_VAR_aws_k8s_version=1.29
66
TF_VAR_aws_k8s_nodes_min=1
77
TF_VAR_aws_k8s_nodes_desired=2
88
TF_VAR_aws_k8s_nodes_max=3

0 commit comments

Comments
 (0)