Skip to content

Commit 85677b0

Browse files
committed
lib: Add CheckpointOptions struct and parsing for CRI options
Add support for parsing checkpoint options from the Kubernetes CRI CheckpointPodRequest map[string]string options field. The new ParseCheckpointOptions function validates known options and their expected types (bool, int, string). SupportedCheckpointOptions exports the currently supported options with help text for use by tools. Currently only "leave-running" is supported. Additional options (tcp-established, ghost-limit, network-lock) are defined internally to test all option type parsers. Boolean values accept: yes, no, true, false, on, off, 0, 1 Generated with Claude Code (https://claude.ai/code) Signed-off-by: Adrian Reber <areber@redhat.com>
1 parent d4ddee6 commit 85677b0

2 files changed

Lines changed: 475 additions & 0 deletions

File tree

lib/checkpoint_options.go

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
3+
package metadata
4+
5+
import (
6+
"fmt"
7+
)
8+
9+
// OptionType represents the type of a checkpoint option value
10+
type OptionType int
11+
12+
const (
13+
OptionTypeBool OptionType = iota
14+
OptionTypeInt
15+
OptionTypeString
16+
)
17+
18+
// CheckpointOption defines a known checkpoint option with its expected type
19+
type CheckpointOption struct {
20+
Type OptionType
21+
}
22+
23+
// SupportedCheckpointOption defines a supported checkpoint option with help text
24+
// for use by tools that include this package.
25+
type SupportedCheckpointOption struct {
26+
Type OptionType
27+
Help string
28+
}
29+
30+
// SupportedCheckpointOptions lists all checkpoint options that are currently
31+
// supported. Tools can use this to display help text or list available options.
32+
var SupportedCheckpointOptions = map[string]SupportedCheckpointOption{
33+
"leave-running": {
34+
Type: OptionTypeBool,
35+
Help: "leave container(s) in running state after checkpointing",
36+
},
37+
}
38+
39+
// CheckpointOptions represents the options from a CheckpointPodRequest
40+
type CheckpointOptions struct {
41+
// LeaveRunning leaves the processes running in the container after checkpointing
42+
LeaveRunning bool `json:"leaveRunning,omitempty"`
43+
// TCPEstablished enables support for established TCP connections in the checkpoint
44+
TCPEstablished bool `json:"tcpEstablished,omitempty"`
45+
// GhostLimit limits max size of deleted file contents inside image
46+
GhostLimit int64 `json:"ghostLimit,omitempty"`
47+
// NetworkLock specifies the network locking/unlocking method
48+
NetworkLock string `json:"networkLock,omitempty"`
49+
}
50+
51+
// knownCheckpointOptions defines all known checkpoint options and their expected types.
52+
// It is built from SupportedCheckpointOptions plus additional options that are not yet
53+
// supported but are defined here to ensure the parsing logic for all option types
54+
// (bool, int, string) is tested and works.
55+
var knownCheckpointOptions map[string]CheckpointOption
56+
57+
func init() {
58+
knownCheckpointOptions = make(map[string]CheckpointOption)
59+
60+
// Include all supported options
61+
for name, opt := range SupportedCheckpointOptions {
62+
knownCheckpointOptions[name] = CheckpointOption{Type: opt.Type}
63+
}
64+
65+
// Additional options for testing different option types (not yet supported)
66+
knownCheckpointOptions["tcp-established"] = CheckpointOption{Type: OptionTypeBool}
67+
knownCheckpointOptions["ghost-limit"] = CheckpointOption{Type: OptionTypeInt}
68+
knownCheckpointOptions["network-lock"] = CheckpointOption{Type: OptionTypeString}
69+
}
70+
71+
// parseBool parses a string value as a boolean, accepting:
72+
// yes, no, true, false, on, off, 0, 1 (case-insensitive)
73+
func parseBool(value string) (bool, error) {
74+
switch value {
75+
case "yes", "Yes", "YES", "true", "True", "TRUE", "on", "On", "ON", "1":
76+
return true, nil
77+
case "no", "No", "NO", "false", "False", "FALSE", "off", "Off", "OFF", "0":
78+
return false, nil
79+
default:
80+
return false, fmt.Errorf("invalid boolean value: %q (accepted: yes, no, true, false, on, off, 0, 1)", value)
81+
}
82+
}
83+
84+
// ParseCheckpointOptions validates and parses checkpoint options from a map[string]string.
85+
// It checks if the options are known and if their values match the expected types.
86+
// Returns a CheckpointOptions struct and any validation errors encountered.
87+
func ParseCheckpointOptions(options map[string]string) (*CheckpointOptions, error) {
88+
result := &CheckpointOptions{}
89+
var errs []string
90+
91+
for key, value := range options {
92+
opt, known := knownCheckpointOptions[key]
93+
if !known {
94+
errs = append(errs, fmt.Sprintf("unknown option: %q", key))
95+
continue
96+
}
97+
98+
switch opt.Type {
99+
case OptionTypeBool:
100+
boolVal, err := parseBool(value)
101+
if err != nil {
102+
errs = append(errs, fmt.Sprintf("option %q: %v", key, err))
103+
continue
104+
}
105+
switch key {
106+
case "leave-running":
107+
result.LeaveRunning = boolVal
108+
case "tcp-established":
109+
result.TCPEstablished = boolVal
110+
}
111+
112+
case OptionTypeInt:
113+
var intVal int64
114+
if _, err := fmt.Sscanf(value, "%d", &intVal); err != nil {
115+
errs = append(errs, fmt.Sprintf("option %q: invalid integer value: %q", key, value))
116+
continue
117+
}
118+
switch key {
119+
case "ghost-limit":
120+
result.GhostLimit = intVal
121+
}
122+
123+
case OptionTypeString:
124+
switch key {
125+
case "network-lock":
126+
result.NetworkLock = value
127+
}
128+
}
129+
}
130+
131+
if len(errs) > 0 {
132+
return result, fmt.Errorf("validation errors: %v", errs)
133+
}
134+
135+
return result, nil
136+
}

0 commit comments

Comments
 (0)