stingray-exec 0.1.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/.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
|