Merge remote-tracking branch 'upstream/master'
This commit is contained in:
27
api/swagger-spec/api.json
Normal file
27
api/swagger-spec/api.json
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"swaggerVersion": "1.2",
|
||||||
|
"apiVersion": "",
|
||||||
|
"basePath": "127.0.0.1:8050",
|
||||||
|
"resourcePath": "/api",
|
||||||
|
"apis": [
|
||||||
|
{
|
||||||
|
"path": "/api",
|
||||||
|
"description": "get available api versions",
|
||||||
|
"operations": [
|
||||||
|
{
|
||||||
|
"type": "void",
|
||||||
|
"method": "GET",
|
||||||
|
"summary": "get available api versions",
|
||||||
|
"nickname": "getApiVersions",
|
||||||
|
"parameters": [],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
30
api/swagger-spec/resourceListing.json
Normal file
30
api/swagger-spec/resourceListing.json
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
{
|
||||||
|
"swaggerVersion": "1.2",
|
||||||
|
"apis": [
|
||||||
|
{
|
||||||
|
"path": "/api/v1beta1",
|
||||||
|
"description": "API at /api/v1beta1 version v1beta1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/api/v1beta2",
|
||||||
|
"description": "API at /api/v1beta2 version v1beta2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/api/v1beta3",
|
||||||
|
"description": "API at /api/v1beta3 version v1beta3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/api",
|
||||||
|
"description": "get available api versions"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/version",
|
||||||
|
"description": "git code version from which this is built"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"apiVersion": "",
|
||||||
|
"info": {
|
||||||
|
"title": "",
|
||||||
|
"description": ""
|
||||||
|
}
|
||||||
|
}
|
4247
api/swagger-spec/v1beta1.json
Normal file
4247
api/swagger-spec/v1beta1.json
Normal file
File diff suppressed because it is too large
Load Diff
4226
api/swagger-spec/v1beta2.json
Normal file
4226
api/swagger-spec/v1beta2.json
Normal file
File diff suppressed because it is too large
Load Diff
3812
api/swagger-spec/v1beta3.json
Normal file
3812
api/swagger-spec/v1beta3.json
Normal file
File diff suppressed because it is too large
Load Diff
27
api/swagger-spec/version.json
Normal file
27
api/swagger-spec/version.json
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"swaggerVersion": "1.2",
|
||||||
|
"apiVersion": "",
|
||||||
|
"basePath": "127.0.0.1:8050",
|
||||||
|
"resourcePath": "/version",
|
||||||
|
"apis": [
|
||||||
|
{
|
||||||
|
"path": "/version",
|
||||||
|
"description": "git code version from which this is built",
|
||||||
|
"operations": [
|
||||||
|
{
|
||||||
|
"type": "void",
|
||||||
|
"method": "GET",
|
||||||
|
"summary": "get the code version",
|
||||||
|
"nickname": "getCodeVersion",
|
||||||
|
"parameters": [],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@@ -34,7 +34,7 @@ The `release.sh` script will build a release. It will build binaries, run tests
|
|||||||
|
|
||||||
The main output is a tar file: `kubernetes.tar.gz`. This includes:
|
The main output is a tar file: `kubernetes.tar.gz`. This includes:
|
||||||
* Cross compiled client utilities.
|
* Cross compiled client utilities.
|
||||||
* Script (`cluster/kubecfg.sh`) for picking and running the right client binary based on platform.
|
* Script (`cluster/kubectl.sh`) for picking and running the right client binary based on platform.
|
||||||
* Examples
|
* Examples
|
||||||
* Cluster deployment scripts for various clouds
|
* Cluster deployment scripts for various clouds
|
||||||
* Tar file containing all server binaries
|
* Tar file containing all server binaries
|
||||||
|
@@ -46,3 +46,5 @@ echo "... calling setup-logging-firewall" >&2
|
|||||||
setup-logging-firewall
|
setup-logging-firewall
|
||||||
|
|
||||||
echo "Done" >&2
|
echo "Done" >&2
|
||||||
|
|
||||||
|
exit 0
|
||||||
|
@@ -123,7 +123,7 @@ elif [[ "${KUBERNETES_PROVIDER}" == "gke" ]]; then
|
|||||||
)
|
)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
detect-master &> /dev/null
|
detect-master > /dev/null
|
||||||
if [[ -n "${KUBE_MASTER_IP-}" && -z "${KUBERNETES_MASTER-}" ]]; then
|
if [[ -n "${KUBE_MASTER_IP-}" && -z "${KUBERNETES_MASTER-}" ]]; then
|
||||||
export KUBERNETES_MASTER=https://${KUBE_MASTER_IP}
|
export KUBERNETES_MASTER=https://${KUBE_MASTER_IP}
|
||||||
fi
|
fi
|
||||||
|
@@ -96,7 +96,7 @@ func (fakeKubeletClient) GetPodStatus(host, podNamespace, podID string) (api.Pod
|
|||||||
return r, nil
|
return r, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fakeKubeletClient) HealthCheck(host string) (probe.Status, error) {
|
func (fakeKubeletClient) HealthCheck(host string) (probe.Result, error) {
|
||||||
return probe.Success, nil
|
return probe.Success, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -33,6 +33,7 @@ import (
|
|||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
|
||||||
nodeControllerPkg "github.com/GoogleCloudPlatform/kubernetes/pkg/cloudprovider/controller"
|
nodeControllerPkg "github.com/GoogleCloudPlatform/kubernetes/pkg/cloudprovider/controller"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/controller"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/controller"
|
||||||
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/dockertools"
|
||||||
kubeletServer "github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/server"
|
kubeletServer "github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/server"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/master"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/master"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/master/ports"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/master/ports"
|
||||||
@@ -139,7 +140,7 @@ func startComponents(etcdClient tools.EtcdClient, cl *client.Client, addr net.IP
|
|||||||
runScheduler(cl)
|
runScheduler(cl)
|
||||||
runControllerManager(machineList, cl, *nodeMilliCPU, *nodeMemory)
|
runControllerManager(machineList, cl, *nodeMilliCPU, *nodeMemory)
|
||||||
|
|
||||||
dockerClient := util.ConnectToDockerOrDie(*dockerEndpoint)
|
dockerClient := dockertools.ConnectToDockerOrDie(*dockerEndpoint)
|
||||||
kubeletServer.SimpleRunKubelet(cl, nil, dockerClient, machineList[0], "/tmp/kubernetes", "", "127.0.0.1", 10250, *masterServiceNamespace, kubeletServer.ProbeVolumePlugins())
|
kubeletServer.SimpleRunKubelet(cl, nil, dockerClient, machineList[0], "/tmp/kubernetes", "", "127.0.0.1", 10250, *masterServiceNamespace, kubeletServer.ProbeVolumePlugins())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
4
contrib/git-sync/Dockerfile
Normal file
4
contrib/git-sync/Dockerfile
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
FROM golang:1.4-onbuild
|
||||||
|
VOLUME ["/git"]
|
||||||
|
ENV GIT_SYNC_DEST /git
|
||||||
|
ENTRYPOINT ["/go/bin/git-sync"]
|
16
contrib/git-sync/README.md
Normal file
16
contrib/git-sync/README.md
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
# git-sync
|
||||||
|
|
||||||
|
git-sync is a command that pull a git repository to a local directory.
|
||||||
|
|
||||||
|
It can be used to source a container volume with the content of a git repo.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```
|
||||||
|
# build the container
|
||||||
|
docker build -t git-sync .
|
||||||
|
# run the git-sync container
|
||||||
|
docker run -d GIT_SYNC_REPO=https://github.com/GoogleCloudPlatform/kubernetes -e GIT_SYNC_BRANCH=gh-pages -r HEAD -v /git-data:/git git-sync
|
||||||
|
# run a nginx container to serve sync'ed content
|
||||||
|
docker run -d -p 8080:80 -v /git-data:/usr/share/nginx/html nginx
|
||||||
|
```
|
30
contrib/git-sync/demo/README.md
Normal file
30
contrib/git-sync/demo/README.md
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
# git-blog-demo
|
||||||
|
|
||||||
|
This demo shows how to use the `git-sync` sidekick container along side `volumes` and `volumeMounts` to create a markdown powered blog.
|
||||||
|
|
||||||
|
## How it works
|
||||||
|
|
||||||
|
The pod is composed of 3 containers that share directories using 2 volumes:
|
||||||
|
|
||||||
|
- The `git-sync` container clones a git repo into the `markdown` volume
|
||||||
|
- The `hugo` container read from the `markdown` volume and render it into the `html` volume.
|
||||||
|
- The `nginx` container serve the content from the `html` volume.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Build the demo containers, and push them to a registry
|
||||||
|
|
||||||
|
```
|
||||||
|
docker build -t <some-registry>/git-sync ..
|
||||||
|
docker build -t <some-registry>/hugo hugo/
|
||||||
|
docker push <some-registry>/hugo <some-registry>/git-sync
|
||||||
|
```
|
||||||
|
|
||||||
|
Create the pod and the service for the blog
|
||||||
|
|
||||||
|
```
|
||||||
|
kubectl pods create config/pod.html
|
||||||
|
kubectl services create config/pod.html
|
||||||
|
```
|
||||||
|
|
||||||
|
Open the service external ip in your browser
|
0
contrib/git-sync/demo/blog/archetypes/.keep
Normal file
0
contrib/git-sync/demo/blog/archetypes/.keep
Normal file
3
contrib/git-sync/demo/blog/config.toml
Normal file
3
contrib/git-sync/demo/blog/config.toml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
baseurl = "http://example.com"
|
||||||
|
languageCode = "en-us"
|
||||||
|
title = "example blog"
|
9
contrib/git-sync/demo/blog/content/about.md
Normal file
9
contrib/git-sync/demo/blog/content/about.md
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
+++
|
||||||
|
date = "2014-12-19T15:29:48-08:00"
|
||||||
|
draft = true
|
||||||
|
title = "about"
|
||||||
|
+++
|
||||||
|
|
||||||
|
## A headline
|
||||||
|
|
||||||
|
Some content about the blog.
|
9
contrib/git-sync/demo/blog/content/post/first.md
Normal file
9
contrib/git-sync/demo/blog/content/post/first.md
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
+++
|
||||||
|
date = "2014-12-19T15:30:18-08:00"
|
||||||
|
draft = true
|
||||||
|
title = "first"
|
||||||
|
+++
|
||||||
|
|
||||||
|
## first port
|
||||||
|
|
||||||
|
This is the first post.
|
0
contrib/git-sync/demo/blog/layouts/.keep
Normal file
0
contrib/git-sync/demo/blog/layouts/.keep
Normal file
0
contrib/git-sync/demo/blog/static/.keep
Normal file
0
contrib/git-sync/demo/blog/static/.keep
Normal file
50
contrib/git-sync/demo/config/pod.yaml
Normal file
50
contrib/git-sync/demo/config/pod.yaml
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
id: blog-pod
|
||||||
|
kind: Pod
|
||||||
|
apiVersion: v1beta1
|
||||||
|
desiredState:
|
||||||
|
manifest:
|
||||||
|
version: v1beta1
|
||||||
|
containers:
|
||||||
|
- name: git-sync
|
||||||
|
image: proppy/git-sync
|
||||||
|
imagePullPolicy: PullAlways
|
||||||
|
env::
|
||||||
|
- name: GIT_SYNC_REPO
|
||||||
|
value: https://github.com/proppy/blog.git
|
||||||
|
- name: GIT_SYNC_DEST
|
||||||
|
value: /git
|
||||||
|
volumeMounts:
|
||||||
|
- name: markdown
|
||||||
|
mountPath: /git
|
||||||
|
- name: hugo
|
||||||
|
image: proppy/hugo
|
||||||
|
imagePullPolicy: PullAlways
|
||||||
|
env:
|
||||||
|
- name: SRC
|
||||||
|
value: /src
|
||||||
|
- name: BUILD_DRAFT
|
||||||
|
value: 'true'
|
||||||
|
- name: BASE_URL
|
||||||
|
value: kube.proppy.sh
|
||||||
|
volumeMounts:
|
||||||
|
- name: markdown
|
||||||
|
mountPath: /src
|
||||||
|
- name: html
|
||||||
|
mountPath: /dest
|
||||||
|
- name: nginx
|
||||||
|
image: nginx
|
||||||
|
volumeMounts:
|
||||||
|
- name: html
|
||||||
|
mountPath: /usr/share/nginx/html
|
||||||
|
ports:
|
||||||
|
- name: http-server
|
||||||
|
containerPort: 80
|
||||||
|
volumes:
|
||||||
|
- name: markdown
|
||||||
|
source:
|
||||||
|
emptyDir: {}
|
||||||
|
- name: html
|
||||||
|
source:
|
||||||
|
emptyDir: {}
|
||||||
|
labels:
|
||||||
|
name: blog
|
8
contrib/git-sync/demo/config/service.yaml
Normal file
8
contrib/git-sync/demo/config/service.yaml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
id: blog-service
|
||||||
|
kind: Service
|
||||||
|
apiVersion: v1beta1
|
||||||
|
port: 80
|
||||||
|
containerPort: http-server
|
||||||
|
selector:
|
||||||
|
name: blog
|
||||||
|
createExternalLoadBalancer: true
|
13
contrib/git-sync/demo/hugo/Dockerfile
Normal file
13
contrib/git-sync/demo/hugo/Dockerfile
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
FROM golang
|
||||||
|
RUN go get -v github.com/spf13/hugo
|
||||||
|
RUN git clone --recursive https://github.com/spf13/hugoThemes.git /themes
|
||||||
|
VOLUME ["/src", "/dest"]
|
||||||
|
EXPOSE 1313
|
||||||
|
ENV SRC /src
|
||||||
|
ENV DEST /dest
|
||||||
|
ENV THEME hyde
|
||||||
|
ENV BUILD_DRAFT false
|
||||||
|
ENV BASE_URL ""
|
||||||
|
ADD run-hugo /run-hugo
|
||||||
|
ENTRYPOINT ["/run-hugo"]
|
||||||
|
CMD ["server", "--source=${SRC}", "--theme=${THEME}", "--buildDrafts=${BUILD_DRAFT}", "--baseUrl=${BASE_URL}", "--watch", "--destination=${DEST}", "--appendPort=false"]
|
@@ -14,12 +14,8 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
set -o errexit
|
set -ex
|
||||||
set -o nounset
|
if [ ! -d ${SRC}/themes ]; then
|
||||||
set -o pipefail
|
ln -s /themes ${SRC}/themes
|
||||||
|
fi
|
||||||
KUBE_ROOT=$(dirname "${BASH_SOURCE}")/..
|
hugo $(eval echo $*) # force default CMD env expansion
|
||||||
source "${KUBE_ROOT}/cluster/kube-env.sh"
|
|
||||||
source "${KUBE_ROOT}/cluster/${KUBERNETES_PROVIDER}/util.sh"
|
|
||||||
|
|
||||||
${KUBE_ROOT}/hack/e2e-suite/goe2e.sh -tTestNetwork
|
|
112
contrib/git-sync/main.go
Normal file
112
contrib/git-sync/main.go
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2014 Google Inc. All rights reserved.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// git-sync is a command that pull a git repository to a local directory.
|
||||||
|
|
||||||
|
package main // import "github.com/GoogleCloudPlatform/kubernetes/contrib/git-sync"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"path"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var flRepo = flag.String("repo", envString("GIT_SYNC_REPO", ""), "git repo url")
|
||||||
|
var flBranch = flag.String("branch", envString("GIT_SYNC_BRANCH", "master"), "git branch")
|
||||||
|
var flRev = flag.String("rev", envString("GIT_SYNC_BRANCH", "HEAD"), "git rev")
|
||||||
|
var flDest = flag.String("dest", envString("GIT_SYNC_DEST", ""), "destination path")
|
||||||
|
var flWait = flag.Int("wait", envInt("GIT_SYNC_WAIT", 0), "number of seconds to wait before exit")
|
||||||
|
|
||||||
|
func envString(key, def string) string {
|
||||||
|
if env := os.Getenv(key); env != "" {
|
||||||
|
return env
|
||||||
|
}
|
||||||
|
return def
|
||||||
|
}
|
||||||
|
|
||||||
|
func envInt(key string, def int) int {
|
||||||
|
if env := os.Getenv(key); env != "" {
|
||||||
|
val, err := strconv.Atoi(env)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("invalid value for %q: using default: %q", key, def)
|
||||||
|
return def
|
||||||
|
}
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
return def
|
||||||
|
}
|
||||||
|
|
||||||
|
const usage = "usage: GIT_SYNC_REPO= GIT_SYNC_DEST= [GIT_SYNC_BRANCH= GIT_SYNC_WAIT=] git-sync -repo GIT_REPO_URL -dest PATH [-branch -wait]"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
flag.Parse()
|
||||||
|
if *flRepo == "" || *flDest == "" {
|
||||||
|
flag.Usage()
|
||||||
|
log.Fatal(usage)
|
||||||
|
}
|
||||||
|
if _, err := exec.LookPath("git"); err != nil {
|
||||||
|
log.Fatalf("required git executable not found: %v", err)
|
||||||
|
}
|
||||||
|
if err := syncRepo(*flRepo, *flDest, *flBranch, *flRev); err != nil {
|
||||||
|
log.Fatalf("error syncing repo: %v", err)
|
||||||
|
}
|
||||||
|
log.Printf("wait %d seconds", *flWait)
|
||||||
|
time.Sleep(time.Duration(*flWait) * time.Second)
|
||||||
|
log.Println("done")
|
||||||
|
}
|
||||||
|
|
||||||
|
// syncRepo syncs the branch of a given repository to the destination at the given rev.
|
||||||
|
func syncRepo(repo, dest, branch, rev string) error {
|
||||||
|
gitRepoPath := path.Join(dest, ".git")
|
||||||
|
_, err := os.Stat(gitRepoPath)
|
||||||
|
switch {
|
||||||
|
case os.IsNotExist(err):
|
||||||
|
// clone repo
|
||||||
|
cmd := exec.Command("git", "clone", "--no-checkout", "-b", branch, repo, dest)
|
||||||
|
output, err := cmd.CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error cloning repo %q: %v: %s", strings.Join(cmd.Args, " "), err, string(output))
|
||||||
|
}
|
||||||
|
log.Printf("clone %q: %s", repo, string(output))
|
||||||
|
case err != nil:
|
||||||
|
return fmt.Errorf("error checking if repo exist %q: %v", gitRepoPath, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// fetch branch
|
||||||
|
cmd := exec.Command("git", "fetch", "origin", branch)
|
||||||
|
cmd.Dir = dest
|
||||||
|
output, err := cmd.CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error running command %q: %v: %s", strings.Join(cmd.Args, " "), err, string(output))
|
||||||
|
}
|
||||||
|
log.Printf("fetch %q: %s", branch, string(output))
|
||||||
|
|
||||||
|
// reset working copy
|
||||||
|
cmd = exec.Command("git", "reset", "--hard", rev)
|
||||||
|
cmd.Dir = dest
|
||||||
|
output, err = cmd.CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error running command %q : %v: %s", strings.Join(cmd.Args, " "), err, string(output))
|
||||||
|
}
|
||||||
|
log.Printf("reset %q: %v", rev, string(output))
|
||||||
|
return nil
|
||||||
|
}
|
@@ -7,15 +7,15 @@ EnvironmentFile=-/etc/kubernetes/config
|
|||||||
EnvironmentFile=-/etc/kubernetes/apiserver
|
EnvironmentFile=-/etc/kubernetes/apiserver
|
||||||
User=kube
|
User=kube
|
||||||
ExecStart=/usr/bin/kube-apiserver \
|
ExecStart=/usr/bin/kube-apiserver \
|
||||||
${KUBE_LOGTOSTDERR} \
|
$KUBE_LOGTOSTDERR \
|
||||||
${KUBE_LOG_LEVEL} \
|
$KUBE_LOG_LEVEL \
|
||||||
${KUBE_ETCD_SERVERS} \
|
$KUBE_ETCD_SERVERS \
|
||||||
${KUBE_API_ADDRESS} \
|
$KUBE_API_ADDRESS \
|
||||||
${KUBE_API_PORT} \
|
$KUBE_API_PORT \
|
||||||
${KUBELET_PORT} \
|
$KUBELET_PORT \
|
||||||
${KUBE_ALLOW_PRIV} \
|
$KUBE_ALLOW_PRIV \
|
||||||
${KUBE_SERVICE_ADDRESSES} \
|
$KUBE_SERVICE_ADDRESSES \
|
||||||
${KUBE_API_ARGS}
|
$KUBE_API_ARGS
|
||||||
Restart=on-failure
|
Restart=on-failure
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
|
@@ -8,11 +8,11 @@ EnvironmentFile=-/etc/kubernetes/apiserver
|
|||||||
EnvironmentFile=-/etc/kubernetes/controller-manager
|
EnvironmentFile=-/etc/kubernetes/controller-manager
|
||||||
User=kube
|
User=kube
|
||||||
ExecStart=/usr/bin/kube-controller-manager \
|
ExecStart=/usr/bin/kube-controller-manager \
|
||||||
${KUBE_LOGTOSTDERR} \
|
$KUBE_LOGTOSTDERR \
|
||||||
${KUBE_LOG_LEVEL} \
|
$KUBE_LOG_LEVEL \
|
||||||
${KUBELET_ADDRESSES} \
|
$KUBELET_ADDRESSES \
|
||||||
${KUBE_MASTER} \
|
$KUBE_MASTER \
|
||||||
${KUBE_CONTROLLER_MANAGER_ARGS}
|
$KUBE_CONTROLLER_MANAGER_ARGS
|
||||||
Restart=on-failure
|
Restart=on-failure
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
|
@@ -6,10 +6,10 @@ Documentation=https://github.com/GoogleCloudPlatform/kubernetes
|
|||||||
EnvironmentFile=-/etc/kubernetes/config
|
EnvironmentFile=-/etc/kubernetes/config
|
||||||
EnvironmentFile=-/etc/kubernetes/proxy
|
EnvironmentFile=-/etc/kubernetes/proxy
|
||||||
ExecStart=/usr/bin/kube-proxy \
|
ExecStart=/usr/bin/kube-proxy \
|
||||||
${KUBE_LOGTOSTDERR} \
|
$KUBE_LOGTOSTDERR \
|
||||||
${KUBE_LOG_LEVEL} \
|
$KUBE_LOG_LEVEL \
|
||||||
${KUBE_ETCD_SERVERS} \
|
$KUBE_ETCD_SERVERS \
|
||||||
${KUBE_PROXY_ARGS}
|
$KUBE_PROXY_ARGS
|
||||||
Restart=on-failure
|
Restart=on-failure
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
|
@@ -8,10 +8,10 @@ EnvironmentFile=-/etc/kubernetes/apiserver
|
|||||||
EnvironmentFile=-/etc/kubernetes/scheduler
|
EnvironmentFile=-/etc/kubernetes/scheduler
|
||||||
User=kube
|
User=kube
|
||||||
ExecStart=/usr/bin/kube-scheduler \
|
ExecStart=/usr/bin/kube-scheduler \
|
||||||
${KUBE_LOGTOSTDERR} \
|
$KUBE_LOGTOSTDERR \
|
||||||
${KUBE_LOG_LEVEL} \
|
$KUBE_LOG_LEVEL \
|
||||||
${KUBE_MASTER} \
|
$KUBE_MASTER \
|
||||||
${KUBE_SCHEDULER_ARGS}
|
$KUBE_SCHEDULER_ARGS
|
||||||
Restart=on-failure
|
Restart=on-failure
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
|
@@ -9,14 +9,14 @@ WorkingDirectory=/var/lib/kubelet
|
|||||||
EnvironmentFile=-/etc/kubernetes/config
|
EnvironmentFile=-/etc/kubernetes/config
|
||||||
EnvironmentFile=-/etc/kubernetes/kubelet
|
EnvironmentFile=-/etc/kubernetes/kubelet
|
||||||
ExecStart=/usr/bin/kubelet \
|
ExecStart=/usr/bin/kubelet \
|
||||||
${KUBE_LOGTOSTDERR} \
|
$KUBE_LOGTOSTDERR \
|
||||||
${KUBE_LOG_LEVEL} \
|
$KUBE_LOG_LEVEL \
|
||||||
${KUBE_ETCD_SERVERS} \
|
$KUBE_ETCD_SERVERS \
|
||||||
${KUBELET_ADDRESS} \
|
$KUBELET_ADDRESS \
|
||||||
${KUBELET_PORT} \
|
$KUBELET_PORT \
|
||||||
${KUBELET_HOSTNAME} \
|
$KUBELET_HOSTNAME \
|
||||||
${KUBE_ALLOW_PRIV} \
|
$KUBE_ALLOW_PRIV \
|
||||||
${KUBELET_ARGS}
|
$KUBELET_ARGS
|
||||||
Restart=on-failure
|
Restart=on-failure
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
|
@@ -14,7 +14,7 @@ The example below creates an elastic Kubernetes cluster with 3 worker nodes and
|
|||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
* [kubecfg CLI](aws/kubecfg.md)
|
* [kubectl CLI](aws/kubectl.md)
|
||||||
* [aws CLI](http://aws.amazon.com/cli)
|
* [aws CLI](http://aws.amazon.com/cli)
|
||||||
* [CoreOS image for AWS](https://coreos.com/docs/running-coreos/cloud-providers/ec2/#choosing-a-channel)
|
* [CoreOS image for AWS](https://coreos.com/docs/running-coreos/cloud-providers/ec2/#choosing-a-channel)
|
||||||
|
|
||||||
@@ -42,7 +42,7 @@ aws cloudformation describe-stack-events --stack-name kubernetes
|
|||||||
aws cloudformation describe-stacks --stack-name kubernetes
|
aws cloudformation describe-stacks --stack-name kubernetes
|
||||||
```
|
```
|
||||||
|
|
||||||
[Skip to kubecfg client configuration](#configure-the-kubecfg-ssh-tunnel)
|
[Skip to kubectl client configuration](#configure-the-kubectl-ssh-tunnel)
|
||||||
|
|
||||||
### Manually
|
### Manually
|
||||||
|
|
||||||
@@ -121,9 +121,9 @@ aws ec2 run-instances --count 1 --image-id <ami_image_id> --key-name <keypair> \
|
|||||||
--user-data file://node.yaml
|
--user-data file://node.yaml
|
||||||
```
|
```
|
||||||
|
|
||||||
### Configure the kubecfg SSH tunnel
|
### Configure the kubectl SSH tunnel
|
||||||
|
|
||||||
This command enables secure communication between the kubecfg client and the Kubernetes API.
|
This command enables secure communication between the kubectl client and the Kubernetes API.
|
||||||
|
|
||||||
```
|
```
|
||||||
ssh -f -nNT -L 8080:127.0.0.1:8080 core@<master-public-ip>
|
ssh -f -nNT -L 8080:127.0.0.1:8080 core@<master-public-ip>
|
||||||
@@ -134,7 +134,7 @@ ssh -f -nNT -L 8080:127.0.0.1:8080 core@<master-public-ip>
|
|||||||
Once the worker instances have fully booted, they will be automatically registered with the Kubernetes API server by the kube-register service running on the master node. It may take a few mins.
|
Once the worker instances have fully booted, they will be automatically registered with the Kubernetes API server by the kube-register service running on the master node. It may take a few mins.
|
||||||
|
|
||||||
```
|
```
|
||||||
kubecfg list minions
|
kubectl get nodes
|
||||||
```
|
```
|
||||||
|
|
||||||
## Starting a simple pod
|
## Starting a simple pod
|
||||||
@@ -167,16 +167,16 @@ Create a pod manifest: `pod.json`
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Create the pod using the kubecfg command line tool
|
### Create the pod using the kubectl command line tool
|
||||||
|
|
||||||
```
|
```
|
||||||
kubecfg -c pod.json create pods
|
kubectl create -f pod.json
|
||||||
```
|
```
|
||||||
|
|
||||||
### Testing
|
### Testing
|
||||||
|
|
||||||
```
|
```
|
||||||
kubecfg list pods
|
kubectl get pods
|
||||||
```
|
```
|
||||||
|
|
||||||
> Record the **Host** of the pod, which should be the private IP address.
|
> Record the **Host** of the pod, which should be the private IP address.
|
||||||
@@ -208,5 +208,5 @@ Visit the public IP address in your browser to view the running pod.
|
|||||||
### Delete the pod
|
### Delete the pod
|
||||||
|
|
||||||
```
|
```
|
||||||
kubecfg delete pods/hello
|
kubectl delete pods hello
|
||||||
```
|
```
|
||||||
|
@@ -247,7 +247,7 @@
|
|||||||
" ExecStart=/opt/bin/kube-apiserver \\\n",
|
" ExecStart=/opt/bin/kube-apiserver \\\n",
|
||||||
" --address=0.0.0.0 \\\n",
|
" --address=0.0.0.0 \\\n",
|
||||||
" --port=8080 \\\n",
|
" --port=8080 \\\n",
|
||||||
" --portal_net 10.244.0.0/16 \\\n",
|
" --portal_net=10.244.0.0/16 \\\n",
|
||||||
" --etcd_servers=http://127.0.0.1:4001 \\\n",
|
" --etcd_servers=http://127.0.0.1:4001 \\\n",
|
||||||
" --public_address_override=$private_ipv4 \\\n",
|
" --public_address_override=$private_ipv4 \\\n",
|
||||||
" --logtostderr=true\n",
|
" --logtostderr=true\n",
|
||||||
|
@@ -1,28 +0,0 @@
|
|||||||
# Install and configure kubecfg
|
|
||||||
|
|
||||||
## Download the kubecfg CLI tool
|
|
||||||
|
|
||||||
### Darwin
|
|
||||||
|
|
||||||
```
|
|
||||||
wget http://storage.googleapis.com/k8s/darwin/kubecfg
|
|
||||||
```
|
|
||||||
|
|
||||||
### Linux
|
|
||||||
|
|
||||||
```
|
|
||||||
wget http://storage.googleapis.com/k8s/linux/kubecfg
|
|
||||||
```
|
|
||||||
|
|
||||||
### Copy kubecfg to your path
|
|
||||||
|
|
||||||
```
|
|
||||||
chmod +x kubecfg
|
|
||||||
mv kubecfg /usr/local/bin/
|
|
||||||
```
|
|
||||||
|
|
||||||
### Create a secure tunnel for API communication
|
|
||||||
|
|
||||||
```
|
|
||||||
ssh -f -nNT -L 8080:127.0.0.1:8080 core@<master-public-ip>
|
|
||||||
```
|
|
28
docs/getting-started-guides/aws/kubectl.md
Normal file
28
docs/getting-started-guides/aws/kubectl.md
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
# Install and configure kubecfg
|
||||||
|
|
||||||
|
## Download the kubecfg CLI tool
|
||||||
|
|
||||||
|
### Darwin
|
||||||
|
|
||||||
|
```
|
||||||
|
wget https://storage.googleapis.com/kubernetes-release/release/v0.9.2/bin/darwin/amd64/kubectl
|
||||||
|
```
|
||||||
|
|
||||||
|
### Linux
|
||||||
|
|
||||||
|
```
|
||||||
|
wget https://storage.googleapis.com/kubernetes-release/release/v0.9.2/bin/linux/amd64/kubectl
|
||||||
|
```
|
||||||
|
|
||||||
|
### Copy kubectl to your path
|
||||||
|
|
||||||
|
```
|
||||||
|
chmod +x kubectl
|
||||||
|
mv kubectl /usr/local/bin/
|
||||||
|
```
|
||||||
|
|
||||||
|
### Create a secure tunnel for API communication
|
||||||
|
|
||||||
|
```
|
||||||
|
ssh -f -nNT -L 8080:127.0.0.1:8080 core@<master-public-ip>
|
||||||
|
```
|
@@ -34,21 +34,26 @@ can tweak some of these parameters by editing `cluster/azure/config-default.sh`.
|
|||||||
|
|
||||||
### Running a container (simple version)
|
### Running a container (simple version)
|
||||||
|
|
||||||
The `cluster/kubecfg.sh` command below spins up two containers, running [Nginx](http://nginx.org/en/) and with port 80 mapped to 8080:
|
Once you have your instances up and running, the `hack/build-go.sh` script sets up
|
||||||
|
your Go workspace and builds the Go components.
|
||||||
|
|
||||||
```
|
The `kubectl.sh` line below spins up two containers running
|
||||||
cd kubernetes
|
[Nginx](http://nginx.org/en/) running on port 80:
|
||||||
cluster/kubecfg.sh -p 8080:80 run dockerfile/nginx 2 myNginx
|
|
||||||
|
```bash
|
||||||
|
cluster/kubectl.sh run-container my-nginx --image=dockerfile/nginx --replicas=2 --port=80
|
||||||
```
|
```
|
||||||
|
|
||||||
To stop the containers:
|
To stop the containers:
|
||||||
```
|
|
||||||
cluster/kubecfg.sh stop myNginx
|
```bash
|
||||||
|
cluster/kubectl.sh stop rc my-nginx
|
||||||
```
|
```
|
||||||
|
|
||||||
To delete the containers:
|
To delete the containers:
|
||||||
```
|
|
||||||
cluster/kubecfg.sh rm myNginx
|
```bash
|
||||||
|
cluster/kubectl.sh delete rc my-nginx
|
||||||
```
|
```
|
||||||
|
|
||||||
### Running a container (more complete version)
|
### Running a container (more complete version)
|
||||||
|
@@ -50,23 +50,23 @@ field values:
|
|||||||
Once you have your instances up and running, the `hack/build-go.sh` script sets up
|
Once you have your instances up and running, the `hack/build-go.sh` script sets up
|
||||||
your Go workspace and builds the Go components.
|
your Go workspace and builds the Go components.
|
||||||
|
|
||||||
The `kubecfg.sh` line below spins up two containers running
|
The `kubectl.sh` line below spins up two containers running
|
||||||
[Nginx](http://nginx.org/en/) with port 80 mapped to 8080:
|
[Nginx](http://nginx.org/en/) running on port 80:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cluster/kubecfg.sh -p 8080:80 run dockerfile/nginx 2 myNginx
|
cluster/kubectl.sh run-container my-nginx --image=dockerfile/nginx --replicas=2 --port=80
|
||||||
```
|
```
|
||||||
|
|
||||||
To stop the containers:
|
To stop the containers:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cluster/kubecfg.sh stop myNginx
|
cluster/kubectl.sh stop rc my-nginx
|
||||||
```
|
```
|
||||||
|
|
||||||
To delete the containers:
|
To delete the containers:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cluster/kubecfg.sh rm myNginx
|
cluster/kubectl.sh delete rc my-nginx
|
||||||
```
|
```
|
||||||
|
|
||||||
### Running a container (more complete version)
|
### Running a container (more complete version)
|
||||||
|
@@ -30,7 +30,7 @@ hack/local-up-cluster.sh
|
|||||||
This will build and start a lightweight local cluster, consisting of a master
|
This will build and start a lightweight local cluster, consisting of a master
|
||||||
and a single minion. Type Control-C to shut it down.
|
and a single minion. Type Control-C to shut it down.
|
||||||
|
|
||||||
You can use the cluster/kubecfg.sh script to interact with the local cluster.
|
You can use the cluster/kubectl.sh script to interact with the local cluster.
|
||||||
You must set the KUBERNETES_PROVIDER and KUBERNETES_MASTER environment variables to let other programs
|
You must set the KUBERNETES_PROVIDER and KUBERNETES_MASTER environment variables to let other programs
|
||||||
know how to reach your master.
|
know how to reach your master.
|
||||||
|
|
||||||
@@ -43,13 +43,13 @@ export KUBERNETES_MASTER=http://localhost:8080
|
|||||||
|
|
||||||
Your cluster is running, and you want to start running containers!
|
Your cluster is running, and you want to start running containers!
|
||||||
|
|
||||||
You can now use any of the cluster/kubecfg.sh commands to interact with your local setup.
|
You can now use any of the cluster/kubectl.sh commands to interact with your local setup.
|
||||||
|
|
||||||
```
|
```
|
||||||
cluster/kubectl.sh get pods
|
cluster/kubectl.sh get pods
|
||||||
cluster/kubectl.sh get services
|
cluster/kubectl.sh get services
|
||||||
cluster/kubectl.sh get replicationControllers
|
cluster/kubectl.sh get replicationControllers
|
||||||
cluster/kubecfg.sh -p 8081:80 run dockerfile/nginx 1 myNginx
|
cluster/kubectl.sh run-container my-nginx --image=dockerfile/nginx --replicas=2 --port=80
|
||||||
|
|
||||||
|
|
||||||
## begin wait for provision to complete, you can monitor the docker pull by opening a new terminal
|
## begin wait for provision to complete, you can monitor the docker pull by opening a new terminal
|
||||||
|
@@ -25,7 +25,7 @@ $ sudo ./util.sh
|
|||||||
|
|
||||||
After this the kubernetes and `etcd` services would be up and running. You can use `service start/stop/restart/force-reload` on the services.
|
After this the kubernetes and `etcd` services would be up and running. You can use `service start/stop/restart/force-reload` on the services.
|
||||||
|
|
||||||
Launching and scheduling containers using kubecfg can also be used at this point, as explained mentioned in the [examples](https://github.com/GoogleCloudPlatform/kubernetes/tree/master/examples/guestbook)
|
Launching and scheduling containers using kubectl can also be used at this point, as explained mentioned in the [examples](https://github.com/GoogleCloudPlatform/kubernetes/tree/master/examples/guestbook)
|
||||||
|
|
||||||
### 3. Customizing the ubuntu launch
|
### 3. Customizing the ubuntu launch
|
||||||
To customize the defaults you will need to tweak `/etc/default/kube*` files and restart the appropriate services. This is needed if the binaries are copied in a place other than `/opt/bin`. A run could look like
|
To customize the defaults you will need to tweak `/etc/default/kube*` files and restart the appropriate services. This is needed if the binaries are copied in a place other than `/opt/bin`. A run could look like
|
||||||
|
@@ -178,10 +178,9 @@ NAME IMAGE(S SELECTOR REPLICAS
|
|||||||
```
|
```
|
||||||
|
|
||||||
Start a container running nginx with a replication controller and three replicas
|
Start a container running nginx with a replication controller and three replicas
|
||||||
(note that this step uses the `kubecfg.sh` command instead of `kubectl.sh`):
|
|
||||||
|
|
||||||
```
|
```
|
||||||
$ cluster/kubecfg.sh -p 8080:80 run dockerfile/nginx 3 myNginx
|
$ cluster/kubectl.sh run-container my-nginx --image=dockerfile/nginx --replicas=3 --port=80
|
||||||
```
|
```
|
||||||
|
|
||||||
When listing the pods, you will see that three containers have been started and are in Waiting state:
|
When listing the pods, you will see that three containers have been started and are in Waiting state:
|
||||||
@@ -231,7 +230,7 @@ NAME LABELS SELECTOR IP PORT
|
|||||||
|
|
||||||
$ cluster/kubectl.sh get replicationControllers
|
$ cluster/kubectl.sh get replicationControllers
|
||||||
NAME IMAGE(S SELECTOR REPLICAS
|
NAME IMAGE(S SELECTOR REPLICAS
|
||||||
myNginx dockerfile/nginx name=myNginx 3
|
myNginx dockerfile/nginx name=my-nginx 3
|
||||||
```
|
```
|
||||||
|
|
||||||
We did not start any services, hence there are none listed. But we see three replicas displayed properly.
|
We did not start any services, hence there are none listed. But we see three replicas displayed properly.
|
||||||
@@ -239,7 +238,7 @@ Check the [guestbook](../../examples/guestbook/README.md) application to learn h
|
|||||||
You can already play with resizing the replicas with:
|
You can already play with resizing the replicas with:
|
||||||
|
|
||||||
```
|
```
|
||||||
$ cluster/kubecfg.sh resize myNginx 2
|
$ cluster/kubectl.sh resize rc my-nginx --replicas=2
|
||||||
$ cluster/kubectl.sh get pods
|
$ cluster/kubectl.sh get pods
|
||||||
NAME IMAGE(S) HOST LABELS STATUS
|
NAME IMAGE(S) HOST LABELS STATUS
|
||||||
7813c8bd-3ffe-11e4-9036-0800279696e1 dockerfile/nginx 10.245.2.2/10.245.2.2 name=myNginx Running
|
7813c8bd-3ffe-11e4-9036-0800279696e1 dockerfile/nginx 10.245.2.2/10.245.2.2 name=myNginx Running
|
||||||
|
@@ -73,7 +73,8 @@ Usage:
|
|||||||
--v=0: log level for V logs
|
--v=0: log level for V logs
|
||||||
--validate=false: If true, use a schema to validate the input before sending it
|
--validate=false: If true, use a schema to validate the input before sending it
|
||||||
--vmodule=: comma-separated list of pattern=N settings for file-filtered logging
|
--vmodule=: comma-separated list of pattern=N settings for file-filtered logging
|
||||||
-w, --www="": Also serve static files from the given directory under the prefix /static
|
-w, --www="": Also serve static files from the given directory under the specified prefix
|
||||||
|
-P, --www-prefix="/static/": Prefix to serve static files under, if static file dir is specified
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -337,7 +338,7 @@ Usage:
|
|||||||
kubectl config [command]
|
kubectl config [command]
|
||||||
|
|
||||||
Available Commands:
|
Available Commands:
|
||||||
view displays the specified .kubeconfig file or a merged result
|
view displays merged .kubeconfig settings or a specified .kubeconfig file.
|
||||||
set-cluster name [--server=server] [--certificate-authority=path/to/certficate/authority] [--api-version=apiversion] [--insecure-skip-tls-verify=true] Sets a cluster entry in .kubeconfig
|
set-cluster name [--server=server] [--certificate-authority=path/to/certficate/authority] [--api-version=apiversion] [--insecure-skip-tls-verify=true] Sets a cluster entry in .kubeconfig
|
||||||
set-credentials name [--auth-path=path/to/auth/file] [--client-certificate=path/to/certficate/file] [--client-key=path/to/key/file] [--token=bearer_token_string] Sets a user entry in .kubeconfig
|
set-credentials name [--auth-path=path/to/auth/file] [--client-certificate=path/to/certficate/file] [--client-key=path/to/key/file] [--token=bearer_token_string] Sets a user entry in .kubeconfig
|
||||||
set-context name [--cluster=cluster-nickname] [--user=user-nickname] [--namespace=namespace] Sets a context entry in .kubeconfig
|
set-context name [--cluster=cluster-nickname] [--user=user-nickname] [--namespace=namespace] Sets a context entry in .kubeconfig
|
||||||
@@ -394,7 +395,13 @@ Use "kubectl help [command]" for more information about that command.
|
|||||||
```
|
```
|
||||||
|
|
||||||
#### config view
|
#### config view
|
||||||
displays the specified .kubeconfig file or a merged result
|
displays merged .kubeconfig settings or a specified .kubeconfig file.
|
||||||
|
Examples:
|
||||||
|
// Show merged .kubeconfig settings.
|
||||||
|
$ kubectl config view
|
||||||
|
|
||||||
|
// Show only local ./.kubeconfig settings
|
||||||
|
$ kubectl config view --local
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
```
|
```
|
||||||
@@ -420,10 +427,14 @@ Usage:
|
|||||||
--log_flush_frequency=5s: Maximum number of seconds between log flushes
|
--log_flush_frequency=5s: Maximum number of seconds between log flushes
|
||||||
--logtostderr=true: log to standard error instead of files
|
--logtostderr=true: log to standard error instead of files
|
||||||
--match-server-version=false: Require server version to match client version
|
--match-server-version=false: Require server version to match client version
|
||||||
--merge=false: merge together the full hierarchy of .kubeconfig files
|
--merge=true: merge together the full hierarchy of .kubeconfig files
|
||||||
--namespace="": If present, the namespace scope for this CLI request.
|
--namespace="": If present, the namespace scope for this CLI request.
|
||||||
|
--no-headers=false: When using the default output, don't print headers
|
||||||
|
-o, --output="": Output format: json|yaml|template|templatefile
|
||||||
|
--output-version="": Output the formatted object with the given version (default api-version)
|
||||||
-s, --server="": The address of the Kubernetes API server
|
-s, --server="": The address of the Kubernetes API server
|
||||||
--stderrthreshold=2: logs at or above this threshold go to stderr
|
--stderrthreshold=2: logs at or above this threshold go to stderr
|
||||||
|
-t, --template="": Template string or path to template file to use when -o=template or -o=templatefile.
|
||||||
--token="": Bearer token for authentication to the API server.
|
--token="": Bearer token for authentication to the API server.
|
||||||
--user="": The name of the kubeconfig user to use
|
--user="": The name of the kubeconfig user to use
|
||||||
--v=0: log level for V logs
|
--v=0: log level for V logs
|
||||||
|
@@ -11,6 +11,15 @@ key/value labels set on it, with at most one label with a particular key.
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
While there are no restrictions on the format of label values, label keys must be of the form:
|
||||||
|
```
|
||||||
|
label-key ::= prefixed-name | name
|
||||||
|
prefixed-name ::= prefix '/' name
|
||||||
|
prefix ::= DNS_SUBDOMAIN
|
||||||
|
name ::= DNS_LABEL
|
||||||
|
```
|
||||||
|
DNS_LABEL and DNS_SUBDOMAIN are defined in the [identifiers design doc](/docs/design/identifiers.md). The prefix is optional. If the prefix is not specified, the key is assumed to be private to the user. Other system components that wish to use labels must specify a prefix. The "kubernetes.io/" prefix is reserved for use by kubernetes components.
|
||||||
|
|
||||||
Unlike [names and UIDs](identifiers.md), labels do not provide uniqueness. In general, we expect many objects to carry the same label(s).
|
Unlike [names and UIDs](identifiers.md), labels do not provide uniqueness. In general, we expect many objects to carry the same label(s).
|
||||||
|
|
||||||
Via a _label selector_, the client/user can identify a set of objects. The label selector is the core grouping primitive in Kubernetes.
|
Via a _label selector_, the client/user can identify a set of objects. The label selector is the core grouping primitive in Kubernetes.
|
||||||
|
@@ -6,7 +6,7 @@ The example combines a web frontend, a redis master for storage and a replicated
|
|||||||
|
|
||||||
### Step Zero: Prerequisites
|
### Step Zero: Prerequisites
|
||||||
|
|
||||||
This example assumes that have a basic understanding of kubernetes services and that you have forked the repository and [turned up a Kubernetes cluster](https://github.com/GoogleCloudPlatform/kubernetes#contents):
|
This example assumes that you have a basic understanding of kubernetes services and that you have forked the repository and [turned up a Kubernetes cluster](https://github.com/GoogleCloudPlatform/kubernetes#contents):
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
$ cd kubernetes
|
$ cd kubernetes
|
||||||
|
@@ -22,8 +22,17 @@ set -o nounset
|
|||||||
set -o pipefail
|
set -o pipefail
|
||||||
|
|
||||||
KUBE_ROOT=$(dirname "${BASH_SOURCE}")/../..
|
KUBE_ROOT=$(dirname "${BASH_SOURCE}")/../..
|
||||||
|
|
||||||
|
: ${KUBE_VERSION_ROOT:=${KUBE_ROOT}}
|
||||||
|
: ${KUBECTL:="${KUBE_VERSION_ROOT}/cluster/kubectl.sh"}
|
||||||
|
: ${KUBE_CONFIG_FILE:="config-test.sh"}
|
||||||
|
|
||||||
|
export KUBECTL KUBE_CONFIG_FILE
|
||||||
|
|
||||||
source "${KUBE_ROOT}/cluster/kube-env.sh"
|
source "${KUBE_ROOT}/cluster/kube-env.sh"
|
||||||
source "${KUBE_ROOT}/cluster/${KUBERNETES_PROVIDER}/util.sh"
|
source "${KUBE_VERSION_ROOT}/cluster/${KUBERNETES_PROVIDER}/util.sh"
|
||||||
|
|
||||||
|
prepare-e2e
|
||||||
|
|
||||||
if [[ "${KUBERNETES_PROVIDER}" != "gce" ]] && [[ "${KUBERNETES_PROVIDER}" != "gke" ]]; then
|
if [[ "${KUBERNETES_PROVIDER}" != "gce" ]] && [[ "${KUBERNETES_PROVIDER}" != "gke" ]]; then
|
||||||
echo "WARNING: Skipping certs.sh for cloud provider: ${KUBERNETES_PROVIDER}."
|
echo "WARNING: Skipping certs.sh for cloud provider: ${KUBERNETES_PROVIDER}."
|
||||||
|
@@ -23,8 +23,17 @@ set -o nounset
|
|||||||
set -o pipefail
|
set -o pipefail
|
||||||
|
|
||||||
KUBE_ROOT=$(dirname "${BASH_SOURCE}")/../..
|
KUBE_ROOT=$(dirname "${BASH_SOURCE}")/../..
|
||||||
|
|
||||||
|
: ${KUBE_VERSION_ROOT:=${KUBE_ROOT}}
|
||||||
|
: ${KUBECTL:="${KUBE_VERSION_ROOT}/cluster/kubectl.sh"}
|
||||||
|
: ${KUBE_CONFIG_FILE:="config-test.sh"}
|
||||||
|
|
||||||
|
export KUBECTL KUBE_CONFIG_FILE
|
||||||
|
|
||||||
source "${KUBE_ROOT}/cluster/kube-env.sh"
|
source "${KUBE_ROOT}/cluster/kube-env.sh"
|
||||||
source "${KUBE_ROOT}/cluster/$KUBERNETES_PROVIDER/util.sh"
|
source "${KUBE_VERSION_ROOT}/cluster/${KUBERNETES_PROVIDER}/util.sh"
|
||||||
|
|
||||||
|
prepare-e2e
|
||||||
|
|
||||||
GUESTBOOK="${KUBE_ROOT}/examples/guestbook"
|
GUESTBOOK="${KUBE_ROOT}/examples/guestbook"
|
||||||
|
|
||||||
|
@@ -22,8 +22,17 @@ set -o nounset
|
|||||||
set -o pipefail
|
set -o pipefail
|
||||||
|
|
||||||
KUBE_ROOT=$(dirname "${BASH_SOURCE}")/../..
|
KUBE_ROOT=$(dirname "${BASH_SOURCE}")/../..
|
||||||
|
|
||||||
|
: ${KUBE_VERSION_ROOT:=${KUBE_ROOT}}
|
||||||
|
: ${KUBECTL:="${KUBE_VERSION_ROOT}/cluster/kubectl.sh"}
|
||||||
|
: ${KUBE_CONFIG_FILE:="config-test.sh"}
|
||||||
|
|
||||||
|
export KUBECTL KUBE_CONFIG_FILE
|
||||||
|
|
||||||
source "${KUBE_ROOT}/cluster/kube-env.sh"
|
source "${KUBE_ROOT}/cluster/kube-env.sh"
|
||||||
source "${KUBE_ROOT}/cluster/$KUBERNETES_PROVIDER/util.sh"
|
source "${KUBE_VERSION_ROOT}/cluster/${KUBERNETES_PROVIDER}/util.sh"
|
||||||
|
|
||||||
|
prepare-e2e
|
||||||
|
|
||||||
liveness_tests="http exec"
|
liveness_tests="http exec"
|
||||||
if [[ ${KUBERNETES_PROVIDER} == "gke" ]]; then
|
if [[ ${KUBERNETES_PROVIDER} == "gke" ]]; then
|
||||||
|
@@ -23,8 +23,17 @@ set -o nounset
|
|||||||
set -o pipefail
|
set -o pipefail
|
||||||
|
|
||||||
KUBE_ROOT=$(dirname "${BASH_SOURCE}")/../..
|
KUBE_ROOT=$(dirname "${BASH_SOURCE}")/../..
|
||||||
|
|
||||||
|
: ${KUBE_VERSION_ROOT:=${KUBE_ROOT}}
|
||||||
|
: ${KUBECTL:="${KUBE_VERSION_ROOT}/cluster/kubectl.sh"}
|
||||||
|
: ${KUBE_CONFIG_FILE:="config-test.sh"}
|
||||||
|
|
||||||
|
export KUBECTL KUBE_CONFIG_FILE
|
||||||
|
|
||||||
source "${KUBE_ROOT}/cluster/kube-env.sh"
|
source "${KUBE_ROOT}/cluster/kube-env.sh"
|
||||||
source "${KUBE_ROOT}/cluster/$KUBERNETES_PROVIDER/util.sh"
|
source "${KUBE_VERSION_ROOT}/cluster/${KUBERNETES_PROVIDER}/util.sh"
|
||||||
|
|
||||||
|
prepare-e2e
|
||||||
|
|
||||||
MONITORING="${KUBE_ROOT}/cluster/addons/cluster-monitoring"
|
MONITORING="${KUBE_ROOT}/cluster/addons/cluster-monitoring"
|
||||||
KUBECTL="${KUBE_ROOT}/cluster/kubectl.sh"
|
KUBECTL="${KUBE_ROOT}/cluster/kubectl.sh"
|
||||||
|
@@ -22,8 +22,17 @@ set -o nounset
|
|||||||
set -o pipefail
|
set -o pipefail
|
||||||
|
|
||||||
KUBE_ROOT=$(dirname "${BASH_SOURCE}")/../..
|
KUBE_ROOT=$(dirname "${BASH_SOURCE}")/../..
|
||||||
|
|
||||||
|
: ${KUBE_VERSION_ROOT:=${KUBE_ROOT}}
|
||||||
|
: ${KUBECTL:="${KUBE_VERSION_ROOT}/cluster/kubectl.sh"}
|
||||||
|
: ${KUBE_CONFIG_FILE:="config-test.sh"}
|
||||||
|
|
||||||
|
export KUBECTL KUBE_CONFIG_FILE
|
||||||
|
|
||||||
source "${KUBE_ROOT}/cluster/kube-env.sh"
|
source "${KUBE_ROOT}/cluster/kube-env.sh"
|
||||||
source "${KUBE_ROOT}/cluster/$KUBERNETES_PROVIDER/util.sh"
|
source "${KUBE_VERSION_ROOT}/cluster/${KUBERNETES_PROVIDER}/util.sh"
|
||||||
|
|
||||||
|
prepare-e2e
|
||||||
|
|
||||||
if [[ "$KUBERNETES_PROVIDER" != "gce" ]] && [[ "$KUBERNETES_PROVIDER" != "gke" ]]; then
|
if [[ "$KUBERNETES_PROVIDER" != "gce" ]] && [[ "$KUBERNETES_PROVIDER" != "gke" ]]; then
|
||||||
echo "WARNING: Skipping pd.sh for cloud provider: ${KUBERNETES_PROVIDER}."
|
echo "WARNING: Skipping pd.sh for cloud provider: ${KUBERNETES_PROVIDER}."
|
||||||
|
@@ -21,8 +21,17 @@ set -o nounset
|
|||||||
set -o pipefail
|
set -o pipefail
|
||||||
|
|
||||||
KUBE_ROOT=$(dirname "${BASH_SOURCE}")/../..
|
KUBE_ROOT=$(dirname "${BASH_SOURCE}")/../..
|
||||||
|
|
||||||
|
: ${KUBE_VERSION_ROOT:=${KUBE_ROOT}}
|
||||||
|
: ${KUBECTL:="${KUBE_VERSION_ROOT}/cluster/kubectl.sh"}
|
||||||
|
: ${KUBE_CONFIG_FILE:="config-test.sh"}
|
||||||
|
|
||||||
|
export KUBECTL KUBE_CONFIG_FILE
|
||||||
|
|
||||||
source "${KUBE_ROOT}/cluster/kube-env.sh"
|
source "${KUBE_ROOT}/cluster/kube-env.sh"
|
||||||
source "${KUBE_ROOT}/cluster/${KUBERNETES_PROVIDER}/util.sh"
|
source "${KUBE_VERSION_ROOT}/cluster/${KUBERNETES_PROVIDER}/util.sh"
|
||||||
|
|
||||||
|
prepare-e2e
|
||||||
|
|
||||||
if [[ "$KUBERNETES_PROVIDER" == "vagrant" ]]; then
|
if [[ "$KUBERNETES_PROVIDER" == "vagrant" ]]; then
|
||||||
echo "WARNING: Skipping services.sh for ${KUBERNETES_PROVIDER}. See https://github.com/GoogleCloudPlatform/kubernetes/issues/3655"
|
echo "WARNING: Skipping services.sh for ${KUBERNETES_PROVIDER}. See https://github.com/GoogleCloudPlatform/kubernetes/issues/3655"
|
||||||
|
@@ -21,9 +21,17 @@ set -o nounset
|
|||||||
set -o pipefail
|
set -o pipefail
|
||||||
|
|
||||||
KUBE_ROOT=$(dirname "${BASH_SOURCE}")/../..
|
KUBE_ROOT=$(dirname "${BASH_SOURCE}")/../..
|
||||||
source "${KUBE_ROOT}/cluster/kube-env.sh"
|
|
||||||
source "${KUBE_ROOT}/cluster/$KUBERNETES_PROVIDER/util.sh"
|
|
||||||
|
|
||||||
|
: ${KUBE_VERSION_ROOT:=${KUBE_ROOT}}
|
||||||
|
: ${KUBECTL:="${KUBE_VERSION_ROOT}/cluster/kubectl.sh"}
|
||||||
|
: ${KUBE_CONFIG_FILE:="config-test.sh"}
|
||||||
|
|
||||||
|
export KUBECTL KUBE_CONFIG_FILE
|
||||||
|
|
||||||
|
source "${KUBE_ROOT}/cluster/kube-env.sh"
|
||||||
|
source "${KUBE_VERSION_ROOT}/cluster/${KUBERNETES_PROVIDER}/util.sh"
|
||||||
|
|
||||||
|
prepare-e2e
|
||||||
|
|
||||||
CONTROLLER_NAME=update-demo
|
CONTROLLER_NAME=update-demo
|
||||||
|
|
||||||
|
@@ -15,6 +15,6 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
# Provided for backwards compatibility
|
# Provided for backwards compatibility
|
||||||
go run "$(dirname $0)/e2e.go" -v -build -up -tests="*" -down
|
go run "$(dirname $0)/e2e.go" -v -build -up -test -down
|
||||||
|
|
||||||
exit $?
|
exit $?
|
||||||
|
159
hack/e2e.go
159
hack/e2e.go
@@ -30,10 +30,8 @@ import (
|
|||||||
"os/signal"
|
"os/signal"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sort"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -44,12 +42,8 @@ var (
|
|||||||
push = flag.Bool("push", false, "If true, push to e2e cluster. Has no effect if -up is true.")
|
push = flag.Bool("push", false, "If true, push to e2e cluster. Has no effect if -up is true.")
|
||||||
pushup = flag.Bool("pushup", false, "If true, push to e2e cluster if it's up, otherwise start the e2e cluster.")
|
pushup = flag.Bool("pushup", false, "If true, push to e2e cluster if it's up, otherwise start the e2e cluster.")
|
||||||
down = flag.Bool("down", false, "If true, tear down the cluster before exiting.")
|
down = flag.Bool("down", false, "If true, tear down the cluster before exiting.")
|
||||||
orderseed = flag.Int64("orderseed", 0, "If non-zero, seed of random test shuffle order. (Otherwise random.)")
|
test = flag.Bool("test", false, "Run Ginkgo tests.")
|
||||||
test = flag.Bool("test", false, "Run all tests in hack/e2e-suite.")
|
|
||||||
tests = flag.String("tests", "", "Run only tests in hack/e2e-suite matching this glob. Ignored if -test is set.")
|
|
||||||
times = flag.Int("times", 1, "Number of times each test is eligible to be run. Individual order is determined by shuffling --times instances of each test using --orderseed (like a multi-deck shoe of cards).")
|
|
||||||
root = flag.String("root", absOrDie(filepath.Clean(filepath.Join(path.Base(os.Args[0]), ".."))), "Root directory of kubernetes repository.")
|
root = flag.String("root", absOrDie(filepath.Clean(filepath.Join(path.Base(os.Args[0]), ".."))), "Root directory of kubernetes repository.")
|
||||||
tap = flag.Bool("tap", false, "Enable Test Anything Protocol (TAP) output (disables --verbose, only failure output recorded)")
|
|
||||||
verbose = flag.Bool("v", false, "If true, print all command output.")
|
verbose = flag.Bool("v", false, "If true, print all command output.")
|
||||||
trace_bash = flag.Bool("trace-bash", false, "If true, pass -x to bash to trace all bash commands")
|
trace_bash = flag.Bool("trace-bash", false, "If true, pass -x to bash to trace all bash commands")
|
||||||
checkVersionSkew = flag.Bool("check_version_skew", true, ""+
|
checkVersionSkew = flag.Bool("check_version_skew", true, ""+
|
||||||
@@ -95,21 +89,6 @@ func main() {
|
|||||||
flag.Parse()
|
flag.Parse()
|
||||||
signal.Notify(signals, os.Interrupt)
|
signal.Notify(signals, os.Interrupt)
|
||||||
|
|
||||||
if *tap {
|
|
||||||
fmt.Printf("TAP version 13\n")
|
|
||||||
log.SetPrefix("# ")
|
|
||||||
|
|
||||||
// TODO: this limitation is fixable by moving runBash to
|
|
||||||
// outputing to temp files, which still lets people check on
|
|
||||||
// stuck things interactively. The current stdout/stderr
|
|
||||||
// approach isn't really going to work with TAP, though.
|
|
||||||
*verbose = false
|
|
||||||
}
|
|
||||||
|
|
||||||
if *test {
|
|
||||||
*tests = "*"
|
|
||||||
}
|
|
||||||
|
|
||||||
if *isup {
|
if *isup {
|
||||||
status := 1
|
status := 1
|
||||||
if IsUp() {
|
if IsUp() {
|
||||||
@@ -137,9 +116,12 @@ func main() {
|
|||||||
log.Fatalf("Error preparing a binary of version %s: %s. Aborting.", *version, err)
|
log.Fatalf("Error preparing a binary of version %s: %s. Aborting.", *version, err)
|
||||||
} else {
|
} else {
|
||||||
versionRoot = newVersionRoot
|
versionRoot = newVersionRoot
|
||||||
|
os.Setenv("KUBE_VERSION_ROOT", newVersionRoot)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
os.Setenv("KUBECTL", versionRoot+`/cluster/kubectl.sh`+kubectlArgs())
|
||||||
|
|
||||||
if *pushup {
|
if *pushup {
|
||||||
if IsUp() {
|
if IsUp() {
|
||||||
log.Printf("e2e cluster is up, pushing.")
|
log.Printf("e2e cluster is up, pushing.")
|
||||||
@@ -165,8 +147,8 @@ func main() {
|
|||||||
switch {
|
switch {
|
||||||
case *ctlCmd != "":
|
case *ctlCmd != "":
|
||||||
failure = !runBash("'kubectl "+*ctlCmd+"'", "$KUBECTL "+*ctlCmd)
|
failure = !runBash("'kubectl "+*ctlCmd+"'", "$KUBECTL "+*ctlCmd)
|
||||||
case *tests != "":
|
case *test:
|
||||||
failure = PrintResults(Test())
|
failure = Test()
|
||||||
}
|
}
|
||||||
|
|
||||||
if *down {
|
if *down {
|
||||||
@@ -275,7 +257,7 @@ func shuffleStrings(strings []string, r *rand.Rand) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test() (results ResultsByTest) {
|
func Test() bool {
|
||||||
defer runBashUntil("watchEvents", "while true; do $KUBECTL --watch-only get events; done")()
|
defer runBashUntil("watchEvents", "while true; do $KUBECTL --watch-only get events; done")()
|
||||||
|
|
||||||
if !IsUp() {
|
if !IsUp() {
|
||||||
@@ -284,128 +266,7 @@ func Test() (results ResultsByTest) {
|
|||||||
|
|
||||||
ValidateClusterSize()
|
ValidateClusterSize()
|
||||||
|
|
||||||
// run tests!
|
return runBash("Ginkgo tests", filepath.Join(*root, "hack", "ginkgo-e2e.sh"))
|
||||||
dir, err := os.Open(filepath.Join(*root, "hack", "e2e-suite"))
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal("Couldn't open e2e-suite dir")
|
|
||||||
}
|
|
||||||
defer dir.Close()
|
|
||||||
names, err := dir.Readdirnames(0)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal("Couldn't read names in e2e-suite dir")
|
|
||||||
}
|
|
||||||
|
|
||||||
toRun := make([]string, 0, len(names))
|
|
||||||
for i := range names {
|
|
||||||
name := names[i]
|
|
||||||
if name == "." || name == ".." {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if match, err := path.Match(*tests, name); !match && err == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Bad test pattern: %v", *tests)
|
|
||||||
}
|
|
||||||
toRun = append(toRun, name)
|
|
||||||
}
|
|
||||||
|
|
||||||
if *orderseed == 0 {
|
|
||||||
// Use low order bits of NanoTime as the default seed. (Using
|
|
||||||
// all the bits makes for a long, very similar looking seed
|
|
||||||
// between runs.)
|
|
||||||
*orderseed = time.Now().UnixNano() & (1<<32 - 1)
|
|
||||||
}
|
|
||||||
sort.Strings(toRun)
|
|
||||||
if *times != 1 {
|
|
||||||
if *times <= 0 {
|
|
||||||
log.Fatal("Invalid --times (negative or no testing requested)!")
|
|
||||||
}
|
|
||||||
newToRun := make([]string, 0, *times*len(toRun))
|
|
||||||
for i := 0; i < *times; i++ {
|
|
||||||
newToRun = append(newToRun, toRun...)
|
|
||||||
}
|
|
||||||
toRun = newToRun
|
|
||||||
}
|
|
||||||
shuffleStrings(toRun, rand.New(rand.NewSource(*orderseed)))
|
|
||||||
log.Printf("Running tests matching %v shuffled with seed %#x: %v", *tests, *orderseed, toRun)
|
|
||||||
results = ResultsByTest{}
|
|
||||||
if *tap {
|
|
||||||
fmt.Printf("1..%v\n", len(toRun))
|
|
||||||
}
|
|
||||||
for i, name := range toRun {
|
|
||||||
absName := filepath.Join(*root, "hack", "e2e-suite", name)
|
|
||||||
log.Printf("Starting test [%v/%v]: %v", i+1, len(toRun), name)
|
|
||||||
start := time.Now()
|
|
||||||
testResult := results[name]
|
|
||||||
res, stdout, stderr := runBashWithOutputs(name, absName)
|
|
||||||
// The duration_ms output is an undocumented Jenkins TAP
|
|
||||||
// plugin feature for test duration. One might think _ms means
|
|
||||||
// milliseconds, but Jenkins interprets this field in seconds.
|
|
||||||
duration_secs := time.Now().Sub(start).Seconds()
|
|
||||||
if res {
|
|
||||||
fmt.Printf("ok %v - %v\n", i+1, name)
|
|
||||||
if *tap {
|
|
||||||
fmt.Printf(" ---\n duration_ms: %.3f\n ...\n", duration_secs)
|
|
||||||
}
|
|
||||||
testResult.Pass++
|
|
||||||
} else {
|
|
||||||
fmt.Printf("not ok %v - %v\n", i+1, name)
|
|
||||||
if *tap {
|
|
||||||
fmt.Printf(" ---\n duration_ms: %.3f\n", duration_secs)
|
|
||||||
}
|
|
||||||
printBashOutputs(" ", " ", stdout, stderr, *tap)
|
|
||||||
if *tap {
|
|
||||||
fmt.Printf(" ...\n")
|
|
||||||
}
|
|
||||||
testResult.Fail++
|
|
||||||
}
|
|
||||||
results[name] = testResult
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func PrintResults(results ResultsByTest) bool {
|
|
||||||
failures := 0
|
|
||||||
|
|
||||||
passed := []string{}
|
|
||||||
flaky := []string{}
|
|
||||||
failed := []string{}
|
|
||||||
for test, result := range results {
|
|
||||||
if result.Pass > 0 && result.Fail == 0 {
|
|
||||||
passed = append(passed, test)
|
|
||||||
} else if result.Pass > 0 && result.Fail > 0 {
|
|
||||||
flaky = append(flaky, test)
|
|
||||||
failures += result.Fail
|
|
||||||
} else {
|
|
||||||
failed = append(failed, test)
|
|
||||||
failures += result.Fail
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sort.Strings(passed)
|
|
||||||
sort.Strings(flaky)
|
|
||||||
sort.Strings(failed)
|
|
||||||
printSubreport("Passed", passed, results)
|
|
||||||
printSubreport("Flaky", flaky, results)
|
|
||||||
printSubreport("Failed", failed, results)
|
|
||||||
if failures > 0 {
|
|
||||||
log.Printf("%v test(s) failed.", failures)
|
|
||||||
} else {
|
|
||||||
log.Printf("Success!")
|
|
||||||
}
|
|
||||||
|
|
||||||
return failures > 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func printSubreport(title string, tests []string, results ResultsByTest) {
|
|
||||||
report := title + " tests:"
|
|
||||||
|
|
||||||
for _, test := range tests {
|
|
||||||
result := results[test]
|
|
||||||
report += fmt.Sprintf(" %v[%v/%v]", test, result.Pass, result.Pass+result.Fail)
|
|
||||||
}
|
|
||||||
log.Printf(report)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// All nonsense below is temporary until we have go versions of these things.
|
// All nonsense below is temporary until we have go versions of these things.
|
||||||
@@ -448,10 +309,6 @@ func runBashUntil(stepName, bashFragment string) func() {
|
|||||||
cmd.Process.Signal(os.Interrupt)
|
cmd.Process.Signal(os.Interrupt)
|
||||||
headerprefix := stepName + " "
|
headerprefix := stepName + " "
|
||||||
lineprefix := " "
|
lineprefix := " "
|
||||||
if *tap {
|
|
||||||
headerprefix = "# " + headerprefix
|
|
||||||
lineprefix = "# " + lineprefix
|
|
||||||
}
|
|
||||||
printBashOutputs(headerprefix, lineprefix, string(stdout.Bytes()), string(stderr.Bytes()), false)
|
printBashOutputs(headerprefix, lineprefix, string(stdout.Bytes()), string(stderr.Bytes()), false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -14,11 +14,24 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
KUBE_ROOT=$(dirname "${BASH_SOURCE}")/../..
|
set -o errexit
|
||||||
source "${KUBE_ROOT}/cluster/kube-env.sh"
|
set -o nounset
|
||||||
source "${KUBE_ROOT}/cluster/$KUBERNETES_PROVIDER/util.sh"
|
set -o pipefail
|
||||||
|
|
||||||
detect-master > /dev/null
|
KUBE_ROOT=$(dirname "${BASH_SOURCE}")/..
|
||||||
|
|
||||||
|
: ${KUBE_VERSION_ROOT:=${KUBE_ROOT}}
|
||||||
|
: ${KUBECTL:="${KUBE_VERSION_ROOT}/cluster/kubectl.sh"}
|
||||||
|
: ${KUBE_CONFIG_FILE:="config-test.sh"}
|
||||||
|
|
||||||
|
export KUBECTL KUBE_CONFIG_FILE
|
||||||
|
|
||||||
|
source "${KUBE_ROOT}/cluster/kube-env.sh"
|
||||||
|
source "${KUBE_VERSION_ROOT}/cluster/${KUBERNETES_PROVIDER}/util.sh"
|
||||||
|
|
||||||
|
prepare-e2e
|
||||||
|
|
||||||
|
detect-master >/dev/null
|
||||||
|
|
||||||
# Detect the OS name/arch so that we can find our binary
|
# Detect the OS name/arch so that we can find our binary
|
||||||
case "$(uname -s)" in
|
case "$(uname -s)" in
|
||||||
@@ -89,5 +102,6 @@ fi
|
|||||||
"${e2e}" "${auth_config[@]:+${auth_config[@]}}" \
|
"${e2e}" "${auth_config[@]:+${auth_config[@]}}" \
|
||||||
--host="https://${KUBE_MASTER_IP-}" \
|
--host="https://${KUBE_MASTER_IP-}" \
|
||||||
--provider="${KUBERNETES_PROVIDER}" \
|
--provider="${KUBERNETES_PROVIDER}" \
|
||||||
|
--ginkgo.v \
|
||||||
${E2E_REPORT_DIR+"--report_dir=${E2E_REPORT_DIR}"} \
|
${E2E_REPORT_DIR+"--report_dir=${E2E_REPORT_DIR}"} \
|
||||||
"${@}"
|
"${@}"
|
@@ -83,5 +83,5 @@ export E2E_REPORT_DIR=${WORKSPACE}
|
|||||||
go run ./hack/e2e.go ${E2E_OPT} -v --down
|
go run ./hack/e2e.go ${E2E_OPT} -v --down
|
||||||
go run ./hack/e2e.go ${E2E_OPT} -v --up
|
go run ./hack/e2e.go ${E2E_OPT} -v --up
|
||||||
go run ./hack/e2e.go -v --ctl="version --match-server-version=false"
|
go run ./hack/e2e.go -v --ctl="version --match-server-version=false"
|
||||||
go run ./hack/e2e.go ${E2E_OPT} --test --tap | tee ../e2e.${JOB_NAME}.${BUILD_NUMBER}.${GITHASH}.tap
|
go run ./hack/e2e.go ${E2E_OPT} -v --test || echo "Ignored, Jenkins will pass/fail based on test failures"
|
||||||
go run ./hack/e2e.go ${E2E_OPT} -v --down
|
go run ./hack/e2e.go ${E2E_OPT} -v --down
|
||||||
|
@@ -55,6 +55,7 @@ readonly KUBE_TEST_PORTABLE=(
|
|||||||
contrib/for-tests/network-tester/service.json
|
contrib/for-tests/network-tester/service.json
|
||||||
hack/e2e.go
|
hack/e2e.go
|
||||||
hack/e2e-suite
|
hack/e2e-suite
|
||||||
|
hack/ginkgo-e2e.sh
|
||||||
)
|
)
|
||||||
|
|
||||||
# If we update this we need to also update the set of golang compilers we build
|
# If we update this we need to also update the set of golang compilers we build
|
||||||
|
@@ -55,6 +55,7 @@ kube::log::status "Starting kubelet in masterless mode"
|
|||||||
"${KUBE_OUTPUT_HOSTBIN}/kubelet" \
|
"${KUBE_OUTPUT_HOSTBIN}/kubelet" \
|
||||||
--really_crash_for_testing=true \
|
--really_crash_for_testing=true \
|
||||||
--root_dir=/tmp/kubelet.$$ \
|
--root_dir=/tmp/kubelet.$$ \
|
||||||
|
--docker_endpoint="fake://" \
|
||||||
--address="127.0.0.1" \
|
--address="127.0.0.1" \
|
||||||
--port="$KUBELET_PORT" 1>&2 &
|
--port="$KUBELET_PORT" 1>&2 &
|
||||||
KUBELET_PID=$!
|
KUBELET_PID=$!
|
||||||
@@ -65,6 +66,7 @@ kube::log::status "Starting kubelet in masterful mode"
|
|||||||
"${KUBE_OUTPUT_HOSTBIN}/kubelet" \
|
"${KUBE_OUTPUT_HOSTBIN}/kubelet" \
|
||||||
--really_crash_for_testing=true \
|
--really_crash_for_testing=true \
|
||||||
--root_dir=/tmp/kubelet.$$ \
|
--root_dir=/tmp/kubelet.$$ \
|
||||||
|
--docker_endpoint="fake://" \
|
||||||
--etcd_servers="http://${ETCD_HOST}:${ETCD_PORT}" \
|
--etcd_servers="http://${ETCD_HOST}:${ETCD_PORT}" \
|
||||||
--hostname_override="127.0.0.1" \
|
--hostname_override="127.0.0.1" \
|
||||||
--address="127.0.0.1" \
|
--address="127.0.0.1" \
|
||||||
|
71
hack/update-swagger-spec.sh
Executable file
71
hack/update-swagger-spec.sh
Executable file
@@ -0,0 +1,71 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Copyright 2015 Google Inc. All rights reserved.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
# Script to fetch latest swagger spec.
|
||||||
|
# Puts the updated spec at swagger-spec/
|
||||||
|
|
||||||
|
set -o errexit
|
||||||
|
set -o nounset
|
||||||
|
set -o pipefail
|
||||||
|
|
||||||
|
KUBE_ROOT=$(dirname "${BASH_SOURCE}")/..
|
||||||
|
SWAGGER_ROOT_DIR="${KUBE_ROOT}/api/swagger-spec"
|
||||||
|
source "${KUBE_ROOT}/hack/lib/init.sh"
|
||||||
|
|
||||||
|
function cleanup()
|
||||||
|
{
|
||||||
|
[[ -n ${APISERVER_PID-} ]] && kill ${APISERVER_PID} 1>&2 2>/dev/null
|
||||||
|
|
||||||
|
kube::etcd::cleanup
|
||||||
|
|
||||||
|
kube::log::status "Clean up complete"
|
||||||
|
}
|
||||||
|
|
||||||
|
trap cleanup EXIT SIGINT
|
||||||
|
|
||||||
|
kube::etcd::start
|
||||||
|
|
||||||
|
ETCD_HOST=${ETCD_HOST:-127.0.0.1}
|
||||||
|
ETCD_PORT=${ETCD_PORT:-4001}
|
||||||
|
API_PORT=${API_PORT:-8050}
|
||||||
|
API_HOST=${API_HOST:-127.0.0.1}
|
||||||
|
KUBELET_PORT=${KUBELET_PORT:-10250}
|
||||||
|
|
||||||
|
# Start kube-apiserver
|
||||||
|
kube::log::status "Starting kube-apiserver"
|
||||||
|
"${KUBE_OUTPUT_HOSTBIN}/kube-apiserver" \
|
||||||
|
--address="127.0.0.1" \
|
||||||
|
--public_address_override="127.0.0.1" \
|
||||||
|
--port="${API_PORT}" \
|
||||||
|
--etcd_servers="http://${ETCD_HOST}:${ETCD_PORT}" \
|
||||||
|
--public_address_override="127.0.0.1" \
|
||||||
|
--kubelet_port=${KUBELET_PORT} \
|
||||||
|
--runtime_config=api/v1beta3 \
|
||||||
|
--portal_net="10.0.0.0/24" 1>&2 &
|
||||||
|
APISERVER_PID=$!
|
||||||
|
|
||||||
|
kube::util::wait_for_url "http://127.0.0.1:${API_PORT}/healthz" "apiserver: "
|
||||||
|
|
||||||
|
SWAGGER_API_PATH="http://127.0.0.1:${API_PORT}/swaggerapi/"
|
||||||
|
kube::log::status "Updating " ${SWAGGER_ROOT_DIR}
|
||||||
|
curl ${SWAGGER_API_PATH} > ${SWAGGER_ROOT_DIR}/resourceListing.json
|
||||||
|
curl ${SWAGGER_API_PATH}version > ${SWAGGER_ROOT_DIR}/version.json
|
||||||
|
curl ${SWAGGER_API_PATH}api > ${SWAGGER_ROOT_DIR}/api.json
|
||||||
|
curl ${SWAGGER_API_PATH}api/v1beta1 > ${SWAGGER_ROOT_DIR}/v1beta1.json
|
||||||
|
curl ${SWAGGER_API_PATH}api/v1beta2 > ${SWAGGER_ROOT_DIR}/v1beta2.json
|
||||||
|
curl ${SWAGGER_API_PATH}api/v1beta3 > ${SWAGGER_ROOT_DIR}/v1beta3.json
|
||||||
|
|
||||||
|
kube::log::status "SUCCESS"
|
@@ -43,7 +43,7 @@ func InterpretCreateError(err error, kind, name string) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// InterpretUpdateError converts a generic etcd error on a create
|
// InterpretUpdateError converts a generic etcd error on a update
|
||||||
// operation into the appropriate API error.
|
// operation into the appropriate API error.
|
||||||
func InterpretUpdateError(err error, kind, name string) error {
|
func InterpretUpdateError(err error, kind, name string) error {
|
||||||
switch {
|
switch {
|
||||||
@@ -54,7 +54,7 @@ func InterpretUpdateError(err error, kind, name string) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// InterpretDeleteError converts a generic etcd error on a create
|
// InterpretDeleteError converts a generic etcd error on a delete
|
||||||
// operation into the appropriate API error.
|
// operation into the appropriate API error.
|
||||||
func InterpretDeleteError(err error, kind, name string) error {
|
func InterpretDeleteError(err error, kind, name string) error {
|
||||||
switch {
|
switch {
|
||||||
|
@@ -35,8 +35,6 @@ func init() {
|
|||||||
&NodeList{},
|
&NodeList{},
|
||||||
&Node{},
|
&Node{},
|
||||||
&Status{},
|
&Status{},
|
||||||
&OperationList{},
|
|
||||||
&Operation{},
|
|
||||||
&Endpoints{},
|
&Endpoints{},
|
||||||
&EndpointsList{},
|
&EndpointsList{},
|
||||||
&Binding{},
|
&Binding{},
|
||||||
@@ -56,8 +54,6 @@ func init() {
|
|||||||
// Legacy names are supported
|
// Legacy names are supported
|
||||||
Scheme.AddKnownTypeWithName("", "Minion", &Node{})
|
Scheme.AddKnownTypeWithName("", "Minion", &Node{})
|
||||||
Scheme.AddKnownTypeWithName("", "MinionList", &NodeList{})
|
Scheme.AddKnownTypeWithName("", "MinionList", &NodeList{})
|
||||||
Scheme.AddKnownTypeWithName("", "ServerOp", &Operation{})
|
|
||||||
Scheme.AddKnownTypeWithName("", "ServerOpList", &OperationList{})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*Pod) IsAnAPIObject() {}
|
func (*Pod) IsAnAPIObject() {}
|
||||||
@@ -73,8 +69,6 @@ func (*Node) IsAnAPIObject() {}
|
|||||||
func (*NodeList) IsAnAPIObject() {}
|
func (*NodeList) IsAnAPIObject() {}
|
||||||
func (*Binding) IsAnAPIObject() {}
|
func (*Binding) IsAnAPIObject() {}
|
||||||
func (*Status) IsAnAPIObject() {}
|
func (*Status) IsAnAPIObject() {}
|
||||||
func (*Operation) IsAnAPIObject() {}
|
|
||||||
func (*OperationList) IsAnAPIObject() {}
|
|
||||||
func (*Event) IsAnAPIObject() {}
|
func (*Event) IsAnAPIObject() {}
|
||||||
func (*EventList) IsAnAPIObject() {}
|
func (*EventList) IsAnAPIObject() {}
|
||||||
func (*ContainerManifest) IsAnAPIObject() {}
|
func (*ContainerManifest) IsAnAPIObject() {}
|
||||||
|
@@ -292,6 +292,8 @@ type Probe struct {
|
|||||||
Handler `json:",inline"`
|
Handler `json:",inline"`
|
||||||
// Length of time before health checking is activated. In seconds.
|
// Length of time before health checking is activated. In seconds.
|
||||||
InitialDelaySeconds int64 `json:"initialDelaySeconds,omitempty"`
|
InitialDelaySeconds int64 `json:"initialDelaySeconds,omitempty"`
|
||||||
|
// Length of time before health checking times out. In seconds.
|
||||||
|
TimeoutSeconds int64 `json:"timeoutSeconds,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// PullPolicy describes a policy for if/when to pull a container image
|
// PullPolicy describes a policy for if/when to pull a container image
|
||||||
@@ -1028,20 +1030,6 @@ const (
|
|||||||
CauseTypeFieldValueNotSupported CauseType = "FieldValueNotSupported"
|
CauseTypeFieldValueNotSupported CauseType = "FieldValueNotSupported"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Operation is an operation delivered to API clients.
|
|
||||||
type Operation struct {
|
|
||||||
TypeMeta `json:",inline"`
|
|
||||||
ObjectMeta `json:"metadata,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// OperationList is a list of operations, as delivered to API clients.
|
|
||||||
type OperationList struct {
|
|
||||||
TypeMeta `json:",inline"`
|
|
||||||
ListMeta `json:"metadata,omitempty"`
|
|
||||||
|
|
||||||
Items []Operation `json:"items"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ObjectReference contains enough information to let you inspect or modify the referred object.
|
// ObjectReference contains enough information to let you inspect or modify the referred object.
|
||||||
type ObjectReference struct {
|
type ObjectReference struct {
|
||||||
Kind string `json:"kind,omitempty"`
|
Kind string `json:"kind,omitempty"`
|
||||||
|
@@ -1050,6 +1050,7 @@ func init() {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
out.InitialDelaySeconds = in.InitialDelaySeconds
|
out.InitialDelaySeconds = in.InitialDelaySeconds
|
||||||
|
out.TimeoutSeconds = in.TimeoutSeconds
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
func(in *LivenessProbe, out *newer.Probe, s conversion.Scope) error {
|
func(in *LivenessProbe, out *newer.Probe, s conversion.Scope) error {
|
||||||
@@ -1063,6 +1064,7 @@ func init() {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
out.InitialDelaySeconds = in.InitialDelaySeconds
|
out.InitialDelaySeconds = in.InitialDelaySeconds
|
||||||
|
out.TimeoutSeconds = in.TimeoutSeconds
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@@ -39,8 +39,6 @@ func init() {
|
|||||||
&MinionList{},
|
&MinionList{},
|
||||||
&Binding{},
|
&Binding{},
|
||||||
&Status{},
|
&Status{},
|
||||||
&ServerOp{},
|
|
||||||
&ServerOpList{},
|
|
||||||
&Event{},
|
&Event{},
|
||||||
&EventList{},
|
&EventList{},
|
||||||
&ContainerManifest{},
|
&ContainerManifest{},
|
||||||
@@ -57,8 +55,6 @@ func init() {
|
|||||||
// Future names are supported
|
// Future names are supported
|
||||||
api.Scheme.AddKnownTypeWithName("v1beta1", "Node", &Minion{})
|
api.Scheme.AddKnownTypeWithName("v1beta1", "Node", &Minion{})
|
||||||
api.Scheme.AddKnownTypeWithName("v1beta1", "NodeList", &MinionList{})
|
api.Scheme.AddKnownTypeWithName("v1beta1", "NodeList", &MinionList{})
|
||||||
api.Scheme.AddKnownTypeWithName("v1beta1", "Operation", &ServerOp{})
|
|
||||||
api.Scheme.AddKnownTypeWithName("v1beta1", "OperationList", &ServerOpList{})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*Pod) IsAnAPIObject() {}
|
func (*Pod) IsAnAPIObject() {}
|
||||||
@@ -74,8 +70,6 @@ func (*Minion) IsAnAPIObject() {}
|
|||||||
func (*MinionList) IsAnAPIObject() {}
|
func (*MinionList) IsAnAPIObject() {}
|
||||||
func (*Binding) IsAnAPIObject() {}
|
func (*Binding) IsAnAPIObject() {}
|
||||||
func (*Status) IsAnAPIObject() {}
|
func (*Status) IsAnAPIObject() {}
|
||||||
func (*ServerOp) IsAnAPIObject() {}
|
|
||||||
func (*ServerOpList) IsAnAPIObject() {}
|
|
||||||
func (*Event) IsAnAPIObject() {}
|
func (*Event) IsAnAPIObject() {}
|
||||||
func (*EventList) IsAnAPIObject() {}
|
func (*EventList) IsAnAPIObject() {}
|
||||||
func (*ContainerManifest) IsAnAPIObject() {}
|
func (*ContainerManifest) IsAnAPIObject() {}
|
||||||
|
@@ -232,6 +232,8 @@ type LivenessProbe struct {
|
|||||||
Exec *ExecAction `json:"exec,omitempty" description:"parameters for exec-based liveness probe"`
|
Exec *ExecAction `json:"exec,omitempty" description:"parameters for exec-based liveness probe"`
|
||||||
// Length of time before health checking is activated. In seconds.
|
// Length of time before health checking is activated. In seconds.
|
||||||
InitialDelaySeconds int64 `json:"initialDelaySeconds,omitempty" description:"number of seconds after the container has started before liveness probes are initiated"`
|
InitialDelaySeconds int64 `json:"initialDelaySeconds,omitempty" description:"number of seconds after the container has started before liveness probes are initiated"`
|
||||||
|
// Length of time before health checking times out. In seconds.
|
||||||
|
TimeoutSeconds int64 `json:"timeoutSeconds,omitempty" description:"number of seconds after which liveness probes timeout; defaults to 1 second"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// PullPolicy describes a policy for if/when to pull a container image
|
// PullPolicy describes a policy for if/when to pull a container image
|
||||||
@@ -808,17 +810,6 @@ const (
|
|||||||
CauseTypeFieldValueNotSupported CauseType = "FieldValueNotSupported"
|
CauseTypeFieldValueNotSupported CauseType = "FieldValueNotSupported"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ServerOp is an operation delivered to API clients.
|
|
||||||
type ServerOp struct {
|
|
||||||
TypeMeta `json:",inline"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ServerOpList is a list of operations, as delivered to API clients.
|
|
||||||
type ServerOpList struct {
|
|
||||||
TypeMeta `json:",inline"`
|
|
||||||
Items []ServerOp `json:"items" description:"list of operations"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ObjectReference contains enough information to let you inspect or modify the referred object.
|
// ObjectReference contains enough information to let you inspect or modify the referred object.
|
||||||
type ObjectReference struct {
|
type ObjectReference struct {
|
||||||
Kind string `json:"kind,omitempty" description:"kind of the referent"`
|
Kind string `json:"kind,omitempty" description:"kind of the referent"`
|
||||||
|
@@ -966,6 +966,7 @@ func init() {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
out.InitialDelaySeconds = in.InitialDelaySeconds
|
out.InitialDelaySeconds = in.InitialDelaySeconds
|
||||||
|
out.TimeoutSeconds = in.TimeoutSeconds
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
func(in *LivenessProbe, out *newer.Probe, s conversion.Scope) error {
|
func(in *LivenessProbe, out *newer.Probe, s conversion.Scope) error {
|
||||||
@@ -979,6 +980,7 @@ func init() {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
out.InitialDelaySeconds = in.InitialDelaySeconds
|
out.InitialDelaySeconds = in.InitialDelaySeconds
|
||||||
|
out.TimeoutSeconds = in.TimeoutSeconds
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@@ -39,8 +39,6 @@ func init() {
|
|||||||
&MinionList{},
|
&MinionList{},
|
||||||
&Binding{},
|
&Binding{},
|
||||||
&Status{},
|
&Status{},
|
||||||
&ServerOp{},
|
|
||||||
&ServerOpList{},
|
|
||||||
&Event{},
|
&Event{},
|
||||||
&EventList{},
|
&EventList{},
|
||||||
&ContainerManifest{},
|
&ContainerManifest{},
|
||||||
@@ -57,8 +55,6 @@ func init() {
|
|||||||
// Future names are supported
|
// Future names are supported
|
||||||
api.Scheme.AddKnownTypeWithName("v1beta2", "Node", &Minion{})
|
api.Scheme.AddKnownTypeWithName("v1beta2", "Node", &Minion{})
|
||||||
api.Scheme.AddKnownTypeWithName("v1beta2", "NodeList", &MinionList{})
|
api.Scheme.AddKnownTypeWithName("v1beta2", "NodeList", &MinionList{})
|
||||||
api.Scheme.AddKnownTypeWithName("v1beta2", "Operation", &ServerOp{})
|
|
||||||
api.Scheme.AddKnownTypeWithName("v1beta2", "OperationList", &ServerOpList{})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*Pod) IsAnAPIObject() {}
|
func (*Pod) IsAnAPIObject() {}
|
||||||
@@ -74,8 +70,6 @@ func (*Minion) IsAnAPIObject() {}
|
|||||||
func (*MinionList) IsAnAPIObject() {}
|
func (*MinionList) IsAnAPIObject() {}
|
||||||
func (*Binding) IsAnAPIObject() {}
|
func (*Binding) IsAnAPIObject() {}
|
||||||
func (*Status) IsAnAPIObject() {}
|
func (*Status) IsAnAPIObject() {}
|
||||||
func (*ServerOp) IsAnAPIObject() {}
|
|
||||||
func (*ServerOpList) IsAnAPIObject() {}
|
|
||||||
func (*Event) IsAnAPIObject() {}
|
func (*Event) IsAnAPIObject() {}
|
||||||
func (*EventList) IsAnAPIObject() {}
|
func (*EventList) IsAnAPIObject() {}
|
||||||
func (*ContainerManifest) IsAnAPIObject() {}
|
func (*ContainerManifest) IsAnAPIObject() {}
|
||||||
|
@@ -191,6 +191,8 @@ type LivenessProbe struct {
|
|||||||
Exec *ExecAction `json:"exec,omitempty" description:"parameters for exec-based liveness probe"`
|
Exec *ExecAction `json:"exec,omitempty" description:"parameters for exec-based liveness probe"`
|
||||||
// Length of time before health checking is activated. In seconds.
|
// Length of time before health checking is activated. In seconds.
|
||||||
InitialDelaySeconds int64 `json:"initialDelaySeconds,omitempty" description:"number of seconds after the container has started before liveness probes are initiated"`
|
InitialDelaySeconds int64 `json:"initialDelaySeconds,omitempty" description:"number of seconds after the container has started before liveness probes are initiated"`
|
||||||
|
// Length of time before health checking times out. In seconds.
|
||||||
|
TimeoutSeconds int64 `json:"timeoutSeconds,omitempty" description:"number of seconds after which liveness probes timeout; defaults to 1 second"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// PullPolicy describes a policy for if/when to pull a container image
|
// PullPolicy describes a policy for if/when to pull a container image
|
||||||
@@ -782,17 +784,6 @@ const (
|
|||||||
CauseTypeFieldValueNotSupported CauseType = "FieldValueNotSupported"
|
CauseTypeFieldValueNotSupported CauseType = "FieldValueNotSupported"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ServerOp is an operation delivered to API clients.
|
|
||||||
type ServerOp struct {
|
|
||||||
TypeMeta `json:",inline"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ServerOpList is a list of operations, as delivered to API clients.
|
|
||||||
type ServerOpList struct {
|
|
||||||
TypeMeta `json:",inline"`
|
|
||||||
Items []ServerOp `json:"items" description:"list of operations"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ObjectReference contains enough information to let you inspect or modify the referred object.
|
// ObjectReference contains enough information to let you inspect or modify the referred object.
|
||||||
type ObjectReference struct {
|
type ObjectReference struct {
|
||||||
Kind string `json:"kind,omitempty" description:"kind of the referent"`
|
Kind string `json:"kind,omitempty" description:"kind of the referent"`
|
||||||
|
@@ -43,8 +43,6 @@ func init() {
|
|||||||
&NodeList{},
|
&NodeList{},
|
||||||
&Binding{},
|
&Binding{},
|
||||||
&Status{},
|
&Status{},
|
||||||
&Operation{},
|
|
||||||
&OperationList{},
|
|
||||||
&Event{},
|
&Event{},
|
||||||
&EventList{},
|
&EventList{},
|
||||||
&List{},
|
&List{},
|
||||||
@@ -57,8 +55,6 @@ func init() {
|
|||||||
// Legacy names are supported
|
// Legacy names are supported
|
||||||
api.Scheme.AddKnownTypeWithName("v1beta3", "Minion", &Node{})
|
api.Scheme.AddKnownTypeWithName("v1beta3", "Minion", &Node{})
|
||||||
api.Scheme.AddKnownTypeWithName("v1beta3", "MinionList", &NodeList{})
|
api.Scheme.AddKnownTypeWithName("v1beta3", "MinionList", &NodeList{})
|
||||||
api.Scheme.AddKnownTypeWithName("v1beta3", "ServerOp", &Operation{})
|
|
||||||
api.Scheme.AddKnownTypeWithName("v1beta3", "ServerOpList", &OperationList{})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*Pod) IsAnAPIObject() {}
|
func (*Pod) IsAnAPIObject() {}
|
||||||
@@ -78,8 +74,6 @@ func (*Node) IsAnAPIObject() {}
|
|||||||
func (*NodeList) IsAnAPIObject() {}
|
func (*NodeList) IsAnAPIObject() {}
|
||||||
func (*Binding) IsAnAPIObject() {}
|
func (*Binding) IsAnAPIObject() {}
|
||||||
func (*Status) IsAnAPIObject() {}
|
func (*Status) IsAnAPIObject() {}
|
||||||
func (*Operation) IsAnAPIObject() {}
|
|
||||||
func (*OperationList) IsAnAPIObject() {}
|
|
||||||
func (*Event) IsAnAPIObject() {}
|
func (*Event) IsAnAPIObject() {}
|
||||||
func (*EventList) IsAnAPIObject() {}
|
func (*EventList) IsAnAPIObject() {}
|
||||||
func (*List) IsAnAPIObject() {}
|
func (*List) IsAnAPIObject() {}
|
||||||
|
@@ -310,6 +310,8 @@ type Probe struct {
|
|||||||
Handler `json:",inline"`
|
Handler `json:",inline"`
|
||||||
// Length of time before health checking is activated. In seconds.
|
// Length of time before health checking is activated. In seconds.
|
||||||
InitialDelaySeconds int64 `json:"initialDelaySeconds,omitempty"`
|
InitialDelaySeconds int64 `json:"initialDelaySeconds,omitempty"`
|
||||||
|
// Length of time before health checking times out. In seconds.
|
||||||
|
TimeoutSeconds int64 `json:"timeoutSeconds,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// PullPolicy describes a policy for if/when to pull a container image
|
// PullPolicy describes a policy for if/when to pull a container image
|
||||||
@@ -1008,22 +1010,6 @@ const (
|
|||||||
CauseTypeFieldValueNotSupported CauseType = "FieldValueNotSupported"
|
CauseTypeFieldValueNotSupported CauseType = "FieldValueNotSupported"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Operation is a request from a client that has not yet been satisfied. The name of an
|
|
||||||
// Operation is assigned by the server when an operation is started, and can be used by
|
|
||||||
// clients to retrieve the final result of the operation at a later time.
|
|
||||||
type Operation struct {
|
|
||||||
TypeMeta `json:",inline"`
|
|
||||||
ObjectMeta `json:"metadata"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// OperationList is a list of operations, as delivered to API clients.
|
|
||||||
type OperationList struct {
|
|
||||||
TypeMeta `json:",inline"`
|
|
||||||
ListMeta `json:"metadata,omitempty"`
|
|
||||||
|
|
||||||
Items []Operation `json:"items"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ObjectReference contains enough information to let you inspect or modify the referred object.
|
// ObjectReference contains enough information to let you inspect or modify the referred object.
|
||||||
type ObjectReference struct {
|
type ObjectReference struct {
|
||||||
Kind string `json:"kind,omitempty"`
|
Kind string `json:"kind,omitempty"`
|
||||||
|
@@ -214,7 +214,7 @@ func TestValidatePorts(t *testing.T) {
|
|||||||
"invalid container port": {[]api.Port{{ContainerPort: 65536, Protocol: "TCP"}}, errors.ValidationErrorTypeInvalid, "[0].containerPort"},
|
"invalid container port": {[]api.Port{{ContainerPort: 65536, Protocol: "TCP"}}, errors.ValidationErrorTypeInvalid, "[0].containerPort"},
|
||||||
"invalid host port": {[]api.Port{{ContainerPort: 80, HostPort: 65536, Protocol: "TCP"}}, errors.ValidationErrorTypeInvalid, "[0].hostPort"},
|
"invalid host port": {[]api.Port{{ContainerPort: 80, HostPort: 65536, Protocol: "TCP"}}, errors.ValidationErrorTypeInvalid, "[0].hostPort"},
|
||||||
"invalid protocol": {[]api.Port{{ContainerPort: 80, Protocol: "ICMP"}}, errors.ValidationErrorTypeNotSupported, "[0].protocol"},
|
"invalid protocol": {[]api.Port{{ContainerPort: 80, Protocol: "ICMP"}}, errors.ValidationErrorTypeNotSupported, "[0].protocol"},
|
||||||
"protocol required": {[]api.Port{{Name: "abc", ContainerPort: 80}}, errors.ValidationErrorTypeRequired, "[0].protocol"}, //yjhong
|
"protocol required": {[]api.Port{{Name: "abc", ContainerPort: 80}}, errors.ValidationErrorTypeRequired, "[0].protocol"},
|
||||||
}
|
}
|
||||||
for k, v := range errorCases {
|
for k, v := range errorCases {
|
||||||
errs := validatePorts(v.P)
|
errs := validatePorts(v.P)
|
||||||
@@ -371,23 +371,26 @@ func TestValidateContainers(t *testing.T) {
|
|||||||
AllowPrivileged: false,
|
AllowPrivileged: false,
|
||||||
})
|
})
|
||||||
errorCases := map[string][]api.Container{
|
errorCases := map[string][]api.Container{
|
||||||
"zero-length name": {{Name: "", Image: "image"}},
|
"zero-length name": {{Name: "", Image: "image", ImagePullPolicy: "IfNotPresent"}},
|
||||||
"name > 63 characters": {{Name: strings.Repeat("a", 64), Image: "image"}},
|
"name > 63 characters": {{Name: strings.Repeat("a", 64), Image: "image", ImagePullPolicy: "IfNotPresent"}},
|
||||||
"name not a DNS label": {{Name: "a.b.c", Image: "image"}},
|
"name not a DNS label": {{Name: "a.b.c", Image: "image", ImagePullPolicy: "IfNotPresent"}},
|
||||||
"name not unique": {
|
"name not unique": {
|
||||||
{Name: "abc", Image: "image"},
|
{Name: "abc", Image: "image", ImagePullPolicy: "IfNotPresent"},
|
||||||
{Name: "abc", Image: "image"},
|
{Name: "abc", Image: "image", ImagePullPolicy: "IfNotPresent"},
|
||||||
},
|
},
|
||||||
"zero-length image": {{Name: "abc", Image: ""}},
|
"zero-length image": {{Name: "abc", Image: "", ImagePullPolicy: "IfNotPresent"}},
|
||||||
"host port not unique": {
|
"host port not unique": {
|
||||||
{Name: "abc", Image: "image", Ports: []api.Port{{ContainerPort: 80, HostPort: 80}}},
|
{Name: "abc", Image: "image", Ports: []api.Port{{ContainerPort: 80, HostPort: 80, Protocol: "TCP"}},
|
||||||
{Name: "def", Image: "image", Ports: []api.Port{{ContainerPort: 81, HostPort: 80}}},
|
ImagePullPolicy: "IfNotPresent"},
|
||||||
|
{Name: "def", Image: "image", Ports: []api.Port{{ContainerPort: 81, HostPort: 80, Protocol: "TCP"}},
|
||||||
|
ImagePullPolicy: "IfNotPresent"},
|
||||||
},
|
},
|
||||||
"invalid env var name": {
|
"invalid env var name": {
|
||||||
{Name: "abc", Image: "image", Env: []api.EnvVar{{Name: "ev.1"}}},
|
{Name: "abc", Image: "image", Env: []api.EnvVar{{Name: "ev.1"}}, ImagePullPolicy: "IfNotPresent"},
|
||||||
},
|
},
|
||||||
"unknown volume name": {
|
"unknown volume name": {
|
||||||
{Name: "abc", Image: "image", VolumeMounts: []api.VolumeMount{{Name: "anything", MountPath: "/foo"}}},
|
{Name: "abc", Image: "image", VolumeMounts: []api.VolumeMount{{Name: "anything", MountPath: "/foo"}},
|
||||||
|
ImagePullPolicy: "IfNotPresent"},
|
||||||
},
|
},
|
||||||
"invalid lifecycle, no exec command.": {
|
"invalid lifecycle, no exec command.": {
|
||||||
{
|
{
|
||||||
@@ -398,6 +401,7 @@ func TestValidateContainers(t *testing.T) {
|
|||||||
Exec: &api.ExecAction{},
|
Exec: &api.ExecAction{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
ImagePullPolicy: "IfNotPresent",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"invalid lifecycle, no http path.": {
|
"invalid lifecycle, no http path.": {
|
||||||
@@ -409,6 +413,7 @@ func TestValidateContainers(t *testing.T) {
|
|||||||
HTTPGet: &api.HTTPGetAction{},
|
HTTPGet: &api.HTTPGetAction{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
ImagePullPolicy: "IfNotPresent",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"invalid lifecycle, no action.": {
|
"invalid lifecycle, no action.": {
|
||||||
@@ -418,6 +423,7 @@ func TestValidateContainers(t *testing.T) {
|
|||||||
Lifecycle: &api.Lifecycle{
|
Lifecycle: &api.Lifecycle{
|
||||||
PreStop: &api.Handler{},
|
PreStop: &api.Handler{},
|
||||||
},
|
},
|
||||||
|
ImagePullPolicy: "IfNotPresent",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"privilege disabled": {
|
"privilege disabled": {
|
||||||
@@ -432,6 +438,7 @@ func TestValidateContainers(t *testing.T) {
|
|||||||
"disk": resource.MustParse("10G"),
|
"disk": resource.MustParse("10G"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
ImagePullPolicy: "IfNotPresent",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"Resource CPU invalid": {
|
"Resource CPU invalid": {
|
||||||
@@ -441,6 +448,7 @@ func TestValidateContainers(t *testing.T) {
|
|||||||
Resources: api.ResourceRequirementSpec{
|
Resources: api.ResourceRequirementSpec{
|
||||||
Limits: getResourceLimits("-10", "0"),
|
Limits: getResourceLimits("-10", "0"),
|
||||||
},
|
},
|
||||||
|
ImagePullPolicy: "IfNotPresent",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"Resource Memory invalid": {
|
"Resource Memory invalid": {
|
||||||
@@ -450,6 +458,7 @@ func TestValidateContainers(t *testing.T) {
|
|||||||
Resources: api.ResourceRequirementSpec{
|
Resources: api.ResourceRequirementSpec{
|
||||||
Limits: getResourceLimits("0", "-10"),
|
Limits: getResourceLimits("0", "-10"),
|
||||||
},
|
},
|
||||||
|
ImagePullPolicy: "IfNotPresent",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -553,17 +562,26 @@ func TestValidateManifest(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
errorCases := map[string]api.ContainerManifest{
|
errorCases := map[string]api.ContainerManifest{
|
||||||
"empty version": {Version: "", ID: "abc"},
|
"empty version": {Version: "", ID: "abc",
|
||||||
"invalid version": {Version: "bogus", ID: "abc"},
|
RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}},
|
||||||
|
DNSPolicy: api.DNSClusterFirst},
|
||||||
|
"invalid version": {Version: "bogus", ID: "abc",
|
||||||
|
RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}},
|
||||||
|
DNSPolicy: api.DNSClusterFirst},
|
||||||
"invalid volume name": {
|
"invalid volume name": {
|
||||||
Version: "v1beta1",
|
Version: "v1beta1",
|
||||||
ID: "abc",
|
ID: "abc",
|
||||||
Volumes: []api.Volume{{Name: "vol.1"}},
|
Volumes: []api.Volume{{Name: "vol.1", Source: api.VolumeSource{EmptyDir: &api.EmptyDir{}}}},
|
||||||
|
RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}},
|
||||||
|
DNSPolicy: api.DNSClusterFirst,
|
||||||
},
|
},
|
||||||
"invalid container name": {
|
"invalid container name": {
|
||||||
Version: "v1beta1",
|
Version: "v1beta1",
|
||||||
ID: "abc",
|
ID: "abc",
|
||||||
Containers: []api.Container{{Name: "ctr.1", Image: "image"}},
|
Containers: []api.Container{{Name: "ctr.1", Image: "image", ImagePullPolicy: "IfNotPresent",
|
||||||
|
TerminationMessagePath: "/foo/bar"}},
|
||||||
|
RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}},
|
||||||
|
DNSPolicy: api.DNSClusterFirst,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for k, v := range errorCases {
|
for k, v := range errorCases {
|
||||||
@@ -602,13 +620,22 @@ func TestValidatePodSpec(t *testing.T) {
|
|||||||
|
|
||||||
failureCases := map[string]api.PodSpec{
|
failureCases := map[string]api.PodSpec{
|
||||||
"bad volume": {
|
"bad volume": {
|
||||||
Volumes: []api.Volume{{}},
|
Volumes: []api.Volume{{}},
|
||||||
|
RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}},
|
||||||
|
DNSPolicy: api.DNSClusterFirst,
|
||||||
},
|
},
|
||||||
"bad container": {
|
"bad container": {
|
||||||
Containers: []api.Container{{}},
|
Containers: []api.Container{{}},
|
||||||
|
RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}},
|
||||||
|
DNSPolicy: api.DNSClusterFirst,
|
||||||
},
|
},
|
||||||
"bad DNS policy": {
|
"bad DNS policy": {
|
||||||
DNSPolicy: api.DNSPolicy("invalid"),
|
DNSPolicy: api.DNSPolicy("invalid"),
|
||||||
|
RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}},
|
||||||
|
},
|
||||||
|
"bad restart policy": {
|
||||||
|
RestartPolicy: api.RestartPolicy{},
|
||||||
|
DNSPolicy: api.DNSClusterFirst,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for k, v := range failureCases {
|
for k, v := range failureCases {
|
||||||
@@ -652,8 +679,20 @@ func TestValidatePod(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
errorCases := map[string]api.Pod{
|
errorCases := map[string]api.Pod{
|
||||||
"bad name": {ObjectMeta: api.ObjectMeta{Name: "", Namespace: "ns"}},
|
"bad name": {
|
||||||
"bad namespace": {ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: ""}},
|
ObjectMeta: api.ObjectMeta{Name: "", Namespace: "ns"},
|
||||||
|
Spec: api.PodSpec{
|
||||||
|
RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}},
|
||||||
|
DNSPolicy: api.DNSClusterFirst,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"bad namespace": {
|
||||||
|
ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: ""},
|
||||||
|
Spec: api.PodSpec{
|
||||||
|
RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}},
|
||||||
|
DNSPolicy: api.DNSClusterFirst,
|
||||||
|
},
|
||||||
|
},
|
||||||
"bad spec": {
|
"bad spec": {
|
||||||
ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: "ns"},
|
ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: "ns"},
|
||||||
Spec: api.PodSpec{
|
Spec: api.PodSpec{
|
||||||
@@ -668,6 +707,10 @@ func TestValidatePod(t *testing.T) {
|
|||||||
"NoUppercaseOrSpecialCharsLike=Equals": "bar",
|
"NoUppercaseOrSpecialCharsLike=Equals": "bar",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Spec: api.PodSpec{
|
||||||
|
RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}},
|
||||||
|
DNSPolicy: api.DNSClusterFirst,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
"bad annotation": {
|
"bad annotation": {
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
@@ -677,6 +720,10 @@ func TestValidatePod(t *testing.T) {
|
|||||||
"NoUppercaseOrSpecialCharsLike=Equals": "bar",
|
"NoUppercaseOrSpecialCharsLike=Equals": "bar",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Spec: api.PodSpec{
|
||||||
|
RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}},
|
||||||
|
DNSPolicy: api.DNSClusterFirst,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for k, v := range errorCases {
|
for k, v := range errorCases {
|
||||||
@@ -857,6 +904,26 @@ func TestValidatePodUpdate(t *testing.T) {
|
|||||||
false,
|
false,
|
||||||
"port change",
|
"port change",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
api.Pod{
|
||||||
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
Name: "foo",
|
||||||
|
Labels: map[string]string{
|
||||||
|
"foo": "bar",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
api.Pod{
|
||||||
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
Name: "foo",
|
||||||
|
Labels: map[string]string{
|
||||||
|
"Bar": "foo",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
"bad label change",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
@@ -914,18 +981,53 @@ func TestValidateBoundPods(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
errorCases := map[string]api.Pod{
|
errorCases := map[string]api.Pod{
|
||||||
"bad name": {ObjectMeta: api.ObjectMeta{Name: "", Namespace: "ns"}},
|
"zero-length name": {
|
||||||
"bad namespace": {ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: ""}},
|
ObjectMeta: api.ObjectMeta{Name: "", Namespace: "ns"},
|
||||||
|
Spec: api.PodSpec{
|
||||||
|
RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}},
|
||||||
|
DNSPolicy: api.DNSClusterFirst,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"bad namespace": {
|
||||||
|
ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: ""},
|
||||||
|
Spec: api.PodSpec{
|
||||||
|
RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}},
|
||||||
|
DNSPolicy: api.DNSClusterFirst,
|
||||||
|
},
|
||||||
|
},
|
||||||
"bad spec": {
|
"bad spec": {
|
||||||
ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: "ns"},
|
ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: "ns"},
|
||||||
Spec: api.PodSpec{
|
Spec: api.PodSpec{
|
||||||
Containers: []api.Container{{}},
|
Containers: []api.Container{{Name: "name", ImagePullPolicy: "IfNotPresent"}},
|
||||||
|
RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}},
|
||||||
|
DNSPolicy: api.DNSClusterFirst,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"name > 253 characters": {
|
||||||
|
ObjectMeta: api.ObjectMeta{Name: strings.Repeat("a", 254), Namespace: "ns"},
|
||||||
|
Spec: api.PodSpec{
|
||||||
|
RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}},
|
||||||
|
DNSPolicy: api.DNSClusterFirst,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"name not a DNS subdomain": {
|
||||||
|
ObjectMeta: api.ObjectMeta{Name: "a..b.c", Namespace: "ns"},
|
||||||
|
Spec: api.PodSpec{
|
||||||
|
RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}},
|
||||||
|
DNSPolicy: api.DNSClusterFirst,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"name with underscore": {
|
||||||
|
ObjectMeta: api.ObjectMeta{Name: "a_b_c", Namespace: "ns"},
|
||||||
|
Spec: api.PodSpec{
|
||||||
|
RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}},
|
||||||
|
DNSPolicy: api.DNSClusterFirst,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for k, v := range errorCases {
|
for k, v := range errorCases {
|
||||||
if errs := ValidatePod(&v); len(errs) == 0 {
|
if errs := ValidatePod(&v); len(errs) != 1 {
|
||||||
t.Errorf("expected failure for %s", k)
|
t.Errorf("expected one failure for %s; got %d: %s", k, len(errs), errs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1314,7 +1416,9 @@ func TestValidateReplicationController(t *testing.T) {
|
|||||||
invalidVolumePodTemplate := api.PodTemplate{
|
invalidVolumePodTemplate := api.PodTemplate{
|
||||||
Spec: api.PodTemplateSpec{
|
Spec: api.PodTemplateSpec{
|
||||||
Spec: api.PodSpec{
|
Spec: api.PodSpec{
|
||||||
Volumes: []api.Volume{{Name: "gcepd", Source: api.VolumeSource{GCEPersistentDisk: &api.GCEPersistentDisk{"my-PD", "ext4", 1, false}}}},
|
Volumes: []api.Volume{{Name: "gcepd", Source: api.VolumeSource{GCEPersistentDisk: &api.GCEPersistentDisk{"my-PD", "ext4", 1, false}}}},
|
||||||
|
RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}},
|
||||||
|
DNSPolicy: api.DNSClusterFirst,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -1502,24 +1606,6 @@ func TestValidateReplicationController(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestValidateBoundPodNoName(t *testing.T) {
|
|
||||||
errorCases := map[string]api.BoundPod{
|
|
||||||
// manifest is tested in api/validation_test.go, ensure it is invoked
|
|
||||||
"empty version": {ObjectMeta: api.ObjectMeta{Name: "test"}, Spec: api.PodSpec{Containers: []api.Container{{Name: ""}}}},
|
|
||||||
|
|
||||||
// Name
|
|
||||||
"zero-length name": {ObjectMeta: api.ObjectMeta{Name: ""}},
|
|
||||||
"name > 255 characters": {ObjectMeta: api.ObjectMeta{Name: strings.Repeat("a", 256)}},
|
|
||||||
"name not a DNS subdomain": {ObjectMeta: api.ObjectMeta{Name: "a.b.c."}},
|
|
||||||
"name with underscore": {ObjectMeta: api.ObjectMeta{Name: "a_b_c"}},
|
|
||||||
}
|
|
||||||
for k, v := range errorCases {
|
|
||||||
if errs := ValidateBoundPod(&v); len(errs) == 0 {
|
|
||||||
t.Errorf("expected failure for %s", k)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestValidateMinion(t *testing.T) {
|
func TestValidateMinion(t *testing.T) {
|
||||||
validSelector := map[string]string{"a": "b"}
|
validSelector := map[string]string{"a": "b"}
|
||||||
invalidSelector := map[string]string{"NoUppercaseOrSpecialCharsLike=Equals": "b"}
|
invalidSelector := map[string]string{"NoUppercaseOrSpecialCharsLike=Equals": "b"}
|
||||||
@@ -1692,6 +1778,17 @@ func TestValidateMinionUpdate(t *testing.T) {
|
|||||||
Labels: map[string]string{"bar": "fooobaz"},
|
Labels: map[string]string{"bar": "fooobaz"},
|
||||||
},
|
},
|
||||||
}, true},
|
}, true},
|
||||||
|
{api.Node{
|
||||||
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
Name: "foo",
|
||||||
|
Labels: map[string]string{"foo": "baz"},
|
||||||
|
},
|
||||||
|
}, api.Node{
|
||||||
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
Name: "foo",
|
||||||
|
Labels: map[string]string{"Foo": "baz"},
|
||||||
|
},
|
||||||
|
}, false},
|
||||||
}
|
}
|
||||||
for i, test := range tests {
|
for i, test := range tests {
|
||||||
errs := ValidateMinionUpdate(&test.oldMinion, &test.minion)
|
errs := ValidateMinionUpdate(&test.oldMinion, &test.minion)
|
||||||
@@ -1848,6 +1945,19 @@ func TestValidateServiceUpdate(t *testing.T) {
|
|||||||
PortalIP: "127.0.0.2",
|
PortalIP: "127.0.0.2",
|
||||||
},
|
},
|
||||||
}, false},
|
}, false},
|
||||||
|
{ // 10
|
||||||
|
api.Service{
|
||||||
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
Name: "foo",
|
||||||
|
Labels: map[string]string{"foo": "baz"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
api.Service{
|
||||||
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
Name: "foo",
|
||||||
|
Labels: map[string]string{"Foo": "baz"},
|
||||||
|
},
|
||||||
|
}, false},
|
||||||
}
|
}
|
||||||
for i, test := range tests {
|
for i, test := range tests {
|
||||||
errs := ValidateServiceUpdate(&test.oldService, &test.service)
|
errs := ValidateServiceUpdate(&test.oldService, &test.service)
|
||||||
|
@@ -17,7 +17,6 @@ limitations under the License.
|
|||||||
package apiserver
|
package apiserver
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"sort"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
@@ -79,23 +78,6 @@ func (ops *Operations) insert(op *Operation) {
|
|||||||
ops.ops[op.ID] = op
|
ops.ops[op.ID] = op
|
||||||
}
|
}
|
||||||
|
|
||||||
// List lists operations for an API client.
|
|
||||||
func (ops *Operations) List() *api.OperationList {
|
|
||||||
ops.lock.Lock()
|
|
||||||
defer ops.lock.Unlock()
|
|
||||||
|
|
||||||
ids := []string{}
|
|
||||||
for id := range ops.ops {
|
|
||||||
ids = append(ids, id)
|
|
||||||
}
|
|
||||||
sort.StringSlice(ids).Sort()
|
|
||||||
ol := &api.OperationList{}
|
|
||||||
for _, id := range ids {
|
|
||||||
ol.Items = append(ol.Items, api.Operation{ObjectMeta: api.ObjectMeta{Name: id}})
|
|
||||||
}
|
|
||||||
return ol
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get returns the operation with the given ID, or nil.
|
// Get returns the operation with the given ID, or nil.
|
||||||
func (ops *Operations) Get(id string) *Operation {
|
func (ops *Operations) Get(id string) *Operation {
|
||||||
ops.lock.Lock()
|
ops.lock.Lock()
|
||||||
|
@@ -46,7 +46,7 @@ type validator struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: can this use pkg/probe/http
|
// TODO: can this use pkg/probe/http
|
||||||
func (s *Server) check(client httpGet) (probe.Status, string, error) {
|
func (s *Server) check(client httpGet) (probe.Result, string, error) {
|
||||||
resp, err := client.Get("http://" + net.JoinHostPort(s.Addr, strconv.Itoa(s.Port)) + s.Path)
|
resp, err := client.Get("http://" + net.JoinHostPort(s.Addr, strconv.Itoa(s.Port)) + s.Path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return probe.Unknown, "", err
|
return probe.Unknown, "", err
|
||||||
@@ -66,7 +66,7 @@ func (s *Server) check(client httpGet) (probe.Status, string, error) {
|
|||||||
type ServerStatus struct {
|
type ServerStatus struct {
|
||||||
Component string `json:"component,omitempty"`
|
Component string `json:"component,omitempty"`
|
||||||
Health string `json:"health,omitempty"`
|
Health string `json:"health,omitempty"`
|
||||||
HealthCode probe.Status `json:"healthCode,omitempty"`
|
HealthCode probe.Result `json:"healthCode,omitempty"`
|
||||||
Msg string `json:"msg,omitempty"`
|
Msg string `json:"msg,omitempty"`
|
||||||
Err string `json:"err,omitempty"`
|
Err string `json:"err,omitempty"`
|
||||||
}
|
}
|
||||||
|
@@ -54,7 +54,7 @@ func TestValidate(t *testing.T) {
|
|||||||
tests := []struct {
|
tests := []struct {
|
||||||
err error
|
err error
|
||||||
data string
|
data string
|
||||||
expectedStatus probe.Status
|
expectedStatus probe.Result
|
||||||
code int
|
code int
|
||||||
expectErr bool
|
expectErr bool
|
||||||
}{
|
}{
|
||||||
|
@@ -41,7 +41,7 @@ type KubeletClient interface {
|
|||||||
|
|
||||||
// KubeletHealthchecker is an interface for healthchecking kubelets
|
// KubeletHealthchecker is an interface for healthchecking kubelets
|
||||||
type KubeletHealthChecker interface {
|
type KubeletHealthChecker interface {
|
||||||
HealthCheck(host string) (probe.Status, error)
|
HealthCheck(host string) (probe.Result, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// PodInfoGetter is an interface for things that can get information about a pod's containers.
|
// PodInfoGetter is an interface for things that can get information about a pod's containers.
|
||||||
@@ -134,7 +134,7 @@ func (c *HTTPKubeletClient) GetPodStatus(host, podNamespace, podID string) (api.
|
|||||||
return status, nil
|
return status, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *HTTPKubeletClient) HealthCheck(host string) (probe.Status, error) {
|
func (c *HTTPKubeletClient) HealthCheck(host string) (probe.Result, error) {
|
||||||
return httprobe.DoHTTPProbe(fmt.Sprintf("%s/healthz", c.url(host)), c.Client)
|
return httprobe.DoHTTPProbe(fmt.Sprintf("%s/healthz", c.url(host)), c.Client)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,6 +148,6 @@ func (c FakeKubeletClient) GetPodStatus(host, podNamespace string, podID string)
|
|||||||
return api.PodStatusResult{}, errors.New("Not Implemented")
|
return api.PodStatusResult{}, errors.New("Not Implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c FakeKubeletClient) HealthCheck(host string) (probe.Status, error) {
|
func (c FakeKubeletClient) HealthCheck(host string) (probe.Result, error) {
|
||||||
return probe.Unknown, errors.New("Not Implemented")
|
return probe.Unknown, errors.New("Not Implemented")
|
||||||
}
|
}
|
||||||
|
@@ -102,7 +102,7 @@ func (m *FakeNodeHandler) Update(node *api.Node) (*api.Node, error) {
|
|||||||
|
|
||||||
// FakeKubeletClient is a fake implementation of KubeletClient.
|
// FakeKubeletClient is a fake implementation of KubeletClient.
|
||||||
type FakeKubeletClient struct {
|
type FakeKubeletClient struct {
|
||||||
Status probe.Status
|
Status probe.Result
|
||||||
Err error
|
Err error
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,7 +110,7 @@ func (c *FakeKubeletClient) GetPodStatus(host, podNamespace, podID string) (api.
|
|||||||
return api.PodStatusResult{}, errors.New("Not Implemented")
|
return api.PodStatusResult{}, errors.New("Not Implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *FakeKubeletClient) HealthCheck(host string) (probe.Status, error) {
|
func (c *FakeKubeletClient) HealthCheck(host string) (probe.Result, error) {
|
||||||
return c.Status, c.Err
|
return c.Status, c.Err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -17,11 +17,17 @@ limitations under the License.
|
|||||||
package constraint
|
package constraint
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Allowed returns true if pods is a collection of bound pods
|
// Allowed returns true if pods is a collection of bound pods
|
||||||
// which can run without conflict on a single minion.
|
// which can run without conflict on a single minion.
|
||||||
func Allowed(pods []api.BoundPod) bool {
|
func Allowed(pods []api.BoundPod) []error {
|
||||||
return !PortsConflict(pods)
|
errors := []error{}
|
||||||
|
for _, port := range hostPortsConflict(pods) {
|
||||||
|
errors = append(errors, fmt.Errorf("host port %v is already in use", port))
|
||||||
|
}
|
||||||
|
return errors
|
||||||
}
|
}
|
||||||
|
@@ -17,6 +17,7 @@ limitations under the License.
|
|||||||
package constraint
|
package constraint
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||||
@@ -40,11 +41,11 @@ func podWithContainers(containers ...api.Container) api.BoundPod {
|
|||||||
|
|
||||||
func TestAllowed(t *testing.T) {
|
func TestAllowed(t *testing.T) {
|
||||||
table := []struct {
|
table := []struct {
|
||||||
allowed bool
|
err string
|
||||||
pods []api.BoundPod
|
pods []api.BoundPod
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
allowed: true,
|
err: "[]",
|
||||||
pods: []api.BoundPod{
|
pods: []api.BoundPod{
|
||||||
podWithContainers(
|
podWithContainers(
|
||||||
containerWithHostPorts(1, 2, 3),
|
containerWithHostPorts(1, 2, 3),
|
||||||
@@ -57,7 +58,7 @@ func TestAllowed(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
allowed: true,
|
err: "[]",
|
||||||
pods: []api.BoundPod{
|
pods: []api.BoundPod{
|
||||||
podWithContainers(
|
podWithContainers(
|
||||||
containerWithHostPorts(0, 0),
|
containerWithHostPorts(0, 0),
|
||||||
@@ -70,7 +71,7 @@ func TestAllowed(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
allowed: false,
|
err: "[host port 3 is already in use]",
|
||||||
pods: []api.BoundPod{
|
pods: []api.BoundPod{
|
||||||
podWithContainers(
|
podWithContainers(
|
||||||
containerWithHostPorts(3, 3),
|
containerWithHostPorts(3, 3),
|
||||||
@@ -78,7 +79,7 @@ func TestAllowed(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
allowed: false,
|
err: "[host port 6 is already in use]",
|
||||||
pods: []api.BoundPod{
|
pods: []api.BoundPod{
|
||||||
podWithContainers(
|
podWithContainers(
|
||||||
containerWithHostPorts(6),
|
containerWithHostPorts(6),
|
||||||
@@ -91,7 +92,7 @@ func TestAllowed(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, item := range table {
|
for _, item := range table {
|
||||||
if e, a := item.allowed, Allowed(item.pods); e != a {
|
if e, a := item.err, Allowed(item.pods); e != fmt.Sprintf("%v", a) {
|
||||||
t.Errorf("Expected %v, got %v: \n%v\v", e, a, item.pods)
|
t.Errorf("Expected %v, got %v: \n%v\v", e, a, item.pods)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -20,10 +20,12 @@ import (
|
|||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
// PortsConflict returns true iff two containers attempt to expose
|
// hostPortsConflict returns an array of host ports that at least two
|
||||||
// the same host port.
|
// containers attempt to expose. The array is empty if no such port
|
||||||
func PortsConflict(pods []api.BoundPod) bool {
|
// exists.
|
||||||
|
func hostPortsConflict(pods []api.BoundPod) []int {
|
||||||
hostPorts := map[int]struct{}{}
|
hostPorts := map[int]struct{}{}
|
||||||
|
conflictingPorts := []int{}
|
||||||
for _, pod := range pods {
|
for _, pod := range pods {
|
||||||
for _, container := range pod.Spec.Containers {
|
for _, container := range pod.Spec.Containers {
|
||||||
for _, port := range container.Ports {
|
for _, port := range container.Ports {
|
||||||
@@ -31,11 +33,11 @@ func PortsConflict(pods []api.BoundPod) bool {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if _, exists := hostPorts[port.HostPort]; exists {
|
if _, exists := hostPorts[port.HostPort]; exists {
|
||||||
return true
|
conflictingPorts = append(conflictingPorts, port.HostPort)
|
||||||
}
|
}
|
||||||
hostPorts[port.HostPort] = struct{}{}
|
hostPorts[port.HostPort] = struct{}{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return conflictingPorts
|
||||||
}
|
}
|
||||||
|
@@ -141,11 +141,24 @@ func (rm *ReplicationManager) watchControllers(resourceVersion *string) {
|
|||||||
}
|
}
|
||||||
if event.Type == watch.Error {
|
if event.Type == watch.Error {
|
||||||
util.HandleError(fmt.Errorf("error from watch during sync: %v", errors.FromObject(event.Object)))
|
util.HandleError(fmt.Errorf("error from watch during sync: %v", errors.FromObject(event.Object)))
|
||||||
|
// Clear the resource version, this may cause us to skip some elements on the watch,
|
||||||
|
// but we'll catch them on the synchronize() call, so it works out.
|
||||||
|
*resourceVersion = ""
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
glog.V(4).Infof("Got watch: %#v", event)
|
glog.V(4).Infof("Got watch: %#v", event)
|
||||||
rc, ok := event.Object.(*api.ReplicationController)
|
rc, ok := event.Object.(*api.ReplicationController)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
if status, ok := event.Object.(*api.Status); ok {
|
||||||
|
if status.Status == api.StatusFailure {
|
||||||
|
glog.Errorf("failed to watch: %v", status)
|
||||||
|
// Clear resource version here, as above, this won't hurt consistency, but we
|
||||||
|
// should consider introspecting more carefully here. (or make the apiserver smarter)
|
||||||
|
// "why not both?"
|
||||||
|
*resourceVersion = ""
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
util.HandleError(fmt.Errorf("unexpected object: %#v", event.Object))
|
util.HandleError(fmt.Errorf("unexpected object: %#v", event.Object))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -166,7 +179,8 @@ func FilterActivePods(pods []api.Pod) []api.Pod {
|
|||||||
var result []api.Pod
|
var result []api.Pod
|
||||||
for _, value := range pods {
|
for _, value := range pods {
|
||||||
if api.PodSucceeded != value.Status.Phase &&
|
if api.PodSucceeded != value.Status.Phase &&
|
||||||
api.PodFailed != value.Status.Phase {
|
api.PodFailed != value.Status.Phase &&
|
||||||
|
api.PodUnknown != value.Status.Phase {
|
||||||
result = append(result, value)
|
result = append(result, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -29,6 +29,7 @@ import (
|
|||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/client/clientcmd"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/client/clientcmd"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl"
|
||||||
cmdconfig "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/config"
|
cmdconfig "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/config"
|
||||||
|
cmdutil "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/resource"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/resource"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
||||||
@@ -143,7 +144,7 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory {
|
|||||||
return kubectl.ReaperFor(mapping.Kind, client)
|
return kubectl.ReaperFor(mapping.Kind, client)
|
||||||
},
|
},
|
||||||
Validator: func(cmd *cobra.Command) (validation.Schema, error) {
|
Validator: func(cmd *cobra.Command) (validation.Schema, error) {
|
||||||
if GetFlagBool(cmd, "validate") {
|
if cmdutil.GetFlagBool(cmd, "validate") {
|
||||||
client, err := clients.ClientForVersion("")
|
client, err := clients.ClientForVersion("")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -217,6 +218,62 @@ Find more information at https://github.com/GoogleCloudPlatform/kubernetes.`,
|
|||||||
return cmds
|
return cmds
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PrintObject prints an api object given command line flags to modify the output format
|
||||||
|
func (f *Factory) PrintObject(cmd *cobra.Command, obj runtime.Object, out io.Writer) error {
|
||||||
|
mapper, _ := f.Object(cmd)
|
||||||
|
_, kind, err := api.Scheme.ObjectVersionAndKind(obj)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
mapping, err := mapper.RESTMapping(kind)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
printer, err := f.PrinterForMapping(cmd, mapping)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return printer.PrintObj(obj, out)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrinterForMapping returns a printer suitable for displaying the provided resource type.
|
||||||
|
// Requires that printer flags have been added to cmd (see AddPrinterFlags).
|
||||||
|
func (f *Factory) PrinterForMapping(cmd *cobra.Command, mapping *meta.RESTMapping) (kubectl.ResourcePrinter, error) {
|
||||||
|
printer, ok, err := cmdutil.PrinterForCommand(cmd)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if ok {
|
||||||
|
clientConfig, err := f.ClientConfig(cmd)
|
||||||
|
checkErr(err)
|
||||||
|
defaultVersion := clientConfig.Version
|
||||||
|
|
||||||
|
version := cmdutil.OutputVersion(cmd, defaultVersion)
|
||||||
|
if len(version) == 0 {
|
||||||
|
version = mapping.APIVersion
|
||||||
|
}
|
||||||
|
if len(version) == 0 {
|
||||||
|
return nil, fmt.Errorf("you must specify an output-version when using this output format")
|
||||||
|
}
|
||||||
|
printer = kubectl.NewVersionedPrinter(printer, mapping.ObjectConvertor, version)
|
||||||
|
} else {
|
||||||
|
printer, err = f.Printer(cmd, mapping, cmdutil.GetFlagBool(cmd, "no-headers"))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return printer, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClientMapperForCommand returns a ClientMapper for the given command and factory.
|
||||||
|
func (f *Factory) ClientMapperForCommand(cmd *cobra.Command) resource.ClientMapper {
|
||||||
|
return resource.ClientMapperFunc(func(mapping *meta.RESTMapping) (resource.RESTClient, error) {
|
||||||
|
return f.RESTClient(cmd, mapping)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// DefaultClientConfig creates a clientcmd.ClientConfig with the following hierarchy:
|
// DefaultClientConfig creates a clientcmd.ClientConfig with the following hierarchy:
|
||||||
// 1. Use the kubeconfig builder. The number of merges and overrides here gets a little crazy. Stay with me.
|
// 1. Use the kubeconfig builder. The number of merges and overrides here gets a little crazy. Stay with me.
|
||||||
// 1. Merge together the kubeconfig itself. This is done with the following hierarchy and merge rules:
|
// 1. Merge together the kubeconfig itself. This is done with the following hierarchy and merge rules:
|
||||||
@@ -266,13 +323,6 @@ func DefaultClientConfig(flags *pflag.FlagSet) clientcmd.ClientConfig {
|
|||||||
return clientConfig
|
return clientConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClientMapperForCommand returns a ClientMapper for the given command and factory.
|
|
||||||
func ClientMapperForCommand(cmd *cobra.Command, f *Factory) resource.ClientMapper {
|
|
||||||
return resource.ClientMapperFunc(func(mapping *meta.RESTMapping) (resource.RESTClient, error) {
|
|
||||||
return f.RESTClient(cmd, mapping)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkErr(err error) {
|
func checkErr(err error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.FatalDepth(1, err)
|
glog.FatalDepth(1, err)
|
||||||
|
@@ -21,6 +21,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||||
@@ -203,3 +204,43 @@ func TestClientVersions(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ExamplePrintReplicationController() {
|
||||||
|
f, tf, codec := NewAPIFactory()
|
||||||
|
tf.Printer = kubectl.NewHumanReadablePrinter(false)
|
||||||
|
tf.Client = &client.FakeRESTClient{
|
||||||
|
Codec: codec,
|
||||||
|
Client: nil,
|
||||||
|
}
|
||||||
|
cmd := f.NewCmdRunContainer(os.Stdout)
|
||||||
|
ctrl := &api.ReplicationController{
|
||||||
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
Name: "foo",
|
||||||
|
Labels: map[string]string{"foo": "bar"},
|
||||||
|
},
|
||||||
|
Spec: api.ReplicationControllerSpec{
|
||||||
|
Replicas: 1,
|
||||||
|
Selector: map[string]string{"foo": "bar"},
|
||||||
|
Template: &api.PodTemplateSpec{
|
||||||
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
Labels: map[string]string{"foo": "bar"},
|
||||||
|
},
|
||||||
|
Spec: api.PodSpec{
|
||||||
|
Containers: []api.Container{
|
||||||
|
{
|
||||||
|
Name: "foo",
|
||||||
|
Image: "someimage",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
err := f.PrintObject(cmd, ctrl, os.Stdout)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
// Output:
|
||||||
|
// CONTROLLER CONTAINER(S) IMAGE(S) SELECTOR REPLICAS
|
||||||
|
// foo foo someimage foo=bar 1
|
||||||
|
}
|
||||||
|
@@ -21,11 +21,12 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/ghodss/yaml"
|
"github.com/golang/glog"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/client/clientcmd"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/client/clientcmd"
|
||||||
clientcmdapi "github.com/GoogleCloudPlatform/kubernetes/pkg/client/clientcmd/api"
|
clientcmdapi "github.com/GoogleCloudPlatform/kubernetes/pkg/client/clientcmd/api"
|
||||||
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
type viewOptions struct {
|
type viewOptions struct {
|
||||||
@@ -38,40 +39,45 @@ func NewCmdConfigView(out io.Writer, pathOptions *pathOptions) *cobra.Command {
|
|||||||
|
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "view",
|
Use: "view",
|
||||||
Short: "displays the specified .kubeconfig file or a merged result",
|
Short: "displays merged .kubeconfig settings or a specified .kubeconfig file.",
|
||||||
Long: `displays the specified .kubeconfig file or a merged result`,
|
Long: `displays merged .kubeconfig settings or a specified .kubeconfig file.
|
||||||
|
Examples:
|
||||||
|
// Show merged .kubeconfig settings.
|
||||||
|
$ kubectl config view
|
||||||
|
|
||||||
|
// Show only local ./.kubeconfig settings
|
||||||
|
$ kubectl config view --local`,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
err := options.run()
|
printer, _, err := util.PrinterForCommand(cmd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("%v\n", err)
|
glog.FatalDepth(1, err)
|
||||||
|
}
|
||||||
|
config, err := options.loadConfig()
|
||||||
|
if err != nil {
|
||||||
|
glog.FatalDepth(1, err)
|
||||||
|
}
|
||||||
|
err = printer.PrintObj(config, out)
|
||||||
|
if err != nil {
|
||||||
|
glog.FatalDepth(1, err)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.Flags().BoolVar(&options.merge, "merge", false, "merge together the full hierarchy of .kubeconfig files")
|
util.AddPrinterFlags(cmd)
|
||||||
|
// Default to yaml
|
||||||
|
cmd.Flags().Set("output", "yaml")
|
||||||
|
cmd.Flags().BoolVar(&options.merge, "merge", true, "merge together the full hierarchy of .kubeconfig files")
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o viewOptions) run() error {
|
func (o viewOptions) loadConfig() (*clientcmdapi.Config, error) {
|
||||||
err := o.validate()
|
err := o.validate()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
config, _, err := o.getStartingConfig()
|
config, _, err := o.getStartingConfig()
|
||||||
if err != nil {
|
return config, err
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
content, err := yaml.Marshal(config)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("%v", string(content))
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o viewOptions) validate() error {
|
func (o viewOptions) validate() error {
|
||||||
|
@@ -51,7 +51,7 @@ Examples:
|
|||||||
checkErr(err)
|
checkErr(err)
|
||||||
|
|
||||||
mapper, typer := f.Object(cmd)
|
mapper, typer := f.Object(cmd)
|
||||||
r := resource.NewBuilder(mapper, typer, ClientMapperForCommand(cmd, f)).
|
r := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand(cmd)).
|
||||||
ContinueOnError().
|
ContinueOnError().
|
||||||
NamespaceParam(cmdNamespace).RequireNamespace().
|
NamespaceParam(cmdNamespace).RequireNamespace().
|
||||||
FilenameParam(flags.Filenames...).
|
FilenameParam(flags.Filenames...).
|
||||||
|
@@ -23,6 +23,7 @@ import (
|
|||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
|
||||||
|
cmdutil "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/resource"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/resource"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
||||||
)
|
)
|
||||||
@@ -62,11 +63,11 @@ Examples:
|
|||||||
checkErr(err)
|
checkErr(err)
|
||||||
|
|
||||||
mapper, typer := f.Object(cmd)
|
mapper, typer := f.Object(cmd)
|
||||||
r := resource.NewBuilder(mapper, typer, ClientMapperForCommand(cmd, f)).
|
r := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand(cmd)).
|
||||||
ContinueOnError().
|
ContinueOnError().
|
||||||
NamespaceParam(cmdNamespace).DefaultNamespace().
|
NamespaceParam(cmdNamespace).DefaultNamespace().
|
||||||
FilenameParam(flags.Filenames...).
|
FilenameParam(flags.Filenames...).
|
||||||
SelectorParam(GetFlagString(cmd, "selector")).
|
SelectorParam(cmdutil.GetFlagString(cmd, "selector")).
|
||||||
ResourceTypeOrNameArgs(args...).
|
ResourceTypeOrNameArgs(args...).
|
||||||
Flatten().
|
Flatten().
|
||||||
Do()
|
Do()
|
||||||
|
@@ -20,6 +20,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -36,7 +37,7 @@ given resource.`,
|
|||||||
checkErr(err)
|
checkErr(err)
|
||||||
|
|
||||||
mapper, _ := f.Object(cmd)
|
mapper, _ := f.Object(cmd)
|
||||||
mapping, namespace, name := ResourceFromArgs(cmd, args, mapper, cmdNamespace)
|
mapping, namespace, name := util.ResourceFromArgs(cmd, args, mapper, cmdNamespace)
|
||||||
|
|
||||||
describer, err := f.Describer(cmd, mapping)
|
describer, err := f.Describer(cmd, mapping)
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
|
@@ -22,6 +22,7 @@ import (
|
|||||||
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl"
|
||||||
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -51,27 +52,28 @@ $ kubectl expose streamer --port=4100 --protocol=udp --service-name=video-stream
|
|||||||
client, err := f.Client(cmd)
|
client, err := f.Client(cmd)
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
|
|
||||||
generatorName := GetFlagString(cmd, "generator")
|
generatorName := util.GetFlagString(cmd, "generator")
|
||||||
|
|
||||||
generator, found := kubectl.Generators[generatorName]
|
generator, found := kubectl.Generators[generatorName]
|
||||||
if !found {
|
if !found {
|
||||||
usageError(cmd, fmt.Sprintf("Generator: %s not found.", generator))
|
usageError(cmd, fmt.Sprintf("Generator: %s not found.", generator))
|
||||||
}
|
}
|
||||||
if GetFlagInt(cmd, "port") < 1 {
|
if util.GetFlagInt(cmd, "port") < 1 {
|
||||||
usageError(cmd, "--port is required and must be a positive integer.")
|
usageError(cmd, "--port is required and must be a positive integer.")
|
||||||
}
|
}
|
||||||
names := generator.ParamNames()
|
names := generator.ParamNames()
|
||||||
params := kubectl.MakeParams(cmd, names)
|
params := kubectl.MakeParams(cmd, names)
|
||||||
if len(GetFlagString(cmd, "service-name")) == 0 {
|
if len(util.GetFlagString(cmd, "service-name")) == 0 {
|
||||||
params["name"] = args[0]
|
params["name"] = args[0]
|
||||||
} else {
|
} else {
|
||||||
params["name"] = GetFlagString(cmd, "service-name")
|
params["name"] = util.GetFlagString(cmd, "service-name")
|
||||||
}
|
}
|
||||||
if _, found := params["selector"]; !found {
|
if _, found := params["selector"]; !found {
|
||||||
rc, err := client.ReplicationControllers(namespace).Get(args[0])
|
rc, err := client.ReplicationControllers(namespace).Get(args[0])
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
params["selector"] = kubectl.MakeLabels(rc.Spec.Selector)
|
params["selector"] = kubectl.MakeLabels(rc.Spec.Selector)
|
||||||
}
|
}
|
||||||
if GetFlagBool(cmd, "create-external-load-balancer") {
|
if util.GetFlagBool(cmd, "create-external-load-balancer") {
|
||||||
params["create-external-load-balancer"] = "true"
|
params["create-external-load-balancer"] = "true"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,22 +83,22 @@ $ kubectl expose streamer --port=4100 --protocol=udp --service-name=video-stream
|
|||||||
service, err := generator.Generate(params)
|
service, err := generator.Generate(params)
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
|
|
||||||
inline := GetFlagString(cmd, "overrides")
|
inline := util.GetFlagString(cmd, "overrides")
|
||||||
if len(inline) > 0 {
|
if len(inline) > 0 {
|
||||||
Merge(service, inline, "Service")
|
util.Merge(service, inline, "Service")
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: extract this flag to a central location, when such a location exists.
|
// TODO: extract this flag to a central location, when such a location exists.
|
||||||
if !GetFlagBool(cmd, "dry-run") {
|
if !util.GetFlagBool(cmd, "dry-run") {
|
||||||
service, err = client.Services(namespace).Create(service.(*api.Service))
|
service, err = client.Services(namespace).Create(service.(*api.Service))
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = PrintObject(cmd, service, f, out)
|
err = f.PrintObject(cmd, service, out)
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
AddPrinterFlags(cmd)
|
util.AddPrinterFlags(cmd)
|
||||||
cmd.Flags().String("generator", "service/v1", "The name of the api generator that you want to use. Default 'service/v1'")
|
cmd.Flags().String("generator", "service/v1", "The name of the api generator that you want to use. Default 'service/v1'")
|
||||||
cmd.Flags().String("protocol", "TCP", "The network protocol for the service you want to be created. Default 'tcp'")
|
cmd.Flags().String("protocol", "TCP", "The network protocol for the service you want to be created. Default 'tcp'")
|
||||||
cmd.Flags().Int("port", -1, "The port that the service should serve on. Required.")
|
cmd.Flags().Int("port", -1, "The port that the service should serve on. Required.")
|
||||||
|
@@ -23,6 +23,7 @@ import (
|
|||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl"
|
||||||
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/resource"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/resource"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
|
||||||
|
|
||||||
@@ -59,7 +60,7 @@ Examples:
|
|||||||
RunGet(f, out, cmd, args)
|
RunGet(f, out, cmd, args)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
AddPrinterFlags(cmd)
|
util.AddPrinterFlags(cmd)
|
||||||
cmd.Flags().StringP("selector", "l", "", "Selector (label query) to filter on")
|
cmd.Flags().StringP("selector", "l", "", "Selector (label query) to filter on")
|
||||||
cmd.Flags().BoolP("watch", "w", false, "After listing/getting the requested object, watch for changes.")
|
cmd.Flags().BoolP("watch", "w", false, "After listing/getting the requested object, watch for changes.")
|
||||||
cmd.Flags().Bool("watch-only", false, "Watch for changes to the requested object(s), without listing/getting first.")
|
cmd.Flags().Bool("watch-only", false, "Watch for changes to the requested object(s), without listing/getting first.")
|
||||||
@@ -70,16 +71,16 @@ Examples:
|
|||||||
// TODO: convert all direct flag accessors to a struct and pass that instead of cmd
|
// TODO: convert all direct flag accessors to a struct and pass that instead of cmd
|
||||||
// TODO: return an error instead of using glog.Fatal and checkErr
|
// TODO: return an error instead of using glog.Fatal and checkErr
|
||||||
func RunGet(f *Factory, out io.Writer, cmd *cobra.Command, args []string) {
|
func RunGet(f *Factory, out io.Writer, cmd *cobra.Command, args []string) {
|
||||||
selector := GetFlagString(cmd, "selector")
|
selector := util.GetFlagString(cmd, "selector")
|
||||||
mapper, typer := f.Object(cmd)
|
mapper, typer := f.Object(cmd)
|
||||||
|
|
||||||
cmdNamespace, err := f.DefaultNamespace(cmd)
|
cmdNamespace, err := f.DefaultNamespace(cmd)
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
|
|
||||||
// handle watch separately since we cannot watch multiple resource types
|
// handle watch separately since we cannot watch multiple resource types
|
||||||
isWatch, isWatchOnly := GetFlagBool(cmd, "watch"), GetFlagBool(cmd, "watch-only")
|
isWatch, isWatchOnly := util.GetFlagBool(cmd, "watch"), util.GetFlagBool(cmd, "watch-only")
|
||||||
if isWatch || isWatchOnly {
|
if isWatch || isWatchOnly {
|
||||||
r := resource.NewBuilder(mapper, typer, ClientMapperForCommand(cmd, f)).
|
r := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand(cmd)).
|
||||||
NamespaceParam(cmdNamespace).DefaultNamespace().
|
NamespaceParam(cmdNamespace).DefaultNamespace().
|
||||||
SelectorParam(selector).
|
SelectorParam(selector).
|
||||||
ResourceTypeOrNameArgs(args...).
|
ResourceTypeOrNameArgs(args...).
|
||||||
@@ -89,7 +90,7 @@ func RunGet(f *Factory, out io.Writer, cmd *cobra.Command, args []string) {
|
|||||||
mapping, err := r.ResourceMapping()
|
mapping, err := r.ResourceMapping()
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
|
|
||||||
printer, err := PrinterForMapping(f, cmd, mapping)
|
printer, err := f.PrinterForMapping(cmd, mapping)
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
|
|
||||||
obj, err := r.Object()
|
obj, err := r.Object()
|
||||||
@@ -115,12 +116,12 @@ func RunGet(f *Factory, out io.Writer, cmd *cobra.Command, args []string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
b := resource.NewBuilder(mapper, typer, ClientMapperForCommand(cmd, f)).
|
b := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand(cmd)).
|
||||||
NamespaceParam(cmdNamespace).DefaultNamespace().
|
NamespaceParam(cmdNamespace).DefaultNamespace().
|
||||||
SelectorParam(selector).
|
SelectorParam(selector).
|
||||||
ResourceTypeOrNameArgs(args...).
|
ResourceTypeOrNameArgs(args...).
|
||||||
Latest()
|
Latest()
|
||||||
printer, generic, err := PrinterForCommand(cmd)
|
printer, generic, err := util.PrinterForCommand(cmd)
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
|
|
||||||
if generic {
|
if generic {
|
||||||
@@ -129,7 +130,7 @@ func RunGet(f *Factory, out io.Writer, cmd *cobra.Command, args []string) {
|
|||||||
defaultVersion := clientConfig.Version
|
defaultVersion := clientConfig.Version
|
||||||
|
|
||||||
// the outermost object will be converted to the output-version
|
// the outermost object will be converted to the output-version
|
||||||
version := outputVersion(cmd, defaultVersion)
|
version := util.OutputVersion(cmd, defaultVersion)
|
||||||
if len(version) == 0 {
|
if len(version) == 0 {
|
||||||
// TODO: add a new ResourceBuilder mode for Object() that attempts to ensure the objects
|
// TODO: add a new ResourceBuilder mode for Object() that attempts to ensure the objects
|
||||||
// are in the appropriate version if one exists (and if not, use the best effort).
|
// are in the appropriate version if one exists (and if not, use the best effort).
|
||||||
@@ -149,7 +150,7 @@ func RunGet(f *Factory, out io.Writer, cmd *cobra.Command, args []string) {
|
|||||||
|
|
||||||
// use the default printer for each object
|
// use the default printer for each object
|
||||||
err = b.Do().Visit(func(r *resource.Info) error {
|
err = b.Do().Visit(func(r *resource.Info) error {
|
||||||
printer, err := PrinterForMapping(f, cmd, r.Mapping)
|
printer, err := f.PrinterForMapping(cmd, r.Mapping)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@@ -20,6 +20,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -66,7 +67,7 @@ Examples:
|
|||||||
}
|
}
|
||||||
|
|
||||||
follow := false
|
follow := false
|
||||||
if GetFlagBool(cmd, "follow") {
|
if util.GetFlagBool(cmd, "follow") {
|
||||||
follow = true
|
follow = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,67 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2014 Google Inc. All rights reserved.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package cmd_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl"
|
|
||||||
. "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd"
|
|
||||||
)
|
|
||||||
|
|
||||||
func ExamplePrintReplicationController() {
|
|
||||||
f, tf, codec := NewAPIFactory()
|
|
||||||
tf.Printer = kubectl.NewHumanReadablePrinter(false)
|
|
||||||
tf.Client = &client.FakeRESTClient{
|
|
||||||
Codec: codec,
|
|
||||||
Client: nil,
|
|
||||||
}
|
|
||||||
cmd := f.NewCmdRunContainer(os.Stdout)
|
|
||||||
ctrl := &api.ReplicationController{
|
|
||||||
ObjectMeta: api.ObjectMeta{
|
|
||||||
Name: "foo",
|
|
||||||
Labels: map[string]string{"foo": "bar"},
|
|
||||||
},
|
|
||||||
Spec: api.ReplicationControllerSpec{
|
|
||||||
Replicas: 1,
|
|
||||||
Selector: map[string]string{"foo": "bar"},
|
|
||||||
Template: &api.PodTemplateSpec{
|
|
||||||
ObjectMeta: api.ObjectMeta{
|
|
||||||
Labels: map[string]string{"foo": "bar"},
|
|
||||||
},
|
|
||||||
Spec: api.PodSpec{
|
|
||||||
Containers: []api.Container{
|
|
||||||
{
|
|
||||||
Name: "foo",
|
|
||||||
Image: "someimage",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
err := PrintObject(cmd, ctrl, f, os.Stdout)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Unexpected error: %v", err)
|
|
||||||
}
|
|
||||||
// Output:
|
|
||||||
// CONTROLLER CONTAINER(S) IMAGE(S) SELECTOR REPLICAS
|
|
||||||
// foo foo someimage foo=bar 1
|
|
||||||
}
|
|
@@ -18,8 +18,10 @@ package cmd
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl"
|
||||||
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
@@ -30,18 +32,23 @@ func (f *Factory) NewCmdProxy(out io.Writer) *cobra.Command {
|
|||||||
Short: "Run a proxy to the Kubernetes API server",
|
Short: "Run a proxy to the Kubernetes API server",
|
||||||
Long: `Run a proxy to the Kubernetes API server.`,
|
Long: `Run a proxy to the Kubernetes API server.`,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
port := GetFlagInt(cmd, "port")
|
port := util.GetFlagInt(cmd, "port")
|
||||||
glog.Infof("Starting to serve on localhost:%d", port)
|
glog.Infof("Starting to serve on localhost:%d", port)
|
||||||
|
|
||||||
clientConfig, err := f.ClientConfig(cmd)
|
clientConfig, err := f.ClientConfig(cmd)
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
|
|
||||||
server, err := kubectl.NewProxyServer(GetFlagString(cmd, "www"), clientConfig)
|
staticPrefix := util.GetFlagString(cmd, "www-prefix")
|
||||||
|
if !strings.HasSuffix(staticPrefix, "/") {
|
||||||
|
staticPrefix += "/"
|
||||||
|
}
|
||||||
|
server, err := kubectl.NewProxyServer(util.GetFlagString(cmd, "www"), staticPrefix, clientConfig)
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
glog.Fatal(server.Serve(port))
|
glog.Fatal(server.Serve(port))
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
cmd.Flags().StringP("www", "w", "", "Also serve static files from the given directory under the prefix /static")
|
cmd.Flags().StringP("www", "w", "", "Also serve static files from the given directory under the specified prefix")
|
||||||
|
cmd.Flags().StringP("www-prefix", "P", "/static/", "Prefix to serve static files under, if static file dir is specified")
|
||||||
cmd.Flags().IntP("port", "p", 8001, "The port on which to run the proxy")
|
cmd.Flags().IntP("port", "p", 8001, "The port on which to run the proxy")
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
@@ -21,6 +21,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl"
|
||||||
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -44,7 +45,7 @@ Examples:
|
|||||||
$ kubectl resize --current-replicas=2 --replicas=3 replicationcontrollers foo
|
$ kubectl resize --current-replicas=2 --replicas=3 replicationcontrollers foo
|
||||||
`,
|
`,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
count := GetFlagInt(cmd, "replicas")
|
count := util.GetFlagInt(cmd, "replicas")
|
||||||
if len(args) != 2 || count < 0 {
|
if len(args) != 2 || count < 0 {
|
||||||
usageError(cmd, "--replicas=<count> <resource> <id>")
|
usageError(cmd, "--replicas=<count> <resource> <id>")
|
||||||
}
|
}
|
||||||
@@ -53,13 +54,13 @@ Examples:
|
|||||||
checkErr(err)
|
checkErr(err)
|
||||||
|
|
||||||
mapper, _ := f.Object(cmd)
|
mapper, _ := f.Object(cmd)
|
||||||
mapping, namespace, name := ResourceFromArgs(cmd, args, mapper, cmdNamespace)
|
mapping, namespace, name := util.ResourceFromArgs(cmd, args, mapper, cmdNamespace)
|
||||||
|
|
||||||
resizer, err := f.Resizer(cmd, mapping)
|
resizer, err := f.Resizer(cmd, mapping)
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
|
|
||||||
resourceVersion := GetFlagString(cmd, "resource-version")
|
resourceVersion := util.GetFlagString(cmd, "resource-version")
|
||||||
currentSize := GetFlagInt(cmd, "current-replicas")
|
currentSize := util.GetFlagInt(cmd, "current-replicas")
|
||||||
s, err := resizer.Resize(namespace, name, &kubectl.ResizePrecondition{currentSize, resourceVersion}, uint(count))
|
s, err := resizer.Resize(namespace, name, &kubectl.ResizePrecondition{currentSize, resourceVersion}, uint(count))
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
fmt.Fprintf(out, "%s\n", s)
|
fmt.Fprintf(out, "%s\n", s)
|
||||||
|
@@ -22,6 +22,7 @@ import (
|
|||||||
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl"
|
||||||
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -48,13 +49,13 @@ $ kubectl rollingupdate frontend-v1 -f frontend-v2.json
|
|||||||
$ cat frontend-v2.json | kubectl rollingupdate frontend-v1 -f -
|
$ cat frontend-v2.json | kubectl rollingupdate frontend-v1 -f -
|
||||||
<update pods of frontend-v1 using json data passed into stdin>`,
|
<update pods of frontend-v1 using json data passed into stdin>`,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
filename := GetFlagString(cmd, "filename")
|
filename := util.GetFlagString(cmd, "filename")
|
||||||
if len(filename) == 0 {
|
if len(filename) == 0 {
|
||||||
usageError(cmd, "Must specify filename for new controller")
|
usageError(cmd, "Must specify filename for new controller")
|
||||||
}
|
}
|
||||||
period := GetFlagDuration(cmd, "update-period")
|
period := util.GetFlagDuration(cmd, "update-period")
|
||||||
interval := GetFlagDuration(cmd, "poll-interval")
|
interval := util.GetFlagDuration(cmd, "poll-interval")
|
||||||
timeout := GetFlagDuration(cmd, "timeout")
|
timeout := util.GetFlagDuration(cmd, "timeout")
|
||||||
if len(args) != 1 {
|
if len(args) != 1 {
|
||||||
usageError(cmd, "Must specify the controller to update")
|
usageError(cmd, "Must specify the controller to update")
|
||||||
}
|
}
|
||||||
@@ -67,7 +68,7 @@ $ cat frontend-v2.json | kubectl rollingupdate frontend-v1 -f -
|
|||||||
cmdApiVersion := clientConfig.Version
|
cmdApiVersion := clientConfig.Version
|
||||||
|
|
||||||
mapper, typer := f.Object(cmd)
|
mapper, typer := f.Object(cmd)
|
||||||
mapping, namespace, newName, data := ResourceFromFile(filename, typer, mapper, schema, cmdApiVersion)
|
mapping, namespace, newName, data := util.ResourceFromFile(filename, typer, mapper, schema, cmdApiVersion)
|
||||||
if mapping.Kind != "ReplicationController" {
|
if mapping.Kind != "ReplicationController" {
|
||||||
usageError(cmd, "%s does not specify a valid ReplicationController", filename)
|
usageError(cmd, "%s does not specify a valid ReplicationController", filename)
|
||||||
}
|
}
|
||||||
@@ -78,7 +79,7 @@ $ cat frontend-v2.json | kubectl rollingupdate frontend-v1 -f -
|
|||||||
|
|
||||||
cmdNamespace, err := f.DefaultNamespace(cmd)
|
cmdNamespace, err := f.DefaultNamespace(cmd)
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
err = CompareNamespace(cmdNamespace, namespace)
|
err = util.CompareNamespace(cmdNamespace, namespace)
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
|
|
||||||
client, err := f.Client(cmd)
|
client, err := f.Client(cmd)
|
||||||
|
@@ -22,6 +22,7 @@ import (
|
|||||||
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl"
|
||||||
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -55,7 +56,7 @@ Examples:
|
|||||||
client, err := f.Client(cmd)
|
client, err := f.Client(cmd)
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
|
|
||||||
generatorName := GetFlagString(cmd, "generator")
|
generatorName := util.GetFlagString(cmd, "generator")
|
||||||
generator, found := kubectl.Generators[generatorName]
|
generator, found := kubectl.Generators[generatorName]
|
||||||
if !found {
|
if !found {
|
||||||
usageError(cmd, fmt.Sprintf("Generator: %s not found.", generator))
|
usageError(cmd, fmt.Sprintf("Generator: %s not found.", generator))
|
||||||
@@ -70,22 +71,22 @@ Examples:
|
|||||||
controller, err := generator.Generate(params)
|
controller, err := generator.Generate(params)
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
|
|
||||||
inline := GetFlagString(cmd, "overrides")
|
inline := util.GetFlagString(cmd, "overrides")
|
||||||
if len(inline) > 0 {
|
if len(inline) > 0 {
|
||||||
Merge(controller, inline, "ReplicationController")
|
util.Merge(controller, inline, "ReplicationController")
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: extract this flag to a central location, when such a location exists.
|
// TODO: extract this flag to a central location, when such a location exists.
|
||||||
if !GetFlagBool(cmd, "dry-run") {
|
if !util.GetFlagBool(cmd, "dry-run") {
|
||||||
controller, err = client.ReplicationControllers(namespace).Create(controller.(*api.ReplicationController))
|
controller, err = client.ReplicationControllers(namespace).Create(controller.(*api.ReplicationController))
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = PrintObject(cmd, controller, f, out)
|
err = f.PrintObject(cmd, controller, out)
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
AddPrinterFlags(cmd)
|
util.AddPrinterFlags(cmd)
|
||||||
cmd.Flags().String("generator", "run-container/v1", "The name of the api generator that you want to use. Default 'run-container-controller/v1'")
|
cmd.Flags().String("generator", "run-container/v1", "The name of the api generator that you want to use. Default 'run-container-controller/v1'")
|
||||||
cmd.Flags().String("image", "", "The image for the container you wish to run.")
|
cmd.Flags().String("image", "", "The image for the container you wish to run.")
|
||||||
cmd.Flags().IntP("replicas", "r", 1, "Number of replicas to create for this container. Default 1")
|
cmd.Flags().IntP("replicas", "r", 1, "Number of replicas to create for this container. Default 1")
|
||||||
|
@@ -20,6 +20,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -42,7 +43,7 @@ Examples:
|
|||||||
}
|
}
|
||||||
cmdNamespace, err := f.DefaultNamespace(cmd)
|
cmdNamespace, err := f.DefaultNamespace(cmd)
|
||||||
mapper, _ := f.Object(cmd)
|
mapper, _ := f.Object(cmd)
|
||||||
mapping, namespace, name := ResourceFromArgs(cmd, args, mapper, cmdNamespace)
|
mapping, namespace, name := util.ResourceFromArgs(cmd, args, mapper, cmdNamespace)
|
||||||
|
|
||||||
reaper, err := f.Reaper(cmd, mapping)
|
reaper, err := f.Reaper(cmd, mapping)
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
|
@@ -20,6 +20,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
|
cmdutil "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/resource"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/resource"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
@@ -53,14 +54,14 @@ Examples:
|
|||||||
checkErr(err)
|
checkErr(err)
|
||||||
|
|
||||||
mapper, typer := f.Object(cmd)
|
mapper, typer := f.Object(cmd)
|
||||||
r := resource.NewBuilder(mapper, typer, ClientMapperForCommand(cmd, f)).
|
r := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand(cmd)).
|
||||||
ContinueOnError().
|
ContinueOnError().
|
||||||
NamespaceParam(cmdNamespace).RequireNamespace().
|
NamespaceParam(cmdNamespace).RequireNamespace().
|
||||||
FilenameParam(flags.Filenames...).
|
FilenameParam(flags.Filenames...).
|
||||||
Flatten().
|
Flatten().
|
||||||
Do()
|
Do()
|
||||||
|
|
||||||
patch := GetFlagString(cmd, "patch")
|
patch := cmdutil.GetFlagString(cmd, "patch")
|
||||||
if len(flags.Filenames) == 0 && len(patch) == 0 {
|
if len(flags.Filenames) == 0 && len(patch) == 0 {
|
||||||
usageError(cmd, "Must specify --filename or --patch to update")
|
usageError(cmd, "Must specify --filename or --patch to update")
|
||||||
}
|
}
|
||||||
@@ -102,7 +103,7 @@ func updateWithPatch(cmd *cobra.Command, args []string, f *Factory, patch string
|
|||||||
checkErr(err)
|
checkErr(err)
|
||||||
|
|
||||||
mapper, _ := f.Object(cmd)
|
mapper, _ := f.Object(cmd)
|
||||||
mapping, namespace, name := ResourceFromArgs(cmd, args, mapper, cmdNamespace)
|
mapping, namespace, name := cmdutil.ResourceFromArgs(cmd, args, mapper, cmdNamespace)
|
||||||
client, err := f.RESTClient(cmd, mapping)
|
client, err := f.RESTClient(cmd, mapping)
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
|
|
||||||
@@ -110,7 +111,7 @@ func updateWithPatch(cmd *cobra.Command, args []string, f *Factory, patch string
|
|||||||
obj, err := helper.Get(namespace, name)
|
obj, err := helper.Get(namespace, name)
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
|
|
||||||
Merge(obj, patch, mapping.Kind)
|
cmdutil.Merge(obj, patch, mapping.Kind)
|
||||||
|
|
||||||
data, err := helper.Codec.Encode(obj)
|
data, err := helper.Codec.Encode(obj)
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
|
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package cmd
|
package util
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
@@ -34,6 +34,18 @@ import (
|
|||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func checkErr(err error) {
|
||||||
|
if err != nil {
|
||||||
|
glog.FatalDepth(1, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func usageError(cmd *cobra.Command, format string, args ...interface{}) {
|
||||||
|
glog.Errorf(format, args...)
|
||||||
|
glog.Errorf("See '%s -h' for help.", cmd.CommandPath())
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
func GetFlagString(cmd *cobra.Command, flag string) string {
|
func GetFlagString(cmd *cobra.Command, flag string) string {
|
||||||
f := cmd.Flags().Lookup(flag)
|
f := cmd.Flags().Lookup(flag)
|
||||||
if f == nil {
|
if f == nil {
|
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package cmd
|
package util
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"reflect"
|
"reflect"
|
@@ -14,16 +14,10 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package cmd
|
package util
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/meta"
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
|
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
@@ -35,28 +29,8 @@ func AddPrinterFlags(cmd *cobra.Command) {
|
|||||||
cmd.Flags().StringP("template", "t", "", "Template string or path to template file to use when -o=template or -o=templatefile.")
|
cmd.Flags().StringP("template", "t", "", "Template string or path to template file to use when -o=template or -o=templatefile.")
|
||||||
}
|
}
|
||||||
|
|
||||||
// PrintObject prints an api object given command line flags to modify the output format
|
// OutputVersion returns the preferred output version for generic content (JSON, YAML, or templates)
|
||||||
func PrintObject(cmd *cobra.Command, obj runtime.Object, f *Factory, out io.Writer) error {
|
func OutputVersion(cmd *cobra.Command, defaultVersion string) string {
|
||||||
mapper, _ := f.Object(cmd)
|
|
||||||
_, kind, err := api.Scheme.ObjectVersionAndKind(obj)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
mapping, err := mapper.RESTMapping(kind)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
printer, err := PrinterForMapping(f, cmd, mapping)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return printer.PrintObj(obj, out)
|
|
||||||
}
|
|
||||||
|
|
||||||
// outputVersion returns the preferred output version for generic content (JSON, YAML, or templates)
|
|
||||||
func outputVersion(cmd *cobra.Command, defaultVersion string) string {
|
|
||||||
outputVersion := GetFlagString(cmd, "output-version")
|
outputVersion := GetFlagString(cmd, "output-version")
|
||||||
if len(outputVersion) == 0 {
|
if len(outputVersion) == 0 {
|
||||||
outputVersion = defaultVersion
|
outputVersion = defaultVersion
|
||||||
@@ -75,32 +49,3 @@ func PrinterForCommand(cmd *cobra.Command) (kubectl.ResourcePrinter, bool, error
|
|||||||
|
|
||||||
return kubectl.GetPrinter(outputFormat, templateFile)
|
return kubectl.GetPrinter(outputFormat, templateFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
// PrinterForMapping returns a printer suitable for displaying the provided resource type.
|
|
||||||
// Requires that printer flags have been added to cmd (see AddPrinterFlags).
|
|
||||||
func PrinterForMapping(f *Factory, cmd *cobra.Command, mapping *meta.RESTMapping) (kubectl.ResourcePrinter, error) {
|
|
||||||
printer, ok, err := PrinterForCommand(cmd)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if ok {
|
|
||||||
clientConfig, err := f.ClientConfig(cmd)
|
|
||||||
checkErr(err)
|
|
||||||
defaultVersion := clientConfig.Version
|
|
||||||
|
|
||||||
version := outputVersion(cmd, defaultVersion)
|
|
||||||
if len(version) == 0 {
|
|
||||||
version = mapping.APIVersion
|
|
||||||
}
|
|
||||||
if len(version) == 0 {
|
|
||||||
return nil, fmt.Errorf("you must specify an output-version when using this output format")
|
|
||||||
}
|
|
||||||
printer = kubectl.NewVersionedPrinter(printer, mapping.ObjectConvertor, version)
|
|
||||||
} else {
|
|
||||||
printer, err = f.Printer(cmd, mapping, GetFlagBool(cmd, "no-headers"))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return printer, nil
|
|
||||||
}
|
|
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package cmd
|
package util
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
@@ -22,6 +22,7 @@ import (
|
|||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl"
|
||||||
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (f *Factory) NewCmdVersion(out io.Writer) *cobra.Command {
|
func (f *Factory) NewCmdVersion(out io.Writer) *cobra.Command {
|
||||||
@@ -29,7 +30,7 @@ func (f *Factory) NewCmdVersion(out io.Writer) *cobra.Command {
|
|||||||
Use: "version",
|
Use: "version",
|
||||||
Short: "Print version of client and server",
|
Short: "Print version of client and server",
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
if GetFlagBool(cmd, "client") {
|
if util.GetFlagBool(cmd, "client") {
|
||||||
kubectl.GetClientVersion(out)
|
kubectl.GetClientVersion(out)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@@ -33,7 +33,7 @@ type ProxyServer struct {
|
|||||||
|
|
||||||
// NewProxyServer creates and installs a new ProxyServer.
|
// NewProxyServer creates and installs a new ProxyServer.
|
||||||
// It automatically registers the created ProxyServer to http.DefaultServeMux.
|
// It automatically registers the created ProxyServer to http.DefaultServeMux.
|
||||||
func NewProxyServer(filebase string, cfg *client.Config) (*ProxyServer, error) {
|
func NewProxyServer(filebase string, staticPrefix string, cfg *client.Config) (*ProxyServer, error) {
|
||||||
prefix := cfg.Prefix
|
prefix := cfg.Prefix
|
||||||
if prefix == "" {
|
if prefix == "" {
|
||||||
prefix = "/api"
|
prefix = "/api"
|
||||||
@@ -47,7 +47,7 @@ func NewProxyServer(filebase string, cfg *client.Config) (*ProxyServer, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
http.Handle("/api/", http.StripPrefix("/api/", proxy))
|
http.Handle("/api/", http.StripPrefix("/api/", proxy))
|
||||||
http.Handle("/static/", newFileHandler("/static/", filebase))
|
http.Handle(staticPrefix, newFileHandler(staticPrefix, filebase))
|
||||||
return proxy, nil
|
return proxy, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -25,6 +25,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -104,7 +105,7 @@ type dockerContainerCommandRunner struct {
|
|||||||
var dockerAPIVersionWithExec = []uint{1, 15}
|
var dockerAPIVersionWithExec = []uint{1, 15}
|
||||||
|
|
||||||
// Returns the major and minor version numbers of docker server.
|
// Returns the major and minor version numbers of docker server.
|
||||||
func (d *dockerContainerCommandRunner) getDockerServerVersion() ([]uint, error) {
|
func (d *dockerContainerCommandRunner) GetDockerServerVersion() ([]uint, error) {
|
||||||
env, err := d.client.Version()
|
env, err := d.client.Version()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to get docker server version - %v", err)
|
return nil, fmt.Errorf("failed to get docker server version - %v", err)
|
||||||
@@ -127,7 +128,7 @@ func (d *dockerContainerCommandRunner) getDockerServerVersion() ([]uint, error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *dockerContainerCommandRunner) nativeExecSupportExists() (bool, error) {
|
func (d *dockerContainerCommandRunner) nativeExecSupportExists() (bool, error) {
|
||||||
version, err := d.getDockerServerVersion()
|
version, err := d.GetDockerServerVersion()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
@@ -641,6 +642,35 @@ func parseImageName(image string) (string, string) {
|
|||||||
return image, tag
|
return image, tag
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get a docker endpoint, either from the string passed in, or $DOCKER_HOST environment variables
|
||||||
|
func getDockerEndpoint(dockerEndpoint string) string {
|
||||||
|
var endpoint string
|
||||||
|
if len(dockerEndpoint) > 0 {
|
||||||
|
endpoint = dockerEndpoint
|
||||||
|
} else if len(os.Getenv("DOCKER_HOST")) > 0 {
|
||||||
|
endpoint = os.Getenv("DOCKER_HOST")
|
||||||
|
} else {
|
||||||
|
endpoint = "unix:///var/run/docker.sock"
|
||||||
|
}
|
||||||
|
glog.Infof("Connecting to docker on %s", endpoint)
|
||||||
|
|
||||||
|
return endpoint
|
||||||
|
}
|
||||||
|
|
||||||
|
func ConnectToDockerOrDie(dockerEndpoint string) DockerInterface {
|
||||||
|
if dockerEndpoint == "fake://" {
|
||||||
|
return &FakeDockerClient{
|
||||||
|
VersionInfo: []string{"apiVersion=1.16"},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
client, err := docker.NewClient(getDockerEndpoint(dockerEndpoint))
|
||||||
|
if err != nil {
|
||||||
|
glog.Fatal("Couldn't connect to docker.")
|
||||||
|
}
|
||||||
|
return client
|
||||||
|
}
|
||||||
|
|
||||||
type ContainerCommandRunner interface {
|
type ContainerCommandRunner interface {
|
||||||
RunInContainer(containerID string, cmd []string) ([]byte, error)
|
RunInContainer(containerID string, cmd []string) ([]byte, error)
|
||||||
|
GetDockerServerVersion() ([]uint, error)
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user