Class: Pvectl::Services::EditVm
- Inherits:
-
Object
- Object
- Pvectl::Services::EditVm
- Defined in:
- lib/pvectl/services/edit_vm.rb,
sig/pvectl/services/edit_vm.rbs
Overview
Orchestrates the interactive VM configuration editing flow.
Fetches current config, opens it in an editor as structured YAML, validates changes, computes a diff, and applies updates via the API. Supports dry-run mode and optimistic locking via digest.
Instance Method Summary collapse
-
#build_result(resource_info, **attrs) ⇒ Models::VmOperationResult
Builds a VmOperationResult with the :edit operation.
-
#build_update_params(changes, original_config) ⇒ Hash
Builds API update parameters from a diff hash.
-
#execute(vmid:) ⇒ Models::VmOperationResult?
Executes the interactive VM edit flow.
-
#initialize(vm_repository:, editor_session: nil, options: {}) ⇒ EditVm
constructor
Creates a new EditVm service.
-
#not_found_result(vmid) ⇒ Models::VmOperationResult
Builds a not-found error result.
Constructor Details
#initialize(vm_repository:, editor_session: nil, options: {}) ⇒ EditVm
Creates a new EditVm service.
26 27 28 29 30 |
# File 'lib/pvectl/services/edit_vm.rb', line 26 def initialize(vm_repository:, editor_session: nil, options: {}) @vm_repository = vm_repository @editor_session = editor_session = end |
Instance Method Details
#build_result(resource_info, **attrs) ⇒ Models::VmOperationResult
Builds a VmOperationResult with the :edit operation.
106 107 108 109 110 111 112 113 114 |
# File 'lib/pvectl/services/edit_vm.rb', line 106 def build_result(resource_info, **attrs) vm = Models::Vm.new( vmid: resource_info[:vmid], node: resource_info[:node] ) Models::VmOperationResult.new( operation: :edit, vm: vm, resource: resource_info, **attrs ) end |
#build_update_params(changes, original_config) ⇒ Hash
Builds API update parameters from a diff hash.
Maps changed/added keys to their new values, removed keys to the
Proxmox delete parameter, and includes digest for optimistic locking.
90 91 92 93 94 95 96 97 98 99 |
# File 'lib/pvectl/services/edit_vm.rb', line 90 def build_update_params(changes, original_config) params = {} changes[:changed].each { |key, (_old, new_val)| params[key] = new_val } changes[:added].each { |key, val| params[key] = val } unless changes[:removed].empty? params[:delete] = changes[:removed].map(&:to_s).join(",") end params[:digest] = original_config[:digest] if original_config[:digest] params end |
#execute(vmid:) ⇒ Models::VmOperationResult?
Executes the interactive VM edit flow.
36 37 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 73 74 75 76 77 78 |
# File 'lib/pvectl/services/edit_vm.rb', line 36 def execute(vmid:) vm = @vm_repository.get(vmid) return not_found_result(vmid) unless vm config = @vm_repository.fetch_config(vm.node, vmid) resource_info = { vmid: vmid, node: vm.node, status: vm.status } yaml_content = ConfigSerializer.to_yaml(config, type: :vm, resource: resource_info) validator = ->(content) { ConfigSerializer.validate(content, type: :vm) } session = @editor_session || EditorSession.new(validator: validator) edited = session.edit(yaml_content) return nil unless edited original_roundtrip = ConfigSerializer.from_yaml(yaml_content, type: :vm) edited_flat = ConfigSerializer.from_yaml(edited, type: :vm) violations = ConfigSerializer.readonly_violations(original_roundtrip, edited_flat, type: :vm) unless violations.empty? return build_result(resource_info, success: false, error: "Read-only fields cannot be changed: #{violations.join(', ')}") end changes = ConfigSerializer.diff(original_roundtrip, edited_flat) if changes[:changed].empty? && changes[:added].empty? && changes[:removed].empty? return nil end params = build_update_params(changes, config) resource_info[:diff] = changes if [:dry_run] return build_result(resource_info, success: true) end @vm_repository.update(vmid, vm.node, params) build_result(resource_info, success: true) rescue StandardError => e build_result({ vmid: vmid }, success: false, error: e.) end |
#not_found_result(vmid) ⇒ Models::VmOperationResult
Builds a not-found error result.
120 121 122 |
# File 'lib/pvectl/services/edit_vm.rb', line 120 def not_found_result(vmid) build_result({ vmid: vmid }, success: false, error: "VM #{vmid} not found") end |