Module: Pvectl::Commands::EditResourceCommand Abstract

Included in:
EditContainer, EditNode, EditVm
Defined in:
lib/pvectl/commands/edit_resource_command.rb,
sig/pvectl/commands/edit_resource_command.rbs

Overview

This module is abstract.

Include this module and implement template methods.

Shared functionality for resource edit commands.

Template method pattern: provides common edit workflow (config loading, editor session, diff display, dry-run) while specialization classes define resource-specific hooks.

Examples:

Specialization

class EditVm
  include EditResourceCommand
  private
  def resource_label = "VM"
  def resource_id_label = "VMID"
  # ...
end

Defined Under Namespace

Modules: ClassMethods

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.included(base) ⇒ void

This method returns an undefined value.

Hook called when module is included.



39
40
41
# File 'lib/pvectl/commands/edit_resource_command.rb', line 39

def self.included(base)
  base.extend(ClassMethods)
end

Instance Method Details

#build_edit_service(connection) ⇒ Object

Builds the edit service for the given connection.

Raises:

  • (NotImplementedError)


122
123
124
# File 'lib/pvectl/commands/edit_resource_command.rb', line 122

def build_edit_service(connection)
  raise NotImplementedError, "#{self.class} must implement #build_edit_service"
end

#build_editor_sessionEditorSession?

Builds an editor session from the --editor option.



161
162
163
164
165
166
167
168
# File 'lib/pvectl/commands/edit_resource_command.rb', line 161

def build_editor_session
  editor_cmd = @options[:editor]
  return nil unless editor_cmd

  Pvectl::EditorSession.new(
    editor: ->(path) { system(editor_cmd, path) }
  )
end

#display_diff(result) ⇒ void

This method returns an undefined value.

Displays a formatted diff from the operation result.



130
131
132
133
134
135
136
137
138
# File 'lib/pvectl/commands/edit_resource_command.rb', line 130

def display_diff(result)
  diff = result.resource&.dig(:diff)
  return unless diff
  return if diff[:changed].empty? && diff[:added].empty? && diff[:removed].empty?

  $stdout.puts "\nChanges:"
  $stdout.puts Pvectl::ConfigSerializer.format_diff(diff)
  $stdout.puts ""
end

#executeInteger

Executes the edit command.

Loads configuration, builds the edit service, and runs it. Handles cancelled edits, successful updates with diff display, dry-run mode, and errors.



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/pvectl/commands/edit_resource_command.rb', line 61

def execute
  resource_id = @args.first
  return usage_error("#{resource_id_label} is required") unless resource_id

  load_config
  connection = Pvectl::Connection.new(@config)
  service = build_edit_service(connection)
  result = service.execute(**execute_params(resource_id))

  if result.nil?
    $stdout.puts "Edit cancelled, no changes made."
    return ExitCodes::SUCCESS
  end

  if result.successful?
    display_diff(result)
    if @options[:"dry-run"]
      $stdout.puts "(dry-run mode — no changes applied)"
    else
      $stdout.puts "#{resource_label} #{resource_id} updated successfully."
    end
    ExitCodes::SUCCESS
  else
    $stderr.puts "Error: #{result.error}"
    ExitCodes::GENERAL_ERROR
  end
rescue Pvectl::Config::ConfigNotFoundError,
       Pvectl::Config::InvalidConfigError,
       Pvectl::Config::ContextNotFoundError,
       Pvectl::Config::ClusterNotFoundError,
       Pvectl::Config::UserNotFoundError
  raise
rescue StandardError => e
  $stderr.puts "Error: #{e.message}"
  ExitCodes::GENERAL_ERROR
end

#execute_params(resource_id) ⇒ Hash

Builds execution parameters from resource ID.

Raises:

  • (NotImplementedError)


114
115
116
# File 'lib/pvectl/commands/edit_resource_command.rb', line 114

def execute_params(resource_id)
  raise NotImplementedError, "#{self.class} must implement #execute_params"
end

#initialize(args, options, global_options) ⇒ EditResourceCommand

Initializes an edit command.



48
49
50
51
52
# File 'lib/pvectl/commands/edit_resource_command.rb', line 48

def initialize(args, options, global_options)
  @args = args
  @options = options
  @global_options = global_options
end

#load_configvoid

This method returns an undefined value.

Loads configuration from file or environment.



143
144
145
146
147
# File 'lib/pvectl/commands/edit_resource_command.rb', line 143

def load_config
  service = Pvectl::Config::Service.new
  service.load(config: @global_options[:config])
  @config = service.current_config
end

#resource_id_labelString

Returns human label for resource ID ("VMID" or "CTID").

Raises:

  • (NotImplementedError)


106
107
108
# File 'lib/pvectl/commands/edit_resource_command.rb', line 106

def resource_id_label
  raise NotImplementedError, "#{self.class} must implement #resource_id_label"
end

#resource_labelString

Returns human label for resource ("VM" or "container").

Raises:

  • (NotImplementedError)


101
102
103
# File 'lib/pvectl/commands/edit_resource_command.rb', line 101

def resource_label
  raise NotImplementedError, "#{self.class} must implement #resource_label"
end

#service_optionsHash

Builds service options from command options.



152
153
154
155
156
# File 'lib/pvectl/commands/edit_resource_command.rb', line 152

def service_options
  opts = {}
  opts[:dry_run] = true if @options[:"dry-run"]
  opts
end

#usage_error(message) ⇒ Integer

Outputs usage error and returns exit code.



174
175
176
177
# File 'lib/pvectl/commands/edit_resource_command.rb', line 174

def usage_error(message)
  $stderr.puts "Error: #{message}"
  ExitCodes::USAGE_ERROR
end