continuent-tools-core 0.1.6 → 0.5.0
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.
- checksums.yaml +4 -4
- data/lib/continuent-tools-core.rb +0 -11
- data/lib/iniparse.rb +66 -0
- data/lib/iniparse/LICENSE +19 -0
- data/lib/iniparse/document.rb +84 -0
- data/lib/iniparse/generator.rb +203 -0
- data/lib/iniparse/line_collection.rb +170 -0
- data/lib/iniparse/lines.rb +327 -0
- data/lib/iniparse/parser.rb +110 -0
- data/lib/tungsten/api.rb +3 -3
- data/lib/tungsten/common.rb +2 -2
- data/lib/tungsten/exec.rb +1 -10
- data/lib/tungsten/iniparse.rb +53 -0
- data/lib/tungsten/install.rb +111 -3
- data/lib/tungsten/properties.rb +11 -19
- data/lib/tungsten/script.rb +124 -2
- data/lib/tungsten/util.rb +94 -1
- metadata +11 -3
@@ -0,0 +1,327 @@
|
|
1
|
+
module IniParse
|
2
|
+
module Lines
|
3
|
+
# A base class from which other line types should inherit.
|
4
|
+
module Line
|
5
|
+
# ==== Parameters
|
6
|
+
# opts<Hash>:: Extra options for the line.
|
7
|
+
#
|
8
|
+
def initialize(opts = {})
|
9
|
+
@comment = opts.fetch(:comment, nil)
|
10
|
+
@comment_sep = opts.fetch(:comment_sep, ';')
|
11
|
+
@comment_prefix = opts.fetch(:comment_prefix, ' ')
|
12
|
+
@comment_offset = opts.fetch(:comment_offset, 0)
|
13
|
+
@indent = opts.fetch(:indent, '')
|
14
|
+
end
|
15
|
+
|
16
|
+
# Returns if this line has an inline comment.
|
17
|
+
def has_comment?
|
18
|
+
not @comment.nil?
|
19
|
+
end
|
20
|
+
|
21
|
+
# Returns this line as a string as it would be represented in an INI
|
22
|
+
# document.
|
23
|
+
def to_ini
|
24
|
+
ini = line_contents
|
25
|
+
ini = @indent + ini if @indent
|
26
|
+
|
27
|
+
if has_comment?
|
28
|
+
ini += ' ' if ini =~ /\S/ # not blank
|
29
|
+
ini = ini.ljust(@comment_offset)
|
30
|
+
ini += comment
|
31
|
+
end
|
32
|
+
|
33
|
+
ini
|
34
|
+
end
|
35
|
+
|
36
|
+
# Returns the contents for this line.
|
37
|
+
def line_contents
|
38
|
+
''
|
39
|
+
end
|
40
|
+
|
41
|
+
# Returns the inline comment for this line. Includes the comment
|
42
|
+
# separator at the beginning of the string.
|
43
|
+
def comment
|
44
|
+
"#{ @comment_sep }#{ @comment_prefix }#{ @comment }"
|
45
|
+
end
|
46
|
+
|
47
|
+
# Returns whether this is a line which has no data.
|
48
|
+
def blank?
|
49
|
+
false
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Represents a section header in an INI document. Section headers consist
|
54
|
+
# of a string of characters wrapped in square brackets.
|
55
|
+
#
|
56
|
+
# [section]
|
57
|
+
# key=value
|
58
|
+
# etc
|
59
|
+
# ...
|
60
|
+
#
|
61
|
+
class Section
|
62
|
+
include Line
|
63
|
+
|
64
|
+
@regex = /^\[ # Opening bracket
|
65
|
+
([^\]]+) # Section name
|
66
|
+
\]$ # Closing bracket
|
67
|
+
/x
|
68
|
+
|
69
|
+
attr_accessor :key
|
70
|
+
attr_reader :lines
|
71
|
+
|
72
|
+
include Enumerable
|
73
|
+
|
74
|
+
# ==== Parameters
|
75
|
+
# key<String>:: The section name.
|
76
|
+
# opts<Hash>:: Extra options for the line.
|
77
|
+
#
|
78
|
+
def initialize(key, opts = {})
|
79
|
+
super(opts)
|
80
|
+
@key = key.to_s
|
81
|
+
@lines = IniParse::OptionCollection.new
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.parse(line, opts)
|
85
|
+
if m = @regex.match(line)
|
86
|
+
[:section, m[1], opts]
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
# Returns this line as a string as it would be represented in an INI
|
91
|
+
# document. Includes options, comments and blanks.
|
92
|
+
def to_ini
|
93
|
+
coll = lines.to_a
|
94
|
+
|
95
|
+
if coll.any?
|
96
|
+
super + $/ + coll.to_a.map do |line|
|
97
|
+
if line.kind_of?(Array)
|
98
|
+
line.map { |dup_line| dup_line.to_ini }.join($/)
|
99
|
+
else
|
100
|
+
line.to_ini
|
101
|
+
end
|
102
|
+
end.join($/)
|
103
|
+
else
|
104
|
+
super
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
# Enumerates through each Option in this section.
|
109
|
+
#
|
110
|
+
# Does not yield blank and comment lines by default; if you want _all_
|
111
|
+
# lines to be yielded, pass true.
|
112
|
+
#
|
113
|
+
# ==== Parameters
|
114
|
+
# include_blank<Boolean>:: Include blank/comment lines?
|
115
|
+
#
|
116
|
+
def each(*args, &blk)
|
117
|
+
@lines.each(*args, &blk)
|
118
|
+
end
|
119
|
+
|
120
|
+
# Adds a new option to this section, or updates an existing one.
|
121
|
+
#
|
122
|
+
# Note that +[]=+ has no knowledge of duplicate options and will happily
|
123
|
+
# overwrite duplicate options with your new value.
|
124
|
+
#
|
125
|
+
# section['an_option']
|
126
|
+
# # => ['duplicate one', 'duplicate two', ...]
|
127
|
+
# section['an_option'] = 'new value'
|
128
|
+
# section['an_option]
|
129
|
+
# # => 'new value'
|
130
|
+
#
|
131
|
+
# If you do not wish to overwrite duplicates, but wish instead for your
|
132
|
+
# new option to be considered a duplicate, use +add_option+ instead.
|
133
|
+
#
|
134
|
+
def []=(key, value)
|
135
|
+
@lines[key.to_s] = IniParse::Lines::Option.new(key.to_s, value)
|
136
|
+
end
|
137
|
+
|
138
|
+
# Returns the value of an option identified by +key+.
|
139
|
+
#
|
140
|
+
# Returns nil if there is no corresponding option. If the key provided
|
141
|
+
# matches a set of duplicate options, an array will be returned containing
|
142
|
+
# the value of each option.
|
143
|
+
#
|
144
|
+
def [](key)
|
145
|
+
key = key.to_s
|
146
|
+
|
147
|
+
if @lines.has_key?(key)
|
148
|
+
if (match = @lines[key]).kind_of?(Array)
|
149
|
+
match.map { |line| line.value }
|
150
|
+
else
|
151
|
+
match.value
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
# Deletes the option identified by +key+.
|
157
|
+
#
|
158
|
+
# Returns the section.
|
159
|
+
#
|
160
|
+
def delete(*args)
|
161
|
+
@lines.delete(*args)
|
162
|
+
self
|
163
|
+
end
|
164
|
+
|
165
|
+
# Like [], except instead of returning just the option value, it returns
|
166
|
+
# the matching line instance.
|
167
|
+
#
|
168
|
+
# Will return an array of lines if the key matches a set of duplicates.
|
169
|
+
#
|
170
|
+
def option(key)
|
171
|
+
@lines[key.to_s]
|
172
|
+
end
|
173
|
+
|
174
|
+
# Returns true if an option with the given +key+ exists in this section.
|
175
|
+
def has_option?(key)
|
176
|
+
@lines.has_key?(key.to_s)
|
177
|
+
end
|
178
|
+
|
179
|
+
# Merges section +other+ into this one. If the section being merged into
|
180
|
+
# this one contains options with the same key, they will be handled as
|
181
|
+
# duplicates.
|
182
|
+
#
|
183
|
+
# ==== Parameters
|
184
|
+
# other<IniParse::Section>:: The section to merge into this one.
|
185
|
+
#
|
186
|
+
def merge!(other)
|
187
|
+
other.lines.each(true) do |line|
|
188
|
+
if line.kind_of?(Array)
|
189
|
+
line.each { |duplicate| @lines << duplicate }
|
190
|
+
else
|
191
|
+
@lines << line
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
#######
|
197
|
+
private
|
198
|
+
#######
|
199
|
+
|
200
|
+
def line_contents
|
201
|
+
'[%s]' % key
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
# Stores options which appear at the beginning of a file, without a
|
206
|
+
# preceding section.
|
207
|
+
class AnonymousSection < Section
|
208
|
+
def initialize
|
209
|
+
super('__anonymous__')
|
210
|
+
end
|
211
|
+
|
212
|
+
def to_ini
|
213
|
+
# Remove the leading space which is added by joining the blank line
|
214
|
+
# content with the options.
|
215
|
+
super.gsub(/\A\n/, '')
|
216
|
+
end
|
217
|
+
|
218
|
+
#######
|
219
|
+
private
|
220
|
+
#######
|
221
|
+
|
222
|
+
def line_contents
|
223
|
+
''
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
# Represents probably the most common type of line in an INI document:
|
228
|
+
# an option. Consists of a key and value, usually separated with an =.
|
229
|
+
#
|
230
|
+
# key = value
|
231
|
+
#
|
232
|
+
class Option
|
233
|
+
include Line
|
234
|
+
|
235
|
+
@regex = /^\s*([^=]+) # Option
|
236
|
+
=
|
237
|
+
(.*?)$ # Value
|
238
|
+
/x
|
239
|
+
|
240
|
+
attr_accessor :key, :value
|
241
|
+
|
242
|
+
# ==== Parameters
|
243
|
+
# key<String>:: The option key.
|
244
|
+
# value<String>:: The value for this option.
|
245
|
+
# opts<Hash>:: Extra options for the line.
|
246
|
+
#
|
247
|
+
def initialize(key, value, opts = {})
|
248
|
+
super(opts)
|
249
|
+
@key, @value = key.to_s, value
|
250
|
+
end
|
251
|
+
|
252
|
+
def self.parse(line, opts)
|
253
|
+
if m = @regex.match(line)
|
254
|
+
[:option, m[1].strip, typecast(m[2].strip), opts]
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
# Attempts to typecast values.
|
259
|
+
def self.typecast(value)
|
260
|
+
case value
|
261
|
+
when /^\s*$/ then nil
|
262
|
+
when /^-?(?:\d|[1-9]\d+)$/ then Integer(value)
|
263
|
+
when /^-?(?:\d|[1-9]\d+)(?:\.\d+)?(?:e[+-]?\d+)?$/i then Float(value)
|
264
|
+
when /true/i then true
|
265
|
+
when /false/i then false
|
266
|
+
else value
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
#######
|
271
|
+
private
|
272
|
+
#######
|
273
|
+
|
274
|
+
def line_contents
|
275
|
+
'%s = %s' % [key, value]
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
# Represents a blank line. Used so that we can preserve blank lines when
|
280
|
+
# writing back to the file.
|
281
|
+
class Blank
|
282
|
+
include Line
|
283
|
+
|
284
|
+
def blank?
|
285
|
+
true
|
286
|
+
end
|
287
|
+
|
288
|
+
def self.parse(line, opts)
|
289
|
+
if line !~ /\S/ # blank
|
290
|
+
if opts[:comment].nil?
|
291
|
+
[:blank]
|
292
|
+
else
|
293
|
+
[:comment, opts[:comment], opts]
|
294
|
+
end
|
295
|
+
end
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
# Represents a comment. Comment lines begin with a semi-colon or hash.
|
300
|
+
#
|
301
|
+
# ; this is a comment
|
302
|
+
# # also a comment
|
303
|
+
#
|
304
|
+
class Comment < Blank
|
305
|
+
# Returns if this line has an inline comment.
|
306
|
+
#
|
307
|
+
# Being a Comment this will always return true, even if the comment
|
308
|
+
# is nil. This would be the case if the line starts with a comment
|
309
|
+
# seperator, but has no comment text. See spec/fixtures/smb.ini for a
|
310
|
+
# real-world example.
|
311
|
+
#
|
312
|
+
def has_comment?
|
313
|
+
true
|
314
|
+
end
|
315
|
+
|
316
|
+
# Returns the inline comment for this line. Includes the comment
|
317
|
+
# separator at the beginning of the string.
|
318
|
+
#
|
319
|
+
# In rare cases where a comment seperator appeared in the original file,
|
320
|
+
# but without a comment, just the seperator will be returned.
|
321
|
+
#
|
322
|
+
def comment
|
323
|
+
@comment !~ /\S/ ? @comment_sep : super
|
324
|
+
end
|
325
|
+
end
|
326
|
+
end # Lines
|
327
|
+
end # IniParse
|
@@ -0,0 +1,110 @@
|
|
1
|
+
module IniParse
|
2
|
+
class Parser
|
3
|
+
|
4
|
+
# Returns the line types.
|
5
|
+
#
|
6
|
+
# ==== Returns
|
7
|
+
# Array
|
8
|
+
#
|
9
|
+
def self.parse_types
|
10
|
+
@@parse_types ||= []
|
11
|
+
end
|
12
|
+
|
13
|
+
# Sets the line types. Handy if you want to add your own custom Line
|
14
|
+
# classes.
|
15
|
+
#
|
16
|
+
# ==== Parameters
|
17
|
+
# types<Array[IniParse::Lines::Line]>:: An array containing Line classes.
|
18
|
+
#
|
19
|
+
def self.parse_types=(types)
|
20
|
+
parse_types.replace(types)
|
21
|
+
end
|
22
|
+
|
23
|
+
self.parse_types = [ IniParse::Lines::Section,
|
24
|
+
IniParse::Lines::Option, IniParse::Lines::Blank ]
|
25
|
+
|
26
|
+
# Creates a new Parser instance for parsing string +source+.
|
27
|
+
#
|
28
|
+
# ==== Parameters
|
29
|
+
# source<String>:: The source string.
|
30
|
+
#
|
31
|
+
def initialize(source)
|
32
|
+
@source = source.dup
|
33
|
+
end
|
34
|
+
|
35
|
+
# Parses the source string and returns the resulting data structure.
|
36
|
+
#
|
37
|
+
# ==== Returns
|
38
|
+
# IniParse::Document
|
39
|
+
#
|
40
|
+
def parse
|
41
|
+
IniParse::Generator.gen do |generator|
|
42
|
+
@source.split("\n", -1).each do |line|
|
43
|
+
generator.send(*Parser.parse_line(line))
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
class << self
|
49
|
+
# Takes a raw line from an INI document, striping out any inline
|
50
|
+
# comment, and indent, then returns the appropriate tuple so that the
|
51
|
+
# Generator instance can add the line to the Document.
|
52
|
+
#
|
53
|
+
# ==== Raises
|
54
|
+
# IniParse::ParseError: If the line could not be parsed.
|
55
|
+
#
|
56
|
+
def parse_line(line)
|
57
|
+
sanitized, opts = strip_indent(*strip_comment(line, {}))
|
58
|
+
|
59
|
+
parsed = nil
|
60
|
+
@@parse_types.each do |type|
|
61
|
+
break if (parsed = type.parse(sanitized, opts))
|
62
|
+
end
|
63
|
+
|
64
|
+
if parsed.nil?
|
65
|
+
raise IniParse::ParseError,
|
66
|
+
"A line of your INI document could not be parsed to a " \
|
67
|
+
"LineType: '#{line}'."
|
68
|
+
end
|
69
|
+
|
70
|
+
parsed
|
71
|
+
end
|
72
|
+
|
73
|
+
#######
|
74
|
+
private
|
75
|
+
#######
|
76
|
+
|
77
|
+
# Strips in inline comment from a line (or value), removes trailing
|
78
|
+
# whitespace and sets the comment options as applicable.
|
79
|
+
def strip_comment(line, opts)
|
80
|
+
if m = /^(^)(?:(;|\#)(\s*)(.*))$$/.match(line) ||
|
81
|
+
m = /^(.*?)(?:\s+(;|\#)(\s*)(.*))$/.match(line) # Comment lines.
|
82
|
+
opts[:comment] = m[4].rstrip
|
83
|
+
opts[:comment_prefix] = m[3]
|
84
|
+
opts[:comment_sep] = m[2]
|
85
|
+
# Remove the line content (since an option value may contain a
|
86
|
+
# semi-colon) _then_ get the index of the comment separator.
|
87
|
+
opts[:comment_offset] =
|
88
|
+
line[(m[1].length..-1)].index(m[2]) + m[1].length
|
89
|
+
|
90
|
+
line = m[1]
|
91
|
+
else
|
92
|
+
line.rstrip!
|
93
|
+
end
|
94
|
+
|
95
|
+
[line, opts]
|
96
|
+
end
|
97
|
+
|
98
|
+
# Removes any leading whitespace from a line, and adds it to the options
|
99
|
+
# hash.
|
100
|
+
def strip_indent(line, opts)
|
101
|
+
if m = /^(\s+).*$/.match(line)
|
102
|
+
line.lstrip!
|
103
|
+
opts[:indent] = m[1]
|
104
|
+
end
|
105
|
+
|
106
|
+
[line, opts]
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end # Parser
|
110
|
+
end # IniParse
|
data/lib/tungsten/api.rb
CHANGED
@@ -7,7 +7,7 @@ require 'net/http'
|
|
7
7
|
|
8
8
|
# SAMPLE USAGE:
|
9
9
|
# api_server='localhost:8090'
|
10
|
-
# service=chicago
|
10
|
+
# service="chicago"
|
11
11
|
#
|
12
12
|
# cctrl = TungstenDataserviceManager.new(api_server)
|
13
13
|
# cctrl.list(:text)
|
@@ -21,10 +21,10 @@ require 'net/http'
|
|
21
21
|
#
|
22
22
|
# begin
|
23
23
|
# APICall.set_return_on_call_fail(:raise)
|
24
|
-
# json_obj = cctrl.post(service}/host1
|
24
|
+
# json_obj = cctrl.post("#{service}/host1", 'promote')
|
25
25
|
# pp json_obj["message"]
|
26
26
|
# rescue Exception => e
|
27
|
-
# puts e # failure message will
|
27
|
+
# puts e # failure message will come here
|
28
28
|
# end
|
29
29
|
|
30
30
|
|