isle/go/cmd/entrypoint/storage.go

128 lines
3.1 KiB
Go

package main
import (
"cmp"
"errors"
"fmt"
"isle/daemon/daecommon"
"slices"
"golang.org/x/exp/maps"
)
type storageAllocation struct {
Index int `yaml:"index"`
daecommon.ConfigStorageAllocation `yaml:",inline"`
}
func indexStorageAllocations(
config daecommon.NetworkConfig,
) []storageAllocation {
slices.SortFunc(
config.Storage.Allocations,
func(i, j daecommon.ConfigStorageAllocation) int {
return cmp.Compare(i.RPCPort, j.RPCPort)
},
)
allocs := make([]storageAllocation, len(config.Storage.Allocations))
for i := range config.Storage.Allocations {
allocs[i] = storageAllocation{i, config.Storage.Allocations[i]}
}
return allocs
}
var subCmdStorageAllocationList = subCmd{
name: "list-allocation",
plural: "s",
descr: "Lists all storage which is currently allocated on this host",
do: doWithOutput(func(ctx subCmdCtx) (any, error) {
ctx, err := ctx.withParsedFlags()
if err != nil {
return nil, fmt.Errorf("parsing flags: %w", err)
}
config, err := ctx.getDaemonRPC().GetConfig(ctx)
if err != nil {
return nil, fmt.Errorf("getting network config: %w", err)
}
return indexStorageAllocations(config), nil
}),
}
var subCmdStorageAllocationRemove = subCmd{
name: "remove-allocation",
descr: "Removes an allocation which has been previously added. " +
"Allocations are identified by their index field from the output of " +
"`storage list-allocation(s)`.",
do: func(ctx subCmdCtx) error {
indexes := ctx.flags.IntSlice(
"index", nil,
"Index of the storage allocation which should be removed. Can be "+
"specified more than once",
)
ctx, err := ctx.withParsedFlags()
if err != nil {
return fmt.Errorf("parsing flags: %w", err)
}
if len(*indexes) == 0 {
return errors.New("At least one --index must be specified")
}
config, err := ctx.getDaemonRPC().GetConfig(ctx)
if err != nil {
return fmt.Errorf("getting network config: %w", err)
}
var (
allocs = indexStorageAllocations(config)
allocsByIndex = map[int]daecommon.ConfigStorageAllocation{}
)
for _, alloc := range allocs {
allocsByIndex[alloc.Index] = alloc.ConfigStorageAllocation
}
for _, index := range *indexes {
if _, ok := allocsByIndex[index]; !ok {
return fmt.Errorf(
"Index %d not found in configured storage allocations: %w",
index, err,
)
}
delete(allocsByIndex, index)
}
// we sort the new allocation set so that tests are deterministic
newAllocs := maps.Values(allocsByIndex)
slices.SortFunc(
newAllocs,
func(i, j daecommon.ConfigStorageAllocation) int {
return cmp.Compare(i.RPCPort, j.RPCPort)
},
)
config.Storage.Allocations = newAllocs
if err := ctx.getDaemonRPC().SetConfig(ctx, config); err != nil {
return fmt.Errorf("updating the network config: %w", err)
}
return nil
},
}
var subCmdStorage = subCmd{
name: "storage",
descr: "Sub-commands having to do with configuration of storage on this host",
do: func(ctx subCmdCtx) error {
return ctx.doSubCmd(
subCmdStorageAllocationList,
subCmdStorageAllocationRemove,
)
},
}