ggoodale-rackspace_cloud 0.3.0 → 0.4.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/README CHANGED
@@ -7,7 +7,7 @@ Example:
7
7
  => nil
8
8
  >> cloud.servers
9
9
  => []
10
- >> new_server = cloud.create_server('development', 1, 8) # create a 256MB Ubunty 9.04 instance)
10
+ >> new_server = cloud.create_server('development', 1, 8) # create a 256MB Ubuntu 9.04 instance)
11
11
  => #<RackspaceCloud::Server:0x1054a78 @image=#<RackspaceCloud::Image:0x10598e8 @name="Ubuntu 9.04 (jaunty)", @updated="2009-07-20T09:14:37-05:00", @created="2009-07-20T09:14:37-05:00", @status="ACTIVE", @rackspace_id=8>, @public_ips=["174.xxx.xxx.xxx"], @flavor=#<RackspaceCloud::Flavor:0x105d40c @name="256 slice", @ram=256, @disk=10, @rackspace_id=1>, @name="development", @progress=80, @adminPass="developmentU5fG3", @host_id="a7765fde333eead221", @private_ips=["10.xxx.xxx.xxx"], @rackspace_id=1, @status="BUILD">
12
12
 
13
13
  ... wait a while ...
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.0
1
+ 0.4.0
@@ -26,29 +26,6 @@ module RackspaceCloud
26
26
  #This should eventually check the versions and raise an APIVersionError if there's a mismatch.
27
27
  end
28
28
 
29
- # storage for the lists of flavors and images we request at auth time
30
- FLAVORS = {}
31
- def RackspaceCloud.populate_flavors
32
- request("/flavors/detail")['flavors'].each do |flavor|
33
- FLAVORS[flavor['id']] = RackspaceCloud::Flavor.new(flavor)
34
- end
35
- nil
36
- end
37
-
38
- IMAGES = {}
39
- def RackspaceCloud.populate_images
40
- request("/images/detail")['images'].each do |image|
41
- IMAGES[image['id']] = RackspaceCloud::Image.new(image)
42
- end
43
- nil
44
- end
45
-
46
- LIMITS = {}
47
- def RackspaceCloud.get_limits
48
- LIMITS.merge!(request("/limits")['limits'])
49
- nil
50
- end
51
-
52
29
  def RackspaceCloud.request_authorization(user, access_key)
53
30
  session = Patron::Session.new
54
31
  session.base_url = BASE_AUTH_URI
@@ -59,48 +36,9 @@ module RackspaceCloud
59
36
 
60
37
  case response.status
61
38
  when 204 # "No Content", which means success
62
- @server_management_url = response.headers['X-Server-Management-Url']
63
- @storage_url = response.headers['X-Storage-Url']
64
- @storage_token = response.headers['X-Storage-Token']
65
- @cdn_management_url = response.headers['X-CDN-Management-Url']
66
- @auth_token = response.headers['X-Auth-Token']
67
- @@authorized = true
39
+ response.headers
68
40
  else
69
41
  raise AuthorizationError, "Error during authorization: #{response.status}"
70
42
  end
71
- nil
72
- end
73
-
74
- def RackspaceCloud.request(path, options={})
75
- raise RuntimeError, "Please authorize before using by calling connect()" unless defined?(@@authorized) && @@authorized
76
- @session ||= begin
77
- s = Patron::Session.new
78
- s.base_url = @server_management_url
79
- s.headers['X-Auth-Token'] = @auth_token
80
- s.headers["User-Agent"] = "rackspacecloud_ruby_gem"
81
- s.timeout = 10
82
- s
83
- end
84
- response = case options[:method]
85
- when :post
86
- @session.headers['Accept'] = "application/json"
87
- @session.headers['Content-Type'] = "application/json"
88
- @session.post("#{path}", options[:data].to_json)
89
- when :put
90
- @session.headers['Content-Type'] = "application/json"
91
- @session.put("#{path}", options[:data].to_json)
92
- when :delete
93
- @session.delete("#{path}")
94
- else
95
- @session.get("#{path}.json")
96
- end
97
-
98
- case response.status
99
- when 200, 202, 204
100
- JSON.parse(response.body) unless response.body.empty?
101
- else
102
- puts response.body
103
- raise RuntimeError, "Error fetching #{path}: #{response.status}"
104
- end
105
43
  end
106
44
  end
@@ -6,22 +6,54 @@ module RackspaceCloud
6
6
  validate_config(config)
7
7
  @user = config[:user]
8
8
  @access_key = config[:access_key]
9
+ @authorized = false
9
10
  end
10
11
 
11
12
  def connect
12
- RackspaceCloud.request_authorization(@user, @access_key)
13
+ configure_service_urls(RackspaceCloud.request_authorization(@user, @access_key))
13
14
  RackspaceCloud.check_version_compatibility
14
- RackspaceCloud.populate_flavors
15
- RackspaceCloud.populate_images
16
- RackspaceCloud.get_limits
15
+ @authorized = true
16
+ populate_flavors
17
+ populate_images
18
+ get_limits
19
+ end
20
+
21
+ def authorized?
22
+ @authorized
17
23
  end
18
24
 
19
- def servers(force_refresh=false)
20
- RackspaceCloud.request("/servers/detail")["servers"].collect {|server_json|
21
- RackspaceCloud::Server.new(server_json)
22
- }
25
+ # storage for the lists of flavors and images we request at auth time
26
+ attr_reader :flavors
27
+ def populate_flavors
28
+ @flavors ||= {}
29
+ request("/flavors/detail")['flavors'].each do |flavor|
30
+ @flavors[flavor['id']] = RackspaceCloud::Flavor.new(flavor)
31
+ end
32
+ nil
33
+ end
34
+
35
+ attr_reader :images
36
+ def populate_images
37
+ @images ||= {}
38
+ request("/images/detail")['images'].each do |image|
39
+ @images[image['id']] = RackspaceCloud::Image.new(self, image)
40
+ end
41
+ nil
23
42
  end
24
43
 
44
+ attr_reader :limits
45
+ def get_limits
46
+ @limits ||= {}
47
+ @limits.merge!(request("/limits")['limits'])
48
+ nil
49
+ end
50
+
51
+ def servers
52
+ request("/servers/detail")["servers"].collect {|server_json|
53
+ RackspaceCloud::Server.new(self, server_json)
54
+ }
55
+ end
56
+
25
57
  def create_server(name, flavor, image, metadata={}, personality=[])
26
58
  new_server_data = {'server' => {
27
59
  'name' => name,
@@ -31,7 +63,53 @@ module RackspaceCloud
31
63
  'personality' => personality
32
64
  }}
33
65
 
34
- RackspaceCloud::Server.new(RackspaceCloud.request("/servers", :method => :post, :data => new_server_data)['server'])
66
+ RackspaceCloud::Server.new(self, request("/servers", :method => :post, :data => new_server_data)['server'])
67
+ end
68
+
69
+ def shared_ip_groups
70
+ request("/shared_ip_groups/detail")['sharedIpGroups'].collect {|group_json|
71
+ RackspaceCloud::SharedIPGroup.new(self, group_json)
72
+ }
73
+ end
74
+
75
+ # Yes, you can only specify at most a single server to initially populate a shared IP group. Odd, that.
76
+ def create_shared_ip_group(name, server=nil)
77
+ new_group_data = {'sharedIpGroup' => {'name' => name, 'server' => server}}
78
+ new_group_data['sharedIpGroup']['server'] = server.to_i unless server.nil?
79
+ RackspaceCloud::SharedIPGroup.new(self, request("/shared_ip_groups", :method => :post, :data => new_group_data))
80
+ end
81
+
82
+ def request(path, options={})
83
+ raise RuntimeError, "Please authorize before using by calling connect()" unless authorized?
84
+ @session ||= begin
85
+ s = Patron::Session.new
86
+ s.base_url = @server_management_url
87
+ s.headers['X-Auth-Token'] = @auth_token
88
+ s.headers["User-Agent"] = "rackspacecloud_ruby_gem"
89
+ s.timeout = 10
90
+ s
91
+ end
92
+ response = case options[:method]
93
+ when :post
94
+ @session.headers['Accept'] = "application/json"
95
+ @session.headers['Content-Type'] = "application/json"
96
+ @session.post("#{path}", options[:data].to_json)
97
+ when :put
98
+ @session.headers['Content-Type'] = "application/json"
99
+ @session.put("#{path}", options[:data].to_json)
100
+ when :delete
101
+ @session.delete("#{path}")
102
+ else
103
+ @session.get("#{path}.json")
104
+ end
105
+
106
+ case response.status
107
+ when 200, 201, 202, 204
108
+ JSON.parse(response.body) unless response.body.empty?
109
+ else
110
+ puts response.body
111
+ raise RuntimeError, "Error fetching #{path}: #{response.status}"
112
+ end
35
113
  end
36
114
 
37
115
  def api_version
@@ -46,5 +124,13 @@ module RackspaceCloud
46
124
  (config[:access_key] && config[:access_key].length) || errors << "missing access_key"
47
125
  raise(ArgumentError, "Error: invalid configuration: #{errors.join(';')}") unless errors.empty?
48
126
  end
127
+
128
+ def configure_service_urls(url_hash = {})
129
+ @server_management_url = url_hash['X-Server-Management-Url']
130
+ @storage_url = url_hash['X-Storage-Url']
131
+ @storage_token = url_hash['X-Storage-Token']
132
+ @cdn_management_url = url_hash['X-CDN-Management-Url']
133
+ @auth_token = url_hash['X-Auth-Token']
134
+ end
49
135
  end
50
136
  end
@@ -2,12 +2,6 @@ module RackspaceCloud
2
2
  class Flavor
3
3
  attr_reader :name, :disk, :ram, :rackspace_id
4
4
 
5
- class << self
6
- def lookup_by_id(id)
7
- RackspaceCloud::FLAVORS[id]
8
- end
9
- end
10
-
11
5
  def initialize(flavor_json)
12
6
  @rackspace_id = flavor_json['id']
13
7
  @name = flavor_json['name']
@@ -3,21 +3,26 @@ module RackspaceCloud
3
3
 
4
4
  MAX_RACKSPACE_IMAGE_ID = 10 # the highest id in use by a standard rackspace image (vs. a user backup)
5
5
 
6
- attr_reader :name, :created, :updated, :status, :progress, :rackspace_id
6
+ attr_reader :name, :created, :updated, :status, :progress, :rackspace_id, :base
7
7
 
8
8
  class << self
9
- def lookup_by_id(id)
10
- RackspaceCloud::IMAGES[id]
9
+ def create_from_server(server, name=nil)
10
+ name ||= generate_timestamped_name(server)
11
+ image_json = server.base.request("/images", :method => :post, :data => {'image' => {'name' => name, 'serverId' => @rackspace_id}})['image']
12
+ new_image = RackspaceCloud::Image.new(image_json)
13
+ @images[new_image.rackspace_id] = new_image
14
+ new_image
11
15
  end
12
16
  end
13
17
 
14
- def initialize(image_json)
18
+ def initialize(base, image_json)
19
+ @base = base
15
20
  populate(image_json)
16
21
  end
17
22
 
18
23
  def delete
19
- raise RuntimeError, "Can't delete Rackspace standar images" if @rackspace_id <= MAX_RACKSPACE_IMAGE_ID
20
- RackspaceCloud.request("/images/#{@rackspace_id}", :method => :delete)
24
+ raise RuntimeError, "Can't delete Rackspace standard images" if @rackspace_id <= MAX_RACKSPACE_IMAGE_ID
25
+ @base.request("/images/#{@rackspace_id}", :method => :delete)
21
26
  end
22
27
 
23
28
  def to_i
@@ -25,8 +30,8 @@ module RackspaceCloud
25
30
  end
26
31
 
27
32
  def refresh
28
- populate(RackspaceCloud.request("/images/#{@rackspace_id}")['image'])
29
- RackspaceCloud::IMAGES[@rackspace_id] = self
33
+ populate(@base.request("/images/#{@rackspace_id}")['image'])
34
+ self
30
35
  end
31
36
 
32
37
  protected
@@ -39,5 +44,9 @@ module RackspaceCloud
39
44
  @status = image_json['status']
40
45
  @progress = image_json['progress']
41
46
  end
47
+
48
+ def generate_timestamped_name(server)
49
+ "#{server.downcase.gsub!(/\W/, "-")}-#{Time.nowTime.now.strftime('%Y%m%d%H%M%S%z')}"
50
+ end
42
51
  end
43
52
  end
@@ -1,17 +1,18 @@
1
1
  module RackspaceCloud
2
2
  class Server
3
- attr_reader :name, :status, :flavor, :image
3
+ attr_reader :name, :status, :flavor, :image, :base
4
4
  attr_reader :rackspace_id, :host_id, :progress
5
5
  attr_reader :public_ips, :private_ips, :adminPass
6
6
 
7
7
  STATUS_VALUES = %w{ACTIVE BUILD REBUILD SUSPENDED QUEUE_RESIZE PREP_RESIZE VERIFY_RESIZE PASSWORD RESCUE REBOOT HARD_REBOOT SHARE_IP SHARE_IP_NO_CONFIG DELETE_IP UNKNOWN}
8
8
 
9
- def initialize(server_json)
9
+ def initialize(base, server_json)
10
+ @base = base
10
11
  populate(server_json)
11
12
  end
12
13
 
13
14
  def ready?
14
- @status == 'ACTIVE'
15
+ self.refresh.status == 'ACTIVE'
15
16
  end
16
17
 
17
18
  def reboot
@@ -38,42 +39,44 @@ module RackspaceCloud
38
39
  action_request('revertResize' => nil)
39
40
  end
40
41
 
42
+ def share_ip_address(ip_address, shared_ip_address_group, configure_server = true)
43
+ @base.request("/servers/#{@rackspace_id}/ips/public/#{ip_address}",
44
+ :method => :put, :data => {'shareIp' => {'sharedIpGroupId' => shared_ip_address_group.to_i, 'configureServer' => configure_server}})
45
+ end
46
+
47
+ def unshare_ip_address(ip_address)
48
+ @base.request("/servers/#{@rackspace_id}/ips/public/#{ip_address}", :method => :delete)
49
+ end
50
+
41
51
  def delete
42
- RackspaceCloud.request("/servers/#{@rackspace_id}", :method => :delete)
52
+ @base.request("/servers/#{@rackspace_id}", :method => :delete)
43
53
  end
44
54
 
45
55
  def update_server_name(new_name)
46
- RackspaceCloud.request("/servers/#{@rackspace_id}", :method => :put, :data => {"server" => {"name" => new_name}})
56
+ @base.request("/servers/#{@rackspace_id}", :method => :put, :data => {"server" => {"name" => new_name}})
47
57
  end
48
58
 
49
59
  def update_admin_password(new_password)
50
- RackspaceCloud.request("/servers/#{@rackspace_id}", :method => :put, :data => {"server" => {"adminPass" => new_password}})
51
- end
52
-
53
- def save_as_image(name)
54
- image_json = RackspaceCloud.request("/images", :method => :post, :data => {'image' => {'name' => name, 'serverId' => @rackspace_id}})['image']
55
- new_image = RackspaceCloud::Image.new(image_json)
56
- RackspaceCloud::IMAGES[new_image.rackspace_id] = new_image
57
- new_image
60
+ @base.request("/servers/#{@rackspace_id}", :method => :put, :data => {"server" => {"adminPass" => new_password}})
58
61
  end
59
62
 
60
63
  # update this server's status and progress by calling /servers/<id>
61
64
  def refresh
62
- populate(RackspaceCloud.request("/servers/#{@rackspace_id}")['server'])
65
+ populate(@base.request("/servers/#{@rackspace_id}")['server'])
63
66
  self
64
67
  end
65
68
 
66
69
  protected
67
70
 
68
71
  def action_request(data)
69
- RackspaceCloud.request("/servers/#{@rackspace_id}/action", :method => :post, :data => data)
72
+ @base.request("/servers/#{@rackspace_id}/action", :method => :post, :data => data)
70
73
  end
71
74
 
72
75
  def populate(server_json)
73
76
  @name = server_json['name']
74
77
  @status = server_json['status']
75
- @flavor = RackspaceCloud::Flavor.lookup_by_id(server_json['flavorId'])
76
- @image = RackspaceCloud::Image.lookup_by_id(server_json['imageId'])
78
+ @flavor = @base.flavors[server_json['flavorId']]
79
+ @image = @base.images[server_json['imageId']]
77
80
  @rackspace_id = server_json['id']
78
81
  @host_id = server_json['hostId']
79
82
  @progress = server_json['progress']
@@ -0,0 +1,33 @@
1
+ module RackspaceCloud
2
+ class SharedIPGroup
3
+ attr_reader :rackspace_id, :name, :servers
4
+
5
+ def initialize(base, group_json)
6
+ @base = base
7
+ populate(group_json)
8
+ end
9
+
10
+ def delete
11
+ @base.request("/shared_ip_groups/#{@rackspace_id}", :method => :delete)
12
+ end
13
+
14
+ def refresh
15
+ populate(@base.request("/shared_ip_groups/detail")['sharedIpGroup'])
16
+ end
17
+
18
+ def to_i
19
+ @rackspace_id
20
+ end
21
+
22
+ protected
23
+
24
+ def populate(group_json)
25
+ puts group_json.inspect
26
+ @rackspace_id = group_json['id']
27
+ @name = group_json['name']
28
+ unless group_json['servers'].nil?
29
+ @servers = @base.servers.select{|server| group_json['servers'].include? server.rackspace_id}
30
+ end
31
+ end
32
+ end
33
+ end
@@ -2,11 +2,11 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{rackspace_cloud}
5
- s.version = "0.3.0"
5
+ s.version = "0.4.0"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Grant Goodale"]
9
- s.date = %q{2009-07-22}
9
+ s.date = %q{2009-08-03}
10
10
  s.description = %q{Gem enabling the management of Rackspace Cloud Server instances.}
11
11
  s.email = %q{grant@moreblinktag.com}
12
12
  s.extra_rdoc_files = [
@@ -24,6 +24,7 @@ Gem::Specification.new do |s|
24
24
  "lib/rackspace_cloud/flavor.rb",
25
25
  "lib/rackspace_cloud/image.rb",
26
26
  "lib/rackspace_cloud/server.rb",
27
+ "lib/rackspace_cloud/shared_ip_group.rb",
27
28
  "rackspace_cloud.gemspec",
28
29
  "test/authentication_test.rb",
29
30
  "test/configuration_test.rb",
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ggoodale-rackspace_cloud
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Grant Goodale
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-07-22 00:00:00 -07:00
12
+ date: 2009-08-03 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -42,12 +42,14 @@ files:
42
42
  - lib/rackspace_cloud/flavor.rb
43
43
  - lib/rackspace_cloud/image.rb
44
44
  - lib/rackspace_cloud/server.rb
45
+ - lib/rackspace_cloud/shared_ip_group.rb
45
46
  - rackspace_cloud.gemspec
46
47
  - test/authentication_test.rb
47
48
  - test/configuration_test.rb
48
49
  - test/test_helper.rb
49
50
  has_rdoc: false
50
51
  homepage: http://github.com/ggoodale/rackspace_cloud
52
+ licenses:
51
53
  post_install_message:
52
54
  rdoc_options:
53
55
  - --charset=UTF-8
@@ -68,7 +70,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
68
70
  requirements: []
69
71
 
70
72
  rubyforge_project:
71
- rubygems_version: 1.2.0
73
+ rubygems_version: 1.3.5
72
74
  signing_key:
73
75
  specification_version: 3
74
76
  summary: Gem enabling the management of Rackspace Cloud Server instances