rest_connection 0.0.1

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.
@@ -0,0 +1,22 @@
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
+ require 'rest_connection/rightscale/executable'
17
+ require 'rest_connection/rightscale/server'
18
+ require 'rest_connection/rightscale/deployment'
19
+ require 'rest_connection/rightscale/status'
20
+ require 'rest_connection/rightscale/server_template'
21
+ require 'rest_connection/rightscale/right_script'
22
+ require 'rest_connection/rightscale/instance'
@@ -0,0 +1,121 @@
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
+ require 'rest_connection/ssh_hax'
17
+
18
+ class Server < RightScale::Api::Base
19
+ include SshHax
20
+ def wait_for_state(st)
21
+ reload
22
+ connection.logger("#{nickname} is #{self.state}")
23
+ while(1)
24
+ return true if state == st
25
+ raise "FATAL error, this server is stranded and needs to be #{st}: #{nickname}, see audit: #{self.audit_link}" if state.include?('stranded')
26
+ sleep 5
27
+ connection.logger("waiting for server #{nickname} to go #{st}, state is #{state}")
28
+ reload
29
+ end
30
+ end
31
+
32
+ def wait_for_operational_with_dns
33
+ wait_for_state("operational")
34
+ while(1)
35
+ connection.logger "waiting for dns-name for #{self.nickname}"
36
+ break if self['dns-name'] && !self['dns-name'].empty?
37
+ self.settings
38
+ sleep 2
39
+ end
40
+ connection.logger "got DNS: #{self['dns-name']}"
41
+ end
42
+
43
+ def audit_link
44
+ # proof of concept for now
45
+ server_id = self.href.split(/\//).last
46
+ "https://my.rightscale.com/servers/#{server_id}#audit_entries"
47
+ end
48
+
49
+ def start
50
+ if self.state == "stopped"
51
+ t = URI.parse(self.href)
52
+ return connection.post(t.path + '/start')
53
+ else
54
+ connection.logger("WARNING: was in #{self.state} so skiping start call")
55
+ end
56
+ end
57
+
58
+ def stop
59
+ if self.state != "stopped"
60
+ t = URI.parse(self.href)
61
+ connection.post(t.path + '/stop')
62
+ else
63
+ connection.logger("WARNING: was in #{self.state} so skiping stop call")
64
+ end
65
+ end
66
+
67
+ def run_script(script)
68
+ serv_href = URI.parse(self.href)
69
+ location = connection.post(serv_href.path + '/run_script', :right_script => script.href)
70
+ Status.new('href' => location)
71
+ end
72
+
73
+ def set_input(name, value)
74
+ serv_href = URI.parse(self.href)
75
+ connection.put(serv_href.path, :server => {:parameters => {name.to_sym => value} })
76
+ end
77
+
78
+ def self.create(opts)
79
+ location = connection.post("servers", :server => opts)
80
+ Server.new('href' => location)
81
+ end
82
+
83
+ def set_template(href)
84
+ serv_href = URI.parse(self.href)
85
+ connection.put(serv_href.path, :server => {:server_template_href => href})
86
+ end
87
+
88
+ def settings
89
+ serv_href = URI.parse(self.href)
90
+ @params.merge! connection.get(serv_href.path + "/settings")
91
+ end
92
+
93
+ def monitors
94
+ serv_href = URI.parse(self.href)
95
+ @params.merge! connection.get(serv_href.path + "/monitors")
96
+ end
97
+
98
+ def reboot
99
+ serv_href = URI.parse(self.href)
100
+ connection.post(serv_href.path + "/reboot")
101
+ end
102
+
103
+ def relaunch
104
+ unless state == "stopped"
105
+ wind_monkey
106
+ server_id = self.href.split(/\//).last
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
119
+ end
120
+ end
121
+
@@ -0,0 +1,31 @@
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 ServerTemplate < RightScale::Api::Base
17
+ def initialize(params)
18
+ @params = params
19
+ fetch_executables
20
+ end
21
+
22
+ def fetch_executables
23
+ my_href = URI.parse(self.href)
24
+ #@params.merge! :executables =? connection.get(my_href.path + "/executables")
25
+ ex = []
26
+ connection.get(my_href.path + "/executables").each do |e|
27
+ ex << Executable.new(e)
28
+ end
29
+ @params["executables"] = ex
30
+ end
31
+ end
@@ -0,0 +1,26 @@
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 Status < RightScale::Api::Base
17
+ def wait_for_completed(audit_link = "no audit link available")
18
+ while(1)
19
+ reload
20
+ return true if self.state == "completed"
21
+ raise "FATAL error, script failed\nSee Audit: #{audit_link}" if self.state == 'failed'
22
+ sleep 5
23
+ connection.logger("querying status of right_script.. got: #{self.state}")
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,141 @@
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
+ require 'net/ssh'
18
+
19
+ # This is a mixin module run_recipes until api support is ready for checking result of recipe run.
20
+ # The mixin typically used from Server#run_recipe
21
+ module SshHax
22
+ # recipe can be either a String, or an Executable
23
+ # host_dns is optional and will default to objects self.dns_name
24
+ def run_recipe(recipe, host_dns=self.dns_name)
25
+ if recipe.is_a?(Executable)
26
+ recipe = recipe.recipe
27
+ 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
+ status = nil
35
+ result = nil
36
+ output = ""
37
+ tail_command ="tail -f -n1 /var/log/messages"
38
+ expect = /RightLink.*RS> ([completed|failed]+: < #{recipe} >)/
39
+ run_this = "rs_run_recipe -n '#{recipe}'"
40
+ Net::SSH.start(host_dns, 'root', :keys => [ssh_key]) do |ssh|
41
+ cmd_channel = ssh.open_channel do |ch1|
42
+ ch1.on_request('exit-status') do |ch, data|
43
+ status = data.read_long
44
+ end
45
+ ch1.exec(run_this) do |ch2, success|
46
+ unless success
47
+ output = "ERROR: SSH cmd failed to exec"
48
+ status = 1
49
+ end
50
+ ch2.on_data do |ch, data|
51
+ output += data
52
+ end
53
+ ch2.on_extended_data do |ch, type, data|
54
+ output += data
55
+ end
56
+
57
+ end
58
+ end
59
+ log_channel = ssh.open_channel do |ch2|
60
+ ch2.exec tail_command do |ch, success|
61
+ raise "could not execute command" unless success
62
+ # "on_data" is called when the process writes something to stdout
63
+ ch.on_data do |c, data|
64
+ output += data
65
+ if data =~ expect
66
+ result = $1
67
+ end
68
+ end
69
+ # "on_extended_data" is called when the process writes something to stderr
70
+ ch.on_extended_data do |c, type, data|
71
+ #STDERR.print data
72
+ end
73
+ ch.on_close do
74
+ end
75
+ ch.on_process do |c|
76
+ if result
77
+ ch.close
78
+ ssh.exec("killall tail")
79
+ end
80
+ end
81
+ end
82
+ end
83
+ cmd_channel.wait
84
+ log_channel.wait
85
+ end
86
+ success = result.include?('completed')
87
+ connection.logger output
88
+ connection.logger "Converge failed. See server audit: #{self.audit_link}" unless success
89
+ return {:status => success, :output => output}
90
+ end
91
+
92
+ def spot_check(command, ssh_key="~/.ssh/publish-test", host_dns=self.dns_name, &block)
93
+ ssh_key = connection.settings[:ssh_key] if connection.settings[:ssh_key]
94
+ connection.logger "SSHing to #{host_dns} using key #{ssh_key}"
95
+ Net::SSH.start(host_dns, 'root', :keys => [ssh_key]) do |ssh|
96
+ result = ssh.exec!(command)
97
+ yield result
98
+ end
99
+ end
100
+
101
+ # returns true or false based on command success
102
+ def spot_check_command?(command, ssh_key="~/.ssh/publish-test", host_dns=self.dns_name)
103
+ ssh_key = connection.settings[:ssh_key] if connection.settings[:ssh_key]
104
+ results = spot_check_command(command, ssh_key, host_dns)
105
+ return results[:status] == 0
106
+ end
107
+
108
+
109
+ # returns hash of exit_status and output from command
110
+ def spot_check_command(command, ssh_key="~/.ssh/publish-test", host_dns=self.dns_name)
111
+ ssh_key = connection.settings[:ssh_key] if connection.settings[:ssh_key]
112
+ connection.logger "SSHing to #{host_dns} using key #{ssh_key}"
113
+ status = nil
114
+ output = ""
115
+ Net::SSH.start(host_dns, 'root', :keys => [ssh_key]) do |ssh|
116
+ cmd_channel = ssh.open_channel do |ch1|
117
+ ch1.on_request('exit-status') do |ch, data|
118
+ status = data.read_long
119
+ end
120
+ output += "Running: #{command}\n"
121
+ ch1.exec(command) do |ch2, success|
122
+ unless success
123
+ output = "ERROR: SSH cmd failed to exec"
124
+ status = 1
125
+ end
126
+ ch2.on_data do |ch, data|
127
+ output += data
128
+ end
129
+ ch2.on_extended_data do |ch, type, data|
130
+ output += data
131
+ end
132
+ end
133
+ end
134
+ end
135
+ connection.logger output
136
+ return {:status => status, :output => output}
137
+ end
138
+
139
+ end
140
+
141
+
@@ -0,0 +1,81 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{rest_connection}
8
+ s.version = "0.0.1"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Jeremy Deininger"]
12
+ s.date = %q{2010-02-12}
13
+ s.description = %q{provides rest_connection}
14
+ s.email = %q{jeremy@rubyonlinux.org}
15
+ s.extra_rdoc_files = [
16
+ "README"
17
+ ]
18
+ s.files = [
19
+ "README",
20
+ "Rakefile",
21
+ "VERSION",
22
+ "config/rest_api_config.yaml.sample",
23
+ "examples/dev_setup.rb",
24
+ "examples/relaunch_deployment.rb",
25
+ "examples/restart_instance_agent.rb",
26
+ "examples/right_scale_ec2_instances_api_test.rb",
27
+ "examples/run_ebs_sequence.rb",
28
+ "examples/run_ebs_terminate.rb",
29
+ "examples/run_mysql_chef_sequence.rb",
30
+ "examples/run_php_chef_sequence.rb",
31
+ "examples/set_deployment_template_href.rb",
32
+ "lib/rest_connection.rb",
33
+ "lib/rest_connection/mechanize_connection.rb",
34
+ "lib/rest_connection/rightscale/deployment.rb",
35
+ "lib/rest_connection/rightscale/executable.rb",
36
+ "lib/rest_connection/rightscale/instance.rb",
37
+ "lib/rest_connection/rightscale/right_script.rb",
38
+ "lib/rest_connection/rightscale/rightscale_api_base.rb",
39
+ "lib/rest_connection/rightscale/rightscale_api_resources.rb",
40
+ "lib/rest_connection/rightscale/server.rb",
41
+ "lib/rest_connection/rightscale/server_template.rb",
42
+ "lib/rest_connection/rightscale/status.rb",
43
+ "lib/rest_connection/ssh_hax.rb",
44
+ "rest_connection.gemspec"
45
+ ]
46
+ s.homepage = %q{http://github.com/jeremyd/rest_connection}
47
+ s.rdoc_options = ["--charset=UTF-8"]
48
+ s.require_paths = ["lib"]
49
+ s.rubygems_version = %q{1.3.5}
50
+ s.summary = %q{lib for restful connections to the rightscale api}
51
+ s.test_files = [
52
+ "examples/console.rb",
53
+ "examples/dev_setup.rb",
54
+ "examples/mysql_dev_rollback.rb",
55
+ "examples/relaunch_deployment.rb",
56
+ "examples/restart_instance_agent.rb",
57
+ "examples/right_scale_ec2_instances_api_test.rb",
58
+ "examples/run_ebs_sequence.rb",
59
+ "examples/run_ebs_terminate.rb",
60
+ "examples/run_mysql_chef_sequence.rb",
61
+ "examples/run_php_chef_sequence.rb",
62
+ "examples/set_deployment_template_href.rb"
63
+ ]
64
+
65
+ if s.respond_to? :specification_version then
66
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
67
+ s.specification_version = 3
68
+
69
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
70
+ s.add_runtime_dependency(%q<mechanize>, [">= 0.9.3"])
71
+ s.add_runtime_dependency(%q<activesupport>, [">= 0"])
72
+ else
73
+ s.add_dependency(%q<mechanize>, [">= 0.9.3"])
74
+ s.add_dependency(%q<activesupport>, [">= 0"])
75
+ end
76
+ else
77
+ s.add_dependency(%q<mechanize>, [">= 0.9.3"])
78
+ s.add_dependency(%q<activesupport>, [">= 0"])
79
+ end
80
+ end
81
+
metadata ADDED
@@ -0,0 +1,109 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rest_connection
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Jeremy Deininger
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-02-12 00:00:00 -08:00
13
+ default_executable:
14
+ 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
+ - !ruby/object:Gem::Dependency
26
+ name: activesupport
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: "0"
34
+ version:
35
+ description: provides rest_connection
36
+ email: jeremy@rubyonlinux.org
37
+ executables: []
38
+
39
+ extensions: []
40
+
41
+ extra_rdoc_files:
42
+ - README
43
+ files:
44
+ - README
45
+ - Rakefile
46
+ - VERSION
47
+ - config/rest_api_config.yaml.sample
48
+ - examples/dev_setup.rb
49
+ - examples/relaunch_deployment.rb
50
+ - examples/restart_instance_agent.rb
51
+ - examples/right_scale_ec2_instances_api_test.rb
52
+ - examples/run_ebs_sequence.rb
53
+ - examples/run_ebs_terminate.rb
54
+ - examples/run_mysql_chef_sequence.rb
55
+ - examples/run_php_chef_sequence.rb
56
+ - examples/set_deployment_template_href.rb
57
+ - lib/rest_connection.rb
58
+ - lib/rest_connection/mechanize_connection.rb
59
+ - lib/rest_connection/rightscale/deployment.rb
60
+ - lib/rest_connection/rightscale/executable.rb
61
+ - lib/rest_connection/rightscale/instance.rb
62
+ - lib/rest_connection/rightscale/right_script.rb
63
+ - lib/rest_connection/rightscale/rightscale_api_base.rb
64
+ - lib/rest_connection/rightscale/rightscale_api_resources.rb
65
+ - lib/rest_connection/rightscale/server.rb
66
+ - lib/rest_connection/rightscale/server_template.rb
67
+ - lib/rest_connection/rightscale/status.rb
68
+ - lib/rest_connection/ssh_hax.rb
69
+ - rest_connection.gemspec
70
+ has_rdoc: true
71
+ homepage: http://github.com/jeremyd/rest_connection
72
+ licenses: []
73
+
74
+ post_install_message:
75
+ rdoc_options:
76
+ - --charset=UTF-8
77
+ require_paths:
78
+ - lib
79
+ required_ruby_version: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: "0"
84
+ version:
85
+ required_rubygems_version: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: "0"
90
+ version:
91
+ requirements: []
92
+
93
+ rubyforge_project:
94
+ rubygems_version: 1.3.5
95
+ signing_key:
96
+ specification_version: 3
97
+ summary: lib for restful connections to the rightscale api
98
+ test_files:
99
+ - examples/console.rb
100
+ - examples/dev_setup.rb
101
+ - examples/mysql_dev_rollback.rb
102
+ - examples/relaunch_deployment.rb
103
+ - examples/restart_instance_agent.rb
104
+ - examples/right_scale_ec2_instances_api_test.rb
105
+ - examples/run_ebs_sequence.rb
106
+ - examples/run_ebs_terminate.rb
107
+ - examples/run_mysql_chef_sequence.rb
108
+ - examples/run_php_chef_sequence.rb
109
+ - examples/set_deployment_template_href.rb