stingray-exec 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +19 -0
- data/.rspec +2 -0
- data/.simplecov +7 -0
- data/AUTHORS.md +2 -0
- data/CONTRIBUTING.md +8 -0
- data/Gemfile +12 -0
- data/LICENSE.txt +22 -0
- data/README.md +66 -0
- data/Rakefile +22 -0
- data/bin/stingray-exec +3 -0
- data/examples/add-pool +10 -0
- data/examples/bork +6 -0
- data/examples/credentials.conf +4 -0
- data/examples/delete-pool +10 -0
- data/examples/list-pools +8 -0
- data/examples/list-virtual-servers +8 -0
- data/generate-actions.rb +119 -0
- data/lib/stingray-exec.rb +5 -0
- data/lib/stingray/control_api.rb +112 -0
- data/lib/stingray/control_api/actions.rb +49 -0
- data/lib/stingray/control_api/catalog_rule_methods.rb +31 -0
- data/lib/stingray/control_api/endpoint.rb +23 -0
- data/lib/stingray/control_api/generated-actions-9.0.yml +9036 -0
- data/lib/stingray/control_api/generated-actions-9.1.yml +9172 -0
- data/lib/stingray/control_api/pool_methods.rb +156 -0
- data/lib/stingray/control_api/soap_helper_methods.rb +69 -0
- data/lib/stingray/exec.rb +16 -0
- data/lib/stingray/exec/cli.rb +134 -0
- data/lib/stingray/exec/dsl.rb +48 -0
- data/lib/stingray/exec/version.rb +5 -0
- data/lib/stingray/junk.rb +16 -0
- data/spec/integration/catalog_rule_spec.rb +116 -0
- data/spec/integration/pool_spec.rb +61 -0
- data/spec/integration/users_spec.rb +21 -0
- data/spec/lib/stingray/control_api_spec.rb +51 -0
- data/spec/lib/stingray/exec/cli_spec.rb +7 -0
- data/spec/lib/stingray/exec/version_spec.rb +5 -0
- data/spec/spec_helper.rb +26 -0
- data/stingray-exec.gemspec +29 -0
- metadata +131 -0
@@ -0,0 +1,156 @@
|
|
1
|
+
require 'stingray/control_api'
|
2
|
+
require 'stingray/control_api/soap_helper_methods'
|
3
|
+
|
4
|
+
module Stingray::ControlApi::PoolMethods
|
5
|
+
include Stingray::ControlApi::SoapHelperMethods
|
6
|
+
|
7
|
+
%w(
|
8
|
+
add_pool
|
9
|
+
get_nodes_priority_value
|
10
|
+
get_nodes_weightings
|
11
|
+
).map(&:to_sym).each do |op|
|
12
|
+
define_method(:"_custom_#{op}") do |node_configs|
|
13
|
+
body = _build_many_keyed_string_arrays(node_configs, :names, :nodes)
|
14
|
+
_make_soap_request('Pool', op, body)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
%w(
|
19
|
+
delete_pool
|
20
|
+
get_autoscale_cloudcredentials
|
21
|
+
get_autoscale_cluster
|
22
|
+
get_autoscale_datacenter
|
23
|
+
get_autoscale_datastore
|
24
|
+
get_autoscale_enabled
|
25
|
+
get_autoscale_external
|
26
|
+
get_autoscale_hysteresis
|
27
|
+
get_autoscale_imageid
|
28
|
+
get_autoscale_ipstouse
|
29
|
+
get_autoscale_lastnode_idletime
|
30
|
+
get_autoscale_max_nodes
|
31
|
+
get_autoscale_min_nodes
|
32
|
+
get_autoscale_names
|
33
|
+
get_autoscale_port
|
34
|
+
get_autoscale_refractory
|
35
|
+
get_autoscale_response_time
|
36
|
+
get_autoscale_scaledown_level
|
37
|
+
get_autoscale_scaleup_level
|
38
|
+
get_autoscale_sizeid
|
39
|
+
get_bandwidth_class
|
40
|
+
get_disabled_nodes
|
41
|
+
get_draining_nodes
|
42
|
+
get_ftp_support_rfc2428
|
43
|
+
get_failpool
|
44
|
+
get_keepalive
|
45
|
+
get_keepalive_non_idempotent
|
46
|
+
get_load_balancing_algorithm
|
47
|
+
get_max_connect_time
|
48
|
+
get_max_connections_pernode
|
49
|
+
get_max_idle_connections_per_node
|
50
|
+
get_max_keepalives_per_node
|
51
|
+
get_max_queue_size
|
52
|
+
get_max_reply_time
|
53
|
+
get_monitors
|
54
|
+
get_node_conn_close
|
55
|
+
get_node_connection_attempts
|
56
|
+
get_node_fail_time
|
57
|
+
get_node_use_nagle
|
58
|
+
get_nodes
|
59
|
+
get_nodes_connection_counts
|
60
|
+
get_nodes_last_used
|
61
|
+
get_note
|
62
|
+
get_passive_monitoring
|
63
|
+
get_persistence
|
64
|
+
get_priority_enabled
|
65
|
+
get_priority_nodes
|
66
|
+
get_priority_values
|
67
|
+
get_queue_timeout
|
68
|
+
get_smtp_send_start_tls
|
69
|
+
get_ssl_client_auth
|
70
|
+
get_ssl_encrypt
|
71
|
+
get_ssl_enhance
|
72
|
+
get_ssl_send_close_alerts
|
73
|
+
get_ssl_server_name_extension
|
74
|
+
get_ssl_strict_verify
|
75
|
+
get_transparent
|
76
|
+
get_udp_accept_from
|
77
|
+
get_udp_accept_from_ip_mask
|
78
|
+
get_weightings
|
79
|
+
).map(&:to_sym).each do |op|
|
80
|
+
define_method(:"_custom_#{op}") do |*names|
|
81
|
+
_make_names_soap_request(names, 'Pool', op)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
%w(
|
86
|
+
add_draining_nodes
|
87
|
+
add_monitors
|
88
|
+
add_nodes
|
89
|
+
disable_nodes
|
90
|
+
enable_nodes
|
91
|
+
remove_draining_nodes
|
92
|
+
remove_monitors
|
93
|
+
remove_nodes
|
94
|
+
set_autoscale_cloudcredentials
|
95
|
+
set_autoscale_cluster
|
96
|
+
set_autoscale_datacenter
|
97
|
+
set_autoscale_datastore
|
98
|
+
set_autoscale_enabled
|
99
|
+
set_autoscale_external
|
100
|
+
set_autoscale_hysteresis
|
101
|
+
set_autoscale_imageid
|
102
|
+
set_autoscale_ipstouse
|
103
|
+
set_autoscale_lastnode_idletime
|
104
|
+
set_autoscale_max_nodes
|
105
|
+
set_autoscale_min_nodes
|
106
|
+
set_autoscale_name
|
107
|
+
set_autoscale_port
|
108
|
+
set_autoscale_refractory
|
109
|
+
set_autoscale_response_time
|
110
|
+
set_autoscale_scaledown_level
|
111
|
+
set_autoscale_scaleup_level
|
112
|
+
set_autoscale_sizeid
|
113
|
+
set_bandwidth_class
|
114
|
+
set_disabled_nodes
|
115
|
+
set_draining_nodes
|
116
|
+
set_ftp_support_rfc2428
|
117
|
+
set_failpool
|
118
|
+
set_keepalive
|
119
|
+
set_keepalive_non_idempotent
|
120
|
+
set_load_balancing_algorithm
|
121
|
+
set_max_connect_time
|
122
|
+
set_max_connections_pernode
|
123
|
+
set_max_idle_connections_pernode
|
124
|
+
set_max_keepalives_pernode
|
125
|
+
set_max_queue_size
|
126
|
+
set_max_reply_time
|
127
|
+
set_monitors
|
128
|
+
set_node_conn_close
|
129
|
+
set_node_connection_attempts
|
130
|
+
set_node_fail_time
|
131
|
+
set_node_use_nagle
|
132
|
+
set_nodes
|
133
|
+
set_nodes_priority_value
|
134
|
+
set_nodes_weightings
|
135
|
+
set_note
|
136
|
+
set_passive_monitoring
|
137
|
+
set_persistence
|
138
|
+
set_priority_enabled
|
139
|
+
set_priority_nodes
|
140
|
+
set_queue_timeout
|
141
|
+
set_smtp_send_start_tls
|
142
|
+
set_ssl_client_auth
|
143
|
+
set_ssl_encrypt
|
144
|
+
set_ssl_enhance
|
145
|
+
set_ssl_send_close_alerts
|
146
|
+
set_ssl_server_name_extension
|
147
|
+
set_ssl_strict_verify
|
148
|
+
set_transparent
|
149
|
+
set_udp_accept_from
|
150
|
+
set_udp_accept_from_ip_mask
|
151
|
+
).map(&:to_sym).each do |op|
|
152
|
+
define_method(:"_custom_#{op}") do |names_values|
|
153
|
+
_make_names_values_soap_request(names_values, 'Pool', op)
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'stingray/control_api'
|
2
|
+
|
3
|
+
module Stingray::ControlApi::SoapHelperMethods
|
4
|
+
def _make_soap_request(ns, method, soap_body)
|
5
|
+
self.client.request(ns, method) do
|
6
|
+
soap.namespaces['xmlns:soapenc'] = 'http://schemas.xmlsoap.org/soap/encoding/'
|
7
|
+
soap.body = soap_body
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def _make_names_values_soap_request(names_values_hash, ns, operation)
|
12
|
+
raise ArgumentError.new('No names -> values given!') if names_values_hash.empty?
|
13
|
+
body = _build_many_keyed_string_arrays(names_values_hash, :names, :values)
|
14
|
+
_make_soap_request(ns, operation, body)
|
15
|
+
end
|
16
|
+
|
17
|
+
def _make_names_soap_request(names_array, ns, operation)
|
18
|
+
raise ArgumentError.new('No names given!') if names_array.empty?
|
19
|
+
body = _build_string_array(names_array, :names)
|
20
|
+
_make_soap_request(ns, operation, body)
|
21
|
+
end
|
22
|
+
|
23
|
+
def _build_string_array(strings, key_name)
|
24
|
+
body = {
|
25
|
+
key_name => {},
|
26
|
+
:attributes! => {
|
27
|
+
key_name => {'soapenc:arrayType' => "xsd:string[#{strings.length}]"}
|
28
|
+
}
|
29
|
+
}
|
30
|
+
|
31
|
+
strings.each_with_index do |s,i|
|
32
|
+
body[key_name][:"s#{i}"] = s
|
33
|
+
end
|
34
|
+
|
35
|
+
body
|
36
|
+
end
|
37
|
+
|
38
|
+
def _build_many_keyed_string_arrays(key_array_hash, keys_name, arrays_name)
|
39
|
+
body = {
|
40
|
+
keys_name => {},
|
41
|
+
arrays_name => {
|
42
|
+
:attributes! => {},
|
43
|
+
},
|
44
|
+
:attributes! => {
|
45
|
+
keys_name => {'soapenc:arrayType' => "xsd:string[#{key_array_hash.length}]"},
|
46
|
+
arrays_name => {'soapenc:arrayType' => "xsd:list[#{key_array_hash.length}]"},
|
47
|
+
},
|
48
|
+
}
|
49
|
+
|
50
|
+
i = 0
|
51
|
+
key_array_hash.each do |k,arr|
|
52
|
+
body[keys_name][:"k#{i}"] = k
|
53
|
+
|
54
|
+
k_arr = {:attributes! => {}}
|
55
|
+
arr.each_with_index do |node,j|
|
56
|
+
k_arr[:"node#{j}"] = node
|
57
|
+
end
|
58
|
+
|
59
|
+
body[arrays_name][:attributes!][:"k#{i}"] = {
|
60
|
+
'soapenc:arrayType' => "xsd:string[#{arr.length}]"
|
61
|
+
}
|
62
|
+
|
63
|
+
body[arrays_name][:"k#{i}"] = k_arr
|
64
|
+
i += 1
|
65
|
+
end
|
66
|
+
|
67
|
+
body
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
require 'stingray/exec'
|
3
|
+
|
4
|
+
class Stingray::Exec::Cli
|
5
|
+
BANNER = <<-EOB.gsub(/^ /, '')
|
6
|
+
Usage: stingray-exec [options] <script>
|
7
|
+
|
8
|
+
Executes scripts in the context of Stingray Traffic Manager configuration
|
9
|
+
models, allowing for access to all methods documented in the Control API. The
|
10
|
+
<script> argument may be a string expression or a filename (or "-" for stdin),
|
11
|
+
and if ommitted will cause stingray-exec to drop into a fancy DSL-tastic pry
|
12
|
+
console.
|
13
|
+
|
14
|
+
All of the command-line configuration flags may also be given as
|
15
|
+
environmental variables, as noted in the help text for each flag. The
|
16
|
+
"endpoint" flag/var deserves special attention as the expected value is buried
|
17
|
+
in the Stingray docs.
|
18
|
+
e.g.: STINGRAY_ENDPOINT='https://stingray-pool-master.example.com:9090/soap'
|
19
|
+
|
20
|
+
See the 'examples' directory in the stingray-exec gem tree for some
|
21
|
+
(surprise!) examples of how to do stuff.
|
22
|
+
|
23
|
+
------- FAIR WARNING: -------
|
24
|
+
The vast majority of Control API methods have been wrapped in very dumb
|
25
|
+
generated code. Read-only methods work fine, but methods that take arguments
|
26
|
+
invariably require custom implementations -- the kind of thing that's typically
|
27
|
+
generated from a WSDL, which we can't legally redistribute. The Control API
|
28
|
+
makes things even more fun by requiring the use of soapenc arrays and lists of
|
29
|
+
arrays. If you want or need to implement such code, the "soap_helper_methods.rb"
|
30
|
+
file in the stingray-exec source may be of help. YMMV.
|
31
|
+
|
32
|
+
|
33
|
+
EOB
|
34
|
+
|
35
|
+
def self.main(argv = ARGV)
|
36
|
+
new(argv).run!
|
37
|
+
end
|
38
|
+
|
39
|
+
attr_reader :argv, :script, :filename
|
40
|
+
|
41
|
+
def initialize(argv)
|
42
|
+
@argv = argv
|
43
|
+
end
|
44
|
+
|
45
|
+
def run!
|
46
|
+
parse_options
|
47
|
+
prepare_script
|
48
|
+
configure
|
49
|
+
evaluate_script
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
def parse_options
|
54
|
+
OptionParser.new do |opts|
|
55
|
+
opts.banner = BANNER
|
56
|
+
opts.on('-v', '--verbose', 'Yelling. (DEBUG=1)') do
|
57
|
+
ENV['DEBUG'] = '1'
|
58
|
+
end
|
59
|
+
opts.on('-k', '--insecure', 'Allow "insecure" SSL connections ' <<
|
60
|
+
'(STINGRAY_SSL_VERIFY_NONE=1)') do
|
61
|
+
ENV['STINGRAY_SSL_VERIFY_NONE'] = '1'
|
62
|
+
end
|
63
|
+
opts.on('-u=', '--user-password=',
|
64
|
+
'Stingray username:password (STINGRAY_AUTH=<user>:<pass>)') do |u|
|
65
|
+
ENV['STINGRAY_AUTH'] = u
|
66
|
+
end
|
67
|
+
opts.on('-C=', '--credentials=', 'Credentials file containing ' <<
|
68
|
+
'username:password (STINGRAY_AUTH=<user>:<pass>)') do |c|
|
69
|
+
ENV['STINGRAY_AUTH'] = read_credentials_file(c)
|
70
|
+
end
|
71
|
+
opts.on('-E=', '--endpoint=',
|
72
|
+
'Stingray server SOAP endpoint (STINGRAY_ENDPOINT=<uri>)') do |endpoint|
|
73
|
+
ENV['STINGRAY_ENDPOINT'] = endpoint
|
74
|
+
end
|
75
|
+
opts.on('-V=', '--stingray-version=', 'Stingray server version, ' <<
|
76
|
+
'e.g. "9.0" or "9.1" (STINGRAY_VERSION="9.1")') do |ver|
|
77
|
+
ENV['STINGRAY_VERSION'] = ver
|
78
|
+
end
|
79
|
+
end.parse!(argv)
|
80
|
+
end
|
81
|
+
|
82
|
+
def read_credentials_file(filename)
|
83
|
+
File.read(filename).split($/).reject do |l|
|
84
|
+
l.strip =~ /^#/ || l.strip.empty?
|
85
|
+
end.first
|
86
|
+
end
|
87
|
+
|
88
|
+
def prepare_script
|
89
|
+
@script = argv.first || ''
|
90
|
+
@filename = ''
|
91
|
+
if File.exists?(@script)
|
92
|
+
@filename = @script
|
93
|
+
@script = File.read(@script)
|
94
|
+
elsif @script == '-'
|
95
|
+
@script = $stdin.read
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def configure
|
100
|
+
Stingray::Exec.configure
|
101
|
+
end
|
102
|
+
|
103
|
+
def evaluate_script
|
104
|
+
require_relative 'dsl'
|
105
|
+
|
106
|
+
# reassign so that scoping is happy once we're inside the new class block
|
107
|
+
script_string = script
|
108
|
+
script_filename = filename
|
109
|
+
shebang_offset = script_string =~ /^#!/ ? 1 : 0
|
110
|
+
|
111
|
+
unless script_string.empty?
|
112
|
+
Class.new(Object) do
|
113
|
+
extend Stingray::Exec::DSL
|
114
|
+
begin
|
115
|
+
stingray_exec(script_string, script_filename, shebang_offset)
|
116
|
+
rescue => e
|
117
|
+
$stderr.puts e.message
|
118
|
+
$stderr.puts e.backtrace.join("\n") if ENV['DEBUG']
|
119
|
+
end
|
120
|
+
end
|
121
|
+
else
|
122
|
+
require 'pry'
|
123
|
+
Pry.config.prompt_name = 'stingray-exec'
|
124
|
+
TOPLEVEL_BINDING.eval('self').extend Stingray::Exec::DSL
|
125
|
+
Pry.start
|
126
|
+
end
|
127
|
+
|
128
|
+
return 0
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
if $0 == __FILE__
|
133
|
+
exit Stingray::Exec::Cli.main
|
134
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'stingray/exec'
|
2
|
+
require 'stingray/control_api'
|
3
|
+
|
4
|
+
module Stingray::Exec::DSL
|
5
|
+
def stingray_exec(string = '', filename = '', lineno = 0, &block)
|
6
|
+
unless string.empty?
|
7
|
+
instance_eval(string, filename, lineno)
|
8
|
+
else
|
9
|
+
instance_eval(&block)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
Stingray::ControlApi::CONFIGURATIONS.each do |cfg_ns,variations|
|
14
|
+
define_method(variations[:snaked]) do
|
15
|
+
ivar = :"@#{variations[:snaked].to_s}"
|
16
|
+
|
17
|
+
if inst = instance_variable_get(ivar)
|
18
|
+
return inst
|
19
|
+
end
|
20
|
+
|
21
|
+
inst = Stingray::ControlApi::const_get(variations[:consted]).new
|
22
|
+
inst.client.http.auth.ssl.verify_mode = ssl_verify_mode
|
23
|
+
instance_variable_set(ivar, inst)
|
24
|
+
inst
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Set the SSL verification mode for all SOAP communication. Valid values are
|
29
|
+
# really up to the HTTP backend, but some known good ones are ":none" and
|
30
|
+
# ":peer". Setting the STINGRAY_SSL_VERIFY_NONE environmental variable will
|
31
|
+
# result in this method defaulting to ":none". Once a configuration model
|
32
|
+
# has been initialized, its verify mode cannot be modified through this
|
33
|
+
# function. Instead, set the model's deeply-nested attribute of
|
34
|
+
# `.client.http.auth.ssl.verify_mode`.
|
35
|
+
def ssl_verify_mode(mode = nil)
|
36
|
+
unless mode.nil?
|
37
|
+
@ssl_verify_mode = mode
|
38
|
+
end
|
39
|
+
@ssl_verify_mode || ENV['STINGRAY_SSL_VERIFY_NONE'] ? :none : :peer
|
40
|
+
end
|
41
|
+
|
42
|
+
# A little helper that allows for iteration over SOAP results that may be
|
43
|
+
# singular or plural (or just plain missing.) A block must always be given.
|
44
|
+
def foreach(anything, &block)
|
45
|
+
raise SyntaxError.new('Block needed!') unless block_given?
|
46
|
+
[*(anything || [])].each(&block)
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Stingray
|
2
|
+
class Junk
|
3
|
+
def self.snakify(str)
|
4
|
+
str.gsub(/::/, '/').
|
5
|
+
gsub(/\./, '_').
|
6
|
+
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
7
|
+
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
8
|
+
tr("-", "_").
|
9
|
+
downcase
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.constify(str)
|
13
|
+
str.gsub(/\./, '').gsub(/_/, '')
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|