swarm_cluster_cli_ope 0.1.3 → 0.2.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 +4 -4
- data/Gemfile.lock +3 -3
- data/README.md +10 -14
- data/lib/swarm_cluster_cli_ope/cli.rb +176 -123
- data/lib/swarm_cluster_cli_ope/configuration.rb +92 -25
- data/lib/swarm_cluster_cli_ope/node.rb +1 -2
- data/lib/swarm_cluster_cli_ope/sync_configs/base.rb +35 -0
- data/lib/swarm_cluster_cli_ope/sync_configs/copy.rb +35 -0
- data/lib/swarm_cluster_cli_ope/sync_configs/rsync.rb +74 -0
- data/lib/swarm_cluster_cli_ope/sync_configs/sqlite3.rb +8 -0
- data/lib/swarm_cluster_cli_ope/version.rb +1 -1
- data/swarm_cluster_cli_ope.gemspec +3 -3
- metadata +11 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: de6a7a1c00385430cb66e44f3fc8c02bac60bc5c930223c9cf56d592205d4963
|
4
|
+
data.tar.gz: 6e400a291bc159ac2e6149f55fe46cbe7dcdeb84b391ee4d7f93c211d19625d2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e680840f5518ac667362afde85caca8f10a86bbb77cc122bd53580284e7ee8c6f365bc0b5b0f158eb494a97431765fd9cf057554c6ed20d3e10ef91779cd1dc3
|
7
|
+
data.tar.gz: 3976388f15a0fe1fd34efe15f2977f3b21d5167c7bbbf3d534c5ab0c10e1b34126110f36e00f186c3cd66b8456929db58585e29a414d6799f1a66b69352e7b31
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
swarm_cluster_cli_ope (0.1
|
4
|
+
swarm_cluster_cli_ope (0.2.1)
|
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.
|
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
|
-
```
|
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/
|
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
|
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
|
-
|
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
|
62
|
+
option :stack_name, required: false, type: :string
|
58
63
|
|
59
64
|
def services
|
60
|
-
|
61
|
-
|
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
|
74
|
+
option :stack_name, required: false, type: :string
|
67
75
|
|
68
76
|
def mc(service_name)
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
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
|
-
|
94
|
-
|
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
|
-
|
122
|
-
|
123
|
-
#
|
124
|
-
|
125
|
-
|
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
|
-
|
129
|
-
c.add("
|
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
|
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
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
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.
|
163
|
-
|
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
|
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
|
-
|
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
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
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
|
-
|
180
|
-
|
181
|
-
|
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
|
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:
|
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
|
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:
|
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,62 @@ module SwarmClusterCliOpe
|
|
206
243
|
end
|
207
244
|
end
|
208
245
|
|
246
|
+
desc "stacksync DIRECTION", "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
|
260
|
+
---- rsync -> RSYNC
|
261
|
+
- configs: è un hash con le configurazioni per ogni tipo di sincronizzazione
|
262
|
+
LONGDESC
|
209
263
|
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
264
|
+
def stacksync(direction)
|
265
|
+
direction = case direction
|
266
|
+
when 'push'
|
267
|
+
:push
|
268
|
+
when 'pull'
|
269
|
+
:pull
|
270
|
+
else
|
271
|
+
raise "ONLY [push|pull] action accepted"
|
272
|
+
end
|
273
|
+
cfgs.env(options[:environment]) do |cfgs|
|
274
|
+
cfgs.sync_configurations.each do |sync|
|
275
|
+
sync.send(direction)
|
276
|
+
end
|
220
277
|
end
|
278
|
+
end
|
221
279
|
|
280
|
+
private
|
222
281
|
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
end
|
282
|
+
def rsync_binded(direction: :down, options: {})
|
283
|
+
cfgs.env(options[:environment]) do |cfgs|
|
284
|
+
cfgs.stack_name = options[:stack_name] || cfgs.stack_name
|
285
|
+
sync = SyncConfigs::Rsync.new(cfgs, {
|
286
|
+
service: options[:service_name],
|
287
|
+
how: 'rsync',
|
288
|
+
configs: {
|
289
|
+
local: options[:local_folder],
|
290
|
+
remote: options[:binded_container_folders]
|
291
|
+
}
|
292
|
+
})
|
293
|
+
|
294
|
+
if direction == :down
|
295
|
+
sync.pull
|
296
|
+
end
|
297
|
+
if direction == :up
|
298
|
+
sync.push
|
299
|
+
end
|
242
300
|
|
243
|
-
cmd = ShellCommandExecution.new(cmd)
|
244
301
|
|
245
|
-
say "Comando da eseguire:"
|
246
|
-
say " #{cmd.string_command}"
|
247
|
-
if yes?("Confermare il comando?[y,yes]")
|
248
|
-
cmd.execute
|
249
302
|
end
|
250
303
|
end
|
251
304
|
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
|
-
|
52
|
-
|
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
|
-
|
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
|
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
|
-
|
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
|
-
|
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
|
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
|
-
|
145
|
-
|
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.
|
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,51 @@ 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
|
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
|
+
logger.debug { "CONFIGS[#{@environment}]: #{project_cfgs.inspect}" }
|
234
|
+
hash[key] = self.class.read_base.merge(project_cfgs)
|
235
|
+
end
|
236
|
+
|
237
|
+
@_merged_configurations[@environment]
|
238
|
+
|
239
|
+
end
|
240
|
+
|
241
|
+
private
|
242
|
+
|
243
|
+
def looped_file(start_folder, file)
|
171
244
|
project_file = nil
|
172
|
-
folder = FileUtils.pwd
|
173
245
|
loop do
|
174
246
|
|
175
|
-
if File.exist?(File.join(
|
176
|
-
project_file = File.join(
|
247
|
+
if File.exist?(File.join(start_folder, file))
|
248
|
+
project_file = File.join(start_folder, file)
|
177
249
|
end
|
178
250
|
|
179
251
|
break unless project_file.nil?
|
180
|
-
break if
|
181
|
-
|
182
|
-
end
|
183
|
-
|
184
|
-
project_cfgs = {}
|
185
|
-
unless project_file.nil?
|
186
|
-
project_cfgs = JSON.parse(File.read(project_file)).deep_symbolize_keys
|
252
|
+
break if start_folder == '/'
|
253
|
+
start_folder = File.expand_path("..", start_folder)
|
187
254
|
end
|
188
255
|
|
189
|
-
|
256
|
+
project_file
|
190
257
|
end
|
191
258
|
|
192
259
|
end
|
@@ -50,8 +50,7 @@ module SwarmClusterCliOpe
|
|
50
50
|
# @return [OpenStruct]
|
51
51
|
def info
|
52
52
|
# path al file di cache
|
53
|
-
|
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
|
+
container.copy_in(local_folder,remote_folder)
|
18
|
+
end
|
19
|
+
|
20
|
+
# @return [TrueClass, FalseClass]
|
21
|
+
def pull
|
22
|
+
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
|
@@ -10,15 +10,15 @@ Gem::Specification.new do |spec|
|
|
10
10
|
spec.description = "Gestione di varie operazioni come sincronia con le cartelle bindate dei container (rsync) up o
|
11
11
|
down e possibilità di scaricare/caricare i file direttamente all'interno del cluster, in
|
12
12
|
modo facilitato"
|
13
|
-
spec.homepage = "https://
|
13
|
+
spec.homepage = "https://github.com/ArchimediaZerogroup/swarm_cluster_cli_ope"
|
14
14
|
spec.license = "MIT"
|
15
15
|
spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
|
16
16
|
|
17
17
|
spec.metadata["allowed_push_host"] = 'https://rubygems.org/'
|
18
18
|
|
19
19
|
spec.metadata["homepage_uri"] = spec.homepage
|
20
|
-
|
21
|
-
|
20
|
+
spec.metadata["source_code_uri"] = "https://github.com/ArchimediaZerogroup/swarm_cluster_cli_ope"
|
21
|
+
spec.metadata["changelog_uri"] = "https://github.com/ArchimediaZerogroup/swarm_cluster_cli_ope/blob/master/CHANGELOG.md"
|
22
22
|
|
23
23
|
# Specify which files should be added to the gem when it is released.
|
24
24
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
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
|
+
version: 0.2.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-
|
11
|
+
date: 2020-07-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -107,15 +107,21 @@ 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
|
113
|
-
homepage: https://
|
117
|
+
homepage: https://github.com/ArchimediaZerogroup/swarm_cluster_cli_ope
|
114
118
|
licenses:
|
115
119
|
- MIT
|
116
120
|
metadata:
|
117
121
|
allowed_push_host: https://rubygems.org/
|
118
|
-
homepage_uri: https://
|
122
|
+
homepage_uri: https://github.com/ArchimediaZerogroup/swarm_cluster_cli_ope
|
123
|
+
source_code_uri: https://github.com/ArchimediaZerogroup/swarm_cluster_cli_ope
|
124
|
+
changelog_uri: https://github.com/ArchimediaZerogroup/swarm_cluster_cli_ope/blob/master/CHANGELOG.md
|
119
125
|
post_install_message:
|
120
126
|
rdoc_options: []
|
121
127
|
require_paths:
|
@@ -131,7 +137,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
131
137
|
- !ruby/object:Gem::Version
|
132
138
|
version: '0'
|
133
139
|
requirements: []
|
134
|
-
rubygems_version: 3.0.
|
140
|
+
rubygems_version: 3.0.8
|
135
141
|
signing_key:
|
136
142
|
specification_version: 4
|
137
143
|
summary: WIP Gemma per la gestione del cluster swarm
|