rest_connection 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/README ADDED
@@ -0,0 +1,7 @@
1
+ RestConnection is a library designed to facilitate Restful connections to APIs using Basic auth and more. However! If you've done any API work you know that every API is different. The goal of RestConnection is to be as lean as possible and a EXAMPLE of how to use Net::HTTP in a restful way. Right now RestConnection uses JSON and Basic Auth, this is easy to change or expand on and it's written to give more control to the user of the library (You).
2
+
3
+ My hope is to include 'helper resources' for common API endpoints while maintaining a somewhat universal 'Connection' class that can be easily understood and modified to suit any Restful API needs. These resources will have a similar usage to ActiveResource.
4
+
5
+ The first API we will be supporting is the RightScale API.
6
+
7
+ I welcome any contributions or suggestions. Thanks!
data/Rakefile ADDED
@@ -0,0 +1,14 @@
1
+ require 'rubygems'
2
+ require 'jeweler'
3
+ Jeweler::Tasks.new do |gemspec|
4
+ gemspec.name = "rest_connection"
5
+ gemspec.summary = "lib for restful connections to the rightscale api"
6
+ gemspec.description = "provides rest_connection"
7
+ gemspec.email = "jeremy@rubyonlinux.org"
8
+ gemspec.homepage = "http://github.com/jeremyd/rest_connection"
9
+ gemspec.authors = ["Jeremy Deininger"]
10
+ gemspec.add_dependency('mechanize', '>= 0.9.3')
11
+ gemspec.add_dependency('activesupport')
12
+ end
13
+ Jeweler::GemcutterTasks.new
14
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
@@ -0,0 +1,7 @@
1
+ ---
2
+ :pass: myUltraSecurePasswordz
3
+ :user: myUserEmail@MyMailDomain.com
4
+ :api_url: https://my.rightscale.com/api/acct/00000000
5
+ :ssh_key: ~/.ssh/my-server-key
6
+ :common_headers:
7
+ X_API_VERSION: "1.0"
@@ -0,0 +1,10 @@
1
+ require 'rubygems'
2
+ require 'rest_connection'
3
+ require 'ruby-debug'
4
+
5
+ puts "entering debug session"
6
+ debugger
7
+ puts "console session commplete"
8
+
9
+
10
+
@@ -0,0 +1,26 @@
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 :growl, "use growl notification (string) when servers are all operational, requires ruby-growl gem", :type => :string, :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
+
21
+ Net::SSH.start(s.dns_name, 'root', :keys => ['~/.ssh/publish-test']) do |ssh|
22
+ puts "setting up devmode: dropbox::install && devmode::setup_cookbooks"
23
+ puts ssh.exec!("rs_run_recipe -n 'dropbox::install'")
24
+ puts ssh.exec!("rs_run_recipe -n 'devmode::setup_cookbooks'")
25
+ end
26
+ end
@@ -0,0 +1,29 @@
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
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/ruby
2
+ require 'rubygems'
3
+ require 'trollop'
4
+ require 'rest_connection'
5
+
6
+ opts = Trollop::options do
7
+ opt :deployment, "deployment nickname", :type => :string, :required => false
8
+ 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
9
+ opt :growl, "use growl notification (string) when servers are all operational, requires ruby-growl gem", :type => :string, :required => false
10
+ opt :id, "deployment id", :type => :string, :required => false
11
+ end
12
+
13
+ # find all servers in the deployment (the fast way)
14
+ if opts[:id]
15
+ deployment = Deployment.find_by_id(opts[:id])
16
+ else
17
+ deployment = Deployment.find_by_nickname_speed(opts[:deployment]).first
18
+ end
19
+ servers = deployment.servers_no_reload
20
+ servers = servers.select { |s| s.nickname =~ /#{opts[:only]}/ } if opts[:only]
21
+ servers.each do |s|
22
+ # send stop
23
+ s.relaunch
24
+ end
25
+
26
+ # wait for termination
27
+ #servers.each do |s|
28
+ # s.wait_for_state('stopped')
29
+ #end
30
+
31
+ # relaunch
32
+ #servers.each do |s|
33
+ # s.start
34
+ #end
35
+
36
+ #if opts[:growl]
37
+ # require 'ruby-growl'
38
+ # servers.each do |s|
39
+ # s.wait_for_state('booting')
40
+ # end
41
+ # g = Growl.new "localhost", "ruby-growl",
42
+ # ["ruby-growl Notification"]
43
+ #g.notify "ruby-growl Notification", "It Came From Ruby-Growl",
44
+ # "Greetings!"
45
+ #end
@@ -0,0 +1,29 @@
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
@@ -0,0 +1,51 @@
1
+ require 'rubygems'
2
+ require 'rest_connection'
3
+ require 'spec'
4
+ require '/var/spool/ec2/user-data'
5
+
6
+ describe Instance, "run this from an ec2_instance" do
7
+ before(:all) do
8
+ @this_instance = Instance.new
9
+ @this_instance.connection.settings[:api_url] = ENV['RS_API_URL']
10
+ @this_instance.connection.settings[:common_headers] = { 'X_API_VERSION' => '1.0' }
11
+ # when tests fail, we need this to ensure a fresh run
12
+ x = @this_instance.detach_ebs_volume(:device => '/dev/sdp')
13
+ sleep 10 if x
14
+ end
15
+ it "should create,attach,detach,delete an ebs_volume" do
16
+ sleep 2
17
+ result = @this_instance.create_ebs_volume({
18
+ :nickname => "ebs_test_candelete#{rand(1000)}",
19
+ :description => "created by ebs integration",
20
+ :size => "1" })
21
+ vol_aws_id = result['aws_id']
22
+ vol_aws_id.should_not == nil
23
+ @this_instance.attach_ebs_volume(:aws_id => result['aws_id'], :device => "/dev/sdp")
24
+ sleep 10
25
+ @this_instance.create_ebs_snapshot(:aws_id => vol_aws_id)
26
+ sleep 5
27
+ @this_instance.detach_ebs_volume(:device => '/dev/sdp')
28
+ sleep 10
29
+ @this_instance.delete_ebs_volume(:aws_id => vol_aws_id)
30
+ end
31
+
32
+ end
33
+
34
+ =begin
35
+ #ROUTES REFERENCE GUIDE
36
+ map.api_inst_resources 'ec2_instances', :member => { :find_latest_ebs_snapshot => :get,
37
+ :find_ebs_snapshots => :get,
38
+ :create_ebs_volume_from_snap => :post,
39
+ :create_ebs_volume => :post,
40
+ :delete_ebs_volume => :delete,
41
+ :detach_ebs_volume => :put,
42
+ :attach_ebs_volume => :put,
43
+ :cleanup_ebs_snapshots => :put,
44
+ :create_ebs_snapshot => :post,
45
+ :update_ebs_snapshot => :put,
46
+ :create_ebs_backup => :post,
47
+ :find_latest_ebs_backup => :get,
48
+ :cleanup_ebs_backups => :put,
49
+ :set_custom_lodgement => :put # should we be using :post or :put ???
50
+ }
51
+ =end
@@ -0,0 +1,95 @@
1
+ #!/usr/bin/ruby
2
+ require 'rubygems'
3
+ require 'trollop'
4
+ require 'rest_connection'
5
+ #
6
+ # EBS regression test
7
+ #
8
+ # prerequirements: run the macro for EBS stripe deployment
9
+ # enter the deployment name below
10
+ #
11
+
12
+ opts = Trollop::options do
13
+ opt :deployment, "deployment nickname", :type => :string, :required => true
14
+ end
15
+
16
+ #ebs_deployment = Deployment.find_by_nickname_speed("Regression Test - MySQL -STRIPE").first
17
+ ebs_deployment = Deployment.find_by_nickname_speed(opts[:deployment]).first
18
+
19
+ # select servers by nickname!
20
+ mysql_s3 = ebs_deployment.servers.detect { |s| s.nickname =~ /MySQL S3 US db1/i }
21
+ mysql_db1 = ebs_deployment.servers.detect { |s| s.nickname =~ /MySQL EBS db1/i }
22
+ mysql_db2 = ebs_deployment.servers.detect { |s| s.nickname =~ /MySQL EBS Stripe db1/i }
23
+ mysql_db3 = ebs_deployment.servers.detect { |s| s.nickname =~ /MySQL EBS Stripe db2/i }
24
+
25
+ # we must reload, so the server can populate it's state. we took a shortcut
26
+ # by grabbing the servers from the deployment's json (the rightscale default response)
27
+ mysql_s3.reload
28
+ mysql_db1.reload
29
+ mysql_db2.reload
30
+ mysql_db3.reload
31
+
32
+ # tweak: (this is closer to an actual user story) setup mysql_db1 for regular EBS
33
+ # the rest of the deployment is normally set to text:2
34
+ # mysql_db1 is [rev 13] so it needs the old input name
35
+
36
+ #mysql_db1.set_input("OPT_EBS_STRIPE_COUNT", "ignore:$ignore")
37
+ #mysql_db1.set_input("DB_EBS_PREFIX", "text:shouldnotmatter-candelete652")
38
+ #mysql_db1.set_input("DB_LINEAGE_NAME", "text:shouldnotmatter-candelete652")
39
+ #mysql_db2.set_input("DB_LINEAGE_NAME", "text:shouldnotmatter-candelete652")
40
+ #mysql_db3.set_input("DB_LINEAGE_NAME", "text:shouldnotmatter-candelete652")
41
+
42
+ # launch all
43
+ mysql_s3.start
44
+ mysql_db1.start
45
+ mysql_db2.start
46
+ mysql_db3.start
47
+
48
+ # wait for operational
49
+ mysql_s3.wait_for_state('operational')
50
+ mysql_db1.wait_for_state('operational')
51
+ mysql_db2.wait_for_state('operational')
52
+ mysql_db3.wait_for_state('operational')
53
+
54
+ sleep 10 #make sure they are operational
55
+
56
+ # we need better api support, but for now we can get our RightScripts from info.yml on an instance (or in the current dir)
57
+ template_scripts = RightScript.from_instance_info
58
+
59
+ # scripts from EBS [rev13]
60
+ slave_init_non_ebs_rev4 = RightScript.new('href' => 'right_scripts/45320')
61
+ slave_init_non_ebs_v1_rev6 = RightScript.new('href' => 'right_scripts/41484')
62
+ restore_rev4 = RightScript.new('href' => 'right_scripts/45319')
63
+
64
+ # see how easy this is to cherry pick the scripts by name? this means no resetting of ids across different templates
65
+ restore_script = template_scripts.detect { |script| script.name =~ /restore/i }
66
+ slave_init_non_ebs = template_scripts.detect { |script| script.name =~ /DB EBS slave init from non-EBS master v1/ }
67
+ slave_init_non_stripe = template_scripts.detect { |script| script.name =~ /DB EBS stripe slave init from EBS non-stripe master/i }
68
+ promote = template_scripts.detect { |script| script.name =~ /promote/i }
69
+ slave_init = template_scripts.detect { |script| script.name == "DB EBS slave init (Stripe alpha)" }
70
+ backup = template_scripts.detect { |script| script.name =~ /DB EBS backup/i }
71
+
72
+ # breathing room is needed below *only to let the servers
73
+ # settle after fail-over operations. wait_for_completed returns
74
+ # when the right_script status is 'success' or 'fail'
75
+
76
+ status = mysql_db1.run_script(slave_init_non_ebs_v1_rev6)
77
+ status = mysql_db1.run_script(slave_init_non_ebs_rev4)
78
+ status.wait_for_completed(mysql_db1.audit_link)
79
+ sleep 220 #breathing room
80
+
81
+ status = mysql_db1.run_script(promote)
82
+ status.wait_for_completed(mysql_db1.audit_link)
83
+ sleep 220 #breathing room
84
+
85
+ status = mysql_db2.run_script(slave_init_non_stripe)
86
+ status.wait_for_completed(mysql_db2.audit_link)
87
+ sleep 220 # breathing room
88
+
89
+ status = mysql_db2.run_script(promote)
90
+ status.wait_for_completed(mysql_db2.audit_link)
91
+ sleep 220 #breathing room
92
+
93
+ status = mysql_db3.run_script(slave_init)
94
+ status.wait_for_completed(mysql_db3.audit_link)
95
+ puts "done!"
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/ruby
2
+ require 'rubygems'
3
+ require 'trollop'
4
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'rightscale_api_resources')
5
+
6
+ #
7
+ # EBS regression test
8
+ #
9
+ # prerequirements: run the macro for EBS stripe deployment
10
+ # enter the deployment name below
11
+ #
12
+
13
+ opts = Trollop::options do
14
+ opt :deployment, "deployment nickname", :type => :string, :required => true
15
+ end
16
+
17
+ ebs_deployment = Deployment.find_by_nickname_speed(opts[:deployment]).first
18
+ # select servers by nickname!
19
+ mysql_s3 = ebs_deployment.servers.detect { |s| s.nickname =~ /MySQL S3 US db1/i }
20
+ mysql_db1 = ebs_deployment.servers.detect { |s| s.nickname =~ /MySQL EBS db1/i }
21
+ mysql_db2 = ebs_deployment.servers.detect { |s| s.nickname =~ /MySQL EBS Stripe db1/i }
22
+ mysql_db3 = ebs_deployment.servers.detect { |s| s.nickname =~ /MySQL EBS Stripe db2/i }
23
+
24
+ # we must reload, so the server can populate it's state
25
+ mysql_s3.reload
26
+ mysql_db1.reload
27
+ mysql_db2.reload
28
+ mysql_db3.reload
29
+
30
+ # stop all
31
+ mysql_s3.stop
32
+ mysql_db1.stop
33
+ mysql_db2.stop
34
+ mysql_db3.stop
35
+
36
+ # wait for stopped
37
+ mysql_s3.wait_for_state('stopped')
38
+ mysql_db1.wait_for_state('stopped')
39
+ mysql_db2.wait_for_state('stopped')
40
+ mysql_db3.wait_for_state('stopped')
@@ -0,0 +1,43 @@
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 => false
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 :id, "deployment id", :type => :string, :required => false
11
+ end
12
+
13
+ # find all servers in the deployment (the fast way)
14
+ if opts[:id]
15
+ deployment = Deployment.find_by_id(opts[:id])
16
+ else
17
+ deployment = Deployment.find_by_nickname_speed(opts[:deployment]).first
18
+ end
19
+ servers = deployment.servers_no_reload
20
+ servers = servers.select { |s| s.nickname =~ /#{opts[:only]}/ } if opts[:only]
21
+
22
+ raise "need at least 2 servers to start, only have: #{servers.size}" if servers.size < 2
23
+
24
+ # wait for servers to be ready
25
+ servers.each do |s|
26
+ s.start
27
+ while(1)
28
+ puts "waiting for dns-name for #{s.nickname}"
29
+ break if s['dns-name'] && !s['dns-name'].empty?
30
+ s.reload
31
+ sleep 2
32
+ end
33
+ puts "DNS: #{s['dns-name']}"
34
+
35
+ s.wait_for_state('operational')
36
+ end
37
+
38
+ servers[0].run_recipe("db_mysql::do_restore_and_become_master")
39
+
40
+ sleep(10)
41
+
42
+ servers[1].run_recipe("db_mysql::do_init_slave")
43
+ servers[1].run_recipe("db_mysql::do_promote_to_master")
@@ -0,0 +1,109 @@
1
+ #!/usr/bin/ruby
2
+ require 'rubygems'
3
+ require 'trollop'
4
+ require 'rest_connection'
5
+ require 'net/ssh'
6
+
7
+ def run_recipe(recipe, host_dns, continue=false)
8
+ STDOUT.puts "sshing to #{host_dns}"
9
+ result = nil
10
+ tail_command ="tail -f -n1 /var/log/messages"
11
+ expect = /RightLink.*RS> ([completed|failed]+: < #{recipe} >)/
12
+
13
+ Net::SSH.start(host_dns, 'root', :keys => ['~/.ssh/publish-test']) do |ssh|
14
+ STDOUT.puts ssh.exec!("rs_run_recipe -n '#{recipe}'")
15
+ log_channel = ssh.open_channel do |ch|
16
+ ch.exec tail_command do |ch, success|
17
+ raise "could not execute command" unless success
18
+ # "on_data" is called when the process writes something to stdout
19
+ ch.on_data do |c, data|
20
+ STDOUT.print data
21
+ if data =~ expect
22
+ STDOUT.puts "FOUND EXPECTED DATA, closing channel"
23
+ result = $1
24
+ end
25
+ end
26
+ # "on_extended_data" is called when the process writes something to stderr
27
+ ch.on_extended_data do |c, type, data|
28
+ STDERR.print data
29
+ end
30
+ ch.on_close do
31
+ STDOUT.puts "closed channel"
32
+ end
33
+ ch.on_process do |c|
34
+ if result
35
+ STDOUT.puts "attempting close"
36
+ ch.close
37
+ ssh.exec("killall tail")
38
+ end
39
+ end
40
+ end
41
+ end
42
+ log_channel.wait
43
+ end
44
+ raise "FATAL: halting execution, script #{result}" if result.include?('failed') && continue == false
45
+ return result
46
+ end
47
+
48
+ def spot_check(command, host_dns, &block)
49
+ Net::SSH.start(host_dns, 'root', :keys => ['~/.ssh/publish-test']) do |ssh|
50
+ result = ssh.exec!(command)
51
+ yield result
52
+ end
53
+ end
54
+
55
+ opts = Trollop::options do
56
+ opt :deployment, "deployment nickname", :type => :string, :required => false
57
+ opt :id, "deployment id", :type => :string, :required => false
58
+ 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
59
+ end
60
+ if opts[:id]
61
+ deployment = Deployment.find_by_id(opts[:id])
62
+ else
63
+ deployment = Deployment.find_by_nickname_speed(opts[:deployment]).first
64
+ end
65
+ servers = deployment.servers_no_reload
66
+ servers = servers.select { |s| s.nickname =~ /#{opts[:only]}/ } if opts[:only]
67
+
68
+ raise "need at least 4 servers to start, only have: #{servers.size}" if servers.size < 4
69
+ # wait for servers to be ready
70
+ servers.each do |s|
71
+ while(1)
72
+ puts "waiting for dns-name for #{s.nickname}"
73
+ break if s['dns-name'] && !s['dns-name'].empty?
74
+ s.reload
75
+ sleep 2
76
+ end
77
+ puts "DNS: #{s['dns-name']}"
78
+
79
+ s.wait_for_state('operational')
80
+ end
81
+
82
+ servers.each do |s|
83
+ puts run_recipe("lb_haproxy::do_attach_request", s.dns_name)
84
+ end
85
+ sleep 20
86
+
87
+ a_frontend = servers.detect {|d| d.nickname.include?("FE")}
88
+ a_frontend.reload
89
+ raise "couldn't find a frontend with FE in the nickname!" unless a_frontend
90
+ puts a_frontend.dns_name
91
+ spot_check("cat /home/haproxy/rightscale_lb.cfg |grep server|grep -v '#'|wc -l", a_frontend.dns_name) do |result|
92
+ puts "found attached servers: #{result}"
93
+ raise "not enough servers #{result}" unless result.to_i == 4
94
+ end
95
+
96
+ servers.each do |s|
97
+ run_recipe("app_php::do_update_code", s.dns_name)
98
+ end
99
+
100
+ servers.each do |s|
101
+ run_recipe("lb_haproxy::do_detach_request", s.dns_name)
102
+ end
103
+ sleep 20
104
+ spot_check("cat /home/haproxy/rightscale_lb.cfg |grep server|grep -v '#'|wc -l", a_frontend.dns_name) do |result|
105
+ puts "found attached servers: #{result}"
106
+ raise "should be zero servers but was #{result}" unless result.to_i == 0
107
+ end
108
+
109
+