vagrant-openstack-provider 0.5.2 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +34 -0
  3. data/lib/vagrant-openstack-provider.rb +2 -31
  4. data/lib/vagrant-openstack-provider/action.rb +21 -7
  5. data/lib/vagrant-openstack-provider/action/abstract_action.rb +22 -0
  6. data/lib/vagrant-openstack-provider/action/connect_openstack.rb +19 -40
  7. data/lib/vagrant-openstack-provider/action/create_server.rb +10 -6
  8. data/lib/vagrant-openstack-provider/action/create_stack.rb +67 -0
  9. data/lib/vagrant-openstack-provider/action/delete_server.rb +28 -3
  10. data/lib/vagrant-openstack-provider/action/delete_stack.rb +72 -0
  11. data/lib/vagrant-openstack-provider/action/message.rb +4 -2
  12. data/lib/vagrant-openstack-provider/action/read_ssh_info.rb +4 -2
  13. data/lib/vagrant-openstack-provider/action/read_state.rb +9 -4
  14. data/lib/vagrant-openstack-provider/action/resume.rb +4 -2
  15. data/lib/vagrant-openstack-provider/action/start_server.rb +4 -2
  16. data/lib/vagrant-openstack-provider/action/stop_server.rb +4 -2
  17. data/lib/vagrant-openstack-provider/action/suspend.rb +4 -2
  18. data/lib/vagrant-openstack-provider/action/sync_folders.rb +17 -13
  19. data/lib/vagrant-openstack-provider/action/wait_accessible.rb +5 -2
  20. data/lib/vagrant-openstack-provider/action/wait_active.rb +5 -3
  21. data/lib/vagrant-openstack-provider/action/wait_stop.rb +5 -3
  22. data/lib/vagrant-openstack-provider/catalog/openstack_catalog.rb +66 -0
  23. data/lib/vagrant-openstack-provider/client/domain.rb +41 -1
  24. data/lib/vagrant-openstack-provider/client/glance.rb +63 -0
  25. data/lib/vagrant-openstack-provider/client/heat.rb +50 -0
  26. data/lib/vagrant-openstack-provider/client/http_utils.rb +18 -0
  27. data/lib/vagrant-openstack-provider/client/neutron.rb +9 -15
  28. data/lib/vagrant-openstack-provider/client/nova.rb +3 -3
  29. data/lib/vagrant-openstack-provider/client/openstack.rb +10 -0
  30. data/lib/vagrant-openstack-provider/command/abstract_command.rb +7 -0
  31. data/lib/vagrant-openstack-provider/command/image_list.rb +12 -2
  32. data/lib/vagrant-openstack-provider/command/main.rb +1 -0
  33. data/lib/vagrant-openstack-provider/command/network_list.rb +3 -3
  34. data/lib/vagrant-openstack-provider/command/subnet_list.rb +25 -0
  35. data/lib/vagrant-openstack-provider/config.rb +78 -7
  36. data/lib/vagrant-openstack-provider/config_resolver.rb +36 -5
  37. data/lib/vagrant-openstack-provider/errors.rb +30 -2
  38. data/lib/vagrant-openstack-provider/logging.rb +39 -0
  39. data/lib/vagrant-openstack-provider/version.rb +1 -1
  40. data/locales/en.yml +107 -4
  41. data/spec/vagrant-openstack-provider/action/connect_openstack_spec.rb +255 -8
  42. data/spec/vagrant-openstack-provider/action/create_server_spec.rb +6 -1
  43. data/spec/vagrant-openstack-provider/action/create_stack_spec.rb +97 -0
  44. data/spec/vagrant-openstack-provider/action/delete_server_spec.rb +34 -6
  45. data/spec/vagrant-openstack-provider/action/delete_stack_spec.rb +64 -0
  46. data/spec/vagrant-openstack-provider/action/read_state_spec.rb +13 -1
  47. data/spec/vagrant-openstack-provider/action/sync_folders_spec.rb +1 -0
  48. data/spec/vagrant-openstack-provider/action/wait_active_spec.rb +1 -1
  49. data/spec/vagrant-openstack-provider/action/wait_stop_spec.rb +1 -1
  50. data/spec/vagrant-openstack-provider/client/glance_spec.rb +128 -0
  51. data/spec/vagrant-openstack-provider/client/heat_spec.rb +124 -0
  52. data/spec/vagrant-openstack-provider/client/neutron_spec.rb +33 -1
  53. data/spec/vagrant-openstack-provider/client/nova_spec.rb +2 -2
  54. data/spec/vagrant-openstack-provider/command/image_list_spec.rb +75 -23
  55. data/spec/vagrant-openstack-provider/command/subnet_list_spec.rb +46 -0
  56. data/spec/vagrant-openstack-provider/config_resolver_spec.rb +85 -19
  57. data/spec/vagrant-openstack-provider/config_spec.rb +177 -1
  58. data/spec/vagrant-openstack-provider/spec_helper.rb +3 -0
  59. metadata +20 -2
@@ -200,7 +200,12 @@ describe VagrantPlugins::Openstack::Action::CreateServer do
200
200
  it 'timeout before the server become active' do
201
201
  nova.stub(:get_server_details).and_return({ 'status' => 'BUILD' }, { 'status' => 'BUILD' })
202
202
  nova.should_receive(:get_server_details).with(env, 'server-01').at_least(2).times
203
- expect { @action.waiting_for_server_to_be_built(env, 'server-01', 1, 3) }.to raise_error Timeout::Error
203
+ expect { @action.waiting_for_server_to_be_built(env, 'server-01', 1, 3) }.to raise_error Errors::Timeout
204
+ end
205
+ it 'raise an error after one retry' do
206
+ nova.stub(:get_server_details).and_return({ 'status' => 'BUILD' }, { 'status' => 'ERROR' })
207
+ nova.should_receive(:get_server_details).with(env, 'server-01').exactly(2).times
208
+ expect { @action.waiting_for_server_to_be_built(env, 'server-01', 1, 3) }.to raise_error Errors::ServerStatusError
204
209
  end
205
210
  end
206
211
  end
@@ -0,0 +1,97 @@
1
+ require 'vagrant-openstack-provider/spec_helper'
2
+ require 'ostruct'
3
+ require 'sshkey'
4
+
5
+ include VagrantPlugins::Openstack::Action
6
+ include VagrantPlugins::Openstack::HttpUtils
7
+ include VagrantPlugins::Openstack::Domain
8
+
9
+ describe VagrantPlugins::Openstack::Action::CreateStack do
10
+
11
+ let(:config) do
12
+ double('config').tap do |config|
13
+ config.stub(:stacks) do
14
+ [
15
+ {
16
+ name: 'stack1',
17
+ template: 'template.yml'
18
+ },
19
+ {
20
+ name: 'stack2',
21
+ template: 'template.yml'
22
+ }
23
+ ]
24
+ end
25
+ end
26
+ end
27
+
28
+ let(:heat) do
29
+ double('heat')
30
+ end
31
+
32
+ let(:env) do
33
+ Hash.new.tap do |env|
34
+ env[:ui] = double('ui')
35
+ env[:ui].stub(:info).with(anything)
36
+ env[:machine] = double('machine')
37
+ env[:machine] = OpenStruct.new.tap do |m|
38
+ m.provider_config = config
39
+ m.id = nil
40
+ end
41
+ env[:openstack_client] = double('openstack_client')
42
+ env[:openstack_client].stub(:heat) { heat }
43
+ end
44
+ end
45
+ before :each do
46
+ CreateStack.send(:public, *CreateStack.private_instance_methods)
47
+ app = double('app')
48
+ app.stub(:call).with(anything)
49
+ @action = CreateStack.new(app, nil)
50
+ YAML.stub(:load_file).with('template.yml').and_return(YAML.load('
51
+ heat_template_version: 2013-05-23
52
+
53
+ description: Simple template to deploy a single compute instance
54
+
55
+ resources:
56
+ my_instance:
57
+ type: OS::Nova::Server
58
+ properties:
59
+ key_name: julien-mac
60
+ image: CoreOS
61
+ flavor: 1_vCPU_RAM_512M_HD_10G
62
+ '))
63
+
64
+ end
65
+
66
+ describe 'call' do
67
+ it 'should create stacks on heat twice' do
68
+ heat.stub(:create_stack).and_return('idstack')
69
+ File.should_receive(:write).with('/stack_stack1_id', 'idstack')
70
+ File.should_receive(:write).with('/stack_stack2_id', 'idstack')
71
+ # TODO(julienvey) assert content of create call is correct
72
+ heat.should_receive(:create_stack).exactly(2).times
73
+ heat.stub(:get_stack_details).and_return('stack_status' => 'CREATE_COMPLETE')
74
+ @action.call(env)
75
+ end
76
+ end
77
+
78
+ describe 'waiting_for_server_to_be_built' do
79
+ context 'when server is not yet active' do
80
+ it 'become active after one retry' do
81
+ heat.stub(:get_stack_details).and_return({ 'stack_status' => 'CREATE_IN_PROGRESS' }, { 'stack_status' => 'CREATE_COMPLETE' })
82
+ heat.should_receive(:get_stack_details).with(env, 'stack1', 'id-01').exactly(2).times
83
+ @action.waiting_for_stack_to_be_created(env, 'stack1', 'id-01', 1, 5)
84
+ end
85
+ it 'timeout before the server become active' do
86
+ heat.stub(:get_stack_details).and_return({ 'stack_status' => 'CREATE_IN_PROGRESS' }, { 'stack_status' => 'CREATE_IN_PROGRESS' })
87
+ heat.should_receive(:get_stack_details).with(env, 'stack1', 'id-01').at_least(2).times
88
+ expect { @action.waiting_for_stack_to_be_created(env, 'stack1', 'id-01', 1, 3) }.to raise_error Errors::Timeout
89
+ end
90
+ it 'raise an error after one retry' do
91
+ heat.stub(:get_stack_details).and_return({ 'stack_status' => 'CREATE_IN_PROGRESS' }, { 'stack_status' => 'CREATE_FAILED' })
92
+ heat.should_receive(:get_stack_details).with(env, 'stack1', 'id-01').exactly(2).times
93
+ expect { @action.waiting_for_stack_to_be_created(env, 'stack1', 'id-01', 1, 3) }.to raise_error Errors::StackStatusError
94
+ end
95
+ end
96
+ end
97
+ end
@@ -27,10 +27,11 @@ describe VagrantPlugins::Openstack::Action::DeleteServer do
27
27
  end
28
28
  end
29
29
 
30
- let(:app) do
31
- double('app').tap do |app|
32
- app.stub(:call).with(anything)
33
- end
30
+ before :each do
31
+ DeleteServer.send(:public, *DeleteServer.private_instance_methods)
32
+ app = double('app')
33
+ app.stub(:call).with(anything)
34
+ @action = DeleteServer.new(app, nil)
34
35
  end
35
36
 
36
37
  describe 'call' do
@@ -38,17 +39,44 @@ describe VagrantPlugins::Openstack::Action::DeleteServer do
38
39
  it 'delete server' do
39
40
  expect(nova).to receive(:delete_server).with(env, 'server_id')
40
41
  expect(nova).to receive(:delete_keypair_if_vagrant).with(env, 'server_id')
41
- @action = DeleteServer.new(app, nil)
42
+ expect(@action).to receive(:waiting_for_instance_to_be_deleted).with(env, 'server_id')
42
43
  @action.call(env)
43
44
  end
44
45
  end
45
46
  context 'when id is not present' do
46
47
  it 'delete server' do
48
+ env[:machine].id = nil
47
49
  expect(nova).should_not_receive(:delete_server)
48
50
  expect(nova).should_not_receive(:delete_keypair_if_vagrant)
49
- @action = DeleteServer.new(app, nil)
50
51
  @action.call(env)
51
52
  end
52
53
  end
53
54
  end
55
+
56
+ describe 'waiting_for_instance_to_be_deleted' do
57
+ context 'when server is not yet active' do
58
+ it 'become deleted after one retry' do
59
+ nova.stub(:get_server_details).once.and_return('status' => 'ACTIVE')
60
+ nova.stub(:get_server_details).once.and_raise(Errors::InstanceNotFound)
61
+ nova.should_receive(:get_server_details).with(env, 'server-01').exactly(1).times
62
+ @action.waiting_for_instance_to_be_deleted(env, 'server-01', 1, 5)
63
+ end
64
+ it 'become deleted after one retry' do
65
+ nova.stub(:get_server_details).and_return({ 'status' => 'ACTIVE' }, { 'status' => 'DELETED' })
66
+ nova.should_receive(:get_server_details).with(env, 'server-01').exactly(2).times
67
+ @action.waiting_for_instance_to_be_deleted(env, 'server-01', 1, 5)
68
+ end
69
+ it 'timeout before the server become active' do
70
+ nova.stub(:get_server_details).and_return({ 'status' => 'ACTIVE' }, { 'status' => 'ACTIVE' })
71
+ nova.should_receive(:get_server_details).with(env, 'server-01').at_least(2).times
72
+ expect { @action.waiting_for_instance_to_be_deleted(env, 'server-01', 1, 3) }.to raise_error Errors::Timeout
73
+ end
74
+ it 'raise an error after one retry' do
75
+ nova.stub(:get_server_details).and_return({ 'status' => 'ACTIVE' }, { 'status' => 'ERROR' })
76
+ nova.should_receive(:get_server_details).with(env, 'server-01').exactly(2).times
77
+ expect { @action.waiting_for_instance_to_be_deleted(env, 'server-01', 1, 3) }.to raise_error Errors::ServerStatusError
78
+ end
79
+ end
80
+ end
81
+
54
82
  end
@@ -0,0 +1,64 @@
1
+ require 'vagrant-openstack-provider/spec_helper'
2
+
3
+ describe VagrantPlugins::Openstack::Action::DeleteStack do
4
+
5
+ let(:heat) do
6
+ double('heat').tap do |app|
7
+ app.stub(:delete_stack)
8
+ end
9
+ end
10
+
11
+ let(:openstack_client) do
12
+ double('openstack_client').tap do |os|
13
+ os.stub(:heat) { heat }
14
+ end
15
+ end
16
+
17
+ let(:env) do
18
+ Hash.new.tap do |env|
19
+ env[:ui] = double('ui')
20
+ env[:ui].stub(:info).with(anything)
21
+ env[:ui].stub(:error).with(anything)
22
+ env[:openstack_client] = openstack_client
23
+ env[:machine] = OpenStruct.new.tap do |m|
24
+ m.id = 'server_id'
25
+ m.data_dir = '/test'
26
+ end
27
+ end
28
+ end
29
+
30
+ before :each do
31
+ DeleteStack.send(:public, *DeleteStack.private_instance_methods)
32
+ app = double('app')
33
+ app.stub(:call).with(anything)
34
+ @action = DeleteStack.new(app, nil)
35
+ end
36
+
37
+ describe 'call' do
38
+ context 'when id is present' do
39
+ it 'delete stack' do
40
+ expect(heat).to receive(:delete_stack).with(env, 'test1', '1234')
41
+ expect(heat).to receive(:delete_stack).with(env, 'test2', '2345')
42
+ @action.stub(:list_stack_files).with(env).and_return([
43
+ {
44
+ name: 'test1',
45
+ id: '1234'
46
+ }, {
47
+ name: 'test2',
48
+ id: '2345'
49
+ }])
50
+ expect(@action).to receive(:waiting_for_stack_to_be_deleted).with(env, 'test1', '1234')
51
+ expect(@action).to receive(:waiting_for_stack_to_be_deleted).with(env, 'test2', '2345')
52
+ @action.call(env)
53
+ end
54
+ end
55
+ context 'when id is not present' do
56
+ it 'delete stack' do
57
+ @action.stub(:list_stack_files).with(env).and_return([])
58
+ expect(heat).should_not_receive(:delete_stack)
59
+ expect(heat).should_not_receive(:waiting_for_stack_to_be_deleted)
60
+ @action.call(env)
61
+ end
62
+ end
63
+ end
64
+ end
@@ -27,7 +27,7 @@ describe VagrantPlugins::Openstack::Action::ReadState do
27
27
 
28
28
  describe 'call' do
29
29
  context 'when server id is present' do
30
- it 'set the state to the one returned by nova' do
30
+ it 'set the state to the vm_state returned by nova' do
31
31
  env[:machine].id = 'server_id'
32
32
  nova.stub(:get_server_details).and_return('status' => 'ACTIVE')
33
33
 
@@ -39,6 +39,18 @@ describe VagrantPlugins::Openstack::Action::ReadState do
39
39
 
40
40
  expect(env[:machine_state_id]).to eq(:active)
41
41
  end
42
+ it 'set the state to the task_state returned by nova extension' do
43
+ env[:machine].id = 'server_id'
44
+ nova.stub(:get_server_details).and_return('OS-EXT-STS:task_state' => 'SUSPENDING')
45
+
46
+ expect(nova).to receive(:get_server_details).with(env, 'server_id')
47
+ expect(app).to receive(:call)
48
+
49
+ @action = ReadState.new(app, nil)
50
+ @action.call(env)
51
+
52
+ expect(env[:machine_state_id]).to eq(:suspending)
53
+ end
42
54
  end
43
55
  context 'when server id is not present' do
44
56
  it 'set the state to :not_created' do
@@ -23,6 +23,7 @@ describe VagrantPlugins::Openstack::Action::SyncFolders do
23
23
  double('provider_config').tap do |c|
24
24
  c.stub(:rsync_includes) { nil }
25
25
  c.stub(:ssh_disabled) { false }
26
+ c.stub(:rsync_ignore_files) { ['.gitignore'] }
26
27
  end
27
28
  end
28
29
 
@@ -40,7 +40,7 @@ describe VagrantPlugins::Openstack::Action::WaitForServerToBeActive do
40
40
  nova.stub(:get_server_details).and_return({ 'status' => 'BUILD' }, { 'status' => 'BUILD' })
41
41
  expect(nova).to receive(:get_server_details).with(env, 'server_id').at_least(2).times
42
42
  @action = WaitForServerToBeActive.new(app, nil, 1, 2)
43
- expect { @action.call(env) }.to raise_error Timeout::Error
43
+ expect { @action.call(env) }.to raise_error Errors::Timeout
44
44
  end
45
45
  end
46
46
  end
@@ -40,7 +40,7 @@ describe VagrantPlugins::Openstack::Action::WaitForServerToStop do
40
40
  nova.stub(:get_server_details).and_return({ 'status' => 'ACTIVE' }, { 'status' => 'ACTIVE' })
41
41
  expect(nova).to receive(:get_server_details).with(env, 'server_id').at_least(2).times
42
42
  @action = WaitForServerToStop.new(app, nil, 1, 2)
43
- expect { @action.call(env) }.to raise_error Timeout::Error
43
+ expect { @action.call(env) }.to raise_error Errors::Timeout
44
44
  end
45
45
  end
46
46
  end
@@ -0,0 +1,128 @@
1
+ require 'vagrant-openstack-provider/spec_helper'
2
+
3
+ describe VagrantPlugins::Openstack::GlanceClient do
4
+
5
+ let(:env) do
6
+ Hash.new
7
+ end
8
+
9
+ let(:session) do
10
+ VagrantPlugins::Openstack.session
11
+ end
12
+
13
+ before :each do
14
+ session.token = '123456'
15
+ session.project_id = 'a1b2c3'
16
+ session.endpoints = { image: 'http://glance' }
17
+ @glance_client = VagrantPlugins::Openstack.glance
18
+ end
19
+
20
+ describe 'get_all_images' do
21
+ context 'with token and project_id acquainted' do
22
+ context 'and api version is v2' do
23
+ it 'returns all images with details' do
24
+ stub_request(:get, 'http://glance/images')
25
+ .with(
26
+ headers:
27
+ {
28
+ 'Accept' => 'application/json',
29
+ 'X-Auth-Token' => '123456'
30
+ })
31
+ .to_return(
32
+ status: 200,
33
+ body: '
34
+ {
35
+ "images": [
36
+ { "id": "i1", "name": "image1", "visibility": "public", "size": "1024", "min_ram": "1", "min_disk": "10" },
37
+ { "id": "i2", "name": "image2", "visibility": "private", "size": "2048", "min_ram": "2", "min_disk": "20" }
38
+ ]
39
+ }')
40
+
41
+ images = @glance_client.get_all_images(env)
42
+
43
+ expect(images).to eq [Image.new('i1', 'image1', 'public', '1024', '1', '10'),
44
+ Image.new('i2', 'image2', 'private', '2048', '2', '20')]
45
+ end
46
+ end
47
+
48
+ context 'and api version is v1' do
49
+ it 'returns all images with details' do
50
+ stub_request(:get, 'http://glance/images')
51
+ .with(
52
+ headers:
53
+ {
54
+ 'Accept' => 'application/json',
55
+ 'X-Auth-Token' => '123456'
56
+ })
57
+ .to_return(
58
+ status: 200,
59
+ body: '
60
+ {
61
+ "images": [
62
+ { "id": "i1", "name": "image1", "is_public": true },
63
+ { "id": "i2", "name": "image2", "is_public": false }
64
+ ]
65
+ }')
66
+
67
+ stub_request(:get, 'http://glance/images/detail')
68
+ .with(
69
+ headers:
70
+ {
71
+ 'Accept' => 'application/json',
72
+ 'X-Auth-Token' => '123456'
73
+ })
74
+ .to_return(
75
+ status: 200,
76
+ body: '
77
+ {
78
+ "images": [
79
+ { "id": "i1", "name": "image1", "is_public": true, "size": "1024", "min_ram": "1", "min_disk": "10" },
80
+ { "id": "i2", "name": "image2", "is_public": false, "size": "2048", "min_ram": "2", "min_disk": "20" }
81
+ ]
82
+ }')
83
+
84
+ images = @glance_client.get_all_images(env)
85
+
86
+ expect(images).to eq [Image.new('i1', 'image1', 'public', '1024', '1', '10'),
87
+ Image.new('i2', 'image2', 'private', '2048', '2', '20')]
88
+ end
89
+ end
90
+ end
91
+ end
92
+
93
+ describe 'get_api_version_list' do
94
+ it 'returns version list' do
95
+ stub_request(:get, 'http://glance/')
96
+ .with(header: { 'Accept' => 'application/json' })
97
+ .to_return(
98
+ status: 200,
99
+ body: '{
100
+ "versions": [
101
+ {
102
+ "status": "...",
103
+ "id": "v1.0",
104
+ "links": [
105
+ {
106
+ "href": "http://glance/v1.0",
107
+ "rel": "self"
108
+ }
109
+ ]
110
+ },
111
+ {
112
+ "status": "CURRENT",
113
+ "id": "v2.0",
114
+ "links": [
115
+ {
116
+ "href": "http://glance/v2.0",
117
+ "rel": "self"
118
+ }
119
+ ]
120
+ }
121
+ ]}')
122
+
123
+ versions = @glance_client.get_api_version_list(:image)
124
+
125
+ expect(versions.size).to eq(2)
126
+ end
127
+ end
128
+ end
@@ -0,0 +1,124 @@
1
+ require 'vagrant-openstack-provider/spec_helper'
2
+
3
+ describe VagrantPlugins::Openstack::NovaClient do
4
+ include FakeFS::SpecHelpers::All
5
+
6
+ let(:config) do
7
+ double('config').tap do |config|
8
+ config.stub(:openstack_auth_url) { 'http://heatAuthV2' }
9
+ config.stub(:openstack_orchestration_url) { nil }
10
+ config.stub(:tenant_name) { 'testTenant' }
11
+ config.stub(:username) { 'username' }
12
+ config.stub(:password) { 'password' }
13
+ end
14
+ end
15
+
16
+ let(:env) do
17
+ Hash.new.tap do |env|
18
+ env[:ui] = double('ui')
19
+ env[:ui].stub(:info).with(anything)
20
+ env[:machine] = double('machine')
21
+ env[:machine].stub(:provider_config) { config }
22
+ end
23
+ end
24
+
25
+ let(:session) do
26
+ VagrantPlugins::Openstack.session
27
+ end
28
+
29
+ before :each do
30
+ session.token = '123456'
31
+ session.project_id = 'a1b2c3'
32
+ session.endpoints = { orchestration: 'http://heat/a1b2c3' }
33
+ @heat_client = VagrantPlugins::Openstack.heat
34
+ end
35
+
36
+ describe 'stack_exists' do
37
+ context 'stack not found' do
38
+ it 'raise an StackNotFound error' do
39
+ stub_request(:get, 'http://heat/a1b2c3/stacks/stack_name/stack_id')
40
+ .with(
41
+ headers:
42
+ {
43
+ 'Accept' => 'application/json',
44
+ 'Accept-Encoding' => 'gzip, deflate',
45
+ 'X-Auth-Token' => '123456'
46
+ })
47
+ .to_return(
48
+ status: 404,
49
+ body: '{"itemNotFound": {"message": "Stack could not be found", "code": 404}}')
50
+
51
+ expect { @heat_client.get_stack_details(env, 'stack_name', 'stack_id') }.to raise_error(VagrantPlugins::Openstack::Errors::StackNotFound)
52
+
53
+ end
54
+ end
55
+ end
56
+
57
+ describe 'create_stack' do
58
+ context 'with token and project_id acquainted' do
59
+ it 'returns new stack id' do
60
+
61
+ stub_request(:post, 'http://heat/a1b2c3/stacks')
62
+ .with(
63
+ body: '{"stack_name":"stck","template":"toto"}',
64
+ headers:
65
+ {
66
+ 'Accept' => 'application/json',
67
+ 'Content-Type' => 'application/json',
68
+ 'X-Auth-Token' => '123456'
69
+ })
70
+ .to_return(status: 202, body: '{ "stack": { "id": "o1o2o3" } }')
71
+
72
+ stack_id = @heat_client.create_stack(env, name: 'stck', template: 'toto')
73
+
74
+ expect(stack_id).to eq('o1o2o3')
75
+ end
76
+ end
77
+ end
78
+
79
+ describe 'get_stack_details' do
80
+ context 'with token and project_id acquainted' do
81
+ it 'returns stack details' do
82
+
83
+ stub_request(:get, 'http://heat/a1b2c3/stacks/stack_id/stack_name')
84
+ .with(headers:
85
+ {
86
+ 'Accept' => 'application/json',
87
+ 'X-Auth-Token' => '123456'
88
+ })
89
+ .to_return(status: 200, body: '
90
+ {
91
+ "stack": {
92
+ "description": "sample stack",
93
+ "disable_rollback": "True",
94
+ "id": "stack_id",
95
+ "stack_name": "stack_name",
96
+ "stack_status": "CREATE_COMPLETE"
97
+ }
98
+ }')
99
+
100
+ stack = @heat_client.get_stack_details(env, 'stack_id', 'stack_name')
101
+
102
+ expect(stack['id']).to eq('stack_id')
103
+ expect(stack['stack_name']).to eq('stack_name')
104
+ end
105
+ end
106
+ end
107
+
108
+ describe 'delete_stack' do
109
+ context 'with token and project_id acquainted' do
110
+ it 'deletes the stack' do
111
+
112
+ stub_request(:delete, 'http://heat/a1b2c3/stacks/stack_id/stack_name')
113
+ .with(headers:
114
+ {
115
+ 'Accept' => 'application/json',
116
+ 'X-Auth-Token' => '123456'
117
+ })
118
+ .to_return(status: 204)
119
+
120
+ @heat_client.delete_stack(env, 'stack_id', 'stack_name')
121
+ end
122
+ end
123
+ end
124
+ end