Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

kola: add http server #419

Merged
merged 5 commits into from
Mar 16, 2023
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
3 changes: 3 additions & 0 deletions cmd/kola/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@ func init() {
// general options
sv(&outputDir, "output-dir", "", "Temporary output directory for test data and logs")
sv(&kola.TorcxManifestFile, "torcx-manifest", "", "Path to a torcx manifest that should be made available to tests")
sv(&kola.DevcontainerURL, "devcontainer-url", "http://bincache.flatcar-linux.net/images/@ARCH@/@VERSION@", "URL to a dev container archive that should be made available to tests")
sv(&kola.DevcontainerFile, "devcontainer-file", "", "Path to a dev container archive that should be made available to tests as alternative to devcontainer-url, note that a working devcontainer-binhost-url is still needed")
sv(&kola.DevcontainerBinhostURL, "devcontainer-binhost-url", "http://bincache.flatcar-linux.net/boards/@ARCH@-usr/@VERSION@/pkgs", "URL to a binary host that the devcontainer test should use")
root.PersistentFlags().StringVarP(&kolaPlatform, "platform", "p", "qemu", "VM platform: "+strings.Join(kolaPlatforms, ", "))
root.PersistentFlags().StringVarP(&kolaChannel, "channel", "", "stable", "Channel: "+strings.Join(kolaChannels, ", "))
root.PersistentFlags().StringVarP(&kolaOffering, "offering", "", "basic", "Offering: "+strings.Join(kolaOfferings, ", "))
Expand Down
15 changes: 9 additions & 6 deletions kola/harness.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,12 @@ var (
EquinixMetalOptions = equinixmetalapi.Options{Options: &Options} // glue to set platform options from main
QEMUOptions = qemu.Options{Options: &Options} // glue to set platform options from main

TestParallelism int //glue var to set test parallelism from main
TAPFile string // if not "", write TAP results here
TorcxManifestFile string // torcx manifest to expose to tests, if set
TestParallelism int //glue var to set test parallelism from main
TAPFile string // if not "", write TAP results here
TorcxManifestFile string // torcx manifest to expose to tests, if set
DevcontainerURL string // dev container to expose to tests, if set
DevcontainerBinhostURL string // dev container binhost URL to use in the devcontainer test
DevcontainerFile string // dev container path to expose to tests, if set
// TorcxManifest is the unmarshalled torcx manifest file. It is available for
// tests to access via `kola.TorcxManifest`. It will be nil if there was no
// manifest given to kola.
Expand Down Expand Up @@ -625,7 +628,7 @@ func runTest(h *harness.H, t *register.Test, pltfrm string, flight platform.Flig

// drop kolet binary on machines
if t.NativeFuncs != nil {
scpKolet(tcluster, architecture(pltfrm))
ScpKolet(tcluster, architecture(pltfrm))
}

defer func() {
Expand Down Expand Up @@ -676,8 +679,8 @@ func findExecDir() string {
return filepath.Dir(p)
}

// scpKolet searches for a kolet binary and copies it to the machine.
func scpKolet(c cluster.TestCluster, mArch string) {
// ScpKolet searches for a kolet binary and copies it to the machine.
func ScpKolet(c cluster.TestCluster, mArch string) {
for _, d := range []string{
".",
findExecDir(),
Expand Down
68 changes: 60 additions & 8 deletions kola/tests/devcontainer/devcontainer.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,23 @@ import (
"encoding/base64"
"errors"
"fmt"
"os"
"strings"
"text/template"
"time"
"unicode"

"github.com/coreos/go-semver/semver"

"github.com/flatcar/mantle/kola"
"github.com/flatcar/mantle/kola/cluster"
"github.com/flatcar/mantle/kola/register"
"github.com/flatcar/mantle/platform"
"github.com/flatcar/mantle/platform/conf"
"github.com/flatcar/mantle/platform/local"
"github.com/flatcar/mantle/platform/machine/qemu"
"github.com/flatcar/mantle/platform/machine/unprivqemu"
"github.com/flatcar/mantle/util"
)

// Both template parameters may contain @ARCH@ and @VERSION@
Expand All @@ -50,11 +55,6 @@ func trimLeftSpace(contents string) string {
}

var (
defaultScriptTemplateParameters = scriptTemplateParameters{
BinhostURLTemplate: "http://bincache.flatcar-linux.net/boards/@ARCH@-usr/@VERSION@/pkgs",
ImageDirectoryURLTemplate: "http://bincache.flatcar-linux.net/images/@ARCH@/@VERSION@",
}

devContainerScriptTemplate = trimLeftSpace(`
#!/bin/bash

Expand Down Expand Up @@ -215,6 +215,9 @@ func init() {
Platforms: []string{"qemu", "qemu-unpriv"},
Distros: []string{"cl"},
MinVersion: semver.Version{Major: 2592},
NativeFuncs: map[string]func() error{
"Http": Serve,
},
})
register.Register(&register.Test{
Name: "devcontainer.docker",
Expand All @@ -225,18 +228,32 @@ func init() {
Distros: []string{"cl"},
// TODO: Revisit this flag when updating SELinux policies.
Flags: []register.Flag{register.NoEnableSelinux},
NativeFuncs: map[string]func() error{
"Http": Serve,
},
})
}

func withSystemdNspawn(c cluster.TestCluster) {
runDevContainerTest(c, defaultScriptTemplateParameters, systemdNspawnScriptBody)
runDevContainerTest(c, systemdNspawnScriptBody)
}

func withDocker(c cluster.TestCluster) {
runDevContainerTest(c, defaultScriptTemplateParameters, dockerScriptBody)
runDevContainerTest(c, dockerScriptBody)
}

func runDevContainerTest(c cluster.TestCluster, scriptParameters scriptTemplateParameters, scriptBody string) {
func runDevContainerTest(c cluster.TestCluster, scriptBody string) {
devcontainerURL := kola.DevcontainerURL
if kola.DevcontainerFile != "" {
// This URL is deterministic as it runs on the started machine.
devcontainerURL = "http://localhost:8080"
}

scriptParameters := scriptTemplateParameters{
BinhostURLTemplate: kola.DevcontainerBinhostURL,
ImageDirectoryURLTemplate: devcontainerURL,
}

userdata, err := prepareUserData(scriptParameters, scriptBody)
if err != nil {
c.Fatalf("preparing user data failed: %v", err)
Expand All @@ -245,6 +262,11 @@ func runDevContainerTest(c cluster.TestCluster, scriptParameters scriptTemplateP
if err != nil {
c.Fatalf("creating a machine failed: %v", err)
}

if kola.DevcontainerFile != "" {
configureHTTPServer(c, machine)
}

if _, err := c.SSH(machine, "/home/core/main-script"); err != nil {
c.Fatalf("main script failed: %v", err)
}
Expand Down Expand Up @@ -297,3 +319,33 @@ func newMachineWithLargeDisk(c cluster.TestCluster, userData *conf.UserData) (pl
}
return nil, errors.New("unknown cluster type, this test should only be running on qemu or qemu-unpriv platforms")
}

func Serve() error {
httpServer := local.SimpleHTTP{}
return httpServer.Serve()
}

func configureHTTPServer(c cluster.TestCluster, srv platform.Machine) {
// manually copy Kolet on the host, as the initial size cluster is 0.
kola.ScpKolet(c, strings.SplitN(kola.QEMUOptions.Board, "-", 2)[0])

in, err := os.Open(kola.DevcontainerFile)
if err != nil {
c.Fatalf("opening dev container file: %v", err)
}

defer in.Close()

if err := platform.InstallFile(in, srv, "/var/www/flatcar_developer_container.bin.bz2"); err != nil {
c.Fatalf("copying dev container to HTTP server: %v", err)
}

c.MustSSH(srv, fmt.Sprintf("sudo systemd-run --quiet ./kolet run %s Http", c.H.Name()))

if err := util.WaitUntilReady(60*time.Second, 5*time.Second, func() (bool, error) {
_, _, err := srv.SSH(fmt.Sprintf("curl %s:8080", srv.PrivateIP()))
return err == nil, nil
}); err != nil {
c.Fatal("timed out waiting for http server to become active")
}
}
15 changes: 15 additions & 0 deletions platform/local/http.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Copyright The Mantle Authors
// SPDX-License-Identifier: Apache-2.0

package local

import (
"net/http"
)

// SimpleHTTP provides a single http server.
type SimpleHTTP struct{}

func (s *SimpleHTTP) Serve() error {
return http.ListenAndServe(":8080", http.FileServer(http.Dir("/var/www")))
}