rest_connection 0.0.1 → 0.0.2
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/Rakefile +0 -1
- data/VERSION +1 -1
- data/examples/console.rb +3 -4
- data/examples/restart_instance_agent.rb +9 -10
- data/examples/set_deployment_images.rb +0 -0
- data/lib/rest_connection/rightscale/ec2_security_group.rb +17 -0
- data/lib/rest_connection/rightscale/ec2_server_array.rb +33 -0
- data/lib/rest_connection/rightscale/ec2_ssh_key.rb +17 -0
- data/lib/rest_connection/rightscale/executable.rb +2 -2
- data/lib/rest_connection/rightscale/multi_cloud_image.rb +17 -0
- data/lib/rest_connection/rightscale/rightscale_api_base.rb +68 -19
- data/lib/rest_connection/rightscale/rightscale_api_resources.rb +4 -0
- data/lib/rest_connection/rightscale/server.rb +55 -26
- data/lib/rest_connection/rightscale/tag.rb +21 -0
- data/lib/rest_connection/ssh_hax.rb +24 -17
- data/rest_connection.gemspec +10 -8
- metadata +25 -21
- data/examples/mysql_dev_rollback.rb +0 -29
- data/lib/rest_connection/mechanize_connection.rb +0 -43
data/Rakefile
CHANGED
@@ -7,7 +7,6 @@ Jeweler::Tasks.new do |gemspec|
|
|
7
7
|
gemspec.email = "jeremy@rubyonlinux.org"
|
8
8
|
gemspec.homepage = "http://github.com/jeremyd/rest_connection"
|
9
9
|
gemspec.authors = ["Jeremy Deininger"]
|
10
|
-
gemspec.add_dependency('mechanize', '>= 0.9.3')
|
11
10
|
gemspec.add_dependency('activesupport')
|
12
11
|
end
|
13
12
|
Jeweler::GemcutterTasks.new
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.2
|
data/examples/console.rb
CHANGED
@@ -7,7 +7,6 @@ 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
|
11
10
|
end
|
12
11
|
|
13
12
|
# find all servers in the deployment (the fast way)
|
@@ -17,13 +16,13 @@ servers = servers.select { |s| s.nickname =~ /#{opts[:only]}/ } if opts[:only]
|
|
17
16
|
|
18
17
|
servers.each do |s|
|
19
18
|
s.wait_for_operational_with_dns
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
19
|
+
# s.spot_check("/opt/rightscale/sandbox/bin/gem uninstall right_resources_premium") do |result|
|
20
|
+
# puts result
|
21
|
+
# end
|
22
|
+
# monit will restart it
|
23
|
+
# OR-- monit -c /opt/rightscale/etc/monitrc restart instance
|
24
|
+
# s.spot_check("rnac --stop instance") do |result|
|
25
|
+
# puts result
|
26
|
+
# end
|
27
|
+
s.run_recipe("database_test::dev_pristine_restore")
|
29
28
|
end
|
File without changes
|
@@ -0,0 +1,17 @@
|
|
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 Ec2SecurityGroup < RightScale::Api::Base
|
17
|
+
end
|
@@ -0,0 +1,33 @@
|
|
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
|
+
# Example:
|
17
|
+
# a = Ec2ServerArray.new(:href => "https://validhref")
|
18
|
+
# st = ServerTemplate.new(:href => "https://validhref")
|
19
|
+
# st.executables.find(:nickname
|
20
|
+
# a.run_script_on_all(
|
21
|
+
|
22
|
+
class Ec2ServerArray < RightScale::Api::Base
|
23
|
+
def run_script_on_all(script, server_template_hrefs, inputs=nil)
|
24
|
+
serv_href = URI.parse(self.href)
|
25
|
+
options = Hash.new
|
26
|
+
options[:ec2_server_array] = Hash.new
|
27
|
+
options[:ec2_server_array][:right_script_href] = self.href
|
28
|
+
options[:ec2_server_array][:parameters] = inputs unless inputs.nil?
|
29
|
+
options[:ec2_server_array][:server_template_hrefs] = server_template_hrefs
|
30
|
+
connection.post(serv_href.path, options)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
@@ -0,0 +1,17 @@
|
|
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 Ec2SshKey < RightScale::Api::Base
|
17
|
+
end
|
@@ -13,14 +13,14 @@ class Executable < RightScale::Api::Base
|
|
13
13
|
# }
|
14
14
|
|
15
15
|
def recipe?
|
16
|
-
if self["recipe"]
|
16
|
+
if self["recipe"] == nil # && right_script['href']
|
17
17
|
return false
|
18
18
|
end
|
19
19
|
true
|
20
20
|
end
|
21
21
|
|
22
22
|
def right_script?
|
23
|
-
if self["recipe"]
|
23
|
+
if self["recipe"] == nil # && right_script['href']
|
24
24
|
return true
|
25
25
|
end
|
26
26
|
false
|
@@ -0,0 +1,17 @@
|
|
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 MultiCloudImage < RightScale::Api::Base
|
17
|
+
end
|
@@ -13,13 +13,11 @@
|
|
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
|
-
require '
|
17
|
-
require 'activesupport'
|
16
|
+
require 'active_support'
|
18
17
|
|
19
18
|
module RightScale
|
20
19
|
module Api
|
21
20
|
class Base
|
22
|
-
include MechanizeConnection::Connection
|
23
21
|
# The params hash of attributes for direct manipulation
|
24
22
|
attr_accessor :params
|
25
23
|
|
@@ -42,6 +40,27 @@ module RightScale
|
|
42
40
|
self.to_s.underscore
|
43
41
|
end
|
44
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
|
+
# matches using result of block match expression
|
57
|
+
# ex: Server.find_by(:nickname) { |n| n =~ /production/ }
|
58
|
+
def self.find_by(attrib, &block)
|
59
|
+
self.find_all.select do |s|
|
60
|
+
yield(s[attrib.to_s])
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
45
64
|
def self.find_all
|
46
65
|
a = Array.new
|
47
66
|
connection.get(self.resource_plural_name).each do |object|
|
@@ -51,9 +70,8 @@ module RightScale
|
|
51
70
|
end
|
52
71
|
|
53
72
|
def self.find_by_nickname(nickname)
|
54
|
-
|
55
|
-
|
56
|
-
end
|
73
|
+
connection.logger("DEPRICATION WARNING: use of find_by_nickname is depricated, please use find_by(:nickname) { |n| n == '#{nickname}' } ")
|
74
|
+
self.find_by(:nickname) { |n| n == nickname }
|
57
75
|
end
|
58
76
|
|
59
77
|
def reload
|
@@ -61,18 +79,41 @@ module RightScale
|
|
61
79
|
@params ? @params.merge!(connection.get(uri.path)) : @params = connection.get(uri.path)
|
62
80
|
end
|
63
81
|
|
64
|
-
|
65
|
-
|
66
|
-
|
82
|
+
# the argument can be
|
83
|
+
# 1) takes href (URI),
|
84
|
+
# 2) or id (Integer)
|
85
|
+
# 3) or symbol :all, :first, :last
|
86
|
+
def self.find(href, &block)
|
87
|
+
if href.is_a?(Integer)
|
88
|
+
return self.new(connection.get(self.resource_plural_name + "/#{href}"))
|
89
|
+
elsif href.is_a?(Symbol)
|
90
|
+
results = self.find_all
|
91
|
+
if block_given?
|
92
|
+
results = results.select { |s| yield(s) }
|
93
|
+
end
|
94
|
+
if href == :all
|
95
|
+
return results
|
96
|
+
elsif href == :first
|
97
|
+
return results.first
|
98
|
+
elsif href == :last
|
99
|
+
return results.last
|
100
|
+
end
|
101
|
+
elsif uri = URI.parse(href)
|
102
|
+
return self.new(connection.get(uri.path))
|
103
|
+
end
|
104
|
+
nil
|
67
105
|
end
|
68
106
|
|
69
107
|
def self.find_by_id(id)
|
70
|
-
|
108
|
+
connection.logger("DEPRICATION WARNING: use of find_by_id is depricated, please use find(id) ")
|
109
|
+
self.find(id)
|
71
110
|
end
|
72
111
|
|
73
112
|
def self.create(opts)
|
74
113
|
location = connection.post(self.resource_plural_name, self.resource_singluar_name.to_sym => opts)
|
75
|
-
self.new('href' => location)
|
114
|
+
newrecord = self.new('href' => location)
|
115
|
+
newrecord.reload
|
116
|
+
newrecord
|
76
117
|
end
|
77
118
|
|
78
119
|
# filter is only implemented on some api endpoints
|
@@ -98,20 +139,28 @@ module RightScale
|
|
98
139
|
|
99
140
|
# the following two methods are used to access the @params hash in a friendly way
|
100
141
|
def method_missing(method_name, *args)
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
142
|
+
mn = method_name.to_s
|
143
|
+
assignment = mn.gsub!(/=/,"")
|
144
|
+
mn_dash = mn.gsub(/_/,"-")
|
145
|
+
if @params[mn]
|
146
|
+
@params[mn] = args[0] if assignment
|
147
|
+
return @params[mn]
|
148
|
+
elsif @params[mn_dash]
|
149
|
+
@params[mn_dash] = args[0] if assignment
|
150
|
+
return @params[mn_dash]
|
105
151
|
else
|
106
152
|
raise "called unknown method #{method_name} with #{args.inspect}"
|
107
153
|
end
|
108
154
|
end
|
109
155
|
|
110
156
|
def [](name)
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
157
|
+
try_these = [name, name.gsub(/_/,'-'), name.to_sym]
|
158
|
+
try_these.each do |t|
|
159
|
+
if @params[t]
|
160
|
+
return @params[name]
|
161
|
+
else
|
162
|
+
return nil
|
163
|
+
end
|
115
164
|
end
|
116
165
|
end
|
117
166
|
|
@@ -20,3 +20,7 @@ require 'rest_connection/rightscale/status'
|
|
20
20
|
require 'rest_connection/rightscale/server_template'
|
21
21
|
require 'rest_connection/rightscale/right_script'
|
22
22
|
require 'rest_connection/rightscale/instance'
|
23
|
+
require 'rest_connection/rightscale/ec2_security_group'
|
24
|
+
require 'rest_connection/rightscale/ec2_ssh_key'
|
25
|
+
require 'rest_connection/rightscale/multi_cloud_image'
|
26
|
+
require 'rest_connection/rightscale/tag'
|
@@ -17,6 +17,16 @@ require 'rest_connection/ssh_hax'
|
|
17
17
|
|
18
18
|
class Server < RightScale::Api::Base
|
19
19
|
include SshHax
|
20
|
+
def self.create(opts)
|
21
|
+
create_options = Hash.new
|
22
|
+
create_options[self.resource_singluar_name.to_sym] = opts
|
23
|
+
create_options["cloud_id"] = opts[:cloud_id] if opts[:cloud_id]
|
24
|
+
location = connection.post(self.resource_plural_name,create_options)
|
25
|
+
newrecord = self.new('href' => location)
|
26
|
+
newrecord.reload
|
27
|
+
newrecord
|
28
|
+
end
|
29
|
+
|
20
30
|
def wait_for_state(st)
|
21
31
|
reload
|
22
32
|
connection.logger("#{nickname} is #{self.state}")
|
@@ -63,23 +73,23 @@ class Server < RightScale::Api::Base
|
|
63
73
|
connection.logger("WARNING: was in #{self.state} so skiping stop call")
|
64
74
|
end
|
65
75
|
end
|
66
|
-
|
67
|
-
|
76
|
+
|
77
|
+
# This method takes a RightScript or Executable, and optional run time parameters in an options hash.
|
78
|
+
def run_script(script,opts=nil)
|
68
79
|
serv_href = URI.parse(self.href)
|
69
|
-
|
80
|
+
script_options = Hash.new
|
81
|
+
script_options[:server] = Hash.new
|
82
|
+
script_options[:server][:right_script_href] = script.href
|
83
|
+
script_options[:server][:parameters] = opts unless opts.nil?
|
84
|
+
location = connection.post(serv_href.path + '/run_script', script_options)
|
70
85
|
Status.new('href' => location)
|
71
|
-
end
|
86
|
+
end
|
72
87
|
|
73
88
|
def set_input(name, value)
|
74
89
|
serv_href = URI.parse(self.href)
|
75
90
|
connection.put(serv_href.path, :server => {:parameters => {name.to_sym => value} })
|
76
91
|
end
|
77
92
|
|
78
|
-
def self.create(opts)
|
79
|
-
location = connection.post("servers", :server => opts)
|
80
|
-
Server.new('href' => location)
|
81
|
-
end
|
82
|
-
|
83
93
|
def set_template(href)
|
84
94
|
serv_href = URI.parse(self.href)
|
85
95
|
connection.put(serv_href.path, :server => {:server_template_href => href})
|
@@ -90,9 +100,14 @@ class Server < RightScale::Api::Base
|
|
90
100
|
@params.merge! connection.get(serv_href.path + "/settings")
|
91
101
|
end
|
92
102
|
|
93
|
-
def
|
103
|
+
def get_sketchy_data
|
94
104
|
serv_href = URI.parse(self.href)
|
95
|
-
@params.merge! connection.get(serv_href.path + "/
|
105
|
+
@params.merge! connection.get(serv_href.path + "/get_sketchy_data")
|
106
|
+
end
|
107
|
+
|
108
|
+
def monitoring
|
109
|
+
serv_href = URI.parse(self.href)
|
110
|
+
@params.merge! connection.get(serv_href.path + "/monitoring")
|
96
111
|
end
|
97
112
|
|
98
113
|
def reboot
|
@@ -100,22 +115,36 @@ class Server < RightScale::Api::Base
|
|
100
115
|
connection.post(serv_href.path + "/reboot")
|
101
116
|
end
|
102
117
|
|
118
|
+
def events
|
119
|
+
my_events = Event.new
|
120
|
+
id = self.href.split(/\//).last
|
121
|
+
my_events.filter_by(:server_id, id)
|
122
|
+
end
|
123
|
+
|
103
124
|
def relaunch
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
base_url = URI.parse(self.href)
|
108
|
-
base_url.path = "/servers/#{server_id}"
|
109
|
-
|
110
|
-
s = agent.get(base_url.to_s)
|
111
|
-
relaunch = s.links.detect {|d| d.to_s == "Relaunch"}
|
112
|
-
prelaunch_page = agent.get(relaunch.href)
|
113
|
-
launch_form = prelaunch_page.forms[2]
|
114
|
-
launch_form.radiobuttons_with(:name => 'launch_immediately').first.check
|
115
|
-
agent.submit(launch_form, launch_form.buttons.first)
|
116
|
-
else
|
117
|
-
connection.logger("WARNING: detected server is #{self.state}, skipping relaunch")
|
118
|
-
end
|
125
|
+
self.stop
|
126
|
+
self.wait_for_state("stopped")
|
127
|
+
self.start
|
119
128
|
end
|
129
|
+
|
130
|
+
# DOES NOT WORK: fragile web scraping
|
131
|
+
# def relaunch
|
132
|
+
# unless state == "stopped"
|
133
|
+
# wind_monkey
|
134
|
+
# server_id = self.href.split(/\//).last
|
135
|
+
# base_url = URI.parse(self.href)
|
136
|
+
# base_url.path = "/servers/#{server_id}"
|
137
|
+
#
|
138
|
+
# s = agent.get(base_url.to_s)
|
139
|
+
# relaunch = s.links.detect {|d| d.to_s == "Relaunch"}
|
140
|
+
# prelaunch_page = agent.get(relaunch.href)
|
141
|
+
# debugger
|
142
|
+
# launch_form = prelaunch_page.forms[2]
|
143
|
+
# launch_form.radiobuttons_with(:name => 'launch_immediately').first.check
|
144
|
+
# agent.submit(launch_form, launch_form.buttons.first)
|
145
|
+
# else
|
146
|
+
# connection.logger("WARNING: detected server is #{self.state}, skipping relaunch")
|
147
|
+
# end
|
148
|
+
# end
|
120
149
|
end
|
121
150
|
|
@@ -0,0 +1,21 @@
|
|
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 Tag < RightScale::Api::Base
|
17
|
+
|
18
|
+
def self.search(resource_name, tags)
|
19
|
+
result = connection.get("/tags/search", :resource_type => resource_name.to_s, :tags => tags )
|
20
|
+
end
|
21
|
+
end
|
@@ -19,25 +19,35 @@ require 'net/ssh'
|
|
19
19
|
# This is a mixin module run_recipes until api support is ready for checking result of recipe run.
|
20
20
|
# The mixin typically used from Server#run_recipe
|
21
21
|
module SshHax
|
22
|
+
|
23
|
+
def ssh_key_config(item)
|
24
|
+
if item.is_a?(Array)
|
25
|
+
ssh_keys = item
|
26
|
+
elsif item.is_a?(String)
|
27
|
+
ssh_keys = [item]
|
28
|
+
elsif k = connection.settings[:ssh_key]
|
29
|
+
ssh_keys = [k]
|
30
|
+
elsif kk = connection.settings[:ssh_keys]
|
31
|
+
ssh_keys = kk
|
32
|
+
else
|
33
|
+
ssh_keys = nil
|
34
|
+
end
|
35
|
+
ssh_keys
|
36
|
+
end
|
37
|
+
|
22
38
|
# recipe can be either a String, or an Executable
|
23
39
|
# host_dns is optional and will default to objects self.dns_name
|
24
|
-
def run_recipe(recipe, host_dns=self.dns_name)
|
40
|
+
def run_recipe(recipe, ssh_key=nil, host_dns=self.dns_name)
|
25
41
|
if recipe.is_a?(Executable)
|
26
42
|
recipe = recipe.recipe
|
27
43
|
end
|
28
|
-
# legacy used this key by default
|
29
|
-
if connection.settings[:ssh_key]
|
30
|
-
ssh_key = connection.settings[:ssh_key]
|
31
|
-
else
|
32
|
-
ssh_key='~/.ssh/publish-test'
|
33
|
-
end
|
34
44
|
status = nil
|
35
45
|
result = nil
|
36
46
|
output = ""
|
37
47
|
tail_command ="tail -f -n1 /var/log/messages"
|
38
48
|
expect = /RightLink.*RS> ([completed|failed]+: < #{recipe} >)/
|
39
49
|
run_this = "rs_run_recipe -n '#{recipe}'"
|
40
|
-
Net::SSH.start(host_dns, 'root', :keys =>
|
50
|
+
Net::SSH.start(host_dns, 'root', :keys => ssh_key_config(ssh_key)) do |ssh|
|
41
51
|
cmd_channel = ssh.open_channel do |ch1|
|
42
52
|
ch1.on_request('exit-status') do |ch, data|
|
43
53
|
status = data.read_long
|
@@ -89,30 +99,27 @@ module SshHax
|
|
89
99
|
return {:status => success, :output => output}
|
90
100
|
end
|
91
101
|
|
92
|
-
def spot_check(command, ssh_key=
|
93
|
-
|
94
|
-
|
95
|
-
Net::SSH.start(host_dns, 'root', :keys => [ssh_key]) do |ssh|
|
102
|
+
def spot_check(command, ssh_key=nil, host_dns=self.dns_name, &block)
|
103
|
+
connection.logger "SSHing to #{host_dns}"
|
104
|
+
Net::SSH.start(host_dns, 'root', :keys => ssh_key_config(ssh_key)) do |ssh|
|
96
105
|
result = ssh.exec!(command)
|
97
106
|
yield result
|
98
107
|
end
|
99
108
|
end
|
100
109
|
|
101
110
|
# returns true or false based on command success
|
102
|
-
def spot_check_command?(command, ssh_key=
|
103
|
-
ssh_key = connection.settings[:ssh_key] if connection.settings[:ssh_key]
|
111
|
+
def spot_check_command?(command, ssh_key=nil, host_dns=self.dns_name)
|
104
112
|
results = spot_check_command(command, ssh_key, host_dns)
|
105
113
|
return results[:status] == 0
|
106
114
|
end
|
107
115
|
|
108
116
|
|
109
117
|
# returns hash of exit_status and output from command
|
110
|
-
def spot_check_command(command, ssh_key=
|
111
|
-
ssh_key = connection.settings[:ssh_key] if connection.settings[:ssh_key]
|
118
|
+
def spot_check_command(command, ssh_key=nil, host_dns=self.dns_name)
|
112
119
|
connection.logger "SSHing to #{host_dns} using key #{ssh_key}"
|
113
120
|
status = nil
|
114
121
|
output = ""
|
115
|
-
Net::SSH.start(host_dns, 'root', :keys =>
|
122
|
+
Net::SSH.start(host_dns, 'root', :keys => ssh_key_config(ssh_key)) do |ssh|
|
116
123
|
cmd_channel = ssh.open_channel do |ch1|
|
117
124
|
ch1.on_request('exit-status') do |ch, data|
|
118
125
|
status = data.read_long
|
data/rest_connection.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
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.2"
|
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-03-18}
|
13
13
|
s.description = %q{provides rest_connection}
|
14
14
|
s.email = %q{jeremy@rubyonlinux.org}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -20,6 +20,7 @@ Gem::Specification.new do |s|
|
|
20
20
|
"Rakefile",
|
21
21
|
"VERSION",
|
22
22
|
"config/rest_api_config.yaml.sample",
|
23
|
+
"examples/console.rb",
|
23
24
|
"examples/dev_setup.rb",
|
24
25
|
"examples/relaunch_deployment.rb",
|
25
26
|
"examples/restart_instance_agent.rb",
|
@@ -30,28 +31,31 @@ Gem::Specification.new do |s|
|
|
30
31
|
"examples/run_php_chef_sequence.rb",
|
31
32
|
"examples/set_deployment_template_href.rb",
|
32
33
|
"lib/rest_connection.rb",
|
33
|
-
"lib/rest_connection/mechanize_connection.rb",
|
34
34
|
"lib/rest_connection/rightscale/deployment.rb",
|
35
|
+
"lib/rest_connection/rightscale/ec2_security_group.rb",
|
36
|
+
"lib/rest_connection/rightscale/ec2_server_array.rb",
|
37
|
+
"lib/rest_connection/rightscale/ec2_ssh_key.rb",
|
35
38
|
"lib/rest_connection/rightscale/executable.rb",
|
36
39
|
"lib/rest_connection/rightscale/instance.rb",
|
40
|
+
"lib/rest_connection/rightscale/multi_cloud_image.rb",
|
37
41
|
"lib/rest_connection/rightscale/right_script.rb",
|
38
42
|
"lib/rest_connection/rightscale/rightscale_api_base.rb",
|
39
43
|
"lib/rest_connection/rightscale/rightscale_api_resources.rb",
|
40
44
|
"lib/rest_connection/rightscale/server.rb",
|
41
45
|
"lib/rest_connection/rightscale/server_template.rb",
|
42
46
|
"lib/rest_connection/rightscale/status.rb",
|
47
|
+
"lib/rest_connection/rightscale/tag.rb",
|
43
48
|
"lib/rest_connection/ssh_hax.rb",
|
44
49
|
"rest_connection.gemspec"
|
45
50
|
]
|
46
51
|
s.homepage = %q{http://github.com/jeremyd/rest_connection}
|
47
52
|
s.rdoc_options = ["--charset=UTF-8"]
|
48
53
|
s.require_paths = ["lib"]
|
49
|
-
s.rubygems_version = %q{1.3.
|
54
|
+
s.rubygems_version = %q{1.3.6}
|
50
55
|
s.summary = %q{lib for restful connections to the rightscale api}
|
51
56
|
s.test_files = [
|
52
57
|
"examples/console.rb",
|
53
58
|
"examples/dev_setup.rb",
|
54
|
-
"examples/mysql_dev_rollback.rb",
|
55
59
|
"examples/relaunch_deployment.rb",
|
56
60
|
"examples/restart_instance_agent.rb",
|
57
61
|
"examples/right_scale_ec2_instances_api_test.rb",
|
@@ -59,6 +63,7 @@ Gem::Specification.new do |s|
|
|
59
63
|
"examples/run_ebs_terminate.rb",
|
60
64
|
"examples/run_mysql_chef_sequence.rb",
|
61
65
|
"examples/run_php_chef_sequence.rb",
|
66
|
+
"examples/set_deployment_images.rb",
|
62
67
|
"examples/set_deployment_template_href.rb"
|
63
68
|
]
|
64
69
|
|
@@ -67,14 +72,11 @@ Gem::Specification.new do |s|
|
|
67
72
|
s.specification_version = 3
|
68
73
|
|
69
74
|
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
70
|
-
s.add_runtime_dependency(%q<mechanize>, [">= 0.9.3"])
|
71
75
|
s.add_runtime_dependency(%q<activesupport>, [">= 0"])
|
72
76
|
else
|
73
|
-
s.add_dependency(%q<mechanize>, [">= 0.9.3"])
|
74
77
|
s.add_dependency(%q<activesupport>, [">= 0"])
|
75
78
|
end
|
76
79
|
else
|
77
|
-
s.add_dependency(%q<mechanize>, [">= 0.9.3"])
|
78
80
|
s.add_dependency(%q<activesupport>, [">= 0"])
|
79
81
|
end
|
80
82
|
end
|
metadata
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rest_connection
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 0
|
8
|
+
- 2
|
9
|
+
version: 0.0.2
|
5
10
|
platform: ruby
|
6
11
|
authors:
|
7
12
|
- Jeremy Deininger
|
@@ -9,29 +14,21 @@ autorequire:
|
|
9
14
|
bindir: bin
|
10
15
|
cert_chain: []
|
11
16
|
|
12
|
-
date: 2010-
|
17
|
+
date: 2010-03-18 00:00:00 -07:00
|
13
18
|
default_executable:
|
14
19
|
dependencies:
|
15
|
-
- !ruby/object:Gem::Dependency
|
16
|
-
name: mechanize
|
17
|
-
type: :runtime
|
18
|
-
version_requirement:
|
19
|
-
version_requirements: !ruby/object:Gem::Requirement
|
20
|
-
requirements:
|
21
|
-
- - ">="
|
22
|
-
- !ruby/object:Gem::Version
|
23
|
-
version: 0.9.3
|
24
|
-
version:
|
25
20
|
- !ruby/object:Gem::Dependency
|
26
21
|
name: activesupport
|
27
|
-
|
28
|
-
|
29
|
-
version_requirements: !ruby/object:Gem::Requirement
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
30
24
|
requirements:
|
31
25
|
- - ">="
|
32
26
|
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 0
|
33
29
|
version: "0"
|
34
|
-
|
30
|
+
type: :runtime
|
31
|
+
version_requirements: *id001
|
35
32
|
description: provides rest_connection
|
36
33
|
email: jeremy@rubyonlinux.org
|
37
34
|
executables: []
|
@@ -45,6 +42,7 @@ files:
|
|
45
42
|
- Rakefile
|
46
43
|
- VERSION
|
47
44
|
- config/rest_api_config.yaml.sample
|
45
|
+
- examples/console.rb
|
48
46
|
- examples/dev_setup.rb
|
49
47
|
- examples/relaunch_deployment.rb
|
50
48
|
- examples/restart_instance_agent.rb
|
@@ -55,16 +53,20 @@ files:
|
|
55
53
|
- examples/run_php_chef_sequence.rb
|
56
54
|
- examples/set_deployment_template_href.rb
|
57
55
|
- lib/rest_connection.rb
|
58
|
-
- lib/rest_connection/mechanize_connection.rb
|
59
56
|
- lib/rest_connection/rightscale/deployment.rb
|
57
|
+
- lib/rest_connection/rightscale/ec2_security_group.rb
|
58
|
+
- lib/rest_connection/rightscale/ec2_server_array.rb
|
59
|
+
- lib/rest_connection/rightscale/ec2_ssh_key.rb
|
60
60
|
- lib/rest_connection/rightscale/executable.rb
|
61
61
|
- lib/rest_connection/rightscale/instance.rb
|
62
|
+
- lib/rest_connection/rightscale/multi_cloud_image.rb
|
62
63
|
- lib/rest_connection/rightscale/right_script.rb
|
63
64
|
- lib/rest_connection/rightscale/rightscale_api_base.rb
|
64
65
|
- lib/rest_connection/rightscale/rightscale_api_resources.rb
|
65
66
|
- lib/rest_connection/rightscale/server.rb
|
66
67
|
- lib/rest_connection/rightscale/server_template.rb
|
67
68
|
- lib/rest_connection/rightscale/status.rb
|
69
|
+
- lib/rest_connection/rightscale/tag.rb
|
68
70
|
- lib/rest_connection/ssh_hax.rb
|
69
71
|
- rest_connection.gemspec
|
70
72
|
has_rdoc: true
|
@@ -80,25 +82,26 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
80
82
|
requirements:
|
81
83
|
- - ">="
|
82
84
|
- !ruby/object:Gem::Version
|
85
|
+
segments:
|
86
|
+
- 0
|
83
87
|
version: "0"
|
84
|
-
version:
|
85
88
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
86
89
|
requirements:
|
87
90
|
- - ">="
|
88
91
|
- !ruby/object:Gem::Version
|
92
|
+
segments:
|
93
|
+
- 0
|
89
94
|
version: "0"
|
90
|
-
version:
|
91
95
|
requirements: []
|
92
96
|
|
93
97
|
rubyforge_project:
|
94
|
-
rubygems_version: 1.3.
|
98
|
+
rubygems_version: 1.3.6
|
95
99
|
signing_key:
|
96
100
|
specification_version: 3
|
97
101
|
summary: lib for restful connections to the rightscale api
|
98
102
|
test_files:
|
99
103
|
- examples/console.rb
|
100
104
|
- examples/dev_setup.rb
|
101
|
-
- examples/mysql_dev_rollback.rb
|
102
105
|
- examples/relaunch_deployment.rb
|
103
106
|
- examples/restart_instance_agent.rb
|
104
107
|
- examples/right_scale_ec2_instances_api_test.rb
|
@@ -106,4 +109,5 @@ test_files:
|
|
106
109
|
- examples/run_ebs_terminate.rb
|
107
110
|
- examples/run_mysql_chef_sequence.rb
|
108
111
|
- examples/run_php_chef_sequence.rb
|
112
|
+
- examples/set_deployment_images.rb
|
109
113
|
- examples/set_deployment_template_href.rb
|
@@ -1,29 +0,0 @@
|
|
1
|
-
#!/usr/bin/ruby
|
2
|
-
require 'rubygems'
|
3
|
-
require 'trollop'
|
4
|
-
require 'rest_connection'
|
5
|
-
require 'net/ssh'
|
6
|
-
|
7
|
-
opts = Trollop::options do
|
8
|
-
opt :deployment, "deployment nickname", :type => :string, :required => true
|
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
|
11
|
-
end
|
12
|
-
|
13
|
-
# find all servers in the deployment (the fast way)
|
14
|
-
deployment = Deployment.find_by_nickname_speed(opts[:deployment]).first
|
15
|
-
servers = deployment.servers_no_reload
|
16
|
-
servers = servers.select { |s| s.nickname =~ /#{opts[:only]}/ } if opts[:only]
|
17
|
-
|
18
|
-
servers.each do |s|
|
19
|
-
s.wait_for_operational_with_dns
|
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")
|
29
|
-
end
|
@@ -1,43 +0,0 @@
|
|
1
|
-
require 'mechanize'
|
2
|
-
require 'logger'
|
3
|
-
require 'uri'
|
4
|
-
|
5
|
-
module MechanizeConnection
|
6
|
-
module Connection
|
7
|
-
|
8
|
-
# creates/returns global mechanize agent
|
9
|
-
def agent
|
10
|
-
@@agent ||= WWW::Mechanize.new do |a|
|
11
|
-
a.log = Logger.new(STDOUT)
|
12
|
-
a.log.level = Logger::INFO
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
# creates/returns global mechanize agent
|
17
|
-
def self.agent
|
18
|
-
@@agent ||= WWW::Mechanize.new do |a|
|
19
|
-
a.log = Logger.new(STDOUT)
|
20
|
-
a.log.level = Logger::INFO
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
# login to rightscale dashboard /sessions/new using rest connection user and pass
|
25
|
-
def wind_monkey
|
26
|
-
base_url = URI.parse(connection.settings[:api_url])
|
27
|
-
base_url.path = "/"
|
28
|
-
if agent.cookie_jar.empty?(base_url)
|
29
|
-
agent.user_agent_alias = 'Mac Safari'
|
30
|
-
# Login
|
31
|
-
base_url = URI.parse(connection.settings[:api_url])
|
32
|
-
agent.user_agent_alias = 'Mac Safari'
|
33
|
-
# Login
|
34
|
-
base_url.path = "/sessions/new"
|
35
|
-
login_page = agent.get(base_url)
|
36
|
-
login_form = login_page.forms.first
|
37
|
-
login_form.email = connection.settings[:user]
|
38
|
-
login_form.password = connection.settings[:pass]
|
39
|
-
agent.submit(login_form, login_form.buttons.first)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|