swarm_cluster_cli_ope 0.2.1 → 0.4
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +11 -1
- data/Gemfile.lock +6 -6
- data/README.md +103 -1
- data/lib/swarm_cluster_cli_ope/cli.rb +88 -5
- data/lib/swarm_cluster_cli_ope/commands/compose_container.rb +12 -0
- data/lib/swarm_cluster_cli_ope/commands/container.rb +7 -0
- data/lib/swarm_cluster_cli_ope/configuration.rb +27 -3
- data/lib/swarm_cluster_cli_ope/models/compose_container.rb +17 -0
- data/lib/swarm_cluster_cli_ope/models/container.rb +7 -1
- data/lib/swarm_cluster_cli_ope/models/service.rb +0 -1
- data/lib/swarm_cluster_cli_ope/sync_configs/base.rb +10 -1
- data/lib/swarm_cluster_cli_ope/sync_configs/base_database.rb +49 -0
- data/lib/swarm_cluster_cli_ope/sync_configs/copy.rb +3 -7
- data/lib/swarm_cluster_cli_ope/sync_configs/env_configs.rb +78 -0
- data/lib/swarm_cluster_cli_ope/sync_configs/mysql.rb +42 -0
- data/lib/swarm_cluster_cli_ope/sync_configs/post_gres.rb +115 -0
- data/lib/swarm_cluster_cli_ope/sync_configs/rsync.rb +0 -3
- data/lib/swarm_cluster_cli_ope/version.rb +1 -1
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dcf7eb87d7665ee32ead2dff9a05a3a7abb09587c6ffb0dcea8fa8c1dee8564b
|
4
|
+
data.tar.gz: f6f4716e71b2505d0b0e1928679ba92bc572c4382bb165f4ae3a77de5c01abcb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fbe56a69b398f32dfd2ba9ef1328fa3c10f6182f689b38089d8aa3a25e67130ee246459cf84e1b06e688172843b4b64c5aeaaec08fa9856fffd3ab5921625d59
|
7
|
+
data.tar.gz: bd0b42b2043c0462914cfe240c59c931554b675001781642674bc82425c4c5df10aeb782acdcdaac4b1727e3e948bda9f93646455e5eaeb80ad91263239ee71f
|
data/CHANGELOG.md
CHANGED
@@ -1,9 +1,19 @@
|
|
1
1
|
## Changelog
|
2
2
|
|
3
|
+
# 0.4
|
4
|
+
- implementazione push pull con il comando **stacksync** di pg
|
5
|
+
- controllo di versione sul file caricato rispeto a gemma, con conseguente warning
|
6
|
+
|
7
|
+
# 0.3
|
8
|
+
- implementazione push pull con il comando **stacksync** di mysql
|
9
|
+
|
10
|
+
# 0.2
|
11
|
+
- implementazione comando **stacksync** con configurazioni nello stack per eseguire rsync di files e dump di sqlite3
|
12
|
+
|
3
13
|
# 0.1.0
|
4
14
|
- rsync dei files da/verso cluster su cartella condivisa
|
5
15
|
- copia files direttamente in container
|
6
16
|
- shell in servizio
|
7
17
|
- mc in servizio
|
8
18
|
- configurazioni globali
|
9
|
-
- configurazioni di progetto
|
19
|
+
- configurazioni di progetto
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
swarm_cluster_cli_ope (0.
|
4
|
+
swarm_cluster_cli_ope (0.4)
|
5
5
|
activesupport
|
6
6
|
open4
|
7
7
|
thor (~> 1.0)
|
@@ -10,23 +10,23 @@ PATH
|
|
10
10
|
GEM
|
11
11
|
remote: https://rubygems.org/
|
12
12
|
specs:
|
13
|
-
activesupport (6.0.3)
|
13
|
+
activesupport (6.0.3.3)
|
14
14
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
15
15
|
i18n (>= 0.7, < 2)
|
16
16
|
minitest (~> 5.1)
|
17
17
|
tzinfo (~> 1.1)
|
18
18
|
zeitwerk (~> 2.2, >= 2.2.2)
|
19
|
-
concurrent-ruby (1.1.
|
20
|
-
i18n (1.8.
|
19
|
+
concurrent-ruby (1.1.7)
|
20
|
+
i18n (1.8.5)
|
21
21
|
concurrent-ruby (~> 1.0)
|
22
|
-
minitest (5.14.
|
22
|
+
minitest (5.14.2)
|
23
23
|
open4 (1.3.4)
|
24
24
|
rake (12.3.3)
|
25
25
|
thor (1.0.1)
|
26
26
|
thread_safe (0.3.6)
|
27
27
|
tzinfo (1.2.7)
|
28
28
|
thread_safe (~> 0.1)
|
29
|
-
zeitwerk (2.
|
29
|
+
zeitwerk (2.4.0)
|
30
30
|
|
31
31
|
PLATFORMS
|
32
32
|
ruby
|
data/README.md
CHANGED
@@ -95,17 +95,119 @@ Utilizzare `rsync_binded_from` per scaricare e `rsync_binded_to` per caricare
|
|
95
95
|
swarm_cli_ope rsync_binded_from --stack-name=STACK_NAME --service_name NOME_SERVIZIO_SENZA_STACK --binded-container-folders CARTELLA_CONTAINER --local-folder CARTELLA_DESTINAZIONE
|
96
96
|
```
|
97
97
|
|
98
|
+
### stacksync
|
99
|
+
Si occupa di scaricare|caricare,utilizzando le configurazioni presenti, i dati dallo stack remoto
|
100
|
+
|
101
|
+
Le configurazioni sono contenute nell'array: sync_configs.
|
102
|
+
|
103
|
+
ogni configurazione è composta da:
|
104
|
+
|
105
|
+
```json
|
106
|
+
{
|
107
|
+
service:""
|
108
|
+
how:""
|
109
|
+
configs:{ }
|
110
|
+
}
|
111
|
+
```
|
112
|
+
|
113
|
+
- service è il nome del servizio
|
114
|
+
- how è il come sincronizzare, definendo la tipologia:
|
115
|
+
- pg -> DB TODO
|
116
|
+
- mysql -> DB: dump del db con mysqldump
|
117
|
+
- sqlite3 -> DB: viene eseguita una copia del file
|
118
|
+
- rsync -> RSYNC
|
119
|
+
- configs: è un hash con le configurazioni per ogni tipo di sincronizzazione
|
120
|
+
|
121
|
+
Possibili CFGS per tipologia:
|
122
|
+
|
123
|
+
- rsync:
|
124
|
+
- local: -> path cartella locale
|
125
|
+
- remote: -> path cartella remota (contesto del container)
|
126
|
+
- sqlite3:
|
127
|
+
- local: -> path al file
|
128
|
+
- remote: -> path al file remoto (contesto del container)
|
129
|
+
- mysql:
|
130
|
+
- local: -> hash di configurazioni per il DB locale
|
131
|
+
- service: "db" -> nome del servizio nel compose locale, DEFAULT: quello definito sopra
|
132
|
+
- mysql_password_env: "MYSQL_PASSWORD" -> variabile ambiente interna al servizio contenente PASSWORD, DEFAULT: MYSQL_PASSWORD
|
133
|
+
- mysql_password: "root" -> valore in chiaro, in sostituzione della variabile ambiente, DEFAULT: root
|
134
|
+
- mysql_user_env: "MYSQL_USER" -> variabile ambiente interna al servizio contenente USERNAME, DEFAULT: MYSQL_USER
|
135
|
+
- mysql_user: "root" -> valore in chiaro, in sostituzione della variabile ambiente, DEFAULT: root
|
136
|
+
- database_name_env: "MYSQL_DATABASE" -> variabile ambiente interna al servizio contenente NOME DB, DEFAULT: MYSQL_DATABASE
|
137
|
+
- database_name: "nome_db" -> valore in chiaro, in sostituzione della variabile ambiente
|
138
|
+
- remote: -> hash di configurazioni per il DB remoto
|
139
|
+
- service: "db" -> nome del servizio nel compose locale, DEFAULT: quello definito sopra
|
140
|
+
- mysql_password_env: "MYSQL_PASSWORD" -> variabile ambiente interna al servizio contenente PASSWORD, DEFAULT: MYSQL_PASSWORD
|
141
|
+
- mysql_password: "root" -> valore in chiaro, in sostituzione della variabile ambiente, DEFAULT: root
|
142
|
+
- mysql_user_env: "MYSQL_USER" -> variabile ambiente interna al servizio contenente USERNAME, DEFAULT: MYSQL_USER
|
143
|
+
- mysql_user: "root" -> valore in chiaro, in sostituzione della variabile ambiente, DEFAULT: root
|
144
|
+
- database_name_env: "MYSQL_DATABASE" -> variabile ambiente interna al servizio contenente NOME DB, DEFAULT: MYSQL_DATABASE
|
145
|
+
- database_name: "MYSQL_DATABASE" -> valore in chiaro, in sostituzione della variabile ambiente
|
146
|
+
- pg:
|
147
|
+
- local: -> hash di configurazioni per il DB locale
|
148
|
+
- service: "db" -> nome del servizio nel compose locale, DEFAULT: quello definito sopra
|
149
|
+
- pg_password_env: "POSTGRES_USER" -> variabile ambiente interna al servizio contenente PASSWORD, DEFAULT: POSTGRES_PASSWORD
|
150
|
+
- pg_password: "" -> valore in chiaro, in sostituzione della variabile ambiente
|
151
|
+
- pg_user_env: "POSTGRES_USER" -> variabile ambiente interna al servizio contenente USERNAME, DEFAULT: POSTGRES_USER
|
152
|
+
- pg_user: "postgres" -> valore in chiaro, in sostituzione della variabile ambiente, DEFAULT: postgres
|
153
|
+
- database_name_env: "POSTGRES_DB" -> variabile ambiente interna al servizio contenente NOME DB, DEFAULT: POSTGRES_DB
|
154
|
+
- database_name: "nome_db" -> valore in chiaro, in sostituzione della variabile ambiente
|
155
|
+
- remote: -> hash di configurazioni per il DB remoto
|
156
|
+
- service: "db" -> nome del servizio nel compose locale, DEFAULT: quello definito sopra
|
157
|
+
- pg_password_env: "POSTGRES_USER" -> variabile ambiente interna al servizio contenente PASSWORD, DEFAULT: POSTGRES_PASSWORD
|
158
|
+
- pg_password: "" -> valore in chiaro, in sostituzione della variabile ambiente
|
159
|
+
- pg_user_env: "POSTGRES_USER" -> variabile ambiente interna al servizio contenente USERNAME, DEFAULT: POSTGRES_USER
|
160
|
+
- pg_user: "postgres" -> valore in chiaro, in sostituzione della variabile ambiente, DEFAULT: postgres
|
161
|
+
- database_name_env: "POSTGRES_DB" -> variabile ambiente interna al servizio contenente NOME DB, DEFAULT: POSTGRES_DB
|
162
|
+
- database_name: "nome_db" -> valore in chiaro, in sostituzione della variabile ambiente
|
163
|
+
|
164
|
+
#### EXAMPLE:
|
165
|
+
Esempio di sincronizzazione di un file sqlite3 e una cartella
|
166
|
+
|
167
|
+
```json
|
168
|
+
{
|
169
|
+
"stack_name": "test1",
|
170
|
+
"sync_configs": [
|
171
|
+
{
|
172
|
+
"service": "second",
|
173
|
+
"how": "rsync",
|
174
|
+
"configs": {
|
175
|
+
"remote": "/test_bind",
|
176
|
+
"local": "./uploads"
|
177
|
+
}
|
178
|
+
},
|
179
|
+
{
|
180
|
+
"service": "test_sqlite3",
|
181
|
+
"how": "sqlite3",
|
182
|
+
"configs": {
|
183
|
+
"remote": "/cartella_sqlite3/esempio.sqlite3",
|
184
|
+
"local": "./development.sqlite3"
|
185
|
+
}
|
186
|
+
}
|
187
|
+
]
|
188
|
+
}
|
189
|
+
```
|
190
|
+
|
191
|
+
|
98
192
|
## Development
|
99
193
|
|
100
194
|
nel file di configurazione creato nella home aggiungere la chiave "dev_mode":1 per collegarsi localmente
|
101
195
|
|
102
196
|
### Abbiamo due tasks swarm di simulazione
|
103
197
|
```shell script
|
104
|
-
docker stack deploy -c test_folder/test_1/docker-compose.yml
|
198
|
+
docker stack deploy -c test_folder/test_1/docker-compose.yml test_1_stack
|
105
199
|
docker stack deploy -c test_folder/test_1/docker-compose.yml test1_staging
|
106
200
|
docker stack deploy -c test_folder/test_2/docker_compose.yml test2
|
107
201
|
```
|
108
202
|
|
203
|
+
Per simulare una sincronizzazione fra locale e remoto di un mysql, lanciamo lo stesso stack anche come compose, in modo
|
204
|
+
da trovarci sulla stessa macchina con tutte e due le situazioni
|
205
|
+
```shell script
|
206
|
+
docker-compose -f test_folder/test_1/docker-compose-local.yml up -d
|
207
|
+
```
|
208
|
+
|
209
|
+
|
210
|
+
|
109
211
|
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version
|
110
212
|
number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git
|
111
213
|
commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
@@ -243,7 +243,12 @@ module SwarmClusterCliOpe
|
|
243
243
|
end
|
244
244
|
end
|
245
245
|
|
246
|
-
desc "
|
246
|
+
desc "version", "versione della cli"
|
247
|
+
def version
|
248
|
+
say VERSION
|
249
|
+
end
|
250
|
+
|
251
|
+
desc "stacksync [DIRECTION:pull|push]", "Si occupa di scaricare|caricare,utilizzando le configurazioni presenti, i dati dallo stack remoto"
|
247
252
|
long_desc <<-LONGDESC.gsub("\n", "\x5")
|
248
253
|
le configurazioni sono contenute nell'array: sync_configs.
|
249
254
|
ogni configurazione è composta da:
|
@@ -255,10 +260,79 @@ module SwarmClusterCliOpe
|
|
255
260
|
- service è il nome del servizio
|
256
261
|
- how è il come sincronizzare, definendo la tipologia:
|
257
262
|
---- pg -> DB TODO
|
258
|
-
---- mysql -> DB
|
259
|
-
---- sqlite3 -> DB
|
263
|
+
---- mysql -> DB dump con mysql
|
264
|
+
---- sqlite3 -> DB: viene eseguita una copia del file
|
260
265
|
---- rsync -> RSYNC
|
261
266
|
- configs: è un hash con le configurazioni per ogni tipo di sincronizzazione
|
267
|
+
|
268
|
+
Possibili CFGS per tipologia:
|
269
|
+
rsync:
|
270
|
+
--local: -> path cartella locale
|
271
|
+
--remote: -> path cartella remota (contesto del container)
|
272
|
+
|
273
|
+
sqlite3:
|
274
|
+
--local: -> path al file
|
275
|
+
--remote: -> path al file remoto (contesto del container)
|
276
|
+
|
277
|
+
mysql:
|
278
|
+
--local: -> hash di configurazioni per il DB locale
|
279
|
+
- service: "db" -> nome del servizio nel compose locale, DEFAULT: quello definito sopra
|
280
|
+
- mysql_password_env: "MYSQL_PASSWORD" -> variabile ambiente interna al servizio contenente PASSWORD, DEFAULT: MYSQL_PASSWORD
|
281
|
+
- mysql_password: "root" -> valore in chiaro, in sostituzione della variabile ambiente, DEFAULT: root
|
282
|
+
- mysql_user_env: "MYSQL_USER" -> variabile ambiente interna al servizio contenente USERNAME, DEFAULT: MYSQL_USER
|
283
|
+
- mysql_user: "root" -> valore in chiaro, in sostituzione della variabile ambiente, DEFAULT: root
|
284
|
+
- database_name_env: "MYSQL_DATABASE" -> variabile ambiente interna al servizio contenente NOME DB, DEFAULT: MYSQL_DATABASE
|
285
|
+
- database_name: "nome_db" -> valore in chiaro, in sostituzione della variabile ambiente
|
286
|
+
--remote: -> hash di configurazioni per il DB remoto
|
287
|
+
- service: "db" -> nome del servizio nel compose locale, DEFAULT: quello definito sopra
|
288
|
+
- mysql_password_env: "MYSQL_PASSWORD" -> variabile ambiente interna al servizio contenente PASSWORD, DEFAULT: MYSQL_PASSWORD
|
289
|
+
- mysql_password: "root" -> valore in chiaro, in sostituzione della variabile ambiente, DEFAULT: root
|
290
|
+
- mysql_user_env: "MYSQL_USER" -> variabile ambiente interna al servizio contenente USERNAME, DEFAULT: MYSQL_USER
|
291
|
+
- mysql_user: "root" -> valore in chiaro, in sostituzione della variabile ambiente, DEFAULT: root
|
292
|
+
- database_name_env: "MYSQL_DATABASE" -> variabile ambiente interna al servizio contenente NOME DB, DEFAULT: MYSQL_DATABASE
|
293
|
+
- database_name: "MYSQL_DATABASE" -> valore in chiaro, in sostituzione della variabile ambiente
|
294
|
+
pg:
|
295
|
+
--local: -> hash di configurazioni per il DB locale
|
296
|
+
- service: "db" -> nome del servizio nel compose locale, DEFAULT: quello definito sopra
|
297
|
+
- pg_password_env: "POSTGRES_USER" -> variabile ambiente interna al servizio contenente PASSWORD, DEFAULT: POSTGRES_PASSWORD
|
298
|
+
- pg_password: "" -> valore in chiaro, in sostituzione della variabile ambiente
|
299
|
+
- pg_user_env: "POSTGRES_USER" -> variabile ambiente interna al servizio contenente USERNAME, DEFAULT: POSTGRES_USER
|
300
|
+
- pg_user: "postgres" -> valore in chiaro, in sostituzione della variabile ambiente, DEFAULT: postgres
|
301
|
+
- database_name_env: "POSTGRES_DB" -> variabile ambiente interna al servizio contenente NOME DB, DEFAULT: POSTGRES_DB
|
302
|
+
- database_name: "nome_db" -> valore in chiaro, in sostituzione della variabile ambiente
|
303
|
+
--remote: -> hash di configurazioni per il DB remoto
|
304
|
+
- service: "db" -> nome del servizio nel compose locale, DEFAULT: quello definito sopra
|
305
|
+
- pg_password_env: "POSTGRES_USER" -> variabile ambiente interna al servizio contenente PASSWORD, DEFAULT: POSTGRES_PASSWORD
|
306
|
+
- pg_password: "" -> valore in chiaro, in sostituzione della variabile ambiente
|
307
|
+
- pg_user_env: "POSTGRES_USER" -> variabile ambiente interna al servizio contenente USERNAME, DEFAULT: POSTGRES_USER
|
308
|
+
- pg_user: "postgres" -> valore in chiaro, in sostituzione della variabile ambiente, DEFAULT: postgres
|
309
|
+
- database_name_env: "POSTGRES_DB" -> variabile ambiente interna al servizio contenente NOME DB, DEFAULT: POSTGRES_DB
|
310
|
+
- database_name: "nome_db" -> valore in chiaro, in sostituzione della variabile ambiente
|
311
|
+
|
312
|
+
|
313
|
+
EXAMPLE:
|
314
|
+
Esempio di sincronizzazione di un file sqlite3 e una cartella
|
315
|
+
{
|
316
|
+
"stack_name": "test1",
|
317
|
+
"sync_configs": [
|
318
|
+
{
|
319
|
+
"service": "second",
|
320
|
+
"how": "rsync",
|
321
|
+
"configs": {
|
322
|
+
"remote": "/test_bind",
|
323
|
+
"local": "./uploads"
|
324
|
+
}
|
325
|
+
},
|
326
|
+
{
|
327
|
+
"service": "test_sqlite3",
|
328
|
+
"how": "sqlite3",
|
329
|
+
"configs": {
|
330
|
+
"remote": "/cartella_sqlite3/esempio.sqlite3",
|
331
|
+
"local": "./development.sqlite3"
|
332
|
+
}
|
333
|
+
}
|
334
|
+
]
|
335
|
+
}
|
262
336
|
LONGDESC
|
263
337
|
|
264
338
|
def stacksync(direction)
|
@@ -271,8 +345,17 @@ module SwarmClusterCliOpe
|
|
271
345
|
raise "ONLY [push|pull] action accepted"
|
272
346
|
end
|
273
347
|
cfgs.env(options[:environment]) do |cfgs|
|
274
|
-
cfgs.sync_configurations
|
275
|
-
|
348
|
+
sync_cfgs = cfgs.sync_configurations
|
349
|
+
if sync_cfgs.empty?
|
350
|
+
say "Attenzione, configurazioni di sincronizzazione vuoto. Leggere la documentazione"
|
351
|
+
else
|
352
|
+
sync_cfgs.each do |sync|
|
353
|
+
say "----------->>>>>>"
|
354
|
+
say "[ #{sync.class.name} ]"
|
355
|
+
sync.send(direction)
|
356
|
+
say "COMPLETE"
|
357
|
+
say "<<<<<<-----------"
|
358
|
+
end
|
276
359
|
end
|
277
360
|
end
|
278
361
|
end
|
@@ -9,6 +9,13 @@ module SwarmClusterCliOpe
|
|
9
9
|
end.execute
|
10
10
|
end
|
11
11
|
|
12
|
+
def exec(container_id,cmd_str)
|
13
|
+
self.base_suffix_command = []
|
14
|
+
command do |cmd|
|
15
|
+
cmd.add("exec #{container_id} #{cmd_str}")
|
16
|
+
end.execute
|
17
|
+
end
|
18
|
+
|
12
19
|
##
|
13
20
|
# Esegue il ps sui container, possibile filtrare passando nome stack e/o nome servizio
|
14
21
|
# @param [String] service_name
|
@@ -140,7 +140,8 @@ module SwarmClusterCliOpe
|
|
140
140
|
if stack_name
|
141
141
|
File.open(File.join(FileUtils.pwd, self.class.cfgs_project_file_name(with_env: @environment)), "wb") do |f|
|
142
142
|
f.write({
|
143
|
-
stack_name: stack_name
|
143
|
+
stack_name: stack_name,
|
144
|
+
version: VERSION
|
144
145
|
}.to_json)
|
145
146
|
end
|
146
147
|
end
|
@@ -163,18 +164,35 @@ module SwarmClusterCliOpe
|
|
163
164
|
nodes.find { |c| c.id == node_id }
|
164
165
|
end
|
165
166
|
|
167
|
+
##
|
168
|
+
# Indica il nome del progetto locale compose, quella parte di nome che viene attaccata in fronte
|
169
|
+
# ad ogni nome di servizio locale, e che come default è il nome della cartella in cui risiede
|
170
|
+
# il docker-compose.yml file
|
171
|
+
# @return [String]
|
172
|
+
def local_compose_project_name
|
173
|
+
File.basename(FileUtils.pwd).downcase
|
174
|
+
end
|
175
|
+
|
166
176
|
##
|
167
177
|
# Elenco di tutte le configurazioni di sincronizzazione
|
178
|
+
# @return [Array]
|
168
179
|
def sync_configurations
|
169
|
-
merged_configurations[:sync_configs]
|
180
|
+
cfgs = merged_configurations[:sync_configs]
|
181
|
+
return [] if cfgs.nil? or !cfgs.is_a?(Array)
|
182
|
+
cfgs.collect do |c|
|
170
183
|
|
171
184
|
case c[:how]
|
172
185
|
when 'sqlite3'
|
173
186
|
SyncConfigs::Sqlite3.new(self, c)
|
174
187
|
when 'rsync'
|
175
188
|
SyncConfigs::Rsync.new(self, c)
|
189
|
+
when 'mysql'
|
190
|
+
SyncConfigs::Mysql.new(self, c)
|
191
|
+
when 'pg'
|
192
|
+
SyncConfigs::PostGres.new(self, c)
|
176
193
|
else
|
177
194
|
logger.error { "CONFIGURAIONE NON PREVISTA: #{c[:how]}" }
|
195
|
+
nil
|
178
196
|
end
|
179
197
|
|
180
198
|
end.compact
|
@@ -230,10 +248,16 @@ module SwarmClusterCliOpe
|
|
230
248
|
project_cfgs.merge!(JSON.parse(File.read(enviroment_file)).deep_symbolize_keys)
|
231
249
|
end
|
232
250
|
|
233
|
-
logger.debug { "CONFIGS[#{@environment}]: #{project_cfgs.inspect}" }
|
234
251
|
hash[key] = self.class.read_base.merge(project_cfgs)
|
235
252
|
end
|
236
253
|
|
254
|
+
configuration_version = @_merged_configurations[@environment][:version]
|
255
|
+
if Gem::Version.new(configuration_version) > Gem::Version.new(VERSION)
|
256
|
+
puts "WARNING: Versione del file di configurazione [#{configuration_version}] più aggiornata della gemma [#{VERSION}], eseguire upgrade
|
257
|
+
gem update swarm_cluster_cli_ope"
|
258
|
+
exit
|
259
|
+
end
|
260
|
+
|
237
261
|
@_merged_configurations[@environment]
|
238
262
|
|
239
263
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module SwarmClusterCliOpe
|
2
|
+
module Models
|
3
|
+
class ComposeContainer < Container
|
4
|
+
|
5
|
+
# @return [SwarmClusterCliOpe::Models::ComposeContainer]
|
6
|
+
def self.find_by_service_name(service_name, stack_name: '')
|
7
|
+
res = ShellCommandExecution.new("docker inspect #{[stack_name, service_name, "1"].compact.join("_".strip)}").execute
|
8
|
+
self.new(JSON.parse(res.raw_result[:stdout]).first)
|
9
|
+
end
|
10
|
+
|
11
|
+
def mapped_uri_connection
|
12
|
+
nil
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -4,7 +4,7 @@ module SwarmClusterCliOpe
|
|
4
4
|
|
5
5
|
#@return [String]
|
6
6
|
attr_accessor :name
|
7
|
-
#@return [String]
|
7
|
+
#@return [String] id del container
|
8
8
|
attr_accessor :id
|
9
9
|
#@return [String] nome dell'immagine
|
10
10
|
attr_accessor :image
|
@@ -51,6 +51,12 @@ module SwarmClusterCliOpe
|
|
51
51
|
docker_command.cp("#{id}:#{src}", dest).success?
|
52
52
|
end
|
53
53
|
|
54
|
+
##
|
55
|
+
# Esegue il comando passato
|
56
|
+
def exec(cmd)
|
57
|
+
docker_command.exec(id, cmd)
|
58
|
+
end
|
59
|
+
|
54
60
|
##
|
55
61
|
# Ritorna il connection_uri del nodo che ospita il container
|
56
62
|
# @return [String]
|
@@ -1,10 +1,13 @@
|
|
1
1
|
module SwarmClusterCliOpe
|
2
2
|
module SyncConfigs
|
3
3
|
class Base < Thor::Shell::Basic
|
4
|
-
|
4
|
+
include LoggerConcern
|
5
5
|
#@return [String] nome del servizio dello stack
|
6
6
|
attr_accessor :service
|
7
7
|
|
8
|
+
#@return [Hash] configurazioni di sincro
|
9
|
+
attr_accessor :configs
|
10
|
+
|
8
11
|
# @param [Hash] configs
|
9
12
|
# @param [Continuation] stack_cfgs
|
10
13
|
def initialize(stack_cfgs, configs)
|
@@ -30,6 +33,12 @@ module SwarmClusterCliOpe
|
|
30
33
|
raise "TO OVERRIDE"
|
31
34
|
end
|
32
35
|
|
36
|
+
private
|
37
|
+
# @return [SwarmClusterCliOpe::Models::Container]
|
38
|
+
def container
|
39
|
+
Models::Container.find_by_service_name(service, stack_name: stack_name)
|
40
|
+
end
|
41
|
+
|
33
42
|
end
|
34
43
|
end
|
35
44
|
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module SwarmClusterCliOpe
|
2
|
+
module SyncConfigs
|
3
|
+
class BaseDatabase < Base
|
4
|
+
|
5
|
+
# @return [SwarmClusterCliOpe::SyncConfigs::EnvConfigs]
|
6
|
+
def remote
|
7
|
+
self.class::EnvConfigs.new(self, @configs[:configs][:remote] || {}, -> { container })
|
8
|
+
end
|
9
|
+
|
10
|
+
# @return [SwarmClusterCliOpe::SyncConfigs::EnvConfigs]
|
11
|
+
def local
|
12
|
+
self.class::EnvConfigs.new(self, @configs[:configs][:local] || {}, -> { local_container })
|
13
|
+
end
|
14
|
+
|
15
|
+
##
|
16
|
+
# Classe interna che rappresenta le configurazioni del DB
|
17
|
+
class EnvConfigs < SwarmClusterCliOpe::SyncConfigs::EnvConfigs
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
##
|
22
|
+
# Funzione che ricapitola le informazioni utilizzate per eseguire l'operazione
|
23
|
+
def resume(direction)
|
24
|
+
puts "RESUME - #{direction}
|
25
|
+
service: #{service}
|
26
|
+
local:
|
27
|
+
service_name: #{local.service_name}
|
28
|
+
database_name: #{local.database_name}
|
29
|
+
username: #{local.username}
|
30
|
+
password: #{local.password}
|
31
|
+
remote:
|
32
|
+
service_name: #{remote.service_name}
|
33
|
+
database_name: #{remote.database_name}
|
34
|
+
username: #{remote.username}
|
35
|
+
password: #{remote.password}"
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def local_container
|
42
|
+
# il nome dello stack del compose usiamo come standard il nome della cartella, come lo fà già composer di default
|
43
|
+
Models::ComposeContainer.find_by_service_name(local.service_name, stack_name: @stack_cfgs.local_compose_project_name)
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -14,20 +14,16 @@ module SwarmClusterCliOpe
|
|
14
14
|
|
15
15
|
# @return [TrueClass, FalseClass]
|
16
16
|
def push
|
17
|
-
container.copy_in(local_folder,remote_folder)
|
17
|
+
say "#{local_folder} -->> #{remote_folder}" if container.copy_in(local_folder,remote_folder)
|
18
18
|
end
|
19
19
|
|
20
20
|
# @return [TrueClass, FalseClass]
|
21
21
|
def pull
|
22
|
-
container.copy_out(remote_folder,local_folder)
|
22
|
+
say "#{remote_folder} -->> #{local_folder}" if container.copy_out(remote_folder,local_folder)
|
23
23
|
end
|
24
24
|
|
25
25
|
|
26
|
-
|
27
|
-
# @return [SwarmClusterCliOpe::Models::Container]
|
28
|
-
def container
|
29
|
-
Models::Container.find_by_service_name(service, stack_name: stack_name)
|
30
|
-
end
|
26
|
+
|
31
27
|
|
32
28
|
|
33
29
|
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
module SwarmClusterCliOpe
|
2
|
+
module SyncConfigs
|
3
|
+
##
|
4
|
+
# Classe per la gestione dell'ambiente differente fra local e remote
|
5
|
+
# sono presenti le variabili di classe per definire una minima DSL per poter definire le variabili
|
6
|
+
# disponibili e i default da utilizzare
|
7
|
+
class EnvConfigs
|
8
|
+
# @param [Hash] configs
|
9
|
+
# @param [SwarmClusterCliOpe::SyncConfigs::Base] sync_configs
|
10
|
+
# @param [Lambda] lambda che ritorna il container Istanza container su cui la
|
11
|
+
def initialize(sync_configs, configs, container)
|
12
|
+
@configs = configs
|
13
|
+
@sync_configs = sync_configs
|
14
|
+
@lambda_container = container
|
15
|
+
end
|
16
|
+
|
17
|
+
##
|
18
|
+
# Metodo che richiama la lambda della generazione del container al momento che ne
|
19
|
+
# è proprio necessario
|
20
|
+
def container
|
21
|
+
@container ||= @lambda_container.call
|
22
|
+
end
|
23
|
+
|
24
|
+
# @return [String]
|
25
|
+
def service_name
|
26
|
+
@configs[:service] || @sync_configs.service
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
##
|
31
|
+
# Costruisce i metodi che restituiscono i valori delle configurazioni
|
32
|
+
#
|
33
|
+
# @param [String,Symbol] name -> nome della stringa con cui viene generato il metodo
|
34
|
+
# @param [String,Symbol] default_env -> nome env default nel caso non sia passato
|
35
|
+
# @param [String,Symbol] configuration_name -> nome della configurazione da utilizzare per estrapolare la configurazione
|
36
|
+
# in automatico viene tenuto conto se cercare per la versione
|
37
|
+
# con _env o senza....precedenza SENZA
|
38
|
+
# @param [nil,String] default_value se non è estrapolato nessun valore, viene utilizzato il valore di default
|
39
|
+
def self.define_cfgs(name, default_env:, configuration_name:,default_value:nil)
|
40
|
+
configuration_name ||= name
|
41
|
+
|
42
|
+
define_method(name) do
|
43
|
+
return self.instance_variable_get("@#{name}") if self.instance_variable_defined?("@#{name}")
|
44
|
+
|
45
|
+
#valore restituito direttamente dalla configurazione
|
46
|
+
if @configs.key?(configuration_name)
|
47
|
+
value = @configs["#{configuration_name}".to_sym] || default_value
|
48
|
+
else
|
49
|
+
env_var = @configs["#{configuration_name}_env".to_sym] || default_env
|
50
|
+
value = find_env_file_variable(env_var) || default_value
|
51
|
+
end
|
52
|
+
self.instance_variable_set("@#{name}", value)
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
##
|
61
|
+
# Estrae l'env dal container e ne tiene in memoria una copia, in modo da non fare multiple chiamate
|
62
|
+
def env
|
63
|
+
@env ||= container.exec("env").raw_result[:stdout].split("\n").collect { |v| v.split('=') }.to_h
|
64
|
+
end
|
65
|
+
|
66
|
+
def find_env_file_variable(env_var)
|
67
|
+
if env_var.match?(/_FILE$/)
|
68
|
+
# dobbiamo controllare la presenza del file e salvarci il contenuto
|
69
|
+
nome_file = env[env_var.to_s]
|
70
|
+
container.exec("cat #{nome_file}").raw_result[:stdout]
|
71
|
+
else
|
72
|
+
# env normale, dobbiamo ricavarlo dal container
|
73
|
+
env[env_var.to_s]
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module SwarmClusterCliOpe
|
2
|
+
module SyncConfigs
|
3
|
+
class Mysql < BaseDatabase
|
4
|
+
|
5
|
+
# @return [TrueClass, FalseClass]
|
6
|
+
def pull
|
7
|
+
resume('pull')
|
8
|
+
if yes?("Confermare il comando?[y,yes]")
|
9
|
+
tmp_file = "/tmp/#{Time.now.to_i}.sql.gz"
|
10
|
+
container.exec("bash -c 'mysqldump -u #{remote.username} --password=#{remote.password} #{remote.database_name} | gzip -c -f' > #{tmp_file}")
|
11
|
+
local_container.copy_in(tmp_file, tmp_file)
|
12
|
+
local_container.exec("bash -c 'zcat #{tmp_file} | mysql -u #{local.username} --password=#{local.password} #{local.database_name}'")
|
13
|
+
end
|
14
|
+
true
|
15
|
+
end
|
16
|
+
|
17
|
+
# @return [TrueClass, FalseClass]
|
18
|
+
def push
|
19
|
+
resume('PUSH')
|
20
|
+
if yes?("ATTENZIONE !!!!!!PUSH!!!!! - Confermare il comando?[y,yes]")
|
21
|
+
tmp_file = "/tmp/#{Time.now.to_i}.sql.gz"
|
22
|
+
local_container.exec("bash -c 'mysqldump -u #{local.username} --password=#{local.password} #{local.database_name} | gzip -c -f' > #{tmp_file}")
|
23
|
+
container.copy_in(tmp_file, tmp_file)
|
24
|
+
container.exec("bash -c 'zcat #{tmp_file} | mysql -u #{remote.username} --password=#{remote.password} #{remote.database_name}'")
|
25
|
+
end
|
26
|
+
true
|
27
|
+
end
|
28
|
+
|
29
|
+
##
|
30
|
+
# Classe interna che rappresenta le configurazioni del DB
|
31
|
+
class EnvConfigs < BaseDatabase::EnvConfigs
|
32
|
+
|
33
|
+
define_cfgs :database_name, default_env: "MYSQL_DATABASE", configuration_name: :database_name
|
34
|
+
define_cfgs :username, default_env: "MYSQL_USER", configuration_name: :mysql_user, default_value: 'root'
|
35
|
+
define_cfgs :password, default_env: "MYSQL_PASSWORD", configuration_name: :mysql_password, default_value: 'root'
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
module SwarmClusterCliOpe
|
2
|
+
module SyncConfigs
|
3
|
+
class PostGres < BaseDatabase
|
4
|
+
|
5
|
+
# @return [TrueClass, FalseClass]
|
6
|
+
def pull
|
7
|
+
resume('pull')
|
8
|
+
|
9
|
+
dump_cmd = dump_cmd(remote.username, remote.password, remote.database_name)
|
10
|
+
logger.info{ "DUMP COMMAND: #{dump_cmd.join(' ')}"}
|
11
|
+
if yes?("Confermare il comando?[y,yes]")
|
12
|
+
tmp_file = "/tmp/#{Time.now.to_i}.sql.gz"
|
13
|
+
container.exec("bash -c '#{dump_cmd.join(' ')}' > #{tmp_file}")
|
14
|
+
local_container.copy_in(tmp_file, tmp_file)
|
15
|
+
|
16
|
+
# drop old db and recreate
|
17
|
+
drop_cmd = drop_cmd(local.username, local.password, local.database_name)
|
18
|
+
logger.info{ "DROP COMMAND: #{drop_cmd.join(' ')}"}
|
19
|
+
local_container.exec("bash -c '#{drop_cmd.join(' ')}'")
|
20
|
+
create_cmd = create_cmd(local.username, local.password, local.database_name)
|
21
|
+
logger.info{ "CREATE COMMAND: #{create_cmd.join(' ')}"}
|
22
|
+
local_container.exec("bash -c '#{create_cmd.join(' ')}'")
|
23
|
+
|
24
|
+
restore_cmd = restore_cmd(local.username, local.password, local.database_name, tmp_file)
|
25
|
+
logger.info{ "RESTORE COMMAND: #{restore_cmd.join(' ')}"}
|
26
|
+
local_container.exec("bash -c '#{restore_cmd.join(' ')}'")
|
27
|
+
end
|
28
|
+
true
|
29
|
+
end
|
30
|
+
|
31
|
+
# @return [TrueClass, FalseClass]
|
32
|
+
def push
|
33
|
+
resume('PUSH')
|
34
|
+
|
35
|
+
dump_cmd = dump_cmd(local.username, local.password, local.database_name)
|
36
|
+
say "DUMP COMMAND: #{dump_cmd.join(' ')}"
|
37
|
+
if yes?("ATTENZIONE !!!!!!PUSH!!!!! - Confermare il comando?[y,yes]")
|
38
|
+
tmp_file = "/tmp/#{Time.now.to_i}.sql.gz"
|
39
|
+
local_container.exec("bash -c '#{dump_cmd.join(' ')}' > #{tmp_file}")
|
40
|
+
container.copy_in(tmp_file, tmp_file)
|
41
|
+
|
42
|
+
# drop old db and recreate
|
43
|
+
drop_cmd = drop_cmd(remote.username, remote.password, remote.database_name)
|
44
|
+
logger.info{ "DROP COMMAND: #{drop_cmd.join(' ')}"}
|
45
|
+
container.exec("bash -c '#{drop_cmd.join(' ')}'")
|
46
|
+
|
47
|
+
create_cmd = create_cmd(remote.username, remote.password, remote.database_name)
|
48
|
+
logger.info{ "CREATE COMMAND: #{create_cmd.join(' ')}"}
|
49
|
+
container.exec("bash -c '#{create_cmd.join(' ')}'")
|
50
|
+
|
51
|
+
restore_cmd = restore_cmd(remote.username, remote.password, remote.database_name, tmp_file)
|
52
|
+
say "RESTORE COMMAND: #{restore_cmd.join(' ')}"
|
53
|
+
container.exec("bash -c '#{restore_cmd.join(' ')}'")
|
54
|
+
end
|
55
|
+
true
|
56
|
+
end
|
57
|
+
|
58
|
+
##
|
59
|
+
# Classe interna che rappresenta le configurazioni del DB
|
60
|
+
class EnvConfigs < BaseDatabase::EnvConfigs
|
61
|
+
|
62
|
+
define_cfgs :database_name, default_env: "POSTGRES_DB", configuration_name: :database_name
|
63
|
+
define_cfgs :username, default_env: "POSTGRES_USER", configuration_name: :pg_user, default_value: 'postgres'
|
64
|
+
define_cfgs :password, default_env: "POSTGRES_PASSWORD", configuration_name: :pg_password
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
def create_cmd(username, password, database_name)
|
71
|
+
create_cmd = []
|
72
|
+
create_cmd << "PGPASSWORD=\"#{password}\""
|
73
|
+
create_cmd << 'createdb'
|
74
|
+
create_cmd << "--username=#{username}"
|
75
|
+
create_cmd << database_name
|
76
|
+
end
|
77
|
+
|
78
|
+
def drop_cmd(username, password, database_name)
|
79
|
+
drop_cmd = []
|
80
|
+
drop_cmd << "PGPASSWORD=\"#{password}\""
|
81
|
+
drop_cmd << 'dropdb'
|
82
|
+
drop_cmd << "--username=#{username}"
|
83
|
+
drop_cmd << database_name
|
84
|
+
drop_cmd
|
85
|
+
end
|
86
|
+
|
87
|
+
def restore_cmd(username, password, database_name, tmp_file)
|
88
|
+
restore_cmd = []
|
89
|
+
restore_cmd << "PGPASSWORD=\"#{password}\""
|
90
|
+
restore_cmd << 'pg_restore'
|
91
|
+
restore_cmd << '--no-acl'
|
92
|
+
restore_cmd << '--no-owner'
|
93
|
+
restore_cmd << "--username=#{username}"
|
94
|
+
restore_cmd << "--dbname=#{database_name}"
|
95
|
+
restore_cmd << tmp_file
|
96
|
+
restore_cmd
|
97
|
+
end
|
98
|
+
|
99
|
+
def dump_cmd(username, password, database_name)
|
100
|
+
dump_cmd = []
|
101
|
+
dump_cmd << "PGPASSWORD=\"#{password}\""
|
102
|
+
dump_cmd << 'pg_dump'
|
103
|
+
dump_cmd << '--no-acl'
|
104
|
+
dump_cmd << '--no-owner'
|
105
|
+
dump_cmd << "--username=#{username}"
|
106
|
+
dump_cmd << '--format=custom'
|
107
|
+
dump_cmd << '--compress=9'
|
108
|
+
dump_cmd << database_name
|
109
|
+
dump_cmd
|
110
|
+
end
|
111
|
+
|
112
|
+
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -28,9 +28,6 @@ module SwarmClusterCliOpe
|
|
28
28
|
private
|
29
29
|
def execute(direction: :down)
|
30
30
|
|
31
|
-
# trovo il container del servizio
|
32
|
-
container = Models::Container.find_by_service_name(service, stack_name: stack_name)
|
33
|
-
|
34
31
|
if container.nil?
|
35
32
|
say "Container non trovato con #{stack_name}@##{service}"
|
36
33
|
exit 0
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: swarm_cluster_cli_ope
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: '0.4'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Marino Bonetti
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-09-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -90,6 +90,7 @@ files:
|
|
90
90
|
- lib/swarm_cluster_cli_ope.rb
|
91
91
|
- lib/swarm_cluster_cli_ope/cli.rb
|
92
92
|
- lib/swarm_cluster_cli_ope/commands/base.rb
|
93
|
+
- lib/swarm_cluster_cli_ope/commands/compose_container.rb
|
93
94
|
- lib/swarm_cluster_cli_ope/commands/container.rb
|
94
95
|
- lib/swarm_cluster_cli_ope/commands/service.rb
|
95
96
|
- lib/swarm_cluster_cli_ope/commands/swarm.rb
|
@@ -99,6 +100,7 @@ files:
|
|
99
100
|
- lib/swarm_cluster_cli_ope/logger_concern.rb
|
100
101
|
- lib/swarm_cluster_cli_ope/manager.rb
|
101
102
|
- lib/swarm_cluster_cli_ope/models/base.rb
|
103
|
+
- lib/swarm_cluster_cli_ope/models/compose_container.rb
|
102
104
|
- lib/swarm_cluster_cli_ope/models/container.rb
|
103
105
|
- lib/swarm_cluster_cli_ope/models/mapped_volume.rb
|
104
106
|
- lib/swarm_cluster_cli_ope/models/service.rb
|
@@ -108,7 +110,11 @@ files:
|
|
108
110
|
- lib/swarm_cluster_cli_ope/shell_command_execution.rb
|
109
111
|
- lib/swarm_cluster_cli_ope/shell_command_response.rb
|
110
112
|
- lib/swarm_cluster_cli_ope/sync_configs/base.rb
|
113
|
+
- lib/swarm_cluster_cli_ope/sync_configs/base_database.rb
|
111
114
|
- lib/swarm_cluster_cli_ope/sync_configs/copy.rb
|
115
|
+
- lib/swarm_cluster_cli_ope/sync_configs/env_configs.rb
|
116
|
+
- lib/swarm_cluster_cli_ope/sync_configs/mysql.rb
|
117
|
+
- lib/swarm_cluster_cli_ope/sync_configs/post_gres.rb
|
112
118
|
- lib/swarm_cluster_cli_ope/sync_configs/rsync.rb
|
113
119
|
- lib/swarm_cluster_cli_ope/sync_configs/sqlite3.rb
|
114
120
|
- lib/swarm_cluster_cli_ope/version.rb
|