fog 0.0.58 → 0.0.59

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. data/README.rdoc +56 -72
  2. data/VERSION.yml +1 -1
  3. data/fog.gemspec +2 -2
  4. data/lib/fog.rb +9 -20
  5. data/lib/fog/aws.rb +119 -135
  6. data/lib/fog/aws/ec2.rb +31 -1
  7. data/lib/fog/aws/requests/ec2/authorize_security_group_ingress.rb +1 -2
  8. data/lib/fog/aws/requests/ec2/create_security_group.rb +1 -1
  9. data/lib/fog/aws/requests/ec2/run_instances.rb +1 -1
  10. data/lib/fog/connection.rb +14 -32
  11. data/lib/fog/rackspace.rb +21 -51
  12. data/lib/fog/rackspace/files.rb +102 -76
  13. data/lib/fog/rackspace/models/files/directories.rb +14 -3
  14. data/lib/fog/rackspace/models/files/directory.rb +3 -1
  15. data/lib/fog/rackspace/models/files/file.rb +3 -1
  16. data/lib/fog/rackspace/models/files/files.rb +4 -1
  17. data/lib/fog/rackspace/models/servers/flavor.rb +3 -1
  18. data/lib/fog/rackspace/models/servers/flavors.rb +16 -4
  19. data/lib/fog/rackspace/models/servers/image.rb +3 -1
  20. data/lib/fog/rackspace/models/servers/images.rb +18 -5
  21. data/lib/fog/rackspace/models/servers/server.rb +3 -1
  22. data/lib/fog/rackspace/models/servers/servers.rb +14 -3
  23. data/lib/fog/rackspace/requests/files/delete_container.rb +5 -13
  24. data/lib/fog/rackspace/requests/files/delete_object.rb +5 -13
  25. data/lib/fog/rackspace/requests/files/get_container.rb +5 -13
  26. data/lib/fog/rackspace/requests/files/get_containers.rb +5 -13
  27. data/lib/fog/rackspace/requests/files/get_object.rb +5 -13
  28. data/lib/fog/rackspace/requests/files/head_container.rb +5 -13
  29. data/lib/fog/rackspace/requests/files/head_containers.rb +5 -13
  30. data/lib/fog/rackspace/requests/files/head_object.rb +5 -13
  31. data/lib/fog/rackspace/requests/files/put_container.rb +5 -13
  32. data/lib/fog/rackspace/requests/files/put_object.rb +6 -14
  33. data/lib/fog/rackspace/requests/servers/create_image.rb +7 -15
  34. data/lib/fog/rackspace/requests/servers/create_server.rb +7 -15
  35. data/lib/fog/rackspace/requests/servers/delete_image.rb +7 -15
  36. data/lib/fog/rackspace/requests/servers/delete_server.rb +7 -15
  37. data/lib/fog/rackspace/requests/servers/get_flavor_details.rb +5 -13
  38. data/lib/fog/rackspace/requests/servers/get_server_details.rb +5 -13
  39. data/lib/fog/rackspace/requests/servers/list_addresses.rb +5 -13
  40. data/lib/fog/rackspace/requests/servers/list_flavors.rb +5 -13
  41. data/lib/fog/rackspace/requests/servers/list_flavors_detail.rb +5 -13
  42. data/lib/fog/rackspace/requests/servers/list_images.rb +5 -13
  43. data/lib/fog/rackspace/requests/servers/list_images_detail.rb +7 -15
  44. data/lib/fog/rackspace/requests/servers/list_private_addresses.rb +5 -13
  45. data/lib/fog/rackspace/requests/servers/list_public_addresses.rb +5 -13
  46. data/lib/fog/rackspace/requests/servers/list_servers.rb +5 -13
  47. data/lib/fog/rackspace/requests/servers/list_servers_detail.rb +7 -15
  48. data/lib/fog/rackspace/requests/servers/reboot_server.rb +5 -13
  49. data/lib/fog/rackspace/requests/servers/update_server.rb +5 -13
  50. data/lib/fog/rackspace/servers.rb +85 -71
  51. data/lib/fog/slicehost.rb +74 -67
  52. data/lib/fog/slicehost/models/flavor.rb +3 -1
  53. data/lib/fog/slicehost/models/flavors.rb +4 -1
  54. data/lib/fog/slicehost/models/image.rb +3 -1
  55. data/lib/fog/slicehost/models/images.rb +4 -1
  56. data/lib/fog/slicehost/models/server.rb +3 -1
  57. data/lib/fog/slicehost/models/servers.rb +4 -1
  58. data/lib/fog/slicehost/requests/create_slice.rb +5 -9
  59. data/lib/fog/slicehost/requests/delete_slice.rb +4 -10
  60. data/lib/fog/slicehost/requests/get_backups.rb +5 -9
  61. data/lib/fog/slicehost/requests/get_flavor.rb +5 -9
  62. data/lib/fog/slicehost/requests/get_flavors.rb +5 -9
  63. data/lib/fog/slicehost/requests/get_image.rb +5 -9
  64. data/lib/fog/slicehost/requests/get_images.rb +5 -9
  65. data/lib/fog/slicehost/requests/get_slice.rb +5 -9
  66. data/lib/fog/slicehost/requests/get_slices.rb +5 -9
  67. data/lib/fog/slicehost/requests/reboot_slice.rb +4 -10
  68. data/lib/fog/terremark.rb +60 -51
  69. data/lib/fog/terremark/requests/get_catalog.rb +5 -9
  70. data/lib/fog/terremark/requests/get_catalog_item.rb +5 -9
  71. data/lib/fog/terremark/requests/get_organization.rb +5 -9
  72. data/lib/fog/terremark/requests/get_organizations.rb +5 -9
  73. data/lib/fog/terremark/requests/get_vapp_template.rb +5 -9
  74. data/lib/fog/terremark/requests/get_vdc.rb +5 -9
  75. data/spec/rackspace/requests/servers/list_images_detail_spec.rb +0 -1
  76. data/spec/rackspace/requests/servers/reboot_server_spec.rb +3 -1
  77. data/spec/slicehost/requests/create_slice_spec.rb +1 -0
  78. metadata +3 -3
@@ -1,64 +1,44 @@
1
1
  = fog
2
2
 
3
- fog helps you interact with cloud services. fog is a work in progress.
3
+ fog helps you interact with cloud services.
4
4
 
5
- == Install
5
+ The quick and dirty, top to bottom:
6
+ * Models provide a simplified interface, making clouds easier to work with and switch between.
7
+ * Requests allow power users to get the most out of the features of each individual cloud.
8
+ * Mocks make testing and integrating a breeze.
6
9
 
7
- sudo gem install fog
10
+ Put them together and you get a great cloud computing experience, but we are getting ahead of ourselves...
8
11
 
9
12
  == Getting Started
10
13
 
11
- You can start stumbling around as soon as you install with the fog command line tool.
12
- After installing, just type 'fog' to get started.
13
- If you don't have credentials setup it will let you know what to do.
14
-
15
- Then just start playing around, fog should let you know if you are forget things.
16
-
17
- For example if you try to create a server but leave out stuff:
18
-
19
- server = AWS.servers.create
14
+ sudo gem install fog
20
15
 
21
- You'll get reminded that things are missing.
16
+ Now just type 'fog' to trying stuff out, confident that fog should let you know what you need to do. Here is an example of wading through server creation for Amazon Elastic Compute Cloud:
22
17
 
18
+ >> server = AWS.servers.create
23
19
  ArgumentError: image_id is required for this operation
20
+ >> server = AWS.servers.create(:image_id => 'ami-5ee70037')
21
+ <Fog::AWS::EC2::Server [...]>
22
+ >> server.destroy # cleanup after yourself or regret it, trust me
23
+ true
24
24
 
25
- So just add the missing stuff and you are off to the races:
26
-
27
- server = AWS.servers.create(:image_id => 'ami-5ee70037')
28
-
29
- But don't forget to cleanup or you'll regret it when you get the bill:
25
+ == Collections
30
26
 
31
- server.destroy
27
+ Nouns like Images and Servers are collections, which form the interface to the cloud.
28
+ Collections provide all, create, get and new methods.
29
+ * all fetches every object of that type from the cloud.
30
+ * create initializes a new record locally and then persists it to the cloud.
31
+ * get fetches a single object by its identity.
32
+ * new initializes a new record locally.
32
33
 
33
- Rinse, repeat, enjoy!
34
+ Common compute nouns are flavors, images and servers.
34
35
 
35
- == Working with Servers
36
+ Common storage nouns are directory and file.
36
37
 
37
- Lets boot up a server on EC2
38
+ As an example, we'll try initializing and persisting a rackspace server:
38
39
 
39
40
  require 'fog'
40
41
 
41
- # initialize a connection to Amazon Elastic Compute Cloud
42
- connection = Fog::AWS::EC2.new(
43
- :aws_access_key_id => id,
44
- :aws_secret_access_key => key
45
- )
46
-
47
- # boot a gentoo server
48
- server = connection.servers.new(:image_id => 'ami-5ee70037')
49
- # you might also want to add the server to security groups, which goes like this:
50
- # AWS.servers.create(:image_id => 'ami-5ee70037', :groups => ['web', 'db'])
51
-
52
- # wait for it to be ready to do stuff
53
- server.wait_for { ready? }
54
-
55
- # DO STUFF
56
-
57
- # shutdown the server
58
- server.destroy
59
-
60
- Now we will try again, but with Rackspace
61
-
62
42
  # initialize a connection to Rackspace Servers
63
43
  connection = Fog::Rackspace::Servers.new(
64
44
  :rackspace_api_key => key,
@@ -76,53 +56,57 @@ Now we will try again, but with Rackspace
76
56
  # shutdown the server
77
57
  server.destroy
78
58
 
79
- == Working with Directories and Files
59
+ == Models
80
60
 
81
- require 'fog'
61
+ Many of the collection methods return individual objects, which provide destroy, save and wait_for methods.
62
+ * destroy will destroy the persisted object from the cloud
63
+ * save will persist the object to the cloud
64
+ * wait_for takes a block and waits for either the block to return true for the object or for a timeout (defaults to 10 minutes)
82
65
 
83
- # initialize a connection to Amazon Simple Storage Solution
84
- connection = Fog::AWS::S3.new(
85
- :aws_access_key_id => id,
86
- :aws_secret_access_key => key
87
- )
66
+ == Mocks
67
+
68
+ Mocking provides an in memory representation of clouds as you make different requests.
69
+ This representation allows subsequent calls to mimic the behavior of the cloud while eliminating the cost and time needed to actually run tests against various providers.
70
+ Mocking is easy to use, just write any functions as you normally would and then in your tests ensure you call:
71
+
72
+ Fog.mock!
73
+
74
+ Make sure you call it first (before you initialize any connections) and all your calls should now run in mock mode.
75
+ If you run into the edges of mock implementation it should let you know that they haven't been implemented yet.
88
76
 
89
- # create a directory
90
- directory = connection.directory.create(:name => 'directoryname')
77
+ == Requests
91
78
 
92
- # create a new file in your directory
93
- directory.files.create(:key => 'filename', :body => 'filebody')
79
+ Requests allow you to dive deeper when the models just can't cut it.
80
+ For instance, ec2 provides methods related to reserved instances that don't have any models (yet anyway).
81
+ You can get a description of your reserved instances like this:
94
82
 
95
- # connect to your directory
96
- directory = connection.directories.get('directoryname')
83
+ $ fog
84
+ >> AWS[:ec2].describe_reserved_instances
85
+ #<Excon::Response [...]>
97
86
 
98
- # get your file
99
- file = directory.files.get('filename')
87
+ It will return an excon response, which has headers and body methods. Both give nice ruby hash representations of the result.
100
88
 
101
- # delete the file
102
- file.destroy
89
+ == Go forth and conquer
103
90
 
104
- # delete the directory
105
- directory.destroy
91
+ That should give you some stuff to try and places to look.
106
92
 
107
- == More info
93
+ You should try out the (varying) support fog has for:
94
+ * AWS [EC2, S3, SimpleDB]
95
+ * Rackspace [Files, Servers]
96
+ * Slicehost
97
+ * Terremark vCloud Express
98
+
99
+ Enjoy, and let me know what I can do to continue improving fog!
108
100
 
109
101
  * Follow {@geemus}[http://twitter.com/geemus] on Twitter.
110
102
  * See upcoming work in the {tracker}[http://www.pivotaltracker.com/projects/54635].
111
103
  * Report bugs in {issues}[http://github.com/geemus/fog/issues].
112
104
 
113
- == Supports
114
-
115
- * AWS EC2
116
- * AWS S3
117
- * AWS SimpleDB (no models yet)
118
- * Rackspace Files (no models yet, just getting started on requests)
119
- * Rackspace Servers (some requests, server model, just getting started)
120
-
121
105
  == Copyright
122
106
 
123
107
  (The MIT License)
124
108
 
125
- Copyright (c) 2009 {geemus (Wesley Beary)}[http://github.com/geemus]
109
+ Copyright (c) 2010 {geemus (Wesley Beary)}[http://github.com/geemus]
126
110
 
127
111
  Permission is hereby granted, free of charge, to any person obtaining
128
112
  a copy of this software and associated documentation files (the
@@ -1,5 +1,5 @@
1
1
  ---
2
2
  :major: 0
3
3
  :minor: 0
4
- :patch: 58
4
+ :patch: 59
5
5
  :build:
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{fog}
8
- s.version = "0.0.58"
8
+ s.version = "0.0.59"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["geemus (Wesley Beary)"]
12
- s.date = %q{2010-03-17}
12
+ s.date = %q{2010-03-26}
13
13
  s.default_executable = %q{fog}
14
14
  s.description = %q{brings clouds to you}
15
15
  s.email = %q{geemus@gmail.com}
data/lib/fog.rb CHANGED
@@ -17,36 +17,25 @@ $LOAD_PATH.unshift __DIR__ unless
17
17
  $LOAD_PATH.include?(__DIR__) ||
18
18
  $LOAD_PATH.include?(File.expand_path(__DIR__))
19
19
 
20
+ require 'fog/collection'
21
+ require 'fog/connection'
22
+ require 'fog/model'
23
+ require 'fog/parser'
24
+ require 'fog/aws'
25
+ require 'fog/rackspace'
26
+ require 'fog/slicehost'
27
+ require 'fog/terremark'
28
+
20
29
  module Fog
21
30
 
22
31
  class MockNotImplemented < StandardError; end
23
32
 
24
33
  def self.mock!
25
34
  @mocking = true
26
- self.reload
27
35
  end
28
36
 
29
37
  def self.mocking?
30
38
  !!@mocking
31
39
  end
32
40
 
33
- def self.dependencies
34
- [
35
- 'fog/collection.rb',
36
- 'fog/connection.rb',
37
- 'fog/model.rb',
38
- 'fog/parser.rb',
39
- 'fog/aws.rb',
40
- 'fog/rackspace.rb',
41
- 'fog/slicehost.rb',
42
- 'fog/terremark.rb'
43
- ]
44
- end
45
-
46
- def self.reload
47
- self.dependencies.each {|dependency| load(dependency)}
48
- end
49
-
50
41
  end
51
-
52
- Fog.dependencies.each {|dependency| require(dependency)}
@@ -1,19 +1,10 @@
1
+ require 'fog/aws/ec2.rb'
1
2
  require 'fog/aws/s3'
2
3
  require 'fog/aws/simpledb'
3
4
 
4
5
  module Fog
5
6
  module AWS
6
7
 
7
- def self.dependencies
8
- [
9
- 'fog/aws/ec2.rb'
10
- ]
11
- end
12
-
13
- def self.reload
14
- self.dependencies.each {|dependency| load(dependency)}
15
- end
16
-
17
8
  def self.indexed_param(key, values)
18
9
  params = {}
19
10
  [*values].each_with_index do |value, index|
@@ -22,161 +13,154 @@ module Fog
22
13
  params
23
14
  end
24
15
 
25
- if Fog.mocking?
26
- srand(Time.now.to_i)
27
-
28
- class Mock
29
-
30
- def self.availability_zone
31
- "us-east-1" << random_selection('abcd', 1)
32
- end
16
+ class Mock
33
17
 
34
- def self.box_usage
35
- sprintf("%0.10f", rand / 100).to_f
36
- end
18
+ def self.availability_zone
19
+ "us-east-1" << random_selection('abcd', 1)
20
+ end
37
21
 
38
- def self.console_output
39
- 'This is my console. There are many like it, but this one is mine. My console is my best friend. It is my life. I must master it as I master my life. My console, without me, is useless. Without my console, I am useless.'
40
- end
22
+ def self.box_usage
23
+ sprintf("%0.10f", rand / 100).to_f
24
+ end
41
25
 
42
- def self.etag
43
- hex(32)
44
- end
26
+ def self.console_output
27
+ 'This is my console. There are many like it, but this one is mine. My console is my best friend. It is my life. I must master it as I master my life. My console, without me, is useless. Without my console, I am useless.'
28
+ end
45
29
 
46
- def self.image
47
- path = []
48
- (rand(3) + 2).times do
49
- path << letters(rand(9) + 8)
50
- end
51
- {
52
- "imageOwnerId" => letters(rand(5) + 4),
53
- "productCodes" => [],
54
- "kernelId" => kernel_id,
55
- "ramdiskId" => ramdisk_id,
56
- "imageState" => "available",
57
- "imageId" => image_id,
58
- "architecture" => "i386",
59
- "isPublic" => true,
60
- "imageLocation" => path.join('/'),
61
- "imageType" => "machine"
62
- }
63
- end
30
+ def self.etag
31
+ hex(32)
32
+ end
64
33
 
65
- def self.image_id
66
- "ami-#{hex(8)}"
67
- end
34
+ def self.image
35
+ path = []
36
+ (rand(3) + 2).times do
37
+ path << letters(rand(9) + 8)
38
+ end
39
+ {
40
+ "imageOwnerId" => letters(rand(5) + 4),
41
+ "productCodes" => [],
42
+ "kernelId" => kernel_id,
43
+ "ramdiskId" => ramdisk_id,
44
+ "imageState" => "available",
45
+ "imageId" => image_id,
46
+ "architecture" => "i386",
47
+ "isPublic" => true,
48
+ "imageLocation" => path.join('/'),
49
+ "imageType" => "machine"
50
+ }
51
+ end
68
52
 
69
- def self.key_fingerprint
70
- fingerprint = []
71
- 20.times do
72
- fingerprint << hex(2)
73
- end
74
- fingerprint.join(':')
75
- end
53
+ def self.image_id
54
+ "ami-#{hex(8)}"
55
+ end
76
56
 
77
- def self.image_id
78
- "ami-#{hex(8)}"
57
+ def self.key_fingerprint
58
+ fingerprint = []
59
+ 20.times do
60
+ fingerprint << hex(2)
79
61
  end
62
+ fingerprint.join(':')
63
+ end
80
64
 
81
- def self.instance_id
82
- "i-#{hex(8)}"
83
- end
65
+ def self.image_id
66
+ "ami-#{hex(8)}"
67
+ end
84
68
 
85
- def self.ip_address
86
- ip = []
87
- 4.times do
88
- ip << numbers(rand(3) + 1).to_i.to_s # remove leading 0
89
- end
90
- ip.join('.')
91
- end
69
+ def self.instance_id
70
+ "i-#{hex(8)}"
71
+ end
92
72
 
93
- def self.kernel_id
94
- "aki-#{hex(8)}"
73
+ def self.ip_address
74
+ ip = []
75
+ 4.times do
76
+ ip << numbers(rand(3) + 1).to_i.to_s # remove leading 0
95
77
  end
78
+ ip.join('.')
79
+ end
96
80
 
97
- def self.key_material
98
- key_material = ['-----BEGIN RSA PRIVATE KEY-----']
99
- 20.times do
100
- key_material << base64(76)
101
- end
102
- key_material << base64(67) + '='
103
- key_material << '-----END RSA PRIVATE KEY-----'
104
- key_material.join("\n")
105
- end
81
+ def self.kernel_id
82
+ "aki-#{hex(8)}"
83
+ end
106
84
 
107
- def self.owner_id
108
- numbers(12)
85
+ def self.key_material
86
+ key_material = ['-----BEGIN RSA PRIVATE KEY-----']
87
+ 20.times do
88
+ key_material << base64(76)
109
89
  end
90
+ key_material << base64(67) + '='
91
+ key_material << '-----END RSA PRIVATE KEY-----'
92
+ key_material.join("\n")
93
+ end
110
94
 
111
- def self.ramdisk_id
112
- "ari-#{hex(8)}"
113
- end
95
+ def self.owner_id
96
+ numbers(12)
97
+ end
114
98
 
115
- def self.request_id
116
- request_id = []
117
- request_id << hex(8)
118
- 3.times do
119
- request_id << hex(4)
120
- end
121
- request_id << hex(12)
122
- request_id.join('-')
123
- end
99
+ def self.ramdisk_id
100
+ "ari-#{hex(8)}"
101
+ end
124
102
 
125
- def self.reservation_id
126
- "r-#{hex(8)}"
103
+ def self.request_id
104
+ request_id = []
105
+ request_id << hex(8)
106
+ 3.times do
107
+ request_id << hex(4)
127
108
  end
109
+ request_id << hex(12)
110
+ request_id.join('-')
111
+ end
128
112
 
129
- def self.snapshot_id
130
- "snap-#{hex(8)}"
131
- end
113
+ def self.reservation_id
114
+ "r-#{hex(8)}"
115
+ end
132
116
 
133
- def self.volume_id
134
- "vol-#{hex(8)}"
135
- end
117
+ def self.snapshot_id
118
+ "snap-#{hex(8)}"
119
+ end
136
120
 
137
- private
121
+ def self.volume_id
122
+ "vol-#{hex(8)}"
123
+ end
138
124
 
139
- def self.random_selection(characters, length)
140
- selection = ''
141
- length.times do
142
- position = rand(characters.length)
143
- selection << characters[position..position]
144
- end
145
- selection
146
- end
125
+ private
147
126
 
148
- def self.letters(length)
149
- random_selection(
150
- 'abcdefghijklmnopqrstuvwxyz',
151
- length
152
- )
127
+ def self.random_selection(characters, length)
128
+ selection = ''
129
+ length.times do
130
+ position = rand(characters.length)
131
+ selection << characters[position..position]
153
132
  end
133
+ selection
134
+ end
154
135
 
155
- def self.numbers(length)
156
- random_selection(
157
- '0123456789',
158
- length
159
- )
160
- end
136
+ def self.letters(length)
137
+ random_selection(
138
+ 'abcdefghijklmnopqrstuvwxyz',
139
+ length
140
+ )
141
+ end
161
142
 
162
- def self.hex(length)
163
- random_selection(
164
- '0123456789abcdef',
165
- length
166
- )
167
- end
143
+ def self.numbers(length)
144
+ random_selection(
145
+ '0123456789',
146
+ length
147
+ )
148
+ end
168
149
 
169
- def self.base64(length)
170
- random_selection(
171
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
172
- length
173
- )
174
- end
150
+ def self.hex(length)
151
+ random_selection(
152
+ '0123456789abcdef',
153
+ length
154
+ )
155
+ end
175
156
 
157
+ def self.base64(length)
158
+ random_selection(
159
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
160
+ length
161
+ )
176
162
  end
177
- end
178
163
 
164
+ end
179
165
  end
180
166
  end
181
-
182
- Fog::AWS.reload