naifa 0.1.0 → 0.1.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/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
|