diff --git a/cmd/ore/hetzner.go b/cmd/ore/hetzner.go new file mode 100644 index 000000000..cb2845211 --- /dev/null +++ b/cmd/ore/hetzner.go @@ -0,0 +1,12 @@ +// Copyright The Mantle Authors. +// SPDX-License-Identifier: Apache-2.0 + +package main + +import ( + "github.com/flatcar/mantle/cmd/ore/hetzner" +) + +func init() { + root.AddCommand(hetzner.Hetzner) +} diff --git a/cmd/ore/hetzner/create.go b/cmd/ore/hetzner/create.go new file mode 100644 index 000000000..ec19d0336 --- /dev/null +++ b/cmd/ore/hetzner/create.go @@ -0,0 +1,44 @@ +// Copyright The Mantle Authors. +// SPDX-License-Identifier: Apache-2.0 + +package hetzner + +import ( + "fmt" + + "github.com/spf13/cobra" +) + +var ( + cmdCreate = &cobra.Command{ + Use: "create-image", + Short: "Create image on Hetzner", + Long: `Upload an image to Hetzner. + +After a successful run, the final line of output will be the ID of the image. +`, + RunE: runCreate, + } + + path string + name string + board string +) + +func init() { + Hetzner.AddCommand(cmdCreate) + cmdCreate.Flags().StringVar(&path, "file", + "https://alpha.release.flatcar-linux.net/amd64-usr/current/flatcar_production_hetzner_image.bin.bz2", + "Flatcar image (can be an absolute path or an URL)") + cmdCreate.Flags().StringVar(&name, "name", "", "image name") + cmdCreate.Flags().StringVar(&board, "board", "amd64-usr", "board of the image") +} + +func runCreate(cmd *cobra.Command, args []string) error { + id, err := API.UploadImage(cmd.Context(), name, path, board) + if err != nil { + return fmt.Errorf("creating an image: %w", err) + } + fmt.Println(id) + return nil +} diff --git a/cmd/ore/hetzner/gc.go b/cmd/ore/hetzner/gc.go new file mode 100644 index 000000000..16e377fb9 --- /dev/null +++ b/cmd/ore/hetzner/gc.go @@ -0,0 +1,35 @@ +// Copyright The Mantle Authors. +// SPDX-License-Identifier: Apache-2.0 + +package hetzner + +import ( + "fmt" + "time" + + "github.com/spf13/cobra" +) + +var ( + cmdGC = &cobra.Command{ + Use: "gc", + Short: "GC resources in Hetzner", + Long: `Delete instances and images created over the given duration ago`, + RunE: runGC, + } + + gcDuration time.Duration +) + +func init() { + Hetzner.AddCommand(cmdGC) + cmdGC.Flags().DurationVar(&gcDuration, "duration", 5*time.Hour, "how old resources must be before they're considered garbage") +} + +func runGC(cmd *cobra.Command, args []string) error { + if err := API.GC(cmd.Context(), gcDuration); err != nil { + return fmt.Errorf("running garbage collection: %w", err) + } + + return nil +} diff --git a/cmd/ore/hetzner/hetzner.go b/cmd/ore/hetzner/hetzner.go new file mode 100644 index 000000000..b04431cf1 --- /dev/null +++ b/cmd/ore/hetzner/hetzner.go @@ -0,0 +1,42 @@ +// Copyright The Mantle Authors. +// SPDX-License-Identifier: Apache-2.0 + +package hetzner + +import ( + "fmt" + + "github.com/coreos/pkg/capnslog" + "github.com/spf13/cobra" + + "github.com/flatcar/mantle/cli" + "github.com/flatcar/mantle/platform/api/hetzner" +) + +var ( + plog = capnslog.NewPackageLogger("github.com/flatcar/mantle", "ore/hetzner") + + Hetzner = &cobra.Command{ + Use: "hetzner [command]", + Short: "hetzner image utilities", + } + + API *hetzner.API + options hetzner.Options +) + +func init() { + cli.WrapPreRun(Hetzner, preflightCheck) + Hetzner.PersistentFlags().StringVar(&options.Token, "hetzner-token", "", "Hetzner token for client authentication") + Hetzner.PersistentFlags().StringVar(&options.Location, "hetzner-location", "", "Hetzner location name") +} + +func preflightCheck(cmd *cobra.Command, args []string) error { + api, err := hetzner.New(&options) + if err != nil { + return fmt.Errorf("creating the Hetner API client: %w", err) + } + + API = api + return nil +}