cft_smartcloud 0.3.0 → 0.3.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/CHANGELOG +4 -0
- data/README.md +26 -28
- data/VERSION +1 -1
- data/bin/cft_smartcloud +33 -8
- data/bin/smartcloud +33 -8
- data/cft_smartcloud.gemspec +3 -2
- data/lib/config/config.yml +2 -2
- data/lib/curl_client.rb +3 -1
- data/lib/dynamic_help_generator.rb +88 -0
- data/lib/smartcloud.rb +24 -59
- metadata +4 -3
data/CHANGELOG
CHANGED
data/README.md
CHANGED
@@ -3,7 +3,7 @@ smartcloud
|
|
3
3
|
|
4
4
|
Provides support for interacting with IBM SmartCloud API and CLI tools
|
5
5
|
|
6
|
-
|
6
|
+
Installation
|
7
7
|
===
|
8
8
|
|
9
9
|
from rubygems.org:
|
@@ -15,7 +15,7 @@ locally:
|
|
15
15
|
rake build
|
16
16
|
gem install pkg/[name of generated gem]
|
17
17
|
|
18
|
-
|
18
|
+
Setup
|
19
19
|
===
|
20
20
|
|
21
21
|
Please set up SMARTCLOUD_USERNAME and SMARTCLOUD_PASSWORD in your .bash_profile
|
@@ -26,12 +26,8 @@ Please set up SMARTCLOUD_USERNAME and SMARTCLOUD_PASSWORD in your .bash_profile
|
|
26
26
|
You can now also supply the username and password on the command line using -u and -p
|
27
27
|
Use `smartcloud help` to get a list of all optoins.
|
28
28
|
|
29
|
-
screencast
|
30
|
-
===
|
31
|
-
|
32
|
-
http://www.youtube.com/cohesiveft#p/u/0/-WdSHP2iwDM (somewhat outdated)
|
33
29
|
|
34
|
-
|
30
|
+
Using the console
|
35
31
|
==
|
36
32
|
|
37
33
|
script/console
|
@@ -44,43 +40,36 @@ using the console
|
|
44
40
|
from the environment variables SMARTCLOUD_USERNAME and SMARTCLOUD_PASSWORD
|
45
41
|
automatically (it's created at the bottom of smartcloud.rb)
|
46
42
|
|
47
|
-
|
43
|
+
Using the commandline
|
48
44
|
==
|
49
45
|
|
50
|
-
|
51
|
-
|
52
|
-
to see a list of methods:
|
46
|
+
To see a list of methods:
|
53
47
|
|
54
48
|
smartcloud help
|
55
49
|
|
56
|
-
|
50
|
+
Examples:
|
57
51
|
|
58
52
|
smartcloud display_volumes
|
53
|
+
smartcloud display_volumes Location=82 State=MOUNTED
|
59
54
|
smartcloud display_instances
|
60
|
-
smartcloud display_instance 12345
|
61
55
|
smartcloud delete_instances 12345 12346 12347
|
62
|
-
smartcloud "
|
63
|
-
smartcloud
|
56
|
+
smartcloud display_images Name="Red Hat"
|
57
|
+
smartcloud display_instances Name="Red Hat" Location=82
|
64
58
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
will return pretty-formatted hashes, or singular values.
|
69
|
-
|
70
|
-
smartcloud display_volumes
|
59
|
+
The 'display_*' methods are intended to generate pretty human readable
|
60
|
+
displays, while the describe methods will return pretty-formatted hashes,
|
61
|
+
or singular values.
|
71
62
|
|
72
|
-
|
73
|
-
|
63
|
+
To save time when dealing with large responses, such as the describe_images
|
64
|
+
call, you can save a response in its native XML format:
|
74
65
|
|
75
|
-
|
66
|
+
smartcloud display_images -S /tmp/images.xml
|
76
67
|
|
77
|
-
|
68
|
+
You can then replay the response, using filters on it
|
78
69
|
|
79
|
-
|
70
|
+
smartcloud display_images Name='Red Hat' -R /tmp/images.xml
|
80
71
|
|
81
|
-
> smartcloud help
|
82
72
|
|
83
|
-
These won't tell you the arguments, you have to look at smartcloud.rb for the args.
|
84
73
|
|
85
74
|
RestClient vs CurlHttpClient
|
86
75
|
===
|
@@ -100,6 +89,15 @@ This project uses the jeweler gem for packaging. See the tasks:
|
|
100
89
|
rake version:bump:...
|
101
90
|
rake build
|
102
91
|
|
92
|
+
To publish to RubyForge
|
93
|
+
|
94
|
+
rake gemcutter:release
|
95
|
+
|
96
|
+
Screencast
|
97
|
+
===
|
98
|
+
|
99
|
+
http://www.youtube.com/cohesiveft#p/u/0/-WdSHP2iwDM (somewhat outdated)
|
100
|
+
|
103
101
|
Copyright
|
104
102
|
==
|
105
103
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.3.
|
1
|
+
0.3.1
|
data/bin/cft_smartcloud
CHANGED
@@ -18,7 +18,7 @@ opts = Slop.new do
|
|
18
18
|
on :U, :api_url=, "URL of api endpoint"
|
19
19
|
on :d, :debug, "Enable debug logging"
|
20
20
|
on :R, :simulated_response_file=, "Pass in a file containing the response (do not hit cloud)"
|
21
|
-
on :S, :save_response
|
21
|
+
on :S, :save_response=, "Save the response (supply filename) as xml, for later use with -R response file"
|
22
22
|
end
|
23
23
|
|
24
24
|
# These are the actual commands appearing after the script name,
|
@@ -31,11 +31,8 @@ end
|
|
31
31
|
|
32
32
|
if commands.size == 1
|
33
33
|
if commands[0] == 'help'
|
34
|
-
puts "#{opts.help}\n\
|
34
|
+
puts "#{opts.help}\n\n"
|
35
35
|
end
|
36
|
-
@cmd=commands[0]
|
37
|
-
elsif commands.size == 2
|
38
|
-
@cmd="#{commands[0]}('#{commands[1]}')"
|
39
36
|
elsif commands.size == 0
|
40
37
|
puts %{
|
41
38
|
#{opts.help}
|
@@ -50,17 +47,45 @@ elsif commands.size == 0
|
|
50
47
|
smartcloud "delete_instance(12345)"
|
51
48
|
smartcloud delete_instance 12345
|
52
49
|
smartcloud delete_instances 12345 12346 12347
|
53
|
-
smartcloud "delete_instances(12345,12346,12347)"
|
54
50
|
smartcloud display_instances
|
51
|
+
smartcloud display_images name="Red Hat"
|
55
52
|
}
|
56
53
|
exit(0)
|
54
|
+
end
|
55
|
+
|
56
|
+
# parse out foo=bar values and turn them into a hash
|
57
|
+
params=[]
|
58
|
+
param_hash={}
|
59
|
+
commands[1..-1].each do |item|
|
60
|
+
if item =~ /=/
|
61
|
+
key,val = item.split('=')
|
62
|
+
param_hash[key]=val
|
63
|
+
else
|
64
|
+
params << item
|
65
|
+
end
|
66
|
+
end
|
67
|
+
params = params.map {|param| "'#{param}'" }.join(',')
|
68
|
+
|
69
|
+
method_invocation = if params.empty? && param_hash.empty?
|
70
|
+
commands[0]
|
71
|
+
elsif !params.empty? && param_hash.empty?
|
72
|
+
"#{commands[0]}(#{params})"
|
73
|
+
elsif params.empty? && !param_hash.empty?
|
74
|
+
"#{commands[0]}(#{param_hash.inspect})"
|
57
75
|
else
|
58
|
-
|
76
|
+
"#{commands[0]}(#{params}, #{param_hash.inspect})"
|
59
77
|
end
|
60
78
|
|
79
|
+
puts "Invoking: #{method_invocation}"
|
61
80
|
# allows us to send arbitrary commands like
|
62
81
|
# smartcloud username password describe_instance("122345")
|
63
|
-
|
82
|
+
begin
|
83
|
+
result = eval("@sc.#{method_invocation}")
|
84
|
+
|
85
|
+
rescue ArgumentError => e
|
86
|
+
puts e.message
|
87
|
+
puts "\nPlease use the following command for more information:\nsmartcloud help #{commands[0]}\n\n"
|
88
|
+
end
|
64
89
|
|
65
90
|
if result == true || result.nil?
|
66
91
|
# do nothing, the command already logged
|
data/bin/smartcloud
CHANGED
@@ -18,7 +18,7 @@ opts = Slop.new do
|
|
18
18
|
on :U, :api_url=, "URL of api endpoint"
|
19
19
|
on :d, :debug, "Enable debug logging"
|
20
20
|
on :R, :simulated_response_file=, "Pass in a file containing the response (do not hit cloud)"
|
21
|
-
on :S, :save_response
|
21
|
+
on :S, :save_response=, "Save the response (supply filename) as xml, for later use with -R response file"
|
22
22
|
end
|
23
23
|
|
24
24
|
# These are the actual commands appearing after the script name,
|
@@ -31,11 +31,8 @@ end
|
|
31
31
|
|
32
32
|
if commands.size == 1
|
33
33
|
if commands[0] == 'help'
|
34
|
-
puts "#{opts.help}\n\
|
34
|
+
puts "#{opts.help}\n\n"
|
35
35
|
end
|
36
|
-
@cmd=commands[0]
|
37
|
-
elsif commands.size == 2
|
38
|
-
@cmd="#{commands[0]}('#{commands[1]}')"
|
39
36
|
elsif commands.size == 0
|
40
37
|
puts %{
|
41
38
|
#{opts.help}
|
@@ -50,17 +47,45 @@ elsif commands.size == 0
|
|
50
47
|
smartcloud "delete_instance(12345)"
|
51
48
|
smartcloud delete_instance 12345
|
52
49
|
smartcloud delete_instances 12345 12346 12347
|
53
|
-
smartcloud "delete_instances(12345,12346,12347)"
|
54
50
|
smartcloud display_instances
|
51
|
+
smartcloud display_images name="Red Hat"
|
55
52
|
}
|
56
53
|
exit(0)
|
54
|
+
end
|
55
|
+
|
56
|
+
# parse out foo=bar values and turn them into a hash
|
57
|
+
params=[]
|
58
|
+
param_hash={}
|
59
|
+
commands[1..-1].each do |item|
|
60
|
+
if item =~ /=/
|
61
|
+
key,val = item.split('=')
|
62
|
+
param_hash[key]=val
|
63
|
+
else
|
64
|
+
params << item
|
65
|
+
end
|
66
|
+
end
|
67
|
+
params = params.map {|param| "'#{param}'" }.join(',')
|
68
|
+
|
69
|
+
method_invocation = if params.empty? && param_hash.empty?
|
70
|
+
commands[0]
|
71
|
+
elsif !params.empty? && param_hash.empty?
|
72
|
+
"#{commands[0]}(#{params})"
|
73
|
+
elsif params.empty? && !param_hash.empty?
|
74
|
+
"#{commands[0]}(#{param_hash.inspect})"
|
57
75
|
else
|
58
|
-
|
76
|
+
"#{commands[0]}(#{params}, #{param_hash.inspect})"
|
59
77
|
end
|
60
78
|
|
79
|
+
puts "Invoking: #{method_invocation}"
|
61
80
|
# allows us to send arbitrary commands like
|
62
81
|
# smartcloud username password describe_instance("122345")
|
63
|
-
|
82
|
+
begin
|
83
|
+
result = eval("@sc.#{method_invocation}")
|
84
|
+
|
85
|
+
rescue ArgumentError => e
|
86
|
+
puts e.message
|
87
|
+
puts "\nPlease use the following command for more information:\nsmartcloud help #{commands[0]}\n\n"
|
88
|
+
end
|
64
89
|
|
65
90
|
if result == true || result.nil?
|
66
91
|
# do nothing, the command already logged
|
data/cft_smartcloud.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{cft_smartcloud}
|
8
|
-
s.version = "0.3.
|
8
|
+
s.version = "0.3.1"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["yan", "cohesive"]
|
12
|
-
s.date = %q{
|
12
|
+
s.date = %q{2012-03-12}
|
13
13
|
s.description = %q{CohesiveFT Ruby Interface for IBM SmartCloud and 'smartcloud' command line helper.}
|
14
14
|
s.email = %q{yan.pritzker@cohesiveft.com}
|
15
15
|
s.executables = ["cft_smartcloud", "smartcloud"]
|
@@ -29,6 +29,7 @@ Gem::Specification.new do |s|
|
|
29
29
|
"cft_smartcloud.gemspec",
|
30
30
|
"lib/config/config.yml",
|
31
31
|
"lib/curl_client.rb",
|
32
|
+
"lib/dynamic_help_generator.rb",
|
32
33
|
"lib/hash_fix.rb",
|
33
34
|
"lib/mime-types-1.16/History.txt",
|
34
35
|
"lib/mime-types-1.16/Install.txt",
|
data/lib/config/config.yml
CHANGED
data/lib/curl_client.rb
CHANGED
@@ -9,7 +9,9 @@ class CurlHttpClient
|
|
9
9
|
|
10
10
|
def self.logger; @logger ||= Logger.new(STDOUT); end
|
11
11
|
|
12
|
-
|
12
|
+
# Even though we don't need the options, the REST client does.
|
13
|
+
# So we have this for consistency.
|
14
|
+
def self.get(url, options={})
|
13
15
|
handle_output(curl(url))
|
14
16
|
end
|
15
17
|
|
@@ -0,0 +1,88 @@
|
|
1
|
+
module DynamicHelpGenerator
|
2
|
+
|
3
|
+
def self.included(base)
|
4
|
+
base.extend(ClassMethods)
|
5
|
+
end
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
def help_for(method, args, extra_help="")
|
9
|
+
@method_help||={}
|
10
|
+
@method_help_supplemental||={}
|
11
|
+
@method_help[method.to_s] = args
|
12
|
+
@method_help_supplemental[method.to_s] = extra_help
|
13
|
+
end
|
14
|
+
|
15
|
+
attr_reader :method_help
|
16
|
+
attr_reader :method_help_supplemental
|
17
|
+
end
|
18
|
+
|
19
|
+
def help(method=nil)
|
20
|
+
|
21
|
+
if method
|
22
|
+
args = (self.class.method_help[method.to_s])
|
23
|
+
if !(self.respond_to?(method))
|
24
|
+
return "Sorry, I don't know method: #{method}"
|
25
|
+
end
|
26
|
+
|
27
|
+
args = args && args.map do |arg|
|
28
|
+
if arg.is_a?(Hash)
|
29
|
+
# If an argument is required, just list it
|
30
|
+
if arg.values.first==:req
|
31
|
+
arg.keys.first.to_s
|
32
|
+
# If it's optional, list it in brackets
|
33
|
+
elsif arg.values.first==:opt
|
34
|
+
"[#{arg.keys.first.to_s}]"
|
35
|
+
# If there is an array of options, list them
|
36
|
+
else
|
37
|
+
"#{arg.keys.first.to_s}=>#{arg.values.first.inspect}"
|
38
|
+
end
|
39
|
+
else
|
40
|
+
arg
|
41
|
+
end
|
42
|
+
end.join(", ")
|
43
|
+
|
44
|
+
extra_help = self.class.method_help_supplemental[method.to_s] || ""
|
45
|
+
|
46
|
+
puts %{ * #{method.to_s}#{'(' + args + ')' if args}#{extra_help}}
|
47
|
+
else
|
48
|
+
# These verbs help us figure out what 'group' the method belongs to
|
49
|
+
verbs = %w(describe display create get allocate clone export attach detach delete generate update remove restart rename)
|
50
|
+
verb_noun = /(#{verbs.join('|')})_(.*)(s|es)?/ # we're going to remove the verb and trailing 's'
|
51
|
+
|
52
|
+
methods = public_methods - Object.public_methods - ['post','get','put','delete','logger','logger=','help']
|
53
|
+
|
54
|
+
# Group methods by the noun they operate on
|
55
|
+
methods_grouped_by_noun = methods.inject({}) do |h, method|
|
56
|
+
method_name, verb, noun = *(method.match(verb_noun))
|
57
|
+
if method_name.nil?
|
58
|
+
# match failed
|
59
|
+
method_name = method
|
60
|
+
noun = "misc"
|
61
|
+
end
|
62
|
+
synonyms = {
|
63
|
+
:keypair => :key,
|
64
|
+
:address_offering => :address,
|
65
|
+
:location_by_name => :location,
|
66
|
+
:storage_offering => :storage,
|
67
|
+
:volume => :storage,
|
68
|
+
:volume_offering => :storage,
|
69
|
+
}
|
70
|
+
noun.gsub!(/s$/,'') unless noun =~ /address/
|
71
|
+
if synonyms.keys.include?(noun.to_sym)
|
72
|
+
noun = synonyms[noun.to_sym].to_s
|
73
|
+
end
|
74
|
+
h[noun] ||= []
|
75
|
+
h[noun] << method_name
|
76
|
+
h
|
77
|
+
end
|
78
|
+
methods_grouped_by_noun.keys.sort.each do |noun|
|
79
|
+
methods = methods_grouped_by_noun[noun]
|
80
|
+
next unless methods
|
81
|
+
puts "== #{noun.capitalize} ==\n\n"
|
82
|
+
methods.sort.each {|m| help(m)}
|
83
|
+
puts
|
84
|
+
end
|
85
|
+
nil
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
data/lib/smartcloud.rb
CHANGED
@@ -24,13 +24,14 @@ require 'xmlsimple'
|
|
24
24
|
require 'smartcloud_logger'
|
25
25
|
require 'curl_client'
|
26
26
|
require 'terminal-table'
|
27
|
+
require "dynamic_help_generator"
|
27
28
|
|
28
29
|
IBM_TOOLS_HOME=File.join(File.dirname(__FILE__), "cli_tools") unless defined?(IBM_TOOLS_HOME)
|
29
30
|
|
30
31
|
# Encapsulates communications with IBM SmartCloud via REST
|
31
32
|
|
32
33
|
class IBMSmartCloud
|
33
|
-
|
34
|
+
include DynamicHelpGenerator
|
34
35
|
attr_accessor :logger
|
35
36
|
|
36
37
|
def initialize(opts={})
|
@@ -59,57 +60,22 @@ class IBMSmartCloud
|
|
59
60
|
|
60
61
|
class << self
|
61
62
|
@config = YAML.load_file(File.join(File.dirname(__FILE__), "config/config.yml"))
|
62
|
-
attr_reader :method_help
|
63
|
-
attr_reader :method_help_supplemental
|
64
63
|
attr_reader :config
|
65
64
|
end
|
66
65
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
if method
|
76
|
-
args = (self.class.method_help[method.to_s])
|
77
|
-
if !(self.respond_to?(method))
|
78
|
-
return "Sorry, I don't know method: #{method}"
|
79
|
-
end
|
80
|
-
|
81
|
-
args = args && args.map do |arg|
|
82
|
-
if arg.is_a?(Hash)
|
83
|
-
# If an argument is required, just list it
|
84
|
-
if arg.values.first==:req
|
85
|
-
arg.keys.first.to_s
|
86
|
-
# If it's optional, list it in brackets
|
87
|
-
elsif arg.values.first==:opt
|
88
|
-
"[#{arg.keys.first.to_s}]"
|
89
|
-
# If there is an array of options, list them
|
90
|
-
else
|
91
|
-
"#{arg.keys.first.to_s}=>#{arg.values.first.inspect}"
|
92
|
-
end
|
93
|
-
else
|
94
|
-
arg
|
95
|
-
end
|
96
|
-
end.join(", ")
|
97
|
-
|
98
|
-
extra_help = self.class.method_help_supplemental[method.to_s] || ""
|
99
|
-
|
100
|
-
puts %{ * #{method.to_s}#{'(' + args + ')' if args}#{extra_help + "\n" if extra_help}}
|
66
|
+
# Get a list of data centers
|
67
|
+
help_for :describe_locations, [{:name => :opt}], %{
|
68
|
+
If name is given, will find the location by name
|
69
|
+
}
|
70
|
+
def describe_locations(name=nil)
|
71
|
+
locations = get("/locations").Location
|
72
|
+
if name
|
73
|
+
locations.detect {|loc| loc.Name =~ /#{name}/}
|
101
74
|
else
|
102
|
-
|
103
|
-
methods.sort.each {|m| help(m)}
|
104
|
-
nil
|
75
|
+
locations
|
105
76
|
end
|
106
77
|
end
|
107
78
|
|
108
|
-
# Get a list of data centers
|
109
|
-
def describe_locations
|
110
|
-
get("/locations").Location
|
111
|
-
end
|
112
|
-
|
113
79
|
def describe_location(location_id)
|
114
80
|
get("/locations/#{location_id}").Location
|
115
81
|
end
|
@@ -214,21 +180,26 @@ class IBMSmartCloud
|
|
214
180
|
post("/offerings/image/#{image_id}", :name => name, :description => description).ImageID
|
215
181
|
end
|
216
182
|
|
217
|
-
# Export an image to a volume
|
183
|
+
# Export an image to a volume - create the volume first
|
218
184
|
help_for :export_image, [{:name=>:req}, {:size => ['Small','Medium','Large']}, {:image_id => :req}, {:location => :req}]
|
219
185
|
def export_image(name, size, image_id, location)
|
220
186
|
# Note we figure out the correct size based on the name and location
|
221
187
|
storage_offering=describe_storage_offerings(location, size)
|
222
188
|
|
223
|
-
response = post("/storage", :name => name, :size => storage_offering.Capacity, :format => 'EXT3', :offeringID => storage_offering.ID, :location => location
|
189
|
+
response = post("/storage", :name => name, :size => storage_offering.Capacity, :format => 'EXT3', :offeringID => storage_offering.ID, :location => location)
|
190
|
+
volumeID = response.Volume.ID
|
191
|
+
|
192
|
+
poll_for_volume_state(volumeID, :unmounted)
|
193
|
+
|
194
|
+
response = put("/storage/#{volumeID}", :imageId => image_id)
|
224
195
|
response.Volume.ID
|
225
196
|
end
|
226
197
|
|
227
198
|
help_for :import_image, [{:name=>:req, :volume_id => :req}]
|
228
199
|
def import_image(name, volume_id)
|
229
200
|
# TODO: this is a complete guess as we have no info from IBM as to the URL for this api, only the parameters
|
230
|
-
response = post("/offerings/image", :
|
231
|
-
response.
|
201
|
+
response = post("/offerings/image", :volumeId => volume_id, :name => name)
|
202
|
+
response.Image.ID
|
232
203
|
end
|
233
204
|
|
234
205
|
# Launches a clone request and returns ID of new volume
|
@@ -289,8 +260,6 @@ class IBMSmartCloud
|
|
289
260
|
delete("/keys/#{name}")
|
290
261
|
true
|
291
262
|
end
|
292
|
-
alias remove_key remove_keypair
|
293
|
-
alias delete_key remove_keypair
|
294
263
|
|
295
264
|
help_for :describe_key, [:name]
|
296
265
|
def describe_key(name)
|
@@ -341,10 +310,6 @@ class IBMSmartCloud
|
|
341
310
|
arrayize(get("/keys").PublicKey)
|
342
311
|
end
|
343
312
|
|
344
|
-
def describe_unused_keys
|
345
|
-
describe_keys.select {|key| key.Instances == {}}
|
346
|
-
end
|
347
|
-
|
348
313
|
def display_keys
|
349
314
|
keys = describe_keys
|
350
315
|
|
@@ -638,14 +603,13 @@ class IBMSmartCloud
|
|
638
603
|
output = if @simulated_response
|
639
604
|
@simulated_response
|
640
605
|
else
|
641
|
-
@http_client.get File.join(@api_url, path)
|
606
|
+
@http_client.get File.join(@api_url, path), :accept => :response, :headers => "User-Agent: cloudapi"
|
642
607
|
end
|
643
608
|
|
644
609
|
# Save Response for posterity
|
645
610
|
if @save_response && !output.empty?
|
646
|
-
|
647
|
-
|
648
|
-
File.open(response_file,'w') {|f| f.write(output)}
|
611
|
+
logger.info "Saving response to: #{@save_response}"
|
612
|
+
File.open(@save_response,'w') {|f| f.write(output)}
|
649
613
|
end
|
650
614
|
|
651
615
|
if output && !output.empty?
|
@@ -723,6 +687,7 @@ class IBMSmartCloud
|
|
723
687
|
order_by = filters.delete(:order)
|
724
688
|
|
725
689
|
filters.each do |filter, value|
|
690
|
+
filter = filter.to_sym
|
726
691
|
value = value.to_s.upcase if (filter==:status || filter==:state)
|
727
692
|
if filter == :name || filter == :Name
|
728
693
|
instances = instances.select {|inst| inst.send(filter.to_s.capitalize) =~ /#{value}/}
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 3
|
8
|
-
-
|
9
|
-
version: 0.3.
|
8
|
+
- 1
|
9
|
+
version: 0.3.1
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- yan
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date:
|
18
|
+
date: 2012-03-12 00:00:00 -05:00
|
19
19
|
default_executable:
|
20
20
|
dependencies: []
|
21
21
|
|
@@ -41,6 +41,7 @@ files:
|
|
41
41
|
- cft_smartcloud.gemspec
|
42
42
|
- lib/config/config.yml
|
43
43
|
- lib/curl_client.rb
|
44
|
+
- lib/dynamic_help_generator.rb
|
44
45
|
- lib/hash_fix.rb
|
45
46
|
- lib/mime-types-1.16/History.txt
|
46
47
|
- lib/mime-types-1.16/Install.txt
|