diff --git a/test/images/port-forward-tester/.gitignore b/test/images/port-forward-tester/.gitignore new file mode 100644 index 0000000000..b43a4aae6d --- /dev/null +++ b/test/images/port-forward-tester/.gitignore @@ -0,0 +1 @@ +portforwardtester diff --git a/test/images/port-forward-tester/Dockerfile b/test/images/port-forward-tester/Dockerfile new file mode 100644 index 0000000000..1933d443d3 --- /dev/null +++ b/test/images/port-forward-tester/Dockerfile @@ -0,0 +1,18 @@ +# Copyright 2015 The Kubernetes Authors All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +FROM scratch +ADD portforwardtester portforwardtester +ADD portforwardtester.go portforwardtester.go +ENTRYPOINT ["/portforwardtester"] diff --git a/test/images/port-forward-tester/Makefile b/test/images/port-forward-tester/Makefile new file mode 100644 index 0000000000..be0d3a21eb --- /dev/null +++ b/test/images/port-forward-tester/Makefile @@ -0,0 +1,15 @@ +all: push + +TAG = 1.0 + +portforwardtester: portforwardtester.go + CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -ldflags '-w' ./portforwardtester.go + +image: portforwardtester + docker build -t gcr.io/google_containers/portforwardtester:$(TAG) . + +push: image + gcloud docker push gcr.io/google_containers/portforwardtester:$(TAG) + +clean: + rm -f portforwardtester diff --git a/test/images/port-forward-tester/portforwardtester.go b/test/images/port-forward-tester/portforwardtester.go new file mode 100644 index 0000000000..38f202bf52 --- /dev/null +++ b/test/images/port-forward-tester/portforwardtester.go @@ -0,0 +1,106 @@ +/* +Copyright 2015 The Kubernetes Authors All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// A tiny binary for testing port forwarding. The following environment variables +// control the binary's logic: +// +// BIND_PORT - the TCP port to use for the listener +// EXPECTED_CLIENT_DATA - data that we expect to receive from the client; may be "". +// CHUNKS - how many chunks of data we should send to the client +// CHUNK_SIZE - how large each chunk should be +// CHUNK_INTERVAL - the delay in between sending each chunk +// +// Log messages are written to stdout at various stages of the binary's execution. +// Test code can retrieve this container's log and validate that the expected +// behavior is taking place. +package main + +import ( + "fmt" + "net" + "os" + "strconv" + "strings" + "time" +) + +func getEnvInt(name string) int { + s := os.Getenv(name) + value, err := strconv.Atoi(s) + if err != nil { + fmt.Printf("Error parsing %s %q: %v\n", name, s, err) + os.Exit(1) + } + return value +} + +func main() { + bindPort := os.Getenv("BIND_PORT") + listener, err := net.Listen("tcp", fmt.Sprintf("localhost:%s", bindPort)) + if err != nil { + fmt.Printf("Error listening: %v\n", err) + os.Exit(1) + } + + conn, err := listener.Accept() + if err != nil { + fmt.Printf("Error accepting connection: %v\n", err) + os.Exit(1) + } + defer conn.Close() + fmt.Println("Accepted client connection") + + expectedClientData := os.Getenv("EXPECTED_CLIENT_DATA") + if len(expectedClientData) > 0 { + buf := make([]byte, len(expectedClientData)) + read, err := conn.Read(buf) + if read != len(expectedClientData) { + fmt.Printf("Expected to read %d bytes from client, but got %d instead. err=%v\n", len(expectedClientData), read, err) + os.Exit(2) + } + if expectedClientData != string(buf) { + fmt.Printf("Expect to read %q, but got %q. err=%v\n", expectedClientData, string(buf), err) + os.Exit(3) + } + if err != nil { + fmt.Printf("Read err: %v\n", err) + } + fmt.Println("Received expected client data") + } + + chunks := getEnvInt("CHUNKS") + chunkSize := getEnvInt("CHUNK_SIZE") + chunkInterval := getEnvInt("CHUNK_INTERVAL") + + stringData := strings.Repeat("x", chunkSize) + data := []byte(stringData) + + for i := 0; i < chunks; i++ { + written, err := conn.Write(data) + if written != chunkSize { + fmt.Printf("Expected to write %d bytes from client, but wrote %d instead. err=%v\n", chunkSize, written, err) + os.Exit(4) + } + if err != nil { + fmt.Printf("Write err: %v\n", err) + } + if i+1 < chunks { + time.Sleep(time.Duration(chunkInterval) * time.Millisecond) + } + } + + fmt.Println("Done") +}