swarm_cluster_cli_ope 0.1.6 → 0.3.1

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 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