Class: Pvectl::Services::EditHosts

Inherits:
Object
  • Object
show all
Defined in:
lib/pvectl/services/edit_hosts.rb,
sig/pvectl/services/edit_hosts.rbs

Overview

Orchestrates the interactive editing flow for /etc/hosts on a node.

Fetches current /etc/hosts content + digest, opens it in an editor, and POSTs the new content back with the original digest for optimistic locking. If Proxmox returns a digest collision (concurrent modification) or any other error, the message is surfaced verbatim to the user.

Unlike DNS (structured YAML), /etc/hosts is edited as raw text — there is no parsing or validation pvectl-side.

Examples:

Basic usage

service = EditHosts.new(hosts_repository: repo)
result = service.execute(node_name: "pve1")

Dry run

service = EditHosts.new(hosts_repository: repo, options: { dry_run: true })
result = service.execute(node_name: "pve1")

Instance Method Summary collapse

Constructor Details

#initialize(hosts_repository:, editor_session: nil, options: {}) ⇒ EditHosts

Creates a new EditHosts service.



29
30
31
32
33
# File 'lib/pvectl/services/edit_hosts.rb', line 29

def initialize(hosts_repository:, editor_session: nil, options: {})
  @hosts_repository = hosts_repository
  @editor_session = editor_session
  @options = options
end

Instance Method Details

#build_result(resource_info, **attrs) ⇒ Models::NodeOperationResult

Builds a NodeOperationResult with the :edit operation.



70
71
72
73
74
75
# File 'lib/pvectl/services/edit_hosts.rb', line 70

def build_result(resource_info, **attrs)
  node_model = Models::Node.new(name: resource_info[:node_name])
  Models::NodeOperationResult.new(
    operation: :edit, node_model: node_model, resource: resource_info, **attrs
  )
end

#execute(node_name:) ⇒ Models::NodeOperationResult?

Executes the interactive /etc/hosts edit flow.



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/pvectl/services/edit_hosts.rb', line 39

def execute(node_name:)
  hosts = @hosts_repository.fetch(node_name)
  original = hosts.data || ""
  digest = hosts.digest

  session = @editor_session || EditorSession.new
  edited = session.edit(original)

  return nil if edited.nil?
  return nil if edited == original

  resource_info = {
    node_name: node_name,
    diff: { original: original, edited: edited }
  }

  return build_result(resource_info, success: true) if @options[:dry_run]

  @hosts_repository.update(node_name, edited, digest)
  build_result(resource_info, success: true)
rescue StandardError => e
  build_result({ node_name: node_name }, success: false, error: e.message)
end