diff --git a/lib/kitchen/driver/cloudstack.rb b/lib/kitchen/driver/cloudstack.rb index 6040887..73d3ebb 100644 --- a/lib/kitchen/driver/cloudstack.rb +++ b/lib/kitchen/driver/cloudstack.rb @@ -128,6 +128,7 @@ def client # Deploys the instance and waits for CloudStack to finish building it. # + # @param state [Hash] mutable instance state; gains +server_id+ # @return [Hash] the "virtualmachine" payload describing the instance def deploy_instance(state) options = ServerOptions.new(config, instance_name: instance.name).to_h @@ -144,6 +145,11 @@ def deploy_instance(state) # Works out the address Test Kitchen should connect to, allocating a # public address and forwarding the transport's port when asked to. + # + # @param state [Hash] mutable instance state; gains +ipaddressid+ and + # +forwardingruleid+ when a public address is associated + # @param server_info [Hash] the "virtualmachine" payload from CloudStack + # @return [String] the address the transport should connect to def hostname_for(state, server_info) unless config[:associate_public_ip] return config[:cloudstack_vm_public_ip] || @@ -161,6 +167,10 @@ def hostname_for(state, server_info) # Credentials go into state because the transport merges state over its # own config, so this is how a driver tells the transport how to log in. + # + # @param state [Hash] mutable instance state; gains the credential keys + # @param server_info [Hash] the "virtualmachine" payload from CloudStack + # @return [void] def apply_credentials(state, server_info) credentials = Credentials.new(config) state.merge!(credentials.to_state(server_info)) diff --git a/lib/kitchen/driver/cloudstack/client.rb b/lib/kitchen/driver/cloudstack/client.rb index a776ff7..4405569 100644 --- a/lib/kitchen/driver/cloudstack/client.rb +++ b/lib/kitchen/driver/cloudstack/client.rb @@ -43,6 +43,10 @@ class Client # not configured. DEFAULT_TIMEOUT = 600 + # @param config [Hash] the driver configuration + # @param compute [Fog::Compute, nil] an existing connection, for tests + # @param sleeper [#call, nil] receives a number of seconds to wait, + # for tests that must not actually sleep def initialize(config, compute: nil, sleeper: nil) @config = config @compute = compute @@ -124,6 +128,9 @@ def timeout # CloudStack reports failures as an "errortext" inside the job result, # but falls back to the whole payload when the shape is unexpected. + # + # @param response [Hash] the async job payload + # @return [String] a message describing the failure def job_error(response) result = response["jobresult"] return response.inspect unless result.is_a?(Hash) diff --git a/lib/kitchen/driver/cloudstack/credentials.rb b/lib/kitchen/driver/cloudstack/credentials.rb index e53659c..75bcfc1 100644 --- a/lib/kitchen/driver/cloudstack/credentials.rb +++ b/lib/kitchen/driver/cloudstack/credentials.rb @@ -33,6 +33,9 @@ class Credentials attr_reader :warnings + # @param config [Hash] the driver configuration + # @param home [String, nil] the home directory keypair paths expand against + # @param working_dir [String] the directory relative keypair paths expand against def initialize(config, home: ENV["HOME"], working_dir: ".") @config = config @home = home diff --git a/lib/kitchen/driver/cloudstack/networking.rb b/lib/kitchen/driver/cloudstack/networking.rb index 691c59c..bdbc8bc 100644 --- a/lib/kitchen/driver/cloudstack/networking.rb +++ b/lib/kitchen/driver/cloudstack/networking.rb @@ -29,6 +29,10 @@ class Networking # this in the message. Teardown treats it as success. ALREADY_GONE = /does not exist/ + # @param config [Hash] the driver configuration + # @param client [Client] the shared CloudStack client + # @param port [Integer] the transport port to forward and open + # @param logger [#debug, nil] where already-gone resources are noted def initialize(config, client:, port:, logger: nil) @config = config @client = client @@ -56,6 +60,10 @@ def associate_public_ip(state) end # Forwards the transport's port on the public address to the instance. + # + # @param state [Hash] mutable instance state; gains +forwardingruleid+ + # @param virtualmachine_id [String] the instance to forward to + # @return [void] def create_port_forward(state, virtualmachine_id) response = compute.create_port_forwarding_rule( "ipaddressid" => state[:ipaddressid], @@ -72,6 +80,9 @@ def create_port_forward(state, virtualmachine_id) # Removes everything {#associate_public_ip} and {#create_port_forward} # created, in the reverse order, tolerating resources already gone. + # + # @param state [Hash] instance state naming the resources to remove + # @return [void] def teardown(state) delete_port_forward(state) if state[:forwardingruleid] delete_firewall_rule(state) if state[:firewall_rule_id] @@ -138,6 +149,12 @@ def release_public_ip(state) # Teardown should not fail because something is already deleted, but # any other API error is worth surfacing. + # + # @param description [String] names the resource, for the debug message + # @yield the deletion call to attempt + # @return [void] + # @raise [Fog::Cloudstack::Compute::BadRequest] for any error other + # than the resource already being gone def tolerating_missing(description) yield rescue Fog::Cloudstack::Compute::BadRequest => e diff --git a/lib/kitchen/driver/cloudstack/server_options.rb b/lib/kitchen/driver/cloudstack/server_options.rb index 530ac07..0a7d658 100644 --- a/lib/kitchen/driver/cloudstack/server_options.rb +++ b/lib/kitchen/driver/cloudstack/server_options.rb @@ -49,6 +49,10 @@ class ServerOptions # pre-encoded is passed through rather than double-encoded. BASE64_PATTERN = %r{^(?:[A-Za-z0-9+/]{4}\n?)*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$} + # @param config [Hash] the driver configuration + # @param instance_name [String] the Test Kitchen instance name + # @param login [String] the local username, used in the generated name + # @param hostname [String] the local hostname, used in the generated name def initialize(config, instance_name:, login: Etc.getlogin, hostname: Socket.gethostname) @config = config @instance_name = instance_name @@ -106,6 +110,10 @@ def generate_name # Shortens the longest part repeatedly until the parts fit the budget, # which keeps the shorter, more identifying parts intact. + # + # @param parts [Array] the name components + # @param budget [Integer] the total characters the parts may occupy + # @return [Array] the components, shortened to fit def truncate_to_budget(parts, budget) parts = parts.dup while parts.sum(&:length) > budget