occi-cli 4.2.0.beta.2 → 4.2.0.beta.3
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +7 -7
- data/bin/occi +14 -197
- data/lib/occi/cli/errors/mixin_lookup_error.rb +5 -0
- data/lib/occi/cli/helpers/create_helper.rb +43 -20
- data/lib/occi/cli/occi_opts.rb +42 -39
- data/lib/occi/cli/resource_output_factory.rb +14 -4
- data/lib/occi/cli/version.rb +1 -1
- data/lib/occi-cli.rb +1 -1
- data/occi-cli.gemspec +0 -1
- metadata +3 -18
data/README.md
CHANGED
@@ -110,18 +110,12 @@ ruby -v
|
|
110
110
|
Usage
|
111
111
|
-----
|
112
112
|
### Client
|
113
|
-
The OCCI gem includes a client you can use directly from shell with the following auth methods: x509 (with --password, --user-cred and --ca-path), basic (with --username and --password), digest (with --username and --password), none. If you won't set a password using --password, the client will ask for it later on.
|
113
|
+
The OCCI gem includes a client you can use directly from shell with the following auth methods: x509 (with --password, --user-cred and --ca-path), basic (with --username and --password), digest (with --username and --password), none. If you won't set a password using --password, the client will ask for it later on.
|
114
114
|
|
115
115
|
To find out more about available options and defaults use
|
116
116
|
|
117
117
|
occi --help
|
118
118
|
|
119
|
-
To run the client in an interactive mode use
|
120
|
-
|
121
|
-
occi --interactive
|
122
|
-
occi --interactive --endpoint https://<ENDPOINT>:<PORT>/
|
123
|
-
occi --interactive --endpoint https://<ENDPOINT>:<PORT>/ --auth x509
|
124
|
-
|
125
119
|
To list available resources use
|
126
120
|
|
127
121
|
occi --endpoint https://<ENDPOINT>:<PORT>/ --action list --resource compute --auth x509
|
@@ -161,6 +155,12 @@ To delete a compute resource use
|
|
161
155
|
Changelog
|
162
156
|
---------
|
163
157
|
|
158
|
+
### Version 4.2
|
159
|
+
* Droppped the interactive mode (it might return in the future)
|
160
|
+
* Updated internals
|
161
|
+
* Updated user interface and human-readable rendering
|
162
|
+
* __Includes interface changes incompatible with v4.1.x__
|
163
|
+
|
164
164
|
### Version 4.1
|
165
165
|
* Dropped Ruby 1.8.x support
|
166
166
|
* Dropped jRuby 1.6.x support
|
data/bin/occi
CHANGED
@@ -16,7 +16,6 @@
|
|
16
16
|
|
17
17
|
require 'rubygems'
|
18
18
|
require 'pp'
|
19
|
-
require 'highline/import'
|
20
19
|
require 'openssl'
|
21
20
|
|
22
21
|
require 'occi-cli'
|
@@ -47,9 +46,7 @@ if options.auth[:password].nil? || options.auth[:user_cert_password].nil?
|
|
47
46
|
options.auth[:password] = options.auth[:user_cert_password]
|
48
47
|
end
|
49
48
|
|
50
|
-
# establish a connection
|
51
|
-
# this will considerably speed-up the interactive mode and has
|
52
|
-
# no effect on the non-interactive one
|
49
|
+
# establish a connection
|
53
50
|
begin
|
54
51
|
Occi::Log.info "Establishing a connection to #{options.endpoint} ..."
|
55
52
|
|
@@ -58,7 +55,7 @@ begin
|
|
58
55
|
rescue OpenSSL::SSL::SSLError => ssl_ex
|
59
56
|
# generic SSL error raised whilst establishing a connection
|
60
57
|
# possibly an untrusted server cert or invalid user credentials
|
61
|
-
Occi::Log.
|
58
|
+
Occi::Log.fatal "An SSL error occurred! Please, make sure your credentials " \
|
62
59
|
"are valid and recognized by the endpoint! Message: #{ssl_ex.message}"
|
63
60
|
|
64
61
|
raise ssl_ex if options.debug
|
@@ -66,7 +63,7 @@ rescue OpenSSL::SSL::SSLError => ssl_ex
|
|
66
63
|
rescue OpenSSL::PKey::RSAError => key_ex
|
67
64
|
# generic X509 error raised whilst reading user's credentials from a file
|
68
65
|
# possibly a wrong password or mangled/unsupported credential format
|
69
|
-
Occi::Log.
|
66
|
+
Occi::Log.fatal "An X509 error occurred! Please, make sure you are using the " \
|
70
67
|
"right password and the file contains both your certificate " \
|
71
68
|
"and your private key! Message: #{key_ex.message}"
|
72
69
|
|
@@ -75,12 +72,16 @@ rescue OpenSSL::PKey::RSAError => key_ex
|
|
75
72
|
rescue Errno::ECONNREFUSED
|
76
73
|
# the remote server has refused our connection attempt(s)
|
77
74
|
# there is nothing we can do ...
|
78
|
-
Occi::Log.
|
75
|
+
Occi::Log.fatal "Connection refused by #{options.endpoint}!"
|
76
|
+
exit!
|
77
|
+
rescue Errno::ETIMEDOUT
|
78
|
+
# connection attempt timed out
|
79
|
+
Occi::Log.fatal "Connection to #{options.endpoint} timed out!"
|
79
80
|
exit!
|
80
81
|
rescue Exception => ex
|
81
82
|
# something went wrong during the execution
|
82
83
|
# hide the stack trace in non-debug modes
|
83
|
-
Occi::Log.
|
84
|
+
Occi::Log.fatal "An error occurred! Message: #{ex.message}"
|
84
85
|
|
85
86
|
raise ex if options.debug
|
86
87
|
exit!
|
@@ -90,7 +91,7 @@ end
|
|
90
91
|
if options.dump_model
|
91
92
|
|
92
93
|
if !model.respond_to? :instance_variables
|
93
|
-
Occi::Log.
|
94
|
+
Occi::Log.fatal "Your Ruby doesn't support 'instance_variables' calls!"
|
94
95
|
exit!
|
95
96
|
end
|
96
97
|
|
@@ -125,193 +126,9 @@ if options.dump_model
|
|
125
126
|
exit! true
|
126
127
|
end
|
127
128
|
|
128
|
-
# start
|
129
|
-
# interactive menus and actions execution
|
130
|
-
# this block will run while options.interactive is True, i.e.
|
131
|
-
# only once in the non-interactive mode
|
129
|
+
# start executing actions
|
132
130
|
begin
|
133
131
|
|
134
|
-
# display menus in the interactive mode, there are two main variables
|
135
|
-
# that need to be set here: options.action and options.resource
|
136
|
-
if options.interactive
|
137
|
-
|
138
|
-
Occi::Log.debug "Running in an interactive mode ..."
|
139
|
-
|
140
|
-
# reset action and resource, just to be sure
|
141
|
-
options.action = nil
|
142
|
-
options.resource = nil
|
143
|
-
|
144
|
-
# offer just the resource types we will be able to process
|
145
|
-
menu_resources = []
|
146
|
-
menu_resources << resource_type_identifiers.select { |i| i.include?("infrastructure#") }
|
147
|
-
menu_resources << ["http://schemas.ogf.org/occi/infrastructure#os_tpl", "http://schemas.ogf.org/occi/infrastructure#resource_tpl"]
|
148
|
-
menu_resources.flatten!
|
149
|
-
menu_resources.uniq!
|
150
|
-
|
151
|
-
# separate menus from each other
|
152
|
-
say("\n")
|
153
|
-
|
154
|
-
# first we need an action
|
155
|
-
choose do |menu|
|
156
|
-
menu.prompt = "Please, choose an action: "
|
157
|
-
|
158
|
-
# list action requires a resource type
|
159
|
-
menu.choice(:list) {
|
160
|
-
options.action = :list
|
161
|
-
|
162
|
-
# separate menus from each other
|
163
|
-
say("\n")
|
164
|
-
|
165
|
-
choose do |list_menu|
|
166
|
-
list_menu.prompt = "Which one should I list? "
|
167
|
-
|
168
|
-
menu_resources.each do |menu_resource|
|
169
|
-
list_menu.choice(menu_resource) { options.resource = menu_resource.to_s }
|
170
|
-
end
|
171
|
-
|
172
|
-
list_menu.choice(:back) { options.action = :skip }
|
173
|
-
end
|
174
|
-
}
|
175
|
-
|
176
|
-
# describe action requires a resource type or a resource location
|
177
|
-
menu.choice(:describe) {
|
178
|
-
options.action = :describe
|
179
|
-
|
180
|
-
# separate menus from each other
|
181
|
-
say("\n")
|
182
|
-
|
183
|
-
# display the resource types first
|
184
|
-
choose do |describe_menu|
|
185
|
-
describe_menu.prompt = "Which one should I describe? "
|
186
|
-
|
187
|
-
menu_resources.each do |menu_resource|
|
188
|
-
describe_menu.choice(menu_resource) {
|
189
|
-
options.resource = menu_resource.to_s
|
190
|
-
|
191
|
-
# separate menus from each other
|
192
|
-
say("\n")
|
193
|
-
|
194
|
-
# display available resources for this resource type
|
195
|
-
choose do |describe_menu_spec|
|
196
|
-
describe_menu_spec.prompt = "Should I describe a specific resource? "
|
197
|
-
|
198
|
-
describe_menu_spec.choice(:all) {
|
199
|
-
# leave options.resource set to compute/network/storage
|
200
|
-
}
|
201
|
-
|
202
|
-
found = helper_list options
|
203
|
-
found.each do |found_resource|
|
204
|
-
describe_menu_spec.choice(found_resource.to_sym) { options.resource = found_resource }
|
205
|
-
end
|
206
|
-
|
207
|
-
describe_menu_spec.choice(:back) { options.action = :skip }
|
208
|
-
end unless menu_resource.to_s.reverse.start_with? "lpt_"
|
209
|
-
}
|
210
|
-
end
|
211
|
-
|
212
|
-
describe_menu.choice(:back) { options.action = :skip }
|
213
|
-
end
|
214
|
-
}
|
215
|
-
|
216
|
-
# create action requires resource type, resource title
|
217
|
-
# and optionally mixins (usually two, os_tpl and resource_tpl)
|
218
|
-
menu.choice(:create) {
|
219
|
-
options.action = :create
|
220
|
-
|
221
|
-
# separate menus from each other
|
222
|
-
say("\n")
|
223
|
-
|
224
|
-
# display the resource types
|
225
|
-
choose do |create_menu|
|
226
|
-
create_menu.prompt = "Which one should I create? "
|
227
|
-
|
228
|
-
menu_resources.each do |menu_resource|
|
229
|
-
create_menu.choice(menu_resource) {
|
230
|
-
options.resource = menu_resource.to_s
|
231
|
-
} unless menu_resource.to_s.reverse.start_with? "lpt_"
|
232
|
-
end
|
233
|
-
|
234
|
-
create_menu.choice(:back) { options.action = :skip }
|
235
|
-
end
|
236
|
-
|
237
|
-
# if the user didn't choose "Back", ask for details
|
238
|
-
# TODO: currently only COMPUTE is supported
|
239
|
-
if options.action == :create
|
240
|
-
options.attributes = {} if options.attributes.nil?
|
241
|
-
|
242
|
-
options.attributes[:title] = ask("What name should I give to the new resource? ")
|
243
|
-
number_of_mixins = ask("How many mixins do you wish me to mix into this resource? ",
|
244
|
-
Integer) { |q| q.in = 0..2 }
|
245
|
-
|
246
|
-
options.mixins = Occi::Core::Mixins.new
|
247
|
-
(1..number_of_mixins).each do |mixin_number|
|
248
|
-
mixin = ask("What mixin should I mix in? ") { |q| q.validate = Occi::Cli::OcciOpts::MIXIN_REGEXP }
|
249
|
-
parts = mixin.split("#")
|
250
|
-
|
251
|
-
options.mixins << Occi::Core::Mixin.new("#{parts[0]}#", parts[1])
|
252
|
-
end
|
253
|
-
end
|
254
|
-
}
|
255
|
-
|
256
|
-
# delete action requires a resource location
|
257
|
-
menu.choice(:delete) {
|
258
|
-
options.action = :delete
|
259
|
-
|
260
|
-
# separate menus from each other
|
261
|
-
say("\n")
|
262
|
-
|
263
|
-
# display the resource types first
|
264
|
-
choose do |delete_menu|
|
265
|
-
delete_menu.prompt = "Please, choose a resource type: "
|
266
|
-
|
267
|
-
menu_resources.each do |menu_resource|
|
268
|
-
delete_menu.choice(menu_resource) {
|
269
|
-
|
270
|
-
# separate menus from each other
|
271
|
-
say("\n")
|
272
|
-
|
273
|
-
# display available resources for this type
|
274
|
-
choose do |delete_menu_spec|
|
275
|
-
delete_menu_spec.prompt = "Which resource should I delete? "
|
276
|
-
|
277
|
-
opts = OpenStruct.new
|
278
|
-
opts.resource = menu_resource.to_s
|
279
|
-
|
280
|
-
found = helper_list opts
|
281
|
-
found.each do |found_resource|
|
282
|
-
delete_menu_spec.choice(found_resource.to_sym) { options.resource = found_resource }
|
283
|
-
end
|
284
|
-
|
285
|
-
delete_menu_spec.choice(:back) { options.action = :skip }
|
286
|
-
end unless menu_resource.to_s.reverse.start_with? "lpt_"
|
287
|
-
} unless menu_resource.to_s.reverse.start_with? "lpt_"
|
288
|
-
end
|
289
|
-
|
290
|
-
delete_menu.choice(:back) { options.action = :skip }
|
291
|
-
end
|
292
|
-
}
|
293
|
-
|
294
|
-
# TODO: trigger is not yet implemented
|
295
|
-
menu.choice(:trigger) {
|
296
|
-
options.action = :skip
|
297
|
-
say("Not implemented yet!")
|
298
|
-
}
|
299
|
-
|
300
|
-
# refresh the OCCI model structures without exiting/re-launching
|
301
|
-
# the client, useful when adding new os_tpls/resource_tpls on
|
302
|
-
# the server
|
303
|
-
menu.choice(:refresh) {
|
304
|
-
options.action = :refresh
|
305
|
-
}
|
306
|
-
|
307
|
-
# enough is enough, bye!
|
308
|
-
menu.choice(:quit) {
|
309
|
-
say("Good bye!")
|
310
|
-
exit!(true)
|
311
|
-
}
|
312
|
-
end
|
313
|
-
end
|
314
|
-
|
315
132
|
Occi::Log.info "Executing action #{options.action.to_s} on #{options.resource} ..."
|
316
133
|
|
317
134
|
# call the appropriate helper and then format its output
|
@@ -337,15 +154,15 @@ begin
|
|
337
154
|
rescue Errno::ECONNREFUSED
|
338
155
|
# remote server refused our connection attempt(s)
|
339
156
|
# even though initial connect was successful
|
340
|
-
Occi::Log.
|
157
|
+
Occi::Log.fatal "Connection refused by #{options.endpoint}!"
|
341
158
|
exit!
|
342
159
|
rescue Exception => ex
|
343
160
|
# something went wrong during the execution
|
344
161
|
# hide the stack trace in non-debug modes
|
345
|
-
Occi::Log.
|
162
|
+
Occi::Log.fatal "An error occurred! Message: #{ex.message}"
|
346
163
|
|
347
164
|
raise ex if options.debug
|
348
165
|
exit!
|
349
|
-
end
|
166
|
+
end
|
350
167
|
|
351
168
|
Occi::Log.info "OCCI client is shutting down ..."
|
@@ -4,33 +4,50 @@ module Occi::Cli::Helpers::CreateHelper
|
|
4
4
|
location = nil
|
5
5
|
|
6
6
|
if resource_types.include?(options.resource) || resource_type_identifiers.include?(options.resource)
|
7
|
-
|
8
|
-
|
7
|
+
location = helper_create_resource(options)
|
8
|
+
else
|
9
|
+
Occi::Log.warn "I have no idea what #{options.resource.inspect} is ..."
|
10
|
+
raise "Unknown resource #{options.resource.inspect}, there is nothing to create here!"
|
11
|
+
end
|
12
|
+
|
13
|
+
return location if output.nil?
|
14
|
+
|
15
|
+
puts location
|
16
|
+
end
|
17
|
+
|
18
|
+
def helper_create_resource(options)
|
19
|
+
Occi::Log.debug "#{options.resource.inspect} is a resource type."
|
20
|
+
|
21
|
+
# TODO: implement the rest
|
22
|
+
raise "Not yet implemented!" unless options.resource.include? "compute"
|
23
|
+
|
24
|
+
res = resource(options.resource)
|
9
25
|
|
10
|
-
|
26
|
+
Occi::Log.debug "Creating #{options.resource.inspect}: #{res.inspect}"
|
11
27
|
|
12
|
-
|
28
|
+
helper_attach_mixins(options, res)
|
13
29
|
|
30
|
+
if res.kind_of? Occi::Infrastructure::Compute
|
14
31
|
helper_attach_links(options, res)
|
15
|
-
|
32
|
+
# TODO: context vars are only attributes!
|
16
33
|
helper_attach_context_vars(options, res)
|
34
|
+
end
|
17
35
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
res.hostname = options.attributes[:title]
|
22
|
-
|
23
|
-
Occi::Log.debug "Creating #{options.resource.inspect}:\n#{res.inspect}"
|
36
|
+
options.attributes.names.each_pair do |attribute, value|
|
37
|
+
res.attributes[attribute.to_s] = value
|
38
|
+
end
|
24
39
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
raise "Unknown resource #{options.resource.inspect}, there is nothing to create here!"
|
40
|
+
# TODO: OCCI-OS uses occi.compute.hostname instead of title
|
41
|
+
if res.kind_of? Occi::Infrastructure::Compute
|
42
|
+
res.hostname = options.attributes["occi.core.title"] if res.hostname.blank?
|
29
43
|
end
|
30
44
|
|
31
|
-
|
45
|
+
# TODO: enable check
|
46
|
+
#res.check
|
32
47
|
|
33
|
-
|
48
|
+
Occi::Log.debug "Creating #{options.resource.inspect}: #{res.inspect}"
|
49
|
+
|
50
|
+
create res
|
34
51
|
end
|
35
52
|
|
36
53
|
def helper_attach_links(options, res)
|
@@ -56,10 +73,15 @@ module Occi::Cli::Helpers::CreateHelper
|
|
56
73
|
|
57
74
|
def helper_attach_mixins(options, res)
|
58
75
|
return unless options.mixins
|
59
|
-
Occi::Log.debug "with mixins: #{options.mixins}"
|
76
|
+
Occi::Log.debug "with mixins: #{options.mixins.inspect}"
|
60
77
|
|
61
78
|
options.mixins.to_a.each do |mxn|
|
62
79
|
Occi::Log.debug "Adding mixin #{mxn.inspect} to #{options.resource.inspect}"
|
80
|
+
|
81
|
+
mxn = model.get_by_id(mxn.type_identifier)
|
82
|
+
raise Occi::Cli::Errors::MixinLookupError,
|
83
|
+
"The specified mixin is not declared in the model! #{mxn.type_identifier.inspect}" if mxn.blank?
|
84
|
+
|
63
85
|
res.mixins << mxn
|
64
86
|
end
|
65
87
|
end
|
@@ -67,7 +89,7 @@ module Occi::Cli::Helpers::CreateHelper
|
|
67
89
|
def helper_attach_context_vars(options, res)
|
68
90
|
# TODO: find a better/universal way to do contextualization
|
69
91
|
return unless options.context_vars
|
70
|
-
Occi::Log.debug "with context variables: #{options.context_vars}"
|
92
|
+
Occi::Log.debug "with context variables: #{options.context_vars.inspect}"
|
71
93
|
|
72
94
|
options.context_vars.each_pair do |var, val|
|
73
95
|
schema = nil
|
@@ -82,6 +104,7 @@ module Occi::Cli::Helpers::CreateHelper
|
|
82
104
|
schema = "http://schemas.openstack.org/compute/instance#"
|
83
105
|
mxn_attrs['org.openstack.compute.user_data'] = {}
|
84
106
|
else
|
107
|
+
Occi::Log.warn "Unknown context variable! #{var.to_s.inspect}"
|
85
108
|
schema = "http://schemas.ogf.org/occi/core#"
|
86
109
|
end
|
87
110
|
|
@@ -95,7 +118,7 @@ module Occi::Cli::Helpers::CreateHelper
|
|
95
118
|
when :user_data
|
96
119
|
res.attributes['org.openstack.compute.user_data'] = val
|
97
120
|
else
|
98
|
-
|
121
|
+
Occi::Log.warn "Not setting attributes for an unknown context variable! #{var.to_s.inspect}"
|
99
122
|
end
|
100
123
|
end
|
101
124
|
end
|
data/lib/occi/cli/occi_opts.rb
CHANGED
@@ -3,8 +3,6 @@ require 'optparse'
|
|
3
3
|
require 'uri'
|
4
4
|
require 'base64'
|
5
5
|
|
6
|
-
require 'occi/cli/resource_output_factory'
|
7
|
-
|
8
6
|
module Occi::Cli
|
9
7
|
|
10
8
|
class OcciOpts
|
@@ -14,6 +12,7 @@ module Occi::Cli
|
|
14
12
|
ACTIONS = [:list, :describe, :create, :delete, :trigger].freeze
|
15
13
|
LOG_OUTPUTS = [:stdout, :stderr].freeze
|
16
14
|
ALLOWED_CONTEXT_VARS = [:public_key, :user_data].freeze
|
15
|
+
LOG_LEVELS = [:debug, :error, :fatal, :info, :unknown, :warn].freeze
|
17
16
|
|
18
17
|
MIXIN_REGEXP = /^(https?:\/\/\S+?)#(\S+)$/
|
19
18
|
CONTEXT_REGEXP = ATTR_REGEXP = /^(.+?)=(.+)$/
|
@@ -25,17 +24,14 @@ module Occi::Cli
|
|
25
24
|
options = OpenStruct.new
|
26
25
|
|
27
26
|
options.debug = false
|
28
|
-
options.verbose = false
|
29
27
|
|
30
28
|
options.log = {}
|
31
29
|
options.log[:out] = STDERR
|
32
|
-
options.log[:level] = Occi::Log::
|
30
|
+
options.log[:level] = Occi::Log::ERROR
|
33
31
|
|
34
32
|
options.filter = nil
|
35
33
|
options.dump_model = false
|
36
34
|
|
37
|
-
options.interactive = false
|
38
|
-
|
39
35
|
options.endpoint = "https://localhost:3300/"
|
40
36
|
|
41
37
|
options.auth = {}
|
@@ -50,7 +46,7 @@ module Occi::Cli
|
|
50
46
|
|
51
47
|
options.mixins = Occi::Core::Mixins.new
|
52
48
|
options.links = nil
|
53
|
-
options.attributes =
|
49
|
+
options.attributes = Occi::Core::Attributes.new
|
54
50
|
options.context_vars = nil
|
55
51
|
|
56
52
|
# TODO: change media type back to occi+json after the rOCCI-server update
|
@@ -61,7 +57,6 @@ module Occi::Cli
|
|
61
57
|
opts.banner = %{Usage: occi [OPTIONS]
|
62
58
|
|
63
59
|
Examples:
|
64
|
-
occi --interactive --endpoint https://localhost:3300/ --auth x509
|
65
60
|
|
66
61
|
occi --endpoint https://localhost:3300/ --action list --resource os_tpl --auth x509
|
67
62
|
|
@@ -76,12 +71,6 @@ occi --endpoint https://localhost:3300/ --action delete --resource /compute/65sd
|
|
76
71
|
opts.separator ""
|
77
72
|
opts.separator "Options:"
|
78
73
|
|
79
|
-
opts.on("-i",
|
80
|
-
"--interactive",
|
81
|
-
"Run as an interactive client without additional arguments") do |interactive|
|
82
|
-
options.interactive = interactive
|
83
|
-
end
|
84
|
-
|
85
74
|
opts.on("-e",
|
86
75
|
"--endpoint URI",
|
87
76
|
String,
|
@@ -172,14 +161,15 @@ occi --endpoint https://localhost:3300/ --action delete --resource /compute/65sd
|
|
172
161
|
opts.on("-t",
|
173
162
|
"--attribute ATTRS",
|
174
163
|
Array,
|
175
|
-
"Comma separated attributes for new resources such as title=\"Name\", required") do |attributes|
|
176
|
-
options.attributes ||=
|
164
|
+
"Comma separated attributes for new resources such as occi.core.title=\"Name\", required") do |attributes|
|
165
|
+
options.attributes ||= Occi::Core::Attributes.new
|
177
166
|
|
178
167
|
attributes.each do |attribute|
|
179
168
|
ary = ATTR_REGEXP.match(attribute).to_a.drop 1
|
180
169
|
raise ArgumentError, "Attribute must always contain ATTR=VALUE pairs!" unless ary.length == 2
|
181
170
|
|
182
|
-
|
171
|
+
ary[0] = "occi.core.#{ary[0]}" unless ary[0].include?('.')
|
172
|
+
options.attributes[ary[0]] = ary[1]
|
183
173
|
end
|
184
174
|
end
|
185
175
|
|
@@ -267,9 +257,18 @@ occi --endpoint https://localhost:3300/ --action delete --resource /compute/65sd
|
|
267
257
|
options.output_format = output_format
|
268
258
|
end
|
269
259
|
|
260
|
+
opts.on("-b",
|
261
|
+
"--log-level LEVEL",
|
262
|
+
LOG_LEVELS,
|
263
|
+
"Set the specified logging level, less intrusive than debug mode") do |log_level|
|
264
|
+
unless options.log[:level] == Occi::Log::DEBUG
|
265
|
+
options.log[:level] = Occi::Log.const_get(log_level.to_s.upcase)
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
270
269
|
opts.on_tail("-m",
|
271
270
|
"--dump-model",
|
272
|
-
"Contact the endpoint and dump its model
|
271
|
+
"Contact the endpoint and dump its model") do |dump_model|
|
273
272
|
options.dump_model = dump_model
|
274
273
|
end
|
275
274
|
|
@@ -280,13 +279,6 @@ occi --endpoint https://localhost:3300/ --action delete --resource /compute/65sd
|
|
280
279
|
options.log[:level] = Occi::Log::DEBUG
|
281
280
|
end
|
282
281
|
|
283
|
-
opts.on_tail("-b",
|
284
|
-
"--verbose",
|
285
|
-
"Be more verbose, less intrusive than debug mode") do |verbose|
|
286
|
-
options.verbose = verbose
|
287
|
-
options.log[:level] = Occi::Log::INFO unless options.log[:level] == Occi::Log::DEBUG
|
288
|
-
end
|
289
|
-
|
290
282
|
opts.on_tail("-h",
|
291
283
|
"--help",
|
292
284
|
"Show this message") do
|
@@ -336,16 +328,6 @@ occi --endpoint https://localhost:3300/ --action delete --resource /compute/65sd
|
|
336
328
|
private
|
337
329
|
|
338
330
|
def self.check_restrictions(options, opts)
|
339
|
-
if options.interactive && options.dump_model
|
340
|
-
if @@quiet
|
341
|
-
exit false
|
342
|
-
else
|
343
|
-
puts "You cannot use '--dump-model' and '--interactive' at the same time!"
|
344
|
-
puts opts
|
345
|
-
exit!
|
346
|
-
end
|
347
|
-
end
|
348
|
-
|
349
331
|
if !options.dump_model && options.filter
|
350
332
|
if @@quiet
|
351
333
|
exit false
|
@@ -366,7 +348,7 @@ occi --endpoint https://localhost:3300/ --action delete --resource /compute/65sd
|
|
366
348
|
end
|
367
349
|
end
|
368
350
|
|
369
|
-
return if options.
|
351
|
+
return if options.dump_model
|
370
352
|
|
371
353
|
mandatory = []
|
372
354
|
|
@@ -390,8 +372,8 @@ occi --endpoint https://localhost:3300/ --action delete --resource /compute/65sd
|
|
390
372
|
check_hash options, mandatory, opts
|
391
373
|
|
392
374
|
if check_attrs
|
393
|
-
mandatory = [
|
394
|
-
|
375
|
+
mandatory = ["occi.core.title"]
|
376
|
+
check_attributes options.attributes, mandatory, opts
|
395
377
|
end
|
396
378
|
end
|
397
379
|
|
@@ -400,7 +382,28 @@ occi --endpoint https://localhost:3300/ --action delete --resource /compute/65sd
|
|
400
382
|
hash = hash.marshal_dump
|
401
383
|
end
|
402
384
|
|
403
|
-
missing = mandatory.select{ |param| hash[param].
|
385
|
+
missing = mandatory.select { |param| hash[param].blank? }
|
386
|
+
report_missing missing, opts
|
387
|
+
end
|
388
|
+
|
389
|
+
def self.check_attributes(attributes, mandatory, opts)
|
390
|
+
missing = []
|
391
|
+
attributes = Occi::Core::Attributes.new(attributes)
|
392
|
+
|
393
|
+
mandatory.each do |attribute|
|
394
|
+
begin
|
395
|
+
attributes[attribute]
|
396
|
+
raise Occi::Errors::AttributeMissingError,
|
397
|
+
"Attribute #{attribute.inspect} is empty!" unless attributes[attribute]
|
398
|
+
rescue Occi::Errors::AttributeMissingError
|
399
|
+
missing << attribute
|
400
|
+
end
|
401
|
+
end
|
402
|
+
|
403
|
+
report_missing missing, opts
|
404
|
+
end
|
405
|
+
|
406
|
+
def self.report_missing(missing, opts)
|
404
407
|
unless missing.empty?
|
405
408
|
if @@quiet
|
406
409
|
exit false
|
@@ -39,11 +39,21 @@ module Occi::Cli
|
|
39
39
|
|
40
40
|
def resources_to_json(occi_resources)
|
41
41
|
# generate JSON document from Occi::Core::Resources
|
42
|
+
occi_resources = occi_resources.to_a
|
43
|
+
|
42
44
|
if @output_format == :json_pretty
|
43
|
-
|
45
|
+
output_first = "[\n"
|
46
|
+
output_ary = occi_resources.collect { |r| JSON.pretty_generate(r.as_json.to_hash) }
|
47
|
+
separator = ",\n"
|
48
|
+
output_last = "\n]"
|
44
49
|
else
|
45
|
-
|
50
|
+
output_first = "["
|
51
|
+
output_ary = occi_resources.collect { |r| JSON.generate(r.as_json.to_hash) }
|
52
|
+
separator = ","
|
53
|
+
output_last = "]"
|
46
54
|
end
|
55
|
+
|
56
|
+
"#{output_first}#{output_ary.join(separator)}#{output_last}"
|
47
57
|
end
|
48
58
|
alias_method :resources_to_json_pretty, :resources_to_json
|
49
59
|
alias_method :mixins_to_json, :resources_to_json
|
@@ -52,9 +62,9 @@ module Occi::Cli
|
|
52
62
|
def locations_to_json(url_locations)
|
53
63
|
# generate JSON document from an array of strings
|
54
64
|
if @output_format == :json_pretty
|
55
|
-
JSON.pretty_generate
|
65
|
+
JSON.pretty_generate url_locations
|
56
66
|
else
|
57
|
-
JSON.generate
|
67
|
+
JSON.generate url_locations
|
58
68
|
end
|
59
69
|
end
|
60
70
|
alias_method :locations_to_json_pretty, :locations_to_json
|
data/lib/occi/cli/version.rb
CHANGED
data/lib/occi-cli.rb
CHANGED
data/occi-cli.gemspec
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: occi-cli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.2.0.beta.
|
4
|
+
version: 4.2.0.beta.3
|
5
5
|
prerelease: 6
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2013-12-
|
14
|
+
date: 2013-12-06 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: occi-api
|
@@ -29,22 +29,6 @@ dependencies:
|
|
29
29
|
- - '='
|
30
30
|
- !ruby/object:Gem::Version
|
31
31
|
version: 4.2.0.beta.2
|
32
|
-
- !ruby/object:Gem::Dependency
|
33
|
-
name: highline
|
34
|
-
requirement: !ruby/object:Gem::Requirement
|
35
|
-
none: false
|
36
|
-
requirements:
|
37
|
-
- - ! '>='
|
38
|
-
- !ruby/object:Gem::Version
|
39
|
-
version: '0'
|
40
|
-
type: :runtime
|
41
|
-
prerelease: false
|
42
|
-
version_requirements: !ruby/object:Gem::Requirement
|
43
|
-
none: false
|
44
|
-
requirements:
|
45
|
-
- - ! '>='
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '0'
|
48
32
|
- !ruby/object:Gem::Dependency
|
49
33
|
name: json
|
50
34
|
requirement: !ruby/object:Gem::Requirement
|
@@ -88,6 +72,7 @@ files:
|
|
88
72
|
- lib/occi/cli/errors.rb
|
89
73
|
- lib/occi/cli/errors/formatter_input_type_error.rb
|
90
74
|
- lib/occi/cli/errors/formatter_output_type_error.rb
|
75
|
+
- lib/occi/cli/errors/mixin_lookup_error.rb
|
91
76
|
- lib/occi/cli/helpers.rb
|
92
77
|
- lib/occi/cli/helpers/common_helper.rb
|
93
78
|
- lib/occi/cli/helpers/create_helper.rb
|