right_api_helper 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md ADDED
@@ -0,0 +1,3 @@
1
+ CHANGELOG
2
+ =========
3
+ `20140516` - added provisioner class to help with launching servers.
@@ -0,0 +1,226 @@
1
+ #
2
+ # Author: cary@rightscale.com
3
+ # Copyright 2014 RightScale, Inc.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
18
+ # Basic helper gem for provisioning IaaS servers using the RightScale API.
19
+ #
20
+ # It is intended to be used by ruby applications that need to launch servers.
21
+ #
22
+ # ## Usage
23
+ #
24
+ # Example:
25
+ #
26
+ # require "right_api_helper"
27
+ #
28
+ # # initialize rightscale provisioner
29
+ # @rightscale =
30
+ # RightApiHelper::Provisioner.new("my_user@somewhere.com", // user
31
+ # "my_rightscale_password", // password
32
+ # 12345) // rightscale account ID
33
+ #
34
+ # # setup some inputs
35
+ # server_inputs = {
36
+ # # open up port 8000
37
+ # "sys_firewall/rule/enable" => "text:enable",
38
+ # "sys_firewall/rule/port" => "text:8000",
39
+ # "sys_firewall/rule/ip_address" => "text:any",
40
+ # "sys_firewall/rule/protocol" => "text:tcp"
41
+ # }
42
+ #
43
+ # # provision a RightScale managed server from a ServerTemplate
44
+ # @rightscale.provision("My Cool Server",
45
+ # "ServerTemplate for Linux (v13.5)", // name or ID
46
+ # "AWS US-East",
47
+ # "My Deployment",
48
+ # server_inputs)
49
+ #
50
+ # # wait for server to be ready
51
+ # state = @rightscale.wait_for_operational
52
+ #
53
+ # # Do stuff with your brand new server...
54
+
55
+
56
+ module RightApiHelper
57
+
58
+ #
59
+ # This is the main class to use to create a server on the RightScale platform.
60
+ # Use the {#provision} method to create and launch
61
+ # the server.
62
+ #
63
+ # The other methods are for checking server state and gathering information
64
+ # once the server is operational.
65
+ #
66
+ class Provisioner < Base
67
+
68
+ RETRY_DELAY = 10 # seconds
69
+ BAD_STATES_UP = [ "stranded", "terminated"]
70
+
71
+ def initialize(right_api_client)
72
+ super(right_api_client)
73
+ @api_shim = RightApiHelper::API15.new(right_api_client)
74
+ end
75
+
76
+ def connection_url
77
+ raise "No server provisioned. No connection URL available." unless @server
78
+ unless @data_request_url
79
+ user_data = @server.current_instance.show(:view => "full").user_data
80
+ @data_request_url = @api_shim.data_request_url(user_data)
81
+ @logger.debug "Data Request URL: #{@data_request_url}"
82
+ end
83
+ @data_request_url
84
+ end
85
+
86
+ # Provision a server using RightScale
87
+ #
88
+ # @param server_name [String] the name to give the server that will be
89
+ # created.
90
+ # @param server_template [String] the name or ID of the ServerTemplate to
91
+ # create the server from.
92
+ # @param cloud_name [String] name of cloud to provision on.
93
+ # @param deployment_name [String] name of deployment to add the server to.
94
+ # This will be created if it does not exist.
95
+ # @param inputs [Array] An array of {Input} objects.
96
+ # @param ssh_key_id [String] The resource_uuid of an ssh key from the
97
+ # RightScale dashboard. Only required on EC2 and Eucalyptus.
98
+ # @param secgroup_id [Array] An array of security group IDs to place the
99
+ # server in.
100
+ #
101
+ # @raise {RightApiProvisionException} if anything
102
+ # goes wrong
103
+ def provision(servertemplate,
104
+ server_name = "default",
105
+ cloud_name = "ec2",
106
+ deployment_name = "default",
107
+ inputs = nil,
108
+ multi_cloud_image_name = nil,
109
+ ssh_key_uuid = nil,
110
+ security_groups = nil)
111
+
112
+ # fail if the requested cloud is not registered with RightScale account
113
+ @cloud = @api_shim.find_cloud_by_name(cloud_name)
114
+ unless @cloud
115
+ clouds = @client.list_clouds.inject("") { |str, c| str == "" ? c.name : "#{str}, #{c.name}" }
116
+ raise RightScaleError, "ERROR: cannot find a cloud named: '#{cloud_name}'. " +
117
+ "Please check the spelling of the 'cloud_name' parameter in " +
118
+ "your Vagrant file and verify the cloud is registered with " +
119
+ "your RightScale account? Supported clouds: #{clouds}"
120
+ end
121
+
122
+ # Verify ssh key uuid, if required by cloud
123
+ if @api_shim.requires_ssh_keys?(@cloud)
124
+ @ssh_key = @api_shim.find_ssh_key_by_uuid_or_first(@cloud, ssh_key_uuid)
125
+ raise "ERROR: cannot find an ssh_key named: #{ssh_key_uuid}" unless @ssh_key
126
+ end
127
+
128
+ # Verify security group, if required by cloud
129
+ if @api_shim.requires_security_groups?(@cloud)
130
+ @sec_groups = []
131
+ security_groups ||= ["default"]
132
+ security_groups.each do |name|
133
+ group = @api_shim.find_security_group_by_name(@cloud, name)
134
+ raise "ERROR: cannot find an security group named: #{name}" unless group
135
+ @sec_groups << group
136
+ end
137
+ end
138
+
139
+ # check for existing deployment and server in RightScale account
140
+ @deployment = @api_shim.find_deployment_by_name(deployment_name)
141
+ @logger.info "Deployment '#{deployment_name}' #{@deployment ? "found." : "not found."}"
142
+ @server = @api_shim.find_server_by_name(server_name) if @deployment
143
+ @logger.info "Server '#{server_name}' #{@server ? "found." : "not found."}"
144
+
145
+ if @server
146
+ # verify existing server is on the cloud we are requesting, if not fail.
147
+ actual_cloud_name = @api_shim.server_cloud_name(@server)
148
+ raise "ERROR: the server is in the '#{actual_cloud_name}' cloud, " +
149
+ "and not in the requested '#{cloud_name}' cloud.\n" +
150
+ "Please delete the server or pick and new server name." if cloud_name != actual_cloud_name
151
+ end
152
+
153
+ unless @deployment && @server
154
+ # we need to create a server, can we find the servertemplate?
155
+ begin
156
+ @servertemplate = @client.find_servertemplate(server_template)
157
+ rescue
158
+ raise RightScaleError, "ERROR: cannot find ServerTemplate '#{server_template}'. Did you import it?\n" +
159
+ "Visit http://bit.ly/VnOiA7 for more info.\n\n"
160
+ end
161
+
162
+ # We need to find the to be used in the server if the MCI name is given
163
+ begin
164
+ @mci =
165
+ if multi_cloud_image_name.nil? || multi_cloud_image_name.empty?
166
+ nil
167
+ else
168
+ @client.find_mci_by_name(multi_cloud_image_name)
169
+ end
170
+ rescue Exception => e
171
+ raise RightScaleError, "ERROR: Cannot find the mci '#{multi_cloud_image_name}'. Please make sure" +
172
+ " that you have the MCI under the server template selected." +
173
+ " Exception: #{e.inspect}"
174
+ end
175
+ end
176
+
177
+ # create deployment and server as needed
178
+ unless @deployment
179
+ @deployment = @api_shim.create_deployment(deployment_name)
180
+ @logger.info "Created deployment."
181
+ end
182
+
183
+ unless @server
184
+ @server = @api_shim.create_server(@deployment, @servertemplate, @mci, @cloud, server_name, @ssh_key, @sec_groups)
185
+ @logger.info "Created server."
186
+ end
187
+
188
+ unless @api_shim.is_provisioned?(@server)
189
+
190
+ # setup any inputs
191
+ begin
192
+ @client.set_server_inputs(@server, inputs) if inputs && ! inputs.empty?
193
+ rescue Exception => e
194
+ raise RightScaleError, "Problem setting inputs. \n #{e.message}\n\n"
195
+ end
196
+
197
+ # launch server
198
+ @logger.info "Launching server..."
199
+ @server = @api_shim.launch_server(@server, inputs)
200
+ @api_shim.set_bad_states(BAD_STATES_UP)
201
+ @api_shim.server_wait_for_state(@server, "booting", 30)
202
+ end
203
+
204
+ end
205
+
206
+ def server_ready?
207
+ @api_shim.server_ready?(@server)
208
+ end
209
+
210
+ def wait_for_operational
211
+ @api_shim.set_bad_states(BAD_STATES_UP)
212
+ @api_shim.server_wait_for_state(@server, "operational", 30)
213
+ end
214
+
215
+ def server_info
216
+ info = @api_shim.server_info(@server)
217
+ while info.private_ip_addresses.empty?
218
+ @logger.info "Waiting for cloud to provide IP address..."
219
+ sleep 30
220
+ info = @api_shim.server_info(@server)
221
+ end
222
+ info
223
+ end
224
+
225
+ end
226
+ end
@@ -1,3 +1,3 @@
1
1
  module RightApiHelper
2
- VERSION = "1.0.0"
2
+ VERSION = "1.1.0"
3
3
  end
@@ -26,6 +26,7 @@ require 'right_api_helper/api15'
26
26
  require 'right_api_helper/deployments'
27
27
  require 'right_api_helper/instances'
28
28
  require 'right_api_helper/scripts/deployments_creator'
29
+ require 'right_api_helper/provisioner'
29
30
 
30
31
  module RightApiHelper
31
32
  # Hey now!
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+
3
+ describe RightApiHelper::Provisioner do
4
+
5
+ it "initializes" do
6
+ VCR.use_cassette('right_api_session') do
7
+ session = RightApiHelper::Session.new
8
+ session.should_receive(:setup_client_logging)
9
+ @right_api_client = session.create_client_from_file("~/.right_api_client/login.yml")
10
+ end
11
+ VCR.use_cassette('right_api_general') do
12
+ @helper = RightApiHelper::Provisioner.new(@right_api_client)
13
+ @logger = stub("Logger")
14
+ @helper.logger(@logger)
15
+ end
16
+ end
17
+
18
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: right_api_helper
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-05-13 00:00:00.000000000 Z
12
+ date: 2014-05-16 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: right_api_client
@@ -149,6 +149,7 @@ extra_rdoc_files: []
149
149
  files:
150
150
  - .gitignore
151
151
  - .rspec
152
+ - CHANGELOG.md
152
153
  - Gemfile
153
154
  - LICENSE
154
155
  - README.md
@@ -178,6 +179,7 @@ files:
178
179
  - lib/right_api_helper/cache.rb
179
180
  - lib/right_api_helper/deployments.rb
180
181
  - lib/right_api_helper/instances.rb
182
+ - lib/right_api_helper/provisioner.rb
181
183
  - lib/right_api_helper/scripts/deployments_creator.rb
182
184
  - lib/right_api_helper/session.rb
183
185
  - lib/right_api_helper/version.rb
@@ -187,6 +189,7 @@ files:
187
189
  - spec/data/deployments.json
188
190
  - spec/deployments_spec.rb
189
191
  - spec/instances_spec.rb
192
+ - spec/provisioner_spec.rb
190
193
  - spec/scripts/deployments_creator_spec.rb
191
194
  - spec/session_spec.rb
192
195
  - spec/spec_helper.rb
@@ -221,6 +224,7 @@ test_files:
221
224
  - spec/data/deployments.json
222
225
  - spec/deployments_spec.rb
223
226
  - spec/instances_spec.rb
227
+ - spec/provisioner_spec.rb
224
228
  - spec/scripts/deployments_creator_spec.rb
225
229
  - spec/session_spec.rb
226
230
  - spec/spec_helper.rb