netscaler-cli 0.2.3 → 0.3.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/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source :rubygems
2
+
3
+ gem 'log4r', '~> 1.1'
4
+ gem 'savon', '~> 0.7'
5
+ gem 'highline', '>= 1.6'
6
+
7
+ group :test do
8
+ gem 'rspec'
9
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,28 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ builder (3.0.0)
5
+ crack (0.1.8)
6
+ diff-lcs (1.1.2)
7
+ highline (1.6.1)
8
+ log4r (1.1.9)
9
+ rspec (2.2.0)
10
+ rspec-core (~> 2.2)
11
+ rspec-expectations (~> 2.2)
12
+ rspec-mocks (~> 2.2)
13
+ rspec-core (2.2.1)
14
+ rspec-expectations (2.2.0)
15
+ diff-lcs (~> 1.1.2)
16
+ rspec-mocks (2.2.0)
17
+ savon (0.7.9)
18
+ builder (>= 2.1.2)
19
+ crack (>= 0.1.4)
20
+
21
+ PLATFORMS
22
+ ruby
23
+
24
+ DEPENDENCIES
25
+ highline (>= 1.6)
26
+ log4r (~> 1.1)
27
+ rspec
28
+ savon (~> 0.7)
data/README.markdown CHANGED
@@ -12,9 +12,12 @@ 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-vserver* -- An interface for enabling, disabling, and binding responder policies to a specific virtual server.
16
- * *netscaler-service* -- An interface for enabling, disabling, and binding virtual servers to specific service.
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.
17
18
 
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
+
18
21
  # Configuration
19
22
 
20
23
  All of the commands rely upon a configuration file in the YAML format. By default, it looks for a file in your home directory
@@ -23,8 +26,9 @@ All of the commands rely upon a configuration file in the YAML format. By defau
23
26
 
24
27
  Each load balancer requires an entry in the file in the form:
25
28
 
26
- netscaler.loadbalancer.somecompany.com
29
+ netscaler.loadbalancer.somecompany.com:
27
30
  username: 'some.username'
28
31
  password: 'super!duper!secret!'
32
+ alias: prod
29
33
 
30
- Multiple entries can be in the file; the password setting is not required. If it is not given in the file, the tool will ask you for it.
34
+ 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.
data/Rakefile CHANGED
@@ -28,11 +28,11 @@ begin
28
28
  gem.homepage = 'http://github.com/gabemc/netscaler-cli'
29
29
  gem.files = FileList["[A-Z]*", "{bin,lib,spec}/**/*"]
30
30
 
31
- gem.add_dependency 'highline', '>=1.5.2'
32
- gem.add_dependency 'log4r', '>=1.1.7'
31
+ gem.add_dependency 'log4r', '>=1.1.9'
33
32
  gem.add_dependency 'savon', '>=0.7.9'
33
+ gem.add_dependency 'highline', '>=1.6'
34
34
 
35
- gem.add_development_dependency 'rspec', '>=2.0.1'
35
+ gem.add_development_dependency 'rspec', '>=2.2.0'
36
36
  end
37
37
  rescue LoadError
38
38
  puts "Jeweler or dependencies are not available. Install it with: sudo gem install jeweler"
@@ -4,7 +4,7 @@ module Netscaler
4
4
  class BaseExecutor
5
5
  include Netscaler::Logging
6
6
 
7
- attr_reader :host, :client
7
+ attr_reader :host, :client, :json
8
8
 
9
9
  def initialize(host, client)
10
10
  @host = host
@@ -32,16 +32,14 @@ module Netscaler
32
32
  log.debug(result)
33
33
 
34
34
  response = result.to_hash["#{name.to_s}_response".to_sym]
35
- if block_given?
35
+ msg = response[:return][:message]
36
+ if msg !~ /^Done$/
37
+ log.error(response[:return][:message])
38
+ exit(1)
39
+ elsif block_given?
36
40
  yield response
37
- else
38
- msg = response[:return][:message]
39
- if msg !~ /^Done$/
40
- log.error(response[:return][:message])
41
- exit(1)
42
- else
43
- log.debug(msg)
44
- end
41
+ else
42
+ log.debug(msg)
45
43
  end
46
44
 
47
45
  result
@@ -78,6 +78,10 @@ module Netscaler
78
78
  "Prints extra debug information") do |d|
79
79
  options[:debug] = d
80
80
  end
81
+ opts.on('--json',
82
+ "Prints out JSON data instead of textual output.") do |j|
83
+ options[:json] = j
84
+ end
81
85
  opts.on('-v', '--version',
82
86
  "Show the version information") do |v|
83
87
  puts "#{File.basename($0)} version: #{Netscaler::Version.to_s}"
@@ -10,17 +10,22 @@ module Netscaler
10
10
  @servers = read_config_file(file)
11
11
  end
12
12
 
13
- def [](host)
14
- found = @servers[host]
15
- if found.nil?
16
- raise Netscaler::ConfigurationError.new("The specified Netscaler host was not found")
13
+ def [](name)
14
+ # First, try the aliases
15
+ @servers.each_key do |lbname|
16
+ found = @servers[lbname]
17
+ if found['alias'] == name
18
+ return create_config(lbname, found)
19
+ end
17
20
  end
18
21
 
19
- if found['username'].nil?
20
- raise Netscaler::ConfigurationError.new("No username was specified for the given Netscaler host")
22
+ # Next, check the actual server names
23
+ found = @servers[name]
24
+ if found.nil?
25
+ raise Netscaler::ConfigurationError.new("The specified Netscaler host was not found")
21
26
  end
22
27
 
23
- Configuration.new(host, found['username'], found['password'])
28
+ return create_config(name, found)
24
29
  end
25
30
 
26
31
  def load_balancers
@@ -28,6 +33,14 @@ module Netscaler
28
33
  end
29
34
 
30
35
  private
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
+
31
44
  def read_config_file(file)
32
45
  if file.nil?
33
46
  file = File.expand_path(".netscaler-cli.yml", Etc.getpwuid.dir)
@@ -47,12 +60,13 @@ module Netscaler
47
60
  end
48
61
 
49
62
  class Configuration
50
- attr_reader :host, :username, :password
63
+ attr_reader :host, :username, :password, :alias
51
64
 
52
- def initialize(host, username, password=nil)
65
+ def initialize(host, username, password=nil, nalias=nil)
53
66
  @host = host
54
67
  @username = username
55
68
  @password = password
69
+ @alias = nalias
56
70
 
57
71
  query_password
58
72
  end
@@ -17,11 +17,59 @@ module Netscaler::Server
17
17
 
18
18
  def status(options)
19
19
  send_request('getserver', @params) do |response|
20
- info = response[:return][:list][:item]
21
- puts "Name: #{info[:name]}"
22
- puts "IP Address: #{info[:ipaddress]}"
23
- puts "State: #{info[:state]}"
20
+ resp = Response.new(response)
21
+ if options[:json]
22
+ puts resp.to_json
23
+ else
24
+ puts resp.to_s
25
+ end
24
26
  end
25
27
  end
26
28
  end
29
+
30
+ class Response
31
+ attr_reader :raw_response, :info
32
+
33
+ def initialize(raw_response)
34
+ @raw_response = raw_response
35
+ @info = raw_response[:return][:list][:item]
36
+ end
37
+
38
+ def name
39
+ info[:name]
40
+ end
41
+
42
+ def ip_address
43
+ info[:ipaddress]
44
+ end
45
+
46
+ def state
47
+ info[:state]
48
+ end
49
+
50
+ def services
51
+ info[:servicename][:item]
52
+ end
53
+
54
+ def to_s
55
+ base = "Name:\t#{name}\nIP Address:\t#{ip_address}\nState:\t#{state}\nServices:\n"
56
+ services.each do |service|
57
+ base << "\t#{service}\n"
58
+ end
59
+ base
60
+ end
61
+
62
+ def to_json
63
+ base = "{ 'name': '#{name}', 'ip_address': '#{ip_address}', 'state': '#{state}', 'services': ["
64
+
65
+ services.each_with_index do |service, i|
66
+ base << "'#{service}'"
67
+ if i != services.length - 1
68
+ base << ", "
69
+ end
70
+ end
71
+
72
+ base << "] }"
73
+ end
74
+ end
27
75
  end
@@ -19,25 +19,12 @@ module Netscaler::Service
19
19
  send_request('disableservice', params)
20
20
  end
21
21
 
22
- def status(options)
23
- send_request('getservice', @params) do |response|
24
- info = response[:return][:list][:item]
25
- puts "Name: #{info[:name]}"
26
- puts "IP Address: #{info[:ipaddress]}"
27
- puts "Port: #{info[:port]}"
28
- puts "State: #{info[:svrstate]}"
29
- end
30
- end
31
-
32
22
  def bind(options)
33
23
  params = {
34
24
  :name => options[:vserver],
35
25
  :servicename => host
36
26
  }
37
- send_request('bindlbvserver_service', params) do |response|
38
- #require 'pp'
39
- #pp response
40
- end
27
+ send_request('bindlbvserver_service', params)
41
28
  end
42
29
 
43
30
  def unbind(options)
@@ -45,10 +32,51 @@ module Netscaler::Service
45
32
  :name => options[:vserver],
46
33
  :servicename => host
47
34
  }
48
- send_request('unbindlbvserver_service', params) do |response|
49
- #require 'pp'
50
- #pp response
35
+ send_request('unbindlbvserver_service', params)
36
+ end
37
+
38
+ def status(options)
39
+ send_request('getservice', @params) do |response|
40
+ resp = Response.new(response)
41
+ if options[:json]
42
+ puts resp.to_json
43
+ else
44
+ puts resp.to_s
45
+ end
51
46
  end
52
47
  end
53
48
  end
49
+
50
+ class Response
51
+ attr_reader :raw_response, :info
52
+
53
+ def initialize(raw_response)
54
+ @raw_response = raw_response
55
+ @info = raw_response[:return][:list][:item]
56
+ end
57
+
58
+ def name
59
+ info[:name]
60
+ end
61
+
62
+ def ip_address
63
+ info[:ipaddress]
64
+ end
65
+
66
+ def state
67
+ info[:svrstate]
68
+ end
69
+
70
+ def port
71
+ info[:port]
72
+ end
73
+
74
+ def to_s
75
+ "Name:\t#{name}\nIP:\t#{ip_address}\nState:\t#{state}\nPort:\t#{port}"
76
+ end
77
+
78
+ def to_json
79
+ "{ 'name': '#{name}', 'ip_address': '#{ip_address}', 'state': '#{state}', 'port': #{port} }"
80
+ end
81
+ end
54
82
  end
@@ -2,7 +2,7 @@ require 'scanf'
2
2
 
3
3
  module Netscaler
4
4
  class Version
5
- CURRENT = File.read(File.dirname(__FILE__) + '/../VERSION')
5
+ CURRENT = File.read(File.join(File.dirname(__FILE__), '..', '..', 'etc', 'Version'))
6
6
  MAJOR, MINOR, TINY = CURRENT.scanf('%d.%d.%d')
7
7
 
8
8
  def self.to_s
@@ -21,13 +21,15 @@ module Netscaler::VServer
21
21
  def status(options)
22
22
  send_request('getlbvserver', @params) do |response|
23
23
  begin
24
- info = response[:return][:list][:item]
25
- puts "Name: #{info[:name]}"
26
- puts "IP Address: #{info[:svcipaddress][:item]}"
27
- puts "Port: #{info[:svcport][:item]}"
28
- puts "State: #{info[:svcstate][:item]}"
24
+ resp = Response.new(response)
25
+ if options[:json]
26
+ puts resp.to_json
27
+ else
28
+ puts resp.to_s
29
+ end
29
30
  rescue Exception => e
30
31
  log.fatal "Unable to lookup any information for host: #{host}"
32
+ puts e
31
33
  exit(1)
32
34
  end
33
35
  end
@@ -54,4 +56,104 @@ module Netscaler::VServer
54
56
  send_request('unbindlbvserver_policy', params)
55
57
  end
56
58
  end
59
+
60
+ class Response
61
+ attr_reader :raw_response, :info
62
+
63
+ def initialize(raw_response)
64
+ @raw_response = raw_response
65
+ @info = raw_response[:return][:list][:item]
66
+ end
67
+
68
+ def name
69
+ info[:name]
70
+ end
71
+
72
+ def ip_address
73
+ if info[:ipaddress] =~ /0\.0\.0\.0/
74
+ info[:ipaddress2]
75
+ else
76
+ info[:ipaddress]
77
+ end
78
+ end
79
+
80
+ def type
81
+ info[:servicetype]
82
+ end
83
+
84
+ def port
85
+ info[:port]
86
+ end
87
+
88
+ def state
89
+ info[:state]
90
+ end
91
+
92
+ def servers
93
+ @parsed_servers ||= []
94
+ if !@parsed_servers.empty?
95
+ return @parsed_servers
96
+ end
97
+
98
+ info[:servicename][:item].each do |name|
99
+ srv = ServerInfo.new
100
+ srv.name = name
101
+ @parsed_servers << srv
102
+ end
103
+
104
+ info[:svcstate][:item].each_with_index do |state, i|
105
+ @parsed_servers[i].state = state
106
+ end
107
+
108
+ info[:svcport][:item].each_with_index do |port, i|
109
+ @parsed_servers[i].port = port
110
+ end
111
+
112
+ info[:svcipaddress][:item].each_with_index do |ip_address, i|
113
+ @parsed_servers[i].ip_address = ip_address
114
+ end
115
+
116
+ info[:svctype][:item].each_with_index do |type, i|
117
+ @parsed_servers[i].type = type
118
+ end
119
+
120
+ @parsed_servers
121
+ end
122
+
123
+ def to_s
124
+ base = "Name:\t#{name}\nIP:\t#{ip_address}\nState:\t#{state}\nPort:\t#{port}\nType:\t#{type}\nServers:\n"
125
+ servers.each do |server|
126
+ base << server.to_s
127
+ base << "\n\n"
128
+ end
129
+ base
130
+ end
131
+
132
+ def to_json
133
+ base = "{ 'name': '#{name}', 'ip_address': '#{ip_address}', 'state': '#{state}', 'port': '#{port}', 'type': #{type}, 'servers': [\n "
134
+
135
+ servers.each_with_index do |server, i|
136
+ base << server.to_json
137
+ if i != servers.length - 1
138
+ base << ",\n "
139
+ else
140
+ base << "\n"
141
+ end
142
+ end
143
+
144
+ base << "] }"
145
+ end
146
+ end
147
+
148
+ class ServerInfo
149
+ attr_accessor :name, :ip_address, :state, :port, :type
150
+
151
+ def to_s
152
+ "\tName:\t#{name}\n\tIP:\t#{ip_address}\n\tState:\t#{state}\n\tPort:\t#{port}\n\tType:\t#{type}"
153
+ end
154
+
155
+ def to_json
156
+ "{ 'name': '#{name}', 'ip_address': '#{ip_address}', 'state': '#{state}', 'port': #{port}, 'type': '#{type}' }"
157
+ end
158
+ end
57
159
  end
data/spec/config_spec.rb CHANGED
@@ -16,7 +16,7 @@ module Netscaler
16
16
 
17
17
  describe "when reading an existing file" do
18
18
  it "should be able to load the basic config file" do
19
- reading('simple-config.yml').load_balancers.length.should eql(1)
19
+ reading('simple-config.yml').load_balancers.length.should eql(2)
20
20
  end
21
21
 
22
22
  it "should set the username and password correctly when set in the file." do
@@ -24,6 +24,12 @@ module Netscaler
24
24
  config.username.should eql('some_user')
25
25
  config.password.should eql('somepass')
26
26
  end
27
+
28
+ it "should load via an alias" do
29
+ config = reading('simple-config.yml')['else']
30
+ config.alias.should eql('else')
31
+ config.username.should eql('here')
32
+ end
27
33
  end
28
34
 
29
35
  describe "when reading a non-existent or bad file" do
@@ -1,3 +1,7 @@
1
1
  something.goes.here:
2
2
  username: some_user
3
- password: somepass
3
+ password: somepass
4
+ something.else:
5
+ username: here
6
+ alias: else
7
+ password: blah
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: netscaler-cli
3
3
  version: !ruby/object:Gem::Version
4
- hash: 17
4
+ hash: 19
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 2
9
8
  - 3
10
- version: 0.2.3
9
+ - 0
10
+ version: 0.3.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Gabe McArthur
@@ -15,45 +15,74 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-11-09 00:00:00 -08:00
18
+ date: 2010-12-03 00:00:00 -08:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
22
- name: highline
22
+ name: log4r
23
23
  prerelease: false
24
24
  requirement: &id001 !ruby/object:Gem::Requirement
25
25
  none: false
26
26
  requirements:
27
- - - ">="
27
+ - - ~>
28
28
  - !ruby/object:Gem::Version
29
- hash: 7
29
+ hash: 13
30
30
  segments:
31
31
  - 1
32
- - 5
33
- - 2
34
- version: 1.5.2
32
+ - 1
33
+ version: "1.1"
35
34
  type: :runtime
36
35
  version_requirements: *id001
37
36
  - !ruby/object:Gem::Dependency
38
- name: log4r
37
+ name: savon
39
38
  prerelease: false
40
39
  requirement: &id002 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ~>
43
+ - !ruby/object:Gem::Version
44
+ hash: 5
45
+ segments:
46
+ - 0
47
+ - 7
48
+ version: "0.7"
49
+ type: :runtime
50
+ version_requirements: *id002
51
+ - !ruby/object:Gem::Dependency
52
+ name: highline
53
+ prerelease: false
54
+ requirement: &id003 !ruby/object:Gem::Requirement
41
55
  none: false
42
56
  requirements:
43
57
  - - ">="
44
58
  - !ruby/object:Gem::Version
45
- hash: 29
59
+ hash: 3
46
60
  segments:
47
61
  - 1
62
+ - 6
63
+ version: "1.6"
64
+ type: :runtime
65
+ version_requirements: *id003
66
+ - !ruby/object:Gem::Dependency
67
+ name: log4r
68
+ prerelease: false
69
+ requirement: &id004 !ruby/object:Gem::Requirement
70
+ none: false
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ hash: 1
75
+ segments:
48
76
  - 1
49
- - 7
50
- version: 1.1.7
77
+ - 1
78
+ - 9
79
+ version: 1.1.9
51
80
  type: :runtime
52
- version_requirements: *id002
81
+ version_requirements: *id004
53
82
  - !ruby/object:Gem::Dependency
54
83
  name: savon
55
84
  prerelease: false
56
- requirement: &id003 !ruby/object:Gem::Requirement
85
+ requirement: &id005 !ruby/object:Gem::Requirement
57
86
  none: false
58
87
  requirements:
59
88
  - - ">="
@@ -65,23 +94,38 @@ dependencies:
65
94
  - 9
66
95
  version: 0.7.9
67
96
  type: :runtime
68
- version_requirements: *id003
97
+ version_requirements: *id005
98
+ - !ruby/object:Gem::Dependency
99
+ name: highline
100
+ prerelease: false
101
+ requirement: &id006 !ruby/object:Gem::Requirement
102
+ none: false
103
+ requirements:
104
+ - - ">="
105
+ - !ruby/object:Gem::Version
106
+ hash: 3
107
+ segments:
108
+ - 1
109
+ - 6
110
+ version: "1.6"
111
+ type: :runtime
112
+ version_requirements: *id006
69
113
  - !ruby/object:Gem::Dependency
70
114
  name: rspec
71
115
  prerelease: false
72
- requirement: &id004 !ruby/object:Gem::Requirement
116
+ requirement: &id007 !ruby/object:Gem::Requirement
73
117
  none: false
74
118
  requirements:
75
119
  - - ">="
76
120
  - !ruby/object:Gem::Version
77
- hash: 13
121
+ hash: 7
78
122
  segments:
79
123
  - 2
124
+ - 2
80
125
  - 0
81
- - 1
82
- version: 2.0.1
126
+ version: 2.2.0
83
127
  type: :development
84
- version_requirements: *id004
128
+ version_requirements: *id007
85
129
  description: This gem installs several simple command line utilities locally. It uses the NSConfig.wsdl SOAP interface for remote access.
86
130
  email:
87
131
  - madeonamac@gmail.com
@@ -94,12 +138,13 @@ extensions: []
94
138
  extra_rdoc_files:
95
139
  - README.markdown
96
140
  files:
141
+ - Gemfile
142
+ - Gemfile.lock
97
143
  - README.markdown
98
144
  - Rakefile
99
145
  - bin/netscaler-server
100
146
  - bin/netscaler-service
101
147
  - bin/netscaler-vserver
102
- - lib/VERSION
103
148
  - lib/netscaler/baseexecutor.rb
104
149
  - lib/netscaler/clitemplate.rb
105
150
  - lib/netscaler/config.rb
@@ -126,8 +171,8 @@ homepage: http://github.com/gabemc/netscaler-cli
126
171
  licenses: []
127
172
 
128
173
  post_install_message:
129
- rdoc_options:
130
- - --charset=UTF-8
174
+ rdoc_options: []
175
+
131
176
  require_paths:
132
177
  - lib
133
178
  required_ruby_version: !ruby/object:Gem::Requirement
@@ -156,8 +201,8 @@ signing_key:
156
201
  specification_version: 3
157
202
  summary: Simple command line utilities for interacting remotely with a Netscaler load balancer.
158
203
  test_files:
159
- - spec/vserver/cli_spec.rb
204
+ - spec/config_spec.rb
160
205
  - spec/helpers.rb
161
206
  - spec/server/cli_spec.rb
162
207
  - spec/service/cli_spec.rb
163
- - spec/config_spec.rb
208
+ - spec/vserver/cli_spec.rb
data/lib/VERSION DELETED
@@ -1 +0,0 @@
1
- 0.2.3