kitchen-proxmox 0.3.0 → 0.3.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.
- checksums.yaml +4 -4
- data/lib/kitchen/driver/proxmox/api_client.rb +2 -1
- data/lib/kitchen/driver/proxmox/errors.rb +26 -0
- data/lib/kitchen/driver/proxmox.rb +34 -6
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9431e030d0300d57c9fac8a20047375865cedf9f4a48b34b3039370f2d62a98a
|
|
4
|
+
data.tar.gz: 62e91255a7b9b2586eeef54bcd76bb7110b782ae8c948853ef0691a13e11df5e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e974ac8b7626ed1232e608073c259f5bb90c65aa47bdaf9327195a255dfbcbb7eb969a6cd88c5781c929835daa84f52a63e83aa6e291199de3d32889c244300b
|
|
7
|
+
data.tar.gz: 4b36857b3cfb877ff3bcf292049389cbe26cd43ab2393fb235d3236e8ad5d50ba74ed1ae55076961f97294f2df14e9a8d98d683a50afe4f37af5253ca3066f63
|
|
@@ -5,6 +5,7 @@ require 'json'
|
|
|
5
5
|
require 'uri'
|
|
6
6
|
require 'openssl'
|
|
7
7
|
require 'kitchen'
|
|
8
|
+
require_relative 'errors'
|
|
8
9
|
|
|
9
10
|
module Kitchen
|
|
10
11
|
module Driver
|
|
@@ -145,7 +146,7 @@ module Kitchen
|
|
|
145
146
|
end
|
|
146
147
|
|
|
147
148
|
def handle_response(response)
|
|
148
|
-
raise
|
|
149
|
+
raise ProxmoxErrors::ApiError.new(response.code, response.body) unless response.is_a?(Net::HTTPSuccess)
|
|
149
150
|
|
|
150
151
|
JSON.parse(response.body)['data']
|
|
151
152
|
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Kitchen
|
|
4
|
+
module Driver
|
|
5
|
+
module ProxmoxErrors
|
|
6
|
+
# Structured error raised by ApiClient on non-2xx responses.
|
|
7
|
+
class ApiError < ::StandardError
|
|
8
|
+
attr_reader :status_code, :response_body
|
|
9
|
+
|
|
10
|
+
def initialize(status_code, response_body)
|
|
11
|
+
@status_code = status_code.to_i
|
|
12
|
+
@response_body = response_body
|
|
13
|
+
super("Proxmox API error #{status_code}: #{response_body}")
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Returns true when the error indicates a VMID is already in use.
|
|
17
|
+
def vmid_conflict?
|
|
18
|
+
return false unless status_code == 400 || status_code == 500
|
|
19
|
+
|
|
20
|
+
response_body.match?(/already exists/i) ||
|
|
21
|
+
response_body.match?(/unable to create VM \d+/i)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require 'kitchen'
|
|
4
4
|
require_relative 'proxmox_version'
|
|
5
|
+
require_relative 'proxmox/errors'
|
|
5
6
|
require_relative 'proxmox/api_client'
|
|
6
7
|
|
|
7
8
|
module Kitchen
|
|
@@ -16,6 +17,8 @@ module Kitchen
|
|
|
16
17
|
|
|
17
18
|
plugin_version Kitchen::Driver::PROXMOX_VERSION
|
|
18
19
|
|
|
20
|
+
ApiError = Kitchen::Driver::ProxmoxErrors::ApiError
|
|
21
|
+
|
|
19
22
|
required_config :proxmox_url
|
|
20
23
|
required_config :proxmox_token_id
|
|
21
24
|
required_config :proxmox_token_secret
|
|
@@ -32,6 +35,7 @@ module Kitchen
|
|
|
32
35
|
default_config :clone_timeout, 300
|
|
33
36
|
default_config :start_timeout, 300
|
|
34
37
|
default_config :ip_wait_timeout, 120
|
|
38
|
+
default_config :clone_retries, 5
|
|
35
39
|
|
|
36
40
|
def create(state)
|
|
37
41
|
return if state[:vm_id]
|
|
@@ -65,19 +69,43 @@ module Kitchen
|
|
|
65
69
|
def clone_and_start(state)
|
|
66
70
|
info("Creating Proxmox VM from template #{config[:template_id]}...")
|
|
67
71
|
|
|
68
|
-
vm_id =
|
|
69
|
-
|
|
72
|
+
vm_id, vm_name = allocate_and_clone
|
|
73
|
+
state[:vm_id] = vm_id
|
|
74
|
+
state[:vm_name] = vm_name
|
|
70
75
|
|
|
71
|
-
clone_template(vm_id, vm_name)
|
|
72
76
|
configure_hardware(vm_id)
|
|
73
77
|
start_and_wait_for_ip(state, vm_id)
|
|
74
78
|
|
|
75
|
-
state[:vm_id] = vm_id
|
|
76
|
-
state[:vm_name] = vm_name
|
|
77
|
-
|
|
78
79
|
info("Proxmox VM #{vm_name} (#{vm_id}) created.")
|
|
79
80
|
end
|
|
80
81
|
|
|
82
|
+
def allocate_and_clone
|
|
83
|
+
retries = config[:clone_retries]
|
|
84
|
+
last_error = nil
|
|
85
|
+
|
|
86
|
+
retries.times do |attempt|
|
|
87
|
+
vm_id = allocate_vm_id
|
|
88
|
+
vm_name = generate_vm_name(instance.name)
|
|
89
|
+
|
|
90
|
+
begin
|
|
91
|
+
clone_template(vm_id, vm_name)
|
|
92
|
+
return [vm_id, vm_name]
|
|
93
|
+
rescue ApiError => e
|
|
94
|
+
raise unless e.vmid_conflict?
|
|
95
|
+
|
|
96
|
+
last_error = e
|
|
97
|
+
warn("VMID #{vm_id} conflict (attempt #{attempt + 1}/#{retries}), retrying...")
|
|
98
|
+
sleep backoff_delay(attempt)
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
raise last_error
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def backoff_delay(attempt)
|
|
106
|
+
(0.5 * (2**attempt)) + rand(0.0..1.0)
|
|
107
|
+
end
|
|
108
|
+
|
|
81
109
|
def allocate_vm_id
|
|
82
110
|
Integer(api_client.next_vm_id)
|
|
83
111
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: kitchen-proxmox
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.3.
|
|
4
|
+
version: 0.3.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Richard Nixon
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-05-03 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: A Test Kitchen driver for Proxmox VE. Manages VM lifecycle (create, destroy)
|
|
14
14
|
via the Proxmox REST API. Supports cloning from templates.
|
|
@@ -22,6 +22,7 @@ files:
|
|
|
22
22
|
- README.md
|
|
23
23
|
- lib/kitchen/driver/proxmox.rb
|
|
24
24
|
- lib/kitchen/driver/proxmox/api_client.rb
|
|
25
|
+
- lib/kitchen/driver/proxmox/errors.rb
|
|
25
26
|
- lib/kitchen/driver/proxmox_version.rb
|
|
26
27
|
homepage: https://github.com/trickyearlobe-chef/kitchen-proxmox
|
|
27
28
|
licenses:
|