rest_connection 0.0.3 → 0.0.4
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 +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
|