dropmyemail-openstack 1.0.9

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.
@@ -0,0 +1,123 @@
1
+ module OpenStack
2
+ module Volume
3
+
4
+ class Connection
5
+
6
+ attr_accessor :connection
7
+ attr_reader :volumes_native
8
+
9
+ def initialize(connection)
10
+ @connection = connection
11
+ OpenStack::Authentication.init(@connection)
12
+ @volumes_native, @volume_path = check_if_native("volumes")
13
+ @snapshots_native, @snapshot_path = check_if_native("snapshots")
14
+ end
15
+
16
+ # Returns true if the authentication was successful and returns false otherwise.
17
+ #
18
+ # cs.authok?
19
+ # => true
20
+ def authok?
21
+ @connection.authok
22
+ end
23
+
24
+ #require params: {:display_name, :size}
25
+ #optional params: {:display_description, :metadata=>{:key=>val, ...}, :availability_zone, :volume_type }
26
+ #returns OpenStack::Volume::Volume object
27
+ def create_volume(options)
28
+ raise OpenStack::Exception::MissingArgument, ":display_name and :size must be specified to create a volume" unless (options[:display_name] && options[:size])
29
+ data = JSON.generate(:volume => options)
30
+ response = @connection.csreq("POST",@connection.service_host,"#{@connection.service_path}/#{@volume_path}",@connection.service_port,@connection.service_scheme,{'content-type' => 'application/json'},data)
31
+ OpenStack::Exception.raise_exception(response) unless response.code.match(/^20.$/)
32
+ volume_info = JSON.parse(response.body)["volume"]
33
+ volume = OpenStack::Volume::Volume.new(volume_info)
34
+ end
35
+
36
+ #no options documented in API at Nov 2012
37
+ #(e.g. like limit/marker as used in Nova for servers)
38
+ def list_volumes
39
+ response = @connection.req("GET", "/#{@volume_path}")
40
+ volumes_hash = JSON.parse(response.body)["volumes"]
41
+ volumes_hash.inject([]){|res, current| res << OpenStack::Volume::Volume.new(current); res}
42
+ end
43
+ alias :volumes :list_volumes
44
+
45
+
46
+ def get_volume(vol_id)
47
+ response = @connection.req("GET", "/#{@volume_path}/#{vol_id}")
48
+ volume_hash = JSON.parse(response.body)["volume"]
49
+ OpenStack::Volume::Volume.new(volume_hash)
50
+ end
51
+ alias :volume :get_volume
52
+
53
+ def delete_volume(vol_id)
54
+ response = @connection.req("DELETE", "/#{@volume_path}/#{vol_id}")
55
+ true
56
+ end
57
+
58
+ def list_snapshots
59
+ response = @connection.req("GET", "/#{@snapshot_path}")
60
+ snapshot_hash = JSON.parse(response.body)["snapshots"]
61
+ snapshot_hash.inject([]){|res, current| res << OpenStack::Volume::Snapshot.new(current); res}
62
+ end
63
+ alias :snapshots :list_snapshots
64
+
65
+ def get_snapshot(snap_id)
66
+ response = @connection.req("GET", "/#{@snapshot_path}/#{snap_id}")
67
+ snapshot_hash = JSON.parse(response.body)["snapshot"]
68
+ OpenStack::Volume::Snapshot.new(snapshot_hash)
69
+ end
70
+ alias :snapshot :get_snapshot
71
+
72
+ #require params: {:display_name, :volume_id}
73
+ #optional params: {:display_description, :metadata=>{:key=>val, ...}, :availability_zone, :volume_type }
74
+ #returns OpenStack::Volume::Snapshot object
75
+ def create_snapshot(options)
76
+ raise OpenStack::Exception::MissingArgument, ":volume_id and :display_name must be specified to create a snapshot" unless (options[:display_name] && options[:volume_id])
77
+ #:force documented in API but not explained... clarify (fails without)
78
+ options.merge!({:force=>"true"})
79
+ data = JSON.generate(:snapshot => options)
80
+ response = @connection.csreq("POST",@connection.service_host,"#{@connection.service_path}/#{@snapshot_path}",@connection.service_port,@connection.service_scheme,{'content-type' => 'application/json'},data)
81
+ OpenStack::Exception.raise_exception(response) unless response.code.match(/^20.$/)
82
+ snapshot_info = JSON.parse(response.body)["snapshot"]
83
+ OpenStack::Volume::Snapshot.new(snapshot_info)
84
+ end
85
+
86
+ def delete_snapshot(snap_id)
87
+ @connection.req("DELETE", "/#{@snapshot_path}/#{snap_id}")
88
+ true
89
+ end
90
+
91
+ private
92
+
93
+ #fudge... not clear if volumes support is available as 'native' volume API or
94
+ #as the os-volumes extension. Need to probe to find out (for now)
95
+ #see https://lists.launchpad.net/openstack/msg16601.html
96
+ def check_if_native(entity) #volumes or snapshots
97
+ native = extension = false
98
+ #check if 'native' volume API present:
99
+ begin
100
+ response = @connection.req("GET", "/#{entity}")
101
+ native = true if response.code.match(/^20.$/)
102
+ return true, entity
103
+ rescue OpenStack::Exception::ItemNotFound => not_found
104
+ native = false
105
+ end
106
+ #check if available as extension:
107
+ begin
108
+ response = @connection.req("GET", "/os-#{entity}")
109
+ extension = true if response.code.match(/^20.$/)
110
+ return false, "os-#{entity}"
111
+ rescue OpenStack::Exception::ItemNotFound => not_found
112
+ extension = false
113
+ end
114
+ raise OpenStack::Exception::NotImplemented.new("No Volumes support for this provider", 501, "No #{entity} Support") unless (native || extension)
115
+ end
116
+
117
+
118
+
119
+
120
+ end
121
+
122
+ end
123
+ end
@@ -0,0 +1,25 @@
1
+ module OpenStack
2
+ module Volume
3
+ class Snapshot
4
+
5
+ attr_reader :id
6
+ attr_reader :display_name
7
+ attr_reader :display_description
8
+ attr_reader :volume_id
9
+ attr_reader :status
10
+ attr_reader :size
11
+ attr_reader :created_at
12
+
13
+ def initialize(snap_info)
14
+ @id = snap_info["id"]
15
+ @display_name = snap_info["display_name"] || snap_info["displayName"]
16
+ @display_description = snap_info["display_description"] || snap_info["displayDescription"]
17
+ @volume_id = snap_info["volume_id"] || snap_info["volumeId"]
18
+ @status = snap_info["status"]
19
+ @size = snap_info["size"]
20
+ @created_at = snap_info["created_at"] || snap_info["createdAt"]
21
+ end
22
+
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,31 @@
1
+ module OpenStack
2
+ module Volume
3
+ class Volume
4
+
5
+ attr_reader :id
6
+ attr_reader :display_name
7
+ attr_reader :display_description
8
+ attr_reader :size
9
+ attr_reader :volume_type
10
+ attr_reader :metadata
11
+ attr_reader :availability_zone
12
+ attr_reader :snapshot_id
13
+ attr_reader :attachments
14
+ attr_reader :created_at
15
+
16
+ def initialize(volume_info)
17
+ @id = volume_info["id"]
18
+ @display_name = volume_info["display_name"] || volume_info["displayName"]
19
+ @display_description = volume_info["display_description"] || volume_info["displayDescription"]
20
+ @size = volume_info["size"]
21
+ @volume_type = volume_info["volume_type"] || volume_info["volumeType"]
22
+ @metadata = volume_info["metadata"]
23
+ @availability_zone = volume_info["availability_zone"] || volume_info["availabilityZone"]
24
+ @snapshot_id = volume_info["snapshot_id"] || volume_info["snapshotId"]
25
+ @attachments = volume_info["attachments"]
26
+ @created_at = volume_info["created_at"] || volume_info["createdAt"]
27
+ end
28
+
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,134 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class AuthenticationTest < Test::Unit::TestCase
4
+
5
+ def test_good_authentication
6
+ response = {'x-server-management-url' => 'http://server-manage.example.com/path', 'x-auth-token' => 'dummy_token'}
7
+ response.stubs(:code).returns('204')
8
+ server = mock(:use_ssl= => true, :verify_mode= => true, :start => true, :finish => true)
9
+ server.stubs(:get).returns(response)
10
+ Net::HTTP.stubs(:new).returns(server)
11
+ connection = stub(:authuser => 'good_user',:authtenant => {:type=>"tenantName", :value=>'good_tenant'}, :authkey => 'bad_key', :auth_host => "a.b.c", :auth_port => "443", :auth_scheme => "https", :auth_path => "/v1.0", :service_type=>"compute", :authok= => true, :authtoken= => true, :service_host= => "", :service_path= => "", :service_path => "", :service_port= => "", :service_scheme= => "", :proxy_host => nil, :proxy_port => nil, :api_path => '/foo')
12
+ result = OpenStack::Authentication.init(connection)
13
+ assert_equal result.class, OpenStack::AuthV10
14
+ end
15
+
16
+ def test_bad_authentication
17
+ response = mock()
18
+ response.stubs(:code).returns('499')
19
+ server = mock(:use_ssl= => true, :verify_mode= => true, :start => true)
20
+ server.stubs(:get).returns(response)
21
+ Net::HTTP.stubs(:new).returns(server)
22
+ connection = stub(:authuser => 'bad_user', :authtenant => {:type=>"tenantName", :value=>'good_tenant'}, :authkey => 'bad_key', :auth_host => "a.b.c", :auth_port => "443", :auth_scheme => "https", :auth_path => "/v1.0", :authok= => true, :authtoken= => true, :proxy_host => nil, :proxy_port => nil, :api_path => '/foo')
23
+ assert_raises(OpenStack::Exception::Authentication) do
24
+ result = OpenStack::Authentication.init(connection)
25
+ end
26
+ end
27
+
28
+ def test_bad_hostname
29
+ Net::HTTP.stubs(:new).raises(OpenStack::Exception::Connection)
30
+ connection = stub(:authuser => 'bad_user', :authtenant => {:type=>"tenantName", :value=>'good_tenant'}, :authkey => 'bad_key', :auth_host => "a.b.c", :auth_port => "443", :auth_scheme => "https", :auth_path => "/v1.0", :authok= => true, :authtoken= => true, :proxy_host => nil, :proxy_port => nil, :api_path => '/foo')
31
+ assert_raises(OpenStack::Exception::Connection) do
32
+ result = OpenStack::Authentication.init(connection)
33
+ end
34
+ end
35
+
36
+ def test_service_region
37
+ server = get_test_auth_server
38
+ Net::HTTP.stubs(:new).returns(server)
39
+ server.stubs(:started?).returns(true)
40
+ connection = stub(:authuser => 'good_user', :auth_method => "password",:authtenant => {:type=>"tenantName", :value=>'good_tenant'} , :authkey => 'bad_key', :auth_host => "a.b.c", :auth_port => "443", :auth_scheme => "https", :auth_path => "/v2.0", :authok= => true, :authtoken= => true, :service_host= => "", :service_path= => "", :service_path => "", :service_port= => "", :service_scheme= => "", :proxy_host => nil, :proxy_port => nil, :api_path => '/foo', :service_type => "compute", :service_name => "cloudServers", :region => "South")
41
+ result = OpenStack::Authentication.init(connection)
42
+ assert_equal("compute.south.host", result.uri.host)
43
+ end
44
+
45
+ def test_service_name
46
+ server = get_test_auth_server
47
+ Net::HTTP.stubs(:new).returns(server)
48
+ server.stubs(:started?).returns(true)
49
+ connection = stub(:authuser => 'good_user', :auth_method=>"password", :authtenant => {:type=>"tenantName", :value=>'good_tenant'}, :authkey => 'bad_key', :auth_host => "a.b.c", :auth_port => "443", :auth_scheme => "https", :auth_path => "/v2.0", :authok= => true, :authtoken= => true, :service_host= => "", :service_path= => "", :service_path => "", :service_port= => "", :service_scheme= => "", :proxy_host => nil, :proxy_port => nil, :api_path => '/foo', :service_type => "nova", :service_name => "cloudCompute", :region => "South")
50
+ result = OpenStack::Authentication.init(connection)
51
+ assert_equal("nova.south.host", result.uri.host)
52
+ end
53
+
54
+ def test_service_type
55
+ server = get_test_auth_server
56
+ Net::HTTP.stubs(:new).returns(server)
57
+ server.stubs(:started?).returns(true)
58
+ connection = stub(:authuser => 'good_user', :auth_method => "password", :authtenant => {:type=>"tenantName", :value=>'good_tenant'}, :authkey => 'bad_key', :auth_host => "a.b.c", :auth_port => "443", :auth_scheme => "https", :auth_path => "/v2.0", :authok= => true, :authtoken= => true, :service_host= => "", :service_path= => "", :service_path => "", :service_port= => "", :service_scheme= => "", :proxy_host => nil, :proxy_port => nil, :api_path => '/foo', :service_type => "nova", :service_name => nil, :region => "North")
59
+ result = OpenStack::Authentication.init(connection)
60
+ assert_equal("nova.north.host", result.uri.host)
61
+ end
62
+
63
+
64
+ private
65
+ def get_test_auth_server
66
+ json_response = %{{
67
+ "access":{
68
+ "token":{
69
+ "id":"asdasdasd-adsasdads-asdasdasd-adsadsasd",
70
+ "expires":"2010-11-01T03:32:15-05:00"
71
+ },
72
+ "user":{
73
+ "id":"123",
74
+ "name":"testName",
75
+ "roles":[{
76
+ "id":"234",
77
+ "name":"compute:admin"
78
+ },
79
+ {
80
+ "id":"235",
81
+ "name":"object-store:admin",
82
+ "tenantId":"1"
83
+ }
84
+ ],
85
+ "roles_links":[]
86
+ },
87
+ "serviceCatalog":[{
88
+ "name":"cloudServers",
89
+ "type":"compute",
90
+ "endpoints":[{
91
+ "publicURL":"https://compute.north.host/v1.1",
92
+ "region":"North"
93
+ },
94
+ {
95
+ "publicURL":"https://compute.south.host/v1.1",
96
+ "region":"South"
97
+ }
98
+ ],
99
+ "endpoints_links":[]
100
+ },
101
+ {
102
+ "name":"cloudCompute",
103
+ "type":"nova",
104
+ "endpoints":[{
105
+ "publicURL":"https://nova.north.host/v1.1",
106
+ "region":"North"
107
+ },
108
+ {
109
+ "publicURL":"https://nova.south.host/v1.1",
110
+ "region":"South"
111
+ }
112
+ ],
113
+ "endpoints_links":[{
114
+ "rel":"next",
115
+ "href":"https://identity.north.host/v2.0/endpoints?marker=2"
116
+ }
117
+ ]
118
+ }
119
+ ],
120
+ "serviceCatalog_links":[{
121
+ "rel":"next",
122
+ "href":"https://identity.host/v2.0/endpoints?session=2hfh8Ar&marker=2"
123
+ }
124
+ ]
125
+ }
126
+ }}
127
+
128
+ response = {'x-server-management-url' => 'http://server-manage.example.com/path', 'x-auth-token' => 'dummy_token'}
129
+ response.stubs(:code => "200", :body => json_response)
130
+ server = mock(:use_ssl= => true, :verify_mode= => true, :start => true, :finish => true)
131
+ server.stubs(:post).returns(response)
132
+ return server
133
+ end
134
+ end
@@ -0,0 +1,39 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class ComputeConnectionTest < Test::Unit::TestCase
4
+
5
+ def setup
6
+ connection = stub()
7
+ OpenStack::Authentication.stubs(:init).returns(connection)
8
+ end
9
+
10
+ def test_init_connection_no_credentials
11
+ assert_raises(OpenStack::Exception::MissingArgument) do
12
+ conn = OpenStack::Connection.create(:api_key => "AABBCCDD11", :auth_url => "a.b.c")
13
+ end
14
+ end
15
+
16
+ def test_init_connection_no_password
17
+ assert_raises(OpenStack::Exception::MissingArgument) do
18
+ conn = OpenStack::Connection.create(:username => "test_account", :auth_url => "a.b.c")
19
+ end
20
+ end
21
+
22
+ def test_init_connection_no_auth_url
23
+ assert_raises(OpenStack::Exception::MissingArgument) do
24
+ conn = OpenStack::Connection.create(:username => "test_account", :api_key => "AABBCCDD11")
25
+ end
26
+ end
27
+
28
+ def test_init_connection_bad_auth_url
29
+ assert_raises(OpenStack::Exception::InvalidArgument) do
30
+ conn = OpenStack::Connection.create(:username => "test_account", :api_key => "AABBCCDD11", :auth_url => "***")
31
+ end
32
+ end
33
+
34
+ def test_init_connection
35
+ conn = OpenStack::Connection.create(:username => "test_account", :api_key => "AABBCCDD11", :auth_url => "https://a.b.c")
36
+ assert_not_nil conn, "Connection.new returned nil."
37
+ end
38
+
39
+ end
@@ -0,0 +1,49 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class ExceptionTest < Test::Unit::TestCase
4
+
5
+ def test_400_cloud_servers_fault
6
+ response = mock()
7
+ response.stubs(:code => "400", :body => "{\"ComputeFault\":{\"message\":\"422 Unprocessable Entity: We could not process your request at this time. We have been notified and are looking into the issue. [E03]\",\"details\":\"com.rackspace.cloud.service.servers.OpenStack::ComputeFault: Fault occured\",\"code\":400}}" )
8
+ exception=nil
9
+ begin
10
+ OpenStack::Exception.raise_exception(response)
11
+ rescue Exception => e
12
+ exception=e
13
+ end
14
+ assert_equal(OpenStack::Exception::ComputeFault, e.class)
15
+ assert_equal("400", e.response_code)
16
+ assert_not_nil(e.response_body)
17
+ end
18
+
19
+ def test_413_over_limit
20
+ response = mock()
21
+ response.stubs(:code => "413", :body => "{\"overLimit\":{\"message\":\"Too many requests...\",\"code\":413,\"retryAfter\":\"2010-08-25T10:47:57.890-05:00\"}}")
22
+ exception=nil
23
+ begin
24
+ OpenStack::Exception.raise_exception(response)
25
+ rescue Exception => e
26
+ exception=e
27
+ end
28
+ assert_equal(OpenStack::Exception::OverLimit, e.class)
29
+ assert_equal("413", e.response_code)
30
+ assert_not_nil(e.response_body)
31
+ end
32
+
33
+ def test_other
34
+ response = mock()
35
+ body="{\"blahblah\":{\"message\":\"Failed...\",\"code\":500}}"
36
+ response.stubs(:code => "500", :body => body)
37
+ exception=nil
38
+ begin
39
+ OpenStack::Exception.raise_exception(response)
40
+ rescue Exception => e
41
+ exception=e
42
+ end
43
+ assert_equal(OpenStack::Exception::Other, exception.class)
44
+ assert_equal("500", exception.response_code)
45
+ assert_not_nil(exception.response_body)
46
+ assert_equal(body, exception.response_body)
47
+ end
48
+
49
+ end
@@ -0,0 +1,210 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class MetadataTest < Test::Unit::TestCase
4
+
5
+ include TestConnection
6
+
7
+ def setup
8
+ @compute=get_test_connection
9
+ end
10
+
11
+ def test_metadata_uses_initial_values
12
+ data = {'key1' => 'value1', 'key2' => 'value2'}
13
+ metadata = OpenStack::Compute::Metadata.new(@conn, 'blah', data)
14
+ assert_equal('value1', metadata['key1'])
15
+ assert_equal('value2', metadata['key2'])
16
+ assert_equal(nil, metadata['key0'])
17
+ end
18
+
19
+ def test_metadata_presents_saved_values
20
+ metadata = OpenStack::Compute::Metadata.new(@conn, 'blah')
21
+ metadata['key3'] = 'value3'
22
+ assert_equal('value3', metadata['key3'])
23
+ assert_equal(nil, metadata['key0'])
24
+ end
25
+
26
+ def test_metadata_presents_stored_values
27
+ metadata = OpenStack::Compute::Metadata.new(@conn, 'blah')
28
+ metadata.store('key3', 'value3')
29
+ assert_equal('value3', metadata['key3'])
30
+ assert_equal(nil, metadata['key0'])
31
+ end
32
+
33
+ def test_metadata_looks_up_values_if_none_provided
34
+ data = {'metadata' => {'key4' => 'value4'}}
35
+ json = JSON.generate(data)
36
+ response = mock()
37
+ response.stubs(:code => "200", :body => json)
38
+ conn = mock()
39
+ @compute.stubs(:connection).returns(conn)
40
+ conn.stubs(:req).returns(response)
41
+ metadata = OpenStack::Compute::Metadata.new(@compute, 'blah')
42
+ assert_equal('value4', metadata['key4'])
43
+ assert_equal(nil, metadata['key0'])
44
+ end
45
+
46
+ def test_metadata_save_nil
47
+ conn = mock()
48
+ metadata = OpenStack::Compute::Metadata.new(conn, 'blah')
49
+ metadata.save # do nothing or we'd likely be deleting unintentionally
50
+ end
51
+
52
+ def test_metadata_save
53
+ data = {'key1' => 'value1', 'key3' => 'value3'}
54
+ json = JSON.generate({'metadata' => data})
55
+ response = mock()
56
+ response.stubs(:code => "200", :body => json)
57
+ compute = mock()
58
+ conn = mock()
59
+ compute.stubs(:connection).returns(conn)
60
+ conn.expects(:req).with('PUT', 'blah/metadata', :data => json).returns(response)
61
+ metadata = OpenStack::Compute::Metadata.new(compute, 'blah', data)
62
+ metadata.save
63
+ end
64
+
65
+ def test_metadata_update_all
66
+ data_in = {'key5' => 'value5', 'key6' => 'value6'}
67
+ data_out = {'key5' => 'value5', 'key6' => 'value6', 'key7' => 'value7'}
68
+ json_in = JSON.generate({'metadata' => data_in})
69
+ json_out = JSON.generate({'metadata' => data_out})
70
+ response = mock()
71
+ response.stubs(:code => "200", :body => json_out)
72
+ compute = mock()
73
+ conn = mock()
74
+ compute.stubs(:connection).returns(conn)
75
+ conn.expects(:req).with('POST', 'blah/metadata', :data => json_in).returns(response)
76
+ metadata = OpenStack::Compute::Metadata.new(compute, 'blah')
77
+ metadata['key5'] = 'value5'
78
+ metadata['key6'] = 'value6'
79
+ metadata.update
80
+ assert_equal('value5', metadata['key5'])
81
+ assert_equal('value6', metadata['key6'])
82
+ assert_equal('value7', metadata['key7'])
83
+ end
84
+
85
+ def test_metadata_update_some_keys
86
+ json1 = JSON.generate({'meta' => {'key1' => 'value1'}})
87
+ response1 = mock()
88
+ response1.stubs(:code => "200", :body => json1)
89
+ json2 = JSON.generate({'meta' => {'key2' => 'value2'}})
90
+ response2 = mock()
91
+ response2.stubs(:code => "200", :body => json2)
92
+ conn = mock()
93
+ compute = mock()
94
+ compute.stubs(:connection).returns(conn)
95
+ conn.expects(:req).with('PUT', 'blah/metadata/key1', :data => json1).returns(response1)
96
+ conn.expects(:req).with('PUT', 'blah/metadata/key2', :data => json2).returns(response2)
97
+ data = {'key1' => 'value1', 'key2' => 'value2', 'key3' => 'value3'}
98
+ metadata = OpenStack::Compute::Metadata.new(compute, 'blah', data)
99
+ metadata.update(['key1', 'key2'])
100
+ end
101
+
102
+ def test_metadata_update_one_key
103
+ json = JSON.generate({'meta' => {'key2' => 'value2'}})
104
+ response = mock()
105
+ response.stubs(:code => "200", :body => json)
106
+ compute = mock()
107
+ conn = mock()
108
+ compute.stubs(:connection).returns(conn)
109
+ conn.expects(:req).with('PUT', 'blah/metadata/key2', :data => json).returns(response)
110
+ data = {'key1' => 'value1', 'key2' => 'value2'}
111
+ metadata = OpenStack::Compute::Metadata.new(compute, 'blah', data)
112
+ metadata.update(['key2'])
113
+ end
114
+
115
+ def test_metadata_update_nonexistent_key
116
+ data = {'key1' => 'value1', 'key2' => 'value2'}
117
+ compute = mock()
118
+ conn = mock()
119
+ compute.stubs(:connection).returns(conn)
120
+ metadata = OpenStack::Compute::Metadata.new(compute, 'blah', data)
121
+ metadata.update(['key3']) # just asserting nothing is called on conn
122
+ end
123
+
124
+ def test_metadata_update_nil
125
+ compute = mock()
126
+ conn = mock()
127
+ compute.stubs(:connection).returns(conn)
128
+ metadata = OpenStack::Compute::Metadata.new(compute, 'blah')
129
+ metadata.update # just asserting nothing is called on the connection
130
+ end
131
+
132
+ def test_refresh_one_key
133
+ json = JSON.generate({'meta' => {'key1' => 'value1'}})
134
+ response = mock()
135
+ response.stubs(:code => "200", :body => json)
136
+ compute = mock()
137
+ conn = mock()
138
+ compute.stubs(:connection).returns(conn)
139
+ conn.expects(:req).with('GET', 'blah/metadata/key1').returns(response)
140
+ metadata = OpenStack::Compute::Metadata.new(compute, 'blah')
141
+ metadata.refresh(['key1'])
142
+ assert_equal('value1', metadata['key1'])
143
+ end
144
+
145
+ def test_refresh_some_keys_with_key_not_found
146
+ json = JSON.generate({'meta' => {'key1' => 'value1'}})
147
+ response = mock()
148
+ response.stubs(:code => "200", :body => json)
149
+ not_found = mock()
150
+ not_found.stubs(:code => "404")
151
+ compute = mock()
152
+ conn = mock()
153
+ compute.stubs(:connection).returns(conn)
154
+ conn.expects(:req).with('GET', 'blah/metadata/key1').returns(response)
155
+ conn.expects(:req).with('GET', 'blah/metadata/key0').returns(not_found)
156
+ metadata = OpenStack::Compute::Metadata.new(compute, 'blah')
157
+ metadata.refresh(['key1', 'key0'])
158
+ assert_equal('value1', metadata['key1'])
159
+ assert(metadata['key0'].nil?)
160
+ end
161
+
162
+ def test_delete_a_key
163
+ response = mock()
164
+ response.stubs(:code => "204")
165
+ connection = mock()
166
+ compute = mock()
167
+ compute.stubs(:connection).returns(connection)
168
+ connection.expects(:req).with('DELETE', 'blah/metadata/key1').returns(response)
169
+ metadata = OpenStack::Compute::Metadata.new(compute, 'blah')
170
+ metadata.delete!(['key1'])
171
+ end
172
+
173
+ def test_delete_a_key_with_prior_information
174
+ response = mock()
175
+ response.stubs(:code => "204")
176
+ comp = mock()
177
+ conn = mock()
178
+ comp.stubs(:connection).returns(conn)
179
+ conn.expects(:req).with('DELETE', 'blah/metadata/key1').returns(response)
180
+ data = {'key1' => 'value1', 'key2' => 'value2'}
181
+ metadata = OpenStack::Compute::Metadata.new(comp, 'blah', data)
182
+ metadata.delete!(['key1'])
183
+ assert(metadata['key1'].nil?)
184
+ assert_equal('value2', metadata['key2'])
185
+ end
186
+ ##
187
+ def test_delete_keys_softly
188
+ comp = mock()
189
+ conn = mock()
190
+ comp.stubs(:connection).returns(conn)
191
+ data = {'key1' => 'value1', 'key2' => 'value2', 'key3' => 'value3'}
192
+ metadata = OpenStack::Compute::Metadata.new(comp, 'blah', data)
193
+ metadata.delete(['key1', 'key3'])
194
+ assert(metadata['key1'].nil?)
195
+ assert_equal('value2', metadata['key2'])
196
+ assert(metadata['key3'].nil?)
197
+ end
198
+
199
+ def test_each_pair
200
+ comp = mock()
201
+ conn = mock()
202
+ comp.stubs(:connection).returns(conn)
203
+ data = {'key1' => 'value1', 'key2' => 'value2', 'key3' => 'value3'}
204
+ metadata = OpenStack::Compute::Metadata.new(comp, 'blah', data)
205
+ metadata.each_pair do |k,v|
206
+ assert_equal v, data[k]
207
+ end
208
+ end
209
+
210
+ end