rea-netscaler-cli 0.5.9
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/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
|