mirror of
https://github.com/psviderski/uncloud.git
synced 2026-08-28 03:53:33 +00:00
feat: support x-machines placement constraints in compose files (#90)
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
package compose
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const MachinesExtensionKey = "x-machines"
|
||||
|
||||
// MachinesSource represents the parsed x-machines extension data as slice of strings
|
||||
type MachinesSource []string
|
||||
|
||||
// DecodeMapstructure implements custom decoding for multiple input types
|
||||
func (m *MachinesSource) DecodeMapstructure(value interface{}) error {
|
||||
switch v := value.(type) {
|
||||
case *MachinesSource:
|
||||
// Handle case where compose-go passes a pointer to an already created instance
|
||||
*m = *v
|
||||
return nil
|
||||
case MachinesSource:
|
||||
// Handle case where compose-go passes a direct instance
|
||||
*m = v
|
||||
return nil
|
||||
case string:
|
||||
// Support single string value or comma-separated values
|
||||
// x-machines: my-machine or x-machines: "machine-1,machine-2"
|
||||
machines, err := parseMachineNames(v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*m = MachinesSource(machines)
|
||||
return nil
|
||||
case []string:
|
||||
// Support string array: x-machines: ["machine-1", "machine-2"]
|
||||
machines, err := validateMachineNames(v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*m = MachinesSource(machines)
|
||||
return nil
|
||||
case []interface{}:
|
||||
// Support interface array that may come from YAML parsing
|
||||
machineNames := make([]string, 0, len(v))
|
||||
for i, machine := range v {
|
||||
str, ok := machine.(string)
|
||||
if !ok {
|
||||
return fmt.Errorf("x-machines[%d] is not a string, got %T", i, machine)
|
||||
}
|
||||
machineNames = append(machineNames, str)
|
||||
}
|
||||
machines, err := validateMachineNames(machineNames)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*m = MachinesSource(machines)
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("x-machines must be a string or list of strings, got %T", value)
|
||||
}
|
||||
}
|
||||
|
||||
// parseMachineNames parses a single string that may contain comma-separated machine names
|
||||
func parseMachineNames(machinesStr string) ([]string, error) {
|
||||
// Split by comma and process each machine name, works for both single and multiple values
|
||||
parts := strings.Split(machinesStr, ",")
|
||||
machines := make([]string, 0, len(parts))
|
||||
for _, part := range parts {
|
||||
machines = append(machines, strings.TrimSpace(part))
|
||||
}
|
||||
return validateMachineNames(machines)
|
||||
}
|
||||
|
||||
// validateMachineNames validates machine names to ensure they are not empty and contain valid characters.
|
||||
func validateMachineNames(machines []string) ([]string, error) {
|
||||
for i, machine := range machines {
|
||||
machine = strings.TrimSpace(machine)
|
||||
if machine == "" {
|
||||
return nil, fmt.Errorf("x-machines[%d] cannot be empty", i)
|
||||
}
|
||||
machines[i] = machine
|
||||
}
|
||||
return machines, nil
|
||||
}
|
||||
Reference in New Issue
Block a user