naifa 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +67 -52
- data/lib/naifa/cli.rb +17 -35
- data/lib/naifa/config.rb +9 -5
- data/lib/naifa/heroku.rb +0 -2
- data/lib/naifa/plugins/postgres/cli.rb +47 -0
- data/lib/naifa/plugins/postgres/settings.rb +70 -0
- data/lib/naifa/plugins/postgres.rb +240 -0
- data/lib/naifa/plugins/s3/cli.rb +31 -0
- data/lib/naifa/plugins/s3/settings.rb +24 -0
- data/lib/naifa/plugins/s3.rb +51 -0
- data/lib/naifa/plugins.rb +23 -0
- data/lib/naifa/version.rb +1 -1
- data/lib/naifa.rb +1 -1
- metadata +12 -6
- data/lib/naifa/postgres.rb +0 -180
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b7dd8770b81f31bf68ccefd8075c47684e96e673
|
4
|
+
data.tar.gz: 83d07884667956748f511303493df74252d1f69b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 16f3c9bbbde9428b2687903b42652d49ce459999d3b33718787292446c0dd939f7b0fa84988bf164731313b6a43d4c5086e83e3ba28154385ee612b6dcabf363
|
7
|
+
data.tar.gz: 796136b7e1980256f88b147e0b92acd52e09b796a988c35690d8efd059f66a9c5db2085eca5ed6fcd5e2e14197534c94b1cf06ceb701c5379b8c1f0e9c640272
|
data/README.md
CHANGED
@@ -34,79 +34,104 @@ You should now update some of the settings to meet your app configurations.
|
|
34
34
|
|
35
35
|
The .naifa file contains settings that will have an influence in the available command options.
|
36
36
|
|
37
|
-
The current default settings are the following:
|
37
|
+
The current default generated settings are the following:
|
38
38
|
```
|
39
39
|
---
|
40
|
-
version: 1.
|
40
|
+
version: 1.1
|
41
41
|
db:
|
42
42
|
plugin: :postgres
|
43
43
|
settings:
|
44
44
|
filename: db_backup
|
45
|
-
|
46
|
-
|
47
|
-
db_name: ''
|
48
|
-
environment: :staging
|
45
|
+
path: "./data/db_dumps"
|
46
|
+
environments:
|
49
47
|
production:
|
50
48
|
type: :heroku
|
49
|
+
remote: production
|
51
50
|
staging:
|
52
51
|
type: :heroku
|
52
|
+
remote: staging
|
53
53
|
development:
|
54
54
|
type: :docker
|
55
55
|
app_name: db
|
56
56
|
database: ''
|
57
57
|
username: "\\$POSTGRES_USER"
|
58
58
|
path: "/db_dumps/"
|
59
|
+
backup:
|
60
|
+
environment: :staging
|
59
61
|
restore:
|
60
|
-
path: "./data/db_dumps"
|
61
62
|
environment: :development
|
63
|
+
s3:
|
64
|
+
plugin: :s3
|
65
|
+
settings:
|
66
|
+
environments:
|
67
|
+
production:
|
68
|
+
bucket: s3://production_bucket_name/
|
62
69
|
staging:
|
63
|
-
|
70
|
+
bucket: s3://staging_bucket_name/
|
64
71
|
development:
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
72
|
+
bucket: s3://development_bucket_name/
|
73
|
+
sync:
|
74
|
+
origin: :staging
|
75
|
+
destination: :development
|
76
|
+
sync_options:
|
77
|
+
- "--delete"
|
78
|
+
- "--acl public-read"
|
70
79
|
```
|
71
80
|
|
72
81
|
Taking this into account, you'll be able to run the following commands
|
73
82
|
|
74
|
-
### sync
|
83
|
+
### postgres sync
|
75
84
|
|
76
85
|
```
|
77
|
-
$ naifa sync
|
86
|
+
$ naifa db sync
|
78
87
|
```
|
79
88
|
|
80
89
|
This will sync your staging postgres db in heroku to your development postgres in docker
|
81
90
|
|
82
91
|
```
|
83
|
-
$ naifa sync
|
92
|
+
$ naifa db sync production
|
84
93
|
```
|
85
94
|
|
86
95
|
This will sync your production postgres db in heroku to your development postgres in docker
|
87
96
|
|
88
|
-
### backup
|
97
|
+
### postgres backup
|
89
98
|
|
90
99
|
```
|
91
|
-
$ naifa backup
|
100
|
+
$ naifa db backup
|
92
101
|
```
|
93
102
|
|
94
103
|
This will backup your staging postgres db in heroku to './data/db_dumps/db_backup'
|
95
104
|
|
96
105
|
```
|
97
|
-
$ naifa backup
|
106
|
+
$ naifa db backup production
|
98
107
|
```
|
99
108
|
|
100
109
|
This will backup your postgres postgres db in heroku to './data/db_dumps/db_backup'
|
101
110
|
|
102
|
-
### restore
|
111
|
+
### postgres restore
|
103
112
|
|
104
113
|
```
|
105
|
-
$ naifa restore
|
114
|
+
$ naifa db restore
|
106
115
|
```
|
107
116
|
|
108
117
|
This will restore the backup in './data/db_dumps/db_backup' to your development postgres
|
109
118
|
|
119
|
+
### s3 sync
|
120
|
+
|
121
|
+
```
|
122
|
+
$ naifa s3 sync
|
123
|
+
```
|
124
|
+
|
125
|
+
This will sync your staging s3 bucket with your development s3 bucket
|
126
|
+
|
127
|
+
```
|
128
|
+
$ naifa s3 sync production staging
|
129
|
+
```
|
130
|
+
|
131
|
+
This will sync your production s3 bucket with your staging s3 bucket
|
132
|
+
|
133
|
+
NOTE: sync_options allow you to specify [aws s3 sync](http://docs.aws.amazon.com/cli/latest/reference/s3/sync.html) command options.
|
134
|
+
|
110
135
|
## Advanced
|
111
136
|
|
112
137
|
Imagine that you have 2 databases with different settings and configurations
|
@@ -114,78 +139,68 @@ You can update you configuration file by adding another entry like in the exampl
|
|
114
139
|
|
115
140
|
```
|
116
141
|
---
|
117
|
-
version: 1.
|
142
|
+
version: 1.1
|
118
143
|
db:
|
119
144
|
plugin: :postgres
|
120
145
|
settings:
|
121
146
|
filename: db_backup
|
122
|
-
|
123
|
-
|
124
|
-
db_name: ''
|
125
|
-
environment: :staging
|
147
|
+
path: "./data/db_dumps"
|
148
|
+
environments:
|
126
149
|
production:
|
127
150
|
type: :heroku
|
151
|
+
remote: production
|
128
152
|
staging:
|
129
153
|
type: :heroku
|
154
|
+
remote: staging
|
130
155
|
development:
|
131
156
|
type: :docker
|
132
157
|
app_name: db
|
133
|
-
database:
|
158
|
+
database: ''
|
134
159
|
username: "\\$POSTGRES_USER"
|
135
160
|
path: "/db_dumps/"
|
161
|
+
backup:
|
162
|
+
environment: :staging
|
136
163
|
restore:
|
137
|
-
path: "./data/db_dumps"
|
138
164
|
environment: :development
|
139
|
-
staging:
|
140
|
-
type: :heroku
|
141
|
-
development:
|
142
|
-
type: :docker
|
143
|
-
app_name: db
|
144
|
-
database: dev_db
|
145
|
-
username: "\\$POSTGRES_USER"
|
146
|
-
path: "/db_dumps/"
|
147
165
|
db_local:
|
148
166
|
plugin: :postgres
|
149
167
|
settings:
|
150
168
|
filename: db_backup
|
151
|
-
|
152
|
-
|
153
|
-
db_name: ''
|
154
|
-
environment: :staging
|
169
|
+
path: "./data/db_dumps"
|
170
|
+
environments:
|
155
171
|
production:
|
156
172
|
type: :heroku
|
173
|
+
remote: production
|
157
174
|
staging:
|
158
175
|
type: :heroku
|
176
|
+
remote: staging
|
159
177
|
development:
|
160
178
|
type: :local
|
161
179
|
database: dev_db1
|
162
|
-
username:
|
180
|
+
username: "\\$POSTGRES_USER"
|
181
|
+
password: pass
|
182
|
+
path: "/db_dumps/"
|
183
|
+
backup:
|
184
|
+
environment: :staging
|
163
185
|
restore:
|
164
|
-
path: "./data/db_dumps"
|
165
186
|
environment: :development
|
166
|
-
staging:
|
167
|
-
type: :heroku
|
168
|
-
development:
|
169
|
-
type: :local
|
170
|
-
database: dev_db1
|
171
|
-
username: postgres
|
172
187
|
```
|
173
188
|
|
174
189
|
This configuration will allow you to run the commands like this:
|
175
190
|
|
176
191
|
```
|
177
|
-
$ naifa sync
|
178
|
-
$ naifa sync
|
192
|
+
$ naifa db sync
|
193
|
+
$ naifa db_local sync
|
179
194
|
```
|
180
195
|
|
181
196
|
## Roadmap
|
182
197
|
|
183
198
|
* Add tests
|
184
199
|
* Add documentation
|
185
|
-
* Add AWS S3 sync between environments
|
200
|
+
* -Add AWS S3 sync between environments-
|
186
201
|
* Add MySQL sync, backup and restore
|
187
202
|
* Add MongoDB sync, backup and restore
|
188
|
-
* Rethink the commands to more dynamic depending on the plugin
|
203
|
+
* -Rethink the commands to more dynamic depending on the plugin-
|
189
204
|
* Add logs and better error handling
|
190
205
|
|
191
206
|
## Development
|
data/lib/naifa/cli.rb
CHANGED
@@ -1,46 +1,28 @@
|
|
1
1
|
module Naifa
|
2
2
|
require 'thor'
|
3
|
-
class CLI < Thor
|
4
|
-
|
5
|
-
desc "init <filename>", "Initializes <filename=.naifa> config file with all default settings"
|
6
|
-
def init(filename='.naifa')
|
7
|
-
File.write(filename, Naifa::Config.generate_full_default_settings.to_h.to_yaml)
|
8
|
-
end
|
9
|
-
|
10
|
-
desc "sync <what> <from> <to>", "Syncs <what> from <from> to <to>"
|
11
|
-
def sync(what, from=nil, to=nil)
|
12
|
-
what_config = Naifa::Config.settings[what.to_sym] || {}
|
13
3
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
end
|
4
|
+
module PluginsCLI
|
5
|
+
Naifa::Config.settings.each do |sub_comm, settings|
|
6
|
+
class_eval <<-EORUBY
|
7
|
+
class #{sub_comm.to_s.capitalize} < #{Naifa::Plugins::registry[settings[:plugin]][:cli].to_s}
|
8
|
+
@settings_key = :#{sub_comm}
|
9
|
+
end
|
10
|
+
EORUBY
|
22
11
|
end
|
12
|
+
end
|
23
13
|
|
24
|
-
|
25
|
-
def backup(what, from=nil)
|
26
|
-
what_config = Naifa::Config.settings[what.to_sym] || {}
|
27
|
-
options = from.nil? ? {} : {backup: {environment: from}}
|
14
|
+
class CLI < Thor
|
28
15
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
end
|
16
|
+
desc "init <filename>", "Initializes <filename=.naifa> config file with all default settings"
|
17
|
+
def init(filename='.naifa')
|
18
|
+
File.write(filename, Naifa::Config.generate_example_settings.to_h.to_yaml)
|
33
19
|
end
|
34
20
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
case what_config[:plugin]
|
41
|
-
when :postgres
|
42
|
-
Naifa::Postgres.restore(what_config.fetch(:settings,{}).deep_merge(options))
|
43
|
-
end
|
21
|
+
Naifa::Config.settings.each do |sub_comm, settings|
|
22
|
+
class_eval <<-EORUBY
|
23
|
+
desc "#{sub_comm} SUBCOMMAND ...ARGS", "#{Naifa::Plugins::registry[settings[:plugin]][:description].to_s}"
|
24
|
+
subcommand "#{sub_comm}", PluginsCLI::#{sub_comm.to_s.capitalize}
|
25
|
+
EORUBY
|
44
26
|
end
|
45
27
|
end
|
46
28
|
end
|
data/lib/naifa/config.rb
CHANGED
@@ -3,27 +3,31 @@ module Naifa
|
|
3
3
|
require 'yaml'
|
4
4
|
require 'active_support/core_ext/hash/indifferent_access'
|
5
5
|
|
6
|
-
SETTINGS_VERSION = 1.
|
6
|
+
SETTINGS_VERSION = 1.1
|
7
7
|
DEFAULT_SETTINGS = {
|
8
8
|
db: {
|
9
9
|
:plugin => :postgres
|
10
|
+
},
|
11
|
+
s3: {
|
12
|
+
:plugin => :s3
|
10
13
|
}
|
11
14
|
}.with_indifferent_access.freeze
|
12
15
|
|
13
16
|
def self.settings
|
14
17
|
@settings ||= begin
|
15
18
|
loaded_settings = YAML.load(File.read('.naifa')).with_indifferent_access if File.exists?('.naifa')
|
16
|
-
if !loaded_settings.nil? && loaded_settings
|
19
|
+
if !loaded_settings.nil? && loaded_settings.delete(:version) != SETTINGS_VERSION
|
17
20
|
raise 'Configuration file version is not supported. Please upgrade!'
|
18
21
|
end
|
19
22
|
loaded_settings
|
20
|
-
end ||
|
23
|
+
end || {}
|
21
24
|
end
|
22
25
|
|
23
|
-
def self.
|
26
|
+
def self.generate_example_settings
|
24
27
|
full_settings = {'version' => SETTINGS_VERSION}.with_indifferent_access
|
25
28
|
.merge(DEFAULT_SETTINGS)
|
26
|
-
full_settings[:db][:settings] = Naifa::Postgres::DEFAULT_SETTINGS
|
29
|
+
full_settings[:db][:settings] = Naifa::Plugins::Postgres::DEFAULT_SETTINGS
|
30
|
+
full_settings[:s3][:settings] = Naifa::Plugins::S3::DEFAULT_SETTINGS
|
27
31
|
full_settings.to_hash
|
28
32
|
end
|
29
33
|
|
data/lib/naifa/heroku.rb
CHANGED
@@ -9,9 +9,7 @@ module Naifa
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def self.sync(from=:production, to=:staging)
|
12
|
-
puts "Heroku Sync from: #{from} to: #{to}"
|
13
12
|
res = capture(from)
|
14
|
-
# puts build_restore_command("`#{build_public_url_command(from)}`", to)
|
15
13
|
Kernel.system(build_restore_command("`#{build_public_url_command(from)}`", to)) if res
|
16
14
|
end
|
17
15
|
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Naifa
|
2
|
+
module Plugins
|
3
|
+
class Postgres
|
4
|
+
require 'thor'
|
5
|
+
|
6
|
+
class CLI < Thor
|
7
|
+
@settings_key = nil
|
8
|
+
class << self
|
9
|
+
attr_reader :settings_key
|
10
|
+
end
|
11
|
+
|
12
|
+
desc "sync <from> <to>", "Syncs from <from> to <to>"
|
13
|
+
def sync(from=nil, to=nil)
|
14
|
+
config = Naifa::Config.settings[settings_key] || {}
|
15
|
+
|
16
|
+
options = {backup: {}, restore: {}}
|
17
|
+
options[:backup][:environment] = from unless from.nil?
|
18
|
+
options[:restore][:environment] = to unless to.nil?
|
19
|
+
|
20
|
+
Postgres.sync(config.fetch(:settings,{}).deep_merge(options))
|
21
|
+
end
|
22
|
+
|
23
|
+
desc "backup <from>", "Backup from <from>"
|
24
|
+
def backup(from=nil)
|
25
|
+
config = Naifa::Config.settings[settings_key] || {}
|
26
|
+
options = from.nil? ? {} : {backup: {environment: from}}
|
27
|
+
|
28
|
+
Postgres.backup(config.fetch(:settings,{}).deep_merge(options))
|
29
|
+
end
|
30
|
+
|
31
|
+
desc "restore <to>", "Restore to <to>"
|
32
|
+
def restore(to=nil)
|
33
|
+
config = Naifa::Config.settings[settings_key] || {}
|
34
|
+
options = to.nil? ? {} : {restore: {environment: to}}
|
35
|
+
|
36
|
+
Postgres.restore(config.fetch(:settings,{}).deep_merge(options))
|
37
|
+
end
|
38
|
+
|
39
|
+
no_commands do
|
40
|
+
def settings_key
|
41
|
+
self.class.settings_key
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module Naifa
|
2
|
+
module Plugins
|
3
|
+
class Postgres
|
4
|
+
DEFAULT_FILENAME = 'db_backup'.freeze
|
5
|
+
DEFAULT_SETTINGS = {
|
6
|
+
filename: DEFAULT_FILENAME,
|
7
|
+
path: './data/db_dumps',
|
8
|
+
environments: {
|
9
|
+
production: {
|
10
|
+
type: :heroku,
|
11
|
+
remote: 'production'
|
12
|
+
},
|
13
|
+
staging: {
|
14
|
+
type: :heroku,
|
15
|
+
remote: 'staging'
|
16
|
+
},
|
17
|
+
development: {
|
18
|
+
type: :docker,
|
19
|
+
app_name: 'db',
|
20
|
+
database: '',
|
21
|
+
username: '\$POSTGRES_USER',
|
22
|
+
path: '/db_dumps/'
|
23
|
+
}
|
24
|
+
},
|
25
|
+
backup: {
|
26
|
+
environment: :staging
|
27
|
+
},
|
28
|
+
restore: {
|
29
|
+
environment: :development
|
30
|
+
}
|
31
|
+
}.with_indifferent_access.freeze
|
32
|
+
|
33
|
+
# DEFAULT_SETTINGS = {
|
34
|
+
# filename: DEFAULT_FILENAME,
|
35
|
+
# backup: {
|
36
|
+
# path: './data/db_dumps',
|
37
|
+
# db_name: '',
|
38
|
+
# environment: :staging,
|
39
|
+
# production: {
|
40
|
+
# type: :heroku
|
41
|
+
# },
|
42
|
+
# staging: {
|
43
|
+
# type: :heroku
|
44
|
+
# },
|
45
|
+
# development: {
|
46
|
+
# type: :docker,
|
47
|
+
# app_name: 'db',
|
48
|
+
# database: '',
|
49
|
+
# username: '\$POSTGRES_USER',
|
50
|
+
# path: '/db_dumps/'
|
51
|
+
# }
|
52
|
+
# },
|
53
|
+
# restore: {
|
54
|
+
# path: './data/db_dumps',
|
55
|
+
# environment: :development,
|
56
|
+
# staging: {
|
57
|
+
# type: :heroku
|
58
|
+
# },
|
59
|
+
# development: {
|
60
|
+
# type: :docker,
|
61
|
+
# app_name: 'db',
|
62
|
+
# database: '',
|
63
|
+
# username: '\$POSTGRES_USER',
|
64
|
+
# path: '/db_dumps/'
|
65
|
+
# }
|
66
|
+
# }
|
67
|
+
# }.with_indifferent_access.freeze
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,240 @@
|
|
1
|
+
module Naifa
|
2
|
+
|
3
|
+
module Plugins
|
4
|
+
class Postgres
|
5
|
+
require 'naifa/plugins/postgres/cli'
|
6
|
+
require 'naifa/plugins/postgres/settings'
|
7
|
+
require 'active_support'
|
8
|
+
require 'active_support/core_ext/hash/deep_merge'
|
9
|
+
require 'active_support/core_ext/object/blank'
|
10
|
+
require 'naifa/utils'
|
11
|
+
|
12
|
+
def self.restore(options={})
|
13
|
+
filename = options.fetch(:filename, DEFAULT_FILENAME)
|
14
|
+
|
15
|
+
_restore(filename, options)
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.backup(options={})
|
19
|
+
filename = options.fetch(:filename, DEFAULT_FILENAME)
|
20
|
+
|
21
|
+
_backup(filename, options)
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.sync(options={})
|
25
|
+
options ||= {}
|
26
|
+
filename = options.fetch(:filename, DEFAULT_FILENAME)
|
27
|
+
|
28
|
+
backup_settings = options.fetch(:backup, {})
|
29
|
+
restore_settings = options.fetch(:restore, {})
|
30
|
+
environments_settings = options.fetch(:environments, {})
|
31
|
+
|
32
|
+
if backup_settings[:environment].blank? ||
|
33
|
+
environments_settings[backup_settings[:environment]].blank? ||
|
34
|
+
restore_settings[:environment].blank? ||
|
35
|
+
environments_settings[restore_settings[:environment]].blank?
|
36
|
+
|
37
|
+
raise Thor::Error, "Sync (Backup and Restore) environments are not defined"
|
38
|
+
end
|
39
|
+
|
40
|
+
if environments_settings[backup_settings[:environment]][:type] == :heroku &&
|
41
|
+
environments_settings[restore_settings[:environment]][:type] == :heroku
|
42
|
+
|
43
|
+
Heroku::Postgres.sync(
|
44
|
+
environments_settings[backup_settings[:environment]][:remote].presence || backup_settings[:environment],
|
45
|
+
environments_settings[restore_settings[:environment]][:remote].presence || restore_settings[:environment]
|
46
|
+
)
|
47
|
+
else
|
48
|
+
_backup(filename, options)
|
49
|
+
_restore(filename, options)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def self._backup(filename, options={})
|
54
|
+
options ||= {}
|
55
|
+
backup_settings = options[:backup]
|
56
|
+
environments_settings = options[:environments]
|
57
|
+
|
58
|
+
if backup_settings[:environment].blank? ||
|
59
|
+
environments_settings[backup_settings[:environment]].blank?
|
60
|
+
|
61
|
+
raise Thor::Error, "Backup environment is not defined"
|
62
|
+
end
|
63
|
+
|
64
|
+
environment_settings = environments_settings[backup_settings[:environment]]
|
65
|
+
|
66
|
+
case environment_settings[:type]
|
67
|
+
when :remote
|
68
|
+
if environment_settings[:host].blank? ||
|
69
|
+
environment_settings[:username].blank? ||
|
70
|
+
environment_settings[:database].blank? ||
|
71
|
+
(environment_settings[:path].presence || options[:path].presence).blank?
|
72
|
+
|
73
|
+
raise Thor::Error, "Backup remote environment #{backup_settings[:environment]} is not correctly configured"
|
74
|
+
end
|
75
|
+
|
76
|
+
command_line = build_backup_command(
|
77
|
+
environment_settings[:host],
|
78
|
+
environment_settings[:username],
|
79
|
+
environment_settings[:database],
|
80
|
+
File.join(
|
81
|
+
environment_settings[:path].presence || options[:path].presence,
|
82
|
+
filename
|
83
|
+
)
|
84
|
+
)
|
85
|
+
Kernel.system(command_line)
|
86
|
+
when :local
|
87
|
+
if environment_settings[:username].blank? ||
|
88
|
+
environment_settings[:database].blank? ||
|
89
|
+
(environment_settings[:path].presence || options[:path].presence).blank?
|
90
|
+
|
91
|
+
raise Thor::Error, "Backup local environment #{backup_settings[:environment]} is not correctly configured"
|
92
|
+
end
|
93
|
+
|
94
|
+
command_line = build_backup_command(
|
95
|
+
'localhost',
|
96
|
+
environment_settings[:username],
|
97
|
+
environment_settings[:database],
|
98
|
+
File.join(
|
99
|
+
environment_settings[:path].presence || options[:path].presence,
|
100
|
+
filename
|
101
|
+
)
|
102
|
+
)
|
103
|
+
Kernel.system(command_line)
|
104
|
+
when :heroku
|
105
|
+
if (environment_settings[:path].presence || options[:path].presence).blank?
|
106
|
+
raise Thor::Error, "Backup heroku environment #{backup_settings[:environment]} is not correctly configured"
|
107
|
+
end
|
108
|
+
|
109
|
+
Heroku::Postgres.backup(
|
110
|
+
File.join(
|
111
|
+
environment_settings[:path].presence || options[:path].presence,
|
112
|
+
filename
|
113
|
+
),
|
114
|
+
environment_settings[:remote].presence || backup_settings[:environment]
|
115
|
+
)
|
116
|
+
when :docker
|
117
|
+
if environment_settings[:username].blank? ||
|
118
|
+
environment_settings[:database].blank? ||
|
119
|
+
(environment_settings[:path].presence || options[:path].presence).blank? ||
|
120
|
+
environment_settings[:app_name].blank?
|
121
|
+
|
122
|
+
raise Thor::Error, "Restore docker environment #{backup_settings[:environment]} is not correctly configured"
|
123
|
+
end
|
124
|
+
|
125
|
+
command_line = build_backup_command(
|
126
|
+
'localhost',
|
127
|
+
environment_settings[:username],
|
128
|
+
environment_settings[:database],
|
129
|
+
File.join(
|
130
|
+
environment_settings[:path].presence || options[:path].presence,
|
131
|
+
filename
|
132
|
+
)
|
133
|
+
)
|
134
|
+
Utils.docker_compose_exec_command(
|
135
|
+
environment_settings[:app_name].presence,
|
136
|
+
command_line
|
137
|
+
)
|
138
|
+
else
|
139
|
+
raise Thor::Error, "Backup unsupported type"
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
private_class_method :_backup
|
144
|
+
|
145
|
+
def self._restore(filename, options={})
|
146
|
+
options ||= {}
|
147
|
+
|
148
|
+
restore_settings = options[:restore]
|
149
|
+
environments_settings = options[:environments]
|
150
|
+
|
151
|
+
if restore_settings[:environment].blank? ||
|
152
|
+
environments_settings[restore_settings[:environment]].blank?
|
153
|
+
|
154
|
+
raise Thor::Error, "Restore environment is not defined"
|
155
|
+
end
|
156
|
+
|
157
|
+
environment_settings = environments_settings[restore_settings[:environment]]
|
158
|
+
|
159
|
+
case environment_settings[:type]
|
160
|
+
when :remote
|
161
|
+
if environment_settings[:host].blank? ||
|
162
|
+
environment_settings[:username].blank? ||
|
163
|
+
environment_settings[:database].blank? ||
|
164
|
+
(environment_settings[:path].presence || options[:path].presence).blank?
|
165
|
+
|
166
|
+
raise Thor::Error, "Restore remote environment #{restore_settings[:environment]} is not correctly configured"
|
167
|
+
end
|
168
|
+
|
169
|
+
command_line = build_restore_command(
|
170
|
+
environment_settings[:host],
|
171
|
+
environment_settings[:username],
|
172
|
+
environment_settings[:database],
|
173
|
+
File.join(
|
174
|
+
environment_settings[:path].presence || options[:path].presence,
|
175
|
+
filename
|
176
|
+
)
|
177
|
+
)
|
178
|
+
Kernel.system(command_line)
|
179
|
+
when :local
|
180
|
+
if environment_settings[:username].blank? ||
|
181
|
+
environment_settings[:database].blank? ||
|
182
|
+
(environment_settings[:path].presence || options[:path].presence).blank?
|
183
|
+
|
184
|
+
raise Thor::Error, "Restore local environment #{restore_settings[:environment]} is not correctly configured"
|
185
|
+
end
|
186
|
+
|
187
|
+
command_line = build_restore_command(
|
188
|
+
'localhost',
|
189
|
+
environment_settings[:username],
|
190
|
+
environment_settings[:database],
|
191
|
+
File.join(
|
192
|
+
environment_settings[:path] || options[:path],
|
193
|
+
filename
|
194
|
+
)
|
195
|
+
)
|
196
|
+
Kernel.system(command_line)
|
197
|
+
when :docker
|
198
|
+
if environment_settings[:username].blank? ||
|
199
|
+
environment_settings[:database].blank? ||
|
200
|
+
(environment_settings[:path].presence || options[:path].presence).blank? ||
|
201
|
+
environment_settings[:app_name].blank?
|
202
|
+
|
203
|
+
raise Thor::Error, "Restore docker environment #{restore_settings[:environment]} is not correctly configured"
|
204
|
+
end
|
205
|
+
|
206
|
+
command_line = build_restore_command(
|
207
|
+
'localhost',
|
208
|
+
environment_settings[:username],
|
209
|
+
environment_settings[:database],
|
210
|
+
File.join(
|
211
|
+
environment_settings[:path].presence || options[:path].presence,
|
212
|
+
filename
|
213
|
+
)
|
214
|
+
)
|
215
|
+
Utils.docker_compose_exec_command(
|
216
|
+
environment_settings[:app_name],
|
217
|
+
command_line
|
218
|
+
)
|
219
|
+
else
|
220
|
+
raise Thor::Error, "Restore unsupported type"
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
private_class_method :_restore
|
225
|
+
|
226
|
+
def self.build_restore_command(host, username, database, filename)
|
227
|
+
"pg_restore --verbose --clean --no-acl --no-owner -h #{host} -U #{username} -d #{database} #{filename}"
|
228
|
+
end
|
229
|
+
|
230
|
+
private_class_method :build_restore_command
|
231
|
+
|
232
|
+
def self.build_backup_command(host, username, database, filename)
|
233
|
+
"pg_dump -Fc -h #{host} -U #{username} -d #{database} > #{filename}"
|
234
|
+
end
|
235
|
+
|
236
|
+
private_class_method :build_backup_command
|
237
|
+
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Naifa
|
2
|
+
module Plugins
|
3
|
+
class S3
|
4
|
+
require 'thor'
|
5
|
+
|
6
|
+
class CLI < Thor
|
7
|
+
@settings_key = nil
|
8
|
+
class << self
|
9
|
+
attr_reader :settings_key
|
10
|
+
end
|
11
|
+
|
12
|
+
desc "sync <from> <to>", "Syncs from <from> to <to>"
|
13
|
+
def sync(from=nil, to=nil)
|
14
|
+
config = Naifa::Config.settings[settings_key] || {}
|
15
|
+
|
16
|
+
options = {sync: {}}
|
17
|
+
options[:sync][:origin] = from unless from.nil?
|
18
|
+
options[:sync][:destination] = to unless to.nil?
|
19
|
+
|
20
|
+
S3.sync(config.fetch(:settings,{}).deep_merge(options))
|
21
|
+
end
|
22
|
+
|
23
|
+
no_commands do
|
24
|
+
def settings_key
|
25
|
+
self.class.settings_key
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Naifa
|
2
|
+
module Plugins
|
3
|
+
class S3
|
4
|
+
DEFAULT_SETTINGS = {
|
5
|
+
environments: {
|
6
|
+
production: {
|
7
|
+
bucket: 's3://production_bucket_name/'
|
8
|
+
},
|
9
|
+
staging: {
|
10
|
+
bucket: 's3://staging_bucket_name/'
|
11
|
+
},
|
12
|
+
development: {
|
13
|
+
bucket: 's3://development_bucket_name/'
|
14
|
+
}
|
15
|
+
},
|
16
|
+
sync: {
|
17
|
+
origin: :staging,
|
18
|
+
destination: :development,
|
19
|
+
sync_options: ['--delete', '--acl public-read']
|
20
|
+
}
|
21
|
+
}.with_indifferent_access.freeze
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Naifa
|
2
|
+
|
3
|
+
module Plugins
|
4
|
+
class S3
|
5
|
+
require 'naifa/plugins/s3/cli'
|
6
|
+
require 'naifa/plugins/s3/settings'
|
7
|
+
require 'active_support'
|
8
|
+
require 'active_support/core_ext/hash/deep_merge'
|
9
|
+
require 'active_support/core_ext/object/blank'
|
10
|
+
require 'naifa/utils'
|
11
|
+
|
12
|
+
def self.sync(options={})
|
13
|
+
options ||= {}
|
14
|
+
|
15
|
+
sync_settings = options[:sync]
|
16
|
+
environments_settings = options[:environments]
|
17
|
+
|
18
|
+
if sync_settings.blank? ||
|
19
|
+
sync_settings[:origin].blank? ||
|
20
|
+
sync_settings[:destination].blank?
|
21
|
+
|
22
|
+
raise Thor::Error, "Sync settings are not defined"
|
23
|
+
end
|
24
|
+
|
25
|
+
origin = sync_settings[:origin]
|
26
|
+
destination = sync_settings[:destination]
|
27
|
+
|
28
|
+
if environments_settings.blank? ||
|
29
|
+
environments_settings[origin].blank? || environments_settings[origin][:bucket].blank? ||
|
30
|
+
environments_settings[destination].blank? || environments_settings[destination][:bucket].blank?
|
31
|
+
|
32
|
+
raise Thor::Error, "Sync environments not set"
|
33
|
+
end
|
34
|
+
|
35
|
+
command = build_sync_command(
|
36
|
+
environments_settings[origin][:bucket],
|
37
|
+
environments_settings[destination][:bucket],
|
38
|
+
sync_settings.fetch(:sync_options, [])
|
39
|
+
)
|
40
|
+
|
41
|
+
Kernel.system(command)
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.build_sync_command(from_bucket, to_bucket, sync_options=[])
|
45
|
+
command = "aws s3 sync #{from_bucket} #{to_bucket}"
|
46
|
+
command << " #{sync_options.join(' ')}" if sync_options.present?
|
47
|
+
command
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Naifa
|
2
|
+
require 'naifa/plugins/postgres'
|
3
|
+
require 'naifa/plugins/s3'
|
4
|
+
|
5
|
+
module Plugins
|
6
|
+
REGISTRY = {
|
7
|
+
postgres: {
|
8
|
+
cli: Naifa::Plugins::Postgres::CLI,
|
9
|
+
description: 'Sync, backup and restore postgres dbs'
|
10
|
+
},
|
11
|
+
s3: {
|
12
|
+
cli: Naifa::Plugins::S3::CLI,
|
13
|
+
description: 'Syncs s3 buckets'
|
14
|
+
}
|
15
|
+
}.with_indifferent_access.freeze
|
16
|
+
|
17
|
+
def registry
|
18
|
+
REGISTRY
|
19
|
+
end
|
20
|
+
|
21
|
+
module_function :registry
|
22
|
+
end
|
23
|
+
end
|
data/lib/naifa/version.rb
CHANGED
data/lib/naifa.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: naifa
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Filipe Dias
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-03-
|
11
|
+
date: 2017-03-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -94,8 +94,8 @@ dependencies:
|
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0.19'
|
97
|
-
description:
|
98
|
-
|
97
|
+
description: " Naifa is a tool aimed at providing a collection of commands that
|
98
|
+
simplify the development workflow.\n"
|
99
99
|
email:
|
100
100
|
- f.dias@runtime-revolution.com
|
101
101
|
executables:
|
@@ -118,7 +118,13 @@ files:
|
|
118
118
|
- lib/naifa/cli.rb
|
119
119
|
- lib/naifa/config.rb
|
120
120
|
- lib/naifa/heroku.rb
|
121
|
-
- lib/naifa/
|
121
|
+
- lib/naifa/plugins.rb
|
122
|
+
- lib/naifa/plugins/postgres.rb
|
123
|
+
- lib/naifa/plugins/postgres/cli.rb
|
124
|
+
- lib/naifa/plugins/postgres/settings.rb
|
125
|
+
- lib/naifa/plugins/s3.rb
|
126
|
+
- lib/naifa/plugins/s3/cli.rb
|
127
|
+
- lib/naifa/plugins/s3/settings.rb
|
122
128
|
- lib/naifa/utils.rb
|
123
129
|
- lib/naifa/version.rb
|
124
130
|
- naifa.gemspec
|
@@ -142,7 +148,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
142
148
|
version: '0'
|
143
149
|
requirements: []
|
144
150
|
rubyforge_project:
|
145
|
-
rubygems_version: 2.
|
151
|
+
rubygems_version: 2.5.1
|
146
152
|
signing_key:
|
147
153
|
specification_version: 4
|
148
154
|
summary: Naifa is a tool aimed at providing a collection of commands that simplify
|
data/lib/naifa/postgres.rb
DELETED
@@ -1,180 +0,0 @@
|
|
1
|
-
module Naifa
|
2
|
-
require 'naifa/utils'
|
3
|
-
|
4
|
-
class Postgres
|
5
|
-
require 'active_support/core_ext/hash/deep_merge'
|
6
|
-
|
7
|
-
DEFAULT_SETTINGS = {
|
8
|
-
filename: 'db_backup',
|
9
|
-
backup: {
|
10
|
-
path: './data/db_dumps',
|
11
|
-
db_name: '',
|
12
|
-
environment: :staging,
|
13
|
-
production: {
|
14
|
-
type: :heroku
|
15
|
-
},
|
16
|
-
staging: {
|
17
|
-
type: :heroku
|
18
|
-
},
|
19
|
-
development: {
|
20
|
-
type: :docker,
|
21
|
-
app_name: 'db',
|
22
|
-
database: '',
|
23
|
-
username: '\$POSTGRES_USER',
|
24
|
-
path: '/db_dumps/'
|
25
|
-
}
|
26
|
-
},
|
27
|
-
restore: {
|
28
|
-
path: './data/db_dumps',
|
29
|
-
environment: :development,
|
30
|
-
staging: {
|
31
|
-
type: :heroku
|
32
|
-
},
|
33
|
-
development: {
|
34
|
-
type: :docker,
|
35
|
-
app_name: 'db',
|
36
|
-
database: '',
|
37
|
-
username: '\$POSTGRES_USER',
|
38
|
-
path: '/db_dumps/'
|
39
|
-
}
|
40
|
-
}
|
41
|
-
}.with_indifferent_access.freeze
|
42
|
-
|
43
|
-
def self.restore(options={})
|
44
|
-
filename = options.fetch(:filename, DEFAULT_SETTINGS[:filename])
|
45
|
-
restore_settings = DEFAULT_SETTINGS[:restore].deep_merge(options.fetch(:restore, {}))
|
46
|
-
|
47
|
-
_restore(filename, restore_settings)
|
48
|
-
end
|
49
|
-
|
50
|
-
def self.backup(options={})
|
51
|
-
filename = options.fetch(:filename, DEFAULT_SETTINGS[:filename])
|
52
|
-
backup_settings = DEFAULT_SETTINGS[:backup].deep_merge(options.fetch(:backup, {}))
|
53
|
-
|
54
|
-
_backup(filename, backup_settings)
|
55
|
-
end
|
56
|
-
|
57
|
-
def self.sync(options={})
|
58
|
-
filename = options.fetch(:filename, DEFAULT_SETTINGS[:filename])
|
59
|
-
|
60
|
-
backup_settings = DEFAULT_SETTINGS[:backup].deep_merge(options.fetch(:backup, {}))
|
61
|
-
restore_settings = DEFAULT_SETTINGS[:restore].deep_merge(options.fetch(:restore, {}))
|
62
|
-
|
63
|
-
return false if backup_settings[:environment].nil? ||
|
64
|
-
backup_settings[backup_settings[:environment]].nil? ||
|
65
|
-
restore_settings[:environment].nil? ||
|
66
|
-
restore_settings[restore_settings[:environment]].nil?
|
67
|
-
|
68
|
-
if backup_settings[backup_settings[:environment]][:type] == :heroku &&
|
69
|
-
restore_settings[restore_settings[:environment]][:type] == :heroku
|
70
|
-
|
71
|
-
Heroku::Postgres.sync(
|
72
|
-
backup_settings[:environment],
|
73
|
-
restore_settings[:environment]
|
74
|
-
)
|
75
|
-
else
|
76
|
-
res = _backup(filename, backup_settings)
|
77
|
-
_restore(filename, restore_settings) if res
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
def self._backup(filename, options)
|
82
|
-
environment = options[:environment]
|
83
|
-
return false if environment.nil? || options[environment].nil?
|
84
|
-
|
85
|
-
case options[environment][:type]
|
86
|
-
when :remote
|
87
|
-
command_line = build_backup_command(
|
88
|
-
options[environment][:host],
|
89
|
-
options[environment][:username] || options[:username],
|
90
|
-
options[environment][:database] || options[:database],
|
91
|
-
File.join(
|
92
|
-
options[environment][:path] || options[:path],
|
93
|
-
filename
|
94
|
-
)
|
95
|
-
)
|
96
|
-
Kernel.system(command_line)
|
97
|
-
when :local
|
98
|
-
command_line = build_backup_command(
|
99
|
-
'localhost',
|
100
|
-
options[environment][:username] || options[:username],
|
101
|
-
options[environment][:database] || options[:database],
|
102
|
-
File.join(
|
103
|
-
options[environment][:path] || options[:path],
|
104
|
-
filename
|
105
|
-
)
|
106
|
-
)
|
107
|
-
Kernel.system(command_line)
|
108
|
-
when :heroku
|
109
|
-
Heroku::Postgres.backup(
|
110
|
-
File.join(
|
111
|
-
options[environment][:path] || options[:path],
|
112
|
-
filename
|
113
|
-
),
|
114
|
-
environment
|
115
|
-
)
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
private_class_method :_backup
|
120
|
-
|
121
|
-
def self._restore(filename, options={})
|
122
|
-
environment = options[:environment]
|
123
|
-
return false if environment.nil? || options[environment].nil?
|
124
|
-
|
125
|
-
case options[environment][:type]
|
126
|
-
when :remote
|
127
|
-
command_line = build_restore_command(
|
128
|
-
options[environment][:host],
|
129
|
-
options[environment][:username] || options[:username],
|
130
|
-
options[environment][:database] || options[:database],
|
131
|
-
File.join(
|
132
|
-
options[environment][:path] || options[:path],
|
133
|
-
filename
|
134
|
-
)
|
135
|
-
)
|
136
|
-
Kernel.system(command_line)
|
137
|
-
when :local
|
138
|
-
command_line = build_restore_command(
|
139
|
-
'localhost',
|
140
|
-
options[environment][:username] || options[:username],
|
141
|
-
options[environment][:database] || options[:database],
|
142
|
-
File.join(
|
143
|
-
options[environment][:path] || options[:path],
|
144
|
-
filename
|
145
|
-
)
|
146
|
-
)
|
147
|
-
Kernel.system(command_line)
|
148
|
-
when :docker
|
149
|
-
command_line = build_restore_command(
|
150
|
-
'localhost',
|
151
|
-
options[environment][:username] || options[:username],
|
152
|
-
options[environment][:database] || options[:database],
|
153
|
-
File.join(
|
154
|
-
options[environment][:path] || options[:path],
|
155
|
-
filename
|
156
|
-
)
|
157
|
-
)
|
158
|
-
Utils.docker_compose_exec_command(
|
159
|
-
options[environment][:app_name],
|
160
|
-
command_line
|
161
|
-
)
|
162
|
-
end
|
163
|
-
end
|
164
|
-
|
165
|
-
private_class_method :_restore
|
166
|
-
|
167
|
-
def self.build_restore_command(host, username, database, filename)
|
168
|
-
"pg_restore --verbose --clean --no-acl --no-owner -h #{host} -U #{username} -d #{database} #{filename}"
|
169
|
-
end
|
170
|
-
|
171
|
-
private_class_method :build_restore_command
|
172
|
-
|
173
|
-
def self.build_backup_command(host, username, database, filename)
|
174
|
-
"pg_dump -Fc -h #{host} -U #{username} -d #{database} > #{filename}"
|
175
|
-
end
|
176
|
-
|
177
|
-
private_class_method :build_backup_command
|
178
|
-
|
179
|
-
end
|
180
|
-
end
|