right_api_helper 1.0.0 → 1.1.0

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/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