Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
26 changes: 17 additions & 9 deletions cmd/kola/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ package main

import (
"fmt"
"io/ioutil"
"net"
"os"
"os/user"
Expand All @@ -42,7 +41,7 @@ var (
kolaDisableSELinuxAVCChecks bool
defaultTargetBoard = sdk.DefaultBoard()
kolaArchitectures = []string{"amd64"}
kolaPlatforms = []string{"akamai", "aws", "azure", "brightbox", "do", "esx", "external", "gce", "hetzner", "openstack", "qemu", "qemu-unpriv", "scaleway"}
kolaPlatforms = []string{"akamai", "aws", "azure", "brightbox", "do", "esx", "external", "gce", "hetzner", "openstack", "qemu", "qemu-unpriv", "scaleway", "stackit"}
kolaDistros = []string{"cl", "fcos", "rhcos"}
kolaChannels = []string{"alpha", "beta", "stable", "edge", "lts"}
kolaOfferings = []string{"basic", "pro"}
Expand Down Expand Up @@ -225,12 +224,20 @@ func init() {
sv(&kola.AkamaiOptions.Image, "akamai-image", "", "Akamai image ID")
sv(&kola.AkamaiOptions.Region, "akamai-region", "", "Akamai region")
sv(&kola.AkamaiOptions.Type, "akamai-type", "g6-nanode-1", "Akamai instance type")

// STACKIT specific options
sv(&kola.STACKITOptions.Region, "stackit-region", "eu01", "STACKIT region")
sv(&kola.STACKITOptions.ProjectId, "stackit-project-id", "", "STACKIT project ID")
sv(&kola.STACKITOptions.ServiceAccountKeyPath, "stackit-service-account-key-path", "$HOME/.stackit/credentials.json", "STACKIT service account key path")
sv(&kola.STACKITOptions.MachineType, "stackit-type", "c2i.8", "STACKIT instance type")
sv(&kola.STACKITOptions.AvailabilityZone, "stackit-availability-zone", "eu01-2", "STACKIT availability zone")
sv(&kola.STACKITOptions.ImageId, "stackit-image-id", "", "STACKIT image ID")
}

// Sync up the command line options if there is dependency
func syncOptions() error {
// sync `Board` option with other cloud provider
// it seems kola has a strong dependency to qemu and it has been
// it seems kola has a strong dependency to qemu, and it has been
// build around that's why the `Board` is associated to `QEMU`
// but it can be helpful for other provider to get access to the Board in the runtime
board := kola.QEMUOptions.Board
Expand All @@ -245,6 +252,7 @@ func syncOptions() error {
kola.ScalewayOptions.Board = board
kola.HetznerOptions.Board = board
kola.AkamaiOptions.Board = board
kola.STACKITOptions.Board = board

validateOption := func(name, item string, valid []string) error {
for _, v := range valid {
Expand Down Expand Up @@ -284,7 +292,7 @@ func syncOptions() error {
kola.QEMUOptions.Firmware = kolaDefaultFirmware[kola.QEMUOptions.Board]
}
if kola.QEMUOptions.EnableSecureboot && kola.QEMUOptions.OVMFVars == "" {
return fmt.Errorf("Secureboot requires OVMF vars file")
return fmt.Errorf("secureboot requires OVMF vars file")
}
units, _ := root.PersistentFlags().GetStringSlice("debug-systemd-units")
for _, unit := range units {
Expand All @@ -302,15 +310,15 @@ func syncOptions() error {
if kola.Options.IgnitionVersion == "" {
kola.Options.IgnitionVersion, ok = kolaIgnitionVersionDefaults[kola.Options.Distribution]
if !ok {
return fmt.Errorf("Distribution %q has no default Ignition version", kola.Options.Distribution)
return fmt.Errorf("distribution %q has no default Ignition version", kola.Options.Distribution)
}
}

if kola.Options.SSHRetries == 0 {
kola.Options.SSHRetries = kolaSSHRetries
}
if kola.Options.SSHRetries < 0 {
return fmt.Errorf("Number of SSH retries can't be negative, is %d", kola.Options.SSHRetries)
return fmt.Errorf("number of SSH retries can't be negative, is %d", kola.Options.SSHRetries)
}
if kola.Options.SSHTimeout == 0 {
kola.Options.SSHTimeout = kolaSSHTimeout
Expand All @@ -331,14 +339,14 @@ func GetSSHKeys(sshKeys []string) ([]agent.Key, error) {
if agentEnv != "" {
f, err := net.Dial("unix", agentEnv)
if err != nil {
return nil, fmt.Errorf("Couldn't connect to unix socket %q: %v", agentEnv, err)
return nil, fmt.Errorf("couldn't connect to unix socket %q: %v", agentEnv, err)
}
defer f.Close()

agent := agent.NewClient(f)
keys, err := agent.List()
if err != nil {
return nil, fmt.Errorf("Couldn't talk to ssh-agent: %v", err)
return nil, fmt.Errorf("couldn't talk to ssh-agent: %v", err)
}
for _, key := range keys {
allKeys = append(allKeys, *key)
Expand All @@ -359,7 +367,7 @@ func GetSSHKeys(sshKeys []string) ([]agent.Key, error) {
}
// read key files, failing if any are missing
for _, path := range sshKeys {
keybytes, err := ioutil.ReadFile(path)
keybytes, err := os.ReadFile(path)
if err != nil {
return nil, err
}
Expand Down
10 changes: 10 additions & 0 deletions cmd/ore/stackit.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Copyright The Mantle Authors.
// SPDX-License-Identifier: Apache-2.0

package main

import "github.com/flatcar/mantle/cmd/ore/stackit"

func init() {
root.AddCommand(stackit.STACKIT)
}
36 changes: 36 additions & 0 deletions cmd/ore/stackit/create.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package stackit

import (
"fmt"
"github.com/spf13/cobra"
)

var (
cmdCreate = &cobra.Command{
Use: "create-image",
Short: "Create image on STACKIT",
Long: "Upload an image to STACKIT",
RunE: runCreate,
}

name string
board string
file string
)

func init() {
STACKIT.AddCommand(cmdCreate)
cmdCreate.Flags().StringVar(&file, "file", "flatcar_production_stackit_image.img", "path to local Flatcar image (.img)")
cmdCreate.Flags().StringVar(&name, "name", "flatcar-kola-test", "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, file, board)
if err != nil {
return fmt.Errorf("creating an image: %w", err)
}
fmt.Println(id)
return nil
}
31 changes: 31 additions & 0 deletions cmd/ore/stackit/gc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package stackit

import (
"fmt"
"github.com/spf13/cobra"
"time"
)

var (
cmdGC = &cobra.Command{
Use: "gc",
Short: "GC resources in STACKIT",
Long: "Delete instances and images created over the given duration ago",
RunE: runGC,
}

gcDuration time.Duration
)

func init() {
STACKIT.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
}
43 changes: 43 additions & 0 deletions cmd/ore/stackit/stackit.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright The Mantle Authors.
// SPDX-License-Identifier: Apache-2.0

package stackit

import (
"fmt"
"github.com/coreos/pkg/capnslog"
"github.com/flatcar/mantle/cli"
"github.com/flatcar/mantle/platform/api/stackit"
"github.com/spf13/cobra"
"os"
)

var (
plog = capnslog.NewPackageLogger("github.com/flatcar/mantle", "ore/stackit")

STACKIT = &cobra.Command{
Use: "stackit [command]",
Short: "stackit image utilities",
}

API *stackit.API
options stackit.Options
)

func init() {
cli.WrapPreRun(STACKIT, preflightCheck)
STACKIT.PersistentFlags().StringVar(&options.Region, "stackit-region", "eu01", "STACKIT region")
STACKIT.PersistentFlags().StringVar(&options.ProjectId, "stackit-project-id", "", "STACKIT project ID")
STACKIT.PersistentFlags().StringVar(&options.ServiceAccountKeyPath, "stackit-service-account-key-path", "", "STACKIT service account key path")
}

func preflightCheck(cmd *cobra.Command, args []string) error {
a, err := stackit.New(&options)
if err != nil {
fmt.Fprintf(os.Stderr, "could not create STACKIT API client: %v\n", err)
os.Exit(1)
}

API = a
return nil
}
4 changes: 4 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ require (
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.35
github.com/spf13/cobra v1.10.2
github.com/spf13/pflag v1.0.10
github.com/stackitcloud/stackit-sdk-go/core v0.17.3
github.com/stackitcloud/stackit-sdk-go/services/iaas v1.0.0
github.com/stretchr/testify v1.11.1
github.com/vincent-petithory/dataurl v1.0.0
github.com/vishvananda/netlink v1.3.1
Expand All @@ -57,6 +59,7 @@ require (
golang.org/x/sys v0.38.0
google.golang.org/api v0.257.0
gopkg.in/yaml.v3 v3.0.1
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397
)

require (
Expand Down Expand Up @@ -127,6 +130,7 @@ require (
github.com/prometheus/common v0.66.1 // indirect
github.com/prometheus/procfs v0.16.1 // indirect
github.com/spiffe/go-spiffe/v2 v2.6.0 // indirect
github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.17.1 // indirect
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect
go.etcd.io/bbolt v1.3.9 // indirect
go.etcd.io/etcd/api/v3 v3.5.13 // indirect
Expand Down
8 changes: 8 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,12 @@ github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spiffe/go-spiffe/v2 v2.6.0 h1:l+DolpxNWYgruGQVV0xsfeya3CsC7m8iBzDnMpsbLuo=
github.com/spiffe/go-spiffe/v2 v2.6.0/go.mod h1:gm2SeUoMZEtpnzPNs2Csc0D/gX33k1xIx7lEzqblHEs=
github.com/stackitcloud/stackit-sdk-go/core v0.17.3 h1:GsZGmRRc/3GJLmCUnsZswirr5wfLRrwavbnL/renOqg=
github.com/stackitcloud/stackit-sdk-go/core v0.17.3/go.mod h1:HBCXJGPgdRulplDzhrmwC+Dak9B/x0nzNtmOpu+1Ahg=
github.com/stackitcloud/stackit-sdk-go/services/iaas v1.0.0 h1:qLMpd5whPMLnaLEdFQjK51q/o9V6eMFMORBDSsyGyNI=
github.com/stackitcloud/stackit-sdk-go/services/iaas v1.0.0/go.mod h1:854gnLR92NvAbJAA1xZEumrtNh1DoBP1FXTMvhwYA6w=
github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.17.1 h1:r7oaINTwLmIG31AaqKTuQHHFF8YNuYGzi+46DOuSjw4=
github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.17.1/go.mod h1:ipcrPRbwfQXHH18dJVfY7K5ujHF5dTT6isoXgmA7YwQ=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
Expand Down Expand Up @@ -684,6 +690,8 @@ honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 h1:hwvWFiBzdWw1FhfY1FooPn3kzWuJ8tmbZBHi4zVsl1Y=
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
13 changes: 11 additions & 2 deletions kola/harness.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ import (
"strings"
"time"

"github.com/flatcar/mantle/platform/machine/stackit"

"golang.org/x/crypto/ssh/agent"

"github.com/coreos/go-semver/semver"
Expand All @@ -47,6 +49,7 @@ import (
hetznerapi "github.com/flatcar/mantle/platform/api/hetzner"
openstackapi "github.com/flatcar/mantle/platform/api/openstack"
scalewayapi "github.com/flatcar/mantle/platform/api/scaleway"
stackitapi "github.com/flatcar/mantle/platform/api/stackit"
"github.com/flatcar/mantle/platform/conf"
"github.com/flatcar/mantle/platform/machine/akamai"
"github.com/flatcar/mantle/platform/machine/aws"
Expand Down Expand Up @@ -81,6 +84,7 @@ var (
ExternalOptions = external.Options{Options: &Options} // glue to set platform options from main
GCEOptions = gcloudapi.Options{Options: &Options} // glue to set platform options from main
OpenStackOptions = openstackapi.Options{Options: &Options} // glue to set platform options from main
STACKITOptions = stackitapi.Options{Options: &Options} // glue to set platform options from main
QEMUOptions = qemu.Options{Options: &Options} // glue to set platform options from main
ScalewayOptions = scalewayapi.Options{Options: &Options} // glue to set platform options from main
HetznerOptions = hetznerapi.Options{Options: &Options} // glue to set platform options from main
Expand Down Expand Up @@ -262,6 +266,8 @@ func NewFlight(pltfrm string) (flight platform.Flight, err error) {
flight, err = hetzner.NewFlight(&HetznerOptions)
case "openstack":
flight, err = openstack.NewFlight(&OpenStackOptions)
case "stackit":
flight, err = stackit.NewFlight(&STACKITOptions)
case "qemu":
flight, err = qemu.NewFlight(&QEMUOptions)
case "qemu-unpriv":
Expand Down Expand Up @@ -684,10 +690,13 @@ func architecture(pltfrm string) string {
if pltfrm == "hetzner" && HetznerOptions.Board != "" {
nativeArch = boardToArch(HetznerOptions.Board)
}
if pltfrm == "stackit" && STACKITOptions.Board != "" {
nativeArch = boardToArch(STACKITOptions.Board)
}
return nativeArch
}

// returns the arch part of an sdk board name
// returns the arch part of a sdk board name
func boardToArch(board string) string {
return strings.SplitN(board, "-", 2)[0]
}
Expand Down Expand Up @@ -732,7 +741,7 @@ func UploadKolet(c cluster.TestCluster, mArch string) error {
return nil
}
}
return fmt.Errorf("Unable to locate kolet binary for %s", mArch)
return fmt.Errorf("unable to locate kolet binary for %s", mArch)
}

// ScpKolet searches for a kolet binary and copies it to the
Expand Down
3 changes: 1 addition & 2 deletions network/ssh.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import (
"crypto/rand"
"crypto/rsa"
"fmt"
"io/ioutil"
"net"
"os"
"strings"
Expand Down Expand Up @@ -68,7 +67,7 @@ func NewSSHAgent(dialer Dialer) (*SSHAgent, error) {
return nil, err
}

sockDir, err := ioutil.TempDir("", "mantle-ssh-")
sockDir, err := os.MkdirTemp("", "mantle-ssh-")
if err != nil {
return nil, err
}
Expand Down
Loading
Loading