Add glide.yaml and vendor deps

This commit is contained in:
Dalton Hubble 2016-12-03 22:43:32 -08:00
parent db918f12ad
commit 5b3d5e81bd
18880 changed files with 5166045 additions and 1 deletions

8
vendor/k8s.io/kubernetes/test/images/BUILD generated vendored Normal file
View file

@ -0,0 +1,8 @@
package(default_visibility = ["//visibility:public"])
filegroup(
name = "sources",
srcs = glob([
"**/*",
]),
)

View file

@ -0,0 +1,24 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_binary",
"go_library",
"go_test",
"cgo_library",
)
go_binary(
name = "clusterapi-tester",
srcs = ["main.go"],
tags = ["automanaged"],
deps = [
"//pkg/api:go_default_library",
"//pkg/client/clientset_generated/internalclientset:go_default_library",
"//pkg/client/restclient:go_default_library",
"//pkg/fields:go_default_library",
"//pkg/labels:go_default_library",
],
)

View file

@ -0,0 +1,18 @@
# Copyright 2016 The Kubernetes Authors.
#
# 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 busybox
MAINTAINER Prashanth B <beeps@google.com>
ADD main main
ENTRYPOINT ["/main"]

View file

@ -0,0 +1,31 @@
# Copyright 2016 The Kubernetes Authors.
#
# 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.
all: push
# 0.0 shouldn't clobber any released builds
TAG = 1.0
PREFIX = gcr.io/google_containers/clusterapi-tester
main: main.go
CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -ldflags '-w' -o main ./main.go
container: main
docker build -t $(PREFIX):$(TAG) .
push: container
gcloud docker -- push $(PREFIX):$(TAG)
clean:
rm -f main

View file

@ -0,0 +1,66 @@
/*
Copyright 2014 The Kubernetes Authors.
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 simple pod that first lists all nodes/services through the Kubernetes
// api, then serves a 200 on /healthz.
package main
import (
"log"
"fmt"
"net/http"
"k8s.io/kubernetes/pkg/api"
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
"k8s.io/kubernetes/pkg/client/restclient"
"k8s.io/kubernetes/pkg/fields"
"k8s.io/kubernetes/pkg/labels"
)
func main() {
cc, err := restclient.InClusterConfig()
if err != nil {
log.Fatalf("Failed to create client: %v", err)
}
kubeClient, err := clientset.NewForConfig(cc)
if err != nil {
log.Fatalf("Failed to create client: %v", err)
}
listAll := api.ListOptions{LabelSelector: labels.Everything(), FieldSelector: fields.Everything()}
nodes, err := kubeClient.Core().Nodes().List(listAll)
if err != nil {
log.Fatalf("Failed to list nodes: %v", err)
}
log.Printf("Nodes:")
for _, node := range nodes.Items {
log.Printf("\t%v", node.Name)
}
services, err := kubeClient.Core().Services(api.NamespaceDefault).List(listAll)
if err != nil {
log.Fatalf("Failed to list services: %v", err)
}
log.Printf("Services:")
for _, svc := range services.Items {
log.Printf("\t%v", svc.Name)
}
log.Printf("Success")
http.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Ok")
})
log.Fatal(http.ListenAndServe(":8080", nil))
}

View file

@ -0,0 +1,19 @@
apiVersion: v1
kind: Pod
metadata:
name: clusterapi-tester
spec:
containers:
- image: gcr.io/google_containers/clusterapi-tester:1.0
name: clusterapi-tester
readinessProbe:
httpGet:
path: /healthz
port: 8080
scheme: HTTP
initialDelaySeconds: 10
timeoutSeconds: 5
failureThreshold: 3
periodSeconds: 10
successThreshold: 1
restartPolicy: OnFailure

View file

@ -0,0 +1,19 @@
# Copyright 2016 The Kubernetes Authors.
#
# 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 alpine
MAINTAINER Bowei Du "bowei@google.com"
RUN apk update --no-cache
RUN apk add bind-tools

27
vendor/k8s.io/kubernetes/test/images/dnsutils/Makefile generated vendored Normal file
View file

@ -0,0 +1,27 @@
# Copyright 2016 The Kubernetes Authors.
#
# 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.
# This image does not tag
TAG ?=
PREFIX ?= gcr.io/google_containers
all: push
image:
docker build -t $(PREFIX)/dnsutils .
push: image
gcloud docker -- push $(PREFIX)/dnsutils
clean:

View file

@ -0,0 +1,17 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_binary",
"go_library",
"go_test",
"cgo_library",
)
go_binary(
name = "entrypoint-tester",
srcs = ["ep.go"],
tags = ["automanaged"],
)

View file

@ -0,0 +1,20 @@
# Copyright 2016 The Kubernetes Authors.
#
# 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 ep ep
ADD ep ep-2
EXPOSE 8080
ENTRYPOINT ["/ep"]
CMD ["default", "arguments"]

View file

@ -0,0 +1,30 @@
# Copyright 2016 The Kubernetes Authors.
#
# 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.
TAG = 0.1
PREFIX = kubernetes
all: push
ep: ep.go
CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -ldflags '-w' ./ep.go
image: ep
sudo docker build -t $(PREFIX)/eptest:$(TAG) .
push: image
sudo docker push $(PREFIX)/eptest:$(TAG)
clean:
rm -f ep

View file

@ -0,0 +1,29 @@
/*
Copyright 2015 The Kubernetes Authors.
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.
*/
package main
import (
"fmt"
"os"
)
// This program prints the arguments it's passed and exits.
func main() {
args := os.Args
fmt.Printf("%v\n", args)
os.Exit(0)
}

View file

@ -0,0 +1,17 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_binary",
"go_library",
"go_test",
"cgo_library",
)
go_binary(
name = "fakegitserver",
srcs = ["gitserver.go"],
tags = ["automanaged"],
)

View file

@ -0,0 +1,18 @@
# Copyright 2016 The Kubernetes Authors.
#
# 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 GITHASH.txt /
ADD gitserver /
ENTRYPOINT ["/gitserver"]

View file

@ -0,0 +1,32 @@
# Copyright 2016 The Kubernetes Authors.
#
# 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.
.PHONY: all image push clean
TAG = 0.1
PREFIX = gcr.io/google_containers
IMAGE = fakegitserver
ARCH = amd64
image:
./prepare.sh $(ARCH)
docker build -t $(PREFIX)/$(IMAGE):$(TAG) .
push: image
gcloud docker -- push $(PREFIX)/$(IMAGE):$(TAG)
all: push
clean:
rm -f gitserver GITHASH.txt

View file

@ -0,0 +1,34 @@
/*
Copyright 2016 The Kubernetes Authors.
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.
*/
package main
import (
"io"
"net/http"
)
func hello(w http.ResponseWriter, r *http.Request) {
io.WriteString(w, "I am a fake git server")
}
// When doing `git clone localhost:8000`, you will clone an empty git repo named "8000" on local.
// You can also use `git clone localhost:8000 my-repo-name` to rename that repo.
func main() {
http.HandleFunc("/", hello)
http.ListenAndServe(":8000", nil)
}

View file

@ -0,0 +1,26 @@
#!/bin/bash
# Copyright 2016 The Kubernetes Authors.
#
# 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.
set -e
set -x
ARCH=$1
# Build the binary.
CGO_ENABLED=0 GOOS=linux GOARCH=${ARCH} go build -a -installsuffix cgo -ldflags '-w' ./gitserver.go
# Write down the current commit hash.
echo $(git rev-parse HEAD) >> GITHASH.txt

View file

@ -0,0 +1 @@
goproxy

18
vendor/k8s.io/kubernetes/test/images/goproxy/BUILD generated vendored Normal file
View file

@ -0,0 +1,18 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_binary",
"go_library",
"go_test",
"cgo_library",
)
go_binary(
name = "goproxy",
srcs = ["goproxy.go"],
tags = ["automanaged"],
deps = ["//vendor:github.com/elazarl/goproxy"],
)

View file

@ -0,0 +1,18 @@
# Copyright 2016 The Kubernetes Authors.
#
# 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 goproxy goproxy
EXPOSE 8080
ENTRYPOINT ["/goproxy"]

30
vendor/k8s.io/kubernetes/test/images/goproxy/Makefile generated vendored Normal file
View file

@ -0,0 +1,30 @@
# Copyright 2016 The Kubernetes Authors.
#
# 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.
TAG = 0.1
PREFIX = gcr.io/google_containers
all: push
goproxy: goproxy.go
CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -ldflags '-w' ./goproxy.go
image: goproxy
docker build -t $(PREFIX)/goproxy:$(TAG) .
push: image
gcloud docker -- push $(PREFIX)/goproxy:$(TAG)
clean:
rm -f goproxy

View file

@ -0,0 +1,30 @@
/*
Copyright 2015 The Kubernetes Authors.
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.
*/
package main
import (
"log"
"net/http"
"github.com/elazarl/goproxy"
)
func main() {
proxy := goproxy.NewProxyHttpServer()
proxy.Verbose = true
log.Fatal(http.ListenAndServe(":8080", proxy))
}

16
vendor/k8s.io/kubernetes/test/images/goproxy/pod.yaml generated vendored Normal file
View file

@ -0,0 +1,16 @@
apiVersion: v1
kind: Pod
metadata:
name: goproxy
labels:
app: goproxy
spec:
containers:
- name: goproxy
image: gcr.io/google_containers/goproxy:0.1
ports:
- containerPort: 8080
readinessProbe:
tcpSocket:
port: 8080

View file

@ -0,0 +1,23 @@
# Copyright 2016 The Kubernetes Authors.
#
# 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 alpine:3.2
# install necessary packages:
# - curl, nc: used by a lot of e2e tests
# - iproute2: includes ss used in NodePort tests
run apk --update add curl netcat-openbsd iproute2 && rm -rf /var/cache/apk/*
# wait forever
CMD rm -f /fifo && mkfifo /fifo && exec cat </fifo

30
vendor/k8s.io/kubernetes/test/images/hostexec/Makefile generated vendored Normal file
View file

@ -0,0 +1,30 @@
# Copyright 2016 The Kubernetes Authors.
#
# 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.
.PHONY: all image push clean
TAG = 1.2
PREFIX = gcr.io/google_containers
all: push
image:
docker build -t $(PREFIX)/hostexec:$(TAG) .
push: image
gcloud docker -- push $(PREFIX)/hostexec:$(TAG)
clean:
rm -f hostexec

12
vendor/k8s.io/kubernetes/test/images/hostexec/pod.yaml generated vendored Normal file
View file

@ -0,0 +1,12 @@
apiVersion: v1
kind: Pod
metadata:
name: hostexec
labels:
app: hostexec
spec:
containers:
- name: hostexec
image: gcr.io/google_containers/hostexec:1.2
securityContext:
hostNetwork: true

21
vendor/k8s.io/kubernetes/test/images/iperf/Dockerfile generated vendored Normal file
View file

@ -0,0 +1,21 @@
# Copyright 2016 The Kubernetes Authors.
#
# 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 gcr.io/google_containers/ubuntu-slim:0.2
MAINTAINER jay@apache.org
RUN apt-get update && apt-get install -y --no-install-recommends iperf bash \
&& apt-get clean -y \
&& rm -rf /var/lib/apt/lists/* \
&& ln -s /usr/bin/iperf /usr/local/bin/iperf
RUN ls -altrh /usr/local/bin/iperf

31
vendor/k8s.io/kubernetes/test/images/iperf/Makefile generated vendored Normal file
View file

@ -0,0 +1,31 @@
# Copyright 2016 The Kubernetes Authors.
#
# 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.
TAG = e2e
PREFIX = gcr.io/google_containers
IMAGE = iperf
all: push
container: image
image:
docker build -t $(PREFIX)/${IMAGE} . # Build new image and automatically tag it as latest
docker tag $(PREFIX)/${IMAGE} $(PREFIX)/${IMAGE}:$(TAG) # Add the version tag to the latest image
push: image
gcloud docker -- push $(PREFIX)/${IMAGE} # Push image tagged as latest to repository
gcloud docker -- push $(PREFIX)/${IMAGE}:$(TAG) # Push version tagged image to repository (since this image is already pushed it will simply create or update version tag)
clean:

8
vendor/k8s.io/kubernetes/test/images/iperf/README.md generated vendored Normal file
View file

@ -0,0 +1,8 @@
This is a dockerfile which we curate inside of kubernetes for running iperf as a service.
Eventually we would like to update it to iperf3.
Possibly we might even start using a pure go based iperf and maintain the same cmd line abstraction.
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/test/images/iperf/README.md?pixel)]()

View file

@ -0,0 +1,20 @@
# Copyright 2016 The Kubernetes Authors.
#
# 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 debian:jessie
MAINTAINER Abhishek Shah "abshah@google.com"
RUN apt-get -q update && \
apt-get install -y dnsutils && \
apt-get clean

View file

@ -0,0 +1,27 @@
# Copyright 2016 The Kubernetes Authors.
#
# 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.
# This image does not tag
#TAG =
PREFIX = gcr.io/google_containers
all: push
image:
docker build -t $(PREFIX)/jessie-dnsutils .
push: image
gcloud docker -- push $(PREFIX)/jessie-dnsutils
clean:

View file

@ -0,0 +1,21 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_binary",
"go_library",
"go_test",
"cgo_library",
)
go_binary(
name = "logs-generator",
srcs = ["logs_generator.go"],
tags = ["automanaged"],
deps = [
"//pkg/util/rand:go_default_library",
"//vendor:github.com/golang/glog",
],
)

View file

@ -0,0 +1,23 @@
# Copyright 2016 The Kubernetes Authors.
#
# 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 gcr.io/google_containers/ubuntu-slim:0.4
MAINTAINER Mik Vyatskov <vmik@google.com>
COPY logs-generator /
CMD /logs-generator --logtostderr \
--log-lines-total=${LOGS_GENERATOR_LINES_TOTAL} \
--run-duration=${LOGS_GENERATOR_DURATION}

View file

@ -0,0 +1,32 @@
# Copyright 2016 The Kubernetes Authors.
#
# 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.
TAG = v0.1.0
PREFIX = gcr.io/google_containers
all: build
build: binary container
binary:
go build -a --ldflags '-w' -o logs-generator .
container:
docker build -t $(PREFIX)/logs-generator:$(TAG) .
push:
gcloud docker -- push $(PREFIX)/logs-generator:$(TAG)
clean:
rm -f logs-generator

View file

@ -0,0 +1,57 @@
# Logs Generator
## Overview
Logs generator is a tool to create predictable load on the logs delivery system.
Is generates random lines with predictable format and predictable average length.
Each line can be later uniquely identified to ensure logs delivery.
## Usage
Tool is parametrized with the total number of number that should be generated and the duration of
the generation process. For example, if you want to create a throughput of 100 lines per second
for a minute, you set total number of lines to 6000 and duration to 1 minute.
Parameters are passed through environment variables. There are no defaults, you should always
set up container parameters. Total number of line is parametrized through env variable
`LOGS_GENERATOR_LINES_TOTAL` and duration in go format is parametrized through env variable
`LOGS_GENERATOR_DURATION`.
Inside the container all log lines are written to the stdout.
Each line is on average 100 bytes long and follows this pattern:
```
2000-12-31T12:59:59Z <id> <method> /api/v1/namespaces/<namespace>/endpoints/<random_string> <random_number>
```
Where `<id>` refers to the number from 0 to `total_lines - 1`, which is unique for each
line in a given run of the container.
## Image
Image is located in the public repository of Google Container Registry under the name
```
gcr.io/google_containers/logs-generator:v0.1.0
```
## Examples
```
docker run -i \
-e "LOGS_GENERATOR_LINES_TOTAL=10" \
-e "LOGS_GENERATOR_DURATION=1s" \
gcr.io/google_containers/logs-generator:v0.1.0
```
```
kubectl run logs-generator \
--generator=run-pod/v1 \
--image=gcr.io/google_containers/logs-generator:v0.1.0 \
--restart=Never \
--env "LOGS_GENERATOR_LINES_TOTAL=1000" \
--env "LOGS_GENERATOR_DURATION=1m"
```
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/test/images/logs-generator/README.md?pixel)]()

View file

@ -0,0 +1,82 @@
/*
Copyright 2016 The Kubernetes Authors.
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.
*/
package main
import (
"flag"
"fmt"
"time"
"github.com/golang/glog"
"k8s.io/kubernetes/pkg/util/rand"
)
var (
httpMethods = []string{
"GET",
"POST",
"PUT",
}
namespaces = []string{
"kube-system",
"default",
"ns",
}
)
var (
linesTotal = flag.Int("log-lines-total", 0, "Total lines that should be generated by the end of the run")
duration = flag.Duration("run-duration", 0, "Total duration of the run")
)
func main() {
flag.Parse()
if *linesTotal <= 0 {
glog.Fatalf("Invalid total number of lines: %d", *linesTotal)
}
if *duration <= 0 {
glog.Fatalf("Invalid duration: %v", *duration)
}
generateLogs(*linesTotal, *duration)
}
// Outputs linesTotal lines of logs to stdout uniformly for duration
func generateLogs(linesTotal int, duration time.Duration) {
delay := duration / time.Duration(linesTotal)
rand.Seed(time.Now().UnixNano())
tick := time.Tick(delay)
for id := 0; id < linesTotal; id++ {
glog.Info(generateLogLine(id))
<-tick
}
}
// Generates apiserver-like line with average length of 100 symbols
func generateLogLine(id int) string {
method := httpMethods[rand.Intn(len(httpMethods))]
namespace := namespaces[rand.Intn(len(namespaces))]
podName := rand.String(rand.IntnRange(3, 5))
url := fmt.Sprintf("/api/v1/namespaces/%s/pods/%s", namespace, podName)
status := rand.IntnRange(200, 600)
return fmt.Sprintf("%d %s %s %d", id, method, url, status)
}

View file

@ -0,0 +1,16 @@
# Copyright 2016 The Kubernetes Authors.
#
# 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 gcr.io/google_containers/mounttest:0.7
USER 1001

View file

@ -0,0 +1,26 @@
# Copyright 2016 The Kubernetes Authors.
#
# 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.
TAG = 0.4
PREFIX = gcr.io/google_containers
all: push
image:
sudo docker build -t $(PREFIX)/mounttest-user:$(TAG) .
push: image
gcloud docker -- push $(PREFIX)/mounttest-user:$(TAG)
clean:

View file

@ -0,0 +1,17 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_binary",
"go_library",
"go_test",
"cgo_library",
)
go_binary(
name = "mount-tester",
srcs = ["mt.go"],
tags = ["automanaged"],
)

View file

@ -0,0 +1,17 @@
# Copyright 2016 The Kubernetes Authors.
#
# 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 mt mt
ENTRYPOINT ["/mt"]

View file

@ -0,0 +1,30 @@
# Copyright 2016 The Kubernetes Authors.
#
# 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.
TAG = 0.7
PREFIX = gcr.io/google_containers
all: push
mt: mt.go
CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -ldflags '-w' ./mt.go
image: mt
sudo docker build -t $(PREFIX)/mounttest:$(TAG) .
push: image
gcloud docker -- push $(PREFIX)/mounttest:$(TAG)
clean:
rm -f mt

268
vendor/k8s.io/kubernetes/test/images/mount-tester/mt.go generated vendored Normal file
View file

@ -0,0 +1,268 @@
/*
Copyright 2015 The Kubernetes Authors.
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.
*/
package main
import (
"flag"
"fmt"
"io/ioutil"
"os"
"syscall"
"time"
)
var (
fsTypePath = ""
fileModePath = ""
filePermPath = ""
fileOwnerPath = ""
newFilePath0644 = ""
newFilePath0666 = ""
newFilePath0660 = ""
newFilePath0777 = ""
readFileContentPath = ""
readFileContentInLoopPath = ""
retryDuration = 180
breakOnExpectedContent = true
)
func init() {
flag.StringVar(&fsTypePath, "fs_type", "", "Path to print the fs type for")
flag.StringVar(&fileModePath, "file_mode", "", "Path to print the mode bits of")
flag.StringVar(&filePermPath, "file_perm", "", "Path to print the perms of")
flag.StringVar(&fileOwnerPath, "file_owner", "", "Path to print the owning UID and GID of")
flag.StringVar(&newFilePath0644, "new_file_0644", "", "Path to write to and read from with perm 0644")
flag.StringVar(&newFilePath0666, "new_file_0666", "", "Path to write to and read from with perm 0666")
flag.StringVar(&newFilePath0660, "new_file_0660", "", "Path to write to and read from with perm 0660")
flag.StringVar(&newFilePath0777, "new_file_0777", "", "Path to write to and read from with perm 0777")
flag.StringVar(&readFileContentPath, "file_content", "", "Path to read the file content from")
flag.StringVar(&readFileContentInLoopPath, "file_content_in_loop", "", "Path to read the file content in loop from")
flag.IntVar(&retryDuration, "retry_time", 180, "Retry time during the loop")
flag.BoolVar(&breakOnExpectedContent, "break_on_expected_content", true, "Break out of loop on expected content, (use with --file_content_in_loop flag only)")
}
// This program performs some tests on the filesystem as dictated by the
// flags passed by the user.
func main() {
flag.Parse()
var (
err error
errs = []error{}
)
// Clear the umask so we can set any mode bits we want.
syscall.Umask(0000)
// NOTE: the ordering of execution of the various command line
// flags is intentional and allows a single command to:
//
// 1. Check the fstype of a path
// 2. Write a new file within that path
// 3. Check that the file's content can be read
//
// Changing the ordering of the following code will break tests.
err = fsType(fsTypePath)
if err != nil {
errs = append(errs, err)
}
err = readWriteNewFile(newFilePath0644, 0644)
if err != nil {
errs = append(errs, err)
}
err = readWriteNewFile(newFilePath0666, 0666)
if err != nil {
errs = append(errs, err)
}
err = readWriteNewFile(newFilePath0660, 0660)
if err != nil {
errs = append(errs, err)
}
err = readWriteNewFile(newFilePath0777, 0777)
if err != nil {
errs = append(errs, err)
}
err = fileMode(fileModePath)
if err != nil {
errs = append(errs, err)
}
err = filePerm(filePermPath)
if err != nil {
errs = append(errs, err)
}
err = fileOwner(fileOwnerPath)
if err != nil {
errs = append(errs, err)
}
err = readFileContent(readFileContentPath)
if err != nil {
errs = append(errs, err)
}
err = readFileContentInLoop(readFileContentInLoopPath, retryDuration, breakOnExpectedContent)
if err != nil {
errs = append(errs, err)
}
if len(errs) != 0 {
os.Exit(1)
}
os.Exit(0)
}
// Defined by Linux (sys/statfs.h) - the type number for tmpfs mounts.
const linuxTmpfsMagic = 0x01021994
func fsType(path string) error {
if path == "" {
return nil
}
buf := syscall.Statfs_t{}
if err := syscall.Statfs(path, &buf); err != nil {
fmt.Printf("error from statfs(%q): %v\n", path, err)
return err
}
if buf.Type == linuxTmpfsMagic {
fmt.Printf("mount type of %q: tmpfs\n", path)
} else {
fmt.Printf("mount type of %q: %v\n", path, buf.Type)
}
return nil
}
func fileMode(path string) error {
if path == "" {
return nil
}
fileinfo, err := os.Stat(path)
if err != nil {
fmt.Printf("error from Stat(%q): %v\n", path, err)
return err
}
fmt.Printf("mode of file %q: %v\n", path, fileinfo.Mode())
return nil
}
func filePerm(path string) error {
if path == "" {
return nil
}
fileinfo, err := os.Stat(path)
if err != nil {
fmt.Printf("error from Stat(%q): %v\n", path, err)
return err
}
fmt.Printf("perms of file %q: %v\n", path, fileinfo.Mode().Perm())
return nil
}
func fileOwner(path string) error {
if path == "" {
return nil
}
buf := syscall.Stat_t{}
if err := syscall.Stat(path, &buf); err != nil {
fmt.Printf("error from stat(%q): %v\n", path, err)
return err
}
fmt.Printf("owner UID of %q: %v\n", path, buf.Uid)
fmt.Printf("owner GID of %q: %v\n", path, buf.Gid)
return nil
}
func readFileContent(path string) error {
if path == "" {
return nil
}
contentBytes, err := ioutil.ReadFile(path)
if err != nil {
fmt.Printf("error reading file content for %q: %v\n", path, err)
return err
}
fmt.Printf("content of file %q: %v\n", path, string(contentBytes))
return nil
}
const initialContent string = "mount-tester new file\n"
func readWriteNewFile(path string, perm os.FileMode) error {
if path == "" {
return nil
}
err := ioutil.WriteFile(path, []byte(initialContent), perm)
if err != nil {
fmt.Printf("error writing new file %q: %v\n", path, err)
return err
}
return readFileContent(path)
}
func readFileContentInLoop(path string, retryDuration int, breakOnExpectedContent bool) error {
if path == "" {
return nil
}
return testFileContent(path, retryDuration, breakOnExpectedContent)
}
func testFileContent(filePath string, retryDuration int, breakOnExpectedContent bool) error {
var (
contentBytes []byte
err error
)
retryTime := time.Second * time.Duration(retryDuration)
for start := time.Now(); time.Since(start) < retryTime; time.Sleep(2 * time.Second) {
contentBytes, err = ioutil.ReadFile(filePath)
if err != nil {
fmt.Printf("Error reading file %s: %v, retrying\n", filePath, err)
continue
}
fmt.Printf("content of file %q: %v\n", filePath, string(contentBytes))
if breakOnExpectedContent {
if string(contentBytes) != initialContent {
fmt.Printf("Unexpected content. Expected: %s. Retrying", initialContent)
continue
}
break
}
}
return err
}

17
vendor/k8s.io/kubernetes/test/images/n-way-http/BUILD generated vendored Normal file
View file

@ -0,0 +1,17 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_binary",
"go_library",
"go_test",
"cgo_library",
)
go_binary(
name = "n-way-http",
srcs = ["server.go"],
tags = ["automanaged"],
)

View file

@ -0,0 +1,18 @@
# Copyright 2016 The Kubernetes Authors.
#
# 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 busybox
MAINTAINER Prashanth B <beeps@google.com>
ADD server server
ENTRYPOINT ["/server"]

View file

@ -0,0 +1,31 @@
# Copyright 2016 The Kubernetes Authors.
#
# 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.
all: push
# 0.0 shouldn't clobber any released builds
TAG = 0.0
PREFIX = gcr.io/google_containers/n-way-http
server: server.go
CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -ldflags '-w' -o server ./server.go
container: server
docker build -t $(PREFIX):$(TAG) .
push: container
gcloud docker -- push $(PREFIX):$(TAG)
clean:
rm -f server

View file

@ -0,0 +1,55 @@
/*
Copyright 2015 The Kubernetes Authors.
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 webserver that runs n http handlers. Example invocation:
// - server -port 8080 -prefix foo -num 10 -start 0
// Will given you 10 /foo(i) endpoints that simply echo foo(i) when requested.
// - server -start 3 -num 1
// Will create just one endpoint, at /foo3
package main
import (
"flag"
"fmt"
"log"
"net/http"
)
var (
port = flag.Int("port", 8080, "Port number for requests.")
prefix = flag.String("prefix", "foo", "String used as path prefix")
num = flag.Int("num", 10, "Number of endpoints to create.")
start = flag.Int("start", 0, "Index to start, only makes sense with --num")
)
func main() {
flag.Parse()
// This container is used to test the GCE L7 controller which expects "/"
// to return a 200 response.
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
fmt.Fprint(w, "ok")
})
for i := *start; i < *start+*num; i++ {
path := fmt.Sprintf("%v%d", *prefix, i)
http.HandleFunc(fmt.Sprintf("/%v", path), func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
fmt.Fprint(w, path)
})
}
log.Printf("server -port %d -prefix %v -num %d -start %d", *port, *prefix, *num, *start)
http.ListenAndServe(fmt.Sprintf(":%d", *port), nil)
}

1
vendor/k8s.io/kubernetes/test/images/net/.gitignore generated vendored Normal file
View file

@ -0,0 +1 @@
/net

21
vendor/k8s.io/kubernetes/test/images/net/BUILD generated vendored Normal file
View file

@ -0,0 +1,21 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_binary",
"go_library",
"go_test",
"cgo_library",
)
go_binary(
name = "net",
srcs = ["main.go"],
tags = ["automanaged"],
deps = [
"//test/images/net/common:go_default_library",
"//test/images/net/nat:go_default_library",
],
)

18
vendor/k8s.io/kubernetes/test/images/net/Dockerfile generated vendored Normal file
View file

@ -0,0 +1,18 @@
# Copyright 2016 The Kubernetes Authors.
#
# 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 alpine
MAINTAINER Bowei Du <bowei@google.com>
COPY net /net
RUN apk update && apk add curl

39
vendor/k8s.io/kubernetes/test/images/net/Makefile generated vendored Normal file
View file

@ -0,0 +1,39 @@
# Copyright 2016 The Kubernetes Authors.
#
# 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.
ARCH := amd64
PREFIX ?= gcr.io/google_containers
TAG ?= 1.0
IMAGE ?= e2e-net-$(ARCH)
SRCS := $(shell find . -name \*.go)
all: image
net: $(SRCS)
CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -ldflags '-w'
image: test net
docker build -t $(PREFIX)/$(IMAGE):$(TAG) .
push: image
gcloud docker -- push $(PREFIX)/$(IMAGE):$(TAG)
clean:
rm -f net
test:
go test ./...
.PHONY: all clean image push test

36
vendor/k8s.io/kubernetes/test/images/net/README.md generated vendored Normal file
View file

@ -0,0 +1,36 @@
# Overview
The goal of this Go project is to consolidate all low-level
network testing "daemons" into one place. In network testing we
frequently have need of simple daemons (common/Runner) that perform
some "trivial" set of actions on a socket.
# Usage
* A package for each general area that is being tested, for example
`nat/` will contain Runners that test various NAT features.
* Every runner should be registered via `main.go:makeRunnerMap()`.
* Runners receive a JSON options structure as to their configuration. `Run()`
should return the disposition of the test.
Runners can be executed into two different ways, either through the
the command-line or via an HTTP request:
## Command-line
````
$ ./net -runner <runner> -options <json>
./net \
-runner nat-closewait-client \
-options '{"RemoteAddr":"127.0.0.1:9999"}'
````
## HTTP server
````
$ ./net --serve :8889
$ curl -v -X POST localhost:8889/run/nat-closewait-server \
-d '{"LocalAddr":"127.0.0.1:9999"}'
````
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/test/images/net/README.md?pixel)]()

17
vendor/k8s.io/kubernetes/test/images/net/common/BUILD generated vendored Normal file
View file

@ -0,0 +1,17 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_binary",
"go_library",
"go_test",
"cgo_library",
)
go_library(
name = "go_default_library",
srcs = ["common.go"],
tags = ["automanaged"],
)

View file

@ -0,0 +1,29 @@
/*
Copyright 2014 The Kubernetes Authors.
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.
*/
package common
import "log"
// Runner is a client or server to run.
type Runner interface {
// NewOptions returns a new empty options structure to be populated
// by from the JSON -options argument.
NewOptions() interface{}
// Run the client or server, taking in options. This execute the
// test code.
Run(logger *log.Logger, options interface{}) error
}

162
vendor/k8s.io/kubernetes/test/images/net/main.go generated vendored Normal file
View file

@ -0,0 +1,162 @@
/*
Copyright 2014 The Kubernetes Authors.
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.
*/
package main
import (
"bytes"
"encoding/json"
"flag"
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
"strings"
"k8s.io/kubernetes/test/images/net/common"
"k8s.io/kubernetes/test/images/net/nat"
)
type runnerMap map[string]common.Runner
type runRequestJSON struct {
runner string
options interface{}
}
var (
// flags for the command line. See usage args below for
// descriptions.
flags struct {
Serve string
Runner string
Options string
}
// runners is a map from runner name to runner instance.
runners = makeRunnerMap()
)
type logOutput struct {
b bytes.Buffer
}
func main() {
initFlags()
log.SetFlags(log.Flags() | log.Lshortfile)
if flags.Serve == "" {
output, err := executeRunner(flags.Runner, flags.Options)
if err == nil {
fmt.Print("output:\n\n" + output.b.String())
os.Exit(0)
} else {
log.Printf("Error: %v", err)
fmt.Print("output:\n\n" + output.b.String())
os.Exit(1)
}
} else {
http.HandleFunc("/run/", handleRunRequest)
log.Printf("Running server on %v", flags.Serve)
log.Fatal(http.ListenAndServe(flags.Serve, nil))
}
}
func initFlags() {
legalRunners := ""
for k := range runners {
legalRunners += " " + k
}
flag.StringVar(
&flags.Serve, "serve", "",
"Address and port to bind to (e.g. 127.0.0.1:8080). Setting this will "+
"run the network tester in server mode runner are triggered through "+
"HTTP requests.")
flag.StringVar(
&flags.Runner, "runner", "",
"Runner to execute (available:"+legalRunners+")")
flag.StringVar(
&flags.Options, "options", "",
"JSON options to the Runner")
flag.Parse()
if flags.Runner == "" && flags.Serve == "" {
log.Fatalf("Must set either -runner or -serve, see --help")
}
}
func makeRunnerMap() runnerMap {
// runner name is <pkg>-<file>-<specific>.
return runnerMap{
"nat-closewait-client": nat.NewCloseWaitClient(),
"nat-closewait-server": nat.NewCloseWaitServer(),
}
}
func executeRunner(name string, rawOptions string) (logOutput, error) {
runner, ok := runners[name]
if ok {
options := runner.NewOptions()
if err := json.Unmarshal([]byte(rawOptions), options); err != nil {
return logOutput{}, fmt.Errorf("Invalid options JSON: %v", err)
}
log.Printf("Options: %+v", options)
output := logOutput{}
logger := log.New(&output.b, "# ", log.Lshortfile)
return output, runner.Run(logger, options)
}
return logOutput{}, fmt.Errorf("Invalid runner: '%v', see --help\n", runner)
}
// handleRunRequest handles a request JSON to the network tester.
func handleRunRequest(w http.ResponseWriter, r *http.Request) {
log.Printf("handleRunRequest %v", *r)
urlParts := strings.Split(r.URL.Path, "/")
if len(urlParts) != 3 {
http.Error(w, fmt.Sprintf("invalid request to run: %v", urlParts), 400)
return
}
runner := urlParts[2]
if r.Body == nil {
http.Error(w, "Missing request body", 400)
return
}
body, err := ioutil.ReadAll(r.Body)
if err != nil {
http.Error(w, fmt.Sprintf("error reading body: %v", err), 400)
return
}
var output logOutput
if output, err = executeRunner(runner, string(body)); err != nil {
contents := fmt.Sprintf("Error from runner: %v\noutput:\n\n%s",
err, output.b.String())
http.Error(w, contents, 500)
return
}
fmt.Fprintf(w, "ok\noutput:\n\n"+output.b.String())
}
func setupLogger() {
}

18
vendor/k8s.io/kubernetes/test/images/net/nat/BUILD generated vendored Normal file
View file

@ -0,0 +1,18 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_binary",
"go_library",
"go_test",
"cgo_library",
)
go_library(
name = "go_default_library",
srcs = ["closewait.go"],
tags = ["automanaged"],
deps = ["//test/images/net/common:go_default_library"],
)

View file

@ -0,0 +1,196 @@
/*
Copyright 2016 The Kubernetes Authors.
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.
*/
package nat
/*
client/server for testing CLOSE_WAIT timeout condition in iptables NAT.
client server
| |
|<--tcp handshake-->|
|<-------fin--------| half-close from server
| | client is in CLOSE_WAIT
*/
import (
"errors"
"io"
"log"
"net"
"time"
"k8s.io/kubernetes/test/images/net/common"
)
// leakedConnection is a global variable that should leak the active
// connection assigned here.
var leakedConnection *net.TCPConn
// Server JSON options.
type CloseWaitServerOptions struct {
// Address to bind for the test
LocalAddr string
// Timeout to wait after sending the FIN.
PostFinTimeoutSeconds int
}
type closeWaitServer struct {
options *CloseWaitServerOptions
}
// NewCloseWaitServer returns a new Runner.
func NewCloseWaitServer() common.Runner {
return &closeWaitServer{}
}
// NewOptions allocates new options structure.
func (server *closeWaitServer) NewOptions() interface{} {
return &CloseWaitServerOptions{}
}
// Run the server-side of the test.
func (server *closeWaitServer) Run(logger *log.Logger, rawOptions interface{}) error {
if options, ok := rawOptions.(*CloseWaitServerOptions); ok {
server.options = options
} else {
return errors.New("invalid type")
}
logger.Printf("Run %v", server.options)
addr, err := net.ResolveTCPAddr("tcp", server.options.LocalAddr)
if err != nil {
return err
}
listener, err := net.ListenTCP("tcp", addr)
if err != nil {
return err
}
defer listener.Close()
logger.Printf("Server listening on %v", addr)
conn, err := listener.AcceptTCP()
if err != nil {
return err
}
defer conn.Close()
logger.Printf("Client connected")
// Send client half-close FIN so client is now in CLOSE_WAIT. We keep
// the client -> server pipe open to verify whether or not the NAT
// dropped our connection.
if err := conn.CloseWrite(); err != nil {
return err
}
logger.Printf("Server sent FIN, waiting %v seconds",
server.options.PostFinTimeoutSeconds)
<-time.After(time.Duration(server.options.PostFinTimeoutSeconds) * time.Second)
logger.Printf("Done")
return nil
}
// Client JSON options
type CloseWaitClientOptions struct {
// RemoteAddr of the server to connect to.
RemoteAddr string
// TimeoutSeconds on I/O with the server.
TimeoutSeconds int
// Half-close timeout (to give the test time to check the status of the
// conntrack table entry.
PostFinTimeoutSeconds int
// Leak connection (assign to global variable so connection persists
// as long as the process remains.
LeakConnection bool
}
type closeWaitClient struct {
options *CloseWaitClientOptions
}
// NewCloseWaitClient creates a new runner
func NewCloseWaitClient() common.Runner {
return &closeWaitClient{}
}
// NewOptions allocates new options structure.
func (client *closeWaitClient) NewOptions() interface{} {
return &CloseWaitClientOptions{}
}
// Run the client.m
func (client *closeWaitClient) Run(logger *log.Logger, rawOptions interface{}) error {
if options, ok := rawOptions.(*CloseWaitClientOptions); ok {
client.options = options
} else {
return errors.New("invalid type")
}
logger.Printf("Run %v", client.options)
addr, err := net.ResolveTCPAddr("tcp", client.options.RemoteAddr)
if err != nil {
return err
}
conn, err := net.DialTCP("tcp", nil, addr)
if err != nil {
return err
}
if !client.options.LeakConnection {
defer conn.Close()
}
logger.Printf("Connected to server")
if client.options.TimeoutSeconds > 0 {
delay := time.Duration(client.options.TimeoutSeconds) * time.Second
conn.SetReadDeadline(time.Now().Add(delay))
}
buf := make([]byte, 1, 1)
size, err := conn.Read(buf)
if err != nil && err != io.EOF {
return err
}
if size != 0 {
return errors.New("Got data but expected EOF")
}
logger.Printf("Server has half-closed the connection, waiting %v seconds",
client.options.PostFinTimeoutSeconds)
if client.options.LeakConnection {
logger.Printf("Leaking client connection (assigning to global variable)")
leakedConnection = conn
}
<-time.After(
time.Duration(client.options.PostFinTimeoutSeconds) * time.Second)
logger.Printf("Done")
return nil
}

View file

@ -0,0 +1 @@
netexec

18
vendor/k8s.io/kubernetes/test/images/netexec/BUILD generated vendored Normal file
View file

@ -0,0 +1,18 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_binary",
"go_library",
"go_test",
"cgo_library",
)
go_binary(
name = "netexec",
srcs = ["netexec.go"],
tags = ["automanaged"],
deps = ["//pkg/util/net:go_default_library"],
)

View file

@ -0,0 +1,25 @@
# Copyright 2016 The Kubernetes Authors.
#
# 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 busybox
MAINTAINER Abhishek Shah "abshah@google.com"
ADD netexec netexec
ADD netexec.go netexec.go
EXPOSE 8080
EXPOSE 8081
RUN mkdir /uploads
ENTRYPOINT ["/netexec"]

33
vendor/k8s.io/kubernetes/test/images/netexec/Makefile generated vendored Normal file
View file

@ -0,0 +1,33 @@
# Copyright 2016 The Kubernetes Authors.
#
# 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.
.PHONY: all netexec image push clean
TAG = 1.7
PREFIX = gcr.io/google_containers
all: push
netexec: netexec.go
CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -ldflags '-w' ./netexec.go
image: netexec
docker build -t $(PREFIX)/netexec:$(TAG) .
push: image
gcloud docker -- push $(PREFIX)/netexec:$(TAG)
clean:
rm -f netexec

407
vendor/k8s.io/kubernetes/test/images/netexec/netexec.go generated vendored Normal file
View file

@ -0,0 +1,407 @@
/*
Copyright 2014 The Kubernetes Authors.
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.
*/
package main
import (
"encoding/json"
"flag"
"fmt"
"io"
"io/ioutil"
"log"
"net"
"net/http"
"net/url"
"os"
"os/exec"
"strconv"
"strings"
"sync/atomic"
"time"
utilnet "k8s.io/kubernetes/pkg/util/net"
)
var (
httpPort = 8080
udpPort = 8081
shellPath = "/bin/sh"
serverReady = &atomicBool{0}
)
// atomicBool uses load/store operations on an int32 to simulate an atomic boolean.
type atomicBool struct {
v int32
}
// set sets the int32 to the given boolean.
func (a *atomicBool) set(value bool) {
if value {
atomic.StoreInt32(&a.v, 1)
return
}
atomic.StoreInt32(&a.v, 0)
}
// get returns true if the int32 == 1
func (a *atomicBool) get() bool {
return atomic.LoadInt32(&a.v) == 1
}
type output struct {
responses []string
errors []string
}
func init() {
flag.IntVar(&httpPort, "http-port", 8080, "HTTP Listen Port")
flag.IntVar(&udpPort, "udp-port", 8081, "UDP Listen Port")
}
func main() {
flag.Parse()
go startUDPServer(udpPort)
startHTTPServer(httpPort)
}
func startHTTPServer(httpPort int) {
http.HandleFunc("/", rootHandler)
http.HandleFunc("/clientip", clientIpHandler)
http.HandleFunc("/echo", echoHandler)
http.HandleFunc("/exit", exitHandler)
http.HandleFunc("/hostname", hostnameHandler)
http.HandleFunc("/shell", shellHandler)
http.HandleFunc("/upload", uploadHandler)
http.HandleFunc("/dial", dialHandler)
http.HandleFunc("/healthz", healthzHandler)
// older handlers
http.HandleFunc("/hostName", hostNameHandler)
http.HandleFunc("/shutdown", shutdownHandler)
log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", httpPort), nil))
}
func rootHandler(w http.ResponseWriter, r *http.Request) {
log.Printf("GET /")
fmt.Fprintf(w, "NOW: %v", time.Now())
}
func echoHandler(w http.ResponseWriter, r *http.Request) {
log.Printf("GET /echo?msg=%s", r.FormValue("msg"))
fmt.Fprintf(w, "%s", r.FormValue("msg"))
}
func clientIpHandler(w http.ResponseWriter, r *http.Request) {
log.Printf("GET /clientip")
fmt.Fprintf(w, r.RemoteAddr)
}
func exitHandler(w http.ResponseWriter, r *http.Request) {
log.Printf("GET /exit?code=%s", r.FormValue("code"))
code, err := strconv.Atoi(r.FormValue("code"))
if err == nil || r.FormValue("code") == "" {
os.Exit(code)
}
fmt.Fprintf(w, "argument 'code' must be an integer [0-127] or empty, got %q", r.FormValue("code"))
}
func hostnameHandler(w http.ResponseWriter, r *http.Request) {
log.Printf("GET /hostname")
fmt.Fprintf(w, getHostName())
}
// healthHandler response with a 200 if the UDP server is ready. It also serves
// as a health check of the HTTP server by virtue of being a HTTP handler.
func healthzHandler(w http.ResponseWriter, r *http.Request) {
log.Printf("GET /healthz")
if serverReady.get() {
w.WriteHeader(200)
return
}
w.WriteHeader(http.StatusPreconditionFailed)
}
func shutdownHandler(w http.ResponseWriter, r *http.Request) {
log.Printf("GET /shutdown")
os.Exit(0)
}
func dialHandler(w http.ResponseWriter, r *http.Request) {
values, err := url.Parse(r.URL.RequestURI())
if err != nil {
http.Error(w, fmt.Sprintf("%v", err), http.StatusBadRequest)
return
}
host := values.Query().Get("host")
port := values.Query().Get("port")
request := values.Query().Get("request") // hostName
protocol := values.Query().Get("protocol")
tryParam := values.Query().Get("tries")
log.Printf("GET /dial?host=%s&protocol=%s&port=%s&request=%s&tries=%s", host, protocol, port, request, tryParam)
tries := 1
if len(tryParam) > 0 {
tries, err = strconv.Atoi(tryParam)
}
if err != nil {
http.Error(w, fmt.Sprintf("tries parameter is invalid. %v", err), http.StatusBadRequest)
return
}
if len(request) == 0 {
http.Error(w, fmt.Sprintf("request parameter not specified. %v", err), http.StatusBadRequest)
return
}
if len(protocol) == 0 {
protocol = "http"
} else {
protocol = strings.ToLower(protocol)
}
if protocol != "http" && protocol != "udp" {
http.Error(w, fmt.Sprintf("unsupported protocol. %s", protocol), http.StatusBadRequest)
return
}
hostPort := net.JoinHostPort(host, port)
var udpAddress *net.UDPAddr
if protocol == "udp" {
udpAddress, err = net.ResolveUDPAddr("udp", hostPort)
if err != nil {
http.Error(w, fmt.Sprintf("host and/or port param are invalid. %v", err), http.StatusBadRequest)
return
}
} else {
_, err = net.ResolveTCPAddr("tcp", hostPort)
if err != nil {
http.Error(w, fmt.Sprintf("host and/or port param are invalid. %v", err), http.StatusBadRequest)
return
}
}
errors := make([]string, 0)
responses := make([]string, 0)
var response string
for i := 0; i < tries; i++ {
if protocol == "udp" {
response, err = dialUDP(request, udpAddress)
} else {
response, err = dialHTTP(request, hostPort)
}
if err != nil {
errors = append(errors, fmt.Sprintf("%v", err))
} else {
responses = append(responses, response)
}
}
output := map[string][]string{}
if len(response) > 0 {
output["responses"] = responses
}
if len(errors) > 0 {
output["errors"] = errors
}
bytes, err := json.Marshal(output)
if err == nil {
fmt.Fprintf(w, string(bytes))
} else {
http.Error(w, fmt.Sprintf("response could not be serialized. %v", err), http.StatusExpectationFailed)
}
}
func dialHTTP(request, hostPort string) (string, error) {
transport := utilnet.SetTransportDefaults(&http.Transport{})
httpClient := createHTTPClient(transport)
resp, err := httpClient.Get(fmt.Sprintf("http://%s/%s", hostPort, request))
defer transport.CloseIdleConnections()
if err == nil {
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err == nil {
return string(body), nil
}
}
return "", err
}
func createHTTPClient(transport *http.Transport) *http.Client {
client := &http.Client{
Transport: transport,
Timeout: 5 * time.Second,
}
return client
}
func dialUDP(request string, remoteAddress *net.UDPAddr) (string, error) {
Conn, err := net.DialUDP("udp", nil, remoteAddress)
if err != nil {
return "", fmt.Errorf("udp dial failed. err:%v", err)
}
defer Conn.Close()
buf := []byte(request)
_, err = Conn.Write(buf)
if err != nil {
return "", fmt.Errorf("udp connection write failed. err:%v", err)
}
udpResponse := make([]byte, 1024)
Conn.SetReadDeadline(time.Now().Add(5 * time.Second))
count, err := Conn.Read(udpResponse)
if err != nil || count == 0 {
return "", fmt.Errorf("reading from udp connection failed. err:'%v'", err)
}
return string(udpResponse[0:count]), nil
}
func shellHandler(w http.ResponseWriter, r *http.Request) {
cmd := r.FormValue("shellCommand")
if cmd == "" {
cmd = r.FormValue("cmd")
}
log.Printf("GET /shell?cmd=%s", cmd)
cmdOut, err := exec.Command(shellPath, "-c", cmd).CombinedOutput()
output := map[string]string{}
if len(cmdOut) > 0 {
output["output"] = string(cmdOut)
}
if err != nil {
output["error"] = fmt.Sprintf("%v", err)
}
log.Printf("Output: %s", output)
bytes, err := json.Marshal(output)
if err == nil {
fmt.Fprintf(w, string(bytes))
} else {
http.Error(w, fmt.Sprintf("response could not be serialized. %v", err), http.StatusExpectationFailed)
}
}
func uploadHandler(w http.ResponseWriter, r *http.Request) {
log.Printf("GET /upload")
result := map[string]string{}
file, _, err := r.FormFile("file")
if err != nil {
result["error"] = "Unable to upload file."
bytes, err := json.Marshal(result)
if err == nil {
fmt.Fprintf(w, string(bytes))
} else {
http.Error(w, fmt.Sprintf("%s. Also unable to serialize output. %v", result["error"], err), http.StatusInternalServerError)
}
log.Printf("Unable to upload file: %s", err)
return
}
defer file.Close()
f, err := ioutil.TempFile("/uploads", "upload")
if err != nil {
result["error"] = "Unable to open file for write"
bytes, err := json.Marshal(result)
if err == nil {
fmt.Fprintf(w, string(bytes))
} else {
http.Error(w, fmt.Sprintf("%s. Also unable to serialize output. %v", result["error"], err), http.StatusInternalServerError)
}
log.Printf("Unable to open file for write: %s", err)
return
}
defer f.Close()
if _, err = io.Copy(f, file); err != nil {
result["error"] = "Unable to write file."
bytes, err := json.Marshal(result)
if err == nil {
fmt.Fprintf(w, string(bytes))
} else {
http.Error(w, fmt.Sprintf("%s. Also unable to serialize output. %v", result["error"], err), http.StatusInternalServerError)
}
log.Printf("Unable to write file: %s", err)
return
}
UploadFile := f.Name()
if err := os.Chmod(UploadFile, 0700); err != nil {
result["error"] = "Unable to chmod file."
bytes, err := json.Marshal(result)
if err == nil {
fmt.Fprintf(w, string(bytes))
} else {
http.Error(w, fmt.Sprintf("%s. Also unable to serialize output. %v", result["error"], err), http.StatusInternalServerError)
}
log.Printf("Unable to chmod file: %s", err)
return
}
log.Printf("Wrote upload to %s", UploadFile)
result["output"] = UploadFile
w.WriteHeader(http.StatusCreated)
bytes, err := json.Marshal(result)
fmt.Fprintf(w, string(bytes))
}
func hostNameHandler(w http.ResponseWriter, r *http.Request) {
log.Printf("GET /hostName")
fmt.Fprintf(w, getHostName())
}
// udp server supports the hostName, echo and clientIP commands.
func startUDPServer(udpPort int) {
serverAddress, err := net.ResolveUDPAddr("udp", fmt.Sprintf(":%d", udpPort))
assertNoError(err)
serverConn, err := net.ListenUDP("udp", serverAddress)
defer serverConn.Close()
buf := make([]byte, 1024)
log.Printf("Started UDP server")
// Start responding to readiness probes.
serverReady.set(true)
defer func() {
log.Printf("UDP server exited")
serverReady.set(false)
}()
for {
n, clientAddress, err := serverConn.ReadFromUDP(buf)
assertNoError(err)
receivedText := strings.ToLower(strings.TrimSpace(string(buf[0:n])))
if receivedText == "hostname" {
log.Println("Sending udp hostName response")
_, err = serverConn.WriteToUDP([]byte(getHostName()), clientAddress)
assertNoError(err)
} else if strings.HasPrefix(receivedText, "echo ") {
parts := strings.SplitN(receivedText, " ", 2)
resp := ""
if len(parts) == 2 {
resp = parts[1]
}
log.Printf("Echoing %v\n", resp)
_, err = serverConn.WriteToUDP([]byte(resp), clientAddress)
assertNoError(err)
} else if receivedText == "clientip" {
log.Printf("Sending back clientip to %s", clientAddress.String())
_, err = serverConn.WriteToUDP([]byte(clientAddress.String()), clientAddress)
assertNoError(err)
} else if len(receivedText) > 0 {
log.Printf("Unknown udp command received: %v\n", receivedText)
}
}
}
func getHostName() string {
hostName, err := os.Hostname()
assertNoError(err)
return hostName
}
func assertNoError(err error) {
if err != nil {
log.Fatal("Error occurred. error:", err)
}
}

39
vendor/k8s.io/kubernetes/test/images/netexec/pod.yaml generated vendored Normal file
View file

@ -0,0 +1,39 @@
apiVersion: v1
kind: Pod
metadata:
name: netexec
labels:
app: netexec
spec:
containers:
- name: netexec
image: gcr.io/google_containers/netexec:1.5
ports:
- containerPort: 8080
protocol: TCP
- containerPort: 8081
protocol: UDP
# give this pod the same liveness and readiness probe because
# we always want the kubelet to restart it if it becomes
# unready, and at the same time we want to observe readiness
# as a signal to start testing.
livenessProbe:
httpGet:
path: /healthz
port: 8080
scheme: HTTP
initialDelaySeconds: 10
timeoutSeconds: 5
failureThreshold: 3
periodSeconds: 10
successThreshold: 1
readinessProbe:
httpGet:
path: /healthz
port: 8080
scheme: HTTP
initialDelaySeconds: 10
timeoutSeconds: 5
failureThreshold: 3
periodSeconds: 10
successThreshold: 1

View file

@ -0,0 +1,22 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_binary",
"go_library",
"go_test",
"cgo_library",
)
go_binary(
name = "network-tester",
srcs = ["webserver.go"],
tags = ["automanaged"],
deps = [
"//pkg/client/clientset_generated/internalclientset:go_default_library",
"//pkg/client/restclient:go_default_library",
"//pkg/util/sets:go_default_library",
],
)

View file

@ -0,0 +1,19 @@
# Copyright 2016 The Kubernetes Authors.
#
# 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
MAINTAINER Daniel Smith <dbsmith@google.com>
ADD webserver webserver
EXPOSE 8080
ENTRYPOINT ["/webserver"]

View file

@ -0,0 +1,32 @@
# Copyright 2016 The Kubernetes Authors.
#
# 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.
TAG = 1.9
PREFIX = gcr.io/google_containers
all: push
webserver: webserver.go
CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -ldflags '-w' ./webserver.go
container: image
image: webserver
docker build -t $(PREFIX)/nettest:$(TAG) .
push: image
gcloud docker -- push $(PREFIX)/nettest:$(TAG)
clean:
rm -f webserver

View file

@ -0,0 +1,44 @@
{
"kind": "ReplicationController",
"apiVersion": "v1",
"metadata": {
"name": "nettest-controller",
"labels": {
"name": "nettest"
}
},
"spec": {
"replicas": 2,
"selector": {
"name": "nettest"
},
"template": {
"metadata": {
"labels": {
"name": "nettest"
}
},
"spec": {
"containers": [
{
"name": "webserver",
"image": "gcr.io/google_containers/nettest:1.8",
"imagePullPolicy": "Always",
"args": [
"-service=nettest",
"-port=8080",
"-namespace=default",
"-peers=2"
],
"ports": [
{
"containerPort": 8080,
"protocol": "TCP"
}
]
}
]
}
}
}
}

View file

@ -0,0 +1,22 @@
{
"kind": "Service",
"apiVersion": "v1",
"metadata": {
"name": "nettest",
"labels": {
"name": "nettest"
}
},
"spec": {
"ports": [
{
"port": 8080,
"protocol": "TCP",
"targetPort": 8080
}
],
"selector": {
"name": "nettest"
}
}
}

View file

@ -0,0 +1,28 @@
{
"kind": "Pod",
"apiVersion": "v1",
"metadata": {
"name": "slow-pod",
"labels": {
"name": "nettest"
}
},
"spec": {
"containers": [
{
"name": "webserver",
"image": "gcr.io/google_containers/nettest:1.8",
"args": [
"-service=nettest",
"-delay-shutdown=10"
],
"ports": [
{
"containerPort": 8080,
"protocol": "TCP"
}
]
}
]
}
}

View file

@ -0,0 +1,42 @@
{
"kind": "ReplicationController",
"apiVersion": "v1",
"metadata": {
"name": "slow-rc",
"labels": {
"name": "nettest"
}
},
"spec": {
"replicas": 8,
"selector": {
"name": "nettest"
},
"template": {
"metadata": {
"labels": {
"name": "nettest"
}
},
"spec": {
"terminationGracePeriodSeconds": 5,
"containers": [
{
"name": "webserver",
"image": "gcr.io/google_containers/nettest:1.8",
"args": [
"-service=nettest",
"-delay-shutdown=10"
],
"ports": [
{
"containerPort": 8080,
"protocol": "TCP"
}
]
}
]
}
}
}
}

View file

@ -0,0 +1,315 @@
/*
Copyright 2014 The Kubernetes Authors.
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 web server for checking networking connectivity.
//
// Will dial out to, and expect to hear from, every pod that is a member of
// the service passed in the flag -service.
//
// Will serve a webserver on given -port.
//
// Visit /read to see the current state, or /quit to shut down.
//
// Visit /status to see pass/running/fail determination. (literally, it will
// return one of those words.)
//
// /write is used by other network test pods to register connectivity.
package main
import (
"bytes"
"encoding/json"
"flag"
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
"os/signal"
"sync"
"syscall"
"time"
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
"k8s.io/kubernetes/pkg/client/restclient"
"k8s.io/kubernetes/pkg/util/sets"
)
var (
port = flag.Int("port", 8080, "Port number to serve at.")
peerCount = flag.Int("peers", 8, "Must find at least this many peers for the test to pass.")
service = flag.String("service", "nettest", "Service to find other network test pods in.")
namespace = flag.String("namespace", "default", "Namespace of this pod. TODO: kubernetes should make this discoverable.")
delayShutdown = flag.Int("delay-shutdown", 0, "Number of seconds to delay shutdown when receiving SIGTERM.")
)
// State tracks the internal state of our little http server.
// It's returned verbatim over the /read endpoint.
type State struct {
// Hostname is set once and never changed-- it's always safe to read.
Hostname string
// The below fields require that lock is held before reading or writing.
Sent map[string]int
Received map[string]int
Errors []string
Log []string
StillContactingPeers bool
lock sync.Mutex
}
func (s *State) doneContactingPeers() {
s.lock.Lock()
defer s.lock.Unlock()
s.StillContactingPeers = false
}
// serveStatus returns "pass", "running", or "fail".
func (s *State) serveStatus(w http.ResponseWriter, r *http.Request) {
s.lock.Lock()
defer s.lock.Unlock()
if len(s.Sent) >= *peerCount && len(s.Received) >= *peerCount {
fmt.Fprintf(w, "pass")
return
}
if s.StillContactingPeers {
fmt.Fprintf(w, "running")
return
}
// Logf can't be called while holding the lock, so defer using a goroutine
go s.Logf("Declaring failure for %s/%s with %d sent and %d received and %d peers", *namespace, *service, len(s.Sent), len(s.Received), *peerCount)
fmt.Fprintf(w, "fail")
}
// serveRead writes our json encoded state
func (s *State) serveRead(w http.ResponseWriter, r *http.Request) {
s.lock.Lock()
defer s.lock.Unlock()
w.WriteHeader(http.StatusOK)
b, err := json.MarshalIndent(s, "", "\t")
s.appendErr(err)
_, err = w.Write(b)
s.appendErr(err)
}
// WritePost is the format that (json encoded) requests to the /write handler should take.
type WritePost struct {
Source string
Dest string
}
// WriteResp is returned by /write
type WriteResp struct {
Hostname string
}
// serveWrite records the contact in our state.
func (s *State) serveWrite(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
s.lock.Lock()
defer s.lock.Unlock()
w.WriteHeader(http.StatusOK)
var wp WritePost
s.appendErr(json.NewDecoder(r.Body).Decode(&wp))
if wp.Source == "" {
s.appendErr(fmt.Errorf("%v: Got request with no source", s.Hostname))
} else {
if s.Received == nil {
s.Received = map[string]int{}
}
s.Received[wp.Source] += 1
}
s.appendErr(json.NewEncoder(w).Encode(&WriteResp{Hostname: s.Hostname}))
}
// appendErr adds err to the list, if err is not nil. s must be locked.
func (s *State) appendErr(err error) {
if err != nil {
s.Errors = append(s.Errors, err.Error())
}
}
// Logf writes to the log message list. s must not be locked.
// s's Log member will drop an old message if it would otherwise
// become longer than 500 messages.
func (s *State) Logf(format string, args ...interface{}) {
s.lock.Lock()
defer s.lock.Unlock()
s.Log = append(s.Log, fmt.Sprintf(format, args...))
if len(s.Log) > 500 {
s.Log = s.Log[1:]
}
}
// s must not be locked
func (s *State) appendSuccessfulSend(toHostname string) {
s.lock.Lock()
defer s.lock.Unlock()
if s.Sent == nil {
s.Sent = map[string]int{}
}
s.Sent[toHostname] += 1
}
var (
// Our one and only state object
state State
)
func main() {
flag.Parse()
if *service == "" {
log.Fatal("Must provide -service flag.")
}
hostname, err := os.Hostname()
if err != nil {
log.Fatalf("Error getting hostname: %v", err)
}
if *delayShutdown > 0 {
termCh := make(chan os.Signal)
signal.Notify(termCh, syscall.SIGTERM)
go func() {
<-termCh
log.Printf("Sleeping %d seconds before exit ...", *delayShutdown)
time.Sleep(time.Duration(*delayShutdown) * time.Second)
os.Exit(0)
}()
}
state := State{
Hostname: hostname,
StillContactingPeers: true,
}
go contactOthers(&state)
http.HandleFunc("/quit", func(w http.ResponseWriter, r *http.Request) {
os.Exit(0)
})
http.HandleFunc("/read", state.serveRead)
http.HandleFunc("/write", state.serveWrite)
http.HandleFunc("/status", state.serveStatus)
go log.Fatal(http.ListenAndServe(fmt.Sprintf("0.0.0.0:%d", *port), nil))
select {}
}
// Find all sibling pods in the service and post to their /write handler.
func contactOthers(state *State) {
sleepTime := 5 * time.Second
// In large cluster getting all endpoints is pretty expensive.
// Thus, we will limit ourselves to send on average at most 10 such
// requests per second
if sleepTime < time.Duration(*peerCount/10)*time.Second {
sleepTime = time.Duration(*peerCount/10) * time.Second
}
timeout := 5 * time.Minute
// Similarly we need to bump timeout so that it is reasonable in large
// clusters.
if timeout < time.Duration(*peerCount)*time.Second {
timeout = time.Duration(*peerCount) * time.Second
}
defer state.doneContactingPeers()
config, err := restclient.InClusterConfig()
if err != nil {
log.Fatalf("Unable to create config; error: %v\n", err)
}
config.ContentType = "application/vnd.kubernetes.protobuf"
client, err := clientset.NewForConfig(config)
if err != nil {
log.Fatalf("Unable to create client; error: %v\n", err)
}
// Double check that that worked by getting the server version.
if v, err := client.Discovery().ServerVersion(); err != nil {
log.Fatalf("Unable to get server version: %v\n", err)
} else {
log.Printf("Server version: %#v\n", v)
}
for start := time.Now(); time.Since(start) < timeout; time.Sleep(sleepTime) {
eps := getWebserverEndpoints(client)
if eps.Len() >= *peerCount {
break
}
state.Logf("%v/%v has %v endpoints (%v), which is less than %v as expected. Waiting for all endpoints to come up.", *namespace, *service, len(eps), eps.List(), *peerCount)
}
// Do this repeatedly, in case there's some propagation delay with getting
// newly started pods into the endpoints list.
for i := 0; i < 15; i++ {
eps := getWebserverEndpoints(client)
for ep := range eps {
state.Logf("Attempting to contact %s", ep)
contactSingle(ep, state)
}
time.Sleep(sleepTime)
}
}
//getWebserverEndpoints returns the webserver endpoints as a set of String, each in the format like "http://{ip}:{port}"
func getWebserverEndpoints(client clientset.Interface) sets.String {
endpoints, err := client.Core().Endpoints(*namespace).Get(*service)
eps := sets.String{}
if err != nil {
state.Logf("Unable to read the endpoints for %v/%v: %v.", *namespace, *service, err)
return eps
}
for _, ss := range endpoints.Subsets {
for _, a := range ss.Addresses {
for _, p := range ss.Ports {
eps.Insert(fmt.Sprintf("http://%s:%d", a.IP, p.Port))
}
}
}
return eps
}
// contactSingle dials the address 'e' and tries to POST to its /write address.
func contactSingle(e string, state *State) {
body, err := json.Marshal(&WritePost{
Dest: e,
Source: state.Hostname,
})
if err != nil {
log.Fatalf("json marshal error: %v", err)
}
resp, err := http.Post(e+"/write", "application/json", bytes.NewReader(body))
if err != nil {
state.Logf("Warning: unable to contact the endpoint %q: %v", e, err)
return
}
defer resp.Body.Close()
body, err = ioutil.ReadAll(resp.Body)
if err != nil {
state.Logf("Warning: unable to read response from '%v': '%v'", e, err)
return
}
var wr WriteResp
err = json.Unmarshal(body, &wr)
if err != nil {
state.Logf("Warning: unable to unmarshal response (%v) from '%v': '%v'", string(body), e, err)
return
}
state.appendSuccessfulSend(wr.Hostname)
}

View file

@ -0,0 +1,39 @@
# Copyright 2016 The Kubernetes Authors.
#
# 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.
# TODO: get rid of bash dependency and switch to plain busybox.
# The tar in busybox also doesn't seem to understand compression.
FROM debian:jessie
MAINTAINER Prashanth.B <beeps@google.com>
# TODO: just use standard redis when there is one for 3.2.0.
RUN apt-get update && apt-get install -y wget make gcc
# See README.md
RUN wget -qO /redis-3.2.0.tar.gz http://download.redis.io/releases/redis-3.2.0.tar.gz && \
tar -xzf /redis-3.2.0.tar.gz -C /tmp/ && rm /redis-3.2.0.tar.gz
# Clean out existing deps before installation
# see https://github.com/antirez/redis/issues/722
RUN cd /tmp/redis-3.2.0 && make distclean && mkdir -p /redis && \
make install INSTALL_BIN=/redis && \
mv /tmp/redis-3.2.0/redis.conf /redis/redis.conf && \
rm -rf /tmp/redis-3.2.0
ADD on-start.sh /
# See contrib/pets/peer-finder for details
RUN wget -qO /peer-finder https://storage.googleapis.com/kubernetes-release/pets/peer-finder
ADD install.sh /
RUN chmod -c 755 /install.sh /on-start.sh /peer-finder
Entrypoint ["/install.sh"]

View file

@ -0,0 +1,27 @@
# Copyright 2016 The Kubernetes Authors.
#
# 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.
all: push
TAG = e2e
PREFIX = gcr.io/google_containers/redis-install-3.2.0
container:
docker build -t $(PREFIX):$(TAG) .
push: container
gcloud docker -- push $(PREFIX):$(TAG)
clean:
docker rmi $(PREFIX):$(TAG)

View file

@ -0,0 +1,12 @@
# Redis petset e2e tester
The image in this directory is the init container for contrib/pets/redis but for one difference, it bakes a specific version of redis into the base image so we get deterministic test results without having to depend on a redis download server. Discussing the tradeoffs to either approach (download the version at runtime, or maintain an image per version) are outside the scope of this document.
You can execute the image locally via:
```
$ docker run -it gcr.io/google_containers/redis-install-3.2.0:e2e --cmd --install-into=/opt --work-dir=/work-dir
```
To share the installation with other containers mount the appropriate volumes as `--install-into` and `--work-dir`, where `install-into` is the directory to install redis into, and `work-dir` is the directory to install the user/admin supplied on-{start,change} hook scripts.
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/test/images/pets/redis/README.md?pixel)]()

51
vendor/k8s.io/kubernetes/test/images/pets/redis/install.sh generated vendored Executable file
View file

@ -0,0 +1,51 @@
#! /bin/bash
# Copyright 2016 The Kubernetes Authors.
#
# 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.
# This volume is assumed to exist and is shared with parent of the init
# container. It contains the redis installation.
INSTALL_VOLUME="/opt"
# This volume is assumed to exist and is shared with the peer-finder
# init container. It contains on-start/change configuration scripts.
WORK_DIR="/work-dir"
VERSION="3.2.0"
for i in "$@"
do
case $i in
-i=*|--install-into=*)
INSTALL_VOLUME="${i#*=}"
shift
;;
-w=*|--work-dir=*)
WORK_DIR="${i#*=}"
shift
;;
*)
# unknown option
;;
esac
done
echo installing config scripts into "${WORK_DIR}"
mkdir -p "${WORK_DIR}"
cp /on-start.sh "${WORK_DIR}"/
cp /peer-finder "${WORK_DIR}"/
echo installing redis-"${VERSION}" into "${INSTALL_VOLUME}"
mkdir -p "${INSTALL_VOLUME}"
mv /redis "${INSTALL_VOLUME}"/redis

49
vendor/k8s.io/kubernetes/test/images/pets/redis/on-start.sh generated vendored Executable file
View file

@ -0,0 +1,49 @@
#!/bin/bash
# Copyright 2016 The Kubernetes Authors.
#
# 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.
set -e
CFG=/opt/redis/redis.conf
HOSTNAME=$(hostname)
DATADIR="/data"
# Port on which redis listens for connections.
PORT=6379
# Ping everyone but ourself to see if there's a master. Only one pet starts at
# a time, so if we don't see a master we can assume the position is ours.
while read -ra LINE; do
if [[ "${LINE}" == *"${HOSTNAME}"* ]]; then
sed -i -e "s|^bind.*$|bind ${LINE}|" ${CFG}
elif [ "$(/opt/redis/redis-cli -h $LINE info | grep role | sed 's,\r$,,')" = "role:master" ]; then
# TODO: More restrictive regex?
sed -i -e "s|^# slaveof.*$|slaveof ${LINE} ${PORT}|" ${CFG}
fi
done
# Set the data directory for append only log and snapshot files. This should
# be a persistent volume for consistency.
sed -i -e "s|^.*dir .*$|dir ${DATADIR}|" ${CFG}
# The append only log is written for every SET operation. Without this setting,
# redis just snapshots periodically which is only safe for a cache. This will
# produce an appendonly.aof file in the configured data dir.
sed -i -e "s|^appendonly .*$|appendonly yes|" ${CFG}
# Every write triggers an fsync. Recommended default is "everysec", which
# is only safe for AP applications.
sed -i -e "s|^appendfsync .*$|appendfsync always|" ${CFG}

View file

@ -0,0 +1,32 @@
# Copyright 2016 The Kubernetes Authors.
#
# 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.
# TODO: get rid of bash dependency and switch to plain busybox.
# The tar in busybox also doesn't seem to understand compression.
FROM debian:jessie
MAINTAINER Prashanth.B <beeps@google.com>
RUN apt-get update && apt-get install -y wget netcat
ADD on-start.sh /
# See contrib/pets/peer-finder for details
RUN wget -qO /peer-finder https://storage.googleapis.com/kubernetes-release/pets/peer-finder
# See README.md
RUN wget -q -O /zookeeper-3.5.0-alpha.tar.gz http://apache.mirrors.pair.com/zookeeper/zookeeper-3.5.0-alpha/zookeeper-3.5.0-alpha.tar.gz && \
tar -xzf /zookeeper-3.5.0-alpha.tar.gz -C /tmp/ && mv /tmp/zookeeper-3.5.0-alpha /zookeeper && rm /zookeeper-3.5.0-alpha.tar.gz
ADD install.sh /
RUN chmod -c 755 /install.sh /on-start.sh /peer-finder
Entrypoint ["/install.sh"]

View file

@ -0,0 +1,27 @@
# Copyright 2016 The Kubernetes Authors.
#
# 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.
all: push
TAG = e2e
PREFIX = gcr.io/google_containers/zookeeper-install-3.5.0-alpha
container:
docker build -t $(PREFIX):$(TAG) .
push: container
gcloud docker -- push $(PREFIX):$(TAG)
clean:
docker rmi $(PREFIX):$(TAG)

View file

@ -0,0 +1,12 @@
# Zookeeper petset e2e tester
The image in this directory is the init container for contrib/pets/zookeeper but for one difference, it bakes a specific version of zookeeper into the base image so we get deterministic test results without having to depend on a zookeeper download server. Discussing the tradeoffs to either approach (download the version at runtime, or maintain an image per version) are outside the scope of this document.
You can execute the image locally via:
```
$ docker run -it gcr.io/google_containers/zookeeper-install-3.5.0-alpha:e2e --cmd --install-into=/opt --work-dir=/work-dir
```
To share the installation with other containers mount the appropriate volumes as `--install-into` and `--work-dir`, where `install-into` is the directory to install zookeeper into, and `work-dir` is the directory to install the user/admin supplied on-{start,change} hook scripts.
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/test/images/pets/zookeeper/README.md?pixel)]()

View file

@ -0,0 +1,70 @@
#! /bin/bash
# Copyright 2016 The Kubernetes Authors.
#
# 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.
# This volume is assumed to exist and is shared with parent of the init
# container. It contains the zookeeper installation.
INSTALL_VOLUME="/opt"
# This volume is assumed to exist and is shared with the peer-finder
# init container. It contains on-start/change configuration scripts.
WORKDIR_VOLUME="/work-dir"
# As of April-2016 is 3.4.8 is the latest stable, but versions 3.5.0 onward
# allow dynamic reconfiguration.
VERSION="3.5.0-alpha"
for i in "$@"
do
case $i in
-i=*|--install-into=*)
INSTALL_VOLUME="${i#*=}"
shift
;;
-w=*|--work-dir=*)
WORKDIR_VOLUME="${i#*=}"
shift
;;
*)
# unknown option
;;
esac
done
echo installing config scripts into "${WORKDIR_VOLUME}"
mkdir -p "${WORKDIR_VOLUME}"
cp /on-start.sh "${WORKDIR_VOLUME}"/
cp /peer-finder "${WORKDIR_VOLUME}"/
echo installing zookeeper-"${VERSION}" into "${INSTALL_VOLUME}"
mkdir -p "${INSTALL_VOLUME}"
mv /zookeeper "${INSTALL_VOLUME}"/zookeeper
cp "${INSTALL_VOLUME}"/zookeeper/conf/zoo_sample.cfg "${INSTALL_VOLUME}"/zookeeper/conf/zoo.cfg
# TODO: Should dynamic config be tied to the version?
IFS="." read -ra RELEASE <<< "${VERSION}"
if [ $(expr "${RELEASE[1]}") -gt 4 ]; then
echo zookeeper-"${VERSION}" supports dynamic reconfiguration, enabling it
echo "standaloneEnabled=false" >> "${INSTALL_VOLUME}"/zookeeper/conf/zoo.cfg
echo "dynamicConfigFile="${INSTALL_VOLUME}"/zookeeper/conf/zoo.cfg.dynamic" >> "${INSTALL_VOLUME}"/zookeeper/conf/zoo.cfg
fi
# TODO: This is a hack, netcat is convenient to have in the zookeeper container
# I want to avoid using a custom zookeeper image just for this. So copy it.
NC=$(which nc)
if [ "${NC}" != "" ]; then
echo copying nc into "${INSTALL_VOLUME}"
cp "${NC}" "${INSTALL_VOLUME}"
fi

View file

@ -0,0 +1,106 @@
#! /bin/bash
# Copyright 2016 The Kubernetes Authors.
#
# 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.
set -eo pipefail
# This script configures zookeeper cluster member ship for version of zookeeper
# >= 3.5.0. It should not be used with the on-change.sh script in this example.
# As of April-2016 is 3.4.8 is the latest stable.
# Both /opt and /tmp/zookeeper are assumed to be volumes shared with the parent.
# The format of each line in the dynamic config file is:
# server.<1 based index>=<server-dns-name>:<peer port>:<election port>[:role];[<client port address>:]<client port>
# <1 based index> is the server index that matches the id in datadir/myid
# <peer port> is the port on which peers communicate to agree on updates
# <election port> is the port used for leader election
# [:role] can be set to observer, participant by default
# <client port address> is optional and defaults to 0.0.0.0
# <client port> is the port on which the server accepts client connections
CFG=/opt/zookeeper/conf/zoo.cfg.dynamic
CFG_BAK=/opt/zookeeper/conf/zoo.cfg.bak
MY_ID_FILE=/tmp/zookeeper/myid
HOSTNAME=$(hostname)
while read -ra LINE; do
PEERS=("${PEERS[@]}" $LINE)
done
# Don't add the first member as an observer
if [ ${#PEERS[@]} -eq 1 ]; then
# We need to write our index in this list of servers into MY_ID_FILE.
# Note that this may not always coincide with the hostname id.
echo 1 > "${MY_ID_FILE}"
echo "server.1=${PEERS[0]}:2888:3888;2181" > "${CFG}"
# TODO: zkServer-initialize is the safe way to handle changes to datadir
# because simply starting will create a new datadir, BUT if the user changed
# pod template they might end up with 2 datadirs and brief split brain.
exit
fi
# Every subsequent member is added as an observer and promoted to a participant
echo "" > "${CFG_BAK}"
i=0
LEADER=$HOSTNAME
for peer in "${PEERS[@]}"; do
let i=i+1
if [[ "${peer}" == *"${HOSTNAME}"* ]]; then
MY_ID=$i
MY_NAME=${peer}
echo $i > "${MY_ID_FILE}"
echo "server.${i}=${peer}:2888:3888:observer;2181" >> "${CFG_BAK}"
else
if [[ $(echo srvr | /opt/nc "${peer}" 2181 | grep Mode) = "Mode: leader" ]]; then
LEADER="${peer}"
fi
echo "server.${i}=${peer}:2888:3888:participant;2181" >> "${CFG_BAK}"
fi
done
# zookeeper won't start without myid anyway.
# This means our hostname wasn't in the peer list.
if [ ! -f "${MY_ID_FILE}" ]; then
exit 1
fi
# Once the dynamic config file is written it shouldn't be modified, so the final
# reconfigure needs to happen through the "reconfig" command.
cp ${CFG_BAK} ${CFG}
# TODO: zkServer-initialize is the safe way to handle changes to datadir
# because simply starting will create a new datadir, BUT if the user changed
# pod template they might end up with 2 datadirs and brief split brain.
/opt/zookeeper/bin/zkServer.sh start
# TODO: We shouldn't need to specify the address of the master as long as
# there's quorum. According to the docs the new server is just not allowed to
# vote, it's still allowed to propose config changes, and it knows the
# existing members of the ensemble from *its* config.
ADD_SERVER="server.$MY_ID=$MY_NAME:2888:3888:participant;0.0.0.0:2181"
/opt/zookeeper/bin/zkCli.sh reconfig -s "${LEADER}":2181 -add "${ADD_SERVER}"
# Prove that we've actually joined the running cluster
ITERATION=0
until $(echo config | /opt/nc localhost 2181 | grep "${ADD_SERVER}" > /dev/null); do
echo $ITERATION] waiting for updated config to sync back to localhost
sleep 1
let ITERATION=ITERATION+1
if [ $ITERATION -eq 20 ]; then
exit 1
fi
done
/opt/zookeeper/bin/zkServer.sh stop

View file

@ -0,0 +1 @@
portforwardtester

View file

@ -0,0 +1,17 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_binary",
"go_library",
"go_test",
"cgo_library",
)
go_binary(
name = "port-forward-tester",
srcs = ["portforwardtester.go"],
tags = ["automanaged"],
)

View file

@ -0,0 +1,18 @@
# Copyright 2015 The Kubernetes Authors.
#
# 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"]

View file

@ -0,0 +1,30 @@
# Copyright 2016 The Kubernetes Authors.
#
# 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.
TAG = 1.2
PREFIX = gcr.io/google_containers
all: push
portforwardtester: portforwardtester.go
CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -ldflags '-w' ./portforwardtester.go
image: portforwardtester
docker build -t $(PREFIX)/portforwardtester:$(TAG) .
push: image
gcloud docker -- push $(PREFIX)/portforwardtester:$(TAG)
clean:
rm -f portforwardtester

View file

@ -0,0 +1,141 @@
/*
Copyright 2015 The Kubernetes Authors.
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
}
// taken from net/http/server.go:
//
// rstAvoidanceDelay is the amount of time we sleep after closing the
// write side of a TCP connection before closing the entire socket.
// By sleeping, we increase the chances that the client sees our FIN
// and processes its final data before they process the subsequent RST
// from closing a connection with known unread data.
// This RST seems to occur mostly on BSD systems. (And Windows?)
// This timeout is somewhat arbitrary (~latency around the planet).
const rstAvoidanceDelay = 500 * time.Millisecond
func main() {
bindAddress := os.Getenv("BIND_ADDRESS")
if bindAddress == "" {
bindAddress = "localhost"
}
bindPort := os.Getenv("BIND_PORT")
addr, err := net.ResolveTCPAddr("tcp", net.JoinHostPort(bindAddress, bindPort))
if err != nil {
fmt.Printf("Error resolving: %v\n", err)
os.Exit(1)
}
listener, err := net.ListenTCP("tcp", addr)
if err != nil {
fmt.Printf("Error listening: %v\n", err)
os.Exit(1)
}
conn, err := listener.AcceptTCP()
if err != nil {
fmt.Printf("Error accepting connection: %v\n", err)
os.Exit(1)
}
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("Shutting down connection")
// set linger timeout to flush buffers. This is the official way according to the go api docs. But
// there are controversial discussions whether this value has any impact on most platforms
// (compare https://codereview.appspot.com/95320043).
conn.SetLinger(-1)
// Flush the connection cleanly, following https://blog.netherlabs.nl/articles/2009/01/18/the-ultimate-so_linger-page-or-why-is-my-tcp-not-reliable:
// 1. close write half of connection which sends a FIN packet
// 2. give client some time to receive the FIN
// 3. close the complete connection
conn.CloseWrite()
time.Sleep(rstAvoidanceDelay)
conn.Close()
fmt.Println("Done")
}

View file

@ -0,0 +1,2 @@
porter
.tag

17
vendor/k8s.io/kubernetes/test/images/porter/BUILD generated vendored Normal file
View file

@ -0,0 +1,17 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_binary",
"go_library",
"go_test",
"cgo_library",
)
go_binary(
name = "porter",
srcs = ["porter.go"],
tags = ["automanaged"],
)

20
vendor/k8s.io/kubernetes/test/images/porter/Dockerfile generated vendored Normal file
View file

@ -0,0 +1,20 @@
# Copyright 2016 The Kubernetes Authors.
#
# 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
MAINTAINER Daniel Smith <dbsmith@google.com>
ADD localhost.crt localhost.crt
ADD localhost.key localhost.key
ADD porter porter
ENTRYPOINT ["/porter"]

47
vendor/k8s.io/kubernetes/test/images/porter/Makefile generated vendored Normal file
View file

@ -0,0 +1,47 @@
# Copyright 2016 The Kubernetes Authors.
#
# 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.
# Use:
#
# `make porter` will build porter.
# `make tag` will suggest a tag.
# `make image` will build an image-- you must supply a tag.
# `make push` will push the image-- you must supply a tag.
# This image does not tag in the normal way
# TAG =
PREFIX = gcr.io/google_containers
SUGGESTED_TAG = $(shell git rev-parse --verify HEAD)
porter: porter.go
CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -ldflags '-w' ./porter.go
tag:
@echo "If all relevant changes are committed, suggest using TAG=$(SUGGESTED_TAG)"
@echo "$$ make container TAG=$(SUGGESTED_TAG)"
@echo "or"
@echo "$$ make push TAG=$(SUGGESTED_TAG)"
container: image
image:
$(if $(TAG),,$(error TAG is not defined. Use 'make tag' after committing changes to see a suggestion))
docker build -t $(PREFIX)/porter:$(TAG) .
push:
$(if $(TAG),,$(error TAG is not defined. Use 'make tag' after committing changes to see a suggestion))
gcloud docker -- push $(PREFIX)/porter:$(TAG)
clean:
rm -f porter

12
vendor/k8s.io/kubernetes/test/images/porter/README.md generated vendored Normal file
View file

@ -0,0 +1,12 @@
This directory contains go source, Dockerfile and Makefile for making a test
container which serves requested data on ports specified in ENV variables.
The included localhost.crt is a PEM-encoded TLS cert with SAN IPs
"127.0.0.1" and "[::1]", expiring at the last second of 2049 (the end
of ASN.1 time), generated from src/crypto/tls:
go run generate_cert.go --rsa-bits 512 --host 127.0.0.1,::1,example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h
To use a different cert/key, mount them into the pod and set the
CERT_FILE and KEY_FILE environment variables to the desired paths.
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/test/images/porter/README.md?pixel)]()

View file

@ -0,0 +1,10 @@
-----BEGIN CERTIFICATE-----
MIIBdzCCASOgAwIBAgIBADALBgkqhkiG9w0BAQUwEjEQMA4GA1UEChMHQWNtZSBD
bzAeFw03MDAxMDEwMDAwMDBaFw00OTEyMzEyMzU5NTlaMBIxEDAOBgNVBAoTB0Fj
bWUgQ28wWjALBgkqhkiG9w0BAQEDSwAwSAJBAN55NcYKZeInyTuhcCwFMhDHCmwa
IUSdtXdcbItRB/yfXGBhiex00IaLXQnSU+QZPRZWYqeTEbFSgihqi1PUDy8CAwEA
AaNoMGYwDgYDVR0PAQH/BAQDAgCkMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA8GA1Ud
EwEB/wQFMAMBAf8wLgYDVR0RBCcwJYILZXhhbXBsZS5jb22HBH8AAAGHEAAAAAAA
AAAAAAAAAAAAAAEwCwYJKoZIhvcNAQEFA0EAAoQn/ytgqpiLcZu9XKbCJsJcvkgk
Se6AbGXgSlq+ZCEVo0qIwSgeBqmsJxUu7NCSOwVJLYNEBO2DtIxoYVk+MA==
-----END CERTIFICATE-----

View file

@ -0,0 +1,9 @@
-----BEGIN RSA PRIVATE KEY-----
MIIBPAIBAAJBAN55NcYKZeInyTuhcCwFMhDHCmwaIUSdtXdcbItRB/yfXGBhiex0
0IaLXQnSU+QZPRZWYqeTEbFSgihqi1PUDy8CAwEAAQJBAQdUx66rfh8sYsgfdcvV
NoafYpnEcB5s4m/vSVe6SU7dCK6eYec9f9wpT353ljhDUHq3EbmE4foNzJngh35d
AekCIQDhRQG5Li0Wj8TM4obOnnXUXf1jRv0UkzE9AHWLG5q3AwIhAPzSjpYUDjVW
MCUXgckTpKCuGwbJk7424Nb8bLzf3kllAiA5mUBgjfr/WtFSJdWcPQ4Zt9KTMNKD
EUO0ukpTwEIl6wIhAMbGqZK3zAAFdq8DD2jPx+UJXnh0rnOkZBzDtJ6/iN69AiEA
1Aq8MJgTaYsDQWyU/hDq5YkDJc9e9DSCvUIzqxQWMQE=
-----END RSA PRIVATE KEY-----

59
vendor/k8s.io/kubernetes/test/images/porter/pod.json generated vendored Normal file
View file

@ -0,0 +1,59 @@
{
"kind": "Pod",
"apiVersion": "v1",
"metadata": {
"name": "porter"
},
"spec": {
"containers": [
{
"name": "porter",
"image": "gcr.io/google_containers/porter:cd5cb5791ebaa8641955f0e8c2a9bed669b1eaab",
"env": [
{
"name": "SERVE_PORT_80",
"value": "foo"
},
{
"name": "SERVE_PORT_81",
"value": "<html><head></head><body><a href=\"/rewriteme\">rewritten link</a></body></html>"
},
{
"name": "SERVE_TLS_PORT_443",
"value": "tls foo"
},
{
"name": "SERVE_TLS_PORT_444",
"value": "<html><head></head><body><a href=\"/tls-rewriteme\">tls rewritten link</a></body></html>"
},
{
"name": "CERT_FILE",
"value": "/localhost.crt"
},
{
"name": "KEY_FILE",
"value": "/localhost.key"
}
],
"ports": [
{
"name": "p80",
"containerPort": 80
},
{
"name": "p81",
"containerPort": 81
},
{
"name": "p443",
"containerPort": 443
},
{
"name": "p444",
"containerPort": 444
}
]
}
]
}
}

82
vendor/k8s.io/kubernetes/test/images/porter/porter.go generated vendored Normal file
View file

@ -0,0 +1,82 @@
/*
Copyright 2015 The Kubernetes Authors.
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 ports.
//
// Reads env vars; for every var of the form SERVE_PORT_X, where X is a valid
// port number, porter starts an HTTP server which serves the env var's value
// in response to any query.
package main
import (
"fmt"
"log"
"net/http"
"os"
"strings"
)
const prefix = "SERVE_PORT_"
const tlsPrefix = "SERVE_TLS_PORT_"
func main() {
for _, vk := range os.Environ() {
// Put everything before the first = sign in parts[0], and
// everything else in parts[1] (even if there are multiple =
// characters).
parts := strings.SplitN(vk, "=", 2)
key := parts[0]
value := parts[1]
if strings.HasPrefix(key, prefix) {
port := strings.TrimPrefix(key, prefix)
go servePort(port, value)
}
if strings.HasPrefix(key, tlsPrefix) {
port := strings.TrimPrefix(key, tlsPrefix)
go serveTLSPort(port, value)
}
}
select {}
}
func servePort(port, value string) {
s := &http.Server{
Addr: "0.0.0.0:" + port,
Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, value)
}),
}
log.Printf("server on port %q failed: %v", port, s.ListenAndServe())
}
func serveTLSPort(port, value string) {
s := &http.Server{
Addr: "0.0.0.0:" + port,
Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, value)
}),
}
certFile := os.Getenv("CERT_FILE")
if len(certFile) == 0 {
certFile = "localhost.crt"
}
keyFile := os.Getenv("KEY_FILE")
if len(keyFile) == 0 {
keyFile = "localhost.key"
}
log.Printf("tls server on port %q with certFile=%q, keyFile=%q failed: %v", port, certFile, keyFile, s.ListenAndServeTLS(certFile, keyFile))
}

View file

@ -0,0 +1,22 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_binary",
"go_library",
"go_test",
"cgo_library",
)
go_binary(
name = "resource-consumer",
srcs = [
"resource_consumer.go",
"resource_consumer_handler.go",
"utils.go",
],
tags = ["automanaged"],
deps = ["//test/images/resource-consumer/common:go_default_library"],
)

View file

@ -0,0 +1,20 @@
# Copyright 2016 The Kubernetes Authors.
#
# 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 jess/stress
MAINTAINER Ewa Socala <socaa@google.com>
ADD consumer /consumer
ADD consume-cpu /consume-cpu
EXPOSE 8080
ENTRYPOINT ["/consumer"]

View file

@ -0,0 +1,41 @@
# Copyright 2016 The Kubernetes Authors.
#
# 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.
TAG = beta4
PREFIX = gcr.io/google_containers
all: clean consumer
consumer:
CGO_ENABLED=0 go build -a -installsuffix cgo --ldflags '-w' -o consume-cpu/consume-cpu ./consume-cpu/consume_cpu.go
CGO_ENABLED=0 go build -a -installsuffix cgo --ldflags '-w' -o consumer .
CGO_ENABLED=0 go build -a -installsuffix cgo --ldflags '-w' -o controller/controller ./controller/controller.go
container: image
image:
sudo docker build -t $(PREFIX)/resource_consumer:$(TAG) .
sudo docker build -t $(PREFIX)/resource_consumer/controller:$(TAG) controller
run_container:
docker run --publish=8080:8080 $(PREFIX)/resource_consumer:$(TAG)
push:
gcloud docker -- push ${PREFIX}/resource_consumer:${TAG}
gcloud docker -- push ${PREFIX}/resource_consumer/controller:${TAG}
clean:
rm -f consumer
rm -f consume-cpu/consume-cpu
rm -f controller/controller

View file

@ -0,0 +1,85 @@
# Resource Consumer
## Overview
Resource Consumer is a tool which allows to generate cpu/memory utilization in a container.
The reason why it was created is testing kubernetes autoscaling.
Resource Consumer can help with autoscaling tests for:
- cluster size autoscaling,
- horizontal autoscaling of pod - changing the size of replication controller,
- vertical autoscaling of pod - changing its resource limits.
## Usage
Resource Consumer starts an HTTP server and handle sent requests.
It listens on port given as a flag (default 8080).
Action of consuming resources is send to the container by a POST http request.
Each http request creates new process.
Http request handler is in file resource_consumer_handler.go
The container consumes specified amount of resources:
- CPU in millicores,
- Memory in megabytes,
- Fake custom metrics.
###Consume CPU http request
- suffix "ConsumeCPU",
- parameters "millicores" and "durationSec".
Consumes specified amount of millicores for durationSec seconds.
Consume CPU uses "./consume-cpu/consume-cpu" binary (file consume-cpu/consume_cpu.go).
When CPU consumption is too low this binary uses cpu by calculating math.sqrt(0) 10^7 times
and if consumption is too high binary sleeps for 10 millisecond.
One replica of Resource Consumer cannot consume more that 1 cpu.
###Consume Memory http request
- suffix "ConsumeMem",
- parameters "megabytes" and "durationSec".
Consumes specified amount of megabytes for durationSec seconds.
Consume Memory uses stress tool (stress -m 1 --vm-bytes megabytes --vm-hang 0 -t durationSec).
Request leading to consuming more memory then container limit will be ignored.
###Bump value of a fake custom metric
- suffix "BumpMetric",
- parameters "metric", "delta" and "durationSec".
Bumps metric with given name by delta for durationSec seconds.
Custom metrics in Prometheus format are exposed on "/metrics" endpoint.
###CURL example
```console
$ kubectl run resource-consumer --image=gcr.io/google_containers/resource_consumer:beta --expose --service-overrides='{ "spec": { "type": "LoadBalancer" } }' --port 8080
$ kubectl get services resource-consumer
```
There are two IPs. The first one is internal, while the second one is the external load-balanced IP. Both serve port 8080. (Use second one)
```console
$ curl --data "millicores=300&durationSec=600" http://<EXTERNAL-IP>:8080/ConsumeCPU
```
300 millicores will be consumed for 600 seconds.
## Image
Docker image of Resource Consumer can be found in Google Container Registry as gcr.io/google_containers/resource_consumer:beta
## Use cases
###Cluster size autoscaling
1. Consume more resources on each node that is specified for autoscaler
2. Observe that cluster size increased
###Horizontal autoscaling of pod
1. Create consuming RC and start consuming appropriate amount of resources
2. Observe that RC has been resized
3. Observe that usage on each replica decreased
###Vertical autoscaling of pod
1. Create consuming pod and start consuming appropriate amount of resources
2. Observed that limits has been increased
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/test/images/resource-consumer/README.md?pixel)]()

View file

@ -0,0 +1,17 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_binary",
"go_library",
"go_test",
"cgo_library",
)
go_library(
name = "go_default_library",
srcs = ["common.go"],
tags = ["automanaged"],
)

View file

@ -0,0 +1,41 @@
/*
Copyright 2016 The Kubernetes Authors.
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.
*/
package common
const (
ConsumeCPUAddress = "/ConsumeCPU"
ConsumeMemAddress = "/ConsumeMem"
BumpMetricAddress = "/BumpMetric"
GetCurrentStatusAddress = "/GetCurrentStatus"
MetricsAddress = "/Metrics"
MillicoresQuery = "millicores"
MegabytesQuery = "megabytes"
MetricNameQuery = "metric"
DeltaQuery = "delta"
DurationSecQuery = "durationSec"
RequestSizeInMillicoresQuery = "requestSizeMillicores"
RequestSizeInMegabytesQuery = "requestSizeMegabytes"
RequestSizeCustomMetricQuery = "requestSizeMetrics"
BadRequest = "Bad request. Not a POST request"
UnknownFunction = "unknown function"
IncorrectFunctionArgument = "incorrect function argument"
NotGivenFunctionArgument = "not given function argument"
FrameworkName = "horizontal-pod-autoscaling"
)

Some files were not shown because too many files have changed in this diff Show more