netscaler-cli 0.3.3 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +7 -3
- data/Gemfile.lock +17 -8
- data/README.markdown +6 -3
- data/Rakefile +4 -6
- data/bin/{netscaler-server → netscaler} +2 -2
- data/etc/Version +1 -1
- data/lib/netscaler/{baseexecutor.rb → base_request.rb} +3 -4
- data/lib/netscaler/cli.rb +201 -0
- data/lib/netscaler/config.rb +20 -15
- data/lib/netscaler/executor.rb +34 -0
- data/lib/netscaler/extensions.rb +47 -0
- data/lib/netscaler/server/request.rb +35 -0
- data/lib/netscaler/server/response.rb +67 -0
- data/lib/netscaler/service/request.rb +42 -0
- data/lib/netscaler/service/response.rb +44 -0
- data/lib/netscaler/vserver/request.rb +67 -0
- data/lib/netscaler/vserver/response.rb +125 -0
- data/spec/netscaler/cli_spec.rb +140 -0
- data/spec/{config_spec.rb → netscaler/config_spec.rb} +23 -9
- data/spec/{configs → netscaler/configs}/bad-yaml.yml +0 -0
- data/spec/{configs → netscaler/configs}/missing-username.yml +0 -0
- data/spec/{configs → netscaler/configs}/simple-config.yml +2 -1
- data/spec/netscaler/extenstions_spec.rb +26 -0
- data/spec/{helpers.rb → spec_helpers.rb} +0 -0
- metadata +108 -53
- data/bin/netscaler-service +0 -5
- data/bin/netscaler-vserver +0 -5
- data/lib/netscaler/clitemplate.rb +0 -147
- data/lib/netscaler/server/cli.rb +0 -60
- data/lib/netscaler/server/executor.rb +0 -115
- data/lib/netscaler/service/cli.rb +0 -49
- data/lib/netscaler/service/executor.rb +0 -82
- data/lib/netscaler/vserver/cli.rb +0 -92
- data/lib/netscaler/vserver/executor.rb +0 -194
- data/spec/server/cli_spec.rb +0 -33
- data/spec/service/cli_spec.rb +0 -45
- data/spec/vserver/cli_spec.rb +0 -75
data/Gemfile
CHANGED
@@ -1,9 +1,13 @@
|
|
1
1
|
source :rubygems
|
2
2
|
|
3
3
|
gem 'log4r', '~> 1.1'
|
4
|
-
gem 'savon', '~> 0.7'
|
4
|
+
gem 'savon', '~> 0.7.0'
|
5
5
|
gem 'highline', '>= 1.6'
|
6
|
+
gem 'choosy', '~> 0.2'
|
6
7
|
|
7
|
-
group :
|
8
|
-
gem 'rspec'
|
8
|
+
group :development do
|
9
|
+
gem 'rspec', :require => "spec"
|
10
|
+
gem 'autotest'
|
11
|
+
gem 'autotest-notification'
|
9
12
|
end
|
13
|
+
|
data/Gemfile.lock
CHANGED
@@ -1,19 +1,25 @@
|
|
1
1
|
GEM
|
2
2
|
remote: http://rubygems.org/
|
3
3
|
specs:
|
4
|
+
ZenTest (4.5.0)
|
5
|
+
autotest (4.4.6)
|
6
|
+
ZenTest (>= 4.4.1)
|
7
|
+
autotest-notification (2.3.1)
|
8
|
+
autotest (~> 4.3)
|
4
9
|
builder (3.0.0)
|
10
|
+
choosy (0.2.3)
|
5
11
|
crack (0.1.8)
|
6
12
|
diff-lcs (1.1.2)
|
7
13
|
highline (1.6.1)
|
8
14
|
log4r (1.1.9)
|
9
|
-
rspec (2.
|
10
|
-
rspec-core (~> 2.
|
11
|
-
rspec-expectations (~> 2.
|
12
|
-
rspec-mocks (~> 2.
|
13
|
-
rspec-core (2.
|
14
|
-
rspec-expectations (2.
|
15
|
+
rspec (2.5.0)
|
16
|
+
rspec-core (~> 2.5.0)
|
17
|
+
rspec-expectations (~> 2.5.0)
|
18
|
+
rspec-mocks (~> 2.5.0)
|
19
|
+
rspec-core (2.5.1)
|
20
|
+
rspec-expectations (2.5.0)
|
15
21
|
diff-lcs (~> 1.1.2)
|
16
|
-
rspec-mocks (2.
|
22
|
+
rspec-mocks (2.5.0)
|
17
23
|
savon (0.7.9)
|
18
24
|
builder (>= 2.1.2)
|
19
25
|
crack (>= 0.1.4)
|
@@ -22,7 +28,10 @@ PLATFORMS
|
|
22
28
|
ruby
|
23
29
|
|
24
30
|
DEPENDENCIES
|
31
|
+
autotest
|
32
|
+
autotest-notification
|
33
|
+
choosy (~> 0.2)
|
25
34
|
highline (>= 1.6)
|
26
35
|
log4r (~> 1.1)
|
27
36
|
rspec
|
28
|
-
savon (~> 0.7)
|
37
|
+
savon (~> 0.7.0)
|
data/README.markdown
CHANGED
@@ -12,9 +12,9 @@ The command line tools can be installed with:
|
|
12
12
|
|
13
13
|
The following commands are currently a part of the system:
|
14
14
|
|
15
|
-
* *netscaler
|
16
|
-
* *netscaler
|
17
|
-
* *netscaler
|
15
|
+
* *netscaler vserver* -- An interface for enabling, disabling, querying, and binding responder policies to a specific virtual server.
|
16
|
+
* *netscaler service* -- An interface for enabling, disabling, querying, and binding servers to specific services.
|
17
|
+
* *netscaler server* -- An interface for enabling, disabling, querying, and binding servers to virtual servers.
|
18
18
|
|
19
19
|
Each command requires at least the --netscaler flag (which can be the full netscaler host name in the configuration file, or its alias, see below).
|
20
20
|
|
@@ -30,5 +30,8 @@ Each load balancer requires an entry in the file in the form:
|
|
30
30
|
username: 'some.username'
|
31
31
|
password: 'super!duper!secret!'
|
32
32
|
alias: prod
|
33
|
+
version: '9.2'
|
33
34
|
|
34
35
|
Multiple entries can be in the file; the password and the alias settings are not required. An alias can be used as a shortcut name on the command line for a particular netscaler server. However, if no password is given in the file for a given configuration, the tool will ask you for it.
|
36
|
+
|
37
|
+
The version information is optional, but breaking API changes were introduced in version 9.2 of Netscaler software, so some commands may fail if this isn't set for this Netscaler software version.
|
data/Rakefile
CHANGED
@@ -12,17 +12,14 @@ include FileUtils
|
|
12
12
|
task :default => :spec
|
13
13
|
|
14
14
|
desc "Run the RSpec tests"
|
15
|
-
RSpec::Core::RakeTask.new
|
16
|
-
t.rspec_opts = ['-b', '-c', '-f', 'p']
|
17
|
-
t.fail_on_error = false
|
18
|
-
end
|
15
|
+
RSpec::Core::RakeTask.new :spec
|
19
16
|
|
20
17
|
begin
|
21
18
|
require 'jeweler'
|
22
19
|
Jeweler::Tasks.new do |gem|
|
23
20
|
gem.name = 'netscaler-cli'
|
24
21
|
gem.version = Netscaler::Version.to_s
|
25
|
-
gem.executables = %W{netscaler
|
22
|
+
gem.executables = %W{netscaler}
|
26
23
|
gem.summary = 'Simple command line utilities for interacting remotely with a Netscaler load balancer.'
|
27
24
|
gem.description = 'This gem installs several simple command line utilities locally. It uses the NSConfig.wsdl SOAP interface for remote access.'
|
28
25
|
gem.email = ['madeonamac@gmail.com']
|
@@ -33,8 +30,9 @@ begin
|
|
33
30
|
gem.add_dependency 'log4r', '>=1.1.9'
|
34
31
|
gem.add_dependency 'savon', '>=0.7.9'
|
35
32
|
gem.add_dependency 'highline', '>=1.6'
|
33
|
+
gem.add_dependency 'choosy', '>=0.2.3'
|
36
34
|
|
37
|
-
gem.add_development_dependency 'rspec', '>=2.
|
35
|
+
gem.add_development_dependency 'rspec', '>=2.5.0'
|
38
36
|
end
|
39
37
|
rescue LoadError
|
40
38
|
puts "Jeweler or dependencies are not available. Install it with: sudo gem install jeweler"
|
data/etc/Version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.4.0
|
@@ -1,13 +1,12 @@
|
|
1
1
|
require 'netscaler/logging'
|
2
2
|
|
3
3
|
module Netscaler
|
4
|
-
class
|
4
|
+
class BaseRequest
|
5
5
|
include Netscaler::Logging
|
6
6
|
|
7
|
-
attr_reader :
|
7
|
+
attr_reader :client
|
8
8
|
|
9
|
-
def initialize(
|
10
|
-
@host = host
|
9
|
+
def initialize(client)
|
11
10
|
@client = client
|
12
11
|
end
|
13
12
|
|
@@ -0,0 +1,201 @@
|
|
1
|
+
require 'netscaler/errors'
|
2
|
+
require 'netscaler/version'
|
3
|
+
require 'netscaler/config'
|
4
|
+
require 'netscaler/executor'
|
5
|
+
require 'netscaler/server/request'
|
6
|
+
require 'netscaler/vserver/request'
|
7
|
+
require 'netscaler/service/request'
|
8
|
+
require 'choosy'
|
9
|
+
|
10
|
+
module Netscaler
|
11
|
+
class CLI
|
12
|
+
|
13
|
+
def initialize(args)
|
14
|
+
@args = args.dup
|
15
|
+
end
|
16
|
+
|
17
|
+
def parse!(propagate=nil)
|
18
|
+
command.parse!(@args, propagate)
|
19
|
+
end
|
20
|
+
|
21
|
+
def execute!
|
22
|
+
begin
|
23
|
+
command.execute!(@args)
|
24
|
+
rescue SystemExit
|
25
|
+
raise
|
26
|
+
rescue Netscaler::ConfigurationError => e
|
27
|
+
print_error(e.message)
|
28
|
+
exit 1
|
29
|
+
rescue Exception => e
|
30
|
+
STDERR.puts e.backtrace
|
31
|
+
print_error(e.message)
|
32
|
+
exit 1
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
protected
|
37
|
+
def command
|
38
|
+
cmds = [servers, vservers, services]
|
39
|
+
@command ||= Choosy::SuperCommand.new :netscaler do
|
40
|
+
printer :standard, :color => true, :headers => [:bold, :blue], :max_width => 80
|
41
|
+
|
42
|
+
summary "This is a command line tool for interacting with Netscaler load balancer"
|
43
|
+
header 'Description:'
|
44
|
+
para "There are several subcommands to do various things with the load balancer. Try 'netscaler help SUBCOMMAND' for more information about the particular command you want to use."
|
45
|
+
para "Note that you can supply a configuration file, which would normally be found under ~/.netscaler-cli.yml. That file describes the relationship between your Netscaler load balancers and the aliases, usernames, and passwords that you supply for them. The file is in the general format:"
|
46
|
+
para " netscaler.host.name.com:
|
47
|
+
alias: is_optional
|
48
|
+
usernamd: is_required
|
49
|
+
password: is_optional_but_querried_if_not_found"
|
50
|
+
|
51
|
+
# COMMANDS
|
52
|
+
header 'Commands:'
|
53
|
+
cmds.each do |cmd|
|
54
|
+
command cmd
|
55
|
+
end
|
56
|
+
para ''
|
57
|
+
help
|
58
|
+
|
59
|
+
# OPTIONS
|
60
|
+
header 'Global Options:'
|
61
|
+
string :netscaler, "The IP Address, hostname, or alias in the config file of the Netscaler load balancer. This is required." do
|
62
|
+
depends_on :config
|
63
|
+
required
|
64
|
+
|
65
|
+
validate do |arg, options|
|
66
|
+
reader = Netscaler::ConfigurationReader.new(options[:config])
|
67
|
+
config = reader[arg]
|
68
|
+
if config.nil?
|
69
|
+
die "the Netscaler address '#{arg}' is not defined in the configuration file"
|
70
|
+
else
|
71
|
+
options[:netscaler] = config
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
yaml :config, "The path to the netscaler configuration file. By default, it is ~/.netscaler-cli.yml" do
|
76
|
+
default File.join(ENV['HOME'], '.netscaler-cli.yml')
|
77
|
+
end
|
78
|
+
|
79
|
+
header 'Informative:'
|
80
|
+
boolean_ :debug, "Print extra debug information"
|
81
|
+
boolean_ :json, "Prints out JSON instead of textual data"
|
82
|
+
version Netscaler::Version.to_s
|
83
|
+
end
|
84
|
+
end#command
|
85
|
+
|
86
|
+
def servers
|
87
|
+
Choosy::Command.new :server do |s|
|
88
|
+
executor Netscaler::Executor.new(Netscaler::Server::Request)
|
89
|
+
summary "Enables, disbles, or lists servers in the load balancer"
|
90
|
+
header 'Description:'
|
91
|
+
para "This is a tool for enabling and disabling a server in a Netscaler load balancer. The name of the server is required, as is the address of the Netscaler load balancer."
|
92
|
+
para "By default, this command will tell you what the current status of the server is."
|
93
|
+
para "If you want to list all of the services, use the --list flag."
|
94
|
+
|
95
|
+
header 'Options:'
|
96
|
+
enum :action, [:enable, :disable, :list, :status], "Either [enable, disable, list]. 'list' will ignore additional arguments. Default action is 'status'" do
|
97
|
+
default :status
|
98
|
+
end
|
99
|
+
arguments do
|
100
|
+
count 0..1 #:at_least => 0, :at_most => 1
|
101
|
+
metaname 'SERVER'
|
102
|
+
validate do |args, options|
|
103
|
+
if args.length == 0
|
104
|
+
die "no server given to act upon" unless options[:action] == :list
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def vservers
|
112
|
+
Choosy::Command.new :vserver do
|
113
|
+
executor Netscaler::Executor.new(Netscaler::VServer::Request)
|
114
|
+
summary "Enables, disables, binds or unbinds policies, or lists virtual servers."
|
115
|
+
header 'Description:'
|
116
|
+
para "This is a tool for acting upon virtual servers (VIPs) in a Netscaler load balancer. The name of the virtual server is required."
|
117
|
+
para "By default, this command will tell you what the current status of the server is."
|
118
|
+
para "If you want to list all of the virtual servers, use the --list flag."
|
119
|
+
|
120
|
+
header 'Options:'
|
121
|
+
enum :action, [:enable, :disable, :list, :bind, :unbind, :status], "Either [enable, disable, list, bind, unbind, status]. 'bind' and 'unbind' require the additional '--policy' flag. 'list' will ignore additional arguments. Default action is 'status'." do
|
122
|
+
default :status
|
123
|
+
end
|
124
|
+
string :policy, "The name of the policy to bind/unbind." do
|
125
|
+
depends_on :action
|
126
|
+
default :unset
|
127
|
+
validate do |arg, options|
|
128
|
+
if [:bind, :unbind].include?(options[:action])
|
129
|
+
die "required by the 'bind/unbind' actions" if arg == :unset
|
130
|
+
else
|
131
|
+
die "only used with bind/unbind" unless arg == :unset
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
integer :Priority, "The integer priority of the policy to bind with. Default is 100." do
|
136
|
+
depends_on :action, :policy
|
137
|
+
default -1
|
138
|
+
validate do |arg, options|
|
139
|
+
if options[:action] == :bind
|
140
|
+
if arg == -1
|
141
|
+
options[:Priority] = 100
|
142
|
+
end
|
143
|
+
elsif arg != -1
|
144
|
+
die "only used with the bind action"
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
arguments do
|
149
|
+
count 0..1 #:at_least => 0, :at_most => 1
|
150
|
+
metaname 'SERVER'
|
151
|
+
validate do |args, options|
|
152
|
+
if args.length == 0
|
153
|
+
die "no virtual server given to act upon" unless options[:action] == :list
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
def services
|
161
|
+
Choosy::Command.new :service do
|
162
|
+
executor Netscaler::Executor.new(Netscaler::Service::Request)
|
163
|
+
summary "Enables, disables, binds or unbinds from a virtual server, a given service."
|
164
|
+
header 'Description:'
|
165
|
+
para "This is a tool for enabling and disabling services in a Netscaler load balancer. The name of the service is required, as is the address of the Netscaler load balancer."
|
166
|
+
|
167
|
+
header 'Options:'
|
168
|
+
enum :action, [:enable, :disable, :bind, :unbind, :status], "Either [enable, disable, bind, unbind, status] of a service. 'bind' and 'unbind' require the '--vserver' flag. Default is 'status'." do
|
169
|
+
default :status
|
170
|
+
end
|
171
|
+
string :vserver, "The virtual server to bind/unbind this service to/from." do
|
172
|
+
depends_on :action
|
173
|
+
default :unset
|
174
|
+
validate do |arg, options|
|
175
|
+
if [:bind, :unbind].include?(options[:action])
|
176
|
+
die "requires the -v/--vserver flag" if arg == :unset
|
177
|
+
else
|
178
|
+
die "only used with bind/unbind" unless arg == :unset
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
arguments do
|
183
|
+
count 0..1 #:at_least => 0, :at_most => 1
|
184
|
+
metaname 'SERVICE'
|
185
|
+
validate do |args, options|
|
186
|
+
if args.length == 0
|
187
|
+
die "no services given to act on" unless options[:action] == :list
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
private
|
195
|
+
def print_error(e)
|
196
|
+
STDERR.puts "#{File.basename($0)}: #{e}"
|
197
|
+
STDERR.puts "Try '#{File.basename($0)} help' for more information"
|
198
|
+
exit 1
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
data/lib/netscaler/config.rb
CHANGED
@@ -6,8 +6,8 @@ require 'highline/import'
|
|
6
6
|
module Netscaler
|
7
7
|
|
8
8
|
class ConfigurationReader
|
9
|
-
def initialize(
|
10
|
-
@servers =
|
9
|
+
def initialize(yaml)
|
10
|
+
@servers = yaml
|
11
11
|
end
|
12
12
|
|
13
13
|
def [](name)
|
@@ -32,16 +32,7 @@ module Netscaler
|
|
32
32
|
@servers.keys
|
33
33
|
end
|
34
34
|
|
35
|
-
|
36
|
-
def create_config(lbname, yaml)
|
37
|
-
if yaml['username'].nil?
|
38
|
-
raise Netscaler::ConfigurationError.new("No username was specified for the given Netscaler host")
|
39
|
-
end
|
40
|
-
|
41
|
-
Configuration.new(lbname, yaml['username'], yaml['password'], yaml['alias'])
|
42
|
-
end
|
43
|
-
|
44
|
-
def read_config_file(file)
|
35
|
+
def self.read_config_file(file)
|
45
36
|
if file.nil?
|
46
37
|
file = File.expand_path(".netscaler-cli.yml", Etc.getpwuid.dir)
|
47
38
|
end
|
@@ -52,21 +43,35 @@ module Netscaler
|
|
52
43
|
|
53
44
|
begin
|
54
45
|
yaml = File.read(file)
|
55
|
-
|
46
|
+
ConfigurationReader.new(YAML::load(yaml))
|
56
47
|
rescue Exception => e
|
57
48
|
raise Netscaler::ConfigurationError.new("Unable to load the netscaler-cli configuration file")
|
58
49
|
end
|
59
50
|
end
|
51
|
+
|
52
|
+
private
|
53
|
+
def create_config(lbname, yaml)
|
54
|
+
if yaml['username'].nil?
|
55
|
+
raise Netscaler::ConfigurationError.new("No username was specified for the given Netscaler host")
|
56
|
+
end
|
57
|
+
|
58
|
+
Configuration.new(lbname, yaml['username'], yaml['password'], yaml['alias'], yaml['version'])
|
59
|
+
end
|
60
60
|
end
|
61
61
|
|
62
62
|
class Configuration
|
63
|
-
attr_reader :host, :username, :password, :alias
|
63
|
+
attr_reader :host, :username, :password, :alias, :version
|
64
64
|
|
65
|
-
def initialize(host, username, password=nil, nalias=nil)
|
65
|
+
def initialize(host, username, password=nil, nalias=nil, version=nil)
|
66
66
|
@host = host
|
67
67
|
@username = username
|
68
68
|
@password = password
|
69
69
|
@alias = nalias
|
70
|
+
@version = if version
|
71
|
+
version.to_s
|
72
|
+
else
|
73
|
+
"9.2"
|
74
|
+
end
|
70
75
|
|
71
76
|
query_password
|
72
77
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'netscaler/errors'
|
2
|
+
require 'netscaler/logging'
|
3
|
+
require 'netscaler/transaction'
|
4
|
+
require 'netscaler/extensions'
|
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 response.to_json
|
20
|
+
else
|
21
|
+
if response.is_a?(Array)
|
22
|
+
if response.length > 0
|
23
|
+
puts response[0].header
|
24
|
+
end
|
25
|
+
else
|
26
|
+
puts response.header
|
27
|
+
end
|
28
|
+
puts response.to_s
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|