Class: Pvectl::Presenters::Snapshot

Inherits:
Base
  • Object
show all
Defined in:
lib/pvectl/presenters/snapshot.rb,
sig/pvectl/presenters/snapshot.rbs

Overview

Presenter for VM/container snapshots.

Defines column layout and formatting for snapshot table output. Supports both list (get) and describe output modes.

Standard columns: VMID, NAME, CREATED, DESCRIPTION Wide columns add: TYPE, VMSTATE, PARENT

Examples:

Using with formatter

presenter = Snapshot.new
formatter = Formatters::Table.new
output = formatter.format(snapshots, presenter)

See Also:

Instance Method Summary collapse

Methods inherited from Base

#format_bytes, #format_firewall, #format_firewall_rules, #format_task_history, #resource, #tags_array, #tags_display, #template_display, #to_wide_row, #uptime_human, #wide_columns

Instance Method Details

#build_children_map(siblings) ⇒ Hash<String, Array<String>>

Builds parent -> children mapping from siblings.



203
204
205
206
207
208
209
# File 'lib/pvectl/presenters/snapshot.rb', line 203

def build_children_map(siblings)
  map = Hash.new { |h, k| h[k] = [] }
  siblings.each do |snap|
    map[snap.parent] << snap.name if snap.parent
  end
  map
end

#build_multi_description(entries) ⇒ Hash

Builds describe hash for multiple VM entries.



144
145
146
147
148
149
150
151
152
153
# File 'lib/pvectl/presenters/snapshot.rb', line 144

def build_multi_description(entries)
  result = {}
  entries.each do |entry|
    snap = entry.snapshot
    label = snap.vm? ? "VM" : "CT"
    header = "#{label} #{snap.vmid} (#{snap.node})"
    result[header] = build_single_description(entry)
  end
  result
end

#build_single_description(entry) ⇒ Hash

Builds describe hash for a single VM entry.



125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/pvectl/presenters/snapshot.rb', line 125

def build_single_description(entry)
  snap = entry.snapshot
  {
    "Name" => snap.name,
    "VMID" => snap.vmid,
    "Node" => snap.node,
    "Type" => snap.resource_type&.to_s,
    "Created" => format_time(snap.created_at),
    "Description" => snap.description || "-",
    "VM State" => snap.has_vmstate? ? "Yes" : "No",
    "Parent" => snap.parent || "-",
    "Snapshot Tree" => build_tree_string(entry)
  }
end

#build_tree_data(entry) ⇒ Array<Hash>

Builds structured tree data for JSON/YAML output.



215
216
217
218
219
220
221
222
223
224
225
226
# File 'lib/pvectl/presenters/snapshot.rb', line 215

def build_tree_data(entry)
  children_map = build_children_map(entry.siblings)
  entry.siblings.map do |snap|
    node = {
      "name" => snap.name,
      "parent" => snap.parent,
      "children" => children_map[snap.name] || []
    }
    node["current_target"] = true if snap.name == entry.snapshot.name
    node
  end
end

#build_tree_string(entry) ⇒ String

Builds tree string for display in table format.



159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/pvectl/presenters/snapshot.rb', line 159

def build_tree_string(entry)
  children_map = build_children_map(entry.siblings)
  roots = entry.siblings.select { |s| s.parent.nil? }.map(&:name)
  all_roots = roots + ["(current)"]

  lines = []
  all_roots.each_with_index do |root, idx|
    last = idx == all_roots.length - 1
    if root == "(current)"
      lines << "#{last ? "\u2514\u2500" : "\u251c\u2500"} (current)"
    else
      render_tree_node(root, children_map, entry.snapshot.name, "", last, lines)
    end
  end

  lines.join("\n")
end

#columnsArray<String>

Returns column headers for standard table output.



26
27
28
# File 'lib/pvectl/presenters/snapshot.rb', line 26

def columns
  %w[VMID NAME CREATED DESCRIPTION]
end

#extra_columnsArray<String>

Returns additional column headers for wide output.



33
34
35
# File 'lib/pvectl/presenters/snapshot.rb', line 33

def extra_columns
  %w[TYPE VMSTATE PARENT]
end

#extra_values(model, **_context) ⇒ Array<String>

Returns additional values for wide output.



56
57
58
59
60
61
62
# File 'lib/pvectl/presenters/snapshot.rb', line 56

def extra_values(model, **_context)
  [
    model.resource_type&.to_s || "-",
    model.has_vmstate? ? "yes" : "no",
    model.parent || "-"
  ]
end

#format_time(time) ⇒ String

Formats time for display.



232
233
234
235
236
# File 'lib/pvectl/presenters/snapshot.rb', line 232

def format_time(time)
  return "-" if time.nil?

  time.strftime("%Y-%m-%d %H:%M:%S")
end

#render_tree_node(name, children_map, target, prefix, last, lines) ⇒ void

This method returns an undefined value.

Recursively renders a tree node.



186
187
188
189
190
191
192
193
194
195
196
197
# File 'lib/pvectl/presenters/snapshot.rb', line 186

def render_tree_node(name, children_map, target, prefix, last, lines)
  connector = last ? "\u2514\u2500" : "\u251c\u2500"
  marker = name == target ? "  \u25c0" : ""
  lines << "#{prefix}#{connector} #{name}#{marker}"

  children = children_map[name] || []
  children.each_with_index do |child, idx|
    child_prefix = prefix + (last ? "   " : "\u2502  ")
    child_last = idx == children.length - 1
    render_tree_node(child, children_map, target, child_prefix, child_last, lines)
  end
end

#snapshot_to_hash(model) ⇒ Hash

Converts a single Snapshot model to hash.



108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/pvectl/presenters/snapshot.rb', line 108

def snapshot_to_hash(model)
  {
    "vmid" => model.vmid,
    "name" => model.name,
    "node" => model.node,
    "type" => model.resource_type&.to_s,
    "description" => model.description,
    "vmstate" => model.has_vmstate?,
    "parent" => model.parent,
    "created" => format_time(model.created_at)
  }
end

#to_description(model) ⇒ Hash

Returns describe output for SnapshotDescription or plain Snapshot.



92
93
94
95
96
97
98
99
100
# File 'lib/pvectl/presenters/snapshot.rb', line 92

def to_description(model)
  return snapshot_to_hash(model) unless model.is_a?(Models::SnapshotDescription)

  if model.single?
    build_single_description(model.entries.first)
  else
    build_multi_description(model.entries)
  end
end

#to_hash(model) ⇒ Hash+

Converts model to hash for JSON/YAML output.

Handles both Models::Snapshot (for list) and Models::SnapshotDescription (for describe).



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/pvectl/presenters/snapshot.rb', line 71

def to_hash(model)
  return snapshot_to_hash(model) unless model.is_a?(Models::SnapshotDescription)

  if model.single?
    entry = model.entries.first
    snapshot_to_hash(entry.snapshot).merge(
      "snapshot_tree" => build_tree_data(entry)
    )
  else
    model.entries.map do |entry|
      snapshot_to_hash(entry.snapshot).merge(
        "snapshot_tree" => build_tree_data(entry)
      )
    end
  end
end

#to_row(model, **_context) ⇒ Array<String>

Converts Snapshot model to table row values.



42
43
44
45
46
47
48
49
# File 'lib/pvectl/presenters/snapshot.rb', line 42

def to_row(model, **_context)
  [
    model.vmid.to_s,
    model.name,
    format_time(model.created_at),
    model.description || "-"
  ]
end