package main import ( "github.com/goccy/go-yaml" "github.com/spf13/cobra" "log" "os" ) type VolumeDefinition struct { Name string `yaml:"name"` } type VolumeConfiguration struct { Name string `yaml:"name"` Container string `yaml:"container"` Host string `yaml:"host"` } type ContainerDefinition struct { Name string `yaml:"name"` Image string `yaml:"image"` Volumes []VolumeConfiguration `yaml:"volumes"` ExtraArgs []string `yaml:"extra-args"` } type ServiceDefinition struct { Name string `yaml:"name"` Volumes []VolumeDefinition `yaml:"volumes"` Containers []ContainerDefinition `yaml:"containers"` } func GetServiceDefinitionFromFile(path string) ServiceDefinition { var definition ServiceDefinition defData, err := os.ReadFile(path) // TODO: Bubble up error? if err != nil { log.Fatalf("Could not parse service configuration at %s: %s", path, err) } if err = yaml.Unmarshal(defData, &definition); err != nil { log.Fatalf("Could not unpack service configuration: %s", err) } return definition } func CreateService(definition ServiceDefinition) { var err error err = CreatePod(definition.Name) if err != nil { log.Fatalf("%s", err) } knownVolumes := map[string]string{} for _, volume := range definition.Volumes { namespacedName := definition.Name + "_" + volume.Name CreateVolume(namespacedName, true) knownVolumes[volume.Name] = namespacedName } for _, container := range definition.Containers { if err = CreateContainer(container, knownVolumes, definition.Name); err != nil { log.Fatalf("%s", err) } } } var cli = &cobra.Command{ Use: "spud", Short: "A not-entirely-terrible-way to manage self-hosted services.", } var start = &cobra.Command{ Use: "start", Short: "Creates or updates a service based on the provided definition.", Run: func(cmd *cobra.Command, args []string) { pathProvided := args[0] def := GetServiceDefinitionFromFile(pathProvided) CreateService(def) }, } func main() { cli.AddCommand(start) cli.Execute() }