occi 3.0.0 → 3.1.0.beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +0 -1
- data/.travis.yml +26 -2
- data/Gemfile +5 -2
- data/Gemfile.lock +42 -26
- data/README.md +64 -4
- data/Rakefile +7 -3
- data/bin/occi +15 -58
- data/config/warble.rb +151 -0
- data/doc/macosx.md +27 -0
- data/examples/dsl_example.rb +16 -7
- data/examples/x509auth_example.rb +13 -7
- data/ext/mkrf_conf.rb +4 -3
- data/features/common/step_definitions/common_steps.rb +9 -9
- data/lib/occi/api/client/client_amqp.rb +25 -14
- data/lib/occi/api/client/client_http.rb +173 -156
- data/lib/occi/api/client/http/authn_utils.rb +82 -0
- data/lib/occi/bin/helpers.rb +84 -26
- data/lib/occi/bin/occi_opts.rb +166 -48
- data/lib/occi/version.rb +1 -1
- data/occi.gemspec +1 -1
- data/spec/occi/api/client/client_amqp_spec.rb +6 -3
- data/spec/occi/api/client/client_http_spec.rb +16 -16
- data/spec/occi/api/client/http/authn_utils_spec.rb +55 -0
- data/spec/occi/api/client/http/httparty_fix_spec.rb +0 -0
- data/spec/occi/api/client/http/net_http_fix_spec.rb +0 -0
- data/spec/occi/api/client/http/rocci-cred-cert.pem +3 -0
- data/spec/occi/api/client/http/rocci-cred-key-jruby.pem +3 -0
- data/spec/occi/api/client/http/rocci-cred-key.pem +3 -0
- data/spec/occi/api/client/http/rocci-cred.p12 +0 -0
- data/spec/occi/bin/helpers_spec.rb +12 -0
- data/spec/occi/bin/occi_opts_spec.rb +60 -0
- data/spec/occi/bin/resource_output_factory_spec.rb +12 -0
- data/spec/spec_helper.rb +26 -0
- metadata +35 -86
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'openssl'
|
2
|
+
|
3
|
+
if defined? JRUBY_VERSION
|
4
|
+
require 'java'
|
5
|
+
end
|
6
|
+
|
7
|
+
module Occi
|
8
|
+
module Api
|
9
|
+
module Client
|
10
|
+
|
11
|
+
class AuthnUtils
|
12
|
+
# Reads credentials from a PKCS#12 compliant file. Returns
|
13
|
+
# X.509 certificate and decrypted private key in PEM
|
14
|
+
# formatted string.
|
15
|
+
#
|
16
|
+
# @example
|
17
|
+
# extract_pem_from_pkcs12 "~/.globus/usercert.p12", "123456"
|
18
|
+
# # => #<String>
|
19
|
+
#
|
20
|
+
# @param [String] Path to a PKCS#12 file with credentials
|
21
|
+
# @param [String] Password needed to unlock the PKCS#12 file
|
22
|
+
# @return [String] Decrypted credentials in a PEM formatted string
|
23
|
+
def self.extract_pem_from_pkcs12(path_to_p12_file, p12_password)
|
24
|
+
# decode certificate and its private key
|
25
|
+
pem_from_pkcs12 = ""
|
26
|
+
if defined? JRUBY_VERSION
|
27
|
+
# Java-based Ruby, read PKCS12 manually
|
28
|
+
# using KeyStore
|
29
|
+
keystore = Java::JavaSecurity::KeyStore.getInstance("PKCS12")
|
30
|
+
p12_input_stream = Java::JavaIo::FileInputStream.new(path_to_p12_file)
|
31
|
+
pass_char_array = Java::JavaLang::String.new(p12_password).to_char_array
|
32
|
+
|
33
|
+
# load and unlock PKCS#12 store
|
34
|
+
keystore.load p12_input_stream, pass_char_array
|
35
|
+
|
36
|
+
# read the first certificate and PK
|
37
|
+
cert = keystore.getCertificate("1")
|
38
|
+
pk = keystore.getKey("1", pass_char_array)
|
39
|
+
|
40
|
+
pem_from_pkcs12 << "-----BEGIN CERTIFICATE-----\n"
|
41
|
+
pem_from_pkcs12 << Java::JavaxXmlBind::DatatypeConverter.printBase64Binary(cert.getEncoded())
|
42
|
+
pem_from_pkcs12 << "\n-----END CERTIFICATE-----"
|
43
|
+
|
44
|
+
pem_from_pkcs12 << "\n"
|
45
|
+
|
46
|
+
pem_from_pkcs12 << "-----BEGIN PRIVATE KEY-----\n"
|
47
|
+
pem_from_pkcs12 << Java::JavaxXmlBind::DatatypeConverter.printBase64Binary(pk.getEncoded())
|
48
|
+
pem_from_pkcs12 << "\n-----END PRIVATE KEY-----"
|
49
|
+
else
|
50
|
+
# C-based Ruby, use OpenSSL::PKCS12
|
51
|
+
pkcs12 = OpenSSL::PKCS12.new(
|
52
|
+
File.open(
|
53
|
+
path_to_p12_file,
|
54
|
+
'rb'
|
55
|
+
),
|
56
|
+
p12_password
|
57
|
+
)
|
58
|
+
|
59
|
+
# store cert and private key in a single PEM formatted string
|
60
|
+
pem_from_pkcs12 << pkcs12.certificate.to_pem << pkcs12.key.to_pem
|
61
|
+
end
|
62
|
+
|
63
|
+
pem_from_pkcs12
|
64
|
+
end
|
65
|
+
|
66
|
+
# Reads X.509 certificates from a file to an array.
|
67
|
+
#
|
68
|
+
# @example
|
69
|
+
# certs_to_file_ary "~/.globus/usercert.pem"
|
70
|
+
# # => [#<String>, #<String>, ...]
|
71
|
+
#
|
72
|
+
# @param [String] Path to a PEM file containing certificates
|
73
|
+
# @return [Array<String>] An array of read certificates
|
74
|
+
def self.certs_to_file_ary(ca_file)
|
75
|
+
# TODO: read and separate multiple certificates
|
76
|
+
[] << File.open(ca_file).read
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
data/lib/occi/bin/helpers.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# a bunch of OCCI client helpers for bin/occi
|
2
2
|
|
3
|
-
def helper_list(options)
|
3
|
+
def helper_list(options, output = nil)
|
4
4
|
found = []
|
5
5
|
|
6
6
|
if resource_types.include? options.resource
|
@@ -10,17 +10,23 @@ def helper_list(options)
|
|
10
10
|
Occi::Log.debug "#{options.resource} is a mixin type."
|
11
11
|
found = mixins options.resource
|
12
12
|
else
|
13
|
-
Occi::Log.
|
14
|
-
|
13
|
+
Occi::Log.warn "I have no idea what #{options.resource} is ..."
|
14
|
+
raise "Unknown resource #{options.resource}, there is nothing to list here!"
|
15
15
|
end
|
16
16
|
|
17
|
-
found
|
17
|
+
return found if output.nil?
|
18
|
+
|
19
|
+
if Occi::Bin::ResourceOutputFactory.allowed_resource_types.include? options.resource.to_sym
|
20
|
+
puts output.format(found, :locations, options.resource.to_sym)
|
21
|
+
else
|
22
|
+
Occi::Log.warn "Not printing, the resource type is not supported!"
|
23
|
+
end
|
18
24
|
end
|
19
25
|
|
20
|
-
def helper_describe(options)
|
26
|
+
def helper_describe(options, output = nil)
|
21
27
|
found = []
|
22
28
|
|
23
|
-
if resource_types.include?
|
29
|
+
if resource_types.include?(options.resource) || options.resource.start_with?(options.endpoint) || options.resource.start_with?('/')
|
24
30
|
Occi::Log.debug "#{options.resource} is a resource type or an actual resource."
|
25
31
|
|
26
32
|
found = describe(options.resource)
|
@@ -37,15 +43,37 @@ def helper_describe(options)
|
|
37
43
|
mxn_type,mxn = options.resource.split('#')
|
38
44
|
found << mixin(mxn, mxn_type, true)
|
39
45
|
else
|
40
|
-
Occi::Log.
|
46
|
+
Occi::Log.warn "I have no idea what #{options.resource} is ..."
|
47
|
+
raise "Unknown resource #{options.resource}, there is nothing to describe here!"
|
48
|
+
end
|
49
|
+
|
50
|
+
return found if output.nil?
|
41
51
|
|
42
|
-
|
52
|
+
if options.resource.start_with? options.endpoint
|
53
|
+
# resource contains full endpoint URI
|
54
|
+
# e.g., http://localhost:3300/network/adfgadf-daf5a6df4afadf-adfad65f4ad
|
55
|
+
resource_type = options.resource.split('/')[3].to_sym
|
56
|
+
elsif options.resource.start_with? '/'
|
57
|
+
# resource contains a path relative to endpoint URI
|
58
|
+
# e.g., /network/adfgadf-daf5a6df4afadf-adfad65f4ad
|
59
|
+
resource_type = options.resource.split('/')[1].to_sym
|
60
|
+
elsif mixin_types.include? options.resource.split('#').first
|
61
|
+
# resource contains a mixin with a type
|
62
|
+
# e.g., os_tpl#debian6
|
63
|
+
resource_type = options.resource.split('#').first.to_sym
|
64
|
+
else
|
65
|
+
# resource probably contains RAW resource_type
|
66
|
+
resource_type = options.resource.to_sym
|
43
67
|
end
|
44
68
|
|
45
|
-
|
69
|
+
if Occi::Bin::ResourceOutputFactory.allowed_resource_types.include? resource_type
|
70
|
+
puts output.format(found, :resources, resource_type)
|
71
|
+
else
|
72
|
+
Occi::Log.warn "Not printing, the resource type [#{resource_type.to_s}] is not supported!"
|
73
|
+
end
|
46
74
|
end
|
47
75
|
|
48
|
-
def helper_create(options)
|
76
|
+
def helper_create(options, output = nil)
|
49
77
|
location = nil
|
50
78
|
|
51
79
|
if resource_types.include? options.resource
|
@@ -55,37 +83,67 @@ def helper_create(options)
|
|
55
83
|
res = resource options.resource
|
56
84
|
|
57
85
|
Occi::Log.debug "Creating #{options.resource}:\n#{res.inspect}"
|
58
|
-
Occi::Log.debug "with mixins:#{options.mixin}"
|
59
86
|
|
60
|
-
options.
|
61
|
-
Occi::Log.debug "
|
62
|
-
|
63
|
-
|
87
|
+
if options.links
|
88
|
+
Occi::Log.debug "with links: #{options.links}"
|
89
|
+
|
90
|
+
options.links.each do |link|
|
91
|
+
link = options.endpoint.chomp('/') + link unless link.start_with? options.endpoint
|
92
|
+
|
93
|
+
if link.include? "/storage/"
|
94
|
+
Occi::Log.debug "Adding storagelink to #{options.resource}"
|
95
|
+
res.storagelink link
|
96
|
+
elsif link.include? "/network/"
|
97
|
+
Occi::Log.debug "Adding networkinterface to #{options.resource}"
|
98
|
+
res.networkinterface link
|
99
|
+
else
|
100
|
+
raise "Unknown link type #{link}, stopping here!"
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
if options.mixins
|
106
|
+
Occi::Log.debug "with mixins: #{options.mixins}"
|
107
|
+
|
108
|
+
options.mixins.keys.each do |type|
|
109
|
+
Occi::Log.debug "Adding mixins of type #{type} to #{options.resource}"
|
64
110
|
|
65
|
-
|
66
|
-
|
67
|
-
|
111
|
+
options.mixins[type].each do |name|
|
112
|
+
mxn = mixin name, type
|
113
|
+
|
114
|
+
raise "Unknown mixin #{type}##{name}, stopping here!" if mxn.nil?
|
115
|
+
Occi::Log.debug "Adding mixin #{mxn} to #{options.resource}"
|
116
|
+
res.mixins << mxn
|
117
|
+
end
|
68
118
|
end
|
69
119
|
end
|
70
120
|
|
71
121
|
#TODO: set other attributes
|
72
|
-
res.title = options.
|
122
|
+
res.title = options.attributes[:title]
|
73
123
|
|
74
124
|
Occi::Log.debug "Creating #{options.resource}:\n#{res.inspect}"
|
75
125
|
|
76
126
|
location = create res
|
77
127
|
else
|
78
|
-
Occi::Log.
|
79
|
-
|
128
|
+
Occi::Log.warn "I have no idea what #{options.resource} is ..."
|
129
|
+
raise "Unknown resource #{options.resource}, there is nothing to create here!"
|
80
130
|
end
|
81
131
|
|
82
|
-
location
|
132
|
+
return location if output.nil?
|
133
|
+
|
134
|
+
puts location
|
83
135
|
end
|
84
136
|
|
85
|
-
def helper_delete(options)
|
86
|
-
delete
|
137
|
+
def helper_delete(options, output = nil)
|
138
|
+
if delete(options.resource)
|
139
|
+
Occi::Log.info "Resource #{options.resource} successfully removed!"
|
140
|
+
else
|
141
|
+
raise "Failed to remove resource #{options.resource}!"
|
142
|
+
end
|
143
|
+
|
144
|
+
true
|
87
145
|
end
|
88
146
|
|
89
|
-
def helper_trigger(options)
|
147
|
+
def helper_trigger(options, output = nil)
|
90
148
|
raise "Not yet implemented!"
|
91
|
-
end
|
149
|
+
end
|
data/lib/occi/bin/occi_opts.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
require 'ostruct'
|
2
2
|
require 'optparse'
|
3
|
+
require 'uri'
|
4
|
+
|
3
5
|
require 'occi/bin/resource_output_factory'
|
4
6
|
|
5
7
|
module Occi
|
@@ -12,7 +14,9 @@ module Occi
|
|
12
14
|
ACTIONS = [:list, :describe, :create, :delete, :trigger].freeze
|
13
15
|
LOG_OUTPUTS = [:stdout, :stderr].freeze
|
14
16
|
|
15
|
-
def self.parse(args)
|
17
|
+
def self.parse(args, test_env = false)
|
18
|
+
|
19
|
+
@@quiet = test_env
|
16
20
|
|
17
21
|
options = OpenStruct.new
|
18
22
|
|
@@ -39,13 +43,31 @@ module Occi
|
|
39
43
|
options.auth[:proxy_ca] = nil
|
40
44
|
|
41
45
|
options.output_format = :plain
|
46
|
+
|
47
|
+
options.mixins = nil
|
48
|
+
options.links = nil
|
49
|
+
options.attributes = nil
|
50
|
+
options.context_vars = nil
|
42
51
|
|
43
52
|
# TODO: change media type back to occi+json after the rOCCI-server update
|
44
53
|
#options.media_type = "application/occi+json"
|
45
54
|
options.media_type = "text/plain,text/occi"
|
46
55
|
|
47
56
|
opts = OptionParser.new do |opts|
|
48
|
-
opts.banner =
|
57
|
+
opts.banner = %{Usage: occi [OPTIONS]
|
58
|
+
|
59
|
+
Examples:
|
60
|
+
occi --interactive --endpoint https://localhost:3300/ --auth x509
|
61
|
+
|
62
|
+
occi --endpoint https://localhost:3300/ --action list --resource os_tpl --auth x509
|
63
|
+
|
64
|
+
occi --endpoint https://localhost:3300/ --action list --resource resource_tpl --auth x509
|
65
|
+
|
66
|
+
occi --endpoint https://localhost:3300/ --action describe --resource os_tpl#debian6 --auth x509
|
67
|
+
|
68
|
+
occi --endpoint https://localhost:3300/ --action create --resource compute --mixin os_tpl#debian6 --mixin resource_tpl#small --attributes title="My rOCCI VM" --auth x509
|
69
|
+
|
70
|
+
occi --endpoint https://localhost:3300/ --action delete --resource /compute/65sd4f654sf65g4-s5fg65sfg465sfg-sf65g46sf5g4sdfg --auth x509}
|
49
71
|
|
50
72
|
opts.separator ""
|
51
73
|
opts.separator "Options:"
|
@@ -60,7 +82,7 @@ module Occi
|
|
60
82
|
"--endpoint URI",
|
61
83
|
String,
|
62
84
|
"OCCI server URI, defaults to '#{options.endpoint}'") do |endpoint|
|
63
|
-
options.endpoint = endpoint
|
85
|
+
options.endpoint = URI(endpoint).to_s
|
64
86
|
end
|
65
87
|
|
66
88
|
opts.on("-n",
|
@@ -80,36 +102,56 @@ module Occi
|
|
80
102
|
opts.on("-p",
|
81
103
|
"--password PASSWORD",
|
82
104
|
String,
|
83
|
-
"Password for basic, digest and x509 authentication or an auth. token
|
105
|
+
"Password for basic, digest and x509 authentication or an auth. token from OS Keystone") do |password|
|
84
106
|
options.auth[:password] = password
|
85
107
|
options.auth[:user_cert_password] = password
|
86
108
|
options.auth[:token] = password
|
87
109
|
end
|
88
110
|
|
89
111
|
opts.on("-c",
|
90
|
-
"--ca-path PATH",
|
112
|
+
"--ca-path PATH",
|
113
|
+
String,
|
114
|
+
"Path to CA certificates directory, defaults to '#{options.auth[:ca_path]}'") do |ca_path|
|
115
|
+
raise ArgumentError, "Path specified in --ca-path is not a directory!" unless File.directory? ca_path
|
116
|
+
raise ArgumentError, "Path specified in --ca-path is not readable!" unless File.readable? ca_path
|
117
|
+
|
91
118
|
options.auth[:ca_path] = ca_path
|
92
119
|
end
|
93
120
|
|
94
121
|
opts.on("-f",
|
95
|
-
"--ca-file PATH",
|
122
|
+
"--ca-file PATH",
|
123
|
+
String,
|
124
|
+
"Path to CA certificates in a file") do |ca_file|
|
125
|
+
raise ArgumentError, "File specified in --ca-file is not a file!" unless File.file? ca_file
|
126
|
+
raise ArgumentError, "File specified in --ca-file is not readable!" unless File.readable? ca_file
|
127
|
+
|
96
128
|
options.auth[:ca_file] = ca_file
|
97
129
|
end
|
98
130
|
|
99
131
|
opts.on("-F",
|
100
|
-
"--filter CATEGORY",
|
132
|
+
"--filter CATEGORY",
|
133
|
+
String,
|
134
|
+
"Category type identifier to filter categories from model, must be used together with the -m option") do |filter|
|
101
135
|
options.filter = filter
|
102
136
|
end
|
103
137
|
|
104
138
|
opts.on("-x",
|
105
|
-
"--user-cred
|
139
|
+
"--user-cred FILE",
|
106
140
|
String,
|
107
141
|
"Path to user's x509 credentials, defaults to '#{options.auth[:user_cert]}'") do |user_cred|
|
142
|
+
raise ArgumentError, "File specified in --user-cred is not a file!" unless File.file? user_cred
|
143
|
+
raise ArgumentError, "File specified in --user-cred is not readable!" unless File.readable? user_cred
|
144
|
+
|
108
145
|
options.auth[:user_cert] = user_cred
|
109
146
|
end
|
110
147
|
|
111
148
|
opts.on("-X",
|
112
|
-
"--proxy-ca
|
149
|
+
"--proxy-ca FILE",
|
150
|
+
String,
|
151
|
+
"Path to a file with GSI proxy's CA certificate(s)") do |proxy_ca|
|
152
|
+
raise ArgumentError, "File specified in --proxy-ca is not a file!" unless File.file? proxy_ca
|
153
|
+
raise ArgumentError, "File specified in --proxy-ca is not readable!" unless File.readable? proxy_ca
|
154
|
+
|
113
155
|
options.auth[:proxy_ca] = proxy_ca
|
114
156
|
end
|
115
157
|
|
@@ -128,10 +170,31 @@ module Occi
|
|
128
170
|
end
|
129
171
|
|
130
172
|
opts.on("-t",
|
131
|
-
"--
|
132
|
-
|
133
|
-
"
|
134
|
-
options.
|
173
|
+
"--attributes ATTRS",
|
174
|
+
Array,
|
175
|
+
"Comma separated attributes for new resources such as title=\"Name\", required") do |attributes|
|
176
|
+
options.attributes = {}
|
177
|
+
|
178
|
+
attributes.each do |attribute|
|
179
|
+
ary = /^(.+?)=(.+)$/.match(attribute).to_a.drop 1
|
180
|
+
raise ArgumentError, "Attributes must always contain ATTR=VALUE pairs!" if ary.length != 2
|
181
|
+
|
182
|
+
options.attributes[ary[0].to_sym] = ary[1]
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
opts.on("-T",
|
187
|
+
"--context CTX_VARS",
|
188
|
+
Array,
|
189
|
+
"Comma separated context variables for new compute resources such as SSH_KEY=\"ssh-rsa dfsdf...adfdf== user@localhost\"") do |context|
|
190
|
+
options.context_vars = {}
|
191
|
+
|
192
|
+
context.each do |ctx|
|
193
|
+
ary = /^(.+?)=(.+)$/.match(ctx).to_a.drop 1
|
194
|
+
raise ArgumentError, "Context variables must always contain ATTR=VALUE pairs!" if ary.length != 2
|
195
|
+
|
196
|
+
options.context_vars[ary[0].to_sym] = ary[1]
|
197
|
+
end
|
135
198
|
end
|
136
199
|
|
137
200
|
opts.on("-a",
|
@@ -149,9 +212,21 @@ module Occi
|
|
149
212
|
|
150
213
|
raise "Unknown mixin format! Use TYPE#NAME!" unless parts.length == 2
|
151
214
|
|
152
|
-
options.
|
153
|
-
options.
|
154
|
-
options.
|
215
|
+
options.mixins = {} if options.mixins.nil?
|
216
|
+
options.mixins[parts[0]] = [] if options.mixins[parts[0]].nil?
|
217
|
+
options.mixins[parts[0]] << parts[1]
|
218
|
+
end
|
219
|
+
|
220
|
+
opts.on("-j",
|
221
|
+
"--link URI",
|
222
|
+
String,
|
223
|
+
"Link specified resource to the resource being created, only for action CREATE and resource COMPUTE") do |link|
|
224
|
+
link_relative_path = URI(link).path
|
225
|
+
|
226
|
+
raise ArgumentError, "Specified link URI is not valid!" unless link_relative_path.start_with? '/'
|
227
|
+
|
228
|
+
options.links = [] if options.links.nil?
|
229
|
+
options.links << link_relative_path
|
155
230
|
end
|
156
231
|
|
157
232
|
opts.on("-g",
|
@@ -198,68 +273,111 @@ module Occi
|
|
198
273
|
opts.on_tail("-h",
|
199
274
|
"--help",
|
200
275
|
"Show this message") do
|
201
|
-
|
202
|
-
|
276
|
+
if @@quiet
|
277
|
+
exit true
|
278
|
+
else
|
279
|
+
puts opts
|
280
|
+
exit! true
|
281
|
+
end
|
203
282
|
end
|
204
283
|
|
205
284
|
opts.on_tail("-v",
|
206
285
|
"--version",
|
207
286
|
"Show version") do
|
208
|
-
|
209
|
-
|
287
|
+
if @@quiet
|
288
|
+
exit true
|
289
|
+
else
|
290
|
+
puts Occi::VERSION
|
291
|
+
exit! true
|
292
|
+
end
|
210
293
|
end
|
211
|
-
|
212
294
|
end
|
213
295
|
|
214
296
|
begin
|
215
297
|
opts.parse!(args)
|
216
298
|
rescue Exception => ex
|
217
|
-
|
218
|
-
|
219
|
-
|
299
|
+
if @@quiet
|
300
|
+
exit false
|
301
|
+
else
|
302
|
+
puts ex.message.capitalize
|
303
|
+
puts opts
|
304
|
+
exit!
|
305
|
+
end
|
220
306
|
end
|
221
307
|
|
222
|
-
|
223
|
-
|
224
|
-
|
308
|
+
check_restrictions options, opts
|
309
|
+
|
310
|
+
options
|
311
|
+
end
|
312
|
+
|
313
|
+
private
|
225
314
|
|
226
|
-
|
315
|
+
def self.check_restrictions(options, opts)
|
316
|
+
if options.interactive && options.dump_model
|
317
|
+
if @@quiet
|
318
|
+
exit false
|
319
|
+
else
|
320
|
+
puts "You cannot use '--dump-model' and '--interactive' at the same time!"
|
321
|
+
puts opts
|
322
|
+
exit!
|
323
|
+
end
|
227
324
|
end
|
228
325
|
|
229
326
|
if !options.dump_model && options.filter
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
327
|
+
if @@quiet
|
328
|
+
exit false
|
329
|
+
else
|
330
|
+
puts "You cannot use '--filter' without '--dump-model'!"
|
331
|
+
puts opts
|
332
|
+
exit!
|
333
|
+
end
|
234
334
|
end
|
235
335
|
|
236
|
-
if
|
237
|
-
mandatory = []
|
336
|
+
return if options.interactive || options.dump_model
|
238
337
|
|
239
|
-
|
240
|
-
|
241
|
-
|
338
|
+
mandatory = []
|
339
|
+
|
340
|
+
if options.action == :trigger
|
341
|
+
mandatory << :trigger_action
|
342
|
+
end
|
242
343
|
|
243
|
-
|
244
|
-
|
344
|
+
if options.action == :create
|
345
|
+
if !options.links.nil?
|
346
|
+
mandatory << :links
|
347
|
+
else
|
348
|
+
mandatory << :mixins
|
245
349
|
end
|
246
350
|
|
247
|
-
mandatory
|
248
|
-
|
249
|
-
|
351
|
+
mandatory << :attributes
|
352
|
+
check_attrs = true
|
353
|
+
end
|
354
|
+
|
355
|
+
mandatory.concat [:resource, :action]
|
356
|
+
|
357
|
+
check_hash options, mandatory, opts
|
250
358
|
|
251
|
-
|
252
|
-
|
359
|
+
if check_attrs
|
360
|
+
mandatory = [:title]
|
361
|
+
check_hash options.attributes, mandatory, opts
|
362
|
+
end
|
363
|
+
end
|
364
|
+
|
365
|
+
def self.check_hash(hash, mandatory, opts)
|
366
|
+
if !hash.is_a? Hash
|
367
|
+
hash = hash.marshal_dump
|
368
|
+
end
|
369
|
+
|
370
|
+
missing = mandatory.select{ |param| hash[param].nil? }
|
371
|
+
if !missing.empty?
|
372
|
+
if @@quiet
|
373
|
+
exit false
|
374
|
+
else
|
253
375
|
puts "Missing required arguments: #{missing.join(', ')}"
|
254
376
|
puts opts
|
255
|
-
|
256
377
|
exit!
|
257
378
|
end
|
258
379
|
end
|
259
|
-
|
260
|
-
options
|
261
380
|
end
|
262
|
-
|
263
381
|
end
|
264
382
|
|
265
383
|
end
|
data/lib/occi/version.rb
CHANGED
data/occi.gemspec
CHANGED
@@ -39,7 +39,7 @@ Gem::Specification.new do |gem|
|
|
39
39
|
gem.add_development_dependency "yard-rspec"
|
40
40
|
gem.add_development_dependency "yard-cucumber"
|
41
41
|
gem.add_development_dependency "rspec-http"
|
42
|
-
|
42
|
+
gem.add_development_dependency "rubygems-tasks"
|
43
43
|
gem.add_development_dependency "webmock"
|
44
44
|
|
45
45
|
gem.required_ruby_version = ">= 1.8.7"
|
@@ -23,9 +23,12 @@ module Occi
|
|
23
23
|
|
24
24
|
=begin
|
25
25
|
before(:all) do
|
26
|
-
@client = Occi::Api::Client::ClientAmqp.new(
|
27
|
-
|
28
|
-
|
26
|
+
@client = Occi::Api::Client::ClientAmqp.new({
|
27
|
+
:endpoint => "http://localhost:9292/",
|
28
|
+
:auth => { :type => "none" },
|
29
|
+
:log => { :out => STDERR, :level => Occi::Log::WARN, :logger => nil },
|
30
|
+
:media_type => "application/occi+json"
|
31
|
+
})
|
29
32
|
end
|
30
33
|
|
31
34
|
it "initialize and connect client" do
|
@@ -11,14 +11,14 @@ module Occi
|
|
11
11
|
context "using media type text/plain" do
|
12
12
|
|
13
13
|
before(:each) do
|
14
|
-
@client = Occi::Api::Client::ClientHttp.new(
|
15
|
-
'https://localhost:3300',
|
16
|
-
{ :type => "none" },
|
17
|
-
{ :out => "/dev/null",
|
18
|
-
|
19
|
-
true,
|
20
|
-
"text/plain,text/occi"
|
21
|
-
)
|
14
|
+
@client = Occi::Api::Client::ClientHttp.new({
|
15
|
+
:endpoint => 'https://localhost:3300',
|
16
|
+
:auth => { :type => "none" },
|
17
|
+
:log => { :out => "/dev/null",
|
18
|
+
:level => Occi::Log::DEBUG },
|
19
|
+
:auto_connect => true,
|
20
|
+
:media_type => "text/plain,text/occi"
|
21
|
+
})
|
22
22
|
end
|
23
23
|
|
24
24
|
after(:each) do
|
@@ -189,14 +189,14 @@ module Occi
|
|
189
189
|
context "using media type application/occi+json" do
|
190
190
|
|
191
191
|
before(:each) do
|
192
|
-
#@client = Occi::Api::ClientHttp.new(
|
193
|
-
# 'https://localhost:3300',
|
194
|
-
# { :type => "none" },
|
195
|
-
# { :out => "/dev/null",
|
196
|
-
#
|
197
|
-
# true,
|
198
|
-
# "application/occi+json"
|
199
|
-
#)
|
192
|
+
#@client = Occi::Api::ClientHttp.new({
|
193
|
+
# :endpoint => 'https://localhost:3300',
|
194
|
+
# :auth => { :type => "none" },
|
195
|
+
# :log => { :out => "/dev/null",
|
196
|
+
# :level => Occi::Log::DEBUG },
|
197
|
+
# :auto_connect => true,
|
198
|
+
# :media_type => "application/occi+json"
|
199
|
+
#})
|
200
200
|
end
|
201
201
|
|
202
202
|
it "establishes connection"
|