swarm_cluster_cli_ope 0.1.6 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4d080e1fbcc49d24e180f7cae13bf99415e85b7ae7a443c175a8251486fd75f5
4
- data.tar.gz: 6b4b0b8ffaf462a4f7ae9e7601276b40cf722860ecd3bfb1270a5734bbb6211d
3
+ metadata.gz: 3d344913376cd573bd0c65e8b1e13b21c22cea8da6765d5c96962bb8117a345b
4
+ data.tar.gz: aba83b091bb644491f7f2159c24ed5809d624713439037e368d874a7b702e2bf
5
5
  SHA512:
6
- metadata.gz: fce5856e48f7d73ff31aac4c26fb2d7c0c235f0c36ab8a6fda65e79b7696f48f35faff221d5e97de4bfd8183d704c76ce11b3534b311fcf6697580c88cfeba0d
7
- data.tar.gz: 90c49135edaabb0d3e4f9abcb63880df81279159198429e803abcb96ac606a8ba908d4392375c52cda82ada9bcf95805d920b3e8a3d066525923daed3885c702
6
+ metadata.gz: 22e815330c638aead770d742b875961892650e73b68abed0b8fd897448d038ebbe4065a417073e9e4ce5039edaa40824eb617a43fa4200974cdb0363505fd83b
7
+ data.tar.gz: 63c7bff02ab029faf11f533a008f53b813381c0915524a501464ac75e52a24b3b930900af05c08d358945ea5587de1811eb93cdd2752cbe4bd3e22b1f8548962
@@ -1,9 +1,15 @@
1
1
  ## Changelog
2
2
 
3
+ # 0.3
4
+ - implementazione push pull con il comando **stacksync** di mysql
5
+
6
+ # 0.2
7
+ - implementazione comando **stacksync** con configurazioni nello stack per eseguire rsync di files e dump di sqlite3
8
+
3
9
  # 0.1.0
4
10
  - rsync dei files da/verso cluster su cartella condivisa
5
11
  - copia files direttamente in container
6
12
  - shell in servizio
7
13
  - mc in servizio
8
14
  - configurazioni globali
9
- - configurazioni di progetto
15
+ - configurazioni di progetto
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- swarm_cluster_cli_ope (0.1.6)
4
+ swarm_cluster_cli_ope (0.3.1)
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.2)
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.6)
20
- i18n (1.8.2)
19
+ concurrent-ruby (1.1.7)
20
+ i18n (1.8.5)
21
21
  concurrent-ruby (~> 1.0)
22
- minitest (5.14.0)
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.3.0)
29
+ zeitwerk (2.4.0)
30
30
 
31
31
  PLATFORMS
32
32
  ruby
data/README.md CHANGED
@@ -36,6 +36,9 @@ FILE di configurazione base:
36
36
  3 DEBUG
37
37
 
38
38
 
39
+ ### ENV differenti
40
+ Tutti i comandi possono essere accompagnati con -e, per scopparli nel relativo ENVIRONMENT
41
+
39
42
  ### Configuratione di un progetto
40
43
  Si occupa di generare nel progetto il file di configurazione in cui impostare impostazioni specifiche di progetto
41
44
  quali stack_name (.swarm_cluster_project)
@@ -92,17 +95,99 @@ Utilizzare `rsync_binded_from` per scaricare e `rsync_binded_to` per caricare
92
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
93
96
  ```
94
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_user_env: "MYSQL_USER" -> variabile ambiente interna al servizio contenente USERNAME, DEFAULT: MYSQL_USER
134
+ - database_name_env: "MYSQL_DATABASE" -> variabile ambiente interna al servizio contenente NOME DB, DEFAULT: MYSQL_DATABASE
135
+ - remote: -> hash di configurazioni per il DB remoto
136
+ - service: "db" -> nome del servizio nel compose locale, DEFAULT: quello definito sopra
137
+ - mysql_password_env: "MYSQL_PASSWORD" -> variabile ambiente interna al servizio contenente PASSWORD, DEFAULT: MYSQL_PASSWORD
138
+ - mysql_user_env: "MYSQL_USER" -> variabile ambiente interna al servizio contenente USERNAME, DEFAULT: MYSQL_USER
139
+ - database_name_env: "MYSQL_DATABASE" -> variabile ambiente interna al servizio contenente NOME DB, DEFAULT: MYSQL_DATABASE
140
+
141
+ #### EXAMPLE:
142
+ Esempio di sincronizzazione di un file sqlite3 e una cartella
143
+
144
+ ```json
145
+ {
146
+ "stack_name": "test1",
147
+ "sync_configs": [
148
+ {
149
+ "service": "second",
150
+ "how": "rsync",
151
+ "configs": {
152
+ "remote": "/test_bind",
153
+ "local": "./uploads"
154
+ }
155
+ },
156
+ {
157
+ "service": "test_sqlite3",
158
+ "how": "sqlite3",
159
+ "configs": {
160
+ "remote": "/cartella_sqlite3/esempio.sqlite3",
161
+ "local": "./development.sqlite3"
162
+ }
163
+ }
164
+ ]
165
+ }
166
+ ```
167
+
168
+
95
169
  ## Development
96
170
 
97
171
  nel file di configurazione creato nella home aggiungere la chiave "dev_mode":1 per collegarsi localmente
98
172
 
99
173
  ### Abbiamo due tasks swarm di simulazione
100
174
  ```shell script
101
- docker stack deploy -c test_folder/test_1/docker_compose.yml test1
175
+ docker stack deploy -c test_folder/test_1/docker-compose.yml test_1_stack
176
+ docker stack deploy -c test_folder/test_1/docker-compose.yml test1_staging
102
177
  docker stack deploy -c test_folder/test_2/docker_compose.yml test2
103
178
  ```
104
179
 
105
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
180
+ Per simulare una sincronizzazione fra locale e remoto di un mysql, lanciamo lo stesso stack anche come compose, in modo
181
+ da trovarci sulla stessa macchina con tutte e due le situazioni
182
+ ```shell script
183
+ docker-compose up -f test_folder/test_1/docker-compose-local.yml -d
184
+ ```
185
+
186
+
187
+
188
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version
189
+ number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git
190
+ commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
106
191
 
107
192
 
108
193
  ## License
@@ -11,6 +11,9 @@ module SwarmClusterCliOpe
11
11
  true
12
12
  end
13
13
 
14
+ class_option :environment, required: false, type: :string, aliases: [:e],
15
+ desc: "Esegue tutte le operazioni nell'env scelto, il file di configurazione dovrà avere il nome: #{Configuration.cfgs_project_file_name}.ENV"
16
+
14
17
  desc "install", "Creazione della configurazione base della gemma"
15
18
 
16
19
  def install
@@ -40,7 +43,9 @@ module SwarmClusterCliOpe
40
43
  desc "config", "Visualizza le configurazioni mergiate (HOME + Project configuration[#{Configuration.cfgs_project_file_name}])"
41
44
 
42
45
  def config
43
- puts JSON.pretty_generate(cfgs.class.merged_configurations)
46
+ cfgs.env(options[:environment]) do
47
+ puts JSON.pretty_generate(cfgs.merged_configurations)
48
+ end
44
49
  end
45
50
 
46
51
 
@@ -54,88 +59,93 @@ module SwarmClusterCliOpe
54
59
  end
55
60
 
56
61
  desc "services", "lista dei servizi per uno stack"
57
- option :stack_name, required: false, type: :string, default: cfgs.stack_name
62
+ option :stack_name, required: false, type: :string
58
63
 
59
64
  def services
60
- Models::Service.all(stack_name: options[:stack_name]).each do |s|
61
- puts s.name
65
+ cfgs.env(options[:environment]) do |cfgs|
66
+ stack_name = options[:stack_name] || cfgs.stack_name
67
+ Models::Service.all(stack_name: stack_name).each do |s|
68
+ puts s.name
69
+ end
62
70
  end
63
71
  end
64
72
 
65
73
  desc "mc SERVICE_NAME", "Apre MC tra la cartella attuale e il container (potrebbe dar luogo a degli errori, ma funziona)"
66
- option :stack_name, required: false, type: :string, default: cfgs.stack_name
74
+ option :stack_name, required: false, type: :string
67
75
 
68
76
  def mc(service_name)
69
-
70
- # Disabilito output della libreria
71
- MakeMakefile::Logging.instance_variable_set(:@logfile, File::NULL)
72
- unless find_executable 'mc'
73
- puts "Non hai installato MC"
74
- exit 0
75
- end
76
-
77
- begin
78
- container = Models::Container.find_by_service_name(service_name, stack_name: options[:stack_name])
79
-
80
- server = container.node.hostname
81
-
82
- # Creo container ssh
83
- # DOCKER_HOST=ssh://swarm_node_1 docker run --rm -d -p 12222:22 \
84
- # --volumes-from sistemi-test_swarm_cluster_cli_wordpress.1.zbbz1xxh4vzzccndvs973jnuc \
85
- # sickp/alpine-sshd:7.5
86
- #
87
- cmd = container.docker_command
88
- cmd.base_suffix_command = ''
89
- shell_operation = cmd.command do |c|
90
- c.add("run --rm -d -p 42222:22 --volumes-from #{container.id} sickp/alpine-sshd:7.5")
77
+ cfgs.env(options[:environment]) do |cfgs|
78
+ stack_name = options[:stack_name] || cfgs.stack_name
79
+ # Disabilito output della libreria
80
+ MakeMakefile::Logging.instance_variable_set(:@logfile, File::NULL)
81
+ unless find_executable 'mc'
82
+ puts "Non hai installato MC"
83
+ exit 0
91
84
  end
92
85
 
93
- puts "Creazione container #{shell_operation.string_command}"
94
- id_container = shell_operation.execute.raw_result[:stdout]
95
- puts "Container generato con id:#{id_container}"
96
-
97
- # eseguo tunnel verso nodo e container ssh
98
- socket_ssh_path = "/tmp/socket_ssh_#{id_container}"
99
- # ssh -f -N -T -M -S <path-to-socket> -L 13333:0.0.0.0:42222 <server>
100
- cmd_tunnel = ["ssh", "-f -N -T -M", "-S #{socket_ssh_path}", "-L 13333:0.0.0.0:42222", server].join(" ")
101
- puts "Apro tunnel"
102
- puts cmd_tunnel
103
- system(cmd_tunnel)
104
-
105
- # apro MC
106
- # mc . sftp://root:root@0.0.0.0:13333
107
- mc_cmd = "mc . sftp://root:root@0.0.0.0:13333"
108
- puts "Apro MC"
109
- puts mc_cmd
110
- system(mc_cmd)
111
- ensure
112
- if socket_ssh_path
113
- # chiudo tunnel
114
- # ssh -S <path-to-socket> -O exit <server>
115
- close_tunnel_cmd = "ssh -S #{socket_ssh_path} -O exit #{server}"
116
- puts "Chiudo tunnel"
117
- # say close_tunnel_cmd
118
- ShellCommandExecution.new(close_tunnel_cmd).execute
119
- end
86
+ begin
87
+ container = Models::Container.find_by_service_name(service_name, stack_name: stack_name)
120
88
 
121
- if id_container
122
- # cancello container
123
- # docker stop #{id_container}
124
- puts "Spengo container di appoggio"
125
- puts "docker stop #{id_container}"
89
+ server = container.node.hostname
90
+
91
+ # Creo container ssh
92
+ # DOCKER_HOST=ssh://swarm_node_1 docker run --rm -d -p 12222:22 \
93
+ # --volumes-from sistemi-test_swarm_cluster_cli_wordpress.1.zbbz1xxh4vzzccndvs973jnuc \
94
+ # sickp/alpine-sshd:7.5
95
+ #
126
96
  cmd = container.docker_command
127
97
  cmd.base_suffix_command = ''
128
- stop_ssh_container = cmd.command do |c|
129
- c.add("stop #{id_container}")
98
+ shell_operation = cmd.command do |c|
99
+ c.add("run --rm -d -p 42222:22 --volumes-from #{container.id} sickp/alpine-sshd:7.5")
100
+ end
101
+
102
+ puts "Creazione container #{shell_operation.string_command}"
103
+ id_container = shell_operation.execute.raw_result[:stdout]
104
+ puts "Container generato con id:#{id_container}"
105
+
106
+ # eseguo tunnel verso nodo e container ssh
107
+ socket_ssh_path = "/tmp/socket_ssh_#{id_container}"
108
+ # ssh -f -N -T -M -S <path-to-socket> -L 13333:0.0.0.0:42222 <server>
109
+ cmd_tunnel = ["ssh", "-f -N -T -M", "-S #{socket_ssh_path}", "-L 13333:0.0.0.0:42222", server].join(" ")
110
+ puts "Apro tunnel"
111
+ puts cmd_tunnel
112
+ system(cmd_tunnel)
113
+
114
+ # apro MC
115
+ # mc . sftp://root:root@0.0.0.0:13333
116
+ mc_cmd = "mc . sftp://root:root@0.0.0.0:13333"
117
+ puts "Apro MC"
118
+ puts mc_cmd
119
+ system(mc_cmd)
120
+ ensure
121
+ if socket_ssh_path
122
+ # chiudo tunnel
123
+ # ssh -S <path-to-socket> -O exit <server>
124
+ close_tunnel_cmd = "ssh -S #{socket_ssh_path} -O exit #{server}"
125
+ puts "Chiudo tunnel"
126
+ # say close_tunnel_cmd
127
+ ShellCommandExecution.new(close_tunnel_cmd).execute
130
128
  end
131
- stop_ssh_container.execute
132
- end
133
129
 
130
+ if id_container
131
+ # cancello container
132
+ # docker stop #{id_container}
133
+ puts "Spengo container di appoggio"
134
+ puts "docker stop #{id_container}"
135
+ cmd = container.docker_command
136
+ cmd.base_suffix_command = ''
137
+ stop_ssh_container = cmd.command do |c|
138
+ c.add("stop #{id_container}")
139
+ end
140
+ stop_ssh_container.execute
141
+ end
142
+
143
+ end
134
144
  end
135
145
  end
136
146
 
137
147
  desc "cp SRC DEST", "Copia la sorgente in destinazione"
138
- option :stack_name, required: false, type: :string, default: cfgs.stack_name
148
+ option :stack_name, required: false, type: :string
139
149
  long_desc <<-LONGDESC
140
150
  SRC e DEST possono essere un servizio, solo uno di essi può essere un servizio (TODO)
141
151
  Per identificare che sia un servizio controllo se nella stringa è presete il :
@@ -144,46 +154,73 @@ module SwarmClusterCliOpe
144
154
  LONGDESC
145
155
 
146
156
  def cp(src, dest)
147
- #identifico quale dei due è il servizio e quale la path
148
- if src.match(/^(.*)\:/)
149
- container = Models::Container.find_by_service_name(Regexp.last_match[1], stack_name: options[:stack_name])
150
- ris = container.copy_out(src.match(/\:(.*)$/)[1], dest)
151
- else
152
- container = Models::Container.find_by_service_name(dest.match(/^(.*)\:/)[1], stack_name: options[:stack_name])
153
- ris = container.copy_in(src, dest.match(/\:(.*)$/)[1])
157
+ cfgs.env(options[:environment]) do |cfgs|
158
+
159
+ cfgs.stack_name = options[:stack_name] || cfgs.stack_name
160
+
161
+ #identifico quale dei due è il servizio e quale la path
162
+ if src.match(/^(.*)\:/)
163
+ service_name = Regexp.last_match[1]
164
+ remote = src.match(/\:(.*)$/)[1]
165
+ local = dest
166
+ execute = :pull
167
+ else
168
+ service_name = dest.match(/^(.*)\:/)[1]
169
+ remote = dest.match(/\:(.*)$/)[1]
170
+ local = src
171
+ execute = :push
172
+ end
173
+
174
+
175
+ cmd = SyncConfigs::Copy.new(cfgs, {
176
+ service: service_name,
177
+ how: 'copy',
178
+ configs: {
179
+ local: local,
180
+ remote: remote
181
+ }
182
+ })
183
+
184
+ puts "COMPLETATO" if cmd.send(execute)
185
+
154
186
  end
155
- puts "COMPLETATO" if ris
156
187
  end
157
188
 
158
189
 
159
190
  desc "configure_project STACK_NAME", "Genera il file di configurazione del progetto contenente il nome dello stack"
160
191
 
161
192
  def configure_project(stack_name)
162
- cfgs.stack_name = stack_name
163
- cfgs.save_project_cfgs
193
+ cfgs.env(options[:environment]) do |c|
194
+ c.stack_name = stack_name
195
+ c.save_project_cfgs
196
+ end
164
197
  end
165
198
 
199
+
166
200
  desc "service_shell SERVICE_NAME", "apre una shell [default bash] dentro al container"
167
- option :stack_name, required: false, type: :string, default: cfgs.stack_name
201
+ option :stack_name, required: false, type: :string
168
202
  option :shell, required: false, type: :string, default: 'bash'
169
203
 
170
204
  def service_shell(service_name)
171
- container = Models::Container.find_by_service_name(service_name, stack_name: options[:stack_name])
205
+ cfgs.env(options[:environment]) do |cfgs|
206
+ stack_name = options[:stack_name] || cfgs.stack_name
207
+ container = Models::Container.find_by_service_name(service_name, stack_name: stack_name)
172
208
 
173
- cmd = container.docker_command
174
- cmd.base_suffix_command = ''
175
- shell_operation = cmd.command do |c|
176
- c.add("exec -it #{container.id} #{options[:shell]}")
177
- end
209
+ cmd = container.docker_command
210
+ cmd.base_suffix_command = ''
211
+ shell_operation = cmd.command do |c|
212
+ c.add("exec -it #{container.id} #{options[:shell]}")
213
+ end
178
214
 
179
- say "Stai entrando della shell in #{options[:shell]} del container #{options[:stack_name]}->#{container.name}[#{container.id}]"
180
- system(shell_operation.string_command)
181
- say "Shell chiusa"
215
+ say "Stai entrando della shell in #{options[:shell]} del container #{stack_name}->#{container.name}[#{container.id}]"
216
+ system(shell_operation.string_command)
217
+ say "Shell chiusa"
218
+ end
182
219
  end
183
220
 
184
221
 
185
222
  desc "rsync_binded_from", "esegue un rsync dalla cartella bindata (viene sincronizzato il contenuto)"
186
- option :stack_name, required: false, type: :string, default: cfgs.stack_name
223
+ option :stack_name, required: false, type: :string
187
224
  option :service_name, required: true, type: :string
188
225
  option :binded_container_folders, required: true, type: :string, desc: "path della cartella bindata all'interno del container da sincronizzare"
189
226
  option :local_folder, required: true, type: :string, desc: "path della cartella dove sincronizzare il comando"
@@ -195,7 +232,7 @@ module SwarmClusterCliOpe
195
232
  end
196
233
 
197
234
  desc "rsync_binded_to", "esegue un rsync verso la cartella bindata"
198
- option :stack_name, required: false, type: :string, default: cfgs.stack_name
235
+ option :stack_name, required: false, type: :string
199
236
  option :service_name, required: true, type: :string
200
237
  option :binded_container_folders, required: true, type: :string, desc: "path della cartella bindata all'interno del container da sincronizzare"
201
238
  option :local_folder, required: true, type: :string, desc: "path della cartella dove sincronizzare il comando"
@@ -206,46 +243,116 @@ module SwarmClusterCliOpe
206
243
  end
207
244
  end
208
245
 
246
+ desc "stacksync [DIRECTION:pull|push]", "Si occupa di scaricare|caricare,utilizzando le configurazioni presenti, i dati dallo stack remoto"
247
+ long_desc <<-LONGDESC.gsub("\n", "\x5")
248
+ le configurazioni sono contenute nell'array: sync_configs.
249
+ ogni configurazione è composta da:
250
+ {
251
+ service:""
252
+ how:""
253
+ configs:{ }
254
+ }
255
+ - service è il nome del servizio
256
+ - how è il come sincronizzare, definendo la tipologia:
257
+ ---- pg -> DB TODO
258
+ ---- mysql -> DB dump con mysql
259
+ ---- sqlite3 -> DB: viene eseguita una copia del file
260
+ ---- rsync -> RSYNC
261
+ - configs: è un hash con le configurazioni per ogni tipo di sincronizzazione
262
+
263
+ Possibili CFGS per tipologia:
264
+ rsync:
265
+ --local: -> path cartella locale
266
+ --remote: -> path cartella remota (contesto del container)
267
+
268
+ sqlite3:
269
+ --local: -> path al file
270
+ --remote: -> path al file remoto (contesto del container)
271
+
272
+ mysql:
273
+ -- local: -> hash di configurazioni per il DB locale
274
+ "service": "db" -> nome del servizio nel compose locale, DEFAULT: quello definito sopra
275
+ "mysql_password_env": "MYSQL_PASSWORD" -> variabile ambiente interna al servizio contenente PASSWORD, DEFAULT: MYSQL_PASSWORD
276
+ "mysql_user_env": "MYSQL_USER" -> variabile ambiente interna al servizio contenente USERNAME, DEFAULT: MYSQL_USER
277
+ "database_name_env": "MYSQL_DATABASE" -> variabile ambiente interna al servizio contenente NOME DB, DEFAULT: MYSQL_DATABASE
278
+ -- remote: -> hash di configurazioni per il DB remoto
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_user_env": "MYSQL_USER" -> variabile ambiente interna al servizio contenente USERNAME, DEFAULT: MYSQL_USER
282
+ "database_name_env": "MYSQL_DATABASE" -> variabile ambiente interna al servizio contenente NOME DB, DEFAULT: MYSQL_DATABASE
283
+
284
+
285
+ EXAMPLE:
286
+ Esempio di sincronizzazione di un file sqlite3 e una cartella
287
+ {
288
+ "stack_name": "test1",
289
+ "sync_configs": [
290
+ {
291
+ "service": "second",
292
+ "how": "rsync",
293
+ "configs": {
294
+ "remote": "/test_bind",
295
+ "local": "./uploads"
296
+ }
297
+ },
298
+ {
299
+ "service": "test_sqlite3",
300
+ "how": "sqlite3",
301
+ "configs": {
302
+ "remote": "/cartella_sqlite3/esempio.sqlite3",
303
+ "local": "./development.sqlite3"
304
+ }
305
+ }
306
+ ]
307
+ }
308
+ LONGDESC
209
309
 
210
- private
211
-
212
- def rsync_binded(direction: :down, options: {})
213
-
214
- # trovo il container del servizio
215
- container = Models::Container.find_by_service_name(options[:service_name], stack_name: options[:stack_name])
216
-
217
- if container.nil?
218
- say "Container non trovato con #{options[:stack_name]}@##{options[:service_name]}"
219
- exit 0
310
+ def stacksync(direction)
311
+ direction = case direction
312
+ when 'push'
313
+ :push
314
+ when 'pull'
315
+ :pull
316
+ else
317
+ raise "ONLY [push|pull] action accepted"
318
+ end
319
+ cfgs.env(options[:environment]) do |cfgs|
320
+ sync_cfgs = cfgs.sync_configurations
321
+ if sync_cfgs.empty?
322
+ say "Attenzione, configurazioni di sincronizzazione vuoto. Leggere la documentazione"
323
+ else
324
+ sync_cfgs.each do |sync|
325
+ say "----------->>>>>>"
326
+ say "[ #{sync.class.name} ]"
327
+ sync.send(direction)
328
+ say "<<<<<<-----------"
329
+ end
330
+ end
220
331
  end
332
+ end
221
333
 
334
+ private
222
335
 
223
- # trovo la cartella bindata e la relativa cartella sul nodo
224
- volume = container.mapped_volumes.find { |v| v.destination == options[:binded_container_folders] and v.is_binded? }
225
- if volume.nil?
226
- say "Non ho trovato il volume bindato con questa destinazione all'interno del container #{options[:binded_container_folders]}"
227
- exit 0
228
- end
229
-
230
- #costruisco il comando rsync fra cartella del nodo e cartella sul pc
231
- cmd = ["rsync", "-zr", "--delete"]
232
- if direction == :down
233
- cmd << "#{volume.ssh_connection_path}/."
234
- # creo la cartella in locale se non esiste
235
- FileUtils.mkdir_p(options[:local_folder])
236
- cmd << options[:local_folder]
237
- end
238
- if direction == :up
239
- cmd << "#{options[:local_folder]}/."
240
- cmd << volume.ssh_connection_path
241
- end
336
+ def rsync_binded(direction: :down, options: {})
337
+ cfgs.env(options[:environment]) do |cfgs|
338
+ cfgs.stack_name = options[:stack_name] || cfgs.stack_name
339
+ sync = SyncConfigs::Rsync.new(cfgs, {
340
+ service: options[:service_name],
341
+ how: 'rsync',
342
+ configs: {
343
+ local: options[:local_folder],
344
+ remote: options[:binded_container_folders]
345
+ }
346
+ })
347
+
348
+ if direction == :down
349
+ sync.pull
350
+ end
351
+ if direction == :up
352
+ sync.push
353
+ end
242
354
 
243
- cmd = ShellCommandExecution.new(cmd)
244
355
 
245
- say "Comando da eseguire:"
246
- say " #{cmd.string_command}"
247
- if yes?("Confermare il comando?[y,yes]")
248
- cmd.execute
249
356
  end
250
357
  end
251
358
  end
@@ -0,0 +1,12 @@
1
+ module SwarmClusterCliOpe
2
+ module Commands
3
+ class ComposeContainer < Container
4
+
5
+ # Siamo in locale
6
+ def docker_host
7
+ ""
8
+ end
9
+
10
+ end
11
+ end
12
+ 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
@@ -15,6 +15,9 @@ module SwarmClusterCliOpe
15
15
  #@return [String] nome dello stack con cui lavoriamo
16
16
  attr_accessor :stack_name
17
17
 
18
+ #@return [String] in che enviroment siamo, altrimenti siamo nel default
19
+ attr_accessor :environment
20
+
18
21
  NoBaseConfigurations = Class.new(Error)
19
22
 
20
23
  ##
@@ -25,6 +28,19 @@ module SwarmClusterCliOpe
25
28
  @_managers = self.nodes.select { |n| read_managers_cache_list.include?(n.name) }.collect { |c| Manager.new(name: c.name.to_s, connection_uri: c.connection_uri) }
26
29
  end
27
30
 
31
+ ##
32
+ # Serve per entrare nell'env corretto.
33
+ # passando l'env, tutto quello eseguito nello yield sarà gestito in quell'env.
34
+ # Verrà controllato quindi che esista il relativo file di configurazion
35
+ def env(enviroment = nil)
36
+ unless enviroment.nil?
37
+ @environment = enviroment.to_s.to_sym
38
+ end
39
+ logger.info { "ENV: #{@environment ? @environment : "BASE"}" }
40
+ yield self
41
+ @environment = nil
42
+ end
43
+
28
44
  ##
29
45
  # Esegue un refresh della lista dei manager, ciclando su tutti i nodi, e scrivendo in /tmp un file temporaneo con
30
46
  # con la lista dei nomi dei managers
@@ -48,8 +64,10 @@ module SwarmClusterCliOpe
48
64
  #
49
65
  # @return [Array<SwarmClusterCliOpe::Node>]
50
66
  def nodes
51
- return @_nodes if @_nodes
52
- @_nodes = self.class.merged_configurations[:connections_maps].collect { |m, c| Node.new(name: m.to_s, connection_uri: c) }
67
+ @_nodes ||= Hash.new do |hash, key|
68
+ hash[key] = self.merged_configurations[:connections_maps].collect { |m, c| Node.new(name: m.to_s, connection_uri: c) }
69
+ end
70
+ @_nodes[environment]
53
71
  end
54
72
 
55
73
  ##
@@ -58,22 +76,31 @@ module SwarmClusterCliOpe
58
76
  # @param [Array<SwarmClusterCliOpe::Node>]
59
77
  # @return [Configuration]
60
78
  def nodes=(objs)
61
- @_nodes = objs
79
+ nodes[environment] = objs
62
80
  self
63
81
  end
64
82
 
65
83
  # @return [String,NilClass] nome dello stack del progetto se configurato
66
84
  def stack_name
67
- return @stack_name if @stack_name
68
85
  return nil unless self.class.exist_base?
69
- @stack_name = self.class.merged_configurations[:stack_name] if self.class.merged_configurations.key?(:stack_name)
86
+ @stack_name ||= Hash.new do |hash, key|
87
+ hash[key] = merged_configurations[:stack_name] if merged_configurations.key?(:stack_name)
88
+ end
89
+ @stack_name[environment]
90
+ end
91
+
92
+ ##
93
+ # Imposta il nome dello stack
94
+ def stack_name=(objs)
95
+ stack_name #lo richiamo per fargli generare la variabile di classe
96
+ @stack_name[environment] = objs
70
97
  end
71
98
 
72
99
  ##
73
100
  # Livello di logging
74
101
  # @return [Integer]
75
102
  def logger_level
76
- self.class.merged_configurations[:log_level].to_s || "0"
103
+ merged_configurations[:log_level].to_s || "0"
77
104
  rescue SwarmClusterCliOpe::Configuration::NoBaseConfigurations
78
105
  # quando andiamo in errore durante l'installazione per avere le informazioni per il logger.
79
106
  # Usiamo lo standard
@@ -85,7 +112,7 @@ module SwarmClusterCliOpe
85
112
  # @return [TrueClass, FalseClass]
86
113
  def development_mode?
87
114
  return false unless self.class.exist_base?
88
- self.class.merged_configurations.key?(:dev_mode)
115
+ merged_configurations.key?(:dev_mode)
89
116
  end
90
117
 
91
118
  ##
@@ -110,8 +137,8 @@ module SwarmClusterCliOpe
110
137
  ##
111
138
  # Si occupa del salvataggio delle configurazioni di progetto, se abbiamo lo stack_name
112
139
  def save_project_cfgs
113
- if @stack_name
114
- File.open(File.join(FileUtils.pwd, self.class.cfgs_project_file_name), "wb") do |f|
140
+ if stack_name
141
+ File.open(File.join(FileUtils.pwd, self.class.cfgs_project_file_name(with_env: @environment)), "wb") do |f|
115
142
  f.write({
116
143
  stack_name: stack_name
117
144
  }.to_json)
@@ -136,13 +163,46 @@ module SwarmClusterCliOpe
136
163
  nodes.find { |c| c.id == node_id }
137
164
  end
138
165
 
166
+ ##
167
+ # Indica il nome del progetto locale compose, quella parte di nome che viene attaccata in fronte
168
+ # ad ogni nome di servizio locale, e che come default è il nome della cartella in cui risiede
169
+ # il docker-compose.yml file
170
+ # @return [String]
171
+ def local_compose_project_name
172
+ File.basename(FileUtils.pwd)
173
+ end
174
+
175
+ ##
176
+ # Elenco di tutte le configurazioni di sincronizzazione
177
+ # @return [Array]
178
+ def sync_configurations
179
+ cfgs = merged_configurations[:sync_configs]
180
+ return [] if cfgs.nil? or !cfgs.is_a?(Array)
181
+ cfgs.collect do |c|
182
+
183
+ case c[:how]
184
+ when 'sqlite3'
185
+ SyncConfigs::Sqlite3.new(self, c)
186
+ when 'rsync'
187
+ SyncConfigs::Rsync.new(self, c)
188
+ when 'mysql'
189
+ SyncConfigs::Mysql.new(self, c)
190
+ else
191
+ logger.error { "CONFIGURAIONE NON PREVISTA: #{c[:how]}" }
192
+ nil
193
+ end
194
+
195
+ end.compact
196
+ end
197
+
139
198
  private
140
199
 
141
200
  ##
142
201
  # nome del file in cui salvare le configurazioni di progetto
143
202
  # @return [String]
144
- def self.cfgs_project_file_name
145
- '.swarm_cluster_project'
203
+ # @param [nil|String] with_env nome dell'env da cercare
204
+ def self.cfgs_project_file_name(with_env: nil)
205
+ ".swarm_cluster_project#{with_env ? ".#{with_env}" : ""}"
146
206
  end
147
207
 
148
208
  ##
@@ -150,7 +210,7 @@ module SwarmClusterCliOpe
150
210
  # quindi ogni ora si autoripulisce e con un md5 delle configurazioni di base
151
211
  # @return [String]
152
212
  def swarm_manager_cache_path
153
- md5 = Digest::MD5.hexdigest(self.class.merged_configurations.to_json)
213
+ md5 = Digest::MD5.hexdigest(self.merged_configurations.to_json)
154
214
  file_name = Time.now.strftime(".swarm_cluster_cli_manager_cache-%Y%m%d%H-#{md5}")
155
215
  File.join("/tmp", file_name)
156
216
  end
@@ -164,29 +224,50 @@ module SwarmClusterCliOpe
164
224
  JSON.parse(File.read(self.base_cfg_path)).deep_symbolize_keys
165
225
  end
166
226
 
227
+ public
228
+
167
229
  ## Cerca le configurazioni di progetto e le mergia se sono presenti
168
230
  # @return [Hash]
169
- def self.merged_configurations
170
- return @_merged_configurations if @_merged_configurations
231
+ def merged_configurations
232
+ return @_merged_configurations[@environment] if @_merged_configurations
233
+
234
+ @_merged_configurations = Hash.new do |hash, key|
235
+ folder = FileUtils.pwd
236
+ default_file = looped_file(folder, self.class.cfgs_project_file_name)
237
+ enviroment_file = looped_file(folder, self.class.cfgs_project_file_name(with_env: key))
238
+
239
+ project_cfgs = {}
240
+ unless default_file.nil?
241
+ project_cfgs = JSON.parse(File.read(default_file)).deep_symbolize_keys
242
+ end
243
+
244
+ unless enviroment_file.nil?
245
+ project_cfgs.merge!(JSON.parse(File.read(enviroment_file)).deep_symbolize_keys)
246
+ end
247
+
248
+ hash[key] = self.class.read_base.merge(project_cfgs)
249
+ end
250
+
251
+ @_merged_configurations[@environment]
252
+
253
+ end
254
+
255
+ private
256
+
257
+ def looped_file(start_folder, file)
171
258
  project_file = nil
172
- folder = FileUtils.pwd
173
259
  loop do
174
260
 
175
- if File.exist?(File.join(folder, cfgs_project_file_name))
176
- project_file = File.join(folder, cfgs_project_file_name)
261
+ if File.exist?(File.join(start_folder, file))
262
+ project_file = File.join(start_folder, file)
177
263
  end
178
264
 
179
265
  break unless project_file.nil?
180
- break if folder == '/'
181
- folder = File.expand_path("..", folder)
182
- end
183
-
184
- project_cfgs = {}
185
- unless project_file.nil?
186
- project_cfgs = JSON.parse(File.read(project_file)).deep_symbolize_keys
266
+ break if start_folder == '/'
267
+ start_folder = File.expand_path("..", start_folder)
187
268
  end
188
269
 
189
- @_merged_configurations = read_base.merge(project_cfgs)
270
+ project_file
190
271
  end
191
272
 
192
273
  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]
@@ -19,7 +19,6 @@ module SwarmClusterCliOpe
19
19
 
20
20
  ##
21
21
  # Containers del servizio
22
-
23
22
  # @return [Array<SwarmClusterCliOpe::Container>]
24
23
  def containers
25
24
  tasks.collect { |t| t.container }
@@ -0,0 +1,44 @@
1
+ module SwarmClusterCliOpe
2
+ module SyncConfigs
3
+ class Base < Thor::Shell::Basic
4
+ include LoggerConcern
5
+ #@return [String] nome del servizio dello stack
6
+ attr_accessor :service
7
+
8
+ #@return [Hash] configurazioni di sincro
9
+ attr_accessor :configs
10
+
11
+ # @param [Hash] configs
12
+ # @param [Continuation] stack_cfgs
13
+ def initialize(stack_cfgs, configs)
14
+ super()
15
+ @configs = configs
16
+
17
+ @service = configs[:service]
18
+ @stack_cfgs = stack_cfgs
19
+ end
20
+
21
+
22
+ delegate :stack_name, to: :@stack_cfgs
23
+
24
+ ##
25
+ # Funzione che dobbiamo sovrascrivere per identificare cosa fare quando scarichiamo i dati
26
+ def pull
27
+ raise "TO OVERRIDE"
28
+ end
29
+
30
+ ##
31
+ # Funzione che dobbiamo sovrascrivere per identificare cosa fare quando carichiamo i dati
32
+ def push
33
+ raise "TO OVERRIDE"
34
+ end
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
+
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,31 @@
1
+ module SwarmClusterCliOpe
2
+ module SyncConfigs
3
+ class Copy < Base
4
+
5
+ # @return [String]
6
+ def local_folder
7
+ @configs[:configs][:local]
8
+ end
9
+
10
+ # @return [String]
11
+ def remote_folder
12
+ @configs[:configs][:remote]
13
+ end
14
+
15
+ # @return [TrueClass, FalseClass]
16
+ def push
17
+ say "#{local_folder} -->> #{remote_folder}" if container.copy_in(local_folder,remote_folder)
18
+ end
19
+
20
+ # @return [TrueClass, FalseClass]
21
+ def pull
22
+ say "#{remote_folder} -->> #{local_folder}" if container.copy_out(remote_folder,local_folder)
23
+ end
24
+
25
+
26
+
27
+
28
+
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,77 @@
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
+ def self.define_cfgs(name, default_env:, configuration_name:)
39
+ configuration_name ||= name
40
+
41
+ define_method(name) do
42
+ return self.instance_variable_get("@#{name}") if self.instance_variable_defined?("@#{name}")
43
+
44
+ #valore restituito direttamente dalla configurazione
45
+ if @configs.key?(configuration_name)
46
+ value = @configs["#{configuration_name}".to_sym]
47
+ else
48
+ env_var = @configs["#{configuration_name}_env".to_sym] || default_env
49
+ value = find_env_file_variable(env_var)
50
+ end
51
+ self.instance_variable_set("@#{name}", value)
52
+ end
53
+
54
+ end
55
+
56
+
57
+ private
58
+
59
+ ##
60
+ # Estrae l'env dal container e ne tiene in memoria una copia, in modo da non fare multiple chiamate
61
+ def env
62
+ @env ||= container.exec("env").raw_result[:stdout].split("\n").collect { |v| v.split('=') }.to_h
63
+ end
64
+
65
+ def find_env_file_variable(env_var)
66
+ if env_var.match?(/_FILE$/)
67
+ # dobbiamo controllare la presenza del file e salvarci il contenuto
68
+ nome_file = env[env_var.to_s]
69
+ container.exec("cat #{nome_file}").raw_result[:stdout]
70
+ else
71
+ # env normale, dobbiamo ricavarlo dal container
72
+ env[env_var.to_s]
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,78 @@
1
+ module SwarmClusterCliOpe
2
+ module SyncConfigs
3
+ class Mysql < Base
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.mysql_user} --password=#{remote.mysql_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.mysql_user} --password=#{local.mysql_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.mysql_user} --password=#{local.mysql_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.mysql_user} --password=#{remote.mysql_password} #{remote.database_name}'")
25
+ end
26
+ true
27
+ end
28
+
29
+ # @return [SwarmClusterCliOpe::SyncConfigs::Mysql::EnvConfigs]
30
+ def remote
31
+ EnvConfigs.new(self, @configs[:configs][:remote] || {}, -> { container })
32
+ end
33
+
34
+ # @return [SwarmClusterCliOpe::SyncConfigs::Mysql::EnvConfigs]
35
+ def local
36
+ EnvConfigs.new(self, @configs[:configs][:local] || {}, -> { local_container })
37
+ end
38
+
39
+
40
+ ##
41
+ # Classe interna che rappresenta le configurazioni del DB
42
+ class EnvConfigs < SwarmClusterCliOpe::SyncConfigs::EnvConfigs
43
+
44
+ define_cfgs :database_name, default_env: "MYSQL_DATABASE", configuration_name: :database_name
45
+ define_cfgs :mysql_user, default_env: "MYSQL_USER", configuration_name: :mysql_user
46
+ define_cfgs :mysql_password, default_env: "MYSQL_PASSWORD", configuration_name: :mysql_password
47
+
48
+ end
49
+
50
+
51
+ ##
52
+ # Funzione che ricapitola le informazioni utilizzate per eseguire l'operazione
53
+ def resume(direction)
54
+ puts "RESUME - #{direction}
55
+ service: #{service}
56
+ local:
57
+ service_name: #{local.service_name}
58
+ database_name: #{local.database_name}
59
+ mysql_user: #{local.mysql_user}
60
+ mysql_password: #{local.mysql_password}
61
+ remote:
62
+ service_name: #{remote.service_name}
63
+ database_name: #{remote.database_name}
64
+ mysql_user: #{remote.mysql_user}
65
+ mysql_password: #{remote.mysql_password}"
66
+
67
+ end
68
+
69
+ private
70
+
71
+ def local_container
72
+ # il nome dello stack del compose usiamo come standard il nome della cartella, come lo fà già composer di default
73
+ Models::ComposeContainer.find_by_service_name(local.service_name, stack_name: @stack_cfgs.local_compose_project_name)
74
+ end
75
+
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,71 @@
1
+ module SwarmClusterCliOpe
2
+ module SyncConfigs
3
+ class Rsync < Base
4
+
5
+
6
+ # @return [String]
7
+ def local_folder
8
+ @configs[:configs][:local]
9
+ end
10
+
11
+ # @return [String]
12
+ def remote_folder
13
+ @configs[:configs][:remote]
14
+ end
15
+
16
+
17
+ # @return [SwarmClusterCliOpe::ShellCommandResponse]
18
+ def push
19
+ execute(direction: :up)
20
+ end
21
+
22
+ # @return [SwarmClusterCliOpe::ShellCommandResponse]
23
+ def pull
24
+ execute(direction: :down)
25
+ end
26
+
27
+
28
+ private
29
+ def execute(direction: :down)
30
+
31
+ if container.nil?
32
+ say "Container non trovato con #{stack_name}@##{service}"
33
+ exit 0
34
+ end
35
+
36
+
37
+ # trovo la cartella bindata e la relativa cartella sul nodo
38
+ volume = container.mapped_volumes.find { |v| v.destination == remote_folder and v.is_binded? }
39
+ if volume.nil?
40
+ say "Non ho trovato il volume bindato con questa destinazione all'interno del container #{remote_folder}"
41
+ exit 0
42
+ end
43
+
44
+ #costruisco il comando rsync fra cartella del nodo e cartella sul pc
45
+ cmd = ["rsync", "-zr", "--delete"]
46
+ if direction == :down
47
+ cmd << "#{volume.ssh_connection_path}/."
48
+ # creo la cartella in locale se non esiste
49
+ FileUtils.mkdir_p(local_folder)
50
+ cmd << local_folder
51
+ end
52
+ if direction == :up
53
+ cmd << "#{local_folder}/."
54
+ cmd << volume.ssh_connection_path
55
+ end
56
+
57
+ cmd = ShellCommandExecution.new(cmd)
58
+
59
+ say "Comando da eseguire:"
60
+ say " #{cmd.string_command}"
61
+ if yes?("Confermare il comando?[y,yes]")
62
+ cmd.execute
63
+ end
64
+
65
+
66
+ end
67
+
68
+
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,8 @@
1
+ module SwarmClusterCliOpe
2
+ module SyncConfigs
3
+ class Sqlite3 < Copy
4
+
5
+
6
+ end
7
+ end
8
+ end
@@ -1,3 +1,3 @@
1
1
  module SwarmClusterCliOpe
2
- VERSION = "0.1.6"
2
+ VERSION = "0.3.1"
3
3
  end
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.1.6
4
+ version: 0.3.1
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-05-12 00:00:00.000000000 Z
11
+ date: 2020-09-09 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
@@ -107,6 +109,12 @@ files:
107
109
  - lib/swarm_cluster_cli_ope/node.rb
108
110
  - lib/swarm_cluster_cli_ope/shell_command_execution.rb
109
111
  - lib/swarm_cluster_cli_ope/shell_command_response.rb
112
+ - lib/swarm_cluster_cli_ope/sync_configs/base.rb
113
+ - lib/swarm_cluster_cli_ope/sync_configs/copy.rb
114
+ - lib/swarm_cluster_cli_ope/sync_configs/env_configs.rb
115
+ - lib/swarm_cluster_cli_ope/sync_configs/mysql.rb
116
+ - lib/swarm_cluster_cli_ope/sync_configs/rsync.rb
117
+ - lib/swarm_cluster_cli_ope/sync_configs/sqlite3.rb
110
118
  - lib/swarm_cluster_cli_ope/version.rb
111
119
  - lib/swarm_cluster_cli_ope/worker.rb
112
120
  - swarm_cluster_cli_ope.gemspec
@@ -133,7 +141,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
133
141
  - !ruby/object:Gem::Version
134
142
  version: '0'
135
143
  requirements: []
136
- rubygems_version: 3.0.6
144
+ rubygems_version: 3.0.8
137
145
  signing_key:
138
146
  specification_version: 4
139
147
  summary: WIP Gemma per la gestione del cluster swarm