nightcrawler_swift 0.5.0 → 0.6.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ce783e76729a865b6b3cd1fffbed84cc287234e9
4
- data.tar.gz: 922f51e1130d4bb27b84bde8de018793c5b5a1c4
3
+ metadata.gz: 6210245e5388c7b1c73fa1c6ff58b2f7a2770320
4
+ data.tar.gz: 6071b7124b88f4293ea186b2755c99a7e6f3b407
5
5
  SHA512:
6
- metadata.gz: ba0dc5e45b62d8011f321aba5c0e28487d5b496cde054a2197db3db5baeb2c9936a542ef5ef02ad9b3d324261b8677b6520140df048045ed4f579fd5bdb8db8e
7
- data.tar.gz: a55710e1eddf95712cb5c3821b1853854b815ecf066ee6bf22c7b259e66f1dd7ad65f1f10405e4b8fe88b0b7c3482dbea3e05faaf9a1343fc1c7425af4152da1
6
+ metadata.gz: 65753c810f8691b5e06afe0db034d692ac9187d7d73e5b3be899a141fd1ffe3eb86114ebb2bcd4c6ebdffadc8760905a9a04d6da93a677f6c3db7a116824ee48
7
+ data.tar.gz: bd9c1a5bbc7dffd4e24c0d8efab7e50f0e8917af973b4b9798e2d9df14b9f61793d1414d196df03b292b6758e431a50c6b3913d22c5fbb198617d2492c587674
data/Changelog.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.6.0
4
+
5
+ - Upload command allows a custom max-age (issue #23)
6
+ - List command allows the following parameters: ```limit```, ```marker```, ```end_marker```, ```prefix```, ```format```, ```delimiter``` and ```path``` (issue #22)
7
+ - Download command uses the internal_url by default (issue #25)
8
+ - CLI now supports a ```--max-age``` to override the default max_age
9
+ - Included ```Expires``` header to upload command based on max_age configuration (issue #9)
10
+ - The _password_ option can be defined by the env variable ```NSWIFT_PASSWORD``` (issue #21)
11
+ - Support for SSL Client Certificates through the options: ```ssl_client_cert```, ```ssl_client_key``` and ```ssl_ca_file```
12
+ - Configurable ```internal_url```
13
+
3
14
  ## 0.5.0
4
15
 
5
16
  - CLI now supports ```-b/--bucket``` to override the default bucket/container (issue #10)
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- nightcrawler_swift (0.5.0)
4
+ nightcrawler_swift (0.6.0)
5
5
  multi_mime (>= 1.0.1)
6
6
  rest-client
7
7
 
data/README.md CHANGED
@@ -41,16 +41,39 @@ config.nightcrawler_swift.password = "my_password1"
41
41
  config.nightcrawler_swift.auth_url = "https://auth.url.com:123/v2.0/tokens"
42
42
  ```
43
43
 
44
+ The __password__ option can be left blank and be defined by the env variable __NSWIFT_PASSWORD__. The env variable will take precedence if the option was set.
45
+
44
46
  __Optional configurations:__
45
47
 
46
48
  ```ruby
47
49
  config.nightcrawler_swift.max_age = 3600 # default: nil
48
- config.nightcrawler_swift.verify_ssl = true # default: false
49
50
  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
51
+
52
+ # default: uses the admin_url returned by authentication
53
+ config.nightcrawler_swift.admin_url = "https://api.host.com/v1/AUTH_1234"
54
+
55
+ # default: uses the public_url returned by authentication
56
+ config.nightcrawler_swift.public_url = "http://asset.host.com/v1/AUTH_1234"
57
+
58
+ # default: 5, to disable set it to false
59
+ config.nightcrawler_swift.retries = 3
60
+
61
+ # in seconds, default: 30
62
+ config.nightcrawler_swift.max_retry_time = 64
63
+
64
+ # default: false. You could use OpenSSL::SSL::VERIFY_PEER
65
+ config.nightcrawler_swift.verify_ssl = true
66
+
67
+ # default: nil
68
+ config.nightcrawler_swift.ssl_client_cert =
69
+ OpenSSL::X509::Certificate.new(File.read("cert.pem"))
70
+
71
+ # default: nil
72
+ config.nightcrawler_swift.ssl_client_key =
73
+ OpenSSL::PKey::RSA.new(File.read("key.pem"), "passphrase, if any")
74
+
75
+ # default: nil
76
+ config.nightcrawler_swift.ssl_ca_file = "ca_certificate.pem"
54
77
  ```
55
78
 
56
79
  By default it will use ```Rails.logger``` as logger, to change that use a different logger in configurations, like:
@@ -95,16 +118,40 @@ NightcrawlerSwift.configure({
95
118
  })
96
119
  ```
97
120
 
121
+ The __password__ option can be left blank and be defined by the env variable __NSWIFT_PASSWORD__. The env variable will take precedence if the option was set.
122
+
123
+
98
124
  __Optional configurations:__
99
125
 
100
126
  ```ruby
101
127
  max_age: 3600,
102
- verify_ssl: true,
103
128
  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
129
+
130
+ # default: uses the admin_url returned by authentication
131
+ admin_url: "https://api.host.com/v1/AUTH_1234",
132
+
133
+ # default: uses the public_url returned by authentication
134
+ public_url: "http://asset.host.com/v1/AUTH_1234",
135
+
136
+ # default: 5, to disable set it to false
137
+ retries: 3,
138
+
139
+ # in seconds, default: 30
140
+ max_retry_time: 64
141
+
142
+ # default: false. You could use OpenSSL::SSL::VERIFY_PEER
143
+ verify_ssl: true,
144
+
145
+ # default: nil
146
+ ssl_client_cert:
147
+ OpenSSL::X509::Certificate.new(File.read("cert.pem")),
148
+
149
+ # default: nil
150
+ ssl_client_key:
151
+ OpenSSL::PKey::RSA.new(File.read("key.pem"), "passphrase, if any"),
152
+
153
+ # default: nil
154
+ ssl_ca_file: "ca_certificate.pem"
108
155
  ```
109
156
 
110
157
  By default it will use ```Logger.new(STDOUT)``` as logger, to change that use:
@@ -149,6 +196,13 @@ $ nswift list
149
196
  ```sh
150
197
  $ nswift upload <real_path> <swift_path> # nswift upload robots.txt assets/robots.txt
151
198
  ```
199
+
200
+ Upload also supports a custom max-age, to override the value defined in ".nswiftrc", example:
201
+
202
+ ```sh
203
+ $ nswift upload <real_path> <swift_path> --max-age VALUE # nswift upload readme assets/readme.md --max-age 300
204
+ ```
205
+
152
206
  ```sh
153
207
  $ nswift download <swift_path> # nswift download assets/robots.txt > my-robots.txt
154
208
  ```
@@ -183,7 +237,15 @@ upload.execute "my_file_path.txt", File.open("../my_file_fullpath.txt", "r")
183
237
  # true / false
184
238
  ```
185
239
 
186
- _This upload command was not designed to send very large files_
240
+ _This upload command was not designed to send very large files_.
241
+
242
+ It will accept a custom max-age, overriding the configured value through ```NightcrawlerSwift.configure```, example:
243
+
244
+ ```ruby
245
+ upload = NightcrawlerSwift::Upload.new
246
+ upload.execute "readme", File.open("readme.md", "r"), max_age: 300
247
+ # true / false
248
+ ```
187
249
 
188
250
  ### Download
189
251
 
@@ -203,6 +265,16 @@ list.execute
203
265
  # [{"hash": "...", "name": "my_file_path.txt"}, {}, {}, ...]
204
266
  ```
205
267
 
268
+ This command supports the following parameters: __limit, marker, end_marker, prefix, format, delimiter, path__
269
+
270
+ Example:
271
+
272
+ ```ruby
273
+ list = NightcrawlerSwift::List.new
274
+ list.execute prefix: '/some/path'
275
+ # [{"hash": "...", "name": "/some/path/with/my_file_path.txt"}, {}, {}, ...]
276
+ ```
277
+
206
278
  ### Delete
207
279
 
208
280
  ```ruby
@@ -1,3 +1,4 @@
1
+ require "cgi"
1
2
  require "date"
2
3
  require "logger"
3
4
  require "digest"
@@ -6,6 +7,8 @@ require "multi_mime"
6
7
  require "rest_client"
7
8
  require "nightcrawler_swift/version"
8
9
  require "nightcrawler_swift/exceptions"
10
+ require "nightcrawler_swift/ext/hash"
11
+ require "nightcrawler_swift/options"
9
12
  require "nightcrawler_swift/gateway"
10
13
  require "nightcrawler_swift/connection"
11
14
  require "nightcrawler_swift/command"
@@ -34,20 +37,19 @@ module NightcrawlerSwift
34
37
  # - auth_url
35
38
  #
36
39
  # - max_age (optional, default: nil)
37
- # - verify_ssl (optional, default: false)
38
40
  # - timeout (in seconds. Optional, default: nil)
39
41
  #
40
42
  # - retries (default: 3)
41
43
  # - max_retry_time (in seconds, default: 30)
42
44
  #
45
+ # - verify_ssl (optional, default: false)
46
+ # - ssl_client_cert (optional, default: nil)
47
+ # - ssl_client_key (optional, default: nil)
48
+ # - ssl_ca_file (optional, default: nil)
49
+ #
43
50
  def configure opts = {}
44
- defaults = {verify_ssl: false, retries: 5, max_retry_time: 30}
45
- @options = OpenStruct.new(defaults.merge(opts))
46
-
47
- if @options.max_age and not @options.max_age.is_a?(Numeric)
48
- raise Exceptions::ConfigurationError.new "max_age should be an Integer"
49
- end
50
-
51
+ opts.symbolize_keys!
52
+ @options = Options.new opts
51
53
  @connection = Connection.new
52
54
  end
53
55
 
@@ -34,6 +34,7 @@ module NightcrawlerSwift::CLI
34
34
  def configure_options
35
35
  @parser.separator "options:"
36
36
  configure_option_bucket
37
+ configure_option_max_age
37
38
  configure_option_config
38
39
  configure_option_help
39
40
  configure_option_version
@@ -43,8 +44,17 @@ module NightcrawlerSwift::CLI
43
44
  desc = "Alternative bucket/container name, overrides the '#{NightcrawlerSwift::CLI::CONFIG_FILE}' configuration"
44
45
  @parser.on("-b", "--bucket=NAME", String, desc) do |name|
45
46
  bucket = name.strip
46
- @runner.options.bucket = bucket
47
- @runner.log "Using bucket: #{@runner.options.bucket}"
47
+ @runner.options.config_hash[:bucket] = bucket
48
+ @runner.log "Using bucket: #{bucket}"
49
+ end
50
+ end
51
+
52
+ def configure_option_max_age
53
+ desc = "Custom max_age value, it overrides the value configured at '#{NightcrawlerSwift::CLI::CONFIG_FILE}'"
54
+ @parser.on("--max-age=VALUE", String, desc) do |value|
55
+ max_age = value.strip.to_i
56
+ @runner.options.config_hash[:max_age] = max_age
57
+ @runner.log "Using max_age: #{max_age}"
48
58
  end
49
59
  end
50
60
 
@@ -34,7 +34,7 @@ module NightcrawlerSwift::CLI
34
34
  @options.default_config_file = true
35
35
  @options.config_file = File.expand_path(File.join(user_home_dir, CONFIG_FILE))
36
36
  @options.cache_file = File.expand_path(File.join(user_home_dir, CACHE_FILE))
37
- @options.bucket = nil
37
+ @options.config_hash = {}
38
38
  end
39
39
 
40
40
  def validate_command_and_options
@@ -55,12 +55,11 @@ module NightcrawlerSwift::CLI
55
55
  end
56
56
 
57
57
  def config_hash
58
- @config_hash ||= JSON.parse(File.read(options.config_file))
58
+ @config_hash ||= JSON.parse(File.read(options.config_file), symbolize_names: true) rescue {}
59
59
  end
60
60
 
61
61
  def execute_command
62
- NightcrawlerSwift.configure config_hash
63
- NightcrawlerSwift.options.bucket = @options.bucket if @options.bucket
62
+ NightcrawlerSwift.configure config_hash.merge(@options.config_hash)
64
63
 
65
64
  connect_and_execute do
66
65
  command_method = "command_#{command_name_normalized}"
@@ -19,26 +19,30 @@ module NightcrawlerSwift
19
19
 
20
20
  protected
21
21
 
22
- def get url, params = {}
23
- prepare_params params
24
- Gateway.new(url).request {|r| r.get params[:headers]}
22
+ def get url, args = {}
23
+ prepare_args args
24
+ Gateway.new(url).request {|r| r.get headers_and_params(args)}
25
25
  end
26
26
 
27
- def put url, params = {}
28
- prepare_params params
29
- Gateway.new(url).request {|r| r.put params[:body], params[:headers]}
27
+ def put url, args = {}
28
+ prepare_args args
29
+ Gateway.new(url).request {|r| r.put args[:body], headers_and_params(args)}
30
30
  end
31
31
 
32
- def delete url, params
33
- prepare_params params
34
- Gateway.new(url).request {|r| r.delete params[:headers]}
32
+ def delete url, args = {}
33
+ prepare_args args
34
+ Gateway.new(url).request {|r| r.delete headers_and_params(args)}
35
35
  end
36
36
 
37
37
  private
38
+ def prepare_args args
39
+ args[:headers] ||= {}
40
+ args[:headers]["X-Storage-Token"] = connection.token_id
41
+ args[:params] ||= {}
42
+ end
38
43
 
39
- def prepare_params params
40
- params[:headers] ||= {}
41
- params[:headers]["X-Storage-Token"] = connection.token_id
44
+ def headers_and_params args
45
+ args[:headers].merge(params: args[:params])
42
46
  end
43
47
  end
44
48
  end
@@ -6,7 +6,7 @@ module NightcrawlerSwift
6
6
  raise Exceptions::ValidationError.new "Delete command requires a path parameter"
7
7
  end
8
8
 
9
- response = delete "#{connection.upload_url}/#{path}", headers: {accept: :json }
9
+ response = delete "#{connection.upload_url}/#{path}", headers: { accept: :json }
10
10
  [200, 201].include?(response.code)
11
11
  end
12
12
 
@@ -6,7 +6,7 @@ module NightcrawlerSwift
6
6
  raise Exceptions::ValidationError.new "Download command requires a path parameter"
7
7
  end
8
8
 
9
- response = get "#{connection.public_url}/#{options.bucket}/#{path}"
9
+ response = get "#{connection.internal_url}/#{options.bucket}/#{path}"
10
10
  response.body
11
11
  end
12
12
 
@@ -1,8 +1,16 @@
1
1
  module NightcrawlerSwift
2
2
  class List < Command
3
3
 
4
- def execute
5
- response = get connection.upload_url, headers: {accept: :json}
4
+ def execute args = {}
5
+ headers = { accept: :json }
6
+
7
+ # http://docs.openstack.org/api/openstack-object-storage/1.0/content/GET_showContainerDetails__v1__account___container__storage_container_services.html#GET_showContainerDetails__v1__account___container__storage_container_services-Request
8
+ params = {}
9
+ [:limit, :marker, :end_marker, :prefix, :format, :delimiter, :path].each do |accepted_parameter|
10
+ params[accepted_parameter] = args[accepted_parameter] if args[accepted_parameter]
11
+ end
12
+
13
+ response = get connection.upload_url, headers: headers, params: params
6
14
  JSON.parse(response.body)
7
15
  end
8
16
 
@@ -1,11 +1,14 @@
1
1
  module NightcrawlerSwift
2
2
  class Upload < Command
3
3
 
4
- def execute path, file
5
- content = file.read
6
- headers = {etag: etag(content), content_type: content_type(file)}
7
- headers.merge!(cache_control: "public, max-age=#{options.max_age}") if options.max_age
8
- response = put "#{connection.upload_url}/#{path}", body: content, headers: headers
4
+ def execute path, file, opts = {}
5
+ body = file.read
6
+ headers = {etag: etag(body), content_type: content_type(file)}
7
+
8
+ max_age = opts[:max_age] || options.max_age
9
+ headers.merge!(cache_control: "public, max-age=#{max_age}", expires: expires(max_age)) if max_age
10
+
11
+ response = put "#{connection.upload_url}/#{path}", body: body, headers: headers
9
12
  [200, 201].include?(response.code)
10
13
  end
11
14
 
@@ -18,5 +21,9 @@ module NightcrawlerSwift
18
21
  Digest::MD5.hexdigest(content)
19
22
  end
20
23
 
24
+ def expires max_age
25
+ CGI.rfc1123_date(Time.now + max_age)
26
+ end
27
+
21
28
  end
22
29
  end
@@ -1,7 +1,7 @@
1
1
  module NightcrawlerSwift
2
2
  class Connection
3
3
  attr_accessor :auth_response
4
- attr_reader :token_id, :expires_at, :catalog, :admin_url, :upload_url, :public_url
4
+ attr_reader :token_id, :expires_at, :catalog, :admin_url, :upload_url, :public_url, :internal_url
5
5
 
6
6
  def connect!
7
7
  authenticate!
@@ -65,6 +65,7 @@ module NightcrawlerSwift
65
65
  def configure_urls
66
66
  @admin_url = opts.admin_url || @endpoints["adminURL"]
67
67
  @public_url = opts.public_url || @endpoints["publicURL"]
68
+ @internal_url = opts.internal_url || @endpoints["internalURL"]
68
69
  @upload_url = "#{@admin_url}/#{opts.bucket}"
69
70
  end
70
71
  end
@@ -0,0 +1,38 @@
1
+ module NightcrawlerSwift
2
+ module Hash
3
+
4
+ unless {}.respond_to?(:symbolize_keys)
5
+ def symbolize_keys
6
+ {}.tap do |result|
7
+ keys.each {|k| result[k.to_sym] = self[k]}
8
+ end
9
+ end
10
+
11
+ def symbolize_keys!
12
+ self.tap do
13
+ keys.each {|k| self[k.to_sym] = delete(k)}
14
+ end
15
+ end
16
+ end
17
+
18
+ unless {}.respond_to?(:compact)
19
+ def compact
20
+ {}.tap do |result|
21
+ keys.each {|k| result[k] = self[k] unless self[k].nil?}
22
+ end
23
+ end
24
+
25
+ def compact!
26
+ self.tap do
27
+ keys.each do |k|
28
+ value = delete(k)
29
+ self[k] = value unless value.nil?
30
+ end
31
+ end
32
+ end
33
+ end
34
+
35
+ end
36
+ end
37
+
38
+ Hash.send :include, NightcrawlerSwift::Hash
@@ -18,8 +18,7 @@ module NightcrawlerSwift
18
18
 
19
19
  @resource = RestClient::Resource.new(
20
20
  @url,
21
- verify_ssl: NightcrawlerSwift.options.verify_ssl,
22
- timeout: NightcrawlerSwift.options.timeout
21
+ {timeout: options.timeout}.merge(ssl_options)
23
22
  )
24
23
  end
25
24
 
@@ -51,6 +50,22 @@ module NightcrawlerSwift
51
50
  NightcrawlerSwift.logger.debug message
52
51
  end
53
52
 
53
+ def options
54
+ NightcrawlerSwift.options
55
+ end
56
+
57
+ def ssl_options
58
+ [
59
+ :verify_ssl,
60
+ :ssl_client_cert,
61
+ :ssl_client_key,
62
+ :ssl_ca_file
63
+
64
+ ].inject({}) {|hash, key|
65
+ hash.tap {hash[key] = options[key]}
66
+ }.compact
67
+ end
68
+
54
69
  def recoverable? e
55
70
  @retries and
56
71
  !RETRY_BLACKLIST.include?(e.class) and
@@ -0,0 +1,27 @@
1
+ module NightcrawlerSwift
2
+ class Options < OpenStruct
3
+
4
+ def initialize params = {}
5
+ params[:password] = ENV["NSWIFT_PASSWORD"] || params[:password]
6
+ super defaults.merge(params)
7
+ validate_max_age!
8
+ end
9
+
10
+ protected
11
+ def defaults
12
+ {
13
+ retries: 5,
14
+ max_retry_time: 30,
15
+ verify_ssl: false
16
+ }
17
+ end
18
+
19
+ private
20
+ def validate_max_age!
21
+ if self.max_age and not self.max_age.is_a?(Numeric)
22
+ raise Exceptions::ConfigurationError.new "max_age should be an Integer"
23
+ end
24
+ end
25
+
26
+ end
27
+ end
@@ -1,3 +1,3 @@
1
1
  module NightcrawlerSwift
2
- VERSION = "0.5.0"
2
+ VERSION = "0.6.0"
3
3
  end
@@ -4,7 +4,7 @@ require "nightcrawler_swift/cli"
4
4
  describe NightcrawlerSwift::CLI::OptParser do
5
5
 
6
6
  let :runner do
7
- instance_double "Runner", options: OpenStruct.new(bucket: nil, config_file: nil, default_config_file: true)
7
+ instance_double "Runner", options: OpenStruct.new(config_hash: {}, config_file: nil, default_config_file: true)
8
8
  end
9
9
 
10
10
  let :config_dir do
@@ -108,7 +108,26 @@ describe NightcrawlerSwift::CLI::OptParser do
108
108
  allow(runner).to receive(:argv).and_return([command])
109
109
  allow(runner).to receive(:log)
110
110
  subject.parse!
111
- expect(runner.options.bucket).to eql bucket_name
111
+ expect(runner.options.config_hash).to include(bucket: bucket_name)
112
+ end
113
+ end
114
+ end
115
+
116
+ ["--max-age=VALUE"].each do |switch|
117
+ context switch do
118
+ let :max_age do
119
+ 300
120
+ end
121
+
122
+ let :command do
123
+ switch.gsub(/VALUE/, max_age.to_s)
124
+ end
125
+
126
+ it "configures the max-age" do
127
+ allow(runner).to receive(:argv).and_return([command])
128
+ allow(runner).to receive(:log)
129
+ subject.parse!
130
+ expect(runner.options.config_hash).to include(max_age: max_age)
112
131
  end
113
132
  end
114
133
  end
@@ -101,7 +101,7 @@ describe NightcrawlerSwift::CLI::Runner do
101
101
  end
102
102
 
103
103
  it "configures NightcrawlerSwift" do
104
- expect(NightcrawlerSwift).to receive(:configure).with opts
104
+ expect(NightcrawlerSwift).to receive(:configure).with opts.symbolize_keys
105
105
  subject.run
106
106
  end
107
107
 
@@ -121,16 +121,31 @@ describe NightcrawlerSwift::CLI::Runner do
121
121
 
122
122
  before do
123
123
  subject.send :configure_default_options
124
- expect(subject.options.bucket).to be_nil
124
+ expect(subject.options.config_hash).to eql({})
125
125
  end
126
126
 
127
127
  it "overrides the default name" do
128
- allow(subject).to receive(:parse_parameters) { subject.options.bucket = bucket_name }
128
+ allow(subject).to receive(:parse_parameters) { subject.options.config_hash[:bucket] = bucket_name }
129
129
  subject.run
130
130
  expect(NightcrawlerSwift.options.bucket).to eql bucket_name
131
131
  end
132
132
  end
133
133
 
134
+ context "with a custom max-age" do
135
+ let(:max_age) { 300 }
136
+
137
+ before do
138
+ subject.send :configure_default_options
139
+ expect(subject.options.config_hash).to eql({})
140
+ end
141
+
142
+ it "overrides the default name" do
143
+ allow(subject).to receive(:parse_parameters) { subject.options.config_hash[:max_age] = max_age }
144
+ subject.run
145
+ expect(NightcrawlerSwift.options.max_age).to eql max_age
146
+ end
147
+ end
148
+
134
149
  it "writes the auth_response into cache file" do
135
150
  expect(File.exist?(cache_file)).to eql false
136
151
  expect(connection).to receive(:auth_response).and_return(OpenStruct.new(connection_success_json))
@@ -60,14 +60,24 @@ describe NightcrawlerSwift::Command do
60
60
 
61
61
  describe "#get" do
62
62
  let :execute_http do
63
- subject.send :get, url, headers: {content_type: :json}
63
+ subject.send :get, url, body: 'ignore_me', headers: { content_type: :json }, params: { b: 2 }
64
64
  end
65
65
 
66
66
  it_behaves_like "command with configured gateway"
67
67
 
68
+ it "ignores body" do
69
+ execute_http
70
+ expect(restclient).to have_received(:get).with(kind_of(Hash))
71
+ end
72
+
68
73
  it "sends headers with token" do
69
74
  execute_http
70
- expect(restclient).to have_received(:get).with(content_type: :json, "X-Storage-Token" => token)
75
+ expect(restclient).to have_received(:get).with(hash_including({ content_type: :json, "X-Storage-Token" => token }))
76
+ end
77
+
78
+ it "sends params" do
79
+ execute_http
80
+ expect(restclient).to have_received(:get).with(hash_including(params: { b: 2 }))
71
81
  end
72
82
 
73
83
  it "returns RestClient response" do
@@ -77,14 +87,24 @@ describe NightcrawlerSwift::Command do
77
87
 
78
88
  describe "#delete" do
79
89
  let :execute_http do
80
- subject.send :delete, url, headers: {content_type: :json}
90
+ subject.send :delete, url, body: 'ignore_me', headers: { content_type: :json }, params: { b: 2 }
81
91
  end
82
92
 
83
93
  it_behaves_like "command with configured gateway"
84
94
 
95
+ it "ignores body" do
96
+ execute_http
97
+ expect(restclient).to have_received(:delete).with(kind_of(Hash))
98
+ end
99
+
85
100
  it "sends headers with token" do
86
101
  execute_http
87
- expect(restclient).to have_received(:delete).with(content_type: :json, "X-Storage-Token" => token)
102
+ expect(restclient).to have_received(:delete).with(hash_including({ content_type: :json, "X-Storage-Token" => token }))
103
+ end
104
+
105
+ it "sends params" do
106
+ execute_http
107
+ expect(restclient).to have_received(:delete).with(hash_including(params: { b: 2 }))
88
108
  end
89
109
 
90
110
  it "returns RestClient response" do
@@ -94,7 +114,7 @@ describe NightcrawlerSwift::Command do
94
114
 
95
115
  describe "#put" do
96
116
  let :execute_http do
97
- subject.send(:put, url, body: 'content', headers: {a: 1})
117
+ subject.send :put, url, body: 'content', headers: { a: 1 }, params: { b: 2 }
98
118
  end
99
119
 
100
120
  it_behaves_like "command with configured gateway"
@@ -105,12 +125,17 @@ describe NightcrawlerSwift::Command do
105
125
 
106
126
  it "sends body" do
107
127
  execute_http
108
- expect(restclient).to have_received(:put).with('content', anything)
128
+ expect(restclient).to have_received(:put).with('content', kind_of(Hash))
109
129
  end
110
130
 
111
131
  it "sends headers with token" do
112
132
  execute_http
113
- expect(restclient).to have_received(:put).with(anything, {a: 1, "X-Storage-Token" => token})
133
+ expect(restclient).to have_received(:put).with(anything, hash_including({ a: 1, "X-Storage-Token" => token }))
134
+ end
135
+
136
+ it "sends params" do
137
+ execute_http
138
+ expect(restclient).to have_received(:put).with(anything, hash_including(params: { b: 2 }))
114
139
  end
115
140
  end
116
141
 
@@ -5,7 +5,7 @@ describe NightcrawlerSwift::Download do
5
5
  let(:connection) { NightcrawlerSwift::Connection.new }
6
6
  let(:token) { "token" }
7
7
  let(:expires_at) { (DateTime.now + 60).to_time }
8
- let(:public_url) { "server-url" }
8
+ let(:internal_url) { "server-url" }
9
9
  let(:bucket) { "rogue" }
10
10
 
11
11
  subject do
@@ -16,7 +16,7 @@ describe NightcrawlerSwift::Download do
16
16
  allow(NightcrawlerSwift).to receive(:connection).and_return(connection)
17
17
  allow(connection).to receive(:token_id).and_return(token)
18
18
  allow(connection).to receive(:expires_at).and_return(expires_at)
19
- allow(connection).to receive(:public_url).and_return(public_url)
19
+ allow(connection).to receive(:internal_url).and_return(internal_url)
20
20
  NightcrawlerSwift.configure bucket: bucket
21
21
  end
22
22
 
@@ -34,7 +34,7 @@ describe NightcrawlerSwift::Download do
34
34
  allow(subject).to receive(:get).and_return(response)
35
35
  end
36
36
 
37
- it "gets using public url" do
37
+ it "gets using internal url" do
38
38
  execute
39
39
  expect(subject).to have_received(:get).with("server-url/#{bucket}/file_path")
40
40
  end
@@ -31,9 +31,19 @@ describe NightcrawlerSwift::List do
31
31
  allow(subject).to receive(:get).and_return(response)
32
32
  end
33
33
 
34
- it "gets upload url" do
34
+ it "gets upload url without parameters" do
35
35
  subject.execute
36
- expect(subject).to have_received(:get).with(connection.upload_url, headers: {accept: :json})
36
+ expect(subject).to have_received(:get).with(connection.upload_url, headers: { accept: :json }, params: {})
37
+ end
38
+
39
+ it "gets upload url with accepted parameters" do
40
+ subject.execute prefix: 'some/prefix', limit: 2
41
+ expect(subject).to have_received(:get).with(connection.upload_url, headers: { accept: :json }, params: { prefix: 'some/prefix', limit: 2 })
42
+ end
43
+
44
+ it "gets upload url without unknown parameters" do
45
+ subject.execute prefix: 'some/prefix', a: 'b'
46
+ expect(subject).to have_received(:get).with(connection.upload_url, headers: { accept: :json }, params: { prefix: 'some/prefix' })
37
47
  end
38
48
 
39
49
  it "returns the parsed json" do
@@ -68,10 +68,47 @@ describe NightcrawlerSwift::Upload do
68
68
  expect(subject).to have_received(:put).with("server-url/file_name", anything)
69
69
  end
70
70
 
71
- it "sends max_age into headers" do
72
- NightcrawlerSwift.configure max_age: max_age
73
- execute
74
- expect(subject).to have_received(:put).with(anything, hash_including(headers: { content_type: "text/css", etag: etag, cache_control: "public, max-age=#{max_age}" }))
71
+ context "max_age" do
72
+ let :default_headers do
73
+ {content_type: "text/css", etag: etag}
74
+ end
75
+
76
+ it "sends default max_age into headers" do
77
+ NightcrawlerSwift.configure max_age: max_age
78
+ execute
79
+ expect(subject).to have_received(:put).with(
80
+ anything,
81
+ hash_including(
82
+ headers: hash_including(default_headers.merge(cache_control: "public, max-age=#{max_age}"))
83
+ )
84
+ )
85
+ end
86
+
87
+ it "allows custom max_age" do
88
+ NightcrawlerSwift.configure
89
+ subject.execute path, file, max_age: 1
90
+ expect(subject).to have_received(:put).with(
91
+ anything,
92
+ hash_including(
93
+ headers: hash_including(default_headers.merge(cache_control: "public, max-age=1"))
94
+ )
95
+ )
96
+ end
97
+
98
+ it "also sends the expires header based on max_age" do
99
+ now = Time.now
100
+ allow(Time).to receive(:now).and_return(now)
101
+ expires = CGI.rfc1123_date(Time.now + max_age)
102
+
103
+ NightcrawlerSwift.configure max_age: max_age
104
+ execute
105
+ expect(subject).to have_received(:put).with(
106
+ anything,
107
+ hash_including(
108
+ headers: default_headers.merge(cache_control: "public, max-age=#{max_age}", expires: expires)
109
+ )
110
+ )
111
+ end
75
112
  end
76
113
 
77
114
  context "when response code is 200" do
@@ -97,6 +97,11 @@ describe NightcrawlerSwift::Connection do
97
97
  expect(subject.public_url).to eql(auth_success_json["access"]["serviceCatalog"].first["endpoints"].first["publicURL"])
98
98
  end
99
99
 
100
+ it "stores the internal_url" do
101
+ subject.connect!
102
+ expect(subject.internal_url).to eql(auth_success_json["access"]["serviceCatalog"].first["endpoints"].first["internalURL"])
103
+ end
104
+
100
105
  it "returns self" do
101
106
  expect(subject.connect!).to eql(subject)
102
107
  end
@@ -0,0 +1,56 @@
1
+ require 'spec_helper'
2
+
3
+ describe NightcrawlerSwift::Hash do
4
+
5
+ subject do
6
+ {"key1" => "value1", "key2" => "value2"}
7
+ end
8
+
9
+ describe "#symbolize_keys" do
10
+ it "creates a new hash with the symbolized keys" do
11
+ result = subject.symbolize_keys
12
+ expect(result).to include(key1: "value1", key2: "value2")
13
+ expect(subject).to include("key1" => "value1", "key2" => "value2")
14
+ end
15
+ end
16
+
17
+ describe "#symbolize_keys!" do
18
+ it "destructively convert all keys to symbols" do
19
+ result = subject.symbolize_keys!
20
+ expect(result).to include(key1: "value1", key2: "value2")
21
+ expect(subject).to include(key1: "value1", key2: "value2")
22
+ expect(result).to eql subject
23
+ end
24
+ end
25
+
26
+ describe "#compact" do
27
+ subject do
28
+ {key1: nil, key2: "value2", key3: nil}
29
+ end
30
+
31
+ it "creates a new hash without the nil items" do
32
+ result = subject.compact
33
+ expect(result).to_not include(:key1, :key3)
34
+ expect(result).to include(:key2)
35
+
36
+ expect(subject).to include(:key1, :key2, :key3)
37
+ end
38
+ end
39
+
40
+ describe "#compact!" do
41
+ subject do
42
+ {key1: nil, key2: "value2", key3: nil}
43
+ end
44
+
45
+ it "destructively remove the items with the nil value" do
46
+ result = subject.compact!
47
+ expect(result).to_not include(:key1, :key3)
48
+ expect(result).to include(:key2)
49
+ expect(subject).to_not include(:key1, :key3)
50
+ expect(subject).to include(:key2)
51
+
52
+ expect(result).to eql subject
53
+ end
54
+ end
55
+
56
+ end
@@ -10,12 +10,16 @@ describe NightcrawlerSwift::Gateway do
10
10
  subject.request {|r| r.get}
11
11
  end
12
12
 
13
+ let :opts do
14
+ {}
15
+ end
16
+
13
17
  subject do
14
18
  NightcrawlerSwift::Gateway.new url
15
19
  end
16
20
 
17
21
  before do
18
- NightcrawlerSwift.configure
22
+ NightcrawlerSwift.configure opts
19
23
  end
20
24
 
21
25
  describe "initialization" do
@@ -27,6 +31,79 @@ describe NightcrawlerSwift::Gateway do
27
31
  )
28
32
  subject
29
33
  end
34
+
35
+ context "with ssl options" do
36
+ context "but only 'ssl_client_cert'" do
37
+ let :opts do
38
+ {verify_ssl: true, ssl_client_cert: "somecert.pem"}
39
+ end
40
+
41
+ it "uses the configured option" do
42
+ expect(RestClient::Resource).to receive(:new).with(
43
+ url,
44
+ timeout: NightcrawlerSwift.options.timeout,
45
+ verify_ssl: NightcrawlerSwift.options.verify_ssl,
46
+ ssl_client_cert: NightcrawlerSwift.options.ssl_client_cert
47
+ )
48
+ subject
49
+ end
50
+ end
51
+
52
+ context "but only 'ssl_client_key'" do
53
+ let :opts do
54
+ {verify_ssl: true, ssl_client_key: "clientkey"}
55
+ end
56
+
57
+ it "uses the configured option" do
58
+ expect(RestClient::Resource).to receive(:new).with(
59
+ url,
60
+ timeout: NightcrawlerSwift.options.timeout,
61
+ verify_ssl: NightcrawlerSwift.options.verify_ssl,
62
+ ssl_client_key: NightcrawlerSwift.options.ssl_client_key
63
+ )
64
+ subject
65
+ end
66
+ end
67
+
68
+ context "but only 'ssl_ca_file'" do
69
+ let :opts do
70
+ {verify_ssl: true, ssl_ca_file: "Certificate Authority File"}
71
+ end
72
+
73
+ it "uses the configured option" do
74
+ expect(RestClient::Resource).to receive(:new).with(
75
+ url,
76
+ timeout: NightcrawlerSwift.options.timeout,
77
+ verify_ssl: NightcrawlerSwift.options.verify_ssl,
78
+ ssl_ca_file: NightcrawlerSwift.options.ssl_ca_file
79
+ )
80
+ subject
81
+ end
82
+ end
83
+
84
+ context "using all options" do
85
+ let :opts do
86
+ {
87
+ verify_ssl: true,
88
+ ssl_client_cert: "somecert.pem",
89
+ ssl_client_key: "clientkey",
90
+ ssl_ca_file: "Certificate Authority File"
91
+ }
92
+ end
93
+
94
+ it "uses the configured options" do
95
+ expect(RestClient::Resource).to receive(:new).with(
96
+ url,
97
+ timeout: NightcrawlerSwift.options.timeout,
98
+ verify_ssl: NightcrawlerSwift.options.verify_ssl,
99
+ ssl_client_cert: NightcrawlerSwift.options.ssl_client_cert,
100
+ ssl_client_key: NightcrawlerSwift.options.ssl_client_key,
101
+ ssl_ca_file: NightcrawlerSwift.options.ssl_ca_file
102
+ )
103
+ subject
104
+ end
105
+ end
106
+ end
30
107
  end
31
108
 
32
109
  describe "#request" do
@@ -0,0 +1,77 @@
1
+ require 'spec_helper'
2
+
3
+ describe NightcrawlerSwift::Options do
4
+
5
+ subject do
6
+ NightcrawlerSwift::Options.new opts
7
+ end
8
+
9
+ let :opts do
10
+ {}
11
+ end
12
+
13
+ describe "initialization" do
14
+ context "verify_ssl" do
15
+ it "defauts to false" do
16
+ expect(subject.verify_ssl).to eql false
17
+ end
18
+ end
19
+
20
+ context "retries" do
21
+ it "defauts to 5" do
22
+ expect(subject.retries).to eql 5
23
+ end
24
+ end
25
+
26
+ context "max_retry_time" do
27
+ it "defauts to 30" do
28
+ expect(subject.max_retry_time).to eql 30
29
+ end
30
+ end
31
+
32
+ context "password" do
33
+ before do
34
+ expect(ENV).to receive(:[]).with("NSWIFT_PASSWORD").and_return("123")
35
+ end
36
+
37
+ it "can be defined by the ENV variable 'NSWIFT_PASSWORD'" do
38
+ expect(subject.password).to eql "123"
39
+ end
40
+
41
+ context "when configured" do
42
+ let :opts do
43
+ {password: "345"}
44
+ end
45
+
46
+ it "takes the ENV variable in precedence" do
47
+ expect(subject.password).to eql "123"
48
+ end
49
+ end
50
+ end
51
+
52
+ context "and max_age isn't an integer" do
53
+ let(:opts) { {max_age: "a string"} }
54
+
55
+ it "raises NightcrawlerSwift::Exceptions::ConfigurationError" do
56
+ expect { subject }.to raise_error(NightcrawlerSwift::Exceptions::ConfigurationError)
57
+ end
58
+ end
59
+
60
+ context "when configured" do
61
+ let :opts do
62
+ {
63
+ bucket: "rogue",
64
+ password: "123",
65
+ retries: 2
66
+ }
67
+ end
68
+
69
+ it "creates with the given values" do
70
+ expect(subject.bucket).to eql "rogue"
71
+ expect(subject.password).to eql "123"
72
+ expect(subject.retries).to eql 2
73
+ end
74
+ end
75
+ end
76
+
77
+ end
@@ -29,7 +29,7 @@ describe NightcrawlerSwift do
29
29
  end
30
30
 
31
31
  describe "::configure" do
32
- it "creates the options struct with the given values" do
32
+ it "creates the options with the given values" do
33
33
  subject.configure opts
34
34
  expect(subject.options).to_not be_nil
35
35
  opts.keys.each do |key|
@@ -42,32 +42,6 @@ describe NightcrawlerSwift do
42
42
  subject.configure opts
43
43
  expect(subject.connection).to_not be_nil
44
44
  end
45
-
46
- context "verify_ssl" do
47
- it "defauts to false" do
48
- expect(subject.options.verify_ssl).to eql false
49
- end
50
- end
51
-
52
- context "retries" do
53
- it "defauts to 5" do
54
- expect(subject.options.retries).to eql 5
55
- end
56
- end
57
-
58
- context "max_retry_time" do
59
- it "defauts to 30" do
60
- expect(subject.options.max_retry_time).to eql 30
61
- end
62
- end
63
-
64
- context "and max_age isn't an integer" do
65
- let(:opts) { {max_age: "a string"} }
66
-
67
- it "raises NightcrawlerSwift::Exceptions::ConfigurationError" do
68
- expect { subject.configure(opts) }.to raise_error(NightcrawlerSwift::Exceptions::ConfigurationError)
69
- end
70
- end
71
45
  end
72
46
 
73
47
  describe "::connection" do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nightcrawler_swift
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - tulios
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-09-11 00:00:00.000000000 Z
12
+ date: 2014-09-25 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rest-client
@@ -145,7 +145,9 @@ files:
145
145
  - lib/nightcrawler_swift/commands/upload.rb
146
146
  - lib/nightcrawler_swift/connection.rb
147
147
  - lib/nightcrawler_swift/exceptions.rb
148
+ - lib/nightcrawler_swift/ext/hash.rb
148
149
  - lib/nightcrawler_swift/gateway.rb
150
+ - lib/nightcrawler_swift/options.rb
149
151
  - lib/nightcrawler_swift/railtie.rb
150
152
  - lib/nightcrawler_swift/tasks/asset_sync.rake
151
153
  - lib/nightcrawler_swift/version.rb
@@ -167,7 +169,9 @@ files:
167
169
  - spec/lib/nightcrawler_swift/commands/sync_spec.rb
168
170
  - spec/lib/nightcrawler_swift/commands/upload_spec.rb
169
171
  - spec/lib/nightcrawler_swift/connection_spec.rb
172
+ - spec/lib/nightcrawler_swift/ext/hash_spec.rb
170
173
  - spec/lib/nightcrawler_swift/gateway_spec.rb
174
+ - spec/lib/nightcrawler_swift/options_spec.rb
171
175
  - spec/lib/nightcrawler_swift/tasks/asset_sync_spec.rb
172
176
  - spec/lib/nightcrawler_swift_spec.rb
173
177
  - spec/spec_helper.rb
@@ -214,7 +218,9 @@ test_files:
214
218
  - spec/lib/nightcrawler_swift/commands/sync_spec.rb
215
219
  - spec/lib/nightcrawler_swift/commands/upload_spec.rb
216
220
  - spec/lib/nightcrawler_swift/connection_spec.rb
221
+ - spec/lib/nightcrawler_swift/ext/hash_spec.rb
217
222
  - spec/lib/nightcrawler_swift/gateway_spec.rb
223
+ - spec/lib/nightcrawler_swift/options_spec.rb
218
224
  - spec/lib/nightcrawler_swift/tasks/asset_sync_spec.rb
219
225
  - spec/lib/nightcrawler_swift_spec.rb
220
226
  - spec/spec_helper.rb