stacktor 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 +7 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +1 -0
- data/lib/stacktor/core/client.rb +51 -0
- data/lib/stacktor/core/request.rb +116 -0
- data/lib/stacktor/core/resource.rb +42 -0
- data/lib/stacktor/identity/v2/client.rb +50 -0
- data/lib/stacktor/identity/v2/token.rb +36 -0
- data/lib/stacktor/swift/v1/client.rb +128 -0
- data/lib/stacktor/swift/v1/container.rb +15 -0
- data/lib/stacktor/swift/v1/container_object.rb +104 -0
- data/lib/stacktor/version.rb +3 -0
- data/lib/stacktor.rb +18 -0
- data/stacktor.gemspec +25 -0
- metadata +102 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: a7d9fb1b2d3e7ed6030c1dbe01e5c1b25e25a3ec
|
4
|
+
data.tar.gz: 391609f9697ddba50c6df80e20a175ba40e74397
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 83a19c0415ddd2fc15292bcd7c7e23d60c4cd8fa9842bd94095865ad43cdf32ff0d1c4bd771568fe5f3f052e12ce16ec3c3537ababa477aafe43076b07cf6aab
|
7
|
+
data.tar.gz: 97004fc01eb339a298d002d7ab8fe854f75dd86c13d44e8e9dff45eaeac815fbb026cda67c89a1808b0873dad50299560ab277b57bf89336ab23a3cc988341de
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 TODO: Write your name
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# Stacktor
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'stacktor'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install stacktor
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
TODO: Write usage instructions here
|
22
|
+
|
23
|
+
## Contributing
|
24
|
+
|
25
|
+
1. Fork it ( http://github.com/<my-github-username>/stacktor/fork )
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Stacktor
|
2
|
+
|
3
|
+
module Core
|
4
|
+
|
5
|
+
class Client
|
6
|
+
|
7
|
+
def initialize(options={})
|
8
|
+
@settings = options
|
9
|
+
end
|
10
|
+
|
11
|
+
def settings
|
12
|
+
@settings
|
13
|
+
end
|
14
|
+
|
15
|
+
def before_request(&block)
|
16
|
+
@before_request_fn = block
|
17
|
+
end
|
18
|
+
|
19
|
+
def url
|
20
|
+
@settings[:url]
|
21
|
+
end
|
22
|
+
|
23
|
+
def url=(val)
|
24
|
+
@settings[:url] = val
|
25
|
+
end
|
26
|
+
|
27
|
+
##
|
28
|
+
# Executes request, running any handlers beforehand
|
29
|
+
# and setting headers as necessary
|
30
|
+
#
|
31
|
+
# params:
|
32
|
+
# req - request to process
|
33
|
+
def execute_request(opts)
|
34
|
+
if !@before_request_fn.nil?
|
35
|
+
@before_request_fn.call(opts, self)
|
36
|
+
end
|
37
|
+
opts[:url] = self.url + opts[:path]
|
38
|
+
opts[:headers] = build_headers.merge( (opts[:headers] || {}) )
|
39
|
+
req = Request.new(opts)
|
40
|
+
resp = req.execute
|
41
|
+
end
|
42
|
+
|
43
|
+
def build_headers
|
44
|
+
{}
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
|
3
|
+
module Stacktor
|
4
|
+
|
5
|
+
module Core
|
6
|
+
|
7
|
+
class Request
|
8
|
+
|
9
|
+
def self.connection_for(uri)
|
10
|
+
@connections ||= {}
|
11
|
+
|
12
|
+
host = uri.host
|
13
|
+
port = uri.port
|
14
|
+
secure = uri.scheme == 'https'
|
15
|
+
|
16
|
+
if @connections[ [host, port, secure] ].nil?
|
17
|
+
c = Net::HTTP.new(host, port)
|
18
|
+
c.use_ssl = secure
|
19
|
+
c.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
20
|
+
c.start
|
21
|
+
@connections[ [host, port, secure] ] = c
|
22
|
+
else
|
23
|
+
c = @connections[ [host, port, secure] ]
|
24
|
+
end
|
25
|
+
return c
|
26
|
+
end
|
27
|
+
|
28
|
+
def initialize(opts)
|
29
|
+
@options = opts
|
30
|
+
end
|
31
|
+
|
32
|
+
def options
|
33
|
+
@options
|
34
|
+
end
|
35
|
+
|
36
|
+
def url
|
37
|
+
@options[:url]
|
38
|
+
end
|
39
|
+
def method
|
40
|
+
@options[:method]
|
41
|
+
end
|
42
|
+
def headers
|
43
|
+
@options[:headers]
|
44
|
+
end
|
45
|
+
def data
|
46
|
+
@options[:data]
|
47
|
+
end
|
48
|
+
def response=(resp)
|
49
|
+
@resp = resp
|
50
|
+
end
|
51
|
+
def response
|
52
|
+
@resp
|
53
|
+
end
|
54
|
+
def do_stream_response?
|
55
|
+
!@options[:response_handler].nil?
|
56
|
+
end
|
57
|
+
|
58
|
+
def success?
|
59
|
+
@resp && !@resp.code.match(/^20.$/).nil?
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
def execute
|
64
|
+
data = self.data
|
65
|
+
uri = URI(self.url)
|
66
|
+
conn = self.class.connection_for(uri)
|
67
|
+
req_kls = Net::HTTP.const_get(self.method.capitalize)
|
68
|
+
headers = self.headers
|
69
|
+
resp_fn = @options[:response_handler]
|
70
|
+
|
71
|
+
if self.method == "GET"
|
72
|
+
uri.query = data.to_query unless data.nil?
|
73
|
+
req = req_kls.new(uri.request_uri, headers)
|
74
|
+
else
|
75
|
+
data_reg = data_stream = nil
|
76
|
+
if data.is_a?(Hash)
|
77
|
+
data_reg = data.to_json
|
78
|
+
elsif data.respond_to?(:read)
|
79
|
+
data_stream = data
|
80
|
+
headers['Content-Length'] = data.size.to_s
|
81
|
+
else
|
82
|
+
data_reg = data
|
83
|
+
end
|
84
|
+
req = req_kls.new(uri.path, headers)
|
85
|
+
req.body_stream = data_stream unless data_stream.nil?
|
86
|
+
req.body = data_reg unless data_reg.nil?
|
87
|
+
end
|
88
|
+
if resp_fn.nil?
|
89
|
+
@resp = conn.request(req)
|
90
|
+
else
|
91
|
+
@resp = conn.request(req) do |r|
|
92
|
+
r.read_body do |bytes|
|
93
|
+
resp_fn.call(bytes)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
return self.to_response_hash
|
98
|
+
end
|
99
|
+
|
100
|
+
def to_response_hash
|
101
|
+
return nil if @resp.nil?
|
102
|
+
success = self.success?
|
103
|
+
ret = {success: success, code: @resp.code, request: self, response: @resp}
|
104
|
+
if self.do_stream_response? && success
|
105
|
+
ret[:body] = nil
|
106
|
+
else
|
107
|
+
ret[:body] = @resp.body
|
108
|
+
end
|
109
|
+
return ret
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Stacktor
|
2
|
+
|
3
|
+
module Core
|
4
|
+
|
5
|
+
class Resource
|
6
|
+
|
7
|
+
attr_accessor :data, :client
|
8
|
+
|
9
|
+
def initialize(data, client, opts={})
|
10
|
+
@client = client
|
11
|
+
self.handle_data(data, opts)
|
12
|
+
end
|
13
|
+
|
14
|
+
def handle_data(data, opts={})
|
15
|
+
if data.is_a?(String)
|
16
|
+
data = JSON.parse(data)
|
17
|
+
end
|
18
|
+
@data = data || {}
|
19
|
+
@options = opts
|
20
|
+
@options[:headers] ||= {}
|
21
|
+
end
|
22
|
+
|
23
|
+
def [](field)
|
24
|
+
@data[field.to_s] || @options[:headers][field.to_s]
|
25
|
+
end
|
26
|
+
def []=(field,val)
|
27
|
+
@data[field.to_s]=val
|
28
|
+
end
|
29
|
+
|
30
|
+
def headers
|
31
|
+
@options[:headers]
|
32
|
+
end
|
33
|
+
|
34
|
+
def method_missing(method, *args, &block)
|
35
|
+
return self[method]
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
|
2
|
+
module Stacktor
|
3
|
+
|
4
|
+
module Identity
|
5
|
+
|
6
|
+
module V2
|
7
|
+
|
8
|
+
class Client < Stacktor::Core::Client
|
9
|
+
|
10
|
+
def authenticate_token(opts)
|
11
|
+
path = "/tokens"
|
12
|
+
data = {
|
13
|
+
auth: {
|
14
|
+
tenantId: opts[:tenant_id],
|
15
|
+
passwordCredentials: {
|
16
|
+
username: opts[:username],
|
17
|
+
password: opts[:password]
|
18
|
+
}
|
19
|
+
}
|
20
|
+
}
|
21
|
+
resp = self.execute_request(
|
22
|
+
path: path,
|
23
|
+
method: "POST",
|
24
|
+
data: data
|
25
|
+
)
|
26
|
+
parse_token(resp)
|
27
|
+
return resp
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def build_headers
|
33
|
+
{
|
34
|
+
'Content-Type' => 'application/json'
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
def parse_token(resp)
|
39
|
+
if resp[:success]
|
40
|
+
resp[:token] = Token.new(resp[:body], self)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Stacktor
|
2
|
+
|
3
|
+
module Identity
|
4
|
+
|
5
|
+
module V2
|
6
|
+
|
7
|
+
class Token < Core::Resource
|
8
|
+
|
9
|
+
def id
|
10
|
+
self.data["access"]["token"]["id"]
|
11
|
+
end
|
12
|
+
def expires_at
|
13
|
+
str = self.data["access"]["token"]["expires"]
|
14
|
+
Time.parse(str)
|
15
|
+
end
|
16
|
+
def expired?
|
17
|
+
self.expires_at < Time.now
|
18
|
+
end
|
19
|
+
|
20
|
+
def valid?
|
21
|
+
!self.expired?
|
22
|
+
end
|
23
|
+
|
24
|
+
def endpoint_url_for_service_type(type, level=:public)
|
25
|
+
svc = self.data['access']['serviceCatalog'].select{|s| s['type'] == type}.first
|
26
|
+
return nil if svc.nil?
|
27
|
+
return svc['endpoints'][0]["#{level.to_s}URL"]
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
module Stacktor
|
2
|
+
|
3
|
+
module Swift
|
4
|
+
|
5
|
+
module V1
|
6
|
+
|
7
|
+
class Client < Stacktor::Core::Client
|
8
|
+
|
9
|
+
def list_containers(opts={})
|
10
|
+
path = "/"
|
11
|
+
opts[:format] = 'json'
|
12
|
+
resp = self.execute_request(
|
13
|
+
path: path,
|
14
|
+
method: "GET",
|
15
|
+
data: opts
|
16
|
+
)
|
17
|
+
parse_containers(resp)
|
18
|
+
return resp
|
19
|
+
end
|
20
|
+
|
21
|
+
## HELPERS
|
22
|
+
|
23
|
+
def get_object_content(opts, &resp_fn)
|
24
|
+
ctn = opts[:container_name]
|
25
|
+
obn = opts[:object_name]
|
26
|
+
|
27
|
+
resp = self.execute_request(
|
28
|
+
path: "/#{ctn}/#{obn}",
|
29
|
+
method: "GET",
|
30
|
+
response_handler: resp_fn
|
31
|
+
)
|
32
|
+
parse_object(resp, {'name' => obn, 'container_name' => ctn})
|
33
|
+
return resp
|
34
|
+
end
|
35
|
+
|
36
|
+
def create_object(opts)
|
37
|
+
ctn = opts[:container_name]
|
38
|
+
obn = opts[:object_name]
|
39
|
+
if opts[:content].is_a?(String)
|
40
|
+
body = StringIO.new(opts[:content])
|
41
|
+
else
|
42
|
+
body = opts[:content]
|
43
|
+
end
|
44
|
+
|
45
|
+
headers = {}
|
46
|
+
if opts[:content_type].nil?
|
47
|
+
headers['X-Detect-Content-Type'] = 'true'
|
48
|
+
else
|
49
|
+
headers['Content-Type'] = opts[:content_type]
|
50
|
+
end
|
51
|
+
if !opts[:metadata].nil?
|
52
|
+
opts[:metadata].each do |k,v|
|
53
|
+
headers["X-Object-Meta-#{k}"] = v
|
54
|
+
end
|
55
|
+
end
|
56
|
+
resp = self.execute_request(
|
57
|
+
path: "/#{ctn}/#{obn}",
|
58
|
+
method: "PUT",
|
59
|
+
headers: headers,
|
60
|
+
data: body
|
61
|
+
)
|
62
|
+
parse_object(resp, {'name' => obn, 'container_name' => ctn})
|
63
|
+
resp[:object].reload if resp[:object]
|
64
|
+
return resp
|
65
|
+
end
|
66
|
+
|
67
|
+
def delete_object(opts)
|
68
|
+
ctn = opts[:container_name]
|
69
|
+
obn = opts[:object_name]
|
70
|
+
|
71
|
+
resp = self.execute_request(
|
72
|
+
path: "/#{ctn}/#{obn}",
|
73
|
+
method: "DELETE"
|
74
|
+
)
|
75
|
+
parse_object(resp, {'name' => obn, 'container_name' => ctn})
|
76
|
+
return resp
|
77
|
+
end
|
78
|
+
|
79
|
+
def get_object_metadata(opts)
|
80
|
+
ctn = opts[:container_name]
|
81
|
+
obn = opts[:object_name]
|
82
|
+
|
83
|
+
resp = self.execute_request(
|
84
|
+
path: "/#{ctn}/#{obn}",
|
85
|
+
method: "HEAD"
|
86
|
+
)
|
87
|
+
parse_object(resp, {'name' => obn, 'container_name' => ctn})
|
88
|
+
return resp
|
89
|
+
end
|
90
|
+
|
91
|
+
def token=(val)
|
92
|
+
@settings[:token] = val
|
93
|
+
end
|
94
|
+
def token
|
95
|
+
@settings[:token]
|
96
|
+
end
|
97
|
+
def has_valid_token?
|
98
|
+
@settings[:token] && @settings[:token].valid?
|
99
|
+
end
|
100
|
+
|
101
|
+
private
|
102
|
+
|
103
|
+
def parse_containers(resp)
|
104
|
+
if resp[:success]
|
105
|
+
resp[:containers] = JSON.parse(resp[:body]).collect {|c| Container.new(c, self)}
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def parse_object(resp, data={})
|
110
|
+
r = resp[:response]
|
111
|
+
if resp[:success]
|
112
|
+
resp[:object] = ContainerObject.new(data, self, headers: r)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def build_headers
|
117
|
+
{
|
118
|
+
'X-Auth-Token' => self.settings[:token].id
|
119
|
+
}
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
module Stacktor
|
2
|
+
|
3
|
+
module Swift
|
4
|
+
|
5
|
+
module V1
|
6
|
+
|
7
|
+
class ContainerObject < Core::Resource
|
8
|
+
|
9
|
+
def name
|
10
|
+
data['name']
|
11
|
+
end
|
12
|
+
|
13
|
+
def container_name
|
14
|
+
data['container_name']
|
15
|
+
end
|
16
|
+
|
17
|
+
def etag
|
18
|
+
data['hash'] || headers['ETag']
|
19
|
+
end
|
20
|
+
|
21
|
+
def content_length
|
22
|
+
bytes = data['bytes'] || headers['Content-Length']
|
23
|
+
bytes ? bytes.to_i : nil
|
24
|
+
end
|
25
|
+
|
26
|
+
def content_type
|
27
|
+
type = data['content_type'] || headers['Content-Type']
|
28
|
+
return nil if type.nil?
|
29
|
+
return type.split(";").first
|
30
|
+
end
|
31
|
+
|
32
|
+
def last_modified
|
33
|
+
t = data['last_modified'] || headers['Last-Modified']
|
34
|
+
return nil if t.nil?
|
35
|
+
return Time.parse(t)
|
36
|
+
end
|
37
|
+
|
38
|
+
def metadata
|
39
|
+
ret = {}
|
40
|
+
headers.each do |k,v|
|
41
|
+
h = k.downcase.strip
|
42
|
+
if h.start_with?("x-object-meta-")
|
43
|
+
mk = h.split('-').last
|
44
|
+
ret[mk] = v
|
45
|
+
end
|
46
|
+
end
|
47
|
+
return ret
|
48
|
+
end
|
49
|
+
|
50
|
+
## TRANSACTIONS
|
51
|
+
|
52
|
+
def read
|
53
|
+
result = @client.get_object_content(container_name: self.container_name, object_name: self.name)
|
54
|
+
if result[:success]
|
55
|
+
return result[:body]
|
56
|
+
else
|
57
|
+
raise result[:body]
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def stream(&block)
|
62
|
+
result = @client.get_object_content(container_name: self.container_name, object_name: self.name) do |bytes|
|
63
|
+
block.call(bytes)
|
64
|
+
end
|
65
|
+
if result[:success]
|
66
|
+
return result[:body]
|
67
|
+
else
|
68
|
+
raise result[:body]
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def write_to_file(path)
|
73
|
+
File.open(path, 'wb') do |fw|
|
74
|
+
self.stream do |bytes|
|
75
|
+
fw.write bytes
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def reload
|
81
|
+
result = @client.get_object_metadata(container_name: self.container_name, object_name: self.name)
|
82
|
+
if result[:success]
|
83
|
+
self.handle_data(result[:body], headers: result[:response])
|
84
|
+
else
|
85
|
+
raise result[:body]
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def delete
|
90
|
+
result = @client.delete_object(container_name: self.container_name, object_name: self.name)
|
91
|
+
if result[:success]
|
92
|
+
return result
|
93
|
+
else
|
94
|
+
raise result[:body]
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
data/lib/stacktor.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'time'
|
3
|
+
require 'active_support/all'
|
4
|
+
require 'stringio'
|
5
|
+
|
6
|
+
require "stacktor/version"
|
7
|
+
require "stacktor/core/request"
|
8
|
+
require "stacktor/core/resource"
|
9
|
+
require "stacktor/core/client"
|
10
|
+
require "stacktor/identity/v2/client"
|
11
|
+
require "stacktor/identity/v2/token"
|
12
|
+
require "stacktor/swift/v1/client"
|
13
|
+
require "stacktor/swift/v1/container"
|
14
|
+
require "stacktor/swift/v1/container_object"
|
15
|
+
|
16
|
+
module Stacktor
|
17
|
+
# Your code goes here...
|
18
|
+
end
|
data/stacktor.gemspec
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'stacktor/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "stacktor"
|
8
|
+
spec.version = Stacktor::VERSION
|
9
|
+
spec.authors = ["Alan Graham"]
|
10
|
+
spec.email = ["alan@productlab.com"]
|
11
|
+
spec.summary = %q{A more structured gem for communicating with OpenStack.}
|
12
|
+
spec.description = %q{A more structured gem for communicating with OpenStack.}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency 'activesupport'
|
22
|
+
|
23
|
+
spec.add_development_dependency "bundler", "~> 1.5"
|
24
|
+
spec.add_development_dependency "rake"
|
25
|
+
end
|
metadata
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: stacktor
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Alan Graham
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-02-25 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activesupport
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.5'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.5'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: A more structured gem for communicating with OpenStack.
|
56
|
+
email:
|
57
|
+
- alan@productlab.com
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- .gitignore
|
63
|
+
- Gemfile
|
64
|
+
- LICENSE.txt
|
65
|
+
- README.md
|
66
|
+
- Rakefile
|
67
|
+
- lib/stacktor.rb
|
68
|
+
- lib/stacktor/core/client.rb
|
69
|
+
- lib/stacktor/core/request.rb
|
70
|
+
- lib/stacktor/core/resource.rb
|
71
|
+
- lib/stacktor/identity/v2/client.rb
|
72
|
+
- lib/stacktor/identity/v2/token.rb
|
73
|
+
- lib/stacktor/swift/v1/client.rb
|
74
|
+
- lib/stacktor/swift/v1/container.rb
|
75
|
+
- lib/stacktor/swift/v1/container_object.rb
|
76
|
+
- lib/stacktor/version.rb
|
77
|
+
- stacktor.gemspec
|
78
|
+
homepage: ''
|
79
|
+
licenses:
|
80
|
+
- MIT
|
81
|
+
metadata: {}
|
82
|
+
post_install_message:
|
83
|
+
rdoc_options: []
|
84
|
+
require_paths:
|
85
|
+
- lib
|
86
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - '>='
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0'
|
91
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - '>='
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0'
|
96
|
+
requirements: []
|
97
|
+
rubyforge_project:
|
98
|
+
rubygems_version: 2.0.14
|
99
|
+
signing_key:
|
100
|
+
specification_version: 4
|
101
|
+
summary: A more structured gem for communicating with OpenStack.
|
102
|
+
test_files: []
|