Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
e99490b
fix(boot-service): uri merging, service name, default path
synackd Jun 3, 2026
eecb41d
docs(man): update default boot-service path to /boot-service
synackd Jun 3, 2026
c2a9093
chore(boot-service): align spacing in multi-line example JSON
synackd Jun 3, 2026
e5b44f7
fix(cmd): boot bmc add: do not require -d
synackd Jun 4, 2026
c2bc026
fix(cmd): boot bmc set: do not require -d
synackd Jun 4, 2026
df24fbf
fix(cmd): boot config add: do not require -d
synackd Jun 4, 2026
7b2c5f3
fix(cmd): boot config set: do not require -d
synackd Jun 4, 2026
4560131
fix(cmd): boot node add: do not require -d
synackd Jun 4, 2026
80a6d60
fix(cmd): boot node set: do not require -d
synackd Jun 4, 2026
c2dc5d0
fix(cmd): boot bmc patch: do not require -d
synackd Jun 4, 2026
7030a4c
fix(cmd): boot config patch: do not require -d
synackd Jun 4, 2026
255c204
fix(cmd): boot node patch: do not require -d
synackd Jun 4, 2026
753fa51
docs(man): clarify boot command synopsis, add cmd table
synackd Jun 5, 2026
273fbd4
docs(man): boot: fix command form descriptions
synackd Jun 5, 2026
987e2f1
fix(cmd): boot: respect --no-confirm for delete
synackd Jun 5, 2026
6cc4dae
fix(cmd): boot bmc get: node -> bmc
synackd Jun 5, 2026
5096850
fix(cmd): boot: patch-format -> patch-method
synackd Jun 6, 2026
a6d41ac
fix(cmd): boot: prompt for deletion before client actions
synackd Jun 6, 2026
0144a20
docs(man): set /boot-service as default boot-service base path
synackd Jun 6, 2026
082fbdf
docs(man): boot: add uid for set commands
synackd Jun 6, 2026
c315eb7
test: add boot-service config options
synackd Jun 8, 2026
288f6cd
fix(cmd): boot: clarify add is able to add >1 BMC
synackd Jun 8, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 37 additions & 33 deletions cmd/boot/bmc/add.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,52 +20,54 @@ func newCmdBootBmcAdd() *cobra.Command {
var bootBmcAddCmd = &cobra.Command{
Use: "add",
Args: cobra.NoArgs,
Short: "Add a new BMC to boot-service",
Long: `Add a new BMC to boot-service.
Short: "Add one or more BMCs to boot-service",
Long: `Add one or more BMCs to boot-service.

See ochami-boot(1) for more details.`,
Example: ` # Add BMC using payload data
ochami boot bmc add -d \
'{
"xname": "x1000c0s0b0",
"description": "This node's BMC",
"interface": {
"type": "management",
"mac": "de:ca:fc:0f:fe:e1",
"ip": "172.16.0.254"
}
}'
"xname": "x1000c0s0b0",
"description": "This node's BMC",
"interface": {
"type": "management",
"mac": "de:ca:fc:0f:fe:e1",
"ip": "172.16.0.254"
}
}'

# Add multiple BMCs using payload data
ochami boot bmc add -d \
'[
{
"xname": "x1000c0s0b0",
"description": "Node 1's BMC",
"interface": {
"type": "management",
"mac": "de:ca:fc:0f:fe:e1",
"ip": "172.16.0.1"
}
},
{
"xname": "x1000c0s0b1",
"description": "Node 2's BMC",
"interface": {
"type": "management",
"mac": "de:ca:fc:0f:fe:e2",
"ip": "172.16.0.2"
}
}
]'
{
"xname": "x1000c0s0b0",
"description": "Node 1's BMC",
"interface": {
"type": "management",
"mac": "de:ca:fc:0f:fe:e1",
"ip": "172.16.0.1"
}
},
{
"xname": "x1000c0s0b1",
"description": "Node 2's BMC",
"interface": {
"type": "management",
"mac": "de:ca:fc:0f:fe:e2",
"ip": "172.16.0.2"
}
}
]'

# Add BMCs using input payload file
ochami boot bmc add -d @payload.json
ochami boot bmc add -d @payload.yaml -f yaml

# Add BMCs using data from stdin
echo '<json_data>' | ochami boot bmc add -d @-
echo '<yaml_data>' | ochami boot bmc add -d @- -f yaml`,
echo '<json_data>' | ochami boot bmc add
echo '<yaml_data>' | ochami boot bmc add -d @- -f yaml
echo '<yaml_data>' | ochami boot bmc add -f yaml`,
Run: func(cmd *cobra.Command, args []string) {
// Create client to use for requests
bootServiceClient := boot_service_lib.GetClient(cmd)
Expand All @@ -75,7 +77,11 @@ See ochami-boot(1) for more details.`,

// Read node data
bmcs := []boot_service_client.CreateBMCRequest{}
cli.HandlePayloadSlice[boot_service_client.CreateBMCRequest](cmd, &bmcs)
if cmd.Flag("data").Changed {
cli.HandlePayloadSlice[boot_service_client.CreateBMCRequest](cmd, &bmcs)
} else {
cli.HandlePayloadStdinSlice[boot_service_client.CreateBMCRequest](cmd, &bmcs)
}

// Send off requests
bmcsCreated, errs, err := bootServiceClient.AddBMCs(cli.Token, bmcs)
Expand Down Expand Up @@ -106,8 +112,6 @@ See ochami-boot(1) for more details.`,
bootBmcAddCmd.Flags().StringP("data", "d", "", "payload data or (if starting with @) file containing payload data (can be - to read from stdin)")
bootBmcAddCmd.Flags().VarP(&cli.FormatInput, "format-input", "f", "format of input payload data (json,json-pretty,yaml)")

bootBmcAddCmd.MarkFlagsOneRequired("data")

bootBmcAddCmd.RegisterFlagCompletionFunc("format-input", cli.CompletionFormatData)

return bootBmcAddCmd
Expand Down
20 changes: 20 additions & 0 deletions cmd/boot/bmc/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,26 @@ See ochami-boot(1) for more details.`,
# Don't confirm deletion
ochami boot bmc delete --no-confirm bmc-773d99bf`,
Run: func(cmd *cobra.Command, args []string) {
// Ask before attempting deletion unless --no-confirm was passed
noConfirm, err := cmd.Flags().GetBool("no-confirm")
if err != nil {
log.Logger.Error().Err(err).Msg("failed to get --no-confirm")
os.Exit(1)
}
if !noConfirm {
log.Logger.Debug().Msg("--no-confirm not passed, prompting user to confirm deletion")
respDelete, err := cli.Ios.LoopYesNo("Really delete?")
if err != nil {
log.Logger.Error().Err(err).Msg("failed to fetch user input")
os.Exit(1)
} else if !respDelete {
log.Logger.Info().Msg("user aborted BMC deletion")
os.Exit(0)
} else {
log.Logger.Debug().Msg("user answered affirmatively to delete BMC(s)")
}
}

// Create client to use for requests
bootServiceClient := boot_service_lib.GetClient(cmd)

Expand Down
2 changes: 1 addition & 1 deletion cmd/boot/bmc/get.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ func newCmdBootBmcGet() *cobra.Command {

See ochami-boot(1) for more details.`,
Example: ` # Get info about a BMC
ochami boot node get bmc-773d99bf`,
ochami boot bmc get bmc-773d99bf`,
Run: func(cmd *cobra.Command, args []string) {
// Create client to use for requests
bootServiceClient := boot_service_lib.GetClient(cmd)
Expand Down
25 changes: 15 additions & 10 deletions cmd/boot/bmc/patch.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,12 @@ If --set/--unset/--add/--remove are specified or --patch-method is 'keyval',
the manual, key-value patch method using dot notation (e.g. key.subkey=value)
is used.

Otherwise, --data can be used to pass in raw patch data, using --patch-format
to specify the patch format (see examples below).
Otherwise, stdin and/or --data can be used to pass in raw patch data, using
--patch-method to specify the patch format (see examples below).

--format-input can only be used with --data. It can be used to tell ochami to
use a different format (e.g. YAML) for the data input for either of these
methods.
--format-input can only be used with stdin/--data. It can be used to tell
ochami to use a different format (e.g. YAML) for the data input for either
of these methods.

See ochami-boot(1) for more details.`,
Example: ` # Patch using JSON patch (RFC 6902)
Expand All @@ -67,7 +67,9 @@ See ochami-boot(1) for more details.`,

# Patch using stdin
echo '<json_data>' | ochami boot bmc patch bmc-773d99bf -d @-
echo '<yaml_data>' | ochami boot bmc patch bmc-773d99bf -f yaml -d @-`,
echo '<json_data>' | ochami boot bmc patch bmc-773d99bf
echo '<yaml_data>' | ochami boot bmc patch bmc-773d99bf -d @- -f yaml
echo '<yaml_data>' | ochami boot bmc patch bmc-773d99bf -f yaml`,
Run: func(cmd *cobra.Command, args []string) {
// Create client to use for requests
bootServiceClient := boot_service_lib.GetClient(cmd)
Expand All @@ -77,8 +79,8 @@ See ochami-boot(1) for more details.`,

var patchData map[string]interface{}
if cmd.Flag("set").Changed || cmd.Flag("unset").Changed || cmd.Flag("add").Changed || cmd.Flag("remove").Changed {
if cmd.Flag("patch-format").Changed && formatPatch != client.PatchMethodKeyVal {
log.Logger.Warn().Msg("overriding --patch-format since --set/--unset/--add/--remove was passed")
if cmd.Flag("patch-method").Changed && formatPatch != client.PatchMethodKeyVal {
log.Logger.Warn().Msg("overriding --patch-method since --set/--unset/--add/--remove was passed")
}

pd, err := client.NewKeyValPatch(setList, unsetList, addList, removeList)
Expand All @@ -89,7 +91,11 @@ See ochami-boot(1) for more details.`,
}
patchData = pd
} else {
cli.HandlePayload(cmd, &patchData)
if cmd.Flag("data").Changed {
cli.HandlePayload(cmd, &patchData)
} else {
cli.HandlePayloadStdin(cmd, &patchData)
}
}

bmcPatched, err := bootServiceClient.PatchBMC(cli.Token, formatPatch, args[0], patchData)
Expand All @@ -116,7 +122,6 @@ See ochami-boot(1) for more details.`,
bootBmcPatchCmd.MarkFlagsMutuallyExclusive("format-input", flag)
bootBmcPatchCmd.MarkFlagsMutuallyExclusive("data", flag)
}
bootBmcPatchCmd.MarkFlagsOneRequired("data", "set", "unset", "add", "remove")

bootBmcPatchCmd.RegisterFlagCompletionFunc("format-input", cli.CompletionFormatData)

Expand Down
28 changes: 16 additions & 12 deletions cmd/boot/bmc/set.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,22 +27,24 @@ See ochami-boot(1) for more details.`,
Example: ` # Set BMC details using payload data
ochami boot bmc set bmc-773d99bf -d \
'{
"xname": "x1000c0s0b0",
"description": "This node's BMC",
"interface": {
"type": "management",
"mac": "de:ca:fc:0f:fe:e1",
"ip": "172.16.0.254"
}
}'
"xname": "x1000c0s0b0",
"description": "This node's BMC",
"interface": {
"type": "management",
"mac": "de:ca:fc:0f:fe:e1",
"ip": "172.16.0.254"
}
}'

# Set BMC details using input payload file
ochami boot bmc set -d @payload.json bmc-773d99bf
ochami boot bmc set -d @payload.yaml -f yaml bmc-773d99bf

# Set BMC details using data from stdin
echo '<json_data>' | ochami boot bmc set -d @- bmc-773d99bf
echo '<yaml_data>' | ochami boot bmc set -d @- -f yaml bmc-773d99bf`,
echo '<json_data>' | ochami boot bmc set bmc-773d99bf
echo '<yaml_data>' | ochami boot bmc set -d @- -f yaml bmc-773d99bf
echo '<yaml_data>' | ochami boot bmc set -f yaml bmc-773d99bf`,
Run: func(cmd *cobra.Command, args []string) {
// Create client to use for requests
bootServiceClient := boot_service_lib.GetClient(cmd)
Expand All @@ -52,7 +54,11 @@ See ochami-boot(1) for more details.`,

// Read BMC data
bmc := boot_service_client.UpdateBMCRequest{}
cli.HandlePayload(cmd, &bmc)
if cmd.Flag("data").Changed {
cli.HandlePayload(cmd, &bmc)
} else {
cli.HandlePayloadStdin(cmd, &bmc)
}

// Send off requests
bmcSet, err := bootServiceClient.SetBMC(cli.Token, args[0], bmc)
Expand All @@ -70,8 +76,6 @@ See ochami-boot(1) for more details.`,
bootBmcSetCmd.Flags().StringP("data", "d", "", "payload data or (if starting with @) file containing payload data (can be - to read from stdin)")
bootBmcSetCmd.Flags().VarP(&cli.FormatInput, "format-input", "f", "format of input payload data (json,json-pretty,yaml)")

bootBmcSetCmd.MarkFlagsOneRequired("data")

bootBmcSetCmd.RegisterFlagCompletionFunc("format-input", cli.CompletionFormatData)

return bootBmcSetCmd
Expand Down
84 changes: 44 additions & 40 deletions cmd/boot/config/add.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,54 +27,56 @@ See ochami-boot(1) for more details.`,
Example: ` # Add boot configuration using payload data
ochami boot config add -d \
'{
"hosts": [
"item1",
"item2"
],
"macs": [
"de:ca:fc:0f:fe:e1",
"de:ca:fc:0f:fe:e2"
],
"nids": [
1,
2
],
"groups": [
"group1",
"group2"
],
"kernel": "http://s3.openchami.cluster/kernels/vmlinuz1",
"initrd": "http://s3.openchami.cluster/initrds/initramfs1.img",
"params": "console=tty0,115200n8 console=ttyS0,115200n8",
"priority": 42
}'
"hosts": [
"item1",
"item2"
],
"macs": [
"de:ca:fc:0f:fe:e1",
"de:ca:fc:0f:fe:e2"
],
"nids": [
1,
2
],
"groups": [
"group1",
"group2"
],
"kernel": "http://s3.openchami.cluster/kernels/vmlinuz1",
"initrd": "http://s3.openchami.cluster/initrds/initramfs1.img",
"params": "console=tty0,115200n8 console=ttyS0,115200n8",
"priority": 42
}'

# Add multiple boot configurations using payload data
ochami boot config add -d \
'[
{
"hosts": ["host1"],
"kernel": "http://s3.openchami.cluster/kernels/vmlinuz1",
"initrd": "http://s3.openchami.cluster/initrds/initramfs1.img",
"params": "console=tty0,115200n8 console=ttyS0,115200n8",
"priority": 42
},
{
"macs": ["de:ca:fc:0f:fe:ee"],
"kernel": "http://s3.openchami.cluster/kernels/vmlinuz2",
"initrd": "http://s3.openchami.cluster/initrds/initramfs2.img",
"params": "ip=dhcp",
"priority": 43
}
]'
{
"hosts": ["host1"],
"kernel": "http://s3.openchami.cluster/kernels/vmlinuz1",
"initrd": "http://s3.openchami.cluster/initrds/initramfs1.img",
"params": "console=tty0,115200n8 console=ttyS0,115200n8",
"priority": 42
},
{
"macs": ["de:ca:fc:0f:fe:ee"],
"kernel": "http://s3.openchami.cluster/kernels/vmlinuz2",
"initrd": "http://s3.openchami.cluster/initrds/initramfs2.img",
"params": "ip=dhcp",
"priority": 43
}
]'

# Add boot configuration using input payload file
ochami boot config add -d @payload.json
ochami boot config add -d @payload.yaml -f yaml

# Add boot configuration using data from stdin
echo '<json_data>' | ochami boot config add -d @-
echo '<yaml_data>' | ochami boot config add -d @- -f yaml`,
echo '<json_data>' | ochami boot config add
echo '<yaml_data>' | ochami boot config add -d @- -f yaml
echo '<yaml_data>' | ochami boot config add -f yaml`,
Run: func(cmd *cobra.Command, args []string) {
// Create client to use for requests
bootServiceClient := boot_service_lib.GetClient(cmd)
Expand All @@ -84,7 +86,11 @@ See ochami-boot(1) for more details.`,

// Read boot configuration data
bcs := []boot_service_client.CreateBootConfigurationRequest{}
cli.HandlePayloadSlice[boot_service_client.CreateBootConfigurationRequest](cmd, &bcs)
if cmd.Flag("data").Changed {
cli.HandlePayloadSlice[boot_service_client.CreateBootConfigurationRequest](cmd, &bcs)
} else {
cli.HandlePayloadStdinSlice[boot_service_client.CreateBootConfigurationRequest](cmd, &bcs)
}

// Send off requests
cfgsCreated, errs, err := bootServiceClient.AddBootConfigs(cli.Token, bcs)
Expand Down Expand Up @@ -115,8 +121,6 @@ See ochami-boot(1) for more details.`,
bootConfigAddCmd.Flags().StringP("data", "d", "", "payload data or (if starting with @) file containing payload data (can be - to read from stdin)")
bootConfigAddCmd.Flags().VarP(&cli.FormatInput, "format-input", "f", "format of input payload data (json,json-pretty,yaml)")

bootConfigAddCmd.MarkFlagsOneRequired("data")

bootConfigAddCmd.RegisterFlagCompletionFunc("format-input", cli.CompletionFormatData)

return bootConfigAddCmd
Expand Down
Loading
Loading