nightcrawler_swift 0.11.1 → 1.0.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: a01ca41080d2e2b24b9005e7fa2e4da34c6fef4b
4
- data.tar.gz: eae62f063a96a74260358ea140eba27ac03e219c
3
+ metadata.gz: 7368872bbed33a3a4928360a3162cbec161ad31d
4
+ data.tar.gz: 7599b6e39f3e7a0c376518beed4deb89978a68f9
5
5
  SHA512:
6
- metadata.gz: 73107c34d413732b19acb85ad51e5cf1e7bf1268cf3f73206d22d09cf6c66db95a94a3c5148638f2256db7955bf89d7f348c00478a482b92d1c9104d00da6f72
7
- data.tar.gz: a056ef9ea2ce5cef78410e93a368dc6aff253152ea40fa1b5987be66b8a33dde52f040e0167f173e231bdd24c5f1d1ef80671be6a010f9d2cc0c3e5cd55dd3a0
6
+ metadata.gz: c4d15c9c9fc23c71b7dfa04cceaa00bf0152603fae8372c5527a5a0cbfce9bbf54438d4c334d39ad483e94b4d2ff724f90e663273e7ca833aef65341243bcbc0
7
+ data.tar.gz: 866b75e3f995ce7754712bb12b13967ff5009d2db7a5e657aba7b14bc6865b9b5222b212ba7b21c96331d6b0ed9663b57ba6bcdd7853ac5502470e21c2348bb8
@@ -1 +1 @@
1
- ruby-2.1.2
1
+ ruby-2.4.1
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- nightcrawler_swift (0.11.1)
4
+ nightcrawler_swift (1.0.0)
5
5
  concurrent-ruby (~> 0.8.0)
6
6
  multi_mime (>= 1.1.0)
7
7
  rest-client
@@ -21,7 +21,7 @@ GEM
21
21
  debugger-linecache (1.2.0)
22
22
  diff-lcs (1.2.5)
23
23
  docile (1.1.5)
24
- domain_name (0.5.20160826)
24
+ domain_name (0.5.20170404)
25
25
  unf (>= 0.0.5, < 1.0.0)
26
26
  http-cookie (1.0.3)
27
27
  domain_name (~> 0.5)
@@ -33,7 +33,7 @@ GEM
33
33
  netrc (0.11.0)
34
34
  rake (10.3.2)
35
35
  ref (1.0.5)
36
- rest-client (2.0.0)
36
+ rest-client (2.0.2)
37
37
  http-cookie (>= 1.0.2, < 2.0)
38
38
  mime-types (>= 1.16, < 4.0)
39
39
  netrc (~> 0.8)
@@ -58,7 +58,7 @@ GEM
58
58
  timecop (0.8.0)
59
59
  unf (0.1.4)
60
60
  unf_ext
61
- unf_ext (0.0.7.2)
61
+ unf_ext (0.0.7.4)
62
62
 
63
63
  PLATFORMS
64
64
  ruby
@@ -73,4 +73,4 @@ DEPENDENCIES
73
73
  timecop
74
74
 
75
75
  BUNDLED WITH
76
- 1.13.5
76
+ 1.15.3
data/README.md CHANGED
@@ -6,6 +6,10 @@
6
6
 
7
7
  Like the X-Men nightcrawler this gem teleports your assets to a OpenStack Swift bucket/container. It was designed to sync your assets with OpenStack Swift and allow some operations with your buckets/containers.
8
8
 
9
+ ## Compatibility
10
+
11
+ nightcrawler_swift version 1.x is compatible with [Identity API v3](https://developer.openstack.org/api-ref/identity/v3/index.html). To use [API v2](https://developer.openstack.org/api-ref/identity/v2/index.html), you should install version 0.x.
12
+
9
13
  ## Installation
10
14
 
11
15
  Add this line to your application's Gemfile:
@@ -14,16 +18,28 @@ Add this line to your application's Gemfile:
14
18
  gem 'nightcrawler_swift'
15
19
  ```
16
20
 
21
+ Or, if you want to use Identity API v2:
22
+
23
+ ```ruby
24
+ gem 'nightcrawler_swift', '< 1.0'
25
+ ```
26
+
17
27
  And then execute:
18
28
 
19
29
  ```sh
20
30
  $ bundle
21
31
  ```
22
32
 
23
- Or install it yourself as:
33
+ Or install it manually:
34
+
35
+ ```sh
36
+ $ gem install nightcrawler_swift # Install latest version
37
+ ```
38
+
39
+ Or set a specific version:
24
40
 
25
41
  ```sh
26
- $ gem install nightcrawler_swift
42
+ $ gem install nightcrawler_swift -v 0.11.1
27
43
  ```
28
44
 
29
45
  ## Usage
@@ -7,7 +7,7 @@ module NightcrawlerSwift
7
7
  end
8
8
 
9
9
  response = delete "#{connection.upload_url}/#{path}", headers: { accept: :json }
10
- [200, 201].include?(response.code)
10
+ response.code >= 200 && response.code < 300
11
11
  end
12
12
 
13
13
  end
@@ -2,6 +2,10 @@ module NightcrawlerSwift
2
2
  class Upload < Command
3
3
 
4
4
  def execute path, file, opts = {}
5
+ if path.nil? or path.empty?
6
+ raise Exceptions::ValidationError.new "Upload command requires a path parameter"
7
+ end
8
+
5
9
  body = file.read
6
10
  headers = {etag: etag(body), content_type: content_type(file)}
7
11
 
@@ -18,7 +22,7 @@ module NightcrawlerSwift
18
22
  headers.merge!(custom_headers) if custom_headers
19
23
 
20
24
  response = put "#{connection.upload_url}/#{path}", body: body, headers: headers
21
- [200, 201].include?(response.code)
25
+ response.code >= 200 && response.code < 300
22
26
  end
23
27
 
24
28
  private
@@ -50,7 +50,7 @@ module NightcrawlerSwift
50
50
  headers = {content_type: :json, accept: :json}
51
51
  response = Gateway.new(url).request {|r| r.post(auth_options.to_json, headers)}
52
52
 
53
- @auth_response = OpenStruct.new(JSON.parse(response.body))
53
+ @auth_response = OpenStruct.new(headers: response.headers, body: JSON.parse(response.body))
54
54
  rescue StandardError => e
55
55
  raise Exceptions::ConnectionError.new(e)
56
56
  end
@@ -58,32 +58,52 @@ module NightcrawlerSwift
58
58
  def auth_options
59
59
  {
60
60
  auth: {
61
- tenantName: opts.tenant_name,
62
- passwordCredentials: {username: opts.username, password: opts.password}
61
+ identity: {
62
+ methods: [
63
+ "password"
64
+ ],
65
+ password: {
66
+ user: {
67
+ domain: {
68
+ id: "default"
69
+ },
70
+ name: opts.username,
71
+ password: opts.password
72
+ }
73
+ }
74
+ },
75
+ scope: {
76
+ project: {
77
+ domain: {
78
+ id: "default"
79
+ },
80
+ name: opts.tenant_name
81
+ }
82
+ }
63
83
  }
64
84
  }
65
85
  end
66
86
 
67
87
  def select_token
68
- @token_id = auth_response.access["token"]["id"]
69
- @expires_at = auth_response.access["token"]["expires"]
88
+ @token_id = auth_response.headers[:x_subject_token]
89
+ @expires_at = auth_response.body["token"]["expires_at"]
70
90
  @expires_at = DateTime.parse(@expires_at).to_time
71
91
  end
72
92
 
73
93
  def select_catalog
74
- catalogs = auth_response.access["serviceCatalog"]
94
+ catalogs = auth_response["body"]["token"]["catalog"]
75
95
  @catalog = catalogs.find {|catalog| catalog["type"] == "object-store"}
76
96
  end
77
97
 
78
98
  def select_endpoints
79
99
  raise Exceptions::ConfigurationError.new "No catalog of type 'object-store' found" if @catalog.nil?
80
- @endpoints = @catalog["endpoints"].first
100
+ @endpoints = @catalog["endpoints"]
81
101
  end
82
102
 
83
103
  def configure_urls
84
- @admin_url = opts.admin_url || @endpoints["adminURL"]
85
- @public_url = opts.public_url || @endpoints["publicURL"]
86
- @internal_url = opts.internal_url || @endpoints["internalURL"]
104
+ @admin_url = opts.admin_url || @endpoints.find {|e| e["interface"] == "admin"}["url"]
105
+ @public_url = opts.public_url || @endpoints.find {|e| e["interface"] == "public"}["url"]
106
+ @internal_url = opts.internal_url || @endpoints.find {|e| e["interface"] == "internal"}["url"]
87
107
  @upload_url = "#{@admin_url}/#{opts.bucket}"
88
108
  end
89
109
  end
@@ -1,3 +1,3 @@
1
1
  module NightcrawlerSwift
2
- VERSION = "0.11.1"
2
+ VERSION = "1.0.0"
3
3
  end
@@ -1,62 +1,87 @@
1
1
  {
2
- "access" : {
3
- "serviceCatalog" : [
4
- {
5
- "name" : "swift",
6
- "endpoints_links" : [],
7
- "type" : "object-store",
8
- "endpoints" : [
9
- {
10
- "publicURL" : "http://public-url-com",
11
- "internalURL" : "http://internal-url-com",
12
- "adminURL" : "http://api-url-com",
13
- "region" : "RegionOne",
14
- "id" : "1"
15
- }
16
- ]
17
- },
18
- {
19
- "name" : "keystone",
20
- "endpoints_links" : [],
21
- "type" : "identity",
22
- "endpoints" : [
23
- {
24
- "publicURL" : "http://auth-url-com:123/v2.0",
25
- "internalURL" : "https://auth-url-com:123/v2.0",
26
- "adminURL" : "https://auth-url-com:321/v2.0",
27
- "region" : "RegionOne",
28
- "id" : "2"
29
- }
30
- ]
31
- }
2
+ "headers": {
3
+ "X-Subject-Token": "12345"
4
+ },
5
+ "body": {
6
+ "token": {
7
+ "methods": [
8
+ "password"
32
9
  ],
33
- "user" : {
34
- "roles" : [
10
+ "roles": [
11
+ {
12
+ "id": "3fe2ff9ee4384b1894a90878d3e92bab",
13
+ "name": "_member_"
14
+ },
15
+ {
16
+ "id": "c573d00d11ed4f75a7cae8e7527eb1ed",
17
+ "name": "swiftoperator"
18
+ }
19
+ ],
20
+ "expires_at": "2017-07-06T18:24:31.037559Z",
21
+ "project": {
22
+ "domain": {
23
+ "id": "default",
24
+ "name": "Default"
25
+ },
26
+ "id": "5c6a4110f7f9436b8e1f6696f9f6a13f",
27
+ "name": "tenant_username1"
28
+ },
29
+ "catalog": [
30
+ {
31
+ "name" : "swift",
32
+ "id": "0f7d75e8a91249628ad63356002b4869",
33
+ "type" : "object-store",
34
+ "endpoints" : [
35
+ {
36
+ "region_id": "RegionOne",
37
+ "url": "http://auth-url-com:123/v3/admin",
38
+ "region": "RegionOne",
39
+ "interface": "admin",
40
+ "id": "a723954cc89d3e93a65c1f658132773d"
41
+ },
35
42
  {
36
- "name" : "swiftoperator"
43
+ "region_id": "RegionOne",
44
+ "url": "http://auth-url-com:123/v3/internal",
45
+ "region": "RegionOne",
46
+ "interface": "internal",
47
+ "id": "beea797b69fa47159e44a220ea05c61c"
48
+ },
49
+ {
50
+ "region_id": "RegionOne",
51
+ "url": "http://auth-url-com:123/v3/public",
52
+ "region": "RegionOne",
53
+ "interface": "public",
54
+ "id": "9e36056aba514263a1d1d8ae10cfb796"
37
55
  }
38
- ],
39
- "roles_links" : [],
40
- "name" : "User Name 1",
41
- "id" : "3",
42
- "username" : "username1"
43
- },
44
- "metadata" : {
45
- "roles" : [
46
- "4"
47
- ],
48
- "is_admin" : 0
56
+ ]
57
+ },
58
+ {
59
+ "name" : "keystone",
60
+ "id" : "7efb509d3a0b446fa324d0bc4503e6d3",
61
+ "type" : "identity",
62
+ "endpoints" : [
63
+ {
64
+ "region_id" : "RegionOne",
65
+ "url" : "http://auth-url-com:123/v3/public",
66
+ "interface": "public",
67
+ "id" : "29e36056aba514263a1d1d8ae10cfb79"
68
+ }
69
+ ]
70
+ }
71
+ ],
72
+ "extras": {},
73
+ "user": {
74
+ "domain": {
75
+ "id": "default",
76
+ "name": "Default"
77
+ },
78
+ "id": "83e2c39492e343f08b0621ddc2e46eab",
79
+ "name": "username1"
49
80
  },
50
- "token" : {
51
- "tenant" : {
52
- "name" : "tenant_username1",
53
- "id" : "5",
54
- "description" : "some desc",
55
- "enabled" : true
56
- },
57
- "issued_at" : "2014-08-25T17:53:26.667691",
58
- "id" : "5",
59
- "expires" : "2014-08-25T18:53:26Z"
60
- }
61
- }
81
+ "audit_ids": [
82
+ "B77HzuC7QimfKre8DhDrhw"
83
+ ],
84
+ "issued_at": "2017-07-06T17:24:31.037629Z"
85
+ }
86
+ }
62
87
  }
@@ -25,7 +25,7 @@ describe NightcrawlerSwift::Delete do
25
25
 
26
26
  context "success" do
27
27
  let :response do
28
- double(:response, code: 200)
28
+ double(:response, code: 204)
29
29
  end
30
30
 
31
31
  before do
@@ -42,6 +42,20 @@ describe NightcrawlerSwift::Delete do
42
42
  end
43
43
  end
44
44
 
45
+ context "failure" do
46
+ let :response do
47
+ double(:response, code: 404)
48
+ end
49
+
50
+ before do
51
+ allow(subject).to receive(:delete).and_return(response)
52
+ end
53
+
54
+ it "returns false" do
55
+ expect(execute).to eql false
56
+ end
57
+ end
58
+
45
59
  context "when the path was not informed" do
46
60
  it "raises NightcrawlerSwift::Exceptions::ValidationError" do
47
61
  expect { subject.execute nil }.to raise_error NightcrawlerSwift::Exceptions::ValidationError
@@ -165,6 +165,13 @@ describe NightcrawlerSwift::Upload do
165
165
  let(:response) { double(:response, code: 500) }
166
166
  it { expect(execute).to be false }
167
167
  end
168
+
169
+ context "when the path was not informed" do
170
+ it "raises NightcrawlerSwift::Exceptions::ValidationError" do
171
+ expect { subject.execute(nil, file) }.to raise_error NightcrawlerSwift::Exceptions::ValidationError
172
+ expect { subject.execute("", file) }.to raise_error NightcrawlerSwift::Exceptions::ValidationError
173
+ end
174
+ end
168
175
  end
169
176
 
170
177
  end
@@ -8,7 +8,7 @@ describe NightcrawlerSwift::Connection do
8
8
  tenant_name: "tenant_username1",
9
9
  username: "username1",
10
10
  password: "some-pass",
11
- auth_url: "https://auth-url-com:123/v2.0/tokens",
11
+ auth_url: "https://auth-url-com:123/v3/auth/tokens",
12
12
  max_age: 31536000 # 1 year
13
13
  }
14
14
  end
@@ -30,19 +30,48 @@ describe NightcrawlerSwift::Connection do
30
30
  let :auth_json do
31
31
  {
32
32
  auth: {
33
- tenantName: opts[:tenant_name],
34
- passwordCredentials: {username: opts[:username], password: opts[:password]}
33
+ identity: {
34
+ methods: [
35
+ "password"
36
+ ],
37
+ password: {
38
+ user: {
39
+ domain: {
40
+ id: "default"
41
+ },
42
+ name: opts[:username],
43
+ password: opts[:password]
44
+ }
45
+ }
46
+ },
47
+ scope: {
48
+ project: {
49
+ domain: {
50
+ id: "default"
51
+ },
52
+ name: opts[:tenant_name]
53
+ }
54
+ }
35
55
  }
36
56
  }.to_json
37
57
  end
38
58
 
39
59
  let :auth_success_response do
40
60
  path = File.join(File.dirname(__FILE__), "../..", "fixtures/auth_success.json")
41
- OpenStruct.new(body: File.read(File.expand_path(path)))
61
+ file_contents = JSON.parse(File.read(File.expand_path(path)))
62
+ headers = file_contents["headers"].reduce({}) do |h, item|
63
+ key, value = item
64
+ h[key.downcase.gsub("-", "_").to_sym] = value
65
+ h
66
+ end
67
+ OpenStruct.new(headers: headers, body: file_contents["body"].to_json)
42
68
  end
43
69
 
44
70
  let :auth_success_json do
45
- JSON.parse(auth_success_response.body)
71
+ {
72
+ "headers" => auth_success_response.headers,
73
+ "body" => JSON.parse(auth_success_response.body)
74
+ }
46
75
  end
47
76
 
48
77
  describe "when it connects" do
@@ -61,48 +90,55 @@ describe NightcrawlerSwift::Connection do
61
90
  and_return(auth_success_response)
62
91
  end
63
92
 
64
- it "stores the auth_response" do
93
+ it "stores the auth response body" do
65
94
  subject.connect!
66
95
  # This test uses 'eq' instead of 'eql' because in Ruby 1.9.x the method
67
96
  # 'equal?' is different than '==' making this test fail
68
- expect(subject.auth_response).to eq(OpenStruct.new(auth_success_json))
97
+ expect(subject.auth_response.body).to eq(auth_success_json["body"])
98
+ end
99
+
100
+ it "stores the auth response headers" do
101
+ subject.connect!
102
+ expect(subject.auth_response.headers).to eq(auth_success_json["headers"])
69
103
  end
70
104
 
71
105
  it "stores the token id" do
72
106
  subject.connect!
73
- expect(subject.token_id).to eql(auth_success_json["access"]["token"]["id"])
107
+ expect(subject.token_id).not_to be_nil
108
+ expect(subject.token_id).to eql(auth_success_json["headers"][:x_subject_token])
74
109
  end
75
110
 
76
111
  it "stores the expires_at" do
77
112
  subject.connect!
78
- expires_at = DateTime.parse(auth_success_json["access"]["token"]["expires"]).to_time
113
+ expires_at = DateTime.parse(auth_success_json["body"]["token"]["expires_at"]).to_time
79
114
  expect(subject.expires_at).to eql(expires_at)
80
115
  end
81
116
 
82
117
  it "stores the catalog" do
83
- expect(subject).to receive(:connect!).and_call_original
84
- expect(subject.catalog).to eql(auth_success_json["access"]["serviceCatalog"][0])
118
+ subject.connect!
119
+ expect(subject.catalog).to eql(auth_success_json["body"]["token"]["catalog"][0])
120
+ expect(subject.catalog["type"]).to eql("object-store")
85
121
  end
86
122
 
87
123
  it "stores the admin_url" do
88
- expect(subject).to receive(:connect!).and_call_original
89
- expect(subject.admin_url).to eql(auth_success_json["access"]["serviceCatalog"].first["endpoints"].first["adminURL"])
124
+ subject.connect!
125
+ expect(subject.admin_url).to eql(auth_success_json["body"]["token"]["catalog"][0]["endpoints"][0]["url"])
90
126
  end
91
127
 
92
128
  it "stores the upload_url" do
129
+ subject.connect!
93
130
  admin_url = subject.admin_url
94
- expect(subject).to receive(:connect!).and_call_original
95
131
  expect(subject.upload_url).to eql("#{admin_url}/#{opts[:bucket]}")
96
132
  end
97
133
 
98
134
  it "stores the public_url" do
99
- expect(subject).to receive(:connect!).and_call_original
100
- expect(subject.public_url).to eql(auth_success_json["access"]["serviceCatalog"].first["endpoints"].first["publicURL"])
135
+ subject.connect!
136
+ expect(subject.public_url).to eql(auth_success_json["body"]["token"]["catalog"][0]["endpoints"][2]["url"])
101
137
  end
102
138
 
103
139
  it "stores the internal_url" do
104
- expect(subject).to receive(:connect!).and_call_original
105
- expect(subject.internal_url).to eql(auth_success_json["access"]["serviceCatalog"].first["endpoints"].first["internalURL"])
140
+ subject.connect!
141
+ expect(subject.internal_url).to eql(auth_success_json["body"]["token"]["catalog"][0]["endpoints"][1]["url"])
106
142
  end
107
143
 
108
144
  it "returns self" do
@@ -111,7 +147,7 @@ describe NightcrawlerSwift::Connection do
111
147
 
112
148
  context "and there isn't any catalog configured" do
113
149
  before do
114
- auth_success_json["access"]["serviceCatalog"] = []
150
+ auth_success_json["body"]["token"]["catalog"] = []
115
151
  allow(subject).to receive(:auth_response).and_return(OpenStruct.new(auth_success_json))
116
152
  end
117
153
 
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.11.1
4
+ version: 1.0.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: 2016-10-19 00:00:00.000000000 Z
12
+ date: 2017-08-22 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rest-client
@@ -230,7 +230,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
230
230
  version: '0'
231
231
  requirements: []
232
232
  rubyforge_project:
233
- rubygems_version: 2.5.1
233
+ rubygems_version: 2.5.2
234
234
  signing_key:
235
235
  specification_version: 4
236
236
  summary: Like the X-Men nightcrawler this gem teleports your assets to a OpenStack