Class: Pvectl::Services::EditDns
- Inherits:
-
Object
- Object
- Pvectl::Services::EditDns
- Defined in:
- lib/pvectl/services/edit_dns.rb,
sig/pvectl/services/edit_dns.rbs
Overview
Orchestrates the interactive editing flow for node DNS settings.
Fetches current DNS config, presents it as YAML in an editor, computes
a diff, and applies changes via the Proxmox API. The Proxmox PUT endpoint
requires the search field — the service validates this before calling.
Constant Summary collapse
- EDITABLE_KEYS =
Editable keys exposed in the YAML editor (in order).
i[search dns1 dns2 dns3].freeze
Instance Method Summary collapse
-
#build_editable(dns) ⇒ Hash{String=>String}
Builds editable hash (string-keyed) from a DnsConfig model.
-
#build_result(resource_info, **attrs) ⇒ Models::NodeOperationResult
Builds a NodeOperationResult with the :edit operation.
-
#build_update_params(edited) ⇒ Hash
Builds API update parameters from edited config.
-
#compute_diff(original, edited) ⇒ Hash
Computes diff between original and edited configs.
-
#execute(node_name:) ⇒ Models::NodeOperationResult?
Executes the interactive DNS edit flow.
-
#initialize(dns_repository:, editor_session: nil, options: {}) ⇒ EditDns
constructor
Creates a new EditDns service.
-
#validate!(edited) ⇒ void
Validates the edited config satisfies API requirements.
Constructor Details
#initialize(dns_repository:, editor_session: nil, options: {}) ⇒ EditDns
Creates a new EditDns service.
28 29 30 31 32 |
# File 'lib/pvectl/services/edit_dns.rb', line 28 def initialize(dns_repository:, editor_session: nil, options: {}) @dns_repository = dns_repository @editor_session = editor_session = end |
Instance Method Details
#build_editable(dns) ⇒ Hash{String=>String}
Builds editable hash (string-keyed) from a DnsConfig model.
80 81 82 83 84 85 86 87 |
# File 'lib/pvectl/services/edit_dns.rb', line 80 def build_editable(dns) { "search" => dns.search, "dns1" => dns.dns1, "dns2" => dns.dns2, "dns3" => dns.dns3 }.compact end |
#build_result(resource_info, **attrs) ⇒ Models::NodeOperationResult
Builds a NodeOperationResult with the :edit operation.
151 152 153 154 155 156 |
# File 'lib/pvectl/services/edit_dns.rb', line 151 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 |
#build_update_params(edited) ⇒ Hash
Builds API update parameters from edited config.
The PUT endpoint requires search and accepts optional dns1-3.
Removed keys are sent as empty strings to clear the field
(Proxmox accepts empty strings as "unset" for optional dns* fields).
135 136 137 138 139 140 141 142 143 144 |
# File 'lib/pvectl/services/edit_dns.rb', line 135 def build_update_params(edited) params = {} EDITABLE_KEYS.each do |key| value = edited[key] params[key] = value.nil? ? "" : value end # search must always have a real value (validated above) params[:search] = edited[:search] params end |
#compute_diff(original, edited) ⇒ Hash
Computes diff between original and edited configs.
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/pvectl/services/edit_dns.rb', line 106 def compute_diff(original, edited) changed = {} added = {} removed = [] edited.each do |key, value| orig_value = original[key] if orig_value.nil? added[key] = value elsif orig_value.to_s != value.to_s changed[key] = [orig_value.to_s, value.to_s] end end original.each_key do |key| removed << key unless edited.key?(key) end { changed: changed, added: added, removed: removed } end |
#execute(node_name:) ⇒ Models::NodeOperationResult?
Executes the interactive DNS edit flow.
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/pvectl/services/edit_dns.rb', line 38 def execute(node_name:) dns = @dns_repository.fetch(node_name) resource_info = { node_name: node_name } editable = build_editable(dns) yaml_content = "# Node: #{node_name} — DNS configuration\n" \ "# 'search' is required by Proxmox. dns1/dns2/dns3 are optional.\n" + editable.to_yaml session = @editor_session || EditorSession.new edited = session.edit(yaml_content) return nil unless edited cleaned = edited.lines.reject { |l| l.strip.start_with?("#") }.join edited_config = YAML.safe_load(cleaned, symbolize_names: true) || {} original_symbolized = editable.transform_keys(&:to_sym) changes = compute_diff(original_symbolized, edited_config) if changes[:changed].empty? && changes[:added].empty? && changes[:removed].empty? return nil end validate!(edited_config) resource_info[:diff] = changes return build_result(resource_info, success: true) if [:dry_run] @dns_repository.update(node_name, build_update_params(edited_config)) build_result(resource_info, success: true) rescue StandardError => e build_result({ node_name: node_name }, success: false, error: e.) end |
#validate!(edited) ⇒ void
This method returns an undefined value.
Validates the edited config satisfies API requirements.
94 95 96 97 98 99 |
# File 'lib/pvectl/services/edit_dns.rb', line 94 def validate!(edited) search = edited[:search] if search.nil? || search.to_s.strip.empty? raise ArgumentError, "search field is required by Proxmox API" end end |