nightcrawler_swift 0.4.0 → 0.5.0

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.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +4 -1
  4. data/Changelog.md +12 -2
  5. data/Gemfile.lock +11 -1
  6. data/README.md +112 -7
  7. data/bin/nswift +1 -1
  8. data/lib/nightcrawler_swift/cli/commands/url_for.rb +9 -0
  9. data/lib/nightcrawler_swift/cli/formatters/basic.rb +40 -0
  10. data/lib/nightcrawler_swift/cli/opt_parser.rb +81 -0
  11. data/lib/nightcrawler_swift/cli/runner.rb +127 -0
  12. data/lib/nightcrawler_swift/cli.rb +16 -173
  13. data/lib/nightcrawler_swift/command.rb +5 -14
  14. data/lib/nightcrawler_swift/commands/delete.rb +4 -6
  15. data/lib/nightcrawler_swift/commands/download.rb +4 -6
  16. data/lib/nightcrawler_swift/commands/list.rb +0 -6
  17. data/lib/nightcrawler_swift/commands/upload.rb +1 -4
  18. data/lib/nightcrawler_swift/connection.rb +15 -15
  19. data/lib/nightcrawler_swift/exceptions.rb +2 -1
  20. data/lib/nightcrawler_swift/gateway.rb +68 -0
  21. data/lib/nightcrawler_swift/version.rb +1 -1
  22. data/lib/nightcrawler_swift.rb +7 -2
  23. data/nightcrawler_swift.gemspec +1 -0
  24. data/spec/lib/nightcrawler_swift/cli/commands/url_for_spec.rb +34 -0
  25. data/spec/lib/nightcrawler_swift/cli/formatters/basic_spec.rb +117 -0
  26. data/spec/lib/nightcrawler_swift/cli/opt_parser_spec.rb +135 -0
  27. data/spec/lib/nightcrawler_swift/{cli_spec.rb → cli/runner_spec.rb} +133 -136
  28. data/spec/lib/nightcrawler_swift/command_spec.rb +17 -32
  29. data/spec/lib/nightcrawler_swift/commands/delete_spec.rb +8 -29
  30. data/spec/lib/nightcrawler_swift/commands/download_spec.rb +8 -29
  31. data/spec/lib/nightcrawler_swift/commands/list_spec.rb +14 -44
  32. data/spec/lib/nightcrawler_swift/commands/upload_spec.rb +1 -8
  33. data/spec/lib/nightcrawler_swift/connection_spec.rb +26 -9
  34. data/spec/lib/nightcrawler_swift/gateway_spec.rb +139 -0
  35. data/spec/lib/nightcrawler_swift_spec.rb +15 -2
  36. data/spec/spec_helper.rb +3 -0
  37. metadata +31 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 616e1624837906ed1b5381823a1de196ba8b41e7
4
- data.tar.gz: 2e4d0b8eb39afb34e6cda6d5e7725c6938a3a817
3
+ metadata.gz: ce783e76729a865b6b3cd1fffbed84cc287234e9
4
+ data.tar.gz: 922f51e1130d4bb27b84bde8de018793c5b5a1c4
5
5
  SHA512:
6
- metadata.gz: 193eccd937c649b468e4b24cff3728d22a6acd7de8ac824876732bff14fbb145e33dafb222ff6069e350912c849b7c55d5e75a56e25a11357e6a8e9d368ece6c
7
- data.tar.gz: 466c00ebec3b67d64efca29ec820afea48ad74a0e702617dc91e570cf0c8c08bfca7a0808b2d8c8d01d3c09d398c64d7df7e7766312e1c35826fa500dd1af264
6
+ metadata.gz: ba0dc5e45b62d8011f321aba5c0e28487d5b496cde054a2197db3db5baeb2c9936a542ef5ef02ad9b3d324261b8677b6520140df048045ed4f579fd5bdb8db8e
7
+ data.tar.gz: a55710e1eddf95712cb5c3821b1853854b815ecf066ee6bf22c7b259e66f1dd7ad65f1f10405e4b8fe88b0b7c3482dbea3e05faaf9a1343fc1c7425af4152da1
data/.gitignore CHANGED
@@ -1,2 +1,3 @@
1
1
  .DS_Store
2
2
  pkg
3
+ coverage
data/.travis.yml CHANGED
@@ -1,4 +1,7 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.1.2
3
+ - 2.1.2
4
4
  script: bundle exec rspec
5
+ env:
6
+ global:
7
+ secure: C1/OCk7bQxlGogDpgYf0vp6e5P/+TsFvO3bnJdfUoMlO3FAZafqq+xarWNZ/caaNEkYUQ2OaQmLYKZ32yVUAPoE1mUou9vijkOIi+m/JHr1sfeJykNYZYVqi7JQ/PILw2Qs80bZ3I0AS7hWCRIADeQUPuWul06uxYEUV1SB6mQI=
data/Changelog.md CHANGED
@@ -1,11 +1,21 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.5.0
4
+
5
+ - CLI now supports ```-b/--bucket``` to override the default bucket/container (issue #10)
6
+ - CLI command for printing the public url of a given path (issue #18)
7
+ - CLI better treatment for errors and invalid commands
8
+ - Bugfix: CLI when receives a invalid command doesn't shows that it is an invalid command (issue #20)
9
+ - Configurable ```admin_url``` and ```public_url``` (issue #14)
10
+ - Included "public" directive in ```Cache-Control``` header
11
+ - Each request will retry X times before failing, the number of retries and the max waiting time can be configured through options
12
+
3
13
  ## 0.4.0
4
14
 
5
15
  - Better catalog selection
6
16
  - Treatment for no catalogs returned
7
- - Splited asset_sync task in two other tasks: sync and asset_sync
8
- - Configurable verify_ssl and timeout
17
+ - Splited asset_sync task in two other tasks: ```sync``` and ```asset_sync```
18
+ - Configurable ```verify_ssl``` and ```timeout```
9
19
  - Automatic connect/reconnect of commands
10
20
  - Bugfix: download command was not using the bucket/container name
11
21
  - Bugfix: the etag header must not be quoted
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- nightcrawler_swift (0.4.0)
4
+ nightcrawler_swift (0.5.0)
5
5
  multi_mime (>= 1.0.1)
6
6
  rest-client
7
7
 
@@ -11,10 +11,14 @@ GEM
11
11
  byebug (3.2.0)
12
12
  columnize (~> 0.8)
13
13
  debugger-linecache (~> 1.2)
14
+ codeclimate-test-reporter (0.4.0)
15
+ simplecov (>= 0.7.1, < 1.0.0)
14
16
  columnize (0.8.9)
15
17
  debugger-linecache (1.2.0)
16
18
  diff-lcs (1.2.5)
19
+ docile (1.1.5)
17
20
  mime-types (2.3)
21
+ multi_json (1.10.1)
18
22
  multi_mime (1.0.1)
19
23
  netrc (0.7.7)
20
24
  rake (10.3.2)
@@ -33,6 +37,11 @@ GEM
33
37
  rspec-mocks (3.0.4)
34
38
  rspec-support (~> 3.0.0)
35
39
  rspec-support (3.0.4)
40
+ simplecov (0.9.0)
41
+ docile (~> 1.1.0)
42
+ multi_json
43
+ simplecov-html (~> 0.8.0)
44
+ simplecov-html (0.8.0)
36
45
 
37
46
  PLATFORMS
38
47
  ruby
@@ -40,6 +49,7 @@ PLATFORMS
40
49
  DEPENDENCIES
41
50
  bundler (~> 1.6)
42
51
  byebug
52
+ codeclimate-test-reporter
43
53
  nightcrawler_swift!
44
54
  rake
45
55
  rspec
data/README.md CHANGED
@@ -6,18 +6,28 @@ Like the X-Men nightcrawler this gem teleports your assets to a OpenStack Swift
6
6
 
7
7
  Add this line to your application's Gemfile:
8
8
 
9
- gem 'nightcrawler_swift'
9
+ ```ruby
10
+ gem 'nightcrawler_swift'
11
+ ```
10
12
 
11
13
  And then execute:
12
14
 
13
- $ bundle
15
+ ```sh
16
+ $ bundle
17
+ ```
14
18
 
15
19
  Or install it yourself as:
16
20
 
17
- $ gem install nightcrawler_swift
21
+ ```sh
22
+ $ gem install nightcrawler_swift
23
+ ```
18
24
 
19
25
  ## Usage
20
26
 
27
+ * [With Rails](https://github.com/tulios/nightcrawler_swift#with-rails)
28
+ * [Programatically](https://github.com/tulios/nightcrawler_swift#programatically)
29
+ * [Command Line](https://github.com/tulios/nightcrawler_swift#command-line)
30
+
21
31
  ### With Rails
22
32
  #### 1) Configure your swift credentials and options
23
33
 
@@ -37,20 +47,36 @@ __Optional configurations:__
37
47
  config.nightcrawler_swift.max_age = 3600 # default: nil
38
48
  config.nightcrawler_swift.verify_ssl = true # default: false
39
49
  config.nightcrawler_swift.timeout = 10 # in seconds, default: nil
50
+ config.nightcrawler_swift.admin_url = "https://api.host.com/v1/AUTH_1234" # default: uses the admin_url returned by authentication
51
+ config.nightcrawler_swift.public_url = "http://asset.host.com/v1/AUTH_1234" # default: uses the public_url returned by authentication
52
+ config.nightcrawler_swift.retries = 3 # default: 5, to disable set it to false
53
+ config.nightcrawler_swift.max_retry_time = 64 # in seconds, default: 30
40
54
  ```
41
55
 
42
- _max_age_ will be used to define *Cache-Control:max-age=<value>* header.
43
-
44
56
  By default it will use ```Rails.logger``` as logger, to change that use a different logger in configurations, like:
45
57
 
46
58
  ```ruby
47
59
  config.nightcrawler_swift.logger = Logger.new(STDOUT)
48
60
  ```
49
61
 
62
+ ##### further explanation of configurations
63
+
64
+ > max_age
65
+
66
+ It will be used to define *Cache-Control:max-age=<value>* header.
67
+
68
+ > retries
69
+
70
+ The number of times to retry the request before failing. To disable this feature set it to __false__.
71
+
72
+ > max_retry_time
73
+
74
+ Maximum delay in seconds between each retry. The delay will start with 1s and will double for each retry until this value.
75
+
50
76
  #### 2) Profit!
51
77
 
52
78
  ```sh
53
- rake nightcrawler_swift:rails:asset_sync
79
+ $ rake nightcrawler_swift:rails:asset_sync
54
80
  ```
55
81
 
56
82
  It will invoke ```rake assets:precompile``` and will copy your public directory to swift bucket/container. To sync the public directory without the asset precompilation use the task: ```nightcrawler_swift:rails:sync```
@@ -74,7 +100,11 @@ __Optional configurations:__
74
100
  ```ruby
75
101
  max_age: 3600,
76
102
  verify_ssl: true,
77
- timeout: 10
103
+ timeout: 10, # in seconds
104
+ admin_url: "https://api.host.com/v1/AUTH_1234", # default: uses the admin_url returned by authentication
105
+ public_url: "http://asset.host.com/v1/AUTH_1234", # default: uses the public_url returned by authentication
106
+ retries: 3, # default: 5, to disable set it to false
107
+ max_retry_time: 64 # in seconds, default: 30
78
108
  ```
79
109
 
80
110
  By default it will use ```Logger.new(STDOUT)``` as logger, to change that use:
@@ -89,6 +119,58 @@ NightcrawlerSwift.logger = Logger.new(StringIO.new)
89
119
  NightcrawlerSwift.sync File.expand_path("./my-dir")
90
120
  ```
91
121
 
122
+ ### Command Line
123
+
124
+ The NightcrawlerSwift shell command (CLI) allows you to interact with your buckets/containers easily, it has the same commands of the gem. To see the help, use the cli without arguments or use the _-h_/_--help_ switch.
125
+
126
+ ```sh
127
+ $ nswift # or nswift -h
128
+ ```
129
+
130
+ ```nswift``` will use the configurations stored at the file __.nswiftrc__ located at your home directory. If you try to use any command without the file, it will create a sample configuration for you, but you can create your own.
131
+
132
+ The configuration is a __json__ file, named __.nswiftrc__. You can include any configuration available to the gem (see the other usages example to know each option available). Follow the format:
133
+
134
+ ```json
135
+ {
136
+ "bucket": "<bucket/container name>",
137
+ "tenant_name": "<tenant name>",
138
+ "username": "<username>",
139
+ "password": "<password>",
140
+ "auth_url": "<auth url, ex: https://auth.url.com:123/v2.0/tokens>"
141
+ }
142
+ ```
143
+
144
+ The following commands are available through the cli:
145
+
146
+ ```sh
147
+ $ nswift list
148
+ ```
149
+ ```sh
150
+ $ nswift upload <real_path> <swift_path> # nswift upload robots.txt assets/robots.txt
151
+ ```
152
+ ```sh
153
+ $ nswift download <swift_path> # nswift download assets/robots.txt > my-robots.txt
154
+ ```
155
+ ```sh
156
+ $ nswift delete <swift_path> # nswift delete assets/robots.txt
157
+ ```
158
+ ```sh
159
+ $ nswift url-for <swift_path> # nswift url-for assets/robots.txt
160
+ ```
161
+
162
+ For any commands you could provide a different configuration file through the _-c_/_--config_ switch, as:
163
+
164
+ ```sh
165
+ $ nswift list -c /dir/my-nswift-rc
166
+ ```
167
+
168
+ and a different bucket/container name through the _-b_/_--bucket_ switch, as:
169
+
170
+ ```sh
171
+ $ nwift list -b rogue
172
+ ```
173
+
92
174
  ## Commands
93
175
 
94
176
  NightcrawlerSwift has some useful built-in commands. All commands require the configuration and will __automatically__ connect/reconnect to keystone when necessary.
@@ -129,6 +211,13 @@ delete.execute "my_file_path.txt"
129
211
  # true / false
130
212
  ```
131
213
 
214
+ ### Sync
215
+
216
+ ```ruby
217
+ sync = NightcrawlerSwift::Sync.new
218
+ sync.execute "/dir/to/synchronize"
219
+ ```
220
+
132
221
  ## Connection
133
222
 
134
223
  To manually establish the connection with keystone, use:
@@ -145,6 +234,22 @@ NightcrawlerSwift.connection.connected?
145
234
 
146
235
  To reconnect just use ```NightcrawlerSwift.connection.connect!``` again.
147
236
 
237
+ ## Options
238
+
239
+ After configure the NightcrawlerSwift you can access your configurations through the __options__ method, like:
240
+
241
+ ```ruby
242
+ NightcrawlerSwift.options
243
+ ```
244
+
245
+ The only difference is that you will access each configuration as a method instead of a hash style, like:
246
+
247
+ ```ruby
248
+ NightcrawlerSwift.configure tenant_name: "rogue"
249
+
250
+ # Can be used as:
251
+ NightcrawlerSwift.options.tenant_name # "rogue"
252
+ ```
148
253
 
149
254
  ## Contributing
150
255
 
data/bin/nswift CHANGED
@@ -5,4 +5,4 @@ $LOAD_PATH.unshift File.dirname(__FILE__) + "/../lib"
5
5
  require "nightcrawler_swift"
6
6
  require "nightcrawler_swift/cli"
7
7
 
8
- NightcrawlerSwift::CLI.new(ARGV).run
8
+ NightcrawlerSwift::CLI::Runner.new(ARGV).run
@@ -0,0 +1,9 @@
1
+ module NightcrawlerSwift::CLI
2
+ class UrlFor < NightcrawlerSwift::Command
3
+
4
+ def execute path
5
+ "#{connection.public_url}/#{options.bucket}/#{path}"
6
+ end
7
+
8
+ end
9
+ end
@@ -0,0 +1,40 @@
1
+ module NightcrawlerSwift::CLI
2
+ module Formatters
3
+ class Basic
4
+
5
+ def initialize runner
6
+ @runner = runner
7
+ end
8
+
9
+ def command_list command
10
+ array = command.new.execute
11
+ array.each {|hash| @runner.log hash["name"]}
12
+ end
13
+
14
+ def command_download command
15
+ filepath = @runner.argv.first
16
+ @runner.log command.new.execute(filepath)
17
+ end
18
+
19
+ def command_upload command
20
+ realpath = @runner.argv.shift
21
+ swiftpath = @runner.argv.shift
22
+
23
+ uploaded = command.new.execute swiftpath, File.open(File.expand_path(realpath), "r")
24
+ @runner.log(uploaded ? "success" : "failure")
25
+ end
26
+
27
+ def command_delete command
28
+ filepath = @runner.argv.first
29
+ deleted = command.new.execute(filepath).to_json
30
+ @runner.log(deleted ? "success" : "failure")
31
+ end
32
+
33
+ def command_url_for command
34
+ filepath = @runner.argv.first
35
+ @runner.log command.new.execute(filepath)
36
+ end
37
+
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,81 @@
1
+ module NightcrawlerSwift::CLI
2
+ class OptParser
3
+
4
+ attr_reader :parser
5
+
6
+ def initialize runner
7
+ @runner = runner
8
+ @parser = OptionParser.new
9
+ configure_instructions
10
+ configure_options
11
+ end
12
+
13
+ def parse!
14
+ @parser.parse!(@runner.argv)
15
+ end
16
+
17
+ def help
18
+ @parser.help
19
+ end
20
+
21
+ private
22
+ def configure_instructions
23
+ @parser.banner = "nswift #{NightcrawlerSwift::VERSION}"
24
+ @parser.separator "Usage: nswift command [options]"
25
+ @parser.separator ""
26
+ @parser.separator "commands:"
27
+ COMMANDS.keys.each do |key|
28
+ @parser.separator " #{key}\t\t\t #{COMMANDS[key][:description]}"
29
+ end
30
+
31
+ @parser.separator ""
32
+ end
33
+
34
+ def configure_options
35
+ @parser.separator "options:"
36
+ configure_option_bucket
37
+ configure_option_config
38
+ configure_option_help
39
+ configure_option_version
40
+ end
41
+
42
+ def configure_option_bucket
43
+ desc = "Alternative bucket/container name, overrides the '#{NightcrawlerSwift::CLI::CONFIG_FILE}' configuration"
44
+ @parser.on("-b", "--bucket=NAME", String, desc) do |name|
45
+ bucket = name.strip
46
+ @runner.options.bucket = bucket
47
+ @runner.log "Using bucket: #{@runner.options.bucket}"
48
+ end
49
+ end
50
+
51
+ def configure_option_config
52
+ @parser.on("-c", "--config=PATH", String, "Alternative '#{NightcrawlerSwift::CLI::CONFIG_FILE}' file") do |path|
53
+ path = File.expand_path(path.strip)
54
+
55
+ unless File.exist?(path)
56
+ @runner.log "Error: No such file or directory - #{path}"
57
+ exit 1
58
+ end
59
+
60
+ @runner.log "Using custom config file at: #{path}"
61
+ @runner.options.config_file = path
62
+ @runner.options.default_config_file = false
63
+ end
64
+ end
65
+
66
+ def configure_option_help
67
+ @parser.on_tail("-h", "--help", "Show this message") do
68
+ @runner.log help
69
+ exit
70
+ end
71
+ end
72
+
73
+ def configure_option_version
74
+ @parser.on_tail("-v", "--version", "Show version") do
75
+ @runner.log NightcrawlerSwift::VERSION
76
+ exit
77
+ end
78
+ end
79
+
80
+ end
81
+ end
@@ -0,0 +1,127 @@
1
+ module NightcrawlerSwift::CLI
2
+ class Runner
3
+ attr_reader :opt_parser, :options
4
+ attr_accessor :argv
5
+
6
+ def initialize argv
7
+ @argv = argv
8
+ configure_logger
9
+ end
10
+
11
+ def run
12
+ configure_default_options
13
+ configure_opt_parser
14
+ parse_parameters
15
+ @command_name = argv.shift
16
+ validate_command_and_options
17
+ execute_command if @command_name
18
+ end
19
+
20
+ def log string
21
+ NightcrawlerSwift.logger.info string
22
+ end
23
+
24
+ private
25
+ def configure_logger
26
+ STDOUT.sync = true
27
+ NightcrawlerSwift.logger.formatter = lambda {|severity, datetime, progname, msg| "#{msg}\n"}
28
+ end
29
+
30
+ def configure_default_options
31
+ user_home_dir = Dir.home
32
+ @options = OpenStruct.new
33
+ @options.configured = true
34
+ @options.default_config_file = true
35
+ @options.config_file = File.expand_path(File.join(user_home_dir, CONFIG_FILE))
36
+ @options.cache_file = File.expand_path(File.join(user_home_dir, CACHE_FILE))
37
+ @options.bucket = nil
38
+ end
39
+
40
+ def validate_command_and_options
41
+ if @command_name.nil? or argv.nil?
42
+ log @opt_parser.help
43
+ exit
44
+ end
45
+
46
+ unless COMMANDS.include?(@command_name)
47
+ log "Error: Unknown command '#{@command_name}'"
48
+ exit 1
49
+ end
50
+
51
+ unless options.configured
52
+ log "You must configure your swift credentials, take a look at:\n #{options.config_file}"
53
+ exit 1
54
+ end
55
+ end
56
+
57
+ def config_hash
58
+ @config_hash ||= JSON.parse(File.read(options.config_file))
59
+ end
60
+
61
+ def execute_command
62
+ NightcrawlerSwift.configure config_hash
63
+ NightcrawlerSwift.options.bucket = @options.bucket if @options.bucket
64
+
65
+ connect_and_execute do
66
+ command_method = "command_#{command_name_normalized}"
67
+ command_class = COMMANDS[@command_name][:command]
68
+ Formatters::Basic.new(self).send(command_method, command_class)
69
+ end
70
+
71
+ rescue NightcrawlerSwift::Exceptions::BaseError, Errno::ENOENT => e
72
+ log "Error: #{e.message}"
73
+ exit 1
74
+ end
75
+
76
+ def command_name_normalized
77
+ @command_name.downcase.gsub(/-/, "_")
78
+ end
79
+
80
+ def connect_and_execute &block
81
+ path = options.cache_file
82
+ if File.exist?(path)
83
+ hash = JSON.parse File.read(path)
84
+ NightcrawlerSwift.connection.auth_response = OpenStruct.new(hash)
85
+ NightcrawlerSwift.connection.configure
86
+
87
+ token_id = NightcrawlerSwift.connection.token_id
88
+ NightcrawlerSwift.logger.debug "Cache found, restablishing connection with token_id: #{token_id}"
89
+ end
90
+
91
+ begin
92
+ block.call
93
+ ensure
94
+ File.open(path, "w") do |f|
95
+ f.write(NightcrawlerSwift.connection.auth_response.to_h.to_json)
96
+ end
97
+ end
98
+ end
99
+
100
+ def parse_parameters
101
+ @opt_parser.parse!
102
+ check_rcfile if options.default_config_file
103
+
104
+ rescue OptionParser::InvalidOption => e
105
+ log e.message
106
+ exit 1
107
+ end
108
+
109
+ def configure_opt_parser
110
+ @opt_parser = OptParser.new self
111
+ end
112
+
113
+ def check_rcfile
114
+ sample = NightcrawlerSwift::CLI.sample_rcfile
115
+ unless File.exist?(options.config_file)
116
+ File.open(options.config_file, "w") { |f|
117
+ f.write(sample)
118
+ }
119
+ end
120
+
121
+ if sample == File.read(options.config_file)
122
+ options.configured = false
123
+ end
124
+ end
125
+
126
+ end
127
+ end