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
3 changes: 3 additions & 0 deletions .github/workflows/e2e.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ jobs:
- TestMultiNodeInstallation
- TestSingleNodeInstallation
- TestTokenBasedMultiNodeInstallation
- TestSingleNodeInstallationRockyLinux8
- TestSingleNodeInstallationDebian12
- TestSingleNodeInstallationCentos8Stream
steps:
- name: Move Docker aside
run: |
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ e2e-test: helmvm-linux-amd64
mkdir -p output/tmp
rm -rf output/tmp/id_rsa*
ssh-keygen -t rsa -N "" -C "Integration Test Key" -f output/tmp/id_rsa
go test -timeout 10m -v ./e2e -run $(TEST_NAME)
go test -timeout 10m -v ./e2e -run $(TEST_NAME)$

.PHONY: create-e2e-workflows
create-e2e-workflows:
Expand Down
68 changes: 50 additions & 18 deletions e2e/cluster/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,15 @@ lxc.cap.drop=
lxc.cgroup.devices.allow=a
lxc.mount.auto=proc:rw sys:rw
lxc.mount.entry = /dev/kmsg dev/kmsg none defaults,bind,create=file`
const checkInternet = `#!/bin/bash
timeout 5 bash -c 'cat < /dev/null > /dev/tcp/www.replicated.com/80'
if [ $? == 0 ]; then
echo "Internet connectivity is up"
exit 0
fi
echo "Internet connectivity is down"
exit 1
`

func init() {
networkaddr = make(chan string, 255)
Expand Down Expand Up @@ -214,20 +223,28 @@ func CopyFilesToNode(in *Input, node string) {
})
}
for _, file := range files {
fp, err := os.Open(file.SourcePath)
if err != nil {
in.T.Fatalf("Failed to open file %s: %v", file.SourcePath, err)
}
defer fp.Close()
req = lxd.ContainerFileArgs{
Content: fp,
Mode: file.Mode,
Type: "file",
}
err = client.CreateContainerFile(node, file.DestPath, req)
if err != nil {
in.T.Fatalf("Failed to copy file %s: %v", file.SourcePath, err)
}
CopyFileToNode(in, node, file)
}
}

// CopyFileToNode copies a single file to a node.
func CopyFileToNode(in *Input, node string, file File) {
client, err := lxd.ConnectLXDUnix(lxdSocket, nil)
if err != nil {
in.T.Fatalf("Failed to connect to LXD: %v", err)
}
fp, err := os.Open(file.SourcePath)
if err != nil {
in.T.Fatalf("Failed to open file %s: %v", file.SourcePath, err)
}
defer fp.Close()
req := lxd.ContainerFileArgs{
Content: fp,
Mode: file.Mode,
Type: "file",
}
if err := client.CreateContainerFile(node, file.DestPath, req); err != nil {
in.T.Fatalf("Failed to copy file %s: %v", file.SourcePath, err)
}
}

Expand All @@ -247,13 +264,28 @@ func CreateNodes(in *Input) []string {
// pinging google.com.
func NodeHasInternet(in *Input, node string) {
in.T.Logf("Testing if node %s can reach the internet", node)
fp, err := os.CreateTemp("/tmp", "internet-XXXXX.sh")
if err != nil {
in.T.Fatalf("Failed to create temporary file: %v", err)
}
fp.Close()
defer func() {
os.RemoveAll(fp.Name())
}()
if err := os.WriteFile(fp.Name(), []byte(checkInternet), 0755); err != nil {
in.T.Fatalf("Failed to write script: %v", err)
}
file := File{
SourcePath: fp.Name(),
DestPath: "/usr/local/bin/check_internet.sh",
Mode: 0755,
}
CopyFileToNode(in, node, file)
cmd := Command{
Node: node,
Stdout: os.Stdout,
Stderr: os.Stderr,
Line: []string{
"nc", "-w", "2", "-zv", "www.replicated.com", "80",
},
Line: []string{"/usr/local/bin/check_internet.sh"},
}
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
Expand Down Expand Up @@ -317,7 +349,7 @@ func CreateNode(in *Input, i int) string {
state := &api.InstanceState{}
for state.Status != "Running" {
time.Sleep(5 * time.Second)
in.T.Logf("Waiting for node %s to run", name)
in.T.Logf("Waiting for node %s to start (running)", name)
if state, _, err = client.GetInstanceState(name); err != nil {
in.T.Fatalf("Failed to get node state %s: %v", name, err)
}
Expand Down
77 changes: 77 additions & 0 deletions e2e/install_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,3 +96,80 @@ func TestMultiNodeInstallation(t *testing.T) {
t.Fatalf("fail to install helmvm from node 00: %v", err)
}
}

func TestSingleNodeInstallationRockyLinux8(t *testing.T) {
t.Parallel()
tc := cluster.NewTestCluster(&cluster.Input{
T: t,
Nodes: 1,
Image: "rockylinux/8",
SSHPublicKey: "../output/tmp/id_rsa.pub",
SSHPrivateKey: "../output/tmp/id_rsa",
HelmVMPath: "../output/bin/helmvm",
})
defer tc.Destroy()
t.Log("installing ssh on node 0")
commands := [][]string{
{"dnf", "install", "-y", "openssh-server"},
{"systemctl", "enable", "sshd"},
{"systemctl", "start", "sshd"},
}
if err := RunCommandsOnNode(t, tc, 0, commands); err != nil {
t.Fatalf("fail to install ssh on node %s: %v", tc.Nodes[0], err)
}
t.Log("installing helmvm on node 0")
line := []string{"single-node-install.sh"}
if _, _, err := RunCommandOnNode(t, tc, 0, line); err != nil {
t.Fatalf("fail to install helmvm on node %s: %v", tc.Nodes[0], err)
}
}

func TestSingleNodeInstallationDebian12(t *testing.T) {
t.Parallel()
tc := cluster.NewTestCluster(&cluster.Input{
T: t,
Nodes: 1,
Image: "debian/12",
SSHPublicKey: "../output/tmp/id_rsa.pub",
SSHPrivateKey: "../output/tmp/id_rsa",
HelmVMPath: "../output/bin/helmvm",
})
defer tc.Destroy()
t.Log("installing ssh on node 0")
line := []string{"apt", "install", "openssh-server", "-y"}
if _, _, err := RunCommandOnNode(t, tc, 0, line); err != nil {
t.Fatalf("fail to install ssh on node 0: %v", err)
}
t.Log("installing helmvm on node 0")
line = []string{"single-node-install.sh"}
if _, _, err := RunCommandOnNode(t, tc, 0, line); err != nil {
t.Fatalf("fail to install helmvm on node %s: %v", tc.Nodes[0], err)
}
}

func TestSingleNodeInstallationCentos8Stream(t *testing.T) {
t.Parallel()
tc := cluster.NewTestCluster(&cluster.Input{
T: t,
Nodes: 1,
Image: "centos/8-Stream",
SSHPublicKey: "../output/tmp/id_rsa.pub",
SSHPrivateKey: "../output/tmp/id_rsa",
HelmVMPath: "../output/bin/helmvm",
})
defer tc.Destroy()
t.Log("installing ssh on node 0")
commands := [][]string{
{"dnf", "install", "-y", "openssh-server"},
{"systemctl", "enable", "sshd"},
{"systemctl", "start", "sshd"},
}
if err := RunCommandsOnNode(t, tc, 0, commands); err != nil {
t.Fatalf("fail to install ssh on node %s: %v", tc.Nodes[0], err)
}
t.Log("installing helmvm on node 0")
line := []string{"single-node-install.sh"}
if _, _, err := RunCommandOnNode(t, tc, 0, line); err != nil {
t.Fatalf("fail to install helmvm on node %s: %v", tc.Nodes[0], err)
}
}
12 changes: 12 additions & 0 deletions e2e/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package e2e
import (
"bytes"
"context"
"strings"
"testing"
"time"

Expand All @@ -17,6 +18,17 @@ func (b *buffer) Close() error {
return nil
}

func RunCommandsOnNode(t *testing.T, cl *cluster.Output, node int, cmds [][]string) error {
for _, cmd := range cmds {
cmdstr := strings.Join(cmd, " ")
t.Logf("running `%s` node %d", cmdstr, node)
if _, _, err := RunCommandOnNode(t, cl, node, cmd); err != nil {
return err
}
}
return nil
}

func RunCommandOnNode(t *testing.T, cl *cluster.Output, node int, line []string) (string, string, error) {
stdout := &buffer{bytes.NewBuffer(nil)}
stderr := &buffer{bytes.NewBuffer(nil)}
Expand Down