rest_connection 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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