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 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
+ */
File without changes
@@ -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
@@ -0,0 +1,3 @@
1
+ module Warthog
2
+
3
+ end
@@ -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
@@ -0,0 +1,5 @@
1
+ require 'warthog/version'
2
+ module Warthog
3
+ ME = :warthog
4
+ ABOUT = "#{ME} v#{VERSION}\nhttps://github.com/evernote/ops-#{ME}\nCopyright (c) 2012 by Evernote Corporation\nLicensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)"
5
+ end
@@ -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,4 @@
1
+ require 'warthog/cli/action/show'
2
+
3
+ module Warthog; module CLI; module Action
4
+ end 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
+
@@ -0,0 +1,3 @@
1
+ module Warthog
2
+ VERSION = "0.1.0"
3
+ end
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: []