mirror of
https://github.com/mulgadc/spinifex.git
synced 2026-10-23 12:47:48 +00:00
c9a4e904a8
Add baseline tests that confirm two fresh-install regressions the existing
suite masks (it authorizes tcp/22 on the default SG before every SSH probe):
- default SG default-deny gates external reach of instances in the
default subnet (SG, not routing)
- a newly-created public subnet never gets its OVN IGW egress LRP, so it
has no route to the VPC IGW despite MapPublicIpOnLaunch
Plus a positive test: instances sharing the default SG can communicate via
ICMP (same-host single-node, cross-host multinode).
Single-node baselines run after TestClusterStatsCLI (0-VM gate); multinode
after TestMultinodePreflight (fixture init). Instances are self-cleaning so
they don't perturb the singleton-VM ordering.
Remove the qemu hostfwd SSH fallback from the harness (InstancePublicSSHHost,
GuestSSHEndpoint) - it bypasses the OVN datapath and masks these regressions.
Endpoints now t.Fatal when no public IP is assigned.
73 lines
2.3 KiB
Go
73 lines
2.3 KiB
Go
//go:build e2e
|
|
|
|
package harness
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os/exec"
|
|
"strconv"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/aws/aws-sdk-go/aws"
|
|
)
|
|
|
|
// GuestSSHEndpoint resolves (host, 22) for SSH-ing into a guest VM via its
|
|
// public IP.
|
|
//
|
|
// There is deliberately NO qemu-hostfwd fallback (see InstancePublicSSHHost):
|
|
// hostfwd bypasses the OVN datapath, so reaching a guest through it would mask
|
|
// the networking regressions these tests exist to catch. A running instance
|
|
// with no public IP is a hard failure.
|
|
func GuestSSHEndpoint(t *testing.T, c *AWSClient, cluster *Cluster, instanceID string, opts ...PollOpt) (host string, port int) {
|
|
t.Helper()
|
|
_ = cluster // retained for signature stability; node hostfwd lookup removed
|
|
inst := WaitForInstanceState(t, c, instanceID, "running", opts...)
|
|
pub := aws.StringValue(inst.PublicIpAddress)
|
|
if pub == "" {
|
|
t.Fatalf("GuestSSHEndpoint: instance %s has no public IP; "+
|
|
"qemu-hostfwd fallback is disabled (it bypasses the OVN datapath)", instanceID)
|
|
}
|
|
return pub, 22
|
|
}
|
|
|
|
// GuestSSHReady polls SSH into the named instance until a probe command
|
|
// succeeds. Pemfile is the test-scoped private key written by EnsureKeyPair;
|
|
// user defaults to ec2-user (the cloud-init account that spinifex injects
|
|
// regardless of distro family — see handlers/ec2/instance/service_impl.go).
|
|
func GuestSSHReady(t *testing.T, host string, port int, user, pemfile string, opts ...PollOpt) {
|
|
t.Helper()
|
|
cfg := applyOpts(pollCfg{timeout: 60 * time.Second, interval: 1 * time.Second}, opts...)
|
|
target := fmt.Sprintf("%s@%s", user, host)
|
|
|
|
EventuallyErr(t, func() error {
|
|
ctx, cancel := context.WithTimeout(context.Background(), cfg.interval+2*time.Second)
|
|
defer cancel()
|
|
args := []string{
|
|
"-i", pemfile,
|
|
"-p", strconv.Itoa(port),
|
|
"-o", "StrictHostKeyChecking=no",
|
|
"-o", "UserKnownHostsFile=/dev/null",
|
|
"-o", "ConnectTimeout=2",
|
|
"-o", "BatchMode=yes",
|
|
"-o", "LogLevel=ERROR",
|
|
target,
|
|
"echo ready",
|
|
}
|
|
if err := runSSH(ctx, args); err != nil {
|
|
return fmt.Errorf("ssh %s:%d: %w", host, port, err)
|
|
}
|
|
return nil
|
|
}, cfg.timeout, cfg.interval)
|
|
}
|
|
|
|
func runSSH(ctx context.Context, args []string) error {
|
|
out, err := exec.CommandContext(ctx, "ssh", args...).CombinedOutput()
|
|
if err != nil {
|
|
return fmt.Errorf("%w: %s", err, strings.TrimSpace(string(out)))
|
|
}
|
|
return nil
|
|
}
|