fog 0.7.1 → 0.7.2

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.
Files changed (93) hide show
  1. data/.gitignore +1 -1
  2. data/Rakefile +43 -0
  3. data/changelog.txt +39 -0
  4. data/docs/_config.yml +39 -0
  5. data/docs/_layouts/default.html +96 -0
  6. data/docs/_posts/2011-01-01-cdn.markdown +82 -0
  7. data/docs/_posts/2011-01-01-contributing.markdown +228 -0
  8. data/docs/_posts/2011-01-01-dns.markdown +79 -0
  9. data/docs/_posts/2011-01-01-press.markdown +32 -0
  10. data/docs/_posts/2011-01-01-start.markdown +21 -0
  11. data/docs/_posts/2011-01-01-storage.markdown +145 -0
  12. data/docs/_posts/2011-01-01-structure.markdown +78 -0
  13. data/docs/_posts/2011-01-01-users.markdown +33 -0
  14. data/docs/index.markdown +94 -0
  15. data/docs/public/crossdomain.xml +25 -0
  16. data/docs/public/css/fog.css +129 -0
  17. data/docs/public/css/handheld.css +8 -0
  18. data/docs/public/css/style.css +129 -0
  19. data/docs/public/images/.gitignore +3 -0
  20. data/docs/public/js/libs/dd_belatedpng.js +13 -0
  21. data/docs/public/js/libs/jquery-1.4.2.js +6240 -0
  22. data/docs/public/js/libs/jquery-1.4.2.min.js +154 -0
  23. data/docs/public/js/libs/modernizr-1.6.min.js +30 -0
  24. data/docs/public/js/mylibs/.gitignore +3 -0
  25. data/docs/public/js/plugins.js +34 -0
  26. data/docs/public/js/profiling/config.js +59 -0
  27. data/docs/public/js/profiling/yahoo-profiling.css +7 -0
  28. data/docs/public/js/profiling/yahoo-profiling.min.js +39 -0
  29. data/docs/public/js/script.js +26 -0
  30. data/docs/public/robots.txt +5 -0
  31. data/fog.gemspec +6 -5
  32. data/lib/fog.rb +1 -1
  33. data/lib/fog/aws/cloud_formation.rb +1 -1
  34. data/lib/fog/compute/aws.rb +24 -0
  35. data/lib/fog/compute/models/aws/key_pair.rb +19 -1
  36. data/lib/fog/compute/models/aws/server.rb +6 -12
  37. data/lib/fog/compute/models/rackspace/server.rb +7 -7
  38. data/lib/fog/compute/requests/aws/attach_volume.rb +4 -0
  39. data/lib/fog/compute/requests/aws/create_security_group.rb +3 -3
  40. data/lib/fog/compute/requests/aws/create_tags.rb +2 -0
  41. data/lib/fog/compute/requests/aws/create_volume.rb +4 -0
  42. data/lib/fog/compute/requests/aws/delete_tags.rb +43 -0
  43. data/lib/fog/compute/requests/aws/describe_instances.rb +3 -7
  44. data/lib/fog/compute/requests/aws/describe_snapshots.rb +4 -6
  45. data/lib/fog/compute/requests/aws/describe_volumes.rb +2 -6
  46. data/lib/fog/core.rb +1 -0
  47. data/lib/fog/core/connection.rb +1 -1
  48. data/lib/fog/core/credentials.rb +5 -1
  49. data/lib/fog/core/parser.rb +1 -2
  50. data/lib/fog/core/ssh.rb +2 -3
  51. data/lib/fog/dns/models/aws/record.rb +1 -1
  52. data/lib/fog/dns/models/bluebox/zone.rb +1 -0
  53. data/lib/fog/storage/models/rackspace/directory.rb +8 -2
  54. data/lib/fog/storage/rackspace.rb +3 -1
  55. data/lib/fog/storage/requests/rackspace/delete_container.rb +1 -1
  56. data/lib/fog/storage/requests/rackspace/delete_object.rb +1 -1
  57. data/lib/fog/storage/requests/rackspace/get_container.rb +1 -1
  58. data/lib/fog/storage/requests/rackspace/get_object.rb +1 -1
  59. data/lib/fog/storage/requests/rackspace/head_container.rb +1 -1
  60. data/lib/fog/storage/requests/rackspace/head_object.rb +2 -2
  61. data/lib/fog/storage/requests/rackspace/put_container.rb +1 -1
  62. data/lib/fog/storage/requests/rackspace/put_object.rb +1 -1
  63. data/spec/spec_helper.rb +0 -4
  64. data/tests/aws/requests/cloud_formation/stack_tests.rb +16 -5
  65. data/tests/aws/requests/rds/instance_tests.rb +4 -2
  66. data/tests/compute/models/aws/address_tests.rb +16 -0
  67. data/tests/compute/models/aws/addresses_tests.rb +5 -0
  68. data/tests/compute/models/aws/key_pair_tests.rb +27 -0
  69. data/tests/compute/models/aws/key_pairs_tests.rb +5 -0
  70. data/tests/compute/models/aws/security_group_tests.rb +5 -0
  71. data/tests/compute/models/aws/security_groups.rb +5 -0
  72. data/tests/compute/models/aws/server_tests.rb +39 -0
  73. data/tests/compute/models/aws/snapshot_tests.rb +10 -0
  74. data/tests/compute/models/aws/snapshots_tests.rb +10 -0
  75. data/tests/compute/models/aws/volume_tests.rb +26 -0
  76. data/tests/compute/models/aws/volumes_tests.rb +5 -0
  77. data/tests/core/credential_tests.rb +36 -0
  78. data/tests/storage/requests/aws/object_tests.rb +1 -1
  79. data/tests/storage/requests/google/object_tests.rb +1 -1
  80. data/tests/storage/requests/rackspace/object_tests.rb +8 -0
  81. metadata +118 -75
  82. data/spec/aws/models/compute/address_spec.rb +0 -103
  83. data/spec/aws/models/compute/addresses_spec.rb +0 -70
  84. data/spec/aws/models/compute/key_pair_spec.rb +0 -86
  85. data/spec/aws/models/compute/key_pairs_spec.rb +0 -71
  86. data/spec/aws/models/compute/security_group_spec.rb +0 -88
  87. data/spec/aws/models/compute/security_groups_spec.rb +0 -71
  88. data/spec/aws/models/compute/server_spec.rb +0 -105
  89. data/spec/aws/models/compute/snapshot_spec.rb +0 -79
  90. data/spec/aws/models/compute/snapshots_spec.rb +0 -85
  91. data/spec/aws/models/compute/volume_spec.rb +0 -174
  92. data/spec/aws/models/compute/volumes_spec.rb +0 -71
  93. data/tests/compute/models/aws/server_monitor_tests.rb +0 -47
@@ -31,10 +31,28 @@ module Fog
31
31
  new_attributes = data.reject {|key,value| !['keyFingerprint', 'keyMaterial', 'keyName'].include?(key)}
32
32
  merge_attributes(new_attributes)
33
33
  true
34
+
35
+ end
36
+
37
+ def write(path="#{ENV['HOME']}/.ssh/fog_#{Fog.credential.to_s}_#{name}.pem")
38
+
39
+ if writable?
40
+ split_private_key = private_key.split(/\n/)
41
+ File.open(path, "w") do |f|
42
+ split_private_key.each {|line| f.puts line}
43
+ f.chmod 0600
44
+ end
45
+ "Key file built: #{path}"
46
+ else
47
+ "Invalid private key"
48
+ end
34
49
  end
35
50
 
36
- private
51
+ def writable?
52
+ !!(private_key && ENV.has_key?('HOME'))
53
+ end
37
54
 
55
+ private
38
56
  end
39
57
 
40
58
  end
@@ -82,7 +82,7 @@ module Fog
82
82
  def key_pair
83
83
  requires :key_name
84
84
 
85
- connection.keypairs.all(key_name).first
85
+ connection.key_pairs.all(key_name).first
86
86
  end
87
87
 
88
88
  def key_pair=(new_keypair)
@@ -218,24 +218,18 @@ module Fog
218
218
  #I tried to call it monitoring= and be smart with attributes[]
219
219
  #but in #save a merge_attribute is called after run_instance
220
220
  #thus making an un-necessary request. Use this until finding a clever solution
221
- def monitor=(boolean)
222
-
223
- #we don't have a server yet. the status silently goes in the attributes for run_instances
224
- if !identity
225
- self.monitoring=boolean
226
- end
227
-
228
- case boolean
221
+ def monitor=(new_monitor)
222
+ if identity
223
+ case new_monitor
229
224
  when true
230
225
  response = connection.monitor_instances(identity)
231
226
  when false
232
227
  response = connection.unmonitor_instances(identity)
233
228
  else
234
229
  raise ArgumentError.new("only Boolean allowed here")
230
+ end
235
231
  end
236
-
237
- #set the attribute, there is only one instance_id here
238
- response.body['instancesSet'][0]['monitoring'] == 'enabled' ? self.monitoring=true : self.monitoring=false
232
+ self.monitoring = new_monitor
239
233
  end
240
234
 
241
235
  end
@@ -61,7 +61,7 @@ module Fog
61
61
  end
62
62
 
63
63
  def public_ip_address
64
- addresses.first
64
+ addresses['public'].first
65
65
  end
66
66
 
67
67
  def public_key_path
@@ -98,8 +98,8 @@ module Fog
98
98
  end
99
99
 
100
100
  def setup(credentials = {})
101
- requires :addresses, :identity, :public_key, :username
102
- Fog::SSH.new(addresses['public'].first, username, credentials).run([
101
+ requires :public_ip_address, :identity, :public_key, :username
102
+ Fog::SSH.new(public_ip_address, username, credentials).run([
103
103
  %{mkdir .ssh},
104
104
  %{echo "#{public_key}" >> ~/.ssh/authorized_keys},
105
105
  %{passwd -l #{username}},
@@ -112,19 +112,19 @@ module Fog
112
112
  end
113
113
 
114
114
  def ssh(commands)
115
- requires :addresses, :identity, :username
115
+ requires :public_ip_address, :identity, :username
116
116
 
117
117
  options = {}
118
118
  options[:key_data] = [private_key] if private_key
119
- Fog::SSH.new(addresses['public'].first, username, options).run(commands)
119
+ Fog::SSH.new(public_ip_address, username, options).run(commands)
120
120
  end
121
121
 
122
122
  def scp(local_path, remote_path)
123
- requires :addresses, :username
123
+ requires :public_ip_address, :username
124
124
 
125
125
  options = {}
126
126
  options[:key_data] = [private_key] if private_key
127
- Fog::SCP.new(addresses['public'].first, username, options).upload(local_path, remote_path)
127
+ Fog::SCP.new(public_ip_address, username, options).upload(local_path, remote_path)
128
128
  end
129
129
 
130
130
  def username
@@ -43,6 +43,10 @@ module Fog
43
43
  instance = @data[:instances][instance_id]
44
44
  volume = @data[:volumes][volume_id]
45
45
  if instance && volume
46
+ unless volume['status'] == 'available'
47
+ raise Fog::AWS::Compute::Error.new("Client.VolumeInUse => Volume #{volume_id} is unavailable")
48
+ end
49
+
46
50
  data = {
47
51
  'attachTime' => Time.now,
48
52
  'device' => device,
@@ -20,7 +20,7 @@ module Fog
20
20
  request(
21
21
  'Action' => 'CreateSecurityGroup',
22
22
  'GroupName' => name,
23
- 'GroupDescription' => CGI.escape(description),
23
+ 'GroupDescription' => description,
24
24
  :parser => Fog::Parsers::AWS::Compute::Basic.new
25
25
  )
26
26
  end
@@ -33,8 +33,8 @@ module Fog
33
33
  response = Excon::Response.new
34
34
  unless @data[:security_groups][name]
35
35
  data = {
36
- 'groupDescription' => CGI.escape(description).gsub('%20', '+'),
37
- 'groupName' => CGI.escape(name).gsub('%20', '+'),
36
+ 'groupDescription' => description,
37
+ 'groupName' => name,
38
38
  'ipPermissions' => [],
39
39
  'ownerId' => @owner_id
40
40
  }
@@ -62,6 +62,8 @@ module Fog
62
62
  @data[:tags][key] ||= {}
63
63
  @data[:tags][key][value] ||= []
64
64
  @data[:tags][key][value] = @data[:tags][key][value] & tagged
65
+
66
+ tagged.each {|resource| @data[:"#{resource['resourceType']}s"][resource['resourceId']]['tagSet'][key] = value}
65
67
  end
66
68
 
67
69
  response = Excon::Response.new
@@ -38,6 +38,10 @@ module Fog
38
38
  def create_volume(availability_zone, size, snapshot_id = nil)
39
39
  response = Excon::Response.new
40
40
  if availability_zone && size
41
+ if snapshot_id && !@data[:snapshots][snapshot_id]
42
+ raise Fog::AWS::Compute::NotFound.new("The snapshot '#{snapshot_id}' does not exist.")
43
+ end
44
+
41
45
  response.status = 200
42
46
  volume_id = Fog::AWS::Mock.volume_id
43
47
  data = {
@@ -37,6 +37,49 @@ module Fog
37
37
  end
38
38
 
39
39
  end
40
+
41
+ class Mock
42
+ def delete_tags(resources, tags)
43
+ tagged = resources.map do |resource_id|
44
+ type = case resource_id
45
+ when /^ami\-[a-z0-9]{8}$/i
46
+ 'image'
47
+ when /^i\-[a-z0-9]{8}$/i
48
+ 'instance'
49
+ when /^snap\-[a-z0-9]{8}$/i
50
+ 'snapshot'
51
+ when /^vol\-[a-z0-9]{8}$/i
52
+ 'volume'
53
+ end
54
+ if type && @data[:"#{type}s"][resource_id]
55
+ { 'resourceId' => resource_id, 'resourceType' => type }
56
+ else
57
+ raise(Fog::Service::NotFound.new("The #{type} ID '#{resource_id}' does not exist"))
58
+ end
59
+ end
60
+
61
+ tags.each do |key, value|
62
+ @data[:tags][key][value] = @data[:tags][key][value] - tagged
63
+ end
64
+
65
+ tagged.each do |resource|
66
+ object = @data[:"#{resource['resourceType']}s"][resource['resourceId']]
67
+ tags.each do |key, value|
68
+ tagset = object['tagSet']
69
+ tagset.delete(key) if tagset.has_key?(key) && (value.nil? || tagset[key] == value)
70
+ end
71
+ end
72
+
73
+ response = Excon::Response.new
74
+ response.status = true
75
+ response.body = {
76
+ 'requestId' => Fog::AWS::Mock.request_id,
77
+ 'return' => true
78
+ }
79
+ response
80
+ end
81
+ end
82
+
40
83
  end
41
84
  end
42
85
  end
@@ -74,20 +74,16 @@ module Fog
74
74
  filters = {'instance-id' => [*filters]}
75
75
  end
76
76
 
77
- if filters.keys.any? {|key| key =~ /^tag/}
78
- Formatador.display_line("[yellow][WARN] describe_instances tag filters are not yet mocked[/] [light_black](#{caller.first})[/]")
79
- Fog::Mock.not_implemented
80
- end
81
-
82
77
  response = Excon::Response.new
83
78
 
84
79
  instance_set = @data[:instances].values
85
-
80
+ instance_set = apply_tag_filters(instance_set, filters)
81
+
86
82
  aliases = {
87
83
  'architecture' => 'architecture',
88
84
  'availability-zone' => 'availabilityZone',
89
85
  'client-token' => 'clientToken',
90
- 'dns-token' => 'dnsName',
86
+ 'dns-name' => 'dnsName',
91
87
  'group-id' => 'groupId',
92
88
  'image-id' => 'imageId',
93
89
  'instance-id' => 'instanceId',
@@ -59,11 +59,6 @@ module Fog
59
59
  Formatador.display_line("[yellow][WARN] describe_snapshots with a second param is deprecated, use describe_snapshots(options) instead[/] [light_black](#{caller.first})[/]")
60
60
  end
61
61
 
62
- if filters.keys.any? {|key| key =~ /^tag/}
63
- Formatador.display_line("[yellow][WARN] describe_snapshots tag filters are not yet mocked[/] [light_black](#{caller.first})[/]")
64
- Fog::Mock.not_implemented
65
- end
66
-
67
62
  response = Excon::Response.new
68
63
 
69
64
  snapshot_set = @data[:snapshots].values
@@ -75,6 +70,8 @@ module Fog
75
70
  Formatador.display_line("[yellow][WARN] describe_snapshots with RestorableBy is not mocked[/] [light_black](#{caller.first})[/]")
76
71
  end
77
72
 
73
+ snapshot_set = apply_tag_filters(snapshot_set, filters)
74
+
78
75
  aliases = {
79
76
  'description' => 'description',
80
77
  'owner-id' => 'ownerId',
@@ -85,11 +82,12 @@ module Fog
85
82
  'volume-id' => 'volumeId',
86
83
  'volume-size' => 'volumeSize'
87
84
  }
85
+
88
86
  for filter_key, filter_value in filters
89
87
  aliased_key = aliases[filter_key]
90
88
  snapshot_set = snapshot_set.reject{|snapshot| ![*filter_value].include?(snapshot[aliased_key])}
91
89
  end
92
-
90
+
93
91
  snapshot_set.each do |snapshot|
94
92
  case snapshot['status']
95
93
  when 'in progress', 'pending'
@@ -50,15 +50,11 @@ module Fog
50
50
  filters = {'volume-id' => [*filters]}
51
51
  end
52
52
 
53
- if filters.keys.any? {|key| key =~ /^tag/}
54
- Formatador.display_line("[yellow][WARN] describe_volumes tag filters are not yet mocked[/] [light_black](#{caller.first})[/]")
55
- Fog::Mock.not_implemented
56
- end
57
-
58
53
  response = Excon::Response.new
59
54
 
60
55
  volume_set = @data[:volumes].values
61
-
56
+ volume_set = apply_tag_filters(volume_set, filters)
57
+
62
58
  aliases = {
63
59
  'availability-zone' => 'availabilityZone',
64
60
  'create-time' => 'createTime',
@@ -8,6 +8,7 @@ $LOAD_PATH.unshift __LIB_DIR__ unless
8
8
  require 'rubygems'
9
9
  require 'base64'
10
10
  require 'cgi'
11
+ require 'uri'
11
12
  require 'excon'
12
13
  require 'fileutils'
13
14
  require 'formatador'
@@ -13,7 +13,7 @@ module Fog
13
13
  unless block_given?
14
14
  if (parser = params.delete(:parser))
15
15
  body = Nokogiri::XML::SAX::PushParser.new(parser)
16
- block = lambda { |chunk| body << chunk }
16
+ block = lambda { |chunk, remaining, total| body << chunk }
17
17
  end
18
18
  end
19
19
 
@@ -18,7 +18,10 @@ module Fog
18
18
 
19
19
  # @return [String] The path for configuration_file
20
20
  def self.credentials_path
21
- @credential_path ||= File.expand_path(ENV["FOG_RC"] || (ENV['HOME'] && '~/.fog'))
21
+ @credential_path ||= begin
22
+ path = ENV["FOG_RC"] || (ENV['HOME'] && '~/.fog')
23
+ File.expand_path(path) if path
24
+ end
22
25
  end
23
26
 
24
27
  # @return [String] The new path for credentials file
@@ -85,6 +88,7 @@ An alternate file may be used by placing its path in the FOG_RC environment vari
85
88
  :rackspace_api_key:
86
89
  :rackspace_username:
87
90
  :rackspace_servicenet:
91
+ :rackspace_cdn_ssl:
88
92
  :slicehost_password:
89
93
  :terremark_username:
90
94
  :terremark_password:
@@ -15,8 +15,7 @@ module Fog
15
15
  end
16
16
 
17
17
  def characters(string)
18
- @value ||= ''
19
- @value << string.strip
18
+ @value = string
20
19
  end
21
20
 
22
21
  def start_element(name, attrs = [])
@@ -51,11 +51,10 @@ module Fog
51
51
  begin
52
52
  Net::SSH.start(@address, @username, @options) do |ssh|
53
53
  commands.each do |command|
54
- escaped_command = command.sub(/'/, %{'"'"'})
55
- result = Result.new(escaped_command)
54
+ result = Result.new(command)
56
55
  ssh.open_channel do |ssh_channel|
57
56
  ssh_channel.request_pty
58
- ssh_channel.exec(%{bash -lc '#{escaped_command}'}) do |channel, success|
57
+ ssh_channel.exec(command) do |channel, success|
59
58
  unless success
60
59
  raise "Could not execute command: #{command.inspect}"
61
60
  end
@@ -16,7 +16,7 @@ module Fog
16
16
  attribute :created_at, :aliases => ['SubmittedAt']
17
17
 
18
18
  def initialize(attributes={})
19
- self.ttl ||= 3600
19
+ self.ttl ||= 3600
20
20
  super
21
21
  end
22
22
 
@@ -19,6 +19,7 @@ module Fog
19
19
  attribute :minimum
20
20
 
21
21
  def initialize(attributes = {})
22
+ self.ttl ||= 3600
22
23
  super(attributes)
23
24
  end
24
25
 
@@ -38,7 +38,13 @@ module Fog
38
38
  requires :key
39
39
  @public_url ||= begin
40
40
  begin response = connection.cdn.head_container(key)
41
- response.headers['X-CDN-Enabled'] == 'True' && response.headers['X-CDN-URI']
41
+ if response.headers['X-CDN-Enabled'] == 'True'
42
+ if connection.rackspace_cdn_ssl == true
43
+ response.headers['X-CDN-SSL-URI']
44
+ else
45
+ response.headers['X-CDN-URI']
46
+ end
47
+ end
42
48
  rescue Fog::Service::NotFound
43
49
  nil
44
50
  end
@@ -56,7 +62,7 @@ module Fog
56
62
  end
57
63
  true
58
64
  end
59
-
65
+
60
66
  end
61
67
 
62
68
  end
@@ -3,7 +3,7 @@ module Fog
3
3
  class Storage < Fog::Service
4
4
 
5
5
  requires :rackspace_api_key, :rackspace_username
6
- recognizes :rackspace_auth_url, :rackspace_servicenet, :persistent
6
+ recognizes :rackspace_auth_url, :rackspace_servicenet, :rackspace_cdn_ssl, :persistent
7
7
  recognizes :provider # remove post deprecation
8
8
 
9
9
  model_path 'fog/storage/models/rackspace'
@@ -68,6 +68,7 @@ module Fog
68
68
 
69
69
  class Real
70
70
  include Utils
71
+ attr_reader :rackspace_cdn_ssl
71
72
 
72
73
  def initialize(options={})
73
74
  unless options.delete(:provider)
@@ -81,6 +82,7 @@ module Fog
81
82
  require 'json'
82
83
  @rackspace_api_key = options[:rackspace_api_key]
83
84
  @rackspace_username = options[:rackspace_username]
85
+ @rackspace_cdn_ssl = options[:rackspace_cdn_ssl]
84
86
  credentials = Fog::Rackspace.authenticate(options)
85
87
  @auth_token = credentials['X-Auth-Token']
86
88
 
@@ -12,7 +12,7 @@ module Fog
12
12
  response = request(
13
13
  :expects => 204,
14
14
  :method => 'DELETE',
15
- :path => CGI.escape(name)
15
+ :path => URI.escape(name)
16
16
  )
17
17
  response
18
18
  end
@@ -13,7 +13,7 @@ module Fog
13
13
  response = request(
14
14
  :expects => 204,
15
15
  :method => 'DELETE',
16
- :path => "#{CGI.escape(container)}/#{CGI.escape(object)}"
16
+ :path => "#{URI.escape(container)}/#{URI.escape(object)}"
17
17
  )
18
18
  response
19
19
  end