occi-cli 4.2.0.beta.2 → 4.2.0.beta.3
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/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
|