bbcloud 0.7 → 0.8

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 CHANGED
@@ -1,4 +1,3 @@
1
1
  pkg/*
2
2
  *.gem
3
3
  .bundle
4
- lib/bbcloud/vendor/
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2010 Brightbox Systems Ltd.
1
+ Copyright (c) 2010 John Leach, Brightbox Systems Ltd <john@brightbox.co.uk>
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  of this software and associated documentation files (the "Software"), to deal
data/README CHANGED
@@ -1,9 +1,11 @@
1
1
  = Brightbox Cloud Command Line Interface
2
2
 
3
- bbcloud is a cli tool to interact with the (forthcoming) Brightbox
4
- cloud API.
3
+ brightbox-cli is a set of cli tools to interact with the Brightbox
4
+ Cloud API.
5
5
 
6
- http://www.brightbox.co.uk
6
+ http://beta.brightbox.com
7
+
8
+ http://docs.brightbox.com/cli
7
9
 
8
10
  == Packaging
9
11
 
@@ -12,11 +14,6 @@ http://www.brightbox.co.uk
12
14
  gems can be vendored into lib/bbcloud/vendor for packaging and will be
13
15
  prioritized over any gems.
14
16
 
15
- === GEM packaging
16
-
17
- The gem currently has our branch of fog vendored, as the official fog
18
- gem doesn't have our work merged in yet.
19
-
20
17
  === Debian/Ubuntu packaging
21
18
 
22
19
  Any gems that have equivalent packages available are set as
@@ -31,4 +28,29 @@ to packaging. These are:
31
28
  * ini
32
29
 
33
30
  Rubygems support can be disabled by defining the DISABLE_RUBYGEMS
34
- constant in lib/bbcloud/os_config.rb
31
+ constant in lib/bbcloud/os_config.rb
32
+
33
+ Ubuntu packaging scripts are available on the packaging-lucid git
34
+ branch.
35
+
36
+ == License
37
+
38
+ Copyright (c) 2010 John Leach, Brightbox Systems Ltd <john@brightbox.co.uk>
39
+
40
+ Permission is hereby granted, free of charge, to any person obtaining a copy
41
+ of this software and associated documentation files (the "Software"), to deal
42
+ in the Software without restriction, including without limitation the rights
43
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
44
+ copies of the Software, and to permit persons to whom the Software is
45
+ furnished to do so, subject to the following conditions:
46
+
47
+ The above copyright notice and this permission notice shall be included in
48
+ all copies or substantial portions of the Software.
49
+
50
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
51
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
52
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
53
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
54
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
55
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
56
+ THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,56 @@
1
+ = Brightbox Cloud Command Line Interface
2
+
3
+ brightbox-cli is a set of cli tools to interact with the Brightbox
4
+ Cloud API.
5
+
6
+ http://beta.brightbox.com
7
+
8
+ http://docs.brightbox.com/cli
9
+
10
+ == Packaging
11
+
12
+ === Vendoring libraries
13
+
14
+ gems can be vendored into lib/bbcloud/vendor for packaging and will be
15
+ prioritized over any gems.
16
+
17
+ === Debian/Ubuntu packaging
18
+
19
+ Any gems that have equivalent packages available are set as
20
+ dependencies to the Debian package. Any other gems are vendored prior
21
+ to packaging. These are:
22
+
23
+ * formatador (required by hirb)
24
+ * excon (required by fog)
25
+ * gli
26
+ * fog
27
+ * hirb
28
+ * ini
29
+
30
+ Rubygems support can be disabled by defining the DISABLE_RUBYGEMS
31
+ constant in lib/bbcloud/os_config.rb
32
+
33
+ Ubuntu packaging scripts are available on the packaging-lucid git
34
+ branch.
35
+
36
+ == License
37
+
38
+ Copyright (c) 2010 John Leach, Brightbox Systems Ltd <john@brightbox.co.uk>
39
+
40
+ Permission is hereby granted, free of charge, to any person obtaining a copy
41
+ of this software and associated documentation files (the "Software"), to deal
42
+ in the Software without restriction, including without limitation the rights
43
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
44
+ copies of the Software, and to permit persons to whom the Software is
45
+ furnished to do so, subject to the following conditions:
46
+
47
+ The above copyright notice and this permission notice shall be included in
48
+ all copies or substantial portions of the Software.
49
+
50
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
51
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
52
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
53
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
54
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
55
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
56
+ THE SOFTWARE.
data/bbcloud.gemspec CHANGED
@@ -21,7 +21,7 @@ Gem::Specification.new do |s|
21
21
 
22
22
  s.add_dependency 'gli', '1.1.2'
23
23
  s.add_dependency 'hirb', '0.3.5'
24
- s.add_dependency 'brightbox-fog', '0.3.16'
24
+ s.add_dependency 'fog', '=0.3.23'
25
25
  s.add_dependency 'excon', '>=0.2.4'
26
26
  s.add_dependency 'ini', '0.1.1'
27
27
  end
data/lib/bbcloud/api.rb CHANGED
@@ -24,6 +24,8 @@ module Brightbox
24
24
  @fog_model = m
25
25
  @id = m.id
26
26
  end
27
+ CONFIG.cache_id @id unless @id.nil?
28
+ @id
27
29
  end
28
30
 
29
31
  def fog_model
@@ -53,6 +55,8 @@ module Brightbox
53
55
  objects = args.collect do |arg|
54
56
  cached_get(arg)
55
57
  end
58
+ elsif args.respond_to? :to_s
59
+ objects = [cached_get(args.to_s)]
56
60
  end
57
61
  # wrap in our objects
58
62
  objects.collect! { |o| new(o) unless o.nil? }
@@ -87,7 +91,7 @@ module Brightbox
87
91
  if value
88
92
  value
89
93
  else
90
- debug "writing cache entry #{id}"
94
+ CONFIG.cache_id id
91
95
  @cache[id] = get(id)
92
96
  end
93
97
  end
@@ -100,6 +104,7 @@ module Brightbox
100
104
  @cache = {}
101
105
  all.each do |f|
102
106
  @cache[f.id] = f
107
+ CONFIG.cache_id f.id
103
108
  end
104
109
  end
105
110
 
data/lib/bbcloud/cli.rb CHANGED
@@ -1,7 +1,10 @@
1
1
  os_config = File.join(File.dirname(__FILE__), 'os_config.rb')
2
2
  require os_config if File.exist? os_config
3
3
 
4
- require "rubygems" unless defined?(DISABLE_RUBYGEMS)
4
+ unless defined?(DISABLE_RUBYGEMS)
5
+ require "rubygems"
6
+ gem "fog", "=0.3.23"
7
+ end
5
8
 
6
9
  # Add any vendored libraries into search path
7
10
  Dir.glob(File.join(File.dirname(__FILE__), 'vendor/*')).each do |f|
@@ -17,7 +20,7 @@ end
17
20
  require 'date'
18
21
  require 'gli'
19
22
  require 'bbcloud/tables'
20
- require 'brightbox-fog'
23
+ require 'fog'
21
24
 
22
25
  %w{api servers images types zones cloud_ips users accounts config version}.each do |f|
23
26
  require File.join(File.dirname(__FILE__), f)
@@ -120,7 +123,7 @@ end
120
123
  desc 'Display version information'
121
124
  command [:version] do |c|
122
125
  c.action do |global_options, options, args|
123
- info "Brightbox CLI version: #{Brightbox::VERSION}"
126
+ info "Brightbox CLI version: #{Brightbox::VERSION}, Fog version: #{Fog::VERSION}"
124
127
  end
125
128
  end
126
129
 
@@ -0,0 +1,22 @@
1
+ desc 'Lists the api clients defined in the config'
2
+ command [:client_list] do |c|
3
+
4
+ c.action do |global_options, options, args|
5
+
6
+ info "Using config file #{CONFIG.config_filename}"
7
+
8
+ clients = CONFIG.clients.collect do |calias|
9
+ c = CONFIG[calias]
10
+ calias = calias + "*" if CONFIG.client_name == calias and CONFIG.clients.size > 1
11
+ {
12
+ :alias => calias,
13
+ :client_id => c["client_id"],
14
+ :secret => c["secret"],
15
+ :api_url => c["api_url"],
16
+ :auth_url => c["auth_url"] || c["api_url"]
17
+ }
18
+ end
19
+
20
+ render_table clients, :fields => [:alias, :client_id, :secret, :api_url, :auth_url]
21
+ end
22
+ end
@@ -1,6 +1,7 @@
1
1
  desc 'Create servers'
2
2
  arg_name 'image_id'
3
3
  command [:create] do |c|
4
+
4
5
  c.desc "Number of servers to create"
5
6
  c.default_value 1
6
7
  c.flag [:i, "server-count"]
@@ -15,6 +16,14 @@ command [:create] do |c|
15
16
  c.desc "Friendly name of server"
16
17
  c.flag [:n, :name]
17
18
 
19
+ c.desc "Specify user data"
20
+ c.flag [:m, :user_data]
21
+
22
+ c.desc "Specify the user data from a local file"
23
+ c.flag [:f, :user_data_file]
24
+
25
+ c.desc "Don't base64 encode the user data"
26
+ c.switch [:e, :no_base64]
18
27
 
19
28
  c.action do |global_options, options, args|
20
29
 
@@ -50,15 +59,37 @@ command [:create] do |c|
50
59
  end
51
60
  raise "Couldn't find server type #{type_id}" unless type
52
61
 
53
- msg = "Creating #{options[:i]} '#{type.handle}' (#{type.id}) server#{options[:i] > 1 ? 's' : ''} with image #{image.name.strip} (#{image.id})"
62
+ user_data = options[:m]
63
+ user_data_file = options[:f]
64
+
65
+ if user_data_file
66
+ raise "Cannot specify user data on command line and in file at same time" if user_data
67
+ File.open(user_data_file, "r") do |f|
68
+ raise "User data file too big (>16k)" if f.size > 16 * 1024
69
+ user_data = f.read
70
+ end
71
+ end
72
+
73
+ if user_data
74
+ unless options[:e]
75
+ require 'base64'
76
+ user_data = Base64.encode64(user_data)
77
+ end
78
+ raise "User data too big (>16k)" if user_data.size > 16 * 1024
79
+ end
80
+
81
+ msg = "Creating #{options[:i] > 1 ? options[:i] : 'a'} #{type.handle} (#{type.id})"
82
+ msg << " server#{options[:i] > 1 ? 's' : ''} with image #{image.name.strip} (#{image.id})"
54
83
  msg << " in zone #{zone.handle} (#{zone})" if zone
84
+ msg << " with #{user_data.size / 1024}k of user data" if user_data
55
85
  info msg
56
86
  servers = []
57
87
  options[:i].times do
58
88
  servers << Server.create(:image_id => image.id,
59
89
  :flavor_id => type.id,
60
90
  :zone_id => zone.to_s,
61
- :name => options[:n])
91
+ :name => options[:n],
92
+ :user_data => user_data)
62
93
  end
63
94
  render_table(servers, global_options)
64
95
  end
@@ -7,10 +7,10 @@ command [:destroy] do |c|
7
7
  raise "you must specify the id of the server(s) you want to destroy"
8
8
  end
9
9
 
10
-
11
10
  servers = args.collect do |sid|
12
11
  info "Destroying server #{sid}"
13
12
  server = Server.find sid
13
+ raise "Server #{sid} does not exist" if server.nil?
14
14
  begin
15
15
  server.destroy
16
16
  rescue Brightbox::Api::Conflict => e
@@ -36,6 +36,25 @@ class BBConfig
36
36
  @config_filename
37
37
  end
38
38
 
39
+ def cache_path
40
+ if @cache_path
41
+ @cache_path
42
+ else
43
+ @cache_path = File.join(@dir, 'cache')
44
+ unless File.exists? @cache_path
45
+ begin
46
+ FileUtils.mkdir @cache_path
47
+ rescue Errno::EEXIST
48
+ end
49
+ end
50
+ @cache_path
51
+ end
52
+ end
53
+
54
+ def cache_id(cid)
55
+ FileUtils.touch(File.join(cache_path, cid)) unless cid.nil?
56
+ end
57
+
39
58
  def config
40
59
  return @config if @config
41
60
  return {} if @config == false
@@ -16,7 +16,6 @@ module Brightbox
16
16
  def attributes
17
17
  a = fog_model.attributes
18
18
  a[:image] = image
19
- a[:description] = description.to_s.strip
20
19
  a[:created_at] = created_at
21
20
  a[:created_on] = fog_model.created_at.strftime("%Y-%m-%d")
22
21
  a[:type] = server_type
@@ -0,0 +1,113 @@
1
+
2
+ = Conventional INI File Parsing and Writing
3
+
4
+ == Introduction
5
+
6
+ Ah yes, INI files. We love them. We hate them. We cannot escape
7
+ them. Originally made popular by Windows, INI files are everywhere
8
+ including in Samba[www.samba.org] and Trac[trac.edgewall.org]. This
9
+ gem has one goal: make INI file, structure, and stream manipulation
10
+ as fast, safe, and simple as possible. We take a modal approach
11
+ with a pluggable parser class.
12
+
13
+ == Sample File
14
+
15
+ ; some comment about section1
16
+ [section1]
17
+ var1 = foo
18
+ var2 = doodle
19
+
20
+ [section2]
21
+
22
+ ; some comment about var1
23
+ var1 = baz
24
+
25
+ ; some comment about var2
26
+ var2 = shoodle
27
+
28
+ == Conventional Format
29
+
30
+ There is no formal INI specification but most parsers observe the
31
+ following so we do also by default:
32
+
33
+ === Sections
34
+
35
+ Section declarations are wrapped in square brackets
36
+ (<tt>[section1]</tt>) with no spaces surrounding the section
37
+ name. Duplicate sections are discouraged but if included are merged.
38
+
39
+ === Parameters
40
+
41
+ The <tt>var1 = foo</tt> above is an example of a parameter, also
42
+ frequently referred to a property, item, or pair. Each parameter is
43
+ made up of a key name (<tt>var1</tt>), an equals sign (<tt>=</tt>),
44
+ and a value (<tt>foo</tt>) with optional spaces. Leading spaces
45
+ before the key name are allowed and leading spaces before or after
46
+ the value are trimmed. Values are literally the characters that
47
+ remain, even if quoted (<tt>var1 = "foo"</tt> would include the
48
+ quotes in the value). Duplicate parameters, either in the same
49
+ section or merged duplicate sections, play 'last one wins'.
50
+
51
+ === Comments
52
+
53
+ All lines starting with a semicolon (<tt>;</tt>) are assumed to be
54
+ comments and are ignored. This character must be the first on the line.
55
+
56
+ === Blank Lines
57
+
58
+ All lines that contain nothing but spaces are ignored.
59
+
60
+ === Line Endings
61
+
62
+ Lines end at either a CRLF or just a LF (CR=\015, LF=\012). Files
63
+ may mix the two within the same file to accomodate edits from
64
+ different platforms.
65
+
66
+ === Format Variations Supported
67
+
68
+ Because INI format is not formally specified, many variations exist
69
+ in the wild. Some of these are supported by extra parsers that are
70
+ included and set by changing the <tt>mode</tt> of the <ini> instance.
71
+
72
+ To maintain backward compatibility with the original 'inifile' gem,
73
+ the following variations are supported by the default parser:
74
+
75
+ * <b>Comments:</b> the comment character can be specified when an instance is created
76
+ * <b>Parameters:</b> separator character can be specified when an instance is created
77
+ * <b>Duplicate Sections:</b> merged
78
+ * <b>Duplicate Parameters:</b> the last one wins
79
+
80
+ === Currently Unsupported Format Variations
81
+
82
+ If it isn't listed above, chances are it isn't supported. But here
83
+ are some specific variations in case you are wondering (and, yes,
84
+ we do have plans eventually support them, either as defaults or options):
85
+
86
+ * Parameter value continuation with backslash (<tt>\\</tt>)
87
+ * Parameter value double-quoting with escapes (<tt>foo = "value with \\n in it"</tt>)
88
+ * Parameter values using braces (<tt>{}</tt>)
89
+ * Parameter values using simple commas parsing into arrays
90
+
91
+ == Copyright and License
92
+
93
+ Copyright (c) 2006-2007 The 'ini' and 'inifile' Gem Team
94
+
95
+ Permission is hereby granted, free of charge, to any person obtaining
96
+ a copy of this software and associated documentation files (the
97
+ "Software"), to deal in the Software without restriction, including
98
+ without limitation the rights to use, copy, modify, merge, publish,
99
+ distribute, sublicense, and/or sell copies of the Software, and to
100
+ permit persons to whom the Software is furnished to do so, subject to
101
+ the following conditions:
102
+
103
+ The above copyright notice and this permission notice shall be
104
+ included in all copies or substantial portions of the Software.
105
+
106
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
107
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
108
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
109
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
110
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
111
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
112
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
113
+
@@ -0,0 +1,266 @@
1
+ # $Id: ini.rb 1 2007-01-17 15:21:30Z ironmo $
2
+
3
+ #
4
+ # This class represents the INI file and can be used to parse, modify,
5
+ # and write INI files.
6
+ #
7
+ class Ini
8
+
9
+ # :stopdoc:
10
+ class Error < StandardError; end
11
+ # :startdoc:
12
+
13
+ #
14
+ # call-seq:
15
+ # IniFile.load( filename )
16
+ # IniFile.load( filename, options )
17
+ #
18
+ # Open the given _filename_ and load the contetns of the INI file.
19
+ # The following _options_ can be passed to this method:
20
+ #
21
+ # :comment => ';' The line comment character(s)
22
+ # :parameter => '=' The parameter / value separator
23
+ #
24
+ def self.load( filename, opts = {} )
25
+ new(filename, opts)
26
+ end
27
+
28
+ #
29
+ # call-seq:
30
+ # IniFile.new( filename )
31
+ # IniFile.new( filename, options )
32
+ #
33
+ # Create a new INI file using the given _filename_. If _filename_
34
+ # exists and is a regular file, then its contents will be parsed.
35
+ # The following _options_ can be passed to this method:
36
+ #
37
+ # :comment => ';' The line comment character(s)
38
+ # :parameter => '=' The parameter / value separator
39
+ #
40
+ def initialize( filename, opts = {} )
41
+ @fn = filename
42
+ @comment = opts[:comment] || ';'
43
+ @param = opts[:parameter] || '='
44
+ @ini = Hash.new {|h,k| h[k] = Hash.new}
45
+
46
+ @rgxp_comment = %r/\A\s*\z|\A\s*[#{@comment}]/
47
+ @rgxp_section = %r/\A\s*\[([^\]]+)\]/o
48
+ @rgxp_param = %r/\A([^#{@param}]+)#{@param}(.*)\z/
49
+
50
+ parse
51
+ end
52
+
53
+ #
54
+ # call-seq:
55
+ # write
56
+ # write( filename )
57
+ #
58
+ # Write the INI file contents to the filesystem. The given _filename_
59
+ # will be used to write the file. If _filename_ is not given, then the
60
+ # named used when constructing this object will be used.
61
+ #
62
+ def write( filename = nil )
63
+ @fn = filename unless filename.nil?
64
+
65
+ ::File.open(@fn, 'w') do |f|
66
+ @ini.each do |section,hash|
67
+ f.puts "[#{section}]"
68
+ hash.each {|param,val| f.puts "#{param} #{@param} #{val}"}
69
+ f.puts
70
+ end
71
+ end
72
+ self
73
+ end
74
+ alias :save :write
75
+
76
+ #
77
+ # call-seq:
78
+ # each {|section, parameter, value| block}
79
+ #
80
+ # Yield each _section_, _parameter_, _value_ in turn to the given
81
+ # _block_. The method returns immediately if no block is supplied.
82
+ #
83
+ def each
84
+ return unless block_given?
85
+ @ini.each do |section,hash|
86
+ hash.each do |param,val|
87
+ yield section, param, val
88
+ end
89
+ end
90
+ self
91
+ end
92
+
93
+ #
94
+ # call-seq:
95
+ # each_section {|section| block}
96
+ #
97
+ # Yield each _section_ in turn to the given _block_. The method returns
98
+ # immediately if no block is supplied.
99
+ #
100
+ def each_section
101
+ return unless block_given?
102
+ @ini.each_key {|section| yield section}
103
+ self
104
+ end
105
+
106
+ #
107
+ # call-seq:
108
+ # delete_section( section )
109
+ #
110
+ # Deletes the named _section_ from the INI file. Returns the
111
+ # parameter / value pairs if the section exists in the INI file. Otherwise,
112
+ # returns +nil+.
113
+ #
114
+ def delete_section( section )
115
+ @ini.delete section.to_s
116
+ end
117
+
118
+ #
119
+ # call-seq:
120
+ # ini_file[section]
121
+ #
122
+ # Get the hash of parameter/value pairs for the given _section_. If the
123
+ # _section_ hash does not exist it will be created.
124
+ #
125
+ def []( section )
126
+ return nil if section.nil?
127
+ @ini[section.to_s]
128
+ end
129
+
130
+ #
131
+ # call-seq:
132
+ # has_section?( section )
133
+ #
134
+ # Returns +true+ if the named _section_ exists in the INI file.
135
+ #
136
+ def has_section?( section )
137
+ @ini.has_key? section.to_s
138
+ end
139
+
140
+ #
141
+ # call-seq:
142
+ # sections
143
+ #
144
+ # Returns an array of the section names.
145
+ #
146
+ def sections
147
+ @ini.keys
148
+ end
149
+
150
+ #
151
+ # call-seq:
152
+ # freeze
153
+ #
154
+ # Freeze the state of the +IniFile+ object. Any attempts to change the
155
+ # object will raise an error.
156
+ #
157
+ def freeze
158
+ super
159
+ @ini.each_value {|h| h.freeze}
160
+ @ini.freeze
161
+ self
162
+ end
163
+
164
+ #
165
+ # call-seq:
166
+ # taint
167
+ #
168
+ # Marks the INI file as tainted -- this will traverse each section marking
169
+ # each section as tainted as well.
170
+ #
171
+ def taint
172
+ super
173
+ @ini.each_value {|h| h.taint}
174
+ @ini.taint
175
+ self
176
+ end
177
+
178
+ #
179
+ # call-seq:
180
+ # dup
181
+ #
182
+ # Produces a duplicate of this INI file. The duplicate is independent of the
183
+ # original -- i.e. the duplicate can be modified without changing the
184
+ # orgiinal. The tainted state of the original is copied to the duplicate.
185
+ #
186
+ def dup
187
+ other = super
188
+ other.instance_variable_set(:@ini, Hash.new {|h,k| h[k] = Hash.new})
189
+ @ini.each_pair {|s,h| other[s].merge! h}
190
+ other.taint if self.tainted?
191
+ other
192
+ end
193
+
194
+ #
195
+ # call-seq:
196
+ # clone
197
+ #
198
+ # Produces a duplicate of this INI file. The duplicate is independent of the
199
+ # original -- i.e. the duplicate can be modified without changing the
200
+ # orgiinal. The tainted state and the frozen state of the original is copied
201
+ # to the duplicate.
202
+ #
203
+ def clone
204
+ other = dup
205
+ other.freeze if self.frozen?
206
+ other
207
+ end
208
+
209
+ #
210
+ # call-seq:
211
+ # eql?( other )
212
+ #
213
+ # Returns +true+ if the _other_ object is equivalent to this INI file. For
214
+ # two INI files to be equivalent, they must have the same sections with the
215
+ # same parameter / value pairs in each section.
216
+ #
217
+ def eql?( other )
218
+ return true if equal? other
219
+ return false unless other.instance_of? self.class
220
+ @ini == other.instance_variable_get(:@ini)
221
+ end
222
+ alias :== :eql?
223
+
224
+
225
+ private
226
+ #
227
+ # call-seq
228
+ # parse
229
+ #
230
+ # Parse the ini file contents.
231
+ #
232
+ def parse
233
+ return unless ::Kernel.test ?f, @fn
234
+ section = nil
235
+
236
+ ::File.open(@fn, 'r') do |f|
237
+ while line = f.gets
238
+ line = line.chomp
239
+
240
+ case line
241
+ # ignore blank lines and comment lines
242
+ when @rgxp_comment
243
+ next
244
+
245
+ # this is a section declaration
246
+ when @rgxp_section
247
+ section = @ini[$1.strip]
248
+
249
+ # otherwise we have a parameter
250
+ when @rgxp_param
251
+ begin
252
+ section[$1.strip] = $2.strip
253
+ rescue NoMethodError
254
+ raise Error, "parameter encountered before first section"
255
+ end
256
+
257
+ else
258
+ raise Error, "could not parse line '#{line}"
259
+ end
260
+ end # while
261
+ end # File.open
262
+ end
263
+
264
+ end
265
+
266
+ # EOF
@@ -0,0 +1,10 @@
1
+ # $Id: inifile.rb 1 2007-01-17 15:21:30Z ironmo $
2
+
3
+ # The 'inifile' gem will eventually be deprecated in favor of the
4
+ # 'ini' gem as it becomes able to handle streams, stringio and string buffers of INI
5
+ # formatted data.
6
+
7
+ require 'ini'
8
+
9
+ class IniFile < Ini
10
+ end
@@ -0,0 +1,6 @@
1
+ ; having a paramater / value pair outside a section is an error
2
+ one = 1
3
+
4
+ [section_one]
5
+ one = 1
6
+ two = 2
@@ -0,0 +1,6 @@
1
+ [section_one]
2
+ one = 1
3
+ two = 2
4
+
5
+ ; the following is not a valid line
6
+ invalid line
@@ -0,0 +1,5 @@
1
+ # comments should be ignored
2
+ [section_one]
3
+ one = 1
4
+ two = 2
5
+
@@ -0,0 +1,17 @@
1
+ [section_one]
2
+ one = 1
3
+ two = 2
4
+
5
+ [section_two]
6
+ three = 3
7
+
8
+ ; comments should be ignored
9
+ [section three]
10
+ four =4
11
+ five=5
12
+ six =6
13
+
14
+ [section_four]
15
+ [section_five]
16
+ seven and eight= 7 & 8
17
+
@@ -0,0 +1,7 @@
1
+ # comments should be ignored
2
+ ; multiple comments characeters are supported
3
+ ; (I'm lookin' at you, samba)
4
+ [section_one]
5
+ one = 1
6
+ two = 2
7
+
@@ -0,0 +1,5 @@
1
+ ; comments should be ignored
2
+ [section_one]
3
+ one : 1
4
+ two:2
5
+
@@ -0,0 +1,273 @@
1
+ # Code Generated by ZenTest v. 3.3.0
2
+ # classname: asrt / meth = ratio%
3
+ # Rini::IniFile: 0 / 9 = 0.00%
4
+
5
+ $:.unshift(File.expand_path(File.dirname(__FILE__) + "/../lib"))
6
+ require "inifile"
7
+
8
+ begin; require 'turn'; rescue LoadError; end
9
+ require 'test/unit' unless defined? $ZENTEST and $ZENTEST
10
+
11
+ class TestIniFile < Test::Unit::TestCase
12
+
13
+ def setup
14
+ @ini_file = ::IniFile.new 'test/data/good.ini'
15
+ @contents = [
16
+ ['section_one', 'one', '1'],
17
+ ['section_one', 'two', '2'],
18
+ ['section_two', 'three', '3'],
19
+ ['section three', 'four', '4'],
20
+ ['section three', 'five', '5'],
21
+ ['section three', 'six', '6'],
22
+ ['section_five', 'seven and eight', '7 & 8']
23
+ ].sort
24
+ end
25
+
26
+ def test_class_load
27
+ ini_file = ::IniFile.load 'test/data/good.ini'
28
+ assert_instance_of ::IniFile, ini_file
29
+
30
+ # see if we can parse different style comments
31
+ assert_raise(::IniFile::Error) {::IniFile.load 'test/data/comment.ini'}
32
+
33
+ ini_file = ::IniFile.load 'test/data/comment.ini', :comment => '#'
34
+ assert_instance_of ::IniFile, ini_file
35
+
36
+ # see if we can parse mixed style comments
37
+ assert_raise(::IniFile::Error) {::IniFile.load 'test/data/mixed_comment.ini'}
38
+
39
+ ini_file = ::IniFile.load 'test/data/mixed_comment.ini', :comment => ';#'
40
+ assert_instance_of ::IniFile, ini_file
41
+
42
+ # see if we can parse different style param separators
43
+ assert_raise(::IniFile::Error) {::IniFile.load 'test/data/param.ini'}
44
+
45
+ ini_file = ::IniFile.load 'test/data/param.ini', :parameter => ':'
46
+ assert_instance_of ::IniFile, ini_file
47
+
48
+ # make sure we error out on files with bad lines
49
+ assert_raise(::IniFile::Error) {::IniFile.load 'test/data/bad_1.ini'}
50
+ assert_raise(::IniFile::Error) {::IniFile.load 'test/data/bad_2.ini'}
51
+ end
52
+
53
+ def test_clone
54
+ clone = @ini_file.clone
55
+ assert_equal @ini_file, clone
56
+ assert !clone.tainted?
57
+ assert !clone.frozen?
58
+
59
+ # the clone should be completely independent of the original
60
+ clone['new_section']['one'] = 1
61
+ assert_not_equal @ini_file, clone
62
+
63
+ # the tainted state is copied to clones
64
+ @ini_file.taint
65
+ assert @ini_file.tainted?
66
+
67
+ clone = @ini_file.clone
68
+ assert clone.tainted?
69
+
70
+ # the frozen state is also copied to clones
71
+ @ini_file.freeze
72
+ assert @ini_file.frozen?
73
+
74
+ clone = @ini_file.clone
75
+ assert clone.tainted?
76
+ assert clone.frozen?
77
+ end
78
+
79
+ def test_delete_section
80
+ assert_nil @ini_file.delete_section('section_nil')
81
+
82
+ h = {'one' => '1', 'two' => '2'}
83
+ assert_equal true, @ini_file.has_section?('section_one')
84
+ assert_equal h, @ini_file.delete_section('section_one')
85
+ assert_equal false, @ini_file.has_section?('section_one')
86
+ assert_nil @ini_file.delete_section('section_one')
87
+ end
88
+
89
+ def test_dup
90
+ dup = @ini_file.dup
91
+ assert_equal @ini_file, dup
92
+ assert !dup.tainted?
93
+ assert !dup.frozen?
94
+
95
+ # the duplicate should be completely independent of the original
96
+ dup['new_section']['one'] = 1
97
+ assert_not_equal @ini_file, dup
98
+
99
+ # the tainted state is copied to duplicates
100
+ @ini_file.taint
101
+ assert @ini_file.tainted?
102
+
103
+ dup = @ini_file.dup
104
+ assert dup.tainted?
105
+
106
+ # the frozen state, however, is not
107
+ @ini_file.freeze
108
+ assert @ini_file.frozen?
109
+
110
+ dup = @ini_file.dup
111
+ assert dup.tainted?
112
+ assert !dup.frozen?
113
+ end
114
+
115
+ def test_each
116
+ ary = []
117
+ @ini_file.each {|*args| ary << args}
118
+
119
+ assert_equal @contents, ary.sort
120
+
121
+ ary = []
122
+ ::IniFile.new('temp.ini').each {|*args| ary << args}
123
+ assert_equal [], ary
124
+ end
125
+
126
+ def test_each_section
127
+ expected = [
128
+ 'section_one', 'section_two', 'section three',
129
+ 'section_four', 'section_five'
130
+ ].sort
131
+
132
+ ary = []
133
+ @ini_file.each_section {|section| ary << section}
134
+
135
+ assert_equal expected, ary.sort
136
+
137
+ ary = []
138
+ ::IniFile.new('temp.ini').each_section {|section| ary << section}
139
+ assert_equal [], ary
140
+ end
141
+
142
+ def test_eql_eh
143
+ assert @ini_file.eql?(@ini_file)
144
+ assert @ini_file.eql?(@ini_file.clone)
145
+ assert !@ini_file.eql?('string')
146
+ assert !@ini_file.eql?(IniFile.new(''))
147
+ end
148
+
149
+ def test_freeze
150
+ assert_equal false, @ini_file.frozen?
151
+ @ini_file.each_section do |s|
152
+ assert_equal false, @ini_file[s].frozen?
153
+ end
154
+
155
+ @ini_file.freeze
156
+
157
+ assert_equal true, @ini_file.frozen?
158
+ @ini_file.each_section do |s|
159
+ assert_equal true, @ini_file[s].frozen?
160
+ end
161
+ end
162
+
163
+ def test_has_section_eh
164
+ assert_equal true, @ini_file.has_section?('section_one')
165
+ assert_equal false, @ini_file.has_section?('section_ten')
166
+ assert_equal true, @ini_file.has_section?(:section_two)
167
+ assert_equal false, @ini_file.has_section?(nil)
168
+
169
+ ini_file = ::IniFile.new 'temp.ini'
170
+ assert_equal false, ini_file.has_section?('section_one')
171
+ assert_equal false, ini_file.has_section?('one')
172
+ assert_equal false, ini_file.has_section?('two')
173
+ end
174
+
175
+ def test_index
176
+ expected = {
177
+ 'one' => '1',
178
+ 'two' => '2'
179
+ }
180
+ assert_equal expected, @ini_file[:section_one]
181
+
182
+ expected = {'three' => '3'}
183
+ assert_equal expected, @ini_file['section_two']
184
+
185
+ expected = {
186
+ 'four' => '4',
187
+ 'five' => '5',
188
+ 'six' => '6',
189
+ }
190
+ assert_equal expected, @ini_file['section three']
191
+
192
+ expected = {}
193
+ assert_equal expected, @ini_file['section_four']
194
+
195
+ expected = {'seven and eight' => '7 & 8'}
196
+ assert_equal expected, @ini_file['section_five']
197
+
198
+ expected = {}
199
+ assert_equal expected, @ini_file['section_six']
200
+
201
+ assert_nil @ini_file[nil]
202
+
203
+ expected = {}
204
+ ini_file = ::IniFile.new 'temp.ini'
205
+ assert_equal expected, ini_file['section_one']
206
+ assert_equal expected, ini_file['one']
207
+ assert_nil ini_file[nil]
208
+ end
209
+
210
+ def test_initialize
211
+ # see if we can parse different style comments
212
+ assert_raise(::IniFile::Error) {::IniFile.new 'test/data/comment.ini'}
213
+
214
+ ini_file = ::IniFile.new 'test/data/comment.ini', :comment => '#'
215
+ assert_equal true, ini_file.has_section?('section_one')
216
+
217
+ # see if we can parse different style param separators
218
+ assert_raise(::IniFile::Error) {::IniFile.new 'test/data/param.ini'}
219
+
220
+ ini_file = ::IniFile.new 'test/data/param.ini', :parameter => ':'
221
+ assert_equal true, ini_file.has_section?('section_one')
222
+ assert_equal '1', ini_file['section_one']['one']
223
+ assert_equal '2', ini_file['section_one']['two']
224
+
225
+ # make sure we error out on files with bad lines
226
+ assert_raise(::IniFile::Error) {::IniFile.new 'test/data/bad_1.ini'}
227
+ assert_raise(::IniFile::Error) {::IniFile.new 'test/data/bad_2.ini'}
228
+ end
229
+
230
+ def test_sections
231
+ expected = [
232
+ 'section_one', 'section_two', 'section three',
233
+ 'section_four', 'section_five'
234
+ ].sort
235
+
236
+ assert_equal expected, @ini_file.sections.sort
237
+
238
+ ini_file = ::IniFile.new 'temp.ini'
239
+ assert_equal [], ini_file.sections
240
+ end
241
+
242
+ def test_taint
243
+ assert_equal false, @ini_file.tainted?
244
+ @ini_file.each_section do |s|
245
+ assert_equal false, @ini_file[s].tainted?
246
+ end
247
+
248
+ @ini_file.taint
249
+
250
+ assert_equal true, @ini_file.tainted?
251
+ @ini_file.each_section do |s|
252
+ assert_equal true, @ini_file[s].tainted?
253
+ end
254
+ end
255
+
256
+ def test_write
257
+ tmp = 'test/data/temp.ini'
258
+ ::File.delete tmp if ::Kernel.test(?f, tmp)
259
+
260
+ @ini_file.save tmp
261
+ assert_equal true, ::Kernel.test(?f, tmp)
262
+
263
+ ::File.delete tmp if ::Kernel.test(?f, tmp)
264
+
265
+ ini_file = ::IniFile.new tmp
266
+ ini_file.save
267
+ assert_nil ::Kernel.test(?s, tmp)
268
+
269
+ ::File.delete tmp if ::Kernel.test(?f, tmp)
270
+ end
271
+ end
272
+
273
+ # EOF
@@ -1,3 +1,3 @@
1
1
  module Brightbox
2
- VERSION = "0.7"
2
+ VERSION = "0.8"
3
3
  end
@@ -0,0 +1,92 @@
1
+ # brightbox cli tools completion
2
+ #
3
+
4
+ _brightbox()
5
+ {
6
+ local cur prev
7
+
8
+ COMPREPLY=()
9
+ _get_comp_words_by_ref cur prev
10
+
11
+ command=''
12
+ for (( i=1; i < COMP_CWORD; i++ )); do
13
+ if [[ "${COMP_WORDS[i]}" != -* ]]; then
14
+ command=${COMP_WORDS[i]}
15
+ break
16
+ fi
17
+ done
18
+
19
+ case $1 in
20
+ brightbox-servers)
21
+ case $command in
22
+ create)
23
+ if [[ "$cur" == -* ]] ; then
24
+ COMPREPLY=( $( compgen -W '--name --type --zone --server-count --user-data-file --user-data --no-base64' -- "$cur" ) )
25
+ else
26
+ test -d ~/.brightbox/cache && COMPREPLY=( $( compgen -W '`ls ~/.brightbox/cache/`' -- "$cur" ) )
27
+ fi
28
+ ;;
29
+ destroy|list|show|shutdown|snapshot|start|stop)
30
+ test -d ~/.brightbox/cache && COMPREPLY=( $( compgen -W '`ls ~/.brightbox/cache/`' -- "$cur" ) )
31
+ ;;
32
+ *)
33
+ COMPREPLY=( $( compgen -W 'create destroy help list show shutdown snapshot start stop' -- "$cur" ) )
34
+ ;;
35
+ esac
36
+ ;;
37
+ brightbox-images)
38
+ case $command in
39
+ destroy|list|show)
40
+ test -d ~/.brightbox/cache && COMPREPLY=( $( compgen -W '`ls ~/.brightbox/cache/`' -- "$cur" ) )
41
+ ;;
42
+ *)
43
+ COMPREPLY=( $( compgen -W 'destroy help list show' -- "$cur" ) )
44
+ ;;
45
+ esac
46
+ ;;
47
+ brightbox-cloudips)
48
+ case $command in
49
+ map)
50
+ if [[ "$cur" == -* ]] ; then
51
+ COMPREPLY=( $( compgen -W '--unmap' -- "$cur" ) )
52
+ else
53
+ test -d ~/.brightbox/cache && COMPREPLY=( $( compgen -W '`ls ~/.brightbox/cache/`' -- "$cur" ) )
54
+ fi
55
+ ;;
56
+ create|destroy|list|unmap|show)
57
+ test -d ~/.brightbox/cache && COMPREPLY=( $( compgen -W '`ls ~/.brightbox/cache/`' -- "$cur" ) )
58
+ ;;
59
+ *)
60
+ COMPREPLY=( $( compgen -W 'create destroy list ummap show map help' -- "$cur" ) )
61
+ ;;
62
+ esac
63
+ ;;
64
+ brightbox-config)
65
+ case $command in
66
+ client_add)
67
+ if [[ "$cur" == -* ]] ; then
68
+ COMPREPLY=( $( compgen -W '--alias --auth-url' -- "$cur" ) )
69
+ fi
70
+ ;;
71
+ client_default|client_remove|client_list)
72
+ ;;
73
+ *)
74
+ COMPREPLY=( $( compgen -W 'client_add client_remove client_default help' -- "$cur" ) )
75
+ ;;
76
+ esac
77
+ ;;
78
+ esac
79
+
80
+ }
81
+ complete -F _brightbox -o filenames brightbox-servers
82
+ complete -F _brightbox -o filenames brightbox-images
83
+ complete -F _brightbox -o filenames brightbox-cloudips
84
+ complete -F _brightbox -o filenames brightbox-config
85
+
86
+ # Local variables:
87
+ # mode: shell-script
88
+ # sh-basic-offset: 4
89
+ # sh-indent-comment: t
90
+ # indent-tabs-mode: nil
91
+ # End:
92
+ # ex: ts=4 sw=4 et filetype=sh
metadata CHANGED
@@ -1,12 +1,11 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bbcloud
3
3
  version: !ruby/object:Gem::Version
4
- hash: 5
5
4
  prerelease: false
6
5
  segments:
7
6
  - 0
8
- - 7
9
- version: "0.7"
7
+ - 8
8
+ version: "0.8"
10
9
  platform: ruby
11
10
  authors:
12
11
  - John Leach
@@ -14,7 +13,7 @@ autorequire:
14
13
  bindir: bin
15
14
  cert_chain: []
16
15
 
17
- date: 2010-11-16 00:00:00 +00:00
16
+ date: 2010-11-20 00:00:00 +00:00
18
17
  default_executable:
19
18
  dependencies:
20
19
  - !ruby/object:Gem::Dependency
@@ -25,7 +24,6 @@ dependencies:
25
24
  requirements:
26
25
  - - "="
27
26
  - !ruby/object:Gem::Version
28
- hash: 23
29
27
  segments:
30
28
  - 1
31
29
  - 1
@@ -41,7 +39,6 @@ dependencies:
41
39
  requirements:
42
40
  - - "="
43
41
  - !ruby/object:Gem::Version
44
- hash: 25
45
42
  segments:
46
43
  - 0
47
44
  - 3
@@ -50,19 +47,18 @@ dependencies:
50
47
  type: :runtime
51
48
  version_requirements: *id002
52
49
  - !ruby/object:Gem::Dependency
53
- name: brightbox-fog
50
+ name: fog
54
51
  prerelease: false
55
52
  requirement: &id003 !ruby/object:Gem::Requirement
56
53
  none: false
57
54
  requirements:
58
55
  - - "="
59
56
  - !ruby/object:Gem::Version
60
- hash: 51
61
57
  segments:
62
58
  - 0
63
59
  - 3
64
- - 16
65
- version: 0.3.16
60
+ - 23
61
+ version: 0.3.23
66
62
  type: :runtime
67
63
  version_requirements: *id003
68
64
  - !ruby/object:Gem::Dependency
@@ -73,7 +69,6 @@ dependencies:
73
69
  requirements:
74
70
  - - ">="
75
71
  - !ruby/object:Gem::Version
76
- hash: 31
77
72
  segments:
78
73
  - 0
79
74
  - 2
@@ -89,7 +84,6 @@ dependencies:
89
84
  requirements:
90
85
  - - "="
91
86
  - !ruby/object:Gem::Version
92
- hash: 25
93
87
  segments:
94
88
  - 0
95
89
  - 1
@@ -117,6 +111,7 @@ files:
117
111
  - .gitignore
118
112
  - LICENSE
119
113
  - README
114
+ - README.rdoc
120
115
  - Rakefile
121
116
  - bbcloud.gemspec
122
117
  - bin/brightbox-accounts
@@ -142,6 +137,7 @@ files:
142
137
  - lib/bbcloud/commands/cloudips-unmap.rb
143
138
  - lib/bbcloud/commands/config-client-add.rb
144
139
  - lib/bbcloud/commands/config-client-default.rb
140
+ - lib/bbcloud/commands/config-client-list.rb
145
141
  - lib/bbcloud/commands/config-client-remove.rb
146
142
  - lib/bbcloud/commands/images-destroy.rb
147
143
  - lib/bbcloud/commands/images-list.rb
@@ -166,8 +162,19 @@ files:
166
162
  - lib/bbcloud/tables.rb
167
163
  - lib/bbcloud/types.rb
168
164
  - lib/bbcloud/users.rb
165
+ - lib/bbcloud/vendor/brightbox-ini/README
166
+ - lib/bbcloud/vendor/brightbox-ini/lib/ini.rb
167
+ - lib/bbcloud/vendor/brightbox-ini/lib/inifile.rb
168
+ - lib/bbcloud/vendor/brightbox-ini/test/data/bad_1.ini
169
+ - lib/bbcloud/vendor/brightbox-ini/test/data/bad_2.ini
170
+ - lib/bbcloud/vendor/brightbox-ini/test/data/comment.ini
171
+ - lib/bbcloud/vendor/brightbox-ini/test/data/good.ini
172
+ - lib/bbcloud/vendor/brightbox-ini/test/data/mixed_comment.ini
173
+ - lib/bbcloud/vendor/brightbox-ini/test/data/param.ini
174
+ - lib/bbcloud/vendor/brightbox-ini/test/test_inifile.rb
169
175
  - lib/bbcloud/version.rb
170
176
  - lib/bbcloud/zones.rb
177
+ - tools/bash_completion_script
171
178
  has_rdoc: true
172
179
  homepage: http://docs.brightbox.com/cli
173
180
  licenses: []
@@ -182,7 +189,6 @@ required_ruby_version: !ruby/object:Gem::Requirement
182
189
  requirements:
183
190
  - - ">="
184
191
  - !ruby/object:Gem::Version
185
- hash: 3
186
192
  segments:
187
193
  - 0
188
194
  version: "0"
@@ -191,7 +197,6 @@ required_rubygems_version: !ruby/object:Gem::Requirement
191
197
  requirements:
192
198
  - - ">="
193
199
  - !ruby/object:Gem::Version
194
- hash: 3
195
200
  segments:
196
201
  - 0
197
202
  version: "0"