kitchen-rackspace 0.22.0 → 0.22.1

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,150 @@
1
+ RSpec.describe Kitchen::Driver::Rackspace do
2
+ include_context "a driver for an instance"
3
+ include_context "a built server"
4
+
5
+ let(:credentials) do
6
+ { rackspace_username: "hello", rackspace_api_key: "world", wait_for: 1200 }
7
+ end
8
+ let(:config) { credentials }
9
+
10
+ describe "#create" do
11
+ it "generates a server name in the absence of one" do
12
+ driver.create(state)
13
+
14
+ expect(driver[:server_name]).to eq("a_monkey!")
15
+ end
16
+
17
+ it "records the server ID" do
18
+ driver.create(state)
19
+
20
+ expect(state[:server_id]).to eq("test123")
21
+ end
22
+
23
+ it "records the public IP as the hostname" do
24
+ driver.create(state)
25
+
26
+ expect(state[:hostname]).to eq("1.2.3.4")
27
+ end
28
+
29
+ it "records the login user" do
30
+ driver.create(state)
31
+
32
+ expect(state[:username]).to eq("root")
33
+ end
34
+
35
+ it "records the SSH port" do
36
+ driver.create(state)
37
+
38
+ expect(state[:port]).to eq("22")
39
+ end
40
+
41
+ it "records an overridden login user and port" do
42
+ config.merge!(username: "admin", port: "2222")
43
+ driver.create(state)
44
+
45
+ expect(state).to include(username: "admin", port: "2222")
46
+ end
47
+
48
+ it "waits for the server to report ready" do
49
+ expect(server).to receive(:wait_for)
50
+
51
+ driver.create(state)
52
+ end
53
+
54
+ it "waits for the instance to accept a login" do
55
+ expect(driver).to receive(:tcp_check).with(state)
56
+
57
+ driver.create(state)
58
+ end
59
+
60
+ it "does not wait for rackconnect by default" do
61
+ expect(driver).to_not receive(:rackconnect_check)
62
+
63
+ driver.create(state)
64
+ end
65
+
66
+ it "does not wait for managed service level by default" do
67
+ expect(driver).to_not receive(:servicelevel_check)
68
+
69
+ driver.create(state)
70
+ end
71
+
72
+ context "a Fog error" do
73
+ before do
74
+ allow_any_instance_of(described_class).to receive(:create_server)
75
+ .and_raise(Fog::Errors::Error, "Uhoh")
76
+ end
77
+
78
+ it "re-raises it as a Kitchen failure" do
79
+ expect { driver.create(state) }
80
+ .to raise_error(Kitchen::ActionFailed, "Uhoh")
81
+ end
82
+ end
83
+
84
+ # Anything the Rackspace API rejects surfaces from Excon rather than fog,
85
+ # and it has to be turned into a Kitchen failure too or the user gets a
86
+ # raw stack trace instead of a message.
87
+ context "an Excon error" do
88
+ before do
89
+ allow_any_instance_of(described_class).to receive(:create_server)
90
+ .and_raise(Excon::Errors::BadRequest, "Bad flavor")
91
+ end
92
+
93
+ it "re-raises it as a Kitchen failure" do
94
+ expect { driver.create(state) }
95
+ .to raise_error(Kitchen::ActionFailed, /Bad flavor/)
96
+ end
97
+ end
98
+ end
99
+
100
+ describe "#create with rackconnect_wait" do
101
+ let(:config) { credentials.merge(rackconnect_wait: true) }
102
+
103
+ it "waits for rackconnect" do
104
+ expect(driver).to receive(:rackconnect_check).with(server)
105
+
106
+ driver.create(state)
107
+ end
108
+
109
+ it "waits on the rackconnect automation status" do
110
+ driver.send(:rackconnect_check, server)
111
+
112
+ expect(server).to have_received(:wait_for)
113
+ end
114
+
115
+ # RackConnect hands the server a new public address as part of its work.
116
+ # Without the refresh, the stale address goes into the state file and the
117
+ # transport connects to nothing.
118
+ it "refreshes the server so the new public IP is picked up" do
119
+ driver.send(:rackconnect_check, server)
120
+
121
+ expect(server).to have_received(:update)
122
+ end
123
+ end
124
+
125
+ describe "#create with servicelevel_wait" do
126
+ let(:config) { credentials.merge(servicelevel_wait: true) }
127
+
128
+ it "waits for managed service level automation" do
129
+ expect(driver).to receive(:servicelevel_check).with(server)
130
+
131
+ driver.create(state)
132
+ end
133
+
134
+ it "waits on the service level automation status" do
135
+ driver.send(:servicelevel_check, server)
136
+
137
+ expect(server).to have_received(:wait_for)
138
+ end
139
+ end
140
+
141
+ describe "#create with servicenet" do
142
+ let(:config) { credentials.merge(servicenet: true) }
143
+
144
+ it "records the private IP as the hostname" do
145
+ driver.create(state)
146
+
147
+ expect(state[:hostname]).to eq("10.9.8.7")
148
+ end
149
+ end
150
+ end
@@ -0,0 +1,63 @@
1
+ RSpec.describe Kitchen::Driver::Rackspace do
2
+ include_context "a driver for an instance"
3
+
4
+ describe "#destroy" do
5
+ let(:server) { double("server", nil?: false, destroy: true) }
6
+ let(:servers) { instance_double(Fog::Compute::RackspaceV2::Servers, get: server) }
7
+ let(:state) { { server_id: "12345", hostname: "example.com" } }
8
+
9
+ before do
10
+ allow_any_instance_of(described_class).to receive(:compute)
11
+ .and_return(double("compute", servers:))
12
+ end
13
+
14
+ context "a live server that needs to be destroyed" do
15
+ it "destroys the server" do
16
+ expect(server).to receive(:destroy)
17
+
18
+ driver.destroy(state)
19
+ end
20
+
21
+ it "clears the server out of the state" do
22
+ driver.destroy(state)
23
+
24
+ expect(state).to_not include(:server_id)
25
+ expect(state).to_not include(:hostname)
26
+ end
27
+
28
+ it "says which server it destroyed" do
29
+ driver.destroy(state)
30
+
31
+ expect(logged_output.string).to match(/instance <12345> destroyed/)
32
+ end
33
+ end
34
+
35
+ context "no server ID present" do
36
+ let(:state) { {} }
37
+
38
+ it "does nothing" do
39
+ expect(driver).to_not receive(:compute)
40
+
41
+ expect { driver.destroy(state) }.to_not raise_error
42
+ end
43
+ end
44
+
45
+ context "a server that was already destroyed" do
46
+ let(:servers) do
47
+ instance_double(Fog::Compute::RackspaceV2::Servers, get: nil)
48
+ end
49
+
50
+ it "does not try to destroy the server again" do
51
+ expect(server).to_not receive(:destroy)
52
+
53
+ driver.destroy(state)
54
+ end
55
+
56
+ it "still clears the server out of the state" do
57
+ driver.destroy(state)
58
+
59
+ expect(state).to_not include(:server_id)
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,58 @@
1
+ RSpec.describe Kitchen::Driver::Rackspace do
2
+ include_context "a driver for an instance"
3
+
4
+ describe "#default_image" do
5
+ {
6
+ "ubuntu-12.04" => "f2d30a56-bc2b-4906-8027-92f8a45bbb10",
7
+ "ubuntu-12" => "f2d30a56-bc2b-4906-8027-92f8a45bbb10",
8
+ "ubuntu-14.04" => "e6baca58-c5f4-48d3-901a-abdeb0cfe907",
9
+ "ubuntu-14" => "e6baca58-c5f4-48d3-901a-abdeb0cfe907",
10
+ "ubuntu" => "9b3ae961-0ba0-4d5a-973f-2e79043f0ddd",
11
+ "centos-6" => "7d791876-4c8f-44a2-8d4b-e84bfb0b1c8c",
12
+ "centos" => "1a79f262-33d2-428c-924b-9852a6c15ea8",
13
+ }.each do |platform, id|
14
+ context "the platform is #{platform}" do
15
+ let(:platform_name) { platform }
16
+
17
+ it "resolves it to the right image ID" do
18
+ expect(driver[:image_id]).to eq(id)
19
+ end
20
+ end
21
+ end
22
+
23
+ # The bundled table has not been regenerated since 2016, so every modern
24
+ # platform name lands here. `image_id` then has no value, `required_config`
25
+ # rejects it, and the user has to supply one -- which is exactly what the
26
+ # README tells them to do. If this ever starts returning something, the
27
+ # README is wrong.
28
+ context "a platform the bundled table does not know" do
29
+ let(:platform_name) { "ubuntu-24.04" }
30
+
31
+ it "has no image to offer" do
32
+ expect(driver.default_image).to be_nil
33
+ end
34
+ end
35
+ end
36
+
37
+ describe "the bundled image table" do
38
+ subject(:images) { driver.send(:images) }
39
+
40
+ it "parses as JSON" do
41
+ expect { images }.to_not raise_error
42
+ end
43
+
44
+ it "is not empty" do
45
+ expect(images).to_not be_empty
46
+ end
47
+
48
+ it "maps every platform name to a UUID" do
49
+ expect(images.values).to all(match(/\A\h{8}(-\h{4}){3}-\h{12}\z/))
50
+ end
51
+
52
+ it "is only read from disk once" do
53
+ expect(IO).to receive(:read).once.and_call_original
54
+
55
+ 2.times { driver.send(:images) }
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,14 @@
1
+ RSpec.describe Kitchen::Driver::Rackspace do
2
+ include_context "a driver for an instance"
3
+
4
+ describe "plugin metadata" do
5
+ it "declares the driver API version" do
6
+ expect(described_class.instance_variable_get(:@api_version)).to eq(2)
7
+ end
8
+
9
+ it "reports its own gem version to kitchen diagnose" do
10
+ expect(driver.diagnose_plugin[:version])
11
+ .to eq(Kitchen::Driver::RACKSPACE_VERSION)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,63 @@
1
+ RSpec.describe Kitchen::Driver::Rackspace do
2
+ include_context "a driver for an instance"
3
+
4
+ describe "#default_name" do
5
+ subject(:name) { driver.default_name }
6
+
7
+ let(:login) { "user" }
8
+ let(:hostname) { "host" }
9
+
10
+ before do
11
+ allow(Etc).to receive(:getlogin).and_return(login)
12
+ allow(Socket).to receive(:gethostname).and_return(hostname)
13
+ end
14
+
15
+ it "generates a name" do
16
+ expect(name).to match(/^potatoes-user-host-(\S*)/)
17
+ end
18
+
19
+ context "a local node with a long hostname" do
20
+ let(:hostname) { "ab.c" * 20 }
21
+
22
+ it "limits the generated name to 63 characters" do
23
+ expect(name.length).to be <= 63
24
+ end
25
+ end
26
+
27
+ context "a long hostname, username, and base name" do
28
+ let(:login) { "abcd" * 20 }
29
+ let(:hostname) { "efgh" * 20 }
30
+ let(:instance_name) { "ijkl" * 20 }
31
+
32
+ it "limits the generated name to 63 characters" do
33
+ expect(name.length).to eq(63)
34
+ end
35
+ end
36
+
37
+ context "a login and hostname with punctuation in them" do
38
+ let(:login) { "some.u-se-r" }
39
+ let(:hostname) { "a.host-name" }
40
+ let(:instance_name) { "a.instance-name" }
41
+
42
+ it "strips out the dots to prevent bad server names" do
43
+ expect(name).to_not include(".")
44
+ end
45
+
46
+ it "strips out all but the three hyphen separators" do
47
+ expect(name.count("-")).to eq(3)
48
+ end
49
+ end
50
+
51
+ context "a non-login shell" do
52
+ let(:login) { nil }
53
+
54
+ it "subs in a placeholder login string" do
55
+ expect(name).to match(/^potatoes-nologin-/)
56
+ end
57
+ end
58
+
59
+ it "does not repeat itself" do
60
+ expect(driver.default_name).to_not eq(driver.default_name)
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,151 @@
1
+ RSpec.describe Kitchen::Driver::Rackspace do
2
+ include_context "a driver for an instance"
3
+
4
+ describe "#status" do
5
+ let(:server) { double("server", state: "ACTIVE") }
6
+ let(:servers) { instance_double(Fog::Compute::RackspaceV2::Servers) }
7
+
8
+ before do
9
+ allow_any_instance_of(described_class).to receive(:compute)
10
+ .and_return(double("compute", servers:))
11
+ end
12
+
13
+ context "with no server in state" do
14
+ it "reports an unknown status" do
15
+ expect(driver.status({})).to include(live: nil, state: "unknown")
16
+ end
17
+ end
18
+
19
+ context "with a server Rackspace does not know" do
20
+ it "reports an unknown status" do
21
+ expect(servers).to receive(:get).with("gone").and_return(nil)
22
+
23
+ expect(driver.status(server_id: "gone")).to include(state: "unknown")
24
+ end
25
+ end
26
+
27
+ context "with a live server" do
28
+ before do
29
+ allow(servers).to receive(:get).with("12345").and_return(server)
30
+ end
31
+
32
+ it "reports the server as live" do
33
+ expect(driver.status(server_id: "12345")).to include(
34
+ live: true,
35
+ state: "ACTIVE",
36
+ source: "driver",
37
+ resource_id: "12345"
38
+ )
39
+ end
40
+
41
+ it "stamps when the check happened" do
42
+ expect(driver.status(server_id: "12345")[:checked_at])
43
+ .to match(/\A\d{4}-\d{2}-\d{2}T/)
44
+ end
45
+ end
46
+
47
+ context "with a server that is not active" do
48
+ it "reports the server as not live" do
49
+ allow(servers).to receive(:get)
50
+ .with("12345").and_return(double("server", state: "ERROR"))
51
+
52
+ expect(driver.status(server_id: "12345"))
53
+ .to include(live: false, state: "ERROR")
54
+ end
55
+ end
56
+
57
+ context "when Rackspace cannot be reached" do
58
+ it "reports an unknown status rather than raising" do
59
+ allow(servers).to receive(:get)
60
+ .and_raise(Fog::Errors::Error.new("boom"))
61
+
62
+ expect(driver.status(server_id: "12345")).to include(state: "unknown")
63
+ end
64
+
65
+ it "survives an Excon error too" do
66
+ allow(servers).to receive(:get)
67
+ .and_raise(Excon::Errors::SocketError.new(StandardError.new("nope")))
68
+
69
+ expect(driver.status(server_id: "12345")).to include(state: "unknown")
70
+ end
71
+ end
72
+ end
73
+
74
+ describe "#doctor" do
75
+ let(:config) do
76
+ { image_id: "img-1", public_key_path: "/home/user/.ssh/id_rsa.pub" }
77
+ end
78
+ let(:servers) do
79
+ instance_double(Fog::Compute::RackspaceV2::Servers, all: [])
80
+ end
81
+
82
+ before do
83
+ allow(driver).to receive(:compute)
84
+ .and_return(double("compute", servers:))
85
+ end
86
+
87
+ it "reports no problem when the configuration is complete" do
88
+ expect(driver.doctor(state)).to eq(false)
89
+ end
90
+
91
+ # `summary` is not a method fog-rackspace has. Stubbing the collection with
92
+ # a verifying double is what keeps that mistake from coming back.
93
+ it "asks Rackspace for something fog actually implements" do
94
+ driver.doctor(state)
95
+
96
+ expect(servers).to have_received(:all)
97
+ end
98
+
99
+ context "with no resolvable image" do
100
+ let(:config) { { public_key_path: "/key.pub" } }
101
+
102
+ it "reports a problem" do
103
+ allow(driver).to receive(:default_image).and_return(nil)
104
+
105
+ expect(driver.doctor(state)).to eq(true)
106
+ expect(logged_output.string).to match(/No image_id is set/)
107
+ end
108
+ end
109
+
110
+ context "with no public key" do
111
+ let(:config) { { image_id: "img-1", public_key_path: nil } }
112
+
113
+ it "reports a problem" do
114
+ expect(driver.doctor(state)).to eq(true)
115
+ expect(logged_output.string).to match(/No public key was found/)
116
+ end
117
+ end
118
+
119
+ context "with credentials Rackspace rejects" do
120
+ it "reports a problem" do
121
+ allow(driver).to receive(:compute)
122
+ .and_raise(Fog::Errors::Error.new("unauthorized"))
123
+
124
+ expect(driver.doctor(state)).to eq(true)
125
+ expect(logged_output.string)
126
+ .to match(/rejected the configured credentials/)
127
+ end
128
+
129
+ it "names the region it tried" do
130
+ config[:rackspace_region] = "ord"
131
+ allow(driver).to receive(:compute)
132
+ .and_raise(Fog::Errors::Error.new("unauthorized"))
133
+
134
+ driver.doctor(state)
135
+
136
+ expect(logged_output.string).to match(/region ord/)
137
+ end
138
+ end
139
+
140
+ it "reports every problem it finds, not just the first" do
141
+ config.delete(:image_id)
142
+ config[:public_key_path] = nil
143
+ allow(driver).to receive(:default_image).and_return(nil)
144
+
145
+ driver.doctor(state)
146
+
147
+ expect(logged_output.string).to match(/No image_id is set/)
148
+ expect(logged_output.string).to match(/No public key was found/)
149
+ end
150
+ end
151
+ end
@@ -0,0 +1,37 @@
1
+ RSpec.describe Kitchen::Driver::Rackspace do
2
+ include_context "a driver for an instance"
3
+
4
+ describe "#tcp_check" do
5
+ before do
6
+ allow_any_instance_of(described_class).to receive(:wait_for_sshd)
7
+ allow_any_instance_of(described_class).to receive(:sleep)
8
+ end
9
+
10
+ context "the default non-skipping behavior" do
11
+ it "uses Kitchen's own SSH check" do
12
+ expect(driver).to receive(:wait_for_sshd).with(state)
13
+ expect(driver).to_not receive(:sleep)
14
+
15
+ driver.send(:tcp_check, state)
16
+ end
17
+ end
18
+
19
+ context "a config set to wait instead of TCP check" do
20
+ let(:config) { { no_ssh_tcp_check: true } }
21
+
22
+ it "uses a sleep instead of a port check" do
23
+ expect(driver).to_not receive(:wait_for_sshd)
24
+ expect(driver).to receive(:sleep)
25
+
26
+ driver.send(:tcp_check, state)
27
+ end
28
+
29
+ it "sleeps for the configured number of seconds" do
30
+ config[:no_ssh_tcp_check_sleep] = 42
31
+ expect(driver).to receive(:sleep).with(42)
32
+
33
+ driver.send(:tcp_check, state)
34
+ end
35
+ end
36
+ end
37
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,12 +1,28 @@
1
- require "rake"
2
- require "rspec"
3
1
  require "logger"
4
2
  require "stringio" unless defined?(StringIO)
5
3
  require "kitchen"
6
4
 
7
5
  require_relative "../lib/kitchen/driver/rackspace"
6
+
7
+ # `require "fog/rackspace"` only registers the services; it does not load the
8
+ # model classes. Load the ones the specs verify doubles against, so that a
9
+ # stubbed method which fog does not actually implement fails the example
10
+ # instead of quietly passing.
11
+ require "fog/rackspace/models/compute_v2/servers"
12
+
13
+ Dir[File.expand_path("support/**/*.rb", __dir__)].sort.each { |f| require f }
14
+
8
15
  RSpec.configure do |config|
9
- config.run_all_when_everything_filtered = true
10
- config.filter_run(:focus)
11
- config.order = "random"
16
+ config.disable_monkey_patching!
17
+ config.filter_run_when_matching :focus
18
+ config.order = :random
19
+ config.shared_context_metadata_behavior = :apply_to_host_groups
20
+
21
+ config.expect_with :rspec do |expectations|
22
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
23
+ end
24
+
25
+ config.mock_with :rspec do |mocks|
26
+ mocks.verify_partial_doubles = true
27
+ end
12
28
  end
@@ -0,0 +1,51 @@
1
+ # Everything a driver needs to exist outside a real Test Kitchen run: an
2
+ # instance to belong to, a logger to talk to, and a config hash to read.
3
+ #
4
+ # Individual example groups override `config`, `platform_name`, and
5
+ # `instance_name` with `let` to describe the situation under test.
6
+ RSpec.shared_context "a driver for an instance" do
7
+ let(:logged_output) { StringIO.new }
8
+ let(:logger) { Logger.new(logged_output) }
9
+ let(:config) { {} }
10
+ let(:state) { {} }
11
+ let(:platform_name) { "ubuntu" }
12
+ let(:instance_name) { "potatoes" }
13
+
14
+ let(:instance) do
15
+ double("instance",
16
+ name: instance_name,
17
+ logger:,
18
+ to_str: "instance",
19
+ platform: double("platform", name: platform_name))
20
+ end
21
+
22
+ let(:driver) { described_class.new(config) }
23
+
24
+ before do
25
+ allow_any_instance_of(described_class).to receive(:instance)
26
+ .and_return(instance)
27
+ ENV["RACKSPACE_USERNAME"] = "user"
28
+ ENV["RACKSPACE_API_KEY"] = "key"
29
+ end
30
+ end
31
+
32
+ # A server that has finished building and is reachable, as `#create` sees it.
33
+ RSpec.shared_context "a built server" do
34
+ let(:server) do
35
+ double("server",
36
+ id: "test123",
37
+ wait_for: true,
38
+ update: nil,
39
+ public_ip_address: "1.2.3.4",
40
+ private_ip_address: "10.9.8.7")
41
+ end
42
+
43
+ before do
44
+ allow_any_instance_of(described_class).to receive(:default_name)
45
+ .and_return("a_monkey!")
46
+ allow_any_instance_of(described_class).to receive(:create_server)
47
+ .and_return(server)
48
+ allow_any_instance_of(described_class).to receive(:tcp_check)
49
+ .and_return(true)
50
+ end
51
+ end
@@ -0,0 +1,27 @@
1
+ # The driver reads its credentials and its region straight out of the
2
+ # environment, and several examples set those variables to prove it. Without
3
+ # this the values leak from one example into the next, and out of the suite
4
+ # into whatever else the process goes on to do.
5
+ RACKSPACE_ENVIRONMENT_VARIABLES = %w{
6
+ RACKSPACE_USERNAME
7
+ RACKSPACE_API_KEY
8
+ RACKSPACE_REGION
9
+ OS_USERNAME
10
+ OS_PASSWORD
11
+ OS_REGION_NAME
12
+ }.freeze
13
+
14
+ RSpec.configure do |config|
15
+ config.around do |example|
16
+ saved = RACKSPACE_ENVIRONMENT_VARIABLES.to_h { |name| [name, ENV.fetch(name, nil)] }
17
+ RACKSPACE_ENVIRONMENT_VARIABLES.each { |name| ENV.delete(name) }
18
+
19
+ begin
20
+ example.run
21
+ ensure
22
+ saved.each do |name, value|
23
+ value.nil? ? ENV.delete(name) : ENV[name] = value
24
+ end
25
+ end
26
+ end
27
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kitchen-rackspace
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.22.0
4
+ version: 0.22.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jonathan Hartman
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-08-24 00:00:00.000000000 Z
11
+ date: 2026-08-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fog-rackspace
@@ -77,6 +77,7 @@ files:
77
77
  - ".gitignore"
78
78
  - ".markdownlint.yaml"
79
79
  - ".release-please-manifest.json"
80
+ - ".rspec"
80
81
  - ".rubocop.yml"
81
82
  - ".yamllint"
82
83
  - ".yardopts"
@@ -94,8 +95,18 @@ files:
94
95
  - lib/kitchen/driver/rackspace_version.rb
95
96
  - release-please-config.json
96
97
  - renovate.json
97
- - spec/kitchen/driver/rackspace_spec.rb
98
+ - spec/kitchen/driver/rackspace/compute_spec.rb
99
+ - spec/kitchen/driver/rackspace/configuration_spec.rb
100
+ - spec/kitchen/driver/rackspace/create_spec.rb
101
+ - spec/kitchen/driver/rackspace/destroy_spec.rb
102
+ - spec/kitchen/driver/rackspace/image_spec.rb
103
+ - spec/kitchen/driver/rackspace/plugin_spec.rb
104
+ - spec/kitchen/driver/rackspace/server_name_spec.rb
105
+ - spec/kitchen/driver/rackspace/status_spec.rb
106
+ - spec/kitchen/driver/rackspace/tcp_check_spec.rb
98
107
  - spec/spec_helper.rb
108
+ - spec/support/driver_context.rb
109
+ - spec/support/rackspace_environment.rb
99
110
  homepage: https://github.com/test-kitchen/kitchen-rackspace
100
111
  licenses:
101
112
  - Apache-2.0