warthog 0.1.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.
- 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: []
|