rest_connection 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/Rakefile +1 -0
- data/VERSION +1 -1
- data/config/rest_api_config.yaml.sample +4 -1
- data/examples/console.rb +1 -3
- data/examples/restart_instance_agent.rb +10 -9
- data/lib/rest_connection.rb +2 -5
- data/lib/rest_connection/rightscale/audit_entry.rb +44 -0
- data/lib/rest_connection/rightscale/deployment.rb +4 -1
- data/lib/rest_connection/rightscale/ec2_security_group.rb +3 -1
- data/lib/rest_connection/rightscale/ec2_server_array.rb +3 -1
- data/lib/rest_connection/rightscale/ec2_ssh_key.rb +3 -1
- data/lib/rest_connection/rightscale/executable.rb +3 -1
- data/lib/rest_connection/rightscale/instance.rb +3 -1
- data/lib/rest_connection/rightscale/multi_cloud_image.rb +3 -1
- data/lib/rest_connection/rightscale/right_script.rb +3 -1
- data/lib/rest_connection/rightscale/rightscale_api_base.rb +45 -41
- data/lib/rest_connection/rightscale/rightscale_api_resources.rb +2 -0
- data/lib/rest_connection/rightscale/rs_internal.rb +42 -0
- data/lib/rest_connection/rightscale/server.rb +32 -2
- data/lib/rest_connection/rightscale/server_template.rb +8 -1
- data/lib/rest_connection/rightscale/status.rb +7 -1
- data/lib/rest_connection/rightscale/tag.rb +3 -1
- data/lib/rest_connection/ssh_hax.rb +39 -11
- data/rest_connection.gemspec +20 -11
- data/spec/rs_internal_spec.rb +26 -0
- data/spec/server_spec.rb +34 -0
- metadata +27 -9
- data/examples/set_deployment_images.rb +0 -0
data/.gitignore
ADDED
data/Rakefile
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.4
|
@@ -1,7 +1,10 @@
|
|
1
1
|
---
|
2
|
+
:ssh_keys:
|
3
|
+
- ~/.ssh/my_server_key
|
4
|
+
- ~/.ssh/my_server_key-eu
|
5
|
+
- ~/.ssh/my_server_key-west
|
2
6
|
:pass: myUltraSecurePasswordz
|
3
7
|
:user: myUserEmail@MyMailDomain.com
|
4
8
|
:api_url: https://my.rightscale.com/api/acct/00000000
|
5
|
-
:ssh_key: ~/.ssh/my-server-key
|
6
9
|
:common_headers:
|
7
10
|
X_API_VERSION: "1.0"
|
data/examples/console.rb
CHANGED
@@ -7,6 +7,7 @@ require 'net/ssh'
|
|
7
7
|
opts = Trollop::options do
|
8
8
|
opt :deployment, "deployment nickname", :type => :string, :required => true
|
9
9
|
opt :only, "regex string matching the nickname of the servers you want to relaunch. This excludes servers that do not match\nExample --only ubuntu", :type => :string, :required => false
|
10
|
+
opt :hard, "hard reset, uninstalls right_resources premium gem (for code update), and restarts the instance agent", :type => :bool, :required => false
|
10
11
|
end
|
11
12
|
|
12
13
|
# find all servers in the deployment (the fast way)
|
@@ -16,13 +17,13 @@ servers = servers.select { |s| s.nickname =~ /#{opts[:only]}/ } if opts[:only]
|
|
16
17
|
|
17
18
|
servers.each do |s|
|
18
19
|
s.wait_for_operational_with_dns
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
20
|
+
if opts[:hard]
|
21
|
+
s.spot_check("gem uninstall right_resources_premium") do |result|
|
22
|
+
puts result
|
23
|
+
end
|
24
|
+
s.spot_check("monit restart instance") do |result|
|
25
|
+
puts result
|
26
|
+
end
|
27
|
+
end
|
28
|
+
s.run_recipe("database_test::dev_pristine_restore")
|
28
29
|
end
|
data/lib/rest_connection.rb
CHANGED
@@ -169,13 +169,10 @@ module RestConnection
|
|
169
169
|
def logger(message)
|
170
170
|
init_message = "Initializing Logging using "
|
171
171
|
if @@logger.nil?
|
172
|
-
if
|
173
|
-
@@logger = Logger.new(@settings[:log_file])
|
174
|
-
init_message += @settings[:log_file]
|
175
|
-
elsif ENV['REST_CONNECTION_LOG']
|
172
|
+
if ENV['REST_CONNECTION_LOG']
|
176
173
|
@@logger = Logger.new(ENV['REST_CONNECTION_LOG'])
|
177
174
|
init_message += ENV['REST_CONNECTION_LOG']
|
178
|
-
else
|
175
|
+
else
|
179
176
|
@@logger = Logger.new(STDOUT)
|
180
177
|
init_message += "STDOUT"
|
181
178
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# This file is part of RestConnection
|
2
|
+
#
|
3
|
+
# RestConnection is free software: you can redistribute it and/or modify
|
4
|
+
# it under the terms of the GNU General Public License as published by
|
5
|
+
# the Free Software Foundation, either version 3 of the License, or
|
6
|
+
# (at your option) any later version.
|
7
|
+
#
|
8
|
+
# RestConnection is distributed in the hope that it will be useful,
|
9
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
10
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
11
|
+
# GNU General Public License for more details.
|
12
|
+
#
|
13
|
+
# You should have received a copy of the GNU General Public License
|
14
|
+
# along with RestConnection. If not, see <http://www.gnu.org/licenses/>.
|
15
|
+
#
|
16
|
+
#class AuditEntry
|
17
|
+
# attr_accessor :status, :output
|
18
|
+
# def initialize(opts)
|
19
|
+
# @status = opts[:status]
|
20
|
+
# @output = opts[:output]
|
21
|
+
# end
|
22
|
+
# def wait_for_completed(audit_link = "no audit link available")
|
23
|
+
# raise "FATAL: script failed. see audit #{audit_link}" unless @status
|
24
|
+
# end
|
25
|
+
#end
|
26
|
+
|
27
|
+
class AuditEntry
|
28
|
+
include RightScale::Api::Base
|
29
|
+
extend RightScale::Api::BaseExtend
|
30
|
+
|
31
|
+
def wait_for_state(state)
|
32
|
+
while(1)
|
33
|
+
reload
|
34
|
+
connection.logger("state is #{self.state}, waiting for #{state}")
|
35
|
+
raise "FATAL error, script failed\nSee Audit: #{self.href}" if self.state == 'failed'
|
36
|
+
sleep 5
|
37
|
+
return true if state == self.state
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def wait_for_completed(legacy=nil)
|
42
|
+
wait_for_state("completed")
|
43
|
+
end
|
44
|
+
end
|
@@ -13,7 +13,10 @@
|
|
13
13
|
# You should have received a copy of the GNU General Public License
|
14
14
|
# along with RestConnection. If not, see <http://www.gnu.org/licenses/>.
|
15
15
|
|
16
|
-
class Deployment
|
16
|
+
class Deployment
|
17
|
+
include RightScale::Api::Base
|
18
|
+
extend RightScale::Api::BaseExtend
|
19
|
+
|
17
20
|
def set_input(name, value)
|
18
21
|
deploy_href = URI.parse(self.href)
|
19
22
|
connection.put(deploy_href.path, :deployment => {:parameters => {name => value} })
|
@@ -13,5 +13,7 @@
|
|
13
13
|
# You should have received a copy of the GNU General Public License
|
14
14
|
# along with RestConnection. If not, see <http://www.gnu.org/licenses/>.
|
15
15
|
|
16
|
-
class Ec2SecurityGroup
|
16
|
+
class Ec2SecurityGroup
|
17
|
+
include RightScale::Api::Base
|
18
|
+
extend RightScale::Api::BaseExtend
|
17
19
|
end
|
@@ -19,7 +19,9 @@
|
|
19
19
|
# st.executables.find(:nickname
|
20
20
|
# a.run_script_on_all(
|
21
21
|
|
22
|
-
class Ec2ServerArray
|
22
|
+
class Ec2ServerArray
|
23
|
+
include RightScale::Api::Base
|
24
|
+
extend RightScale::Api::BaseExtend
|
23
25
|
def run_script_on_all(script, server_template_hrefs, inputs=nil)
|
24
26
|
serv_href = URI.parse(self.href)
|
25
27
|
options = Hash.new
|
@@ -13,5 +13,7 @@
|
|
13
13
|
# You should have received a copy of the GNU General Public License
|
14
14
|
# along with RestConnection. If not, see <http://www.gnu.org/licenses/>.
|
15
15
|
|
16
|
-
class Ec2SshKey
|
16
|
+
class Ec2SshKey
|
17
|
+
include RightScale::Api::Base
|
18
|
+
extend RightScale::Api::BaseExtend
|
17
19
|
end
|
@@ -16,7 +16,9 @@
|
|
16
16
|
# This is an instance facing api and can only be used with
|
17
17
|
# an authentication URL normally found in the instance's userdata called
|
18
18
|
# RS_API_URL
|
19
|
-
class Instance
|
19
|
+
class Instance
|
20
|
+
include RightScale::Api::Base
|
21
|
+
extend RightScale::Api::BaseExtend
|
20
22
|
#def create_ebs_volume_from_snap(snap_aws_id)
|
21
23
|
# connection.post('create_ebs_volume.js', :aws_id => snap_aws_id )
|
22
24
|
#end
|
@@ -13,5 +13,7 @@
|
|
13
13
|
# You should have received a copy of the GNU General Public License
|
14
14
|
# along with RestConnection. If not, see <http://www.gnu.org/licenses/>.
|
15
15
|
|
16
|
-
class MultiCloudImage
|
16
|
+
class MultiCloudImage
|
17
|
+
include RightScale::Api::Base
|
18
|
+
extend RightScale::Api::BaseExtend
|
17
19
|
end
|
@@ -14,7 +14,9 @@
|
|
14
14
|
# along with RestConnection. If not, see <http://www.gnu.org/licenses/>.
|
15
15
|
|
16
16
|
|
17
|
-
class RightScript
|
17
|
+
class RightScript
|
18
|
+
include RightScale::Api::Base
|
19
|
+
extend RightScale::Api::BaseExtend
|
18
20
|
def self.from_yaml(yaml)
|
19
21
|
scripts = []
|
20
22
|
x = YAML.load(yaml)
|
@@ -17,51 +17,27 @@ require 'active_support'
|
|
17
17
|
|
18
18
|
module RightScale
|
19
19
|
module Api
|
20
|
-
|
21
|
-
# The params hash of attributes for direct manipulation
|
22
|
-
attr_accessor :params
|
23
|
-
|
24
|
-
def self.connection()
|
25
|
-
@@connection ||= RestConnection::Connection.new
|
26
|
-
end
|
20
|
+
module BaseExtend
|
27
21
|
def connection()
|
28
22
|
@@connection ||= RestConnection::Connection.new
|
29
23
|
end
|
30
24
|
|
31
|
-
def
|
32
|
-
@params = params
|
33
|
-
end
|
34
|
-
|
35
|
-
def self.resource_plural_name
|
25
|
+
def resource_plural_name
|
36
26
|
self.to_s.underscore.pluralize
|
37
27
|
end
|
38
28
|
|
39
|
-
def
|
29
|
+
def resource_singluar_name
|
40
30
|
self.to_s.underscore
|
41
31
|
end
|
42
|
-
|
43
|
-
def resource_plural_name
|
44
|
-
self.class.to_s.underscore.pluralize
|
45
|
-
end
|
46
|
-
|
47
|
-
def resource_singular_name
|
48
|
-
self.class.to_s.underscore
|
49
|
-
end
|
50
|
-
|
51
|
-
def save
|
52
|
-
uri = URI.parse(self.href)
|
53
|
-
connection.put(uri.path, resource_singular_name.to_sym => @params)
|
54
|
-
end
|
55
|
-
|
56
32
|
# matches using result of block match expression
|
57
33
|
# ex: Server.find_by(:nickname) { |n| n =~ /production/ }
|
58
|
-
def
|
34
|
+
def find_by(attrib, &block)
|
59
35
|
self.find_all.select do |s|
|
60
36
|
yield(s[attrib.to_s])
|
61
37
|
end
|
62
38
|
end
|
63
39
|
|
64
|
-
def
|
40
|
+
def find_all
|
65
41
|
a = Array.new
|
66
42
|
connection.get(self.resource_plural_name).each do |object|
|
67
43
|
a << self.new(object)
|
@@ -69,21 +45,16 @@ module RightScale
|
|
69
45
|
return a
|
70
46
|
end
|
71
47
|
|
72
|
-
def
|
48
|
+
def find_by_nickname(nickname)
|
73
49
|
connection.logger("DEPRICATION WARNING: use of find_by_nickname is depricated, please use find_by(:nickname) { |n| n == '#{nickname}' } ")
|
74
50
|
self.find_by(:nickname) { |n| n == nickname }
|
75
51
|
end
|
76
52
|
|
77
|
-
def reload
|
78
|
-
uri = URI.parse(self.href)
|
79
|
-
@params ? @params.merge!(connection.get(uri.path)) : @params = connection.get(uri.path)
|
80
|
-
end
|
81
|
-
|
82
53
|
# the argument can be
|
83
54
|
# 1) takes href (URI),
|
84
55
|
# 2) or id (Integer)
|
85
56
|
# 3) or symbol :all, :first, :last
|
86
|
-
def
|
57
|
+
def find(href, &block)
|
87
58
|
if href.is_a?(Integer)
|
88
59
|
return self.new(connection.get(self.resource_plural_name + "/#{href}"))
|
89
60
|
elsif href.is_a?(Symbol)
|
@@ -104,12 +75,12 @@ module RightScale
|
|
104
75
|
nil
|
105
76
|
end
|
106
77
|
|
107
|
-
def
|
78
|
+
def find_by_id(id)
|
108
79
|
connection.logger("DEPRICATION WARNING: use of find_by_id is depricated, please use find(id) ")
|
109
80
|
self.find(id)
|
110
81
|
end
|
111
82
|
|
112
|
-
def
|
83
|
+
def create(opts)
|
113
84
|
location = connection.post(self.resource_plural_name, self.resource_singluar_name.to_sym => opts)
|
114
85
|
newrecord = self.new('href' => location)
|
115
86
|
newrecord.reload
|
@@ -117,12 +88,12 @@ module RightScale
|
|
117
88
|
end
|
118
89
|
|
119
90
|
# filter is only implemented on some api endpoints
|
120
|
-
def
|
91
|
+
def find_by_nickname_speed(nickname)
|
121
92
|
self.find_with_filter('nickname' => nickname)
|
122
93
|
end
|
123
94
|
|
124
95
|
# filter is only implemented on some api endpoints
|
125
|
-
def
|
96
|
+
def find_with_filter(filter = {})
|
126
97
|
filter_params = ""
|
127
98
|
filter.each {|key,val| filter_params += "filter[]=#{key}=#{val}&"}
|
128
99
|
a = Array.new
|
@@ -131,6 +102,36 @@ module RightScale
|
|
131
102
|
end
|
132
103
|
return a
|
133
104
|
end
|
105
|
+
end
|
106
|
+
|
107
|
+
module Base
|
108
|
+
# The params hash of attributes for direct manipulation
|
109
|
+
attr_accessor :params
|
110
|
+
def initialize(params = {})
|
111
|
+
@params = params
|
112
|
+
end
|
113
|
+
|
114
|
+
def connection()
|
115
|
+
@@connection ||= RestConnection::Connection.new
|
116
|
+
end
|
117
|
+
|
118
|
+
def resource_plural_name
|
119
|
+
self.class.to_s.underscore.pluralize
|
120
|
+
end
|
121
|
+
|
122
|
+
def resource_singular_name
|
123
|
+
self.class.to_s.underscore
|
124
|
+
end
|
125
|
+
|
126
|
+
def save
|
127
|
+
uri = URI.parse(self.href)
|
128
|
+
connection.put(uri.path, resource_singular_name.to_sym => @params)
|
129
|
+
end
|
130
|
+
|
131
|
+
def reload
|
132
|
+
uri = URI.parse(self.href)
|
133
|
+
@params ? @params.merge!(connection.get(uri.path)) : @params = connection.get(uri.path)
|
134
|
+
end
|
134
135
|
|
135
136
|
def destroy
|
136
137
|
my_href = URI.parse(self.href)
|
@@ -148,8 +149,11 @@ module RightScale
|
|
148
149
|
elsif @params[mn_dash]
|
149
150
|
@params[mn_dash] = args[0] if assignment
|
150
151
|
return @params[mn_dash]
|
152
|
+
elsif @params[mn.to_sym]
|
153
|
+
return @params[mn.to_sym]
|
151
154
|
else
|
152
|
-
|
155
|
+
return nil
|
156
|
+
#raise "called unknown method #{method_name} with #{args.inspect}"
|
153
157
|
end
|
154
158
|
end
|
155
159
|
|
@@ -24,3 +24,5 @@ require 'rest_connection/rightscale/ec2_security_group'
|
|
24
24
|
require 'rest_connection/rightscale/ec2_ssh_key'
|
25
25
|
require 'rest_connection/rightscale/multi_cloud_image'
|
26
26
|
require 'rest_connection/rightscale/tag'
|
27
|
+
require 'rest_connection/rightscale/rs_internal'
|
28
|
+
require 'rest_connection/rightscale/audit_entry'
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# This file is part of RestConnection
|
2
|
+
#
|
3
|
+
# RestConnection is free software: you can redistribute it and/or modify
|
4
|
+
# it under the terms of the GNU General Public License as published by
|
5
|
+
# the Free Software Foundation, either version 3 of the License, or
|
6
|
+
# (at your option) any later version.
|
7
|
+
#
|
8
|
+
# RestConnection is distributed in the hope that it will be useful,
|
9
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
10
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
11
|
+
# GNU General Public License for more details.
|
12
|
+
#
|
13
|
+
# You should have received a copy of the GNU General Public License
|
14
|
+
# along with RestConnection. If not, see <http://www.gnu.org/licenses/>.
|
15
|
+
|
16
|
+
#
|
17
|
+
# You must have special API access to use these internal API calls.
|
18
|
+
#
|
19
|
+
class RsInternal
|
20
|
+
include RightScale::Api::Base
|
21
|
+
extend RightScale::Api::BaseExtend
|
22
|
+
|
23
|
+
def connection
|
24
|
+
@@little_brother_connection ||= RestConnection::Connection.new
|
25
|
+
@@little_brother_connection.settings[:common_headers] = { 'X-API-VERSION' => '0.1' }
|
26
|
+
@@little_brother_connection
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.connection
|
30
|
+
@@little_brother_connection ||= RestConnection::Connection.new
|
31
|
+
@@little_brother_connection.settings[:common_headers] = { 'X-API-VERSION' => '0.1' }
|
32
|
+
@@little_brother_connection
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.get_server_template_multi_cloud_images(server_template_href)
|
36
|
+
connection.get("rs_internal/get_server_template_multi_cloud_images","server_template_href=#{server_template_href}")
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.set_server_multi_cloud_image(server_href, mci_href)
|
40
|
+
connection.put("rs_internal/set_server_multi_cloud_image", {:server_href => server_href, :multi_cloud_image_href => mci_href})
|
41
|
+
end
|
42
|
+
end
|
@@ -15,8 +15,11 @@
|
|
15
15
|
|
16
16
|
require 'rest_connection/ssh_hax'
|
17
17
|
|
18
|
-
class Server
|
18
|
+
class Server
|
19
|
+
include RightScale::Api::Base
|
20
|
+
extend RightScale::Api::BaseExtend
|
19
21
|
include SshHax
|
22
|
+
|
20
23
|
def self.create(opts)
|
21
24
|
create_options = Hash.new
|
22
25
|
create_options[self.resource_singluar_name.to_sym] = opts
|
@@ -74,8 +77,34 @@ class Server < RightScale::Api::Base
|
|
74
77
|
end
|
75
78
|
end
|
76
79
|
|
77
|
-
# This
|
80
|
+
# This should be used with v5 images only.
|
81
|
+
# executable to run can be an Executable or RightScript object
|
82
|
+
def run_executable(executable, opts=nil)
|
83
|
+
script_options = Hash.new
|
84
|
+
script_options[:server] = Hash.new
|
85
|
+
if executable.is_a?(Executable)
|
86
|
+
if executable.recipe?
|
87
|
+
script_options[:server][:recipe] = executable.recipe
|
88
|
+
else
|
89
|
+
script_options[:server][:right_script_href] = executable.right_script.href
|
90
|
+
end
|
91
|
+
elsif executable.is_a?(RightScript)
|
92
|
+
script_options[:server][:right_script_href] = executable.href
|
93
|
+
else
|
94
|
+
raise "Invalid class passed to run_executable, needs Executable or RightScript, was:#{executable.class}"
|
95
|
+
end
|
96
|
+
|
97
|
+
serv_href = URI.parse(self.href)
|
98
|
+
script_options[:server][:parameters] = opts unless opts.nil?
|
99
|
+
location = connection.post(serv_href.path + '/run_executable', script_options)
|
100
|
+
AuditEntry.new('href' => location)
|
101
|
+
end
|
102
|
+
|
103
|
+
# This should be used with v4 images only.
|
78
104
|
def run_script(script,opts=nil)
|
105
|
+
if script.is_a?(Executable)
|
106
|
+
script = script.right_script
|
107
|
+
end
|
79
108
|
serv_href = URI.parse(self.href)
|
80
109
|
script_options = Hash.new
|
81
110
|
script_options[:server] = Hash.new
|
@@ -127,6 +156,7 @@ class Server < RightScale::Api::Base
|
|
127
156
|
self.start
|
128
157
|
end
|
129
158
|
|
159
|
+
|
130
160
|
# DOES NOT WORK: fragile web scraping
|
131
161
|
# def relaunch
|
132
162
|
# unless state == "stopped"
|
@@ -13,7 +13,9 @@
|
|
13
13
|
# You should have received a copy of the GNU General Public License
|
14
14
|
# along with RestConnection. If not, see <http://www.gnu.org/licenses/>.
|
15
15
|
|
16
|
-
class ServerTemplate
|
16
|
+
class ServerTemplate
|
17
|
+
include RightScale::Api::Base
|
18
|
+
extend RightScale::Api::BaseExtend
|
17
19
|
def initialize(params)
|
18
20
|
@params = params
|
19
21
|
fetch_executables
|
@@ -28,4 +30,9 @@ class ServerTemplate < RightScale::Api::Base
|
|
28
30
|
end
|
29
31
|
@params["executables"] = ex
|
30
32
|
end
|
33
|
+
|
34
|
+
def fetch_multi_cloud_images
|
35
|
+
@params["multi_cloud_images"] = RsInternal.get_server_template_multi_cloud_images(self.href)
|
36
|
+
end
|
37
|
+
|
31
38
|
end
|
@@ -12,8 +12,14 @@
|
|
12
12
|
#
|
13
13
|
# You should have received a copy of the GNU General Public License
|
14
14
|
# along with RestConnection. If not, see <http://www.gnu.org/licenses/>.
|
15
|
+
#
|
16
|
+
# For now this is a stub for using with the ssh enabled Server#run_script
|
15
17
|
|
16
|
-
|
18
|
+
#This is the v4 image only work status api.
|
19
|
+
# was used by Server#run_script (depricating..)
|
20
|
+
class Status
|
21
|
+
include RightScale::Api::Base
|
22
|
+
extend RightScale::Api::BaseExtend
|
17
23
|
def wait_for_completed(audit_link = "no audit link available")
|
18
24
|
while(1)
|
19
25
|
reload
|
@@ -13,7 +13,9 @@
|
|
13
13
|
# You should have received a copy of the GNU General Public License
|
14
14
|
# along with RestConnection. If not, see <http://www.gnu.org/licenses/>.
|
15
15
|
|
16
|
-
class Tag
|
16
|
+
class Tag
|
17
|
+
include RightScale::Api::Base
|
18
|
+
extend RightScale::Api::BaseExtend
|
17
19
|
|
18
20
|
def self.search(resource_name, tags)
|
19
21
|
result = connection.get("/tags/search", :resource_type => resource_name.to_s, :tags => tags )
|
@@ -35,18 +35,11 @@ module SshHax
|
|
35
35
|
ssh_keys
|
36
36
|
end
|
37
37
|
|
38
|
-
|
39
|
-
# host_dns is optional and will default to objects self.dns_name
|
40
|
-
def run_recipe(recipe, ssh_key=nil, host_dns=self.dns_name)
|
41
|
-
if recipe.is_a?(Executable)
|
42
|
-
recipe = recipe.recipe
|
43
|
-
end
|
38
|
+
def run_and_tail(run_this, tail_command, expect, ssh_key=nil, host_dns=self.dns_name)
|
44
39
|
status = nil
|
45
40
|
result = nil
|
46
41
|
output = ""
|
47
|
-
|
48
|
-
expect = /RightLink.*RS> ([completed|failed]+: < #{recipe} >)/
|
49
|
-
run_this = "rs_run_recipe -n '#{recipe}'"
|
42
|
+
connection.logger("Running: #{run_this}")
|
50
43
|
Net::SSH.start(host_dns, 'root', :keys => ssh_key_config(ssh_key)) do |ssh|
|
51
44
|
cmd_channel = ssh.open_channel do |ch1|
|
52
45
|
ch1.on_request('exit-status') do |ch, data|
|
@@ -93,12 +86,46 @@ module SshHax
|
|
93
86
|
cmd_channel.wait
|
94
87
|
log_channel.wait
|
95
88
|
end
|
96
|
-
success = result.include?('completed')
|
97
89
|
connection.logger output
|
90
|
+
success = result.include?('completed')
|
98
91
|
connection.logger "Converge failed. See server audit: #{self.audit_link}" unless success
|
99
92
|
return {:status => success, :output => output}
|
100
93
|
end
|
101
94
|
|
95
|
+
# script is an Executable object with minimally nick or id set
|
96
|
+
def run_executable_with_ssh(script, options={}, ssh_key=nil)
|
97
|
+
raise "FATAL: run_executable called on a server with no dns_name. You need to run .settings on the server to populate this attribute." unless self.dns_name
|
98
|
+
if script.is_a?(Executable)
|
99
|
+
script = script.right_script
|
100
|
+
end
|
101
|
+
|
102
|
+
raise "FATAL: unrecognized format for script. Must be an Executable or RightScript with href or name attributes" unless (script.is_a?(RightScript)) && (script.href || script.name)
|
103
|
+
if script.href
|
104
|
+
run_this = "rs_run_right_script -i #{script.href.split(/\//).last}"
|
105
|
+
elsif script.name
|
106
|
+
run_this = "rs_run_right_script -n #{script.name}"
|
107
|
+
end
|
108
|
+
tail_command ="tail -f -n1 /var/log/messages"
|
109
|
+
expect = /RightLink.*RS> ([completed|failed]+:)/
|
110
|
+
options.each do |key, value|
|
111
|
+
run_this += " -p #{key}=#{value}"
|
112
|
+
end
|
113
|
+
AuditEntry.new(run_and_tail(run_this, tail_command, expect))
|
114
|
+
end
|
115
|
+
|
116
|
+
# recipe can be either a String, or an Executable
|
117
|
+
# host_dns is optional and will default to objects self.dns_name
|
118
|
+
def run_recipe_with_ssh(recipe, ssh_key=nil, host_dns=self.dns_name)
|
119
|
+
raise "FATAL: run_script called on a server with no dns_name. You need to run .settings on the server to populate this attribute." unless self.dns_name
|
120
|
+
if recipe.is_a?(Executable)
|
121
|
+
recipe = recipe.recipe
|
122
|
+
end
|
123
|
+
tail_command ="tail -f -n1 /var/log/messages"
|
124
|
+
expect = /RightLink.*RS> ([completed|failed]+: < #{recipe} >)/
|
125
|
+
run_this = "rs_run_recipe -n '#{recipe}'"
|
126
|
+
run_and_tail(run_this, tail_command, expect, ssh_key)
|
127
|
+
end
|
128
|
+
|
102
129
|
def spot_check(command, ssh_key=nil, host_dns=self.dns_name, &block)
|
103
130
|
connection.logger "SSHing to #{host_dns}"
|
104
131
|
Net::SSH.start(host_dns, 'root', :keys => ssh_key_config(ssh_key)) do |ssh|
|
@@ -116,7 +143,7 @@ module SshHax
|
|
116
143
|
|
117
144
|
# returns hash of exit_status and output from command
|
118
145
|
def spot_check_command(command, ssh_key=nil, host_dns=self.dns_name)
|
119
|
-
connection.logger "SSHing to #{host_dns} using key #{ssh_key}"
|
146
|
+
connection.logger "SSHing to #{host_dns} using key(s) #{ssh_key_config(ssh_key)}"
|
120
147
|
status = nil
|
121
148
|
output = ""
|
122
149
|
Net::SSH.start(host_dns, 'root', :keys => ssh_key_config(ssh_key)) do |ssh|
|
@@ -131,6 +158,7 @@ module SshHax
|
|
131
158
|
status = 1
|
132
159
|
end
|
133
160
|
ch2.on_data do |ch, data|
|
161
|
+
|
134
162
|
output += data
|
135
163
|
end
|
136
164
|
ch2.on_extended_data do |ch, type, data|
|
data/rest_connection.gemspec
CHANGED
@@ -5,18 +5,19 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{rest_connection}
|
8
|
-
s.version = "0.0.
|
8
|
+
s.version = "0.0.4"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Jeremy Deininger"]
|
12
|
-
s.date = %q{2010-
|
12
|
+
s.date = %q{2010-04-15}
|
13
13
|
s.description = %q{provides rest_connection}
|
14
14
|
s.email = %q{jeremy@rubyonlinux.org}
|
15
15
|
s.extra_rdoc_files = [
|
16
16
|
"README"
|
17
17
|
]
|
18
18
|
s.files = [
|
19
|
-
"
|
19
|
+
".gitignore",
|
20
|
+
"README",
|
20
21
|
"Rakefile",
|
21
22
|
"VERSION",
|
22
23
|
"config/rest_api_config.yaml.sample",
|
@@ -31,6 +32,7 @@ Gem::Specification.new do |s|
|
|
31
32
|
"examples/run_php_chef_sequence.rb",
|
32
33
|
"examples/set_deployment_template_href.rb",
|
33
34
|
"lib/rest_connection.rb",
|
35
|
+
"lib/rest_connection/rightscale/audit_entry.rb",
|
34
36
|
"lib/rest_connection/rightscale/deployment.rb",
|
35
37
|
"lib/rest_connection/rightscale/ec2_security_group.rb",
|
36
38
|
"lib/rest_connection/rightscale/ec2_server_array.rb",
|
@@ -41,12 +43,15 @@ Gem::Specification.new do |s|
|
|
41
43
|
"lib/rest_connection/rightscale/right_script.rb",
|
42
44
|
"lib/rest_connection/rightscale/rightscale_api_base.rb",
|
43
45
|
"lib/rest_connection/rightscale/rightscale_api_resources.rb",
|
46
|
+
"lib/rest_connection/rightscale/rs_internal.rb",
|
44
47
|
"lib/rest_connection/rightscale/server.rb",
|
45
48
|
"lib/rest_connection/rightscale/server_template.rb",
|
46
49
|
"lib/rest_connection/rightscale/status.rb",
|
47
50
|
"lib/rest_connection/rightscale/tag.rb",
|
48
51
|
"lib/rest_connection/ssh_hax.rb",
|
49
|
-
"rest_connection.gemspec"
|
52
|
+
"rest_connection.gemspec",
|
53
|
+
"spec/rs_internal_spec.rb",
|
54
|
+
"spec/server_spec.rb"
|
50
55
|
]
|
51
56
|
s.homepage = %q{http://github.com/jeremyd/rest_connection}
|
52
57
|
s.rdoc_options = ["--charset=UTF-8"]
|
@@ -54,17 +59,18 @@ Gem::Specification.new do |s|
|
|
54
59
|
s.rubygems_version = %q{1.3.6}
|
55
60
|
s.summary = %q{lib for restful connections to the rightscale api}
|
56
61
|
s.test_files = [
|
57
|
-
"
|
58
|
-
"
|
59
|
-
"examples/relaunch_deployment.rb",
|
62
|
+
"spec/server_spec.rb",
|
63
|
+
"spec/rs_internal_spec.rb",
|
60
64
|
"examples/restart_instance_agent.rb",
|
65
|
+
"examples/console.rb",
|
66
|
+
"examples/run_php_chef_sequence.rb",
|
67
|
+
"examples/set_deployment_template_href.rb",
|
68
|
+
"examples/dev_setup.rb",
|
61
69
|
"examples/right_scale_ec2_instances_api_test.rb",
|
62
|
-
"examples/
|
70
|
+
"examples/relaunch_deployment.rb",
|
63
71
|
"examples/run_ebs_terminate.rb",
|
64
72
|
"examples/run_mysql_chef_sequence.rb",
|
65
|
-
"examples/
|
66
|
-
"examples/set_deployment_images.rb",
|
67
|
-
"examples/set_deployment_template_href.rb"
|
73
|
+
"examples/run_ebs_sequence.rb"
|
68
74
|
]
|
69
75
|
|
70
76
|
if s.respond_to? :specification_version then
|
@@ -74,13 +80,16 @@ Gem::Specification.new do |s|
|
|
74
80
|
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
75
81
|
s.add_runtime_dependency(%q<activesupport>, [">= 0"])
|
76
82
|
s.add_runtime_dependency(%q<net-ssh>, [">= 0"])
|
83
|
+
s.add_runtime_dependency(%q<json>, [">= 0"])
|
77
84
|
else
|
78
85
|
s.add_dependency(%q<activesupport>, [">= 0"])
|
79
86
|
s.add_dependency(%q<net-ssh>, [">= 0"])
|
87
|
+
s.add_dependency(%q<json>, [">= 0"])
|
80
88
|
end
|
81
89
|
else
|
82
90
|
s.add_dependency(%q<activesupport>, [">= 0"])
|
83
91
|
s.add_dependency(%q<net-ssh>, [">= 0"])
|
92
|
+
s.add_dependency(%q<json>, [">= 0"])
|
84
93
|
end
|
85
94
|
end
|
86
95
|
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rest_connection'
|
3
|
+
require 'spec'
|
4
|
+
require 'ruby-debug'
|
5
|
+
|
6
|
+
describe RsInternal, "exercises the rs_internal api" do
|
7
|
+
before(:all) do
|
8
|
+
@st = ServerTemplate.find(27418)
|
9
|
+
end
|
10
|
+
|
11
|
+
# this will never be checked in, these tests are too hardwired
|
12
|
+
# (doesn't mean it's not useful)
|
13
|
+
it "should get all the mcis for this hardcoded template and set this hardcoded server" do
|
14
|
+
mcis = RsInternal.get_server_template_multi_cloud_images(@st.href)
|
15
|
+
mcis.empty?.should_not == true
|
16
|
+
mcis.first['href'].include?("https://").should == true
|
17
|
+
|
18
|
+
server = "/servers/752944"
|
19
|
+
success = RsInternal.set_server_multi_cloud_image(server, mcis.first['href'])
|
20
|
+
|
21
|
+
debugger
|
22
|
+
puts "blah"
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
data/spec/server_spec.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rest_connection'
|
3
|
+
require 'spec'
|
4
|
+
require 'ruby-debug'
|
5
|
+
|
6
|
+
describe Server, "server api object exercise" do
|
7
|
+
before(:all) do
|
8
|
+
@server_v4_right_script = Server.find(752616) # a v4 server
|
9
|
+
@server_v5_recipe = Server.find(697640) # a v5 server
|
10
|
+
@server_v5_right_script = Server.find() # a v5 server
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should run a right_script on a v4 server" do
|
14
|
+
this_template = ServerTemplate.find(@server_v4_right_script.server_template_href)
|
15
|
+
run_first = this_template.executables.first
|
16
|
+
location = @server_v4_right_script.run_executable(run_first)
|
17
|
+
audit = AuditEntry.new(:href => location)
|
18
|
+
audit.wait_for_completed
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should run a recipe on a v5 server" do
|
22
|
+
this_template = ServerTemplate.find(@server_v5_recipe.server_template_href)
|
23
|
+
run_first = this_template.executables.first
|
24
|
+
audit = @server_v5_recipe.run_executable(run_first)
|
25
|
+
audit.wait_for_completed
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should run a right_script on a v5 server" do
|
29
|
+
this_template = ServerTemplate.find(@server_v5_right_script.server_template_href)
|
30
|
+
run_first = this_template.executables.first
|
31
|
+
audit = @server_v5_right_script.run_executable(run_first)
|
32
|
+
audit.wait_for_completed
|
33
|
+
end
|
34
|
+
end
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
version: 0.0.
|
8
|
+
- 4
|
9
|
+
version: 0.0.4
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Jeremy Deininger
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-
|
17
|
+
date: 2010-04-15 00:00:00 +00:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -41,6 +41,18 @@ dependencies:
|
|
41
41
|
version: "0"
|
42
42
|
type: :runtime
|
43
43
|
version_requirements: *id002
|
44
|
+
- !ruby/object:Gem::Dependency
|
45
|
+
name: json
|
46
|
+
prerelease: false
|
47
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
48
|
+
requirements:
|
49
|
+
- - ">="
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
segments:
|
52
|
+
- 0
|
53
|
+
version: "0"
|
54
|
+
type: :runtime
|
55
|
+
version_requirements: *id003
|
44
56
|
description: provides rest_connection
|
45
57
|
email: jeremy@rubyonlinux.org
|
46
58
|
executables: []
|
@@ -50,6 +62,7 @@ extensions: []
|
|
50
62
|
extra_rdoc_files:
|
51
63
|
- README
|
52
64
|
files:
|
65
|
+
- .gitignore
|
53
66
|
- README
|
54
67
|
- Rakefile
|
55
68
|
- VERSION
|
@@ -65,6 +78,7 @@ files:
|
|
65
78
|
- examples/run_php_chef_sequence.rb
|
66
79
|
- examples/set_deployment_template_href.rb
|
67
80
|
- lib/rest_connection.rb
|
81
|
+
- lib/rest_connection/rightscale/audit_entry.rb
|
68
82
|
- lib/rest_connection/rightscale/deployment.rb
|
69
83
|
- lib/rest_connection/rightscale/ec2_security_group.rb
|
70
84
|
- lib/rest_connection/rightscale/ec2_server_array.rb
|
@@ -75,12 +89,15 @@ files:
|
|
75
89
|
- lib/rest_connection/rightscale/right_script.rb
|
76
90
|
- lib/rest_connection/rightscale/rightscale_api_base.rb
|
77
91
|
- lib/rest_connection/rightscale/rightscale_api_resources.rb
|
92
|
+
- lib/rest_connection/rightscale/rs_internal.rb
|
78
93
|
- lib/rest_connection/rightscale/server.rb
|
79
94
|
- lib/rest_connection/rightscale/server_template.rb
|
80
95
|
- lib/rest_connection/rightscale/status.rb
|
81
96
|
- lib/rest_connection/rightscale/tag.rb
|
82
97
|
- lib/rest_connection/ssh_hax.rb
|
83
98
|
- rest_connection.gemspec
|
99
|
+
- spec/rs_internal_spec.rb
|
100
|
+
- spec/server_spec.rb
|
84
101
|
has_rdoc: true
|
85
102
|
homepage: http://github.com/jeremyd/rest_connection
|
86
103
|
licenses: []
|
@@ -112,14 +129,15 @@ signing_key:
|
|
112
129
|
specification_version: 3
|
113
130
|
summary: lib for restful connections to the rightscale api
|
114
131
|
test_files:
|
132
|
+
- spec/server_spec.rb
|
133
|
+
- spec/rs_internal_spec.rb
|
134
|
+
- examples/restart_instance_agent.rb
|
115
135
|
- examples/console.rb
|
136
|
+
- examples/run_php_chef_sequence.rb
|
137
|
+
- examples/set_deployment_template_href.rb
|
116
138
|
- examples/dev_setup.rb
|
117
|
-
- examples/relaunch_deployment.rb
|
118
|
-
- examples/restart_instance_agent.rb
|
119
139
|
- examples/right_scale_ec2_instances_api_test.rb
|
120
|
-
- examples/
|
140
|
+
- examples/relaunch_deployment.rb
|
121
141
|
- examples/run_ebs_terminate.rb
|
122
142
|
- examples/run_mysql_chef_sequence.rb
|
123
|
-
- examples/
|
124
|
-
- examples/set_deployment_images.rb
|
125
|
-
- examples/set_deployment_template_href.rb
|
143
|
+
- examples/run_ebs_sequence.rb
|
File without changes
|