warthog 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +31 -0
- data/README.md +0 -0
- data/bin/warthog +17 -0
- data/lib/warthog.rb +3 -0
- data/lib/warthog/a10/rest.rb +84 -0
- data/lib/warthog/about.rb +5 -0
- data/lib/warthog/cli.rb +103 -0
- data/lib/warthog/cli/action.rb +4 -0
- data/lib/warthog/cli/action/show.rb +78 -0
- data/lib/warthog/version.rb +3 -0
- metadata +72 -0
data/LICENSE
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright (c) 2012 by Evernote Corporation, All rights reserved.
|
3
|
+
*
|
4
|
+
* Use of the source code and binary libraries included in this package
|
5
|
+
* is permitted under the following terms:
|
6
|
+
*
|
7
|
+
* Redistribution and use in source and binary forms, with or without
|
8
|
+
* modification, are permitted provided that the following conditions
|
9
|
+
* are met:
|
10
|
+
*
|
11
|
+
* 1. Redistributions of source code must retain the above copyright
|
12
|
+
* notice, this list of conditions and the following disclaimer.
|
13
|
+
* 2. Redistributions in binary form must reproduce the above copyright
|
14
|
+
* notice, this list of conditions and the following disclaimer in the
|
15
|
+
* documentation and/or other materials provided with the distribution.
|
16
|
+
*
|
17
|
+
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
18
|
+
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
19
|
+
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
20
|
+
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
21
|
+
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
22
|
+
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
23
|
+
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
24
|
+
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
25
|
+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
26
|
+
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
27
|
+
*
|
28
|
+
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
29
|
+
* not use this file except in compliance with the License. You may obtain a
|
30
|
+
* copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
31
|
+
*/
|
data/README.md
ADDED
File without changes
|
data/bin/warthog
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
lib = File.expand_path(File.dirname(__FILE__) + '/../lib')
|
4
|
+
$LOAD_PATH.unshift(lib) if File.directory?(lib) && !$LOAD_PATH.include?(lib)
|
5
|
+
|
6
|
+
require 'rubygems'
|
7
|
+
require 'warthog'
|
8
|
+
require 'warthog/cli'
|
9
|
+
|
10
|
+
module Warthog
|
11
|
+
|
12
|
+
ID = File.basename($PROGRAM_NAME).to_sym
|
13
|
+
|
14
|
+
app = CLI::CLI.new(ARGV)
|
15
|
+
app.run
|
16
|
+
|
17
|
+
end
|
data/lib/warthog.rb
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
|
3
|
+
module Warthog; module A10
|
4
|
+
|
5
|
+
class AXDevice
|
6
|
+
|
7
|
+
class AuthenticationError < StandardError; end
|
8
|
+
class HTTPError < StandardError; end
|
9
|
+
class AXapiError < StandardError; end
|
10
|
+
|
11
|
+
include HTTParty
|
12
|
+
|
13
|
+
API_VERSIONS = %w(V2)
|
14
|
+
|
15
|
+
def initialize(hostname,username,password,options={})
|
16
|
+
@hostname = hostname
|
17
|
+
@session_id = nil
|
18
|
+
@api_version = nil
|
19
|
+
|
20
|
+
axapi :authenticate, :username => username, :password => password
|
21
|
+
raise StandardError, "unable to obtain session id" unless @session_id
|
22
|
+
end
|
23
|
+
|
24
|
+
def slb_service_group_all
|
25
|
+
output = ''
|
26
|
+
service_group_list = axapi 'slb.service_group.getAll'
|
27
|
+
service_group_list['response']['service_group_list']['service_group'].each do |service_group|
|
28
|
+
name = service_group['name']
|
29
|
+
service_group['member_list']['member'].each do |member|
|
30
|
+
output << "%-16s %12s:%-5s %s %s %s\n" % [name,member['server'],member['port'],member['template'],member['priority'],member['status']] if Hash === member
|
31
|
+
end
|
32
|
+
end
|
33
|
+
output
|
34
|
+
end
|
35
|
+
|
36
|
+
def slb_service_group_search(name)
|
37
|
+
output = ''
|
38
|
+
service_group = axapi 'slb.service_group.search', :name => name
|
39
|
+
service_group['response']['service_group']['member_list']['member'].each do |member|
|
40
|
+
output << "%-16s %12s:%-5s %s %s %s\n" % [name,member['server'],member['port'],member['template'],member['priority'],member['status']]
|
41
|
+
end
|
42
|
+
output
|
43
|
+
end
|
44
|
+
|
45
|
+
protected
|
46
|
+
|
47
|
+
def axapi(method,paramvalues={})
|
48
|
+
if @session_id and @api_version
|
49
|
+
uri = "https://#@hostname/services/rest/#@api_version/?session_id=#@session_id&method=#{method}"
|
50
|
+
paramvalues.each do |param,value|
|
51
|
+
uri << "&#{param}=#{value}"
|
52
|
+
end
|
53
|
+
r = self.class.get(uri)
|
54
|
+
if r.code == 200
|
55
|
+
if r['response']['status'] == 'ok'
|
56
|
+
return r
|
57
|
+
elsif r['response']['status'] == 'fail'
|
58
|
+
raise AXapiError, r['response']['error']['msg']
|
59
|
+
end
|
60
|
+
else
|
61
|
+
raise HTTPError, "HTTP code: #{r.code}"
|
62
|
+
end
|
63
|
+
else
|
64
|
+
API_VERSIONS.each do |api_version|
|
65
|
+
r = self.class.get("https://#@hostname/services/rest/#{api_version}/?method=#{method}&username=#{paramvalues[:username]}&password=#{paramvalues[:password]}")
|
66
|
+
if r.code == 200
|
67
|
+
if r['response']['status'] == 'ok'
|
68
|
+
@session_id = r['response']['session_id']
|
69
|
+
@api_version = api_version
|
70
|
+
elsif r['response']['status'] == 'fail'
|
71
|
+
next if r['response']['error']['code'] == '1004'
|
72
|
+
raise AuthenticationError, r['response']['error']['msg'] if r['response']['error']['code'] == '520486968'
|
73
|
+
end
|
74
|
+
else
|
75
|
+
raise HTTPError, "HTTP code: #{r.code}"
|
76
|
+
end
|
77
|
+
raise StandardError, "unable to obtain session id" unless @session_id
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
end end
|
data/lib/warthog/cli.rb
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
require 'etc'
|
3
|
+
require 'warthog'
|
4
|
+
require 'warthog/cli/action'
|
5
|
+
require 'warthog/a10/rest'
|
6
|
+
require 'warthog/version'
|
7
|
+
require 'warthog/about'
|
8
|
+
|
9
|
+
include Warthog::CLI::Action
|
10
|
+
|
11
|
+
module Warthog; module CLI
|
12
|
+
|
13
|
+
class CLI
|
14
|
+
|
15
|
+
COMMANDS = %w(show)
|
16
|
+
|
17
|
+
def initialize(arguments)
|
18
|
+
@arguments = arguments
|
19
|
+
@whoami = File.basename($PROGRAM_NAME).to_sym
|
20
|
+
|
21
|
+
@options = { :debug => false, :username => Etc.getlogin }
|
22
|
+
@action = nil
|
23
|
+
@elesai = nil
|
24
|
+
end
|
25
|
+
|
26
|
+
def run
|
27
|
+
begin
|
28
|
+
parsed_options?
|
29
|
+
arguments_valid?
|
30
|
+
options_valid?
|
31
|
+
process_options
|
32
|
+
process_arguments
|
33
|
+
process_command
|
34
|
+
|
35
|
+
rescue => e #ArgumentError, OptionParser::MissingArgument, Senedsa::SendNsca::ConfigurationError => e
|
36
|
+
if @options[:debug]
|
37
|
+
output_message "#{e.class}: #{e.message}\n #{e.backtrace.join("\n ")}",1
|
38
|
+
else
|
39
|
+
output_message e.message,1
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
protected
|
45
|
+
|
46
|
+
def parsed_options?
|
47
|
+
opts = OptionParser.new
|
48
|
+
|
49
|
+
opts.banner = "Usage: #{ID} [options] <action> [options] [arguments]"
|
50
|
+
opts.separator ""
|
51
|
+
opts.separator "Actions: (<action> -h displays help for specific action)"
|
52
|
+
opts.separator " show Displays component information"
|
53
|
+
opts.separator ""
|
54
|
+
opts.separator "General options:"
|
55
|
+
opts.on('-H', '--hostname HOSTNAME', String, "A10 Load Balancer hostname") { |o| @options[:hostname] = o }
|
56
|
+
opts.on('-l', '--login USERNAME', String, "Username") { |o| @options[:username] = o }
|
57
|
+
opts.on('-f', '--fake DIRECTORY', String, "Path to directory with output") { |o| @options[:fake] = o }
|
58
|
+
opts.on('-d', '--debug', "Enable debug mode") { @options[:debug] = true}
|
59
|
+
opts.on('-a', '--about', "Display #{ID} information") { output_message ABOUT, 0 }
|
60
|
+
opts.on('-V', '--version', "Display #{ID} version") { output_message VERSION, 0 }
|
61
|
+
opts.on_tail('--help', "Show this message") { @options[:HELP] = true }
|
62
|
+
|
63
|
+
opts.order!(@arguments)
|
64
|
+
output_message opts, 0 if (@arguments.size == 0 and @whoami != :check_a10) or @options[:HELP]
|
65
|
+
|
66
|
+
@action = @whoami == :check_a10 ? :check : @arguments.shift.to_sym
|
67
|
+
case @action
|
68
|
+
when :show then @a10 = Show.new(@arguments,@options)
|
69
|
+
else raise OptionParser::InvalidArgument, "invalid action #@action"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def arguments_valid?
|
74
|
+
true
|
75
|
+
end
|
76
|
+
|
77
|
+
def options_valid?
|
78
|
+
true
|
79
|
+
end
|
80
|
+
|
81
|
+
def process_options
|
82
|
+
raise OptionParser::MissingArgument, "load balancer hostname (-H) must be specified" if @options[:hostname].nil?
|
83
|
+
true
|
84
|
+
end
|
85
|
+
|
86
|
+
def process_arguments
|
87
|
+
true
|
88
|
+
end
|
89
|
+
|
90
|
+
def process_command
|
91
|
+
@a10.exec
|
92
|
+
end
|
93
|
+
|
94
|
+
def output_message(message, exitstatus=nil)
|
95
|
+
m = (! exitstatus.nil? and exitstatus > 0) ? "%s: error: %s" % [ID, message] : message
|
96
|
+
# Syslog.open("elesai", Syslog::LOG_PID | Syslog::LOG_CONS) { |s| s.err "error: #{message}" } unless @options[:debug]
|
97
|
+
$stderr.write "#{m}\n" if STDIN.tty?
|
98
|
+
exit exitstatus unless exitstatus.nil?
|
99
|
+
end
|
100
|
+
|
101
|
+
|
102
|
+
end
|
103
|
+
end end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
module Warthog; module CLI; module Action
|
2
|
+
|
3
|
+
class Show
|
4
|
+
|
5
|
+
COMPONENTS = %w(service-group)
|
6
|
+
|
7
|
+
def initialize(arguments,options)
|
8
|
+
|
9
|
+
@options = options
|
10
|
+
@arguments = arguments
|
11
|
+
|
12
|
+
@component = nil
|
13
|
+
@subcomponent = nil
|
14
|
+
|
15
|
+
opts = OptionParser.new
|
16
|
+
opts.banner = "Usage: #{ID} [options] show <component> [arguments]"
|
17
|
+
opts.separator ""
|
18
|
+
opts.separator " <component> is service-group"
|
19
|
+
opts.order!(@arguments)
|
20
|
+
|
21
|
+
options_valid?
|
22
|
+
arguments_valid?
|
23
|
+
process_arguments
|
24
|
+
|
25
|
+
@show = { :service_group => self.method(:show_service_group)
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
29
|
+
def exec
|
30
|
+
@a10slb = Warthog::A10::AXDevice.new(@options[:hostname],@options[:username],get_password)
|
31
|
+
@show[@component].call(@subcomponent)
|
32
|
+
end
|
33
|
+
|
34
|
+
def show_service_group(name=nil)
|
35
|
+
if name.nil?
|
36
|
+
printf "%s" % [@a10slb.slb_service_group_all]
|
37
|
+
else
|
38
|
+
printf "%s" % [@a10slb.slb_service_group_search(name)]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
protected
|
43
|
+
|
44
|
+
def options_valid?
|
45
|
+
true
|
46
|
+
end
|
47
|
+
|
48
|
+
def arguments_valid?
|
49
|
+
raise ArgumentError, "missing component" if @arguments.size == 0
|
50
|
+
raise ArgumentError, "invalid component #{@arguments[0]}" unless COMPONENTS.include? @arguments[0]
|
51
|
+
true
|
52
|
+
end
|
53
|
+
|
54
|
+
def process_arguments
|
55
|
+
@component = case @arguments[0].gsub(/-/,'_').to_sym
|
56
|
+
when :dummy then a10 = nil
|
57
|
+
else @arguments[0].gsub(/-/,'_').to_sym
|
58
|
+
end
|
59
|
+
@subcomponent = @arguments[1]
|
60
|
+
end
|
61
|
+
|
62
|
+
def get_password
|
63
|
+
password = nil
|
64
|
+
begin
|
65
|
+
printf "Password: "
|
66
|
+
STDOUT.flush
|
67
|
+
system "stty -echo"
|
68
|
+
password = $stdin.gets.chomp
|
69
|
+
ensure
|
70
|
+
system "stty echo"
|
71
|
+
printf "\n"
|
72
|
+
end
|
73
|
+
password
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
end end end
|
78
|
+
|
metadata
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: warthog
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Gerardo López-Fernádez
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-11-23 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: httparty
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
description: POkes A10 SLBs with a RESTick
|
31
|
+
email: gerir@evernote.com
|
32
|
+
executables:
|
33
|
+
- warthog
|
34
|
+
extensions: []
|
35
|
+
extra_rdoc_files: []
|
36
|
+
files:
|
37
|
+
- lib/warthog/a10/rest.rb
|
38
|
+
- lib/warthog/about.rb
|
39
|
+
- lib/warthog/cli/action/show.rb
|
40
|
+
- lib/warthog/cli/action.rb
|
41
|
+
- lib/warthog/cli.rb
|
42
|
+
- lib/warthog/version.rb
|
43
|
+
- lib/warthog.rb
|
44
|
+
- bin/warthog
|
45
|
+
- LICENSE
|
46
|
+
- README.md
|
47
|
+
homepage: https://github.com/evernote/ops-warthog
|
48
|
+
licenses:
|
49
|
+
- Apache License, Version 2.0
|
50
|
+
post_install_message:
|
51
|
+
rdoc_options: []
|
52
|
+
require_paths:
|
53
|
+
- lib
|
54
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
55
|
+
none: false
|
56
|
+
requirements:
|
57
|
+
- - ! '>='
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '0'
|
60
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: 1.3.5
|
66
|
+
requirements: []
|
67
|
+
rubyforge_project:
|
68
|
+
rubygems_version: 1.8.23
|
69
|
+
signing_key:
|
70
|
+
specification_version: 3
|
71
|
+
summary: A10 REST poker
|
72
|
+
test_files: []
|