vzcdn 0.1.9 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6a57e7a8b331b7ded73bccae8a4d2fccc3640ab6
4
- data.tar.gz: 5442f2e2e84bf6df14f05b498eee315f9bbe2dc0
3
+ metadata.gz: 908fd60bab73ffcb6b51ee5800cf18bc1f342497
4
+ data.tar.gz: e5977af1560fc83e7f2065c2665a70fc36faeec0
5
5
  SHA512:
6
- metadata.gz: 0f7424dd530ce0dbf3f53221510dfdc4a5522bc4a9feb1d730d6ab0452b5a4bc411d07b9c1268f8aa4e25af8fd8d4020281add0561f9b358e9ef2a6f5a4c8199
7
- data.tar.gz: 3d8dbc180663af1207657cc9fdd7f14b27f1d39b5adf0817b2fbf5e21e88bfe738ac7c1bdb8e1c077074f601b9db6f483c3856c6a68093ff26621eda4b8cdeaa
6
+ metadata.gz: 1157b4228fd58982be432b0a67f1a3c73ed1cd7850a2fd6f584afd305f2b935e68a375583879c4936ec1e18940267f567235cbae7d93f6c235e6bf01874304b1
7
+ data.tar.gz: f55a563fcb6999f967f4a14e3260635095275ec1191a734a23eb08c986e65e7a8978dffbc5e2de127bc5ca03870ef088036e02616e95aca68e8fdcabab93e166
data/README.md CHANGED
@@ -4,6 +4,10 @@ Commandline UI for Edgecast API
4
4
 
5
5
  ##RELEASE NOTES
6
6
 
7
+ 2014/05/02 0.2.0
8
+ * Add/Update/Delete for groups/records/health-checks in zone.
9
+ * Zone-list with local status
10
+
7
11
  2014/04/22 0.1.9
8
12
  * Create zone support
9
13
  * Add record support
@@ -39,7 +43,7 @@ Or install it yourself as:
39
43
  $ gem install vzcdn
40
44
 
41
45
  ## Usage
42
-
46
+ http://youtu.be/y8MnWYxZiiA
43
47
 
44
48
  ## Contributing
45
49
 
data/bin/ec CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  require 'vzcdn'
4
4
 
5
- # $debug = true
5
+ $debug = 0
6
6
 
7
7
  def add_prefix(prefix, text)
8
8
  result = ""
@@ -13,18 +13,28 @@ def add_prefix(prefix, text)
13
13
  end
14
14
 
15
15
  def dputs(*args)
16
- if $debug
16
+ if $debug > 0
17
17
  puts *args
18
18
  end
19
19
  end
20
20
 
21
+ def ddputs(*args)
22
+ if $debug > 1
23
+ puts *args
24
+ end
25
+ end
26
+
27
+
21
28
  begin
22
- VzcdnApp.new("vzcdn", "vzcdn").run(ARGV)
29
+ scriptname = File.basename $0
30
+ $USER_ENTERED_COMMAND = scriptname + ' ' + ARGV.join(' ')
31
+ VzcdnApp.new(scriptname, "(vzcdn or ec) EdgeCast command line interface").run(ARGV)
23
32
  exit 0
24
33
  rescue Exception => e
25
34
  if e.class != SystemExit
26
35
  puts add_prefix("ERROR:", e.message)
27
- if $debug
36
+ dputs e.backtrace[0]
37
+ if $debug > 1
28
38
  raise e
29
39
  else
30
40
  exit 1
data/bin/vzcdn CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  require 'vzcdn'
4
4
 
5
- # $debug = true
5
+ $debug = 0
6
6
 
7
7
  def add_prefix(prefix, text)
8
8
  result = ""
@@ -13,18 +13,28 @@ def add_prefix(prefix, text)
13
13
  end
14
14
 
15
15
  def dputs(*args)
16
- if $debug
16
+ if $debug > 0
17
17
  puts *args
18
18
  end
19
19
  end
20
20
 
21
+ def ddputs(*args)
22
+ if $debug > 1
23
+ puts *args
24
+ end
25
+ end
26
+
27
+
21
28
  begin
22
- VzcdnApp.new("vzcdn", "vzcdn").run(ARGV)
29
+ scriptname = File.basename $0
30
+ $USER_ENTERED_COMMAND = scriptname + ' ' + ARGV.join(' ')
31
+ VzcdnApp.new(scriptname, "(vzcdn or ec) EdgeCast command line interface").run(ARGV)
23
32
  exit 0
24
33
  rescue Exception => e
25
34
  if e.class != SystemExit
26
35
  puts add_prefix("ERROR:", e.message)
27
- if $debug
36
+ dputs e.backtrace[0]
37
+ if $debug > 1
28
38
  raise e
29
39
  else
30
40
  exit 1
@@ -55,7 +55,12 @@ class Cell
55
55
  set(@default, nil)
56
56
  end
57
57
  return false unless @required
58
- @value.nil?
58
+ # @required is true
59
+ if @repeatable && @value == [ ]
60
+ true
61
+ else
62
+ @value.nil?
63
+ end
59
64
  end
60
65
 
61
66
  def name
@@ -92,9 +97,9 @@ class Arg
92
97
  test = @validator.has_key? value
93
98
  on_error = "Invalid choice for #{@name}, must be one of #{@validator.keys}"
94
99
  elsif vclass == String
95
- result = {}
100
+ result = [ ]
96
101
  Route.new.send("get_available_" + @validator).each { |hash|
97
- result[hash["Name"]] = hash["Id"]
102
+ result << hash["Name"]
98
103
  }
99
104
  @validator = result
100
105
  test = validate?(value, obj)
@@ -119,7 +124,7 @@ class Arg
119
124
  end
120
125
 
121
126
  class Flow
122
- attr_accessor :usage_string
127
+ attr_accessor :usage_string, :pre_cond, :rest, :error
123
128
 
124
129
  def initialize
125
130
  @cells = [ ]
@@ -133,30 +138,35 @@ class Flow
133
138
 
134
139
  def parse(args, obj = nil)
135
140
  @target = obj
136
- rest = [ ]
141
+ @rest = [ ]
137
142
  args.each_with_index { |arg, index|
143
+ if finished || @error
144
+ @rest = args[index..-1]
145
+ break
146
+ end
138
147
  name, value = Util.parse_line(arg)
139
148
  if value.nil?
140
149
  value = name
141
- error, finished = setvalue(value)
150
+ setvalue(value)
142
151
  else
143
- error, finished = set(name, value)
144
- end
145
- if error
146
- result = add_errline(result, error)
147
- finished = :finished
148
- end
149
- if finished
150
- rest = args[index..-1]
151
- break
152
+ set(name, value)
152
153
  end
153
154
  }
154
155
  missing = missing_args
155
- unless missing.empty?
156
- result = add_errline(result, "missing args: #{missing}")
156
+ @error.nil?
157
+ end
158
+
159
+ def finished
160
+ if command && @cells[-1].full?
161
+ # the command was seen
162
+ return true
157
163
  end
158
- # dputs "parse for class #{obj.class} result=#{result}, rest=#{rest}"
159
- return result, rest
164
+ @cells.each { |cell|
165
+ if ! cell.full?
166
+ return false
167
+ end
168
+ }
169
+ return true
160
170
  end
161
171
 
162
172
  def setvalue(value)
@@ -165,13 +175,18 @@ class Flow
165
175
  next
166
176
  else
167
177
  error = cell.set(value, @target)
168
- if error && cell.repeatable
169
- next
170
- end
171
- return error, nil
178
+ if error
179
+ if cell.repeatable
180
+ next # repeatable cell is now full; try to set next cell
181
+ else
182
+ add_errline(error)
183
+ return
184
+ end
185
+ end
186
+ return
172
187
  end
173
188
  }
174
- return nil, :finished
189
+ return
175
190
  end
176
191
 
177
192
  def missing_args
@@ -181,16 +196,19 @@ class Flow
181
196
  missing << cell.name
182
197
  end
183
198
  }
184
- missing
199
+ if missing.length > 0
200
+ add_errline("missing args: #{missing}")
201
+ end
185
202
  end
186
203
 
187
204
  def set(name, value)
188
205
  @cells.each { |cell|
189
206
  if cell.name == name
190
- return cell.set(value, @target), nil
207
+ add_errline(cell.set(value, @target))
208
+ return
191
209
  end
192
210
  }
193
- return "argument named #{name} not found", nil
211
+ add_errline("argument named #{name} not found")
194
212
  end
195
213
 
196
214
  def command
@@ -218,11 +236,12 @@ class Flow
218
236
  return names, desc
219
237
  end
220
238
 
221
- def add_errline(str, error)
222
- if str
223
- str + "\n" + error
239
+ def add_errline(errmsg)
240
+ return if errmsg.nil?
241
+ if @error.nil?
242
+ @error = errmsg
224
243
  else
225
- error
244
+ @error = @error + "\n" + errmsg
226
245
  end
227
246
  end
228
247
  end
@@ -8,7 +8,7 @@ class ConfigInit < Command
8
8
 
9
9
  def create_args
10
10
  add_arg("acct-num", "EdgeCast account number", /[[:alnum:]]+/)
11
- add_arg("token", "Web Services REST API Token (see my.edgecase.com)", /.*/)
11
+ add_arg("token", "Web Services REST API Token (see my.edgecast.com)", /.*/)
12
12
  end
13
13
 
14
14
  def create_flows
@@ -23,7 +23,6 @@ class ConfigInit < Command
23
23
 
24
24
  print_cfg = {
25
25
  "zone" => ["ZoneId", "DomainName", "ZoneType", "Status", "Version", "Records", "FailoverGroups", "LoadBalancingGroups"],
26
- "zone.FailoverGroups.Group.AAAA" => ["Record", "IsPrimary", "HealthCheck"],
27
26
  "zonelist" => ["DomainName", "ZoneId", "Status"]
28
27
  }
29
28
  File.open(config_file("print.cfg"), "w").write(JSON.pretty_generate print_cfg)
@@ -45,28 +45,18 @@ class Command
45
45
  @options << option
46
46
  end
47
47
 
48
- def show_help_option
49
- show_help
50
- raise CancelExecution
51
- end
52
-
53
- def get_args_used(usage, args_used)
54
- line = usage
55
- re = /<(?<argname>[[:alnum:]-]+)>/
56
- while m = re.match(line)
57
- argname = m[:argname]
58
- unless args_used.include? argname
59
- args_used << argname
60
- end
61
- line = line[m.end(0)..-1]
62
- end
63
- end
64
-
65
48
  def show_help
66
49
  puts "#{@name} - #{@desc}"
50
+ valid_flows = @flows.select { |flow|
51
+ flow_passes_preconditions(flow)
52
+ }
53
+ if valid_flows.length == 0
54
+ puts "No usage of #{@name} is valid in this context"
55
+ valid_flows = @flows
56
+ end
67
57
  puts "Usage:"
68
58
  args_used = [ ]
69
- @flows.each { |flow|
59
+ valid_flows.each { |flow|
70
60
  puts " #{@name} #{flow.usage_string}"
71
61
  get_args_used(flow.usage_string, args_used)
72
62
  }
@@ -87,6 +77,27 @@ class Command
87
77
  puts " #{arg.name} : #{arg.desc}#{choice}"
88
78
  }
89
79
  end
80
+ puts "Options:"
81
+ @options.each { | o |
82
+ puts " -#{o[:short_name]} or --#{o[:long_name]}" + (o[:takes_value] ? " (takes value)" : "")
83
+ }
84
+ end
85
+
86
+ def show_help_option
87
+ show_help
88
+ raise CancelExecution
89
+ end
90
+
91
+ def get_args_used(usage, args_used)
92
+ line = usage
93
+ re = /<(?<argname>[[:alnum:]-]+)>/
94
+ while m = re.match(line)
95
+ argname = m[:argname]
96
+ unless args_used.include? argname
97
+ args_used << argname
98
+ end
99
+ line = line[m.end(0)..-1]
100
+ end
90
101
  end
91
102
 
92
103
  def add_arg(name, desc, validator)
@@ -106,9 +117,10 @@ class Command
106
117
  @subcommands.include?(str.to_s)
107
118
  end
108
119
 
109
- def add_flow_from_usage(usage)
120
+ def add_flow_from_usage(usage, *pre_cond)
110
121
  flow = Flow.new
111
122
  flow.usage_string = usage
123
+ flow.pre_cond = pre_cond
112
124
  line = usage
113
125
  re = /\A
114
126
  ( # matches one arg spec
@@ -137,6 +149,34 @@ class Command
137
149
  @flows << flow
138
150
  end
139
151
 
152
+ def flow_passes_parse(flow, args)
153
+ desc = "usage \'#{@name} #{flow.usage_string}\'"
154
+ result = true
155
+ success = flow.parse args, self
156
+ if success
157
+ if flow.command.nil? && flow.rest.length > 0
158
+ result = false
159
+ ddputs "#{desc} failed (args=#{args}) due to superfluous arguments (#{flow.rest})"
160
+ else
161
+ ddputs "#{desc} passed parse, adding to candidate list (rest=#{flow.rest})"
162
+ end
163
+ else
164
+ result = false
165
+ ddputs "#{desc} failed to parse arguments (args=#{args}), #{flow.error}"
166
+ end
167
+ return result
168
+ end
169
+
170
+ def flow_passes_preconditions(flow)
171
+ if flow.pre_cond && flow.pre_cond.length > 0 && (error = send(*flow.pre_cond))
172
+ dputs "usage \'#{@name} #{flow.usage_string}\' failed due to precondition failure:#{error}"
173
+ false
174
+ else
175
+ ddputs "usage \'#{@name} #{flow.usage_string}\' passed any precondition"
176
+ true
177
+ end
178
+ end
179
+
140
180
  def run(args)
141
181
  begin
142
182
  args = ClOptions.new(self, @options).handle(args)
@@ -148,15 +188,28 @@ class Command
148
188
  raise error
149
189
  end
150
190
 
151
- @flows.each { |flow|
152
- error, rest = flow.parse args, self
153
- if error.nil?
154
- execute(flow.arghash, rest)
155
- return
156
- end
191
+ candidate_flows = @flows.select { |flow|
192
+ flow_passes_parse(flow, args)
157
193
  }
158
- puts "ERROR:no usage of #{@name} recognized"
159
- puts ""
160
- show_help
194
+
195
+ valid_flows = candidate_flows.select { |flow|
196
+ flow_passes_preconditions(flow)
197
+ }
198
+
199
+ if valid_flows.length == 1
200
+ flow = valid_flows[0]
201
+ ddputs "usage \'#{@name} #{flow.usage_string}\' matched, executing"
202
+ execute(flow.arghash, flow.rest)
203
+ elsif valid_flows.length > 1
204
+ puts "BUG FOUND: arguments #{args} match the following flows in class #{self.class}"
205
+ valid_flows.each { |flow|
206
+ puts " usage \'#{@name} #{flow.usage_string}\'"
207
+ }
208
+ else
209
+ unless args.length == 0
210
+ puts "ERROR:no usage of #{@name} recognized or allowed\n\n"
211
+ end
212
+ show_help
213
+ end
161
214
  end
162
215
  end
@@ -39,7 +39,7 @@ class CommonRestUtils
39
39
  end
40
40
  end
41
41
  exit
42
- if $debug
42
+ if $debug > 0
43
43
  puts "full URL is:" + url
44
44
  if (body)
45
45
  puts "body is: json_body"
@@ -51,7 +51,7 @@ class CommonRestUtils
51
51
  raise "Bad response code:" + response.code.to_s
52
52
  end
53
53
  if (response.length > 0)
54
- if $debug
54
+ if $debug > 1
55
55
  File.open("raw.json", "w").write(response)
56
56
  end
57
57
  JSON.parse response
@@ -8,26 +8,18 @@ module ConfigReader
8
8
  ConfigHandler::CONFIG_DIRECTORY
9
9
  end
10
10
 
11
- def imkdir(path)
12
- if ! Dir.exists?(path)
13
- Dir.mkdir path
14
- end
15
- path
16
- end
17
-
18
- def mk_user_dir(*dirs)
19
- imkdir user_file(*dirs)
20
- end
21
-
22
- def mk_config_dir(*dirs)
23
- imkdir config_file(*dirs)
11
+ def mkdir(filename)
12
+ FileUtils.mkdir_p(File.dirname(filename))
13
+ filename
24
14
  end
25
15
 
26
16
  def user_file(*dirs_file)
27
- File.join(*dirs_file)
17
+ result = File.join(*dirs_file)
18
+ mkdir result
28
19
  end
29
20
 
30
21
  def config_file(*dirs_file)
31
- File.join(config_dir, *dirs_file)
22
+ filename = File.join(config_dir, *dirs_file)
23
+ mkdir filename
32
24
  end
33
25
  end