swarm_cluster_cli_ope 0.5.0.pre.2 → 0.5.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 +1 -45
- data/README.md +11 -2
- data/lib/swarm_cluster_cli_ope.rb +9 -1
- data/lib/swarm_cluster_cli_ope/base_configuration.rb +226 -0
- data/lib/swarm_cluster_cli_ope/cli.rb +2 -129
- data/lib/swarm_cluster_cli_ope/configuration.rb +10 -186
- data/lib/swarm_cluster_cli_ope/configuration_concern.rb +10 -9
- data/lib/swarm_cluster_cli_ope/k8s.rb +59 -83
- data/lib/swarm_cluster_cli_ope/kubernetes/configuration.rb +75 -0
- data/lib/swarm_cluster_cli_ope/kubernetes/pod.rb +144 -0
- data/lib/swarm_cluster_cli_ope/{k8s_rsync → kubernetes/rsync_cfgs}/password +0 -0
- data/lib/swarm_cluster_cli_ope/{k8s_rsync → kubernetes/rsync_cfgs}/rsyncd.conf +0 -0
- data/lib/swarm_cluster_cli_ope/{k8s_rsync → kubernetes/rsync_cfgs}/rsyncd.secrets +0 -0
- data/lib/swarm_cluster_cli_ope/kubernetes/sync_configs/base_decorator.rb +28 -0
- data/lib/swarm_cluster_cli_ope/kubernetes/sync_configs/mysql.rb +10 -0
- data/lib/swarm_cluster_cli_ope/kubernetes/sync_configs/post_gres.rb +11 -0
- data/lib/swarm_cluster_cli_ope/kubernetes/sync_configs/rsync.rb +125 -0
- data/lib/swarm_cluster_cli_ope/kubernetes/sync_configs/sqlite3.rb +9 -0
- data/lib/swarm_cluster_cli_ope/logger_concern.rb +1 -1
- data/lib/swarm_cluster_cli_ope/shell_command_response.rb +18 -5
- data/lib/swarm_cluster_cli_ope/stack_sync_concern.rb +135 -0
- data/lib/swarm_cluster_cli_ope/sync_configs/base.rb +1 -1
- data/lib/swarm_cluster_cli_ope/sync_configs/mysql.rb +17 -2
- data/lib/swarm_cluster_cli_ope/sync_configs/post_gres.rb +1 -1
- data/lib/swarm_cluster_cli_ope/thor_configuration_concern.rb +29 -0
- data/lib/swarm_cluster_cli_ope/version.rb +1 -1
- data/swarm_cluster_cli_ope.gemspec +0 -1
- metadata +17 -21
@@ -0,0 +1,144 @@
|
|
1
|
+
module SwarmClusterCliOpe
|
2
|
+
module Kubernetes
|
3
|
+
##
|
4
|
+
# Interfaccia per la comunicazione con il POD
|
5
|
+
class Pod
|
6
|
+
include LoggerConcern
|
7
|
+
|
8
|
+
|
9
|
+
#@return [Hash]
|
10
|
+
attr_accessor :pod_description
|
11
|
+
|
12
|
+
#@return [String]
|
13
|
+
attr_accessor :context
|
14
|
+
|
15
|
+
# @param [Hash] pod_description -> hash con le configurazioni ritornate da kubectl
|
16
|
+
# @param [String] context -> se non presente utiliziamo l'attuale
|
17
|
+
def initialize(pod_description, context:)
|
18
|
+
@pod_description = pod_description.to_h.deep_symbolize_keys
|
19
|
+
@context = context
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
# @return [String]
|
24
|
+
def name
|
25
|
+
@pod_description[:metadata][:name]
|
26
|
+
end
|
27
|
+
|
28
|
+
def namespace
|
29
|
+
@pod_description[:metadata][:namespace]
|
30
|
+
end
|
31
|
+
|
32
|
+
# @param [String,Array<String>] cmd -> comando da passare a kubectl exec -- CMD
|
33
|
+
# @return [SwarmClusterCliOpe::ShellCommandResponse]
|
34
|
+
def exec(cmd)
|
35
|
+
base_cmd(["exec", name, "--", cmd].flatten).execute
|
36
|
+
end
|
37
|
+
|
38
|
+
##
|
39
|
+
# Appende solamente la parte base dei comandi
|
40
|
+
# @return [SwarmClusterCliOpe::ShellCommandExecution]
|
41
|
+
# @param [String,Array<String>] cmd
|
42
|
+
def base_cmd(cmd)
|
43
|
+
ShellCommandExecution.new([base_kubectl_cmd_env, cmd].flatten)
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
##
|
48
|
+
# Comando per la copia del file
|
49
|
+
# @param [String] src
|
50
|
+
# @param [String] dst
|
51
|
+
# @return [SwarmClusterCliOpe::ShellCommandExecution]
|
52
|
+
def cp_in(src, dst)
|
53
|
+
base_cmd(["cp", src, "#{name}:#{dst}"])
|
54
|
+
end
|
55
|
+
|
56
|
+
##
|
57
|
+
# Comando per la copia del file dal container
|
58
|
+
# @param [String] src
|
59
|
+
# @param [String] dst
|
60
|
+
# @return [SwarmClusterCliOpe::ShellCommandExecution]
|
61
|
+
def cp_out(src, dst)
|
62
|
+
base_cmd(["cp", "#{name}:#{src}", dst])
|
63
|
+
end
|
64
|
+
|
65
|
+
##
|
66
|
+
# Proxy class per essere simili al container per swarm
|
67
|
+
# @return [TrueClass, FalseClass]
|
68
|
+
# @param [String] src
|
69
|
+
# @param [String] dst
|
70
|
+
def copy_in(src, dst)
|
71
|
+
cp_in(src, dst).execute.success?
|
72
|
+
end
|
73
|
+
|
74
|
+
# @param [String] src
|
75
|
+
# @param [String] dst
|
76
|
+
# @return [TrueClass, FalseClass]
|
77
|
+
def copy_out(src, dst)
|
78
|
+
cp_out(src, dst).execute.success?
|
79
|
+
end
|
80
|
+
|
81
|
+
|
82
|
+
# @param [String] selector
|
83
|
+
# @return [Pod]
|
84
|
+
# @param [nil,String] namespace -> se la sciato vuoto utiliziamo il namespace corrente
|
85
|
+
# @param [String, nil] context -> contesto di kubectl, nel caso utilizziamo il corrente
|
86
|
+
def self.find_by_selector(selector, namespace: nil, context: nil)
|
87
|
+
|
88
|
+
base_cmd = ["kubectl"]
|
89
|
+
base_cmd << "--namespace=#{namespace}" unless namespace.blank?
|
90
|
+
base_cmd << "--context=#{context}" unless context.blank?
|
91
|
+
base_cmd << "get pod"
|
92
|
+
base_cmd << "--selector=#{selector}"
|
93
|
+
base_cmd << "--output=json"
|
94
|
+
|
95
|
+
cmd = ShellCommandExecution.new(base_cmd)
|
96
|
+
ris = cmd.execute(allow_failure: true)
|
97
|
+
if ris.failed?
|
98
|
+
puts "Problemi nella ricerca del pod"
|
99
|
+
exit
|
100
|
+
else
|
101
|
+
if ris.single_obj[:items].empty?
|
102
|
+
puts "non abbiamo trovato il pod"
|
103
|
+
exit
|
104
|
+
else
|
105
|
+
self.new(ris.single_obj[:items].first, context: context)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def self.find_by_name(name, namespace: nil, context: nil)
|
111
|
+
base_cmd = ["kubectl"]
|
112
|
+
base_cmd << "--namespace=#{namespace}" unless namespace.blank?
|
113
|
+
base_cmd << "--context=#{context}" unless context.blank?
|
114
|
+
base_cmd << "get pod #{name}"
|
115
|
+
base_cmd << "--output=json"
|
116
|
+
|
117
|
+
cmd = ShellCommandExecution.new(base_cmd)
|
118
|
+
ris = cmd.execute(allow_failure: true)
|
119
|
+
if ris.failed?
|
120
|
+
puts "Problemi nella ricerca del pod"
|
121
|
+
exit
|
122
|
+
else
|
123
|
+
self.new(ris.single_obj, context: context)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
|
128
|
+
private
|
129
|
+
|
130
|
+
##
|
131
|
+
# Array con i comandi base di kubectl
|
132
|
+
# @return [Array<String>]
|
133
|
+
def base_kubectl_cmd_env(json: false)
|
134
|
+
base_cmd = ["kubectl"]
|
135
|
+
base_cmd << "--namespace=#{namespace}" unless namespace.blank?
|
136
|
+
base_cmd << "--context=#{context}" unless context.blank?
|
137
|
+
base_cmd << "--output=json" if json
|
138
|
+
base_cmd
|
139
|
+
end
|
140
|
+
|
141
|
+
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
module SwarmClusterCliOpe
|
3
|
+
module Kubernetes
|
4
|
+
module SyncConfigs
|
5
|
+
module BaseDecorator
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
included do
|
9
|
+
|
10
|
+
delegate :namespace, :context, to: :@stack_cfgs
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
# @return [SwarmClusterCliOpe::Kubernetes::Pod]
|
15
|
+
def container
|
16
|
+
return @service if @service.is_a? SwarmClusterCliOpe::Kubernetes::Pod
|
17
|
+
@_container ||= Pod.find_by_selector(service, namespace: namespace, context: context)
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
# module ClassMethods
|
23
|
+
|
24
|
+
# end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
module SwarmClusterCliOpe
|
2
|
+
module Kubernetes
|
3
|
+
module SyncConfigs
|
4
|
+
class Rsync < SwarmClusterCliOpe::SyncConfigs::Base
|
5
|
+
|
6
|
+
include BaseDecorator
|
7
|
+
|
8
|
+
# @return [String]
|
9
|
+
def local_folder
|
10
|
+
@configs[:configs][:local]
|
11
|
+
end
|
12
|
+
|
13
|
+
# @return [String]
|
14
|
+
def remote_folder
|
15
|
+
@configs[:configs][:remote]
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
# @return [SwarmClusterCliOpe::ShellCommandResponse]
|
20
|
+
def push
|
21
|
+
execute(direction: :up)
|
22
|
+
end
|
23
|
+
|
24
|
+
# @return [SwarmClusterCliOpe::ShellCommandResponse]
|
25
|
+
def pull
|
26
|
+
execute(direction: :down)
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def execute(direction: :down)
|
33
|
+
|
34
|
+
if container.nil?
|
35
|
+
say "Container non trovato"
|
36
|
+
exit
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
if yes? "Attenzione, i dati locali o remoti verranno sovrascritti/cancellati?[y,yes]"
|
41
|
+
|
42
|
+
podname = container.name
|
43
|
+
|
44
|
+
if namespace.nil?
|
45
|
+
say "Mancata configurazione del namespace tramite argomento o .swarm_cluster_project"
|
46
|
+
exit
|
47
|
+
end
|
48
|
+
|
49
|
+
cmd = container.exec(['bash -c "apt update && apt install -yq rsync psmisc"'])
|
50
|
+
if cmd.failed?
|
51
|
+
puts "Problemi nell'installazione di rsync nel pod"
|
52
|
+
else
|
53
|
+
cmd = container.cp_in(File.expand_path("../../rsync_cfgs/rsyncd.conf", __FILE__), "/tmp/.")
|
54
|
+
copy_1 = cmd.execute.failed?
|
55
|
+
cmd = container.cp_in(File.expand_path("../../rsync_cfgs/rsyncd.secrets", __FILE__), "/tmp/.")
|
56
|
+
copy_2 = cmd.execute.failed?
|
57
|
+
cmd = container.exec(['bash -c "chmod 600 /tmp/rsyncd.secrets && chown root /tmp/*"'])
|
58
|
+
chmod = cmd.failed?
|
59
|
+
if copy_1 or copy_2 or chmod
|
60
|
+
puts "problema nella copia dei file di configurazione nel pod"
|
61
|
+
else
|
62
|
+
|
63
|
+
begin
|
64
|
+
cmd = container.exec('bash -c "rsync --daemon --config=/tmp/rsyncd.conf --verbose --log-file=/tmp/rsync.log"')
|
65
|
+
if cmd.failed?
|
66
|
+
say "Rsync non Inizializzato"
|
67
|
+
else
|
68
|
+
begin
|
69
|
+
local_port = rand(30000..40000)
|
70
|
+
|
71
|
+
p = IO.popen(container.base_cmd("port-forward #{podname} #{local_port}:873").string_command)
|
72
|
+
pid = p.pid
|
73
|
+
say "PID in execuzione port forward:#{pid}"
|
74
|
+
|
75
|
+
begin
|
76
|
+
|
77
|
+
sleep 1
|
78
|
+
|
79
|
+
# lanciamo il comando quindi per far rsync
|
80
|
+
rsync_command = [
|
81
|
+
"rsync -az --no-o --no-g",
|
82
|
+
"--delete",
|
83
|
+
"--password-file=#{ File.expand_path("../../rsync_cfgs/password", __FILE__)}"
|
84
|
+
]
|
85
|
+
|
86
|
+
if direction == :up
|
87
|
+
rsync_command << "#{local_folder}/."
|
88
|
+
rsync_command << "rsync://root@0.0.0.0:#{local_port}/archives#{remote_folder}"
|
89
|
+
else
|
90
|
+
rsync_command << "rsync://root@0.0.0.0:#{local_port}/archives#{remote_folder}/."
|
91
|
+
rsync_command << local_folder
|
92
|
+
end
|
93
|
+
say "Eseguo rsync #{rsync_command.join(" ")}"
|
94
|
+
|
95
|
+
cmd = ShellCommandExecution.new(rsync_command)
|
96
|
+
cmd.execute
|
97
|
+
|
98
|
+
ensure
|
99
|
+
sleep 1
|
100
|
+
say "Stoppo porta forwarded"
|
101
|
+
Process.kill("INT", pid)
|
102
|
+
end
|
103
|
+
ensure
|
104
|
+
say "Tolgo il servizio di rsyn"
|
105
|
+
container.exec('bash -c "killall rsync"')
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
ensure
|
110
|
+
say "Eseguo pulizia configurazioni caricate"
|
111
|
+
container.exec('bash -c "rm -fr /tmp/rsyncd*"')
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
@@ -6,7 +6,7 @@ module SwarmClusterCliOpe
|
|
6
6
|
return LoggerConcern.const_get("LOGGER") if LoggerConcern.const_defined?("LOGGER")
|
7
7
|
logger = Logger.new(STDOUT)
|
8
8
|
LoggerConcern.const_set("LOGGER", logger)
|
9
|
-
logger.level = case
|
9
|
+
logger.level = case BaseConfiguration.instance.logger_level
|
10
10
|
when "0"
|
11
11
|
Logger::ERROR
|
12
12
|
when "1"
|
@@ -1,8 +1,8 @@
|
|
1
1
|
require 'forwardable'
|
2
2
|
|
3
3
|
module SwarmClusterCliOpe
|
4
|
-
##
|
5
|
-
# Identifica una risposta dalla shell
|
4
|
+
##
|
5
|
+
# Identifica una risposta dalla shell
|
6
6
|
class ShellCommandResponse
|
7
7
|
extend Forwardable
|
8
8
|
include LoggerConcern
|
@@ -28,9 +28,22 @@ module SwarmClusterCliOpe
|
|
28
28
|
##
|
29
29
|
# Risultato, essendo sempre composto da una lista di righe in formato json, ritorniamo un array di json
|
30
30
|
# @param [Object] object_class
|
31
|
-
# @return [Array<object_class
|
32
|
-
def result(object_class: OpenStruct)
|
33
|
-
|
31
|
+
# @return [Array<object_class>,Object]
|
32
|
+
def result(object_class: OpenStruct, single: false)
|
33
|
+
#tento prima di estrapolare direttamente da json e sucessivamente come array
|
34
|
+
if single
|
35
|
+
# questo per k8s, dato che abbiamo come risposta un json vero
|
36
|
+
object_class.new(JSON.parse(raw_result[:stdout]))
|
37
|
+
else
|
38
|
+
# questo nel caso siamo in swarm che ci ritorna un array di json
|
39
|
+
raw_result[:stdout].split("\n").collect { |s| object_class.new(JSON.parse(s)) }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# @param [Class<OpenStruct>] object_class
|
44
|
+
# @return [Object]
|
45
|
+
def single_obj(object_class: OpenStruct)
|
46
|
+
result(object_class: object_class, single: true)
|
34
47
|
end
|
35
48
|
|
36
49
|
#
|
@@ -0,0 +1,135 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
|
3
|
+
module SwarmClusterCliOpe
|
4
|
+
module StackSyncConcern
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
|
9
|
+
desc "stacksync [DIRECTION:pull|push]", "Si occupa di scaricare|caricare,utilizzando le configurazioni presenti, i dati dallo stack remoto"
|
10
|
+
long_desc <<-LONGDESC.gsub("\n", "\x5")
|
11
|
+
le configurazioni sono contenute nell'array: sync_configs.
|
12
|
+
ogni configurazione è composta da:
|
13
|
+
{
|
14
|
+
service:""
|
15
|
+
how:""
|
16
|
+
configs:{ }
|
17
|
+
}
|
18
|
+
- service è il nome del servizio (o nel caso di k8s una stringa da utilizzare come selettore labels)
|
19
|
+
- how è il come sincronizzare, definendo la tipologia:
|
20
|
+
---- pg -> DB TODO
|
21
|
+
---- mysql -> DB dump con mysql
|
22
|
+
---- sqlite3 -> DB: viene eseguita una copia del file
|
23
|
+
---- rsync -> RSYNC
|
24
|
+
- configs: è un hash con le configurazioni per ogni tipo di sincronizzazione
|
25
|
+
|
26
|
+
Possibili CFGS per tipologia:
|
27
|
+
rsync:
|
28
|
+
--local: -> path cartella locale
|
29
|
+
--remote: -> path cartella remota (contesto del container)
|
30
|
+
|
31
|
+
sqlite3:
|
32
|
+
--local: -> path al file
|
33
|
+
--remote: -> path al file remoto (contesto del container)
|
34
|
+
|
35
|
+
mysql:
|
36
|
+
--local: -> hash di configurazioni per il DB locale
|
37
|
+
- service: "db" -> nome del servizio nel compose locale, DEFAULT: quello definito sopra
|
38
|
+
- mysql_password_env: "MYSQL_PASSWORD" -> variabile ambiente interna al servizio contenente PASSWORD, DEFAULT: MYSQL_PASSWORD
|
39
|
+
- mysql_password: "root" -> valore in chiaro, in sostituzione della variabile ambiente, DEFAULT: root
|
40
|
+
- mysql_user_env: "MYSQL_USER" -> variabile ambiente interna al servizio contenente USERNAME, DEFAULT: MYSQL_USER
|
41
|
+
- mysql_user: "root" -> valore in chiaro, in sostituzione della variabile ambiente, DEFAULT: root
|
42
|
+
- database_name_env: "MYSQL_DATABASE" -> variabile ambiente interna al servizio contenente NOME DB, DEFAULT: MYSQL_DATABASE
|
43
|
+
- database_name: "nome_db" -> valore in chiaro, in sostituzione della variabile ambiente
|
44
|
+
--remote: -> hash di configurazioni per il DB remoto
|
45
|
+
- service: "db" -> nome del servizio nel compose locale, DEFAULT: quello definito sopra
|
46
|
+
- mysql_password_env: "MYSQL_PASSWORD" -> variabile ambiente interna al servizio contenente PASSWORD, DEFAULT: MYSQL_PASSWORD
|
47
|
+
- mysql_password: "root" -> valore in chiaro, in sostituzione della variabile ambiente, DEFAULT: root
|
48
|
+
- mysql_user_env: "MYSQL_USER" -> variabile ambiente interna al servizio contenente USERNAME, DEFAULT: MYSQL_USER
|
49
|
+
- mysql_user: "root" -> valore in chiaro, in sostituzione della variabile ambiente, DEFAULT: root
|
50
|
+
- database_name_env: "MYSQL_DATABASE" -> variabile ambiente interna al servizio contenente NOME DB, DEFAULT: MYSQL_DATABASE
|
51
|
+
- database_name: "MYSQL_DATABASE" -> valore in chiaro, in sostituzione della variabile ambiente
|
52
|
+
pg:
|
53
|
+
--local: -> hash di configurazioni per il DB locale
|
54
|
+
- service: "db" -> nome del servizio nel compose locale, DEFAULT: quello definito sopra
|
55
|
+
- pg_password_env: "POSTGRES_USER" -> variabile ambiente interna al servizio contenente PASSWORD, DEFAULT: POSTGRES_PASSWORD
|
56
|
+
- pg_password: "" -> valore in chiaro, in sostituzione della variabile ambiente
|
57
|
+
- pg_user_env: "POSTGRES_USER" -> variabile ambiente interna al servizio contenente USERNAME, DEFAULT: POSTGRES_USER
|
58
|
+
- pg_user: "postgres" -> valore in chiaro, in sostituzione della variabile ambiente, DEFAULT: postgres
|
59
|
+
- database_name_env: "POSTGRES_DB" -> variabile ambiente interna al servizio contenente NOME DB, DEFAULT: POSTGRES_DB
|
60
|
+
- database_name: "nome_db" -> valore in chiaro, in sostituzione della variabile ambiente
|
61
|
+
--remote: -> hash di configurazioni per il DB remoto
|
62
|
+
- service: "db" -> nome del servizio nel compose locale, DEFAULT: quello definito sopra
|
63
|
+
- pg_password_env: "POSTGRES_USER" -> variabile ambiente interna al servizio contenente PASSWORD, DEFAULT: POSTGRES_PASSWORD
|
64
|
+
- pg_password: "" -> valore in chiaro, in sostituzione della variabile ambiente
|
65
|
+
- pg_user_env: "POSTGRES_USER" -> variabile ambiente interna al servizio contenente USERNAME, DEFAULT: POSTGRES_USER
|
66
|
+
- pg_user: "postgres" -> valore in chiaro, in sostituzione della variabile ambiente, DEFAULT: postgres
|
67
|
+
- database_name_env: "POSTGRES_DB" -> variabile ambiente interna al servizio contenente NOME DB, DEFAULT: POSTGRES_DB
|
68
|
+
- database_name: "nome_db" -> valore in chiaro, in sostituzione della variabile ambiente
|
69
|
+
|
70
|
+
|
71
|
+
EXAMPLE:
|
72
|
+
Esempio di sincronizzazione di un file sqlite3 e una cartella
|
73
|
+
{
|
74
|
+
"stack_name": "test1",
|
75
|
+
"sync_configs": [
|
76
|
+
{
|
77
|
+
"service": "second",
|
78
|
+
"how": "rsync",
|
79
|
+
"configs": {
|
80
|
+
"remote": "/test_bind",
|
81
|
+
"local": "./uploads"
|
82
|
+
}
|
83
|
+
},
|
84
|
+
{
|
85
|
+
"service": "test_sqlite3",
|
86
|
+
"how": "sqlite3",
|
87
|
+
"configs": {
|
88
|
+
"remote": "/cartella_sqlite3/esempio.sqlite3",
|
89
|
+
"local": "./development.sqlite3"
|
90
|
+
}
|
91
|
+
}
|
92
|
+
]
|
93
|
+
}
|
94
|
+
LONGDESC
|
95
|
+
|
96
|
+
def stacksync(direction)
|
97
|
+
direction = case direction
|
98
|
+
when 'push'
|
99
|
+
:push
|
100
|
+
when 'pull'
|
101
|
+
:pull
|
102
|
+
else
|
103
|
+
raise "ONLY [push|pull] action accepted"
|
104
|
+
end
|
105
|
+
|
106
|
+
if direction == :push
|
107
|
+
unless yes? "ATTENZIONE STAI FACENDO PUSH, proseguire????[y,yes]"
|
108
|
+
exit "OK, CIAO"
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
cfgs.env(options[:environment]) do |cfgs|
|
113
|
+
sync_cfgs = cfgs.sync_configurations
|
114
|
+
if sync_cfgs.empty?
|
115
|
+
say "Attenzione, configurazioni di sincronizzazione vuoto. Leggere la documentazione"
|
116
|
+
else
|
117
|
+
sync_cfgs.each do |sync|
|
118
|
+
say "----------->>>>>>"
|
119
|
+
say "[ #{sync.class.name} ]"
|
120
|
+
sync.send(direction)
|
121
|
+
say "COMPLETE"
|
122
|
+
say "<<<<<<-----------"
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
|
129
|
+
end
|
130
|
+
|
131
|
+
# module ClassMethods
|
132
|
+
|
133
|
+
# end
|
134
|
+
end
|
135
|
+
end
|