Class: Pvectl::Commands::Pull
- Inherits:
-
Object
- Object
- Pvectl::Commands::Pull
- Defined in:
- lib/pvectl/commands/pull.rb
Overview
Pull command – exports resource configuration from the Proxmox cluster as kubectl-like YAML manifest files.
Constant Summary collapse
- RESOURCE_TYPES =
{ "vm" => :vm, "vms" => :vm, "container" => :container, "containers" => :container, "ct" => :container }.freeze
- FILE_PREFIXES =
{ vm: "vm", container: "ct" }.freeze
Class Method Summary collapse
-
.register(cli) ⇒ void
Registers the pull command with the CLI.
Instance Method Summary collapse
-
#execute ⇒ Integer
Executes the pull command.
-
#initialize(args, options, global_options) ⇒ Pull
constructor
A new instance of Pull.
Constructor Details
#initialize(args, options, global_options) ⇒ Pull
Returns a new instance of Pull.
81 82 83 84 85 |
# File 'lib/pvectl/commands/pull.rb', line 81 def initialize(args, , ) @args = args @options = @global_options = end |
Class Method Details
.register(cli) ⇒ void
This method returns an undefined value.
Registers the pull command with the CLI.
30 31 32 33 34 35 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 |
# File 'lib/pvectl/commands/pull.rb', line 30 def self.register(cli) cli.desc "Pull resource configuration to YAML manifest" cli.long_desc <<~HELP DESCRIPTION Exports resource configuration from the Proxmox cluster as kubectl-like YAML manifest files. Supports single resources, multiple IDs, selectors, and bulk export with --all. When writing to files (-f), shows a diff of changes and asks for confirmation before overwriting existing files. Use --yes to skip confirmation or --dry-run to preview changes without writing. EXAMPLES $ pvectl pull vm 100 $ pvectl pull vm 100 -f vm-100.yaml $ pvectl pull vm 100 -f vm-100.yaml --dry-run $ pvectl pull vm 100 101 102 -f ./manifests/ $ pvectl pull vm --all -f ./manifests/ --yes $ pvectl pull vm -f ./manifests/ $ pvectl pull vm -l tags=prod -f ./manifests/ $ pvectl pull container 200 NOTES Without -f, YAML is printed to stdout (pipe-friendly). With -f, shows diff against existing files and asks to confirm. With --all or -l, -f must point to a directory. When -f points to a directory with existing manifests and no IDs are given, IDs are inferred from file names (vm-{vmid}.yaml). File naming convention: vm-{vmid}.yaml or ct-{vmid}.yaml. SEE ALSO push, get, describe, edit HELP cli.command :pull do |c| c.flag [:f, :file], desc: "Output file or directory" c.flag [:l, :selector], desc: "Filter by selector (e.g. tags=prod,status=running)", multiple: true c.switch [:all], desc: "Pull all resources of given type", negatable: false c.switch [:y, :yes], desc: "Auto-confirm without prompting", negatable: false c.switch [:"dry-run"], desc: "Show diff without writing files", negatable: false c.flag [:node], desc: "Limit to specific node" c.action do |, , args| Pull.new(args, , ).execute end end end |
Instance Method Details
#execute ⇒ Integer
Executes the pull command.
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
# File 'lib/pvectl/commands/pull.rb', line 90 def execute resource_type_str = @args.shift return usage_error("Resource type is required (vm, container)") unless resource_type_str type = RESOURCE_TYPES[resource_type_str.downcase] return usage_error("Unknown resource type '#{resource_type_str}'. Valid: vm, container") unless type ids = @args.map(&:to_i) all = @options[:all] node = @options[:node] output = @options[:file] # Auto-infer IDs from existing manifest files in directory if ids.empty? && !all && @options[:selector].nil? && output && directory_output?(output) ids = infer_ids_from_directory(output, type) end if ids.empty? && !all && @options[:selector].nil? return usage_error("Provide resource IDs, --all, or -l selector") end if (all || @options[:selector]) && output && !directory_output?(output) return usage_error("--all and -l require -f to be a directory (end with /)") end selector = build_selector(type) load_config connection = Pvectl::Connection.new(@config) service = build_service(connection) result = service.execute(type: type, ids: ids, all: all, node: node, selector: selector) result[:errors].each { |e| $stderr.puts "Error: #{e}" } write_output(result[:manifests], type, output) result[:errors].empty? ? ExitCodes::SUCCESS : ExitCodes::GENERAL_ERROR rescue Pvectl::Config::ConfigNotFoundError, Pvectl::Config::InvalidConfigError, Pvectl::Config::ContextNotFoundError, Pvectl::Config::ClusterNotFoundError, Pvectl::Config::UserNotFoundError raise rescue StandardError => e $stderr.puts "Error: #{e.}" ExitCodes::GENERAL_ERROR end |