add first e2e case

This commit is contained in:
Boshi Lian 2022-07-06 16:46:56 +00:00
parent 9e702013c6
commit 93da136a94
8 changed files with 212 additions and 8 deletions

View file

@ -17,7 +17,14 @@ jobs:
with:
submodules: 'recursive'
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: E2E
run: docker-compose up --build --abort-on-container-exit
working-directory: sshpiperd/e2e
working-directory: e2e
env:
COMPOSE_DOCKER_CLI_BUILD: "1"
DOCKER_BUILDKIT: "1"

View file

@ -37,11 +37,11 @@ jobs:
with:
args: --timeout=10m -E gofmt
- name: Test
- name: Test lib ssh
run: go test -v -race -cover ./...
working-directory: crypto/ssh
- name: Test
- name: Test sshpiper
run: go test -v -race -cover ./...
- name: create release

View file

@ -1,21 +1,20 @@
FROM golang:1.18-stretch as builder
FROM golang:1.18-bullseye as builder
ARG VER=devel
ENV CGO_ENABLED=0
# thanks to https://github.com/montanaflynn/golang-docker-cache
RUN mkdir -p /cache/crypto
COPY crypto /cache/crypto
COPY go.mod go.sum /cache/
WORKDIR /cache
RUN go mod graph | awk '{if ($1 !~ "@") print $2}' | xargs go get
RUN go mod download
RUN mkdir -p /out/plugins
ADD . /src/
WORKDIR /src
RUN go build -o /out -ldflags "-X main.mainver=$VER" ./cmd/...
RUN go build -o /out/plugins -ldflags "-X main.mainver=$VER" ./plugin/...
RUN --mount=type=cache,target=/root/.cache/go-build go build -o /out -ldflags "-X main.mainver=$VER" ./cmd/...
RUN --mount=type=cache,target=/root/.cache/go-build go build -o /out/plugins -ldflags "-X main.mainver=$VER" ./plugin/...
FROM busybox
LABEL maintainer="Boshi Lian<farmer1992@gmail.com>"

11
e2e/Dockerfile_e2e Normal file
View file

@ -0,0 +1,11 @@
FROM golang:1.18-bullseye as builder
ARG VER=devel
ENV CGO_ENABLED=0
RUN mkdir -p /cache/crypto
COPY crypto /cache/crypto
COPY go.mod go.sum /cache/
WORKDIR /cache
RUN go mod download

43
e2e/docker-compose.yml Normal file
View file

@ -0,0 +1,43 @@
version: '3'
services:
host-password:
image: lscr.io/linuxserver/openssh-server:latest
environment:
- PASSWORD_ACCESS=true
- USER_PASSWORD=pass
- USER_NAME=user
volumes:
- shared:/shared
piper-fixed:
environment:
- "SSHPIPERD_LOG_LEVEL=trace"
build: ../
command:
- "/sshpiperd/sshpiperd"
- "/sshpiperd/plugins/fixed"
- "--target"
- "host-password:2222"
depends_on:
- host-password
testrunner:
build:
context: ../
dockerfile: e2e/Dockerfile_e2e
volumes:
- ..:/src
- shared:/shared
command: ["go", "test", "-v"]
working_dir: /src/e2e
depends_on:
- host-password
- piper-fixed
volumes:
shared:
driver_opts:
type: tmpfs
device: tmpfs

141
e2e/e2e_test.go Normal file
View file

@ -0,0 +1,141 @@
// run with docker-compose up --build --abort-on-container-exit
package e2e_test
import (
"bufio"
"bytes"
"fmt"
"io"
"log"
"net"
"os"
"os/exec"
"strings"
"syscall"
"testing"
"time"
"github.com/creack/pty"
"github.com/google/uuid"
)
const waitTimeout = time.Second * 10
func waitForEndpointReady(addr string) {
now := time.Now()
for {
if time.Since(now) > waitTimeout {
log.Panic("timeout waiting for endpoint " + addr)
}
conn, err := net.Dial("tcp", addr)
if err == nil {
log.Printf("endpoint %s is ready", addr)
conn.Close()
break
}
time.Sleep(time.Second)
}
}
func runCmd(cmd string, args ...string) (*exec.Cmd, io.Writer, io.Reader, error) {
c := exec.Command(cmd, args...)
c.SysProcAttr = &syscall.SysProcAttr{Pdeathsig: syscall.SIGTERM}
f, err := pty.Start(c)
if err != nil {
return nil, nil, nil, err
}
var buf bytes.Buffer
r := io.TeeReader(f, &buf)
go io.Copy(os.Stdout, r)
log.Printf("starting %v", c.Args)
go c.Wait()
return c, f, &buf, nil
}
func enterPassword(stdin io.Writer, stdout io.Reader, password string) {
st := time.Now()
for {
scanner := bufio.NewScanner(stdout)
for scanner.Scan() {
line := scanner.Text()
if strings.Contains(line, "'s password") {
stdin.Write([]byte(fmt.Sprintf("%v\n", password)))
log.Printf("got password prompt, sending password")
return
}
}
if time.Since(st) > waitTimeout {
log.Panic("timeout waiting for password prompt")
return
}
}
}
func checkSharedFileContent(t *testing.T, targetfie string, expected string) {
f, err := os.Open(fmt.Sprintf("/shared/%v", targetfie))
if err != nil {
t.Errorf("failed to open shared file, %v", err)
}
defer f.Close()
b, err := io.ReadAll(f)
if err != nil {
t.Errorf("failed to read shared file, %v", err)
}
if string(b) != expected {
t.Errorf("shared file content mismathc, expected %v, got %v", expected, string(b))
}
}
func TestMain(m *testing.M) {
runCmd("ssh", "-V")
for _, ep := range []string{
"host-password:2222",
} {
waitForEndpointReady(ep)
}
os.Exit(m.Run())
}
func TestFixed(t *testing.T) {
waitForEndpointReady("piper-fixed:2222")
randtext := uuid.New().String()
targetfie := uuid.New().String()
c, stdin, stdout, err := runCmd(
"ssh",
"-v",
"-o",
"StrictHostKeyChecking=no",
"-o",
"UserKnownHostsFile=/dev/null",
"-p",
"2222",
"-l",
"user",
"piper-fixed",
fmt.Sprintf(`sh -c "echo -n %v > /shared/%v"`, randtext, targetfie),
)
if err != nil {
t.Errorf("failed to ssh to piper-fixed, %v", err)
}
defer c.Process.Kill()
enterPassword(stdin, stdout, "pass")
time.Sleep(time.Second) // wait for file flush
checkSharedFileContent(t, targetfie, randtext)
}

1
go.mod
View file

@ -7,6 +7,7 @@ replace golang.org/x/crypto => ./crypto
require (
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.0.0
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.0.0
github.com/creack/pty v1.1.18
github.com/google/uuid v1.3.0
github.com/microsoft/kiota-authentication-azure-go v0.2.1
github.com/microsoftgraph/msgraph-sdk-go v0.23.0

2
go.sum
View file

@ -26,6 +26,8 @@ github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWH
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=