rea-netscaler-cli 0.5.9
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +2 -0
- data/Gemfile.lock +57 -0
- data/README.markdown +37 -0
- data/Rakefile +16 -0
- data/bin/netscaler +5 -0
- data/lib/VERSION.yml +6 -0
- data/lib/netscaler/base_request.rb +52 -0
- data/lib/netscaler/cli.rb +246 -0
- data/lib/netscaler/config.rb +89 -0
- data/lib/netscaler/errors.rb +7 -0
- data/lib/netscaler/executor.rb +28 -0
- data/lib/netscaler/logging.rb +47 -0
- data/lib/netscaler/server/request.rb +35 -0
- data/lib/netscaler/server/response.rb +114 -0
- data/lib/netscaler/service/request.rb +42 -0
- data/lib/netscaler/service/response.rb +36 -0
- data/lib/netscaler/servicegroup/request.rb +46 -0
- data/lib/netscaler/servicegroup/response.rb +78 -0
- data/lib/netscaler/transaction.rb +68 -0
- data/lib/netscaler/vserver/request.rb +67 -0
- data/lib/netscaler/vserver/response.rb +115 -0
- data/spec/netscaler/cli_spec.rb +204 -0
- data/spec/netscaler/config_spec.rb +63 -0
- data/spec/netscaler/configs/bad-yaml.yml +2 -0
- data/spec/netscaler/configs/missing-username.yml +2 -0
- data/spec/netscaler/configs/simple-config.yml +8 -0
- data/spec/spec_helpers.rb +9 -0
- metadata +228 -0
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'netscaler/errors'
|
2
|
+
require 'netscaler/logging'
|
3
|
+
require 'netscaler/transaction'
|
4
|
+
require 'json'
|
5
|
+
|
6
|
+
module Netscaler
|
7
|
+
class Executor
|
8
|
+
|
9
|
+
def initialize(request_class)
|
10
|
+
@request_class = request_class
|
11
|
+
end
|
12
|
+
|
13
|
+
def execute!(args, options)
|
14
|
+
Netscaler::Logging.configure(options[:debug])
|
15
|
+
|
16
|
+
Netscaler::Transaction.new options[:netscaler] do |client|
|
17
|
+
@request_class.new(client).send(options[:action], args[0], options) do |response|
|
18
|
+
if options[:json]
|
19
|
+
puts JSON.pretty_generate(response)
|
20
|
+
else
|
21
|
+
STDERR.puts "Tempoararily disabled stdout. Use --json instead. Sorry...."
|
22
|
+
# puts Hirb::Helpers::Tree.render(response)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'log4r'
|
3
|
+
require 'savon'
|
4
|
+
|
5
|
+
module Netscaler
|
6
|
+
# A convenient module for mixins that allow to
|
7
|
+
# share the logging configuration everywhere
|
8
|
+
# easily
|
9
|
+
module Logging
|
10
|
+
@@log = nil
|
11
|
+
|
12
|
+
def Logging.configure(debug)
|
13
|
+
if @@log.nil?
|
14
|
+
@@log = Log4r::Logger.new 'netscaler'
|
15
|
+
@@log.outputters = Log4r::Outputter.stderr
|
16
|
+
@@log.level = Log4r::WARN
|
17
|
+
Log4r::Outputter.stderr.formatter = Log4r::PatternFormatter.new(:pattern => "[%l] %M")
|
18
|
+
|
19
|
+
@@log.level = debug ? Log4r::DEBUG : Log4r::INFO
|
20
|
+
|
21
|
+
Savon.configure do |config|
|
22
|
+
config.log = debug ? true : false
|
23
|
+
config.log_level = :debug
|
24
|
+
config.logger = @@log
|
25
|
+
config.raise_errors = false
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def Logging.log
|
31
|
+
@@log ||= Log4r::Logger.root
|
32
|
+
end
|
33
|
+
|
34
|
+
# Meant for mixing into other classes for simplified logging
|
35
|
+
def log
|
36
|
+
@@log ||= Log4r::Logger.root
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# SHUT THE HELL UP!
|
42
|
+
module HTTPI
|
43
|
+
class << self
|
44
|
+
def log(*messages)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'netscaler/base_request'
|
2
|
+
require 'netscaler/server/response'
|
3
|
+
|
4
|
+
module Netscaler::Server
|
5
|
+
class Request < Netscaler::BaseRequest
|
6
|
+
def enable(server, options)
|
7
|
+
send_request('enableserver', {:name => server})
|
8
|
+
end
|
9
|
+
|
10
|
+
def disable(server, options)
|
11
|
+
send_request('disableserver', {:name => server})
|
12
|
+
end
|
13
|
+
|
14
|
+
def list(server, options)
|
15
|
+
responses = []
|
16
|
+
send_request('getserver', {:empty => :ok}) do |response|
|
17
|
+
response_part(response).each_with_index do |server, i|
|
18
|
+
responses << Response.new(server).to_hash
|
19
|
+
end
|
20
|
+
end
|
21
|
+
yield responses if block_given?
|
22
|
+
end
|
23
|
+
|
24
|
+
def status(server, options)
|
25
|
+
send_request('getserver', {:name => server }) do |response|
|
26
|
+
yield Response.new(response_part(response)).to_hash if block_given?
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
def response_part(response)
|
32
|
+
response[:return][:list][:item]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
module Netscaler::Server
|
2
|
+
class Response
|
3
|
+
def initialize(raw_response)
|
4
|
+
@info = raw_response
|
5
|
+
end
|
6
|
+
|
7
|
+
def name
|
8
|
+
@info[:name]
|
9
|
+
end
|
10
|
+
|
11
|
+
def ip_address
|
12
|
+
@info[:ipaddress]
|
13
|
+
end
|
14
|
+
|
15
|
+
def state
|
16
|
+
@info[:state]
|
17
|
+
end
|
18
|
+
|
19
|
+
def services
|
20
|
+
@parsed_services ||= []
|
21
|
+
return @parsed_services if !@parsed_services.empty? || @info[:servicename].nil?
|
22
|
+
|
23
|
+
if @info[:servicename][:item].is_a?(String)
|
24
|
+
@parsed_services << ServiceInfo.new(@info, nil)
|
25
|
+
else
|
26
|
+
@info[:servicename][:item].each_with_index do |name, i|
|
27
|
+
@parsed_services << ServiceInfo.new(@info, i)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
@parsed_services
|
32
|
+
end
|
33
|
+
|
34
|
+
def to_hash
|
35
|
+
hash = {
|
36
|
+
:name => name,
|
37
|
+
:ip_address => ip_address,
|
38
|
+
:state => state,
|
39
|
+
}
|
40
|
+
|
41
|
+
if !services.empty?
|
42
|
+
hash[:services] = services.map {|s| s.to_hash}
|
43
|
+
end
|
44
|
+
|
45
|
+
hash
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
class ServiceInfo
|
50
|
+
attr_reader :name, :type, :state, :ip_address, :servicegroup
|
51
|
+
|
52
|
+
def initialize(raw_response, index)
|
53
|
+
@name = raw_response[:servicename][:item]
|
54
|
+
@ip_address = raw_response[:serviceipaddress][:item]
|
55
|
+
@state = raw_response[:svrstate][:item]
|
56
|
+
@port = raw_response[:port][:item]
|
57
|
+
@type = raw_response[:servicetype][:item]
|
58
|
+
|
59
|
+
if !index.nil?
|
60
|
+
@name = @name[index]
|
61
|
+
@ip_address = @ip_address[index]
|
62
|
+
@state = @state[index]
|
63
|
+
@port = @port[index]
|
64
|
+
@type = @type[index]
|
65
|
+
end
|
66
|
+
|
67
|
+
@servicegroup = if raw_response[:servicegroupname] && raw_response[:servicegroupname][:item]
|
68
|
+
ServiceGroupInfo.new(raw_response, index)
|
69
|
+
else
|
70
|
+
nil
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def port
|
75
|
+
@port.to_i
|
76
|
+
end
|
77
|
+
|
78
|
+
def to_hash
|
79
|
+
hash = {
|
80
|
+
:name => name,
|
81
|
+
:ip_address => ip_address,
|
82
|
+
:type => type,
|
83
|
+
:state => state,
|
84
|
+
:port => port,
|
85
|
+
}
|
86
|
+
|
87
|
+
if servicegroup
|
88
|
+
hash[:servicegroup] = servicegroup.to_hash
|
89
|
+
end
|
90
|
+
|
91
|
+
hash
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
class ServiceGroupInfo
|
96
|
+
attr_reader :name, :state
|
97
|
+
|
98
|
+
def initialize(raw_response, index)
|
99
|
+
@name = raw_response[:servicegroupname][:item]
|
100
|
+
@state = raw_response[:boundservicegroupsvrstate][:item]
|
101
|
+
|
102
|
+
if !index.nil?
|
103
|
+
@name = @name[index]
|
104
|
+
@state = @state[index]
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def to_hash
|
109
|
+
{ :name => name,
|
110
|
+
:state => state
|
111
|
+
}
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'netscaler/base_request'
|
2
|
+
require 'netscaler/service/response'
|
3
|
+
|
4
|
+
module Netscaler::Service
|
5
|
+
class Request < Netscaler::BaseRequest
|
6
|
+
def enable(service, options)
|
7
|
+
params = { :name => service }
|
8
|
+
send_request('enableservice', params)
|
9
|
+
end
|
10
|
+
|
11
|
+
def disable(service, options)
|
12
|
+
params = {
|
13
|
+
:name => service,
|
14
|
+
:delay => 0
|
15
|
+
}
|
16
|
+
send_request('disableservice', params)
|
17
|
+
end
|
18
|
+
|
19
|
+
def bind(service, options)
|
20
|
+
params = {
|
21
|
+
:name => options[:vserver],
|
22
|
+
:servicename => service
|
23
|
+
}
|
24
|
+
send_request('bindlbvserver_service', params)
|
25
|
+
end
|
26
|
+
|
27
|
+
def unbind(service, options)
|
28
|
+
params = {
|
29
|
+
:name => options[:vserver],
|
30
|
+
:servicename => service
|
31
|
+
}
|
32
|
+
send_request('unbindlbvserver_service', params)
|
33
|
+
end
|
34
|
+
|
35
|
+
def status(service, options)
|
36
|
+
params = { :name => service }
|
37
|
+
send_request('getservice', params) do |response|
|
38
|
+
yield Response.new(response).to_hash if block_given?
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Netscaler::Service
|
2
|
+
class Response
|
3
|
+
def initialize(raw_response)
|
4
|
+
@info = raw_response[:return][:list][:item]
|
5
|
+
end
|
6
|
+
|
7
|
+
def name
|
8
|
+
@info[:name]
|
9
|
+
end
|
10
|
+
|
11
|
+
def ip_address
|
12
|
+
@info[:ipaddress]
|
13
|
+
end
|
14
|
+
|
15
|
+
def state
|
16
|
+
@info[:svrstate]
|
17
|
+
end
|
18
|
+
|
19
|
+
def port
|
20
|
+
@info[:port].to_i
|
21
|
+
end
|
22
|
+
|
23
|
+
def server
|
24
|
+
@info[:servername]
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_hash
|
28
|
+
{ :name => name,
|
29
|
+
:server => server,
|
30
|
+
:ip_address => ip_address,
|
31
|
+
:state => state,
|
32
|
+
:port => port
|
33
|
+
}
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'netscaler/base_request'
|
2
|
+
require 'netscaler/servicegroup/response'
|
3
|
+
|
4
|
+
module Netscaler::ServiceGroup
|
5
|
+
class Request < Netscaler::BaseRequest
|
6
|
+
def enable(service, options)
|
7
|
+
params = { :servicegroupname => service }
|
8
|
+
[:servername, :port].each do |option|
|
9
|
+
params[option] = options[option] if options[option]
|
10
|
+
end
|
11
|
+
send_request('enableservicegroup', params)
|
12
|
+
end
|
13
|
+
|
14
|
+
def disable(servicegroup, options)
|
15
|
+
params = { :servicegroupname => servicegroup }
|
16
|
+
[:servername, :port, :delay].each do |option|
|
17
|
+
params[option] = options[option] if options[option]
|
18
|
+
end
|
19
|
+
send_request('disableservicegroup', params)
|
20
|
+
end
|
21
|
+
|
22
|
+
def bind(servicegroup, options)
|
23
|
+
params = {
|
24
|
+
:name => options[:vserver],
|
25
|
+
:servicegroupname => servicegroup
|
26
|
+
}
|
27
|
+
send_request('bindlbvserver_servicegroup', params)
|
28
|
+
end
|
29
|
+
|
30
|
+
def unbind(servicegroup, options)
|
31
|
+
params = {
|
32
|
+
:name => options[:vserver],
|
33
|
+
:servicename => servicegroup
|
34
|
+
}
|
35
|
+
send_request('unbindlbvserver_servicegroup', params)
|
36
|
+
end
|
37
|
+
|
38
|
+
def status(servicegroup, options)
|
39
|
+
params = { :servicegroupname => servicegroup }
|
40
|
+
send_request('getservicegroup', params) do |response|
|
41
|
+
yield Response.new(response).to_hash if block_given?
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
@@ -0,0 +1,78 @@
|
|
1
|
+
module Netscaler::ServiceGroup
|
2
|
+
class Response
|
3
|
+
def initialize(raw_response)
|
4
|
+
@info = raw_response[:return][:list][:item]
|
5
|
+
end
|
6
|
+
|
7
|
+
def name
|
8
|
+
@info[:servicegroupname]
|
9
|
+
end
|
10
|
+
|
11
|
+
def state
|
12
|
+
@info[:state]
|
13
|
+
end
|
14
|
+
|
15
|
+
def type
|
16
|
+
@info[:servicetype]
|
17
|
+
end
|
18
|
+
|
19
|
+
def servers
|
20
|
+
@parsed_servers ||= []
|
21
|
+
return @parsed_servers if !@parsed_servers.empty? || @info[:servername].nil?
|
22
|
+
|
23
|
+
if @info[:servername][:item].is_a?(String)
|
24
|
+
@parsed_servers << ServerInfo.new(@info, nil)
|
25
|
+
else
|
26
|
+
@info[:servername][:item].each_with_index do |name, i|
|
27
|
+
@parsed_servers << ServerInfo.new(@info, i)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
@parsed_servers
|
32
|
+
end
|
33
|
+
|
34
|
+
def to_hash
|
35
|
+
hash = {
|
36
|
+
:name => name,
|
37
|
+
:state => state,
|
38
|
+
:type => type,
|
39
|
+
}
|
40
|
+
|
41
|
+
if !servers.empty?
|
42
|
+
hash[:servers] = servers.map {|s| s.to_hash}
|
43
|
+
end
|
44
|
+
|
45
|
+
hash
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
class ServerInfo
|
50
|
+
attr_reader :name, :ip_address, :state
|
51
|
+
|
52
|
+
def initialize(raw_response, index)
|
53
|
+
@name = raw_response[:servername][:item]
|
54
|
+
@ip_address = raw_response[:ipaddress][:item]
|
55
|
+
@state = raw_response[:svcstate][:item]
|
56
|
+
@port = raw_response[:port][:item]
|
57
|
+
|
58
|
+
if !index.nil?
|
59
|
+
@name = @name[index]
|
60
|
+
@ip_address = @ip_address[index]
|
61
|
+
@state = @state[index]
|
62
|
+
@port = @port[index]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def port
|
67
|
+
@port.to_i
|
68
|
+
end
|
69
|
+
|
70
|
+
def to_hash
|
71
|
+
{ :name => name,
|
72
|
+
:ip_address => ip_address,
|
73
|
+
:state => state,
|
74
|
+
:port => port
|
75
|
+
}
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'netscaler/logging'
|
2
|
+
require 'savon'
|
3
|
+
|
4
|
+
module Netscaler
|
5
|
+
NSCONFIG_NAMESPACE = "urn:NSConfig"
|
6
|
+
|
7
|
+
class Transaction
|
8
|
+
include Logging
|
9
|
+
|
10
|
+
def initialize(config, &block)
|
11
|
+
@config = config
|
12
|
+
if block_given?
|
13
|
+
execute(&block)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def execute(&block)
|
18
|
+
if !block_given?
|
19
|
+
raise Netscaler::TransactionError.new("No execution block given.")
|
20
|
+
end
|
21
|
+
|
22
|
+
log.debug("Beginning the transaction execution: #{@config.host}")
|
23
|
+
begin
|
24
|
+
client = Savon::Client.new do
|
25
|
+
wsdl.endpoint = url
|
26
|
+
wsdl.namespace = Netscaler::NSCONFIG_NAMESPACE
|
27
|
+
end
|
28
|
+
client.http.auth.ssl.verify_mode = :none
|
29
|
+
|
30
|
+
log.debug("Logging in to the Netscaler host.")
|
31
|
+
body = { :username => @config.username, :password => @config.password }
|
32
|
+
|
33
|
+
response = client.request :login do
|
34
|
+
#soap.namespace = Netscaler::NSCONFIG_NAMESPACE
|
35
|
+
soap.body = body
|
36
|
+
end
|
37
|
+
|
38
|
+
auth_cookie = response.http.headers['Set-Cookie']
|
39
|
+
client.http.headers['Cookie'] = auth_cookie
|
40
|
+
log.debug("Got authorization cookie: #{auth_cookie}")
|
41
|
+
|
42
|
+
log.debug("Yielding client control to the calling context")
|
43
|
+
yield client
|
44
|
+
rescue SystemExit => e
|
45
|
+
raise
|
46
|
+
rescue Exception => e
|
47
|
+
log.fatal(e)
|
48
|
+
log.fatal("Unable to execute transaction.")
|
49
|
+
raise Netscaler::TransactionError.new(e)
|
50
|
+
ensure
|
51
|
+
begin
|
52
|
+
log.debug("Logging out of the Netscaler host.")
|
53
|
+
client.request :logout
|
54
|
+
rescue Exception => e
|
55
|
+
log.fatal(e)
|
56
|
+
log.fatal("Unable to logout.")
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
log.debug("Ending the transaction execution: #{@config.host}")
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
def url
|
65
|
+
"https://#{@config.host}/soap"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|