swarm_cluster_cli_ope 0.1.4 → 0.2.2

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: 5b94cc1986544ce1c00945bf883df5c9e4003509e2a55eabd8dfcb30eece8f9a
4
- data.tar.gz: 2bc401e45d21d81433fa837f8e647e847b395f0f1c725f98685931d25c76ac53
3
+ metadata.gz: e7a0c1998bd04fc1f315b316b47d094352f24d07ca19cd0da18254a59bd4cd68
4
+ data.tar.gz: ef6f7962bf661d9839ace5820485896db7c4066194632d865c54e5b667c05957
5
5
  SHA512:
6
- metadata.gz: df6e5910223f8aaf1b8dac1d7d8ef253e5f87e3fa51fb0240efb9c6f50ab9f586373ad2fc569bb3306603b8ca680bf7543557cf33bba08d5193566f0ba9f2479
7
- data.tar.gz: dd52d60b709b2b5f196f80825f6857940c35cfe76bde1bc964d45b77df876cd683a94261fa34ce83bdd3dc2949af28ca25903e80bedfed367979592c10395955
6
+ metadata.gz: 514cca4b32bf7fa10adc40a0579a5db538a0601733ea78a0bb9514ff6b6cf006cf7bd2d6d744b508048d9a351fd79c2a5fd290b18a28c7b2fc376d19f9eed47c
7
+ data.tar.gz: f174ac4bff4447acb66218ca7d20319caf47b8cd7e67d6a52a0974cfa940eaa5888f6a649e2ccf4b4b7283840c75c1b3ebcd03d17ebe4ef0b082119087782668
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- swarm_cluster_cli_ope (0.1.4)
4
+ swarm_cluster_cli_ope (0.2.2)
5
5
  activesupport
6
6
  open4
7
7
  thor (~> 1.0)
@@ -10,12 +10,12 @@ PATH
10
10
  GEM
11
11
  remote: https://rubygems.org/
12
12
  specs:
13
- activesupport (6.0.2.2)
13
+ activesupport (6.0.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
- zeitwerk (~> 2.2)
18
+ zeitwerk (~> 2.2, >= 2.2.2)
19
19
  concurrent-ruby (1.1.6)
20
20
  i18n (1.8.2)
21
21
  concurrent-ruby (~> 1.0)
data/README.md CHANGED
@@ -22,7 +22,7 @@ Or install it yourself as:
22
22
 
23
23
  Una volta installato lanciare il comando
24
24
 
25
- ```swarm_cluster_cli_ope install``` che si occuperà di configurare le varie impostazioni dell'ambiente
25
+ ```swarm_cli_ope install``` che si occuperà di configurare le varie impostazioni dell'ambiente
26
26
 
27
27
  FILE di configurazione base:
28
28
  ```json
@@ -36,9 +36,12 @@ 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
- quali stack_name
44
+ quali stack_name (.swarm_cluster_project)
42
45
  ```shell script
43
46
  swarm_cli_ope configure_project STACK_NAME
44
47
  ```
@@ -82,10 +85,6 @@ swarm_cli_ope services --stack-name=NOME_STACK
82
85
  ```shell script
83
86
  swarm_cli_ope cp --stack-name=NOME_STACK PATH_FILE_LOCALE NOME_SERVIZIO:DESTINAZIONE_NEL_CONTAINER
84
87
  ```
85
- ES:
86
- ```shell script
87
- swarm_cli_ope cp --stack-name=webapps-examinerapp-staging ./test_folder/test_1/cartella_bindata/test jeapp:/tmp/.
88
- ```
89
88
 
90
89
  ### Rsync da/a container a/da locale
91
90
 
@@ -96,23 +95,20 @@ Utilizzare `rsync_binded_from` per scaricare e `rsync_binded_to` per caricare
96
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
97
96
  ```
98
97
 
99
- ES:
100
- ```shell script
101
- swarm_cli_ope rsync_binded_from --stack-name=web-site-ranchilbosco-production --service_name wordpress --binded-container-folders /var/www/html/wp-content/uploads --destination ./uploads
102
- ```
103
-
104
-
105
98
  ## Development
106
99
 
107
100
  nel file di configurazione creato nella home aggiungere la chiave "dev_mode":1 per collegarsi localmente
108
101
 
109
102
  ### Abbiamo due tasks swarm di simulazione
110
103
  ```shell script
111
- docker stack deploy -c test_folder/test_1/docker_compose.yml test1
104
+ docker stack deploy -c test_folder/test_1/docker-compose.yml test1
105
+ docker stack deploy -c test_folder/test_1/docker-compose.yml test1_staging
112
106
  docker stack deploy -c test_folder/test_2/docker_compose.yml test2
113
107
  ```
114
108
 
115
- 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).
109
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version
110
+ number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git
111
+ commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
116
112
 
117
113
 
118
114
  ## 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
@@ -37,10 +40,12 @@ module SwarmClusterCliOpe
37
40
 
38
41
  end
39
42
 
40
- desc "config", "Visualizza le configurazioni mergiate (HOME + Project)"
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
128
+ end
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
130
141
  end
131
- stop_ssh_container.execute
132
- end
133
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,49 +154,76 @@ 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
- option :local_folder, required: false, type: :string, desc: "path della cartella dove sincronizzare il comando"
226
+ option :local_folder, required: true, type: :string, desc: "path della cartella dove sincronizzare il comando"
190
227
 
191
228
  def rsync_binded_from
192
229
  if yes? "Attenzione, i dati locali verranno sovrascritti/cancellati?[y,yes]"
@@ -195,10 +232,10 @@ 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
- option :local_folder, required: false, type: :string, desc: "path della cartella dove sincronizzare il comando"
238
+ option :local_folder, required: true, type: :string, desc: "path della cartella dove sincronizzare il comando"
202
239
 
203
240
  def rsync_binded_to
204
241
  if yes? "ATTENZIONE, i dati remoti verranno sovrascritti/cancellati da quelli locali?[y,yes]"
@@ -206,46 +243,98 @@ 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 TODO
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
+ EXAMPLE:
273
+ Esempio di sincronizzazione di un file sqlite3 e una cartella
274
+ {
275
+ "stack_name": "test1",
276
+ "sync_configs": [
277
+ {
278
+ "service": "second",
279
+ "how": "rsync",
280
+ "configs": {
281
+ "remote": "/test_bind",
282
+ "local": "./uploads"
283
+ }
284
+ },
285
+ {
286
+ "service": "test_sqlite3",
287
+ "how": "sqlite3",
288
+ "configs": {
289
+ "remote": "/cartella_sqlite3/esempio.sqlite3",
290
+ "local": "./development.sqlite3"
291
+ }
292
+ }
293
+ ]
294
+ }
295
+ LONGDESC
209
296
 
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
297
+ def stacksync(direction)
298
+ direction = case direction
299
+ when 'push'
300
+ :push
301
+ when 'pull'
302
+ :pull
303
+ else
304
+ raise "ONLY [push|pull] action accepted"
305
+ end
306
+ cfgs.env(options[:environment]) do |cfgs|
307
+ cfgs.sync_configurations.each do |sync|
308
+ say "----------->>>>>>"
309
+ say "[ #{sync.class.name} ]"
310
+ sync.send(direction)
311
+ say "<<<<<<-----------"
312
+ end
220
313
  end
314
+ end
221
315
 
316
+ private
222
317
 
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
318
+ def rsync_binded(direction: :down, options: {})
319
+ cfgs.env(options[:environment]) do |cfgs|
320
+ cfgs.stack_name = options[:stack_name] || cfgs.stack_name
321
+ sync = SyncConfigs::Rsync.new(cfgs, {
322
+ service: options[:service_name],
323
+ how: 'rsync',
324
+ configs: {
325
+ local: options[:local_folder],
326
+ remote: options[:binded_container_folders]
327
+ }
328
+ })
329
+
330
+ if direction == :down
331
+ sync.pull
332
+ end
333
+ if direction == :up
334
+ sync.push
335
+ end
242
336
 
243
- cmd = ShellCommandExecution.new(cmd)
244
337
 
245
- say "Comando da eseguire:"
246
- say " #{cmd.string_command}"
247
- if yes?("Confermare il comando?[y,yes]")
248
- cmd.execute
249
338
  end
250
339
  end
251
340
  end
@@ -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,31 @@ module SwarmClusterCliOpe
136
163
  nodes.find { |c| c.id == node_id }
137
164
  end
138
165
 
166
+ ##
167
+ # Elenco di tutte le configurazioni di sincronizzazione
168
+ def sync_configurations
169
+ merged_configurations[:sync_configs].collect do |c|
170
+
171
+ case c[:how]
172
+ when 'sqlite3'
173
+ SyncConfigs::Sqlite3.new(self, c)
174
+ when 'rsync'
175
+ SyncConfigs::Rsync.new(self, c)
176
+ else
177
+ logger.error { "CONFIGURAIONE NON PREVISTA: #{c[:how]}" }
178
+ end
179
+
180
+ end.compact
181
+ end
182
+
139
183
  private
140
184
 
141
185
  ##
142
186
  # nome del file in cui salvare le configurazioni di progetto
143
187
  # @return [String]
144
- def self.cfgs_project_file_name
145
- '.swarm_cluster_project'
188
+ # @param [nil|String] with_env nome dell'env da cercare
189
+ def self.cfgs_project_file_name(with_env: nil)
190
+ ".swarm_cluster_project#{with_env ? ".#{with_env}" : ""}"
146
191
  end
147
192
 
148
193
  ##
@@ -150,7 +195,7 @@ module SwarmClusterCliOpe
150
195
  # quindi ogni ora si autoripulisce e con un md5 delle configurazioni di base
151
196
  # @return [String]
152
197
  def swarm_manager_cache_path
153
- md5 = Digest::MD5.hexdigest(self.class.merged_configurations.to_json)
198
+ md5 = Digest::MD5.hexdigest(self.merged_configurations.to_json)
154
199
  file_name = Time.now.strftime(".swarm_cluster_cli_manager_cache-%Y%m%d%H-#{md5}")
155
200
  File.join("/tmp", file_name)
156
201
  end
@@ -164,29 +209,50 @@ module SwarmClusterCliOpe
164
209
  JSON.parse(File.read(self.base_cfg_path)).deep_symbolize_keys
165
210
  end
166
211
 
212
+ public
213
+
167
214
  ## Cerca le configurazioni di progetto e le mergia se sono presenti
168
215
  # @return [Hash]
169
- def self.merged_configurations
170
- return @_merged_configurations if @_merged_configurations
216
+ def merged_configurations
217
+ return @_merged_configurations[@environment] if @_merged_configurations
218
+
219
+ @_merged_configurations = Hash.new do |hash, key|
220
+ folder = FileUtils.pwd
221
+ default_file = looped_file(folder, self.class.cfgs_project_file_name)
222
+ enviroment_file = looped_file(folder, self.class.cfgs_project_file_name(with_env: key))
223
+
224
+ project_cfgs = {}
225
+ unless default_file.nil?
226
+ project_cfgs = JSON.parse(File.read(default_file)).deep_symbolize_keys
227
+ end
228
+
229
+ unless enviroment_file.nil?
230
+ project_cfgs.merge!(JSON.parse(File.read(enviroment_file)).deep_symbolize_keys)
231
+ end
232
+
233
+ hash[key] = self.class.read_base.merge(project_cfgs)
234
+ end
235
+
236
+ @_merged_configurations[@environment]
237
+
238
+ end
239
+
240
+ private
241
+
242
+ def looped_file(start_folder, file)
171
243
  project_file = nil
172
- folder = FileUtils.pwd
173
244
  loop do
174
245
 
175
- if File.exist?(File.join(folder, cfgs_project_file_name))
176
- project_file = File.join(folder, cfgs_project_file_name)
246
+ if File.exist?(File.join(start_folder, file))
247
+ project_file = File.join(start_folder, file)
177
248
  end
178
249
 
179
250
  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
251
+ break if start_folder == '/'
252
+ start_folder = File.expand_path("..", start_folder)
187
253
  end
188
254
 
189
- @_merged_configurations = read_base.merge(project_cfgs)
255
+ project_file
190
256
  end
191
257
 
192
258
  end
@@ -50,8 +50,7 @@ module SwarmClusterCliOpe
50
50
  # @return [OpenStruct]
51
51
  def info
52
52
  # path al file di cache
53
- # TODO sarebbe da aggiornare ogni tanto, metti che uno non spegne mai il pc
54
- path = "/tmp/.swarm_cluster_cli_info_cache_#{name}"
53
+ path = Time.now.strftime("/tmp/.swarm_cluster_cli_info_cache_#{name}-%Y%m%d%H")
55
54
  if File.exist?(path)
56
55
  i = JSON.parse(File.read(path), object_class: OpenStruct)
57
56
  else
@@ -0,0 +1,35 @@
1
+ module SwarmClusterCliOpe
2
+ module SyncConfigs
3
+ class Base < Thor::Shell::Basic
4
+
5
+ #@return [String] nome del servizio dello stack
6
+ attr_accessor :service
7
+
8
+ # @param [Hash] configs
9
+ # @param [Continuation] stack_cfgs
10
+ def initialize(stack_cfgs, configs)
11
+ super()
12
+ @configs = configs
13
+
14
+ @service = configs[:service]
15
+ @stack_cfgs = stack_cfgs
16
+ end
17
+
18
+
19
+ delegate :stack_name, to: :@stack_cfgs
20
+
21
+ ##
22
+ # Funzione che dobbiamo sovrascrivere per identificare cosa fare quando scarichiamo i dati
23
+ def pull
24
+ raise "TO OVERRIDE"
25
+ end
26
+
27
+ ##
28
+ # Funzione che dobbiamo sovrascrivere per identificare cosa fare quando carichiamo i dati
29
+ def push
30
+ raise "TO OVERRIDE"
31
+ end
32
+
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,35 @@
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
+ private
27
+ # @return [SwarmClusterCliOpe::Models::Container]
28
+ def container
29
+ Models::Container.find_by_service_name(service, stack_name: stack_name)
30
+ end
31
+
32
+
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,74 @@
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
+ # trovo il container del servizio
32
+ container = Models::Container.find_by_service_name(service, stack_name: stack_name)
33
+
34
+ if container.nil?
35
+ say "Container non trovato con #{stack_name}@##{service}"
36
+ exit 0
37
+ end
38
+
39
+
40
+ # trovo la cartella bindata e la relativa cartella sul nodo
41
+ volume = container.mapped_volumes.find { |v| v.destination == remote_folder and v.is_binded? }
42
+ if volume.nil?
43
+ say "Non ho trovato il volume bindato con questa destinazione all'interno del container #{remote_folder}"
44
+ exit 0
45
+ end
46
+
47
+ #costruisco il comando rsync fra cartella del nodo e cartella sul pc
48
+ cmd = ["rsync", "-zr", "--delete"]
49
+ if direction == :down
50
+ cmd << "#{volume.ssh_connection_path}/."
51
+ # creo la cartella in locale se non esiste
52
+ FileUtils.mkdir_p(local_folder)
53
+ cmd << local_folder
54
+ end
55
+ if direction == :up
56
+ cmd << "#{local_folder}/."
57
+ cmd << volume.ssh_connection_path
58
+ end
59
+
60
+ cmd = ShellCommandExecution.new(cmd)
61
+
62
+ say "Comando da eseguire:"
63
+ say " #{cmd.string_command}"
64
+ if yes?("Confermare il comando?[y,yes]")
65
+ cmd.execute
66
+ end
67
+
68
+
69
+ end
70
+
71
+
72
+ end
73
+ end
74
+ 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.4"
2
+ VERSION = "0.2.2"
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.4
4
+ version: 0.2.2
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-05 00:00:00.000000000 Z
11
+ date: 2020-07-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -107,6 +107,10 @@ files:
107
107
  - lib/swarm_cluster_cli_ope/node.rb
108
108
  - lib/swarm_cluster_cli_ope/shell_command_execution.rb
109
109
  - lib/swarm_cluster_cli_ope/shell_command_response.rb
110
+ - lib/swarm_cluster_cli_ope/sync_configs/base.rb
111
+ - lib/swarm_cluster_cli_ope/sync_configs/copy.rb
112
+ - lib/swarm_cluster_cli_ope/sync_configs/rsync.rb
113
+ - lib/swarm_cluster_cli_ope/sync_configs/sqlite3.rb
110
114
  - lib/swarm_cluster_cli_ope/version.rb
111
115
  - lib/swarm_cluster_cli_ope/worker.rb
112
116
  - swarm_cluster_cli_ope.gemspec
@@ -133,7 +137,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
133
137
  - !ruby/object:Gem::Version
134
138
  version: '0'
135
139
  requirements: []
136
- rubygems_version: 3.0.6
140
+ rubygems_version: 3.0.8
137
141
  signing_key:
138
142
  specification_version: 4
139
143
  summary: WIP Gemma per la gestione del cluster swarm