kitchen-rackspace 0.21.2 → 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,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.21.2
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-22 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
@@ -33,7 +33,7 @@ dependencies:
33
33
  version: '1.35'
34
34
  - - "<"
35
35
  - !ruby/object:Gem::Version
36
- version: 2.6.1
36
+ version: '2.3'
37
37
  type: :runtime
38
38
  prerelease: false
39
39
  version_requirements: !ruby/object:Gem::Requirement
@@ -43,14 +43,14 @@ dependencies:
43
43
  version: '1.35'
44
44
  - - "<"
45
45
  - !ruby/object:Gem::Version
46
- version: 2.6.1
46
+ version: '2.3'
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: test-kitchen
49
49
  requirement: !ruby/object:Gem::Requirement
50
50
  requirements:
51
51
  - - ">="
52
52
  - !ruby/object:Gem::Version
53
- version: '1.1'
53
+ version: '3.0'
54
54
  - - "<"
55
55
  - !ruby/object:Gem::Version
56
56
  version: '5.0'
@@ -60,7 +60,7 @@ dependencies:
60
60
  requirements:
61
61
  - - ">="
62
62
  - !ruby/object:Gem::Version
63
- version: '1.1'
63
+ version: '3.0'
64
64
  - - "<"
65
65
  - !ruby/object:Gem::Version
66
66
  version: '5.0'
@@ -72,30 +72,44 @@ extensions: []
72
72
  extra_rdoc_files: []
73
73
  files:
74
74
  - ".github/CODEOWNERS"
75
- - ".github/dependabot.yml"
76
75
  - ".github/workflows/linters.yml"
77
76
  - ".github/workflows/publish.yaml"
78
77
  - ".gitignore"
79
78
  - ".markdownlint.yaml"
80
79
  - ".release-please-manifest.json"
80
+ - ".rspec"
81
81
  - ".rubocop.yml"
82
+ - ".yamllint"
83
+ - ".yardopts"
82
84
  - CHANGELOG.md
85
+ - CONTRIBUTING.md
83
86
  - Gemfile
84
87
  - LICENSE
85
88
  - README.md
86
89
  - Rakefile
87
90
  - data/images.json
91
+ - helpers/dump_flavor_list.rb
88
92
  - helpers/dump_image_list.rb
89
93
  - kitchen-rackspace.gemspec
90
94
  - lib/kitchen/driver/rackspace.rb
91
95
  - lib/kitchen/driver/rackspace_version.rb
92
96
  - release-please-config.json
93
97
  - renovate.json
94
- - 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
95
107
  - spec/spec_helper.rb
108
+ - spec/support/driver_context.rb
109
+ - spec/support/rackspace_environment.rb
96
110
  homepage: https://github.com/test-kitchen/kitchen-rackspace
97
111
  licenses:
98
- - Apache
112
+ - Apache-2.0
99
113
  metadata: {}
100
114
  post_install_message:
101
115
  rdoc_options: []
@@ -116,6 +130,4 @@ rubygems_version: 3.5.9
116
130
  signing_key:
117
131
  specification_version: 4
118
132
  summary: A Test Kitchen Rackspace driver built on Fog
119
- test_files:
120
- - spec/kitchen/driver/rackspace_spec.rb
121
- - spec/spec_helper.rb
133
+ test_files: []
@@ -1,8 +0,0 @@
1
- ---
2
- version: 2
3
- updates:
4
- - package-ecosystem: bundler
5
- directory: "/"
6
- schedule:
7
- interval: daily
8
- open-pull-requests-limit: 10