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:
|
||||
* 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
|
||||
* Cluster deployment scripts for various clouds
|
||||
* Tar file containing all server binaries
|
||||
|
@@ -46,3 +46,5 @@ echo "... calling setup-logging-firewall" >&2
|
||||
setup-logging-firewall
|
||||
|
||||
echo "Done" >&2
|
||||
|
||||
exit 0
|
||||
|
@@ -123,7 +123,7 @@ elif [[ "${KUBERNETES_PROVIDER}" == "gke" ]]; then
|
||||
)
|
||||
fi
|
||||
|
||||
detect-master &> /dev/null
|
||||
detect-master > /dev/null
|
||||
if [[ -n "${KUBE_MASTER_IP-}" && -z "${KUBERNETES_MASTER-}" ]]; then
|
||||
export KUBERNETES_MASTER=https://${KUBE_MASTER_IP}
|
||||
fi
|
||||
|
@@ -96,7 +96,7 @@ func (fakeKubeletClient) GetPodStatus(host, podNamespace, podID string) (api.Pod
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func (fakeKubeletClient) HealthCheck(host string) (probe.Status, error) {
|
||||
func (fakeKubeletClient) HealthCheck(host string) (probe.Result, error) {
|
||||
return probe.Success, nil
|
||||
}
|
||||
|
||||
|
@@ -33,6 +33,7 @@ import (
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
|
||||
nodeControllerPkg "github.com/GoogleCloudPlatform/kubernetes/pkg/cloudprovider/controller"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/controller"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/dockertools"
|
||||
kubeletServer "github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/server"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/master"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/master/ports"
|
||||
@@ -139,7 +140,7 @@ func startComponents(etcdClient tools.EtcdClient, cl *client.Client, addr net.IP
|
||||
runScheduler(cl)
|
||||
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())
|
||||
}
|
||||
|
||||
|
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
|
||||
# limitations under the License.
|
||||
|
||||
set -o errexit
|
||||
set -o nounset
|
||||
set -o pipefail
|
||||
|
||||
KUBE_ROOT=$(dirname "${BASH_SOURCE}")/..
|
||||
source "${KUBE_ROOT}/cluster/kube-env.sh"
|
||||
source "${KUBE_ROOT}/cluster/${KUBERNETES_PROVIDER}/util.sh"
|
||||
|
||||
${KUBE_ROOT}/hack/e2e-suite/goe2e.sh -tTestNetwork
|
||||
set -ex
|
||||
if [ ! -d ${SRC}/themes ]; then
|
||||
ln -s /themes ${SRC}/themes
|
||||
fi
|
||||
hugo $(eval echo $*) # force default CMD env expansion
|
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
|
||||
User=kube
|
||||
ExecStart=/usr/bin/kube-apiserver \
|
||||
${KUBE_LOGTOSTDERR} \
|
||||
${KUBE_LOG_LEVEL} \
|
||||
${KUBE_ETCD_SERVERS} \
|
||||
${KUBE_API_ADDRESS} \
|
||||
${KUBE_API_PORT} \
|
||||
${KUBELET_PORT} \
|
||||
${KUBE_ALLOW_PRIV} \
|
||||
${KUBE_SERVICE_ADDRESSES} \
|
||||
${KUBE_API_ARGS}
|
||||
$KUBE_LOGTOSTDERR \
|
||||
$KUBE_LOG_LEVEL \
|
||||
$KUBE_ETCD_SERVERS \
|
||||
$KUBE_API_ADDRESS \
|
||||
$KUBE_API_PORT \
|
||||
$KUBELET_PORT \
|
||||
$KUBE_ALLOW_PRIV \
|
||||
$KUBE_SERVICE_ADDRESSES \
|
||||
$KUBE_API_ARGS
|
||||
Restart=on-failure
|
||||
|
||||
[Install]
|
||||
|
@@ -8,11 +8,11 @@ EnvironmentFile=-/etc/kubernetes/apiserver
|
||||
EnvironmentFile=-/etc/kubernetes/controller-manager
|
||||
User=kube
|
||||
ExecStart=/usr/bin/kube-controller-manager \
|
||||
${KUBE_LOGTOSTDERR} \
|
||||
${KUBE_LOG_LEVEL} \
|
||||
${KUBELET_ADDRESSES} \
|
||||
${KUBE_MASTER} \
|
||||
${KUBE_CONTROLLER_MANAGER_ARGS}
|
||||
$KUBE_LOGTOSTDERR \
|
||||
$KUBE_LOG_LEVEL \
|
||||
$KUBELET_ADDRESSES \
|
||||
$KUBE_MASTER \
|
||||
$KUBE_CONTROLLER_MANAGER_ARGS
|
||||
Restart=on-failure
|
||||
|
||||
[Install]
|
||||
|
@@ -6,10 +6,10 @@ Documentation=https://github.com/GoogleCloudPlatform/kubernetes
|
||||
EnvironmentFile=-/etc/kubernetes/config
|
||||
EnvironmentFile=-/etc/kubernetes/proxy
|
||||
ExecStart=/usr/bin/kube-proxy \
|
||||
${KUBE_LOGTOSTDERR} \
|
||||
${KUBE_LOG_LEVEL} \
|
||||
${KUBE_ETCD_SERVERS} \
|
||||
${KUBE_PROXY_ARGS}
|
||||
$KUBE_LOGTOSTDERR \
|
||||
$KUBE_LOG_LEVEL \
|
||||
$KUBE_ETCD_SERVERS \
|
||||
$KUBE_PROXY_ARGS
|
||||
Restart=on-failure
|
||||
|
||||
[Install]
|
||||
|
@@ -8,10 +8,10 @@ EnvironmentFile=-/etc/kubernetes/apiserver
|
||||
EnvironmentFile=-/etc/kubernetes/scheduler
|
||||
User=kube
|
||||
ExecStart=/usr/bin/kube-scheduler \
|
||||
${KUBE_LOGTOSTDERR} \
|
||||
${KUBE_LOG_LEVEL} \
|
||||
${KUBE_MASTER} \
|
||||
${KUBE_SCHEDULER_ARGS}
|
||||
$KUBE_LOGTOSTDERR \
|
||||
$KUBE_LOG_LEVEL \
|
||||
$KUBE_MASTER \
|
||||
$KUBE_SCHEDULER_ARGS
|
||||
Restart=on-failure
|
||||
|
||||
[Install]
|
||||
|
@@ -9,14 +9,14 @@ WorkingDirectory=/var/lib/kubelet
|
||||
EnvironmentFile=-/etc/kubernetes/config
|
||||
EnvironmentFile=-/etc/kubernetes/kubelet
|
||||
ExecStart=/usr/bin/kubelet \
|
||||
${KUBE_LOGTOSTDERR} \
|
||||
${KUBE_LOG_LEVEL} \
|
||||
${KUBE_ETCD_SERVERS} \
|
||||
${KUBELET_ADDRESS} \
|
||||
${KUBELET_PORT} \
|
||||
${KUBELET_HOSTNAME} \
|
||||
${KUBE_ALLOW_PRIV} \
|
||||
${KUBELET_ARGS}
|
||||
$KUBE_LOGTOSTDERR \
|
||||
$KUBE_LOG_LEVEL \
|
||||
$KUBE_ETCD_SERVERS \
|
||||
$KUBELET_ADDRESS \
|
||||
$KUBELET_PORT \
|
||||
$KUBELET_HOSTNAME \
|
||||
$KUBE_ALLOW_PRIV \
|
||||
$KUBELET_ARGS
|
||||
Restart=on-failure
|
||||
|
||||
[Install]
|
||||
|
@@ -14,7 +14,7 @@ The example below creates an elastic Kubernetes cluster with 3 worker nodes and
|
||||
|
||||
## Prerequisites
|
||||
|
||||
* [kubecfg CLI](aws/kubecfg.md)
|
||||
* [kubectl CLI](aws/kubectl.md)
|
||||
* [aws CLI](http://aws.amazon.com/cli)
|
||||
* [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
|
||||
```
|
||||
|
||||
[Skip to kubecfg client configuration](#configure-the-kubecfg-ssh-tunnel)
|
||||
[Skip to kubectl client configuration](#configure-the-kubectl-ssh-tunnel)
|
||||
|
||||
### Manually
|
||||
|
||||
@@ -121,9 +121,9 @@ aws ec2 run-instances --count 1 --image-id <ami_image_id> --key-name <keypair> \
|
||||
--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>
|
||||
@@ -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.
|
||||
|
||||
```
|
||||
kubecfg list minions
|
||||
kubectl get nodes
|
||||
```
|
||||
|
||||
## 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
|
||||
|
||||
```
|
||||
kubecfg list pods
|
||||
kubectl get pods
|
||||
```
|
||||
|
||||
> 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
|
||||
|
||||
```
|
||||
kubecfg delete pods/hello
|
||||
kubectl delete pods hello
|
||||
```
|
||||
|
@@ -247,7 +247,7 @@
|
||||
" ExecStart=/opt/bin/kube-apiserver \\\n",
|
||||
" --address=0.0.0.0 \\\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",
|
||||
" --public_address_override=$private_ipv4 \\\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)
|
||||
|
||||
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.
|
||||
|
||||
```
|
||||
cd kubernetes
|
||||
cluster/kubecfg.sh -p 8080:80 run dockerfile/nginx 2 myNginx
|
||||
The `kubectl.sh` line below spins up two containers running
|
||||
[Nginx](http://nginx.org/en/) running on port 80:
|
||||
|
||||
```bash
|
||||
cluster/kubectl.sh run-container my-nginx --image=dockerfile/nginx --replicas=2 --port=80
|
||||
```
|
||||
|
||||
To stop the containers:
|
||||
```
|
||||
cluster/kubecfg.sh stop myNginx
|
||||
|
||||
```bash
|
||||
cluster/kubectl.sh stop rc my-nginx
|
||||
```
|
||||
|
||||
To delete the containers:
|
||||
```
|
||||
cluster/kubecfg.sh rm myNginx
|
||||
|
||||
```bash
|
||||
cluster/kubectl.sh delete rc my-nginx
|
||||
```
|
||||
|
||||
### 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
|
||||
your Go workspace and builds the Go components.
|
||||
|
||||
The `kubecfg.sh` line below spins up two containers running
|
||||
[Nginx](http://nginx.org/en/) with port 80 mapped to 8080:
|
||||
The `kubectl.sh` line below spins up two containers running
|
||||
[Nginx](http://nginx.org/en/) running on port 80:
|
||||
|
||||
```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:
|
||||
|
||||
```bash
|
||||
cluster/kubecfg.sh stop myNginx
|
||||
cluster/kubectl.sh stop rc my-nginx
|
||||
```
|
||||
|
||||
To delete the containers:
|
||||
|
||||
```bash
|
||||
cluster/kubecfg.sh rm myNginx
|
||||
cluster/kubectl.sh delete rc my-nginx
|
||||
```
|
||||
|
||||
### 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
|
||||
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
|
||||
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!
|
||||
|
||||
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 services
|
||||
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
|
||||
|
@@ -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.
|
||||
|
||||
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
|
||||
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
|
||||
(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:
|
||||
@@ -231,7 +230,7 @@ NAME LABELS SELECTOR IP PORT
|
||||
|
||||
$ cluster/kubectl.sh get replicationControllers
|
||||
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.
|
||||
@@ -239,7 +238,7 @@ Check the [guestbook](../../examples/guestbook/README.md) application to learn h
|
||||
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
|
||||
NAME IMAGE(S) HOST LABELS STATUS
|
||||
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
|
||||
--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
|
||||
-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]
|
||||
|
||||
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-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
|
||||
@@ -394,7 +395,13 @@ Use "kubectl help [command]" for more information about that command.
|
||||
```
|
||||
|
||||
#### 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:
|
||||
```
|
||||
@@ -420,10 +427,14 @@ Usage:
|
||||
--log_flush_frequency=5s: Maximum number of seconds between log flushes
|
||||
--logtostderr=true: log to standard error instead of files
|
||||
--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.
|
||||
--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
|
||||
--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.
|
||||
--user="": The name of the kubeconfig user to use
|
||||
--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).
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
$ cd kubernetes
|
||||
|
@@ -22,8 +22,17 @@ set -o nounset
|
||||
set -o pipefail
|
||||
|
||||
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/${KUBERNETES_PROVIDER}/util.sh"
|
||||
source "${KUBE_VERSION_ROOT}/cluster/${KUBERNETES_PROVIDER}/util.sh"
|
||||
|
||||
prepare-e2e
|
||||
|
||||
if [[ "${KUBERNETES_PROVIDER}" != "gce" ]] && [[ "${KUBERNETES_PROVIDER}" != "gke" ]]; then
|
||||
echo "WARNING: Skipping certs.sh for cloud provider: ${KUBERNETES_PROVIDER}."
|
||||
|
@@ -23,8 +23,17 @@ set -o nounset
|
||||
set -o pipefail
|
||||
|
||||
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/$KUBERNETES_PROVIDER/util.sh"
|
||||
source "${KUBE_VERSION_ROOT}/cluster/${KUBERNETES_PROVIDER}/util.sh"
|
||||
|
||||
prepare-e2e
|
||||
|
||||
GUESTBOOK="${KUBE_ROOT}/examples/guestbook"
|
||||
|
||||
|
@@ -22,8 +22,17 @@ set -o nounset
|
||||
set -o pipefail
|
||||
|
||||
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/$KUBERNETES_PROVIDER/util.sh"
|
||||
source "${KUBE_VERSION_ROOT}/cluster/${KUBERNETES_PROVIDER}/util.sh"
|
||||
|
||||
prepare-e2e
|
||||
|
||||
liveness_tests="http exec"
|
||||
if [[ ${KUBERNETES_PROVIDER} == "gke" ]]; then
|
||||
|
@@ -23,8 +23,17 @@ set -o nounset
|
||||
set -o pipefail
|
||||
|
||||
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/$KUBERNETES_PROVIDER/util.sh"
|
||||
source "${KUBE_VERSION_ROOT}/cluster/${KUBERNETES_PROVIDER}/util.sh"
|
||||
|
||||
prepare-e2e
|
||||
|
||||
MONITORING="${KUBE_ROOT}/cluster/addons/cluster-monitoring"
|
||||
KUBECTL="${KUBE_ROOT}/cluster/kubectl.sh"
|
||||
|
@@ -22,8 +22,17 @@ set -o nounset
|
||||
set -o pipefail
|
||||
|
||||
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/$KUBERNETES_PROVIDER/util.sh"
|
||||
source "${KUBE_VERSION_ROOT}/cluster/${KUBERNETES_PROVIDER}/util.sh"
|
||||
|
||||
prepare-e2e
|
||||
|
||||
if [[ "$KUBERNETES_PROVIDER" != "gce" ]] && [[ "$KUBERNETES_PROVIDER" != "gke" ]]; then
|
||||
echo "WARNING: Skipping pd.sh for cloud provider: ${KUBERNETES_PROVIDER}."
|
||||
|
@@ -21,8 +21,17 @@ set -o nounset
|
||||
set -o pipefail
|
||||
|
||||
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/${KUBERNETES_PROVIDER}/util.sh"
|
||||
source "${KUBE_VERSION_ROOT}/cluster/${KUBERNETES_PROVIDER}/util.sh"
|
||||
|
||||
prepare-e2e
|
||||
|
||||
if [[ "$KUBERNETES_PROVIDER" == "vagrant" ]]; then
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
|
@@ -15,6 +15,6 @@
|
||||
# limitations under the License.
|
||||
|
||||
# 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 $?
|
||||
|
159
hack/e2e.go
159
hack/e2e.go
@@ -30,10 +30,8 @@ import (
|
||||
"os/signal"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -44,12 +42,8 @@ var (
|
||||
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.")
|
||||
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 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).")
|
||||
test = flag.Bool("test", false, "Run Ginkgo tests.")
|
||||
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.")
|
||||
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, ""+
|
||||
@@ -95,21 +89,6 @@ func main() {
|
||||
flag.Parse()
|
||||
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 {
|
||||
status := 1
|
||||
if IsUp() {
|
||||
@@ -137,9 +116,12 @@ func main() {
|
||||
log.Fatalf("Error preparing a binary of version %s: %s. Aborting.", *version, err)
|
||||
} else {
|
||||
versionRoot = newVersionRoot
|
||||
os.Setenv("KUBE_VERSION_ROOT", newVersionRoot)
|
||||
}
|
||||
}
|
||||
|
||||
os.Setenv("KUBECTL", versionRoot+`/cluster/kubectl.sh`+kubectlArgs())
|
||||
|
||||
if *pushup {
|
||||
if IsUp() {
|
||||
log.Printf("e2e cluster is up, pushing.")
|
||||
@@ -165,8 +147,8 @@ func main() {
|
||||
switch {
|
||||
case *ctlCmd != "":
|
||||
failure = !runBash("'kubectl "+*ctlCmd+"'", "$KUBECTL "+*ctlCmd)
|
||||
case *tests != "":
|
||||
failure = PrintResults(Test())
|
||||
case *test:
|
||||
failure = Test()
|
||||
}
|
||||
|
||||
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")()
|
||||
|
||||
if !IsUp() {
|
||||
@@ -284,128 +266,7 @@ func Test() (results ResultsByTest) {
|
||||
|
||||
ValidateClusterSize()
|
||||
|
||||
// run tests!
|
||||
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)
|
||||
return runBash("Ginkgo tests", filepath.Join(*root, "hack", "ginkgo-e2e.sh"))
|
||||
}
|
||||
|
||||
// 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)
|
||||
headerprefix := stepName + " "
|
||||
lineprefix := " "
|
||||
if *tap {
|
||||
headerprefix = "# " + headerprefix
|
||||
lineprefix = "# " + lineprefix
|
||||
}
|
||||
printBashOutputs(headerprefix, lineprefix, string(stdout.Bytes()), string(stderr.Bytes()), false)
|
||||
}
|
||||
}
|
||||
|
@@ -14,9 +14,22 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
KUBE_ROOT=$(dirname "${BASH_SOURCE}")/../..
|
||||
set -o errexit
|
||||
set -o nounset
|
||||
set -o pipefail
|
||||
|
||||
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/$KUBERNETES_PROVIDER/util.sh"
|
||||
source "${KUBE_VERSION_ROOT}/cluster/${KUBERNETES_PROVIDER}/util.sh"
|
||||
|
||||
prepare-e2e
|
||||
|
||||
detect-master >/dev/null
|
||||
|
||||
@@ -89,5 +102,6 @@ fi
|
||||
"${e2e}" "${auth_config[@]:+${auth_config[@]}}" \
|
||||
--host="https://${KUBE_MASTER_IP-}" \
|
||||
--provider="${KUBERNETES_PROVIDER}" \
|
||||
--ginkgo.v \
|
||||
${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 --up
|
||||
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
|
||||
|
@@ -55,6 +55,7 @@ readonly KUBE_TEST_PORTABLE=(
|
||||
contrib/for-tests/network-tester/service.json
|
||||
hack/e2e.go
|
||||
hack/e2e-suite
|
||||
hack/ginkgo-e2e.sh
|
||||
)
|
||||
|
||||
# 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" \
|
||||
--really_crash_for_testing=true \
|
||||
--root_dir=/tmp/kubelet.$$ \
|
||||
--docker_endpoint="fake://" \
|
||||
--address="127.0.0.1" \
|
||||
--port="$KUBELET_PORT" 1>&2 &
|
||||
KUBELET_PID=$!
|
||||
@@ -65,6 +66,7 @@ kube::log::status "Starting kubelet in masterful mode"
|
||||
"${KUBE_OUTPUT_HOSTBIN}/kubelet" \
|
||||
--really_crash_for_testing=true \
|
||||
--root_dir=/tmp/kubelet.$$ \
|
||||
--docker_endpoint="fake://" \
|
||||
--etcd_servers="http://${ETCD_HOST}:${ETCD_PORT}" \
|
||||
--hostname_override="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.
|
||||
func InterpretUpdateError(err error, kind, name string) error {
|
||||
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.
|
||||
func InterpretDeleteError(err error, kind, name string) error {
|
||||
switch {
|
||||
|
@@ -35,8 +35,6 @@ func init() {
|
||||
&NodeList{},
|
||||
&Node{},
|
||||
&Status{},
|
||||
&OperationList{},
|
||||
&Operation{},
|
||||
&Endpoints{},
|
||||
&EndpointsList{},
|
||||
&Binding{},
|
||||
@@ -56,8 +54,6 @@ func init() {
|
||||
// Legacy names are supported
|
||||
Scheme.AddKnownTypeWithName("", "Minion", &Node{})
|
||||
Scheme.AddKnownTypeWithName("", "MinionList", &NodeList{})
|
||||
Scheme.AddKnownTypeWithName("", "ServerOp", &Operation{})
|
||||
Scheme.AddKnownTypeWithName("", "ServerOpList", &OperationList{})
|
||||
}
|
||||
|
||||
func (*Pod) IsAnAPIObject() {}
|
||||
@@ -73,8 +69,6 @@ func (*Node) IsAnAPIObject() {}
|
||||
func (*NodeList) IsAnAPIObject() {}
|
||||
func (*Binding) IsAnAPIObject() {}
|
||||
func (*Status) IsAnAPIObject() {}
|
||||
func (*Operation) IsAnAPIObject() {}
|
||||
func (*OperationList) IsAnAPIObject() {}
|
||||
func (*Event) IsAnAPIObject() {}
|
||||
func (*EventList) IsAnAPIObject() {}
|
||||
func (*ContainerManifest) IsAnAPIObject() {}
|
||||
|
@@ -292,6 +292,8 @@ type Probe struct {
|
||||
Handler `json:",inline"`
|
||||
// Length of time before health checking is activated. In seconds.
|
||||
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
|
||||
@@ -1028,20 +1030,6 @@ const (
|
||||
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.
|
||||
type ObjectReference struct {
|
||||
Kind string `json:"kind,omitempty"`
|
||||
|
@@ -1050,6 +1050,7 @@ func init() {
|
||||
return err
|
||||
}
|
||||
out.InitialDelaySeconds = in.InitialDelaySeconds
|
||||
out.TimeoutSeconds = in.TimeoutSeconds
|
||||
return nil
|
||||
},
|
||||
func(in *LivenessProbe, out *newer.Probe, s conversion.Scope) error {
|
||||
@@ -1063,6 +1064,7 @@ func init() {
|
||||
return err
|
||||
}
|
||||
out.InitialDelaySeconds = in.InitialDelaySeconds
|
||||
out.TimeoutSeconds = in.TimeoutSeconds
|
||||
return nil
|
||||
},
|
||||
)
|
||||
|
@@ -39,8 +39,6 @@ func init() {
|
||||
&MinionList{},
|
||||
&Binding{},
|
||||
&Status{},
|
||||
&ServerOp{},
|
||||
&ServerOpList{},
|
||||
&Event{},
|
||||
&EventList{},
|
||||
&ContainerManifest{},
|
||||
@@ -57,8 +55,6 @@ func init() {
|
||||
// Future names are supported
|
||||
api.Scheme.AddKnownTypeWithName("v1beta1", "Node", &Minion{})
|
||||
api.Scheme.AddKnownTypeWithName("v1beta1", "NodeList", &MinionList{})
|
||||
api.Scheme.AddKnownTypeWithName("v1beta1", "Operation", &ServerOp{})
|
||||
api.Scheme.AddKnownTypeWithName("v1beta1", "OperationList", &ServerOpList{})
|
||||
}
|
||||
|
||||
func (*Pod) IsAnAPIObject() {}
|
||||
@@ -74,8 +70,6 @@ func (*Minion) IsAnAPIObject() {}
|
||||
func (*MinionList) IsAnAPIObject() {}
|
||||
func (*Binding) IsAnAPIObject() {}
|
||||
func (*Status) IsAnAPIObject() {}
|
||||
func (*ServerOp) IsAnAPIObject() {}
|
||||
func (*ServerOpList) IsAnAPIObject() {}
|
||||
func (*Event) IsAnAPIObject() {}
|
||||
func (*EventList) IsAnAPIObject() {}
|
||||
func (*ContainerManifest) IsAnAPIObject() {}
|
||||
|
@@ -232,6 +232,8 @@ type LivenessProbe struct {
|
||||
Exec *ExecAction `json:"exec,omitempty" description:"parameters for exec-based liveness probe"`
|
||||
// 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"`
|
||||
// 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
|
||||
@@ -808,17 +810,6 @@ const (
|
||||
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.
|
||||
type ObjectReference struct {
|
||||
Kind string `json:"kind,omitempty" description:"kind of the referent"`
|
||||
|
@@ -966,6 +966,7 @@ func init() {
|
||||
return err
|
||||
}
|
||||
out.InitialDelaySeconds = in.InitialDelaySeconds
|
||||
out.TimeoutSeconds = in.TimeoutSeconds
|
||||
return nil
|
||||
},
|
||||
func(in *LivenessProbe, out *newer.Probe, s conversion.Scope) error {
|
||||
@@ -979,6 +980,7 @@ func init() {
|
||||
return err
|
||||
}
|
||||
out.InitialDelaySeconds = in.InitialDelaySeconds
|
||||
out.TimeoutSeconds = in.TimeoutSeconds
|
||||
return nil
|
||||
},
|
||||
)
|
||||
|
@@ -39,8 +39,6 @@ func init() {
|
||||
&MinionList{},
|
||||
&Binding{},
|
||||
&Status{},
|
||||
&ServerOp{},
|
||||
&ServerOpList{},
|
||||
&Event{},
|
||||
&EventList{},
|
||||
&ContainerManifest{},
|
||||
@@ -57,8 +55,6 @@ func init() {
|
||||
// Future names are supported
|
||||
api.Scheme.AddKnownTypeWithName("v1beta2", "Node", &Minion{})
|
||||
api.Scheme.AddKnownTypeWithName("v1beta2", "NodeList", &MinionList{})
|
||||
api.Scheme.AddKnownTypeWithName("v1beta2", "Operation", &ServerOp{})
|
||||
api.Scheme.AddKnownTypeWithName("v1beta2", "OperationList", &ServerOpList{})
|
||||
}
|
||||
|
||||
func (*Pod) IsAnAPIObject() {}
|
||||
@@ -74,8 +70,6 @@ func (*Minion) IsAnAPIObject() {}
|
||||
func (*MinionList) IsAnAPIObject() {}
|
||||
func (*Binding) IsAnAPIObject() {}
|
||||
func (*Status) IsAnAPIObject() {}
|
||||
func (*ServerOp) IsAnAPIObject() {}
|
||||
func (*ServerOpList) IsAnAPIObject() {}
|
||||
func (*Event) IsAnAPIObject() {}
|
||||
func (*EventList) IsAnAPIObject() {}
|
||||
func (*ContainerManifest) IsAnAPIObject() {}
|
||||
|
@@ -191,6 +191,8 @@ type LivenessProbe struct {
|
||||
Exec *ExecAction `json:"exec,omitempty" description:"parameters for exec-based liveness probe"`
|
||||
// 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"`
|
||||
// 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
|
||||
@@ -782,17 +784,6 @@ const (
|
||||
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.
|
||||
type ObjectReference struct {
|
||||
Kind string `json:"kind,omitempty" description:"kind of the referent"`
|
||||
|
@@ -43,8 +43,6 @@ func init() {
|
||||
&NodeList{},
|
||||
&Binding{},
|
||||
&Status{},
|
||||
&Operation{},
|
||||
&OperationList{},
|
||||
&Event{},
|
||||
&EventList{},
|
||||
&List{},
|
||||
@@ -57,8 +55,6 @@ func init() {
|
||||
// Legacy names are supported
|
||||
api.Scheme.AddKnownTypeWithName("v1beta3", "Minion", &Node{})
|
||||
api.Scheme.AddKnownTypeWithName("v1beta3", "MinionList", &NodeList{})
|
||||
api.Scheme.AddKnownTypeWithName("v1beta3", "ServerOp", &Operation{})
|
||||
api.Scheme.AddKnownTypeWithName("v1beta3", "ServerOpList", &OperationList{})
|
||||
}
|
||||
|
||||
func (*Pod) IsAnAPIObject() {}
|
||||
@@ -78,8 +74,6 @@ func (*Node) IsAnAPIObject() {}
|
||||
func (*NodeList) IsAnAPIObject() {}
|
||||
func (*Binding) IsAnAPIObject() {}
|
||||
func (*Status) IsAnAPIObject() {}
|
||||
func (*Operation) IsAnAPIObject() {}
|
||||
func (*OperationList) IsAnAPIObject() {}
|
||||
func (*Event) IsAnAPIObject() {}
|
||||
func (*EventList) IsAnAPIObject() {}
|
||||
func (*List) IsAnAPIObject() {}
|
||||
|
@@ -310,6 +310,8 @@ type Probe struct {
|
||||
Handler `json:",inline"`
|
||||
// Length of time before health checking is activated. In seconds.
|
||||
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
|
||||
@@ -1008,22 +1010,6 @@ const (
|
||||
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.
|
||||
type ObjectReference struct {
|
||||
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 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"},
|
||||
"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 {
|
||||
errs := validatePorts(v.P)
|
||||
@@ -371,23 +371,26 @@ func TestValidateContainers(t *testing.T) {
|
||||
AllowPrivileged: false,
|
||||
})
|
||||
errorCases := map[string][]api.Container{
|
||||
"zero-length name": {{Name: "", Image: "image"}},
|
||||
"name > 63 characters": {{Name: strings.Repeat("a", 64), Image: "image"}},
|
||||
"name not a DNS label": {{Name: "a.b.c", Image: "image"}},
|
||||
"zero-length name": {{Name: "", Image: "image", ImagePullPolicy: "IfNotPresent"}},
|
||||
"name > 63 characters": {{Name: strings.Repeat("a", 64), Image: "image", ImagePullPolicy: "IfNotPresent"}},
|
||||
"name not a DNS label": {{Name: "a.b.c", Image: "image", ImagePullPolicy: "IfNotPresent"}},
|
||||
"name not unique": {
|
||||
{Name: "abc", Image: "image"},
|
||||
{Name: "abc", Image: "image"},
|
||||
{Name: "abc", Image: "image", ImagePullPolicy: "IfNotPresent"},
|
||||
{Name: "abc", Image: "image", ImagePullPolicy: "IfNotPresent"},
|
||||
},
|
||||
"zero-length image": {{Name: "abc", Image: ""}},
|
||||
"zero-length image": {{Name: "abc", Image: "", ImagePullPolicy: "IfNotPresent"}},
|
||||
"host port not unique": {
|
||||
{Name: "abc", Image: "image", Ports: []api.Port{{ContainerPort: 80, HostPort: 80}}},
|
||||
{Name: "def", Image: "image", Ports: []api.Port{{ContainerPort: 81, HostPort: 80}}},
|
||||
{Name: "abc", Image: "image", Ports: []api.Port{{ContainerPort: 80, HostPort: 80, Protocol: "TCP"}},
|
||||
ImagePullPolicy: "IfNotPresent"},
|
||||
{Name: "def", Image: "image", Ports: []api.Port{{ContainerPort: 81, HostPort: 80, Protocol: "TCP"}},
|
||||
ImagePullPolicy: "IfNotPresent"},
|
||||
},
|
||||
"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": {
|
||||
{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.": {
|
||||
{
|
||||
@@ -398,6 +401,7 @@ func TestValidateContainers(t *testing.T) {
|
||||
Exec: &api.ExecAction{},
|
||||
},
|
||||
},
|
||||
ImagePullPolicy: "IfNotPresent",
|
||||
},
|
||||
},
|
||||
"invalid lifecycle, no http path.": {
|
||||
@@ -409,6 +413,7 @@ func TestValidateContainers(t *testing.T) {
|
||||
HTTPGet: &api.HTTPGetAction{},
|
||||
},
|
||||
},
|
||||
ImagePullPolicy: "IfNotPresent",
|
||||
},
|
||||
},
|
||||
"invalid lifecycle, no action.": {
|
||||
@@ -418,6 +423,7 @@ func TestValidateContainers(t *testing.T) {
|
||||
Lifecycle: &api.Lifecycle{
|
||||
PreStop: &api.Handler{},
|
||||
},
|
||||
ImagePullPolicy: "IfNotPresent",
|
||||
},
|
||||
},
|
||||
"privilege disabled": {
|
||||
@@ -432,6 +438,7 @@ func TestValidateContainers(t *testing.T) {
|
||||
"disk": resource.MustParse("10G"),
|
||||
},
|
||||
},
|
||||
ImagePullPolicy: "IfNotPresent",
|
||||
},
|
||||
},
|
||||
"Resource CPU invalid": {
|
||||
@@ -441,6 +448,7 @@ func TestValidateContainers(t *testing.T) {
|
||||
Resources: api.ResourceRequirementSpec{
|
||||
Limits: getResourceLimits("-10", "0"),
|
||||
},
|
||||
ImagePullPolicy: "IfNotPresent",
|
||||
},
|
||||
},
|
||||
"Resource Memory invalid": {
|
||||
@@ -450,6 +458,7 @@ func TestValidateContainers(t *testing.T) {
|
||||
Resources: api.ResourceRequirementSpec{
|
||||
Limits: getResourceLimits("0", "-10"),
|
||||
},
|
||||
ImagePullPolicy: "IfNotPresent",
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -553,17 +562,26 @@ func TestValidateManifest(t *testing.T) {
|
||||
}
|
||||
|
||||
errorCases := map[string]api.ContainerManifest{
|
||||
"empty version": {Version: "", ID: "abc"},
|
||||
"invalid version": {Version: "bogus", ID: "abc"},
|
||||
"empty version": {Version: "", 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": {
|
||||
Version: "v1beta1",
|
||||
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": {
|
||||
Version: "v1beta1",
|
||||
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 {
|
||||
@@ -603,12 +621,21 @@ func TestValidatePodSpec(t *testing.T) {
|
||||
failureCases := map[string]api.PodSpec{
|
||||
"bad volume": {
|
||||
Volumes: []api.Volume{{}},
|
||||
RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}},
|
||||
DNSPolicy: api.DNSClusterFirst,
|
||||
},
|
||||
"bad container": {
|
||||
Containers: []api.Container{{}},
|
||||
RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}},
|
||||
DNSPolicy: api.DNSClusterFirst,
|
||||
},
|
||||
"bad DNS policy": {
|
||||
DNSPolicy: api.DNSPolicy("invalid"),
|
||||
RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}},
|
||||
},
|
||||
"bad restart policy": {
|
||||
RestartPolicy: api.RestartPolicy{},
|
||||
DNSPolicy: api.DNSClusterFirst,
|
||||
},
|
||||
}
|
||||
for k, v := range failureCases {
|
||||
@@ -652,8 +679,20 @@ func TestValidatePod(t *testing.T) {
|
||||
}
|
||||
|
||||
errorCases := map[string]api.Pod{
|
||||
"bad name": {ObjectMeta: api.ObjectMeta{Name: "", Namespace: "ns"}},
|
||||
"bad namespace": {ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: ""}},
|
||||
"bad name": {
|
||||
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": {
|
||||
ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: "ns"},
|
||||
Spec: api.PodSpec{
|
||||
@@ -668,6 +707,10 @@ func TestValidatePod(t *testing.T) {
|
||||
"NoUppercaseOrSpecialCharsLike=Equals": "bar",
|
||||
},
|
||||
},
|
||||
Spec: api.PodSpec{
|
||||
RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}},
|
||||
DNSPolicy: api.DNSClusterFirst,
|
||||
},
|
||||
},
|
||||
"bad annotation": {
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
@@ -677,6 +720,10 @@ func TestValidatePod(t *testing.T) {
|
||||
"NoUppercaseOrSpecialCharsLike=Equals": "bar",
|
||||
},
|
||||
},
|
||||
Spec: api.PodSpec{
|
||||
RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}},
|
||||
DNSPolicy: api.DNSClusterFirst,
|
||||
},
|
||||
},
|
||||
}
|
||||
for k, v := range errorCases {
|
||||
@@ -857,6 +904,26 @@ func TestValidatePodUpdate(t *testing.T) {
|
||||
false,
|
||||
"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 {
|
||||
@@ -914,18 +981,53 @@ func TestValidateBoundPods(t *testing.T) {
|
||||
}
|
||||
|
||||
errorCases := map[string]api.Pod{
|
||||
"bad name": {ObjectMeta: api.ObjectMeta{Name: "", Namespace: "ns"}},
|
||||
"bad namespace": {ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: ""}},
|
||||
"zero-length name": {
|
||||
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": {
|
||||
ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: "ns"},
|
||||
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 {
|
||||
if errs := ValidatePod(&v); len(errs) == 0 {
|
||||
t.Errorf("expected failure for %s", k)
|
||||
if errs := ValidatePod(&v); len(errs) != 1 {
|
||||
t.Errorf("expected one failure for %s; got %d: %s", k, len(errs), errs)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1315,6 +1417,8 @@ func TestValidateReplicationController(t *testing.T) {
|
||||
Spec: api.PodTemplateSpec{
|
||||
Spec: api.PodSpec{
|
||||
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) {
|
||||
validSelector := map[string]string{"a": "b"}
|
||||
invalidSelector := map[string]string{"NoUppercaseOrSpecialCharsLike=Equals": "b"}
|
||||
@@ -1692,6 +1778,17 @@ func TestValidateMinionUpdate(t *testing.T) {
|
||||
Labels: map[string]string{"bar": "fooobaz"},
|
||||
},
|
||||
}, 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 {
|
||||
errs := ValidateMinionUpdate(&test.oldMinion, &test.minion)
|
||||
@@ -1848,6 +1945,19 @@ func TestValidateServiceUpdate(t *testing.T) {
|
||||
PortalIP: "127.0.0.2",
|
||||
},
|
||||
}, 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 {
|
||||
errs := ValidateServiceUpdate(&test.oldService, &test.service)
|
||||
|
@@ -17,7 +17,6 @@ limitations under the License.
|
||||
package apiserver
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"strconv"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
@@ -79,23 +78,6 @@ func (ops *Operations) insert(op *Operation) {
|
||||
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.
|
||||
func (ops *Operations) Get(id string) *Operation {
|
||||
ops.lock.Lock()
|
||||
|
@@ -46,7 +46,7 @@ type validator struct {
|
||||
}
|
||||
|
||||
// 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)
|
||||
if err != nil {
|
||||
return probe.Unknown, "", err
|
||||
@@ -66,7 +66,7 @@ func (s *Server) check(client httpGet) (probe.Status, string, error) {
|
||||
type ServerStatus struct {
|
||||
Component string `json:"component,omitempty"`
|
||||
Health string `json:"health,omitempty"`
|
||||
HealthCode probe.Status `json:"healthCode,omitempty"`
|
||||
HealthCode probe.Result `json:"healthCode,omitempty"`
|
||||
Msg string `json:"msg,omitempty"`
|
||||
Err string `json:"err,omitempty"`
|
||||
}
|
||||
|
@@ -54,7 +54,7 @@ func TestValidate(t *testing.T) {
|
||||
tests := []struct {
|
||||
err error
|
||||
data string
|
||||
expectedStatus probe.Status
|
||||
expectedStatus probe.Result
|
||||
code int
|
||||
expectErr bool
|
||||
}{
|
||||
|
@@ -41,7 +41,7 @@ type KubeletClient interface {
|
||||
|
||||
// KubeletHealthchecker is an interface for healthchecking kubelets
|
||||
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.
|
||||
@@ -134,7 +134,7 @@ func (c *HTTPKubeletClient) GetPodStatus(host, podNamespace, podID string) (api.
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -148,6 +148,6 @@ func (c FakeKubeletClient) GetPodStatus(host, podNamespace string, podID string)
|
||||
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")
|
||||
}
|
||||
|
@@ -102,7 +102,7 @@ func (m *FakeNodeHandler) Update(node *api.Node) (*api.Node, error) {
|
||||
|
||||
// FakeKubeletClient is a fake implementation of KubeletClient.
|
||||
type FakeKubeletClient struct {
|
||||
Status probe.Status
|
||||
Status probe.Result
|
||||
Err error
|
||||
}
|
||||
|
||||
@@ -110,7 +110,7 @@ func (c *FakeKubeletClient) GetPodStatus(host, podNamespace, podID string) (api.
|
||||
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
|
||||
}
|
||||
|
||||
|
@@ -17,11 +17,17 @@ limitations under the License.
|
||||
package constraint
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||
)
|
||||
|
||||
// Allowed returns true if pods is a collection of bound pods
|
||||
// which can run without conflict on a single minion.
|
||||
func Allowed(pods []api.BoundPod) bool {
|
||||
return !PortsConflict(pods)
|
||||
func Allowed(pods []api.BoundPod) []error {
|
||||
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
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||
@@ -40,11 +41,11 @@ func podWithContainers(containers ...api.Container) api.BoundPod {
|
||||
|
||||
func TestAllowed(t *testing.T) {
|
||||
table := []struct {
|
||||
allowed bool
|
||||
err string
|
||||
pods []api.BoundPod
|
||||
}{
|
||||
{
|
||||
allowed: true,
|
||||
err: "[]",
|
||||
pods: []api.BoundPod{
|
||||
podWithContainers(
|
||||
containerWithHostPorts(1, 2, 3),
|
||||
@@ -57,7 +58,7 @@ func TestAllowed(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
allowed: true,
|
||||
err: "[]",
|
||||
pods: []api.BoundPod{
|
||||
podWithContainers(
|
||||
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{
|
||||
podWithContainers(
|
||||
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{
|
||||
podWithContainers(
|
||||
containerWithHostPorts(6),
|
||||
@@ -91,7 +92,7 @@ func TestAllowed(t *testing.T) {
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
@@ -20,10 +20,12 @@ import (
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||
)
|
||||
|
||||
// PortsConflict returns true iff two containers attempt to expose
|
||||
// the same host port.
|
||||
func PortsConflict(pods []api.BoundPod) bool {
|
||||
// hostPortsConflict returns an array of host ports that at least two
|
||||
// containers attempt to expose. The array is empty if no such port
|
||||
// exists.
|
||||
func hostPortsConflict(pods []api.BoundPod) []int {
|
||||
hostPorts := map[int]struct{}{}
|
||||
conflictingPorts := []int{}
|
||||
for _, pod := range pods {
|
||||
for _, container := range pod.Spec.Containers {
|
||||
for _, port := range container.Ports {
|
||||
@@ -31,11 +33,11 @@ func PortsConflict(pods []api.BoundPod) bool {
|
||||
continue
|
||||
}
|
||||
if _, exists := hostPorts[port.HostPort]; exists {
|
||||
return true
|
||||
conflictingPorts = append(conflictingPorts, port.HostPort)
|
||||
}
|
||||
hostPorts[port.HostPort] = struct{}{}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
return conflictingPorts
|
||||
}
|
||||
|
@@ -141,11 +141,24 @@ func (rm *ReplicationManager) watchControllers(resourceVersion *string) {
|
||||
}
|
||||
if event.Type == watch.Error {
|
||||
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
|
||||
}
|
||||
glog.V(4).Infof("Got watch: %#v", event)
|
||||
rc, ok := event.Object.(*api.ReplicationController)
|
||||
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))
|
||||
continue
|
||||
}
|
||||
@@ -166,7 +179,8 @@ func FilterActivePods(pods []api.Pod) []api.Pod {
|
||||
var result []api.Pod
|
||||
for _, value := range pods {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
@@ -29,6 +29,7 @@ import (
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/client/clientcmd"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl"
|
||||
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/runtime"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
||||
@@ -143,7 +144,7 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory {
|
||||
return kubectl.ReaperFor(mapping.Kind, client)
|
||||
},
|
||||
Validator: func(cmd *cobra.Command) (validation.Schema, error) {
|
||||
if GetFlagBool(cmd, "validate") {
|
||||
if cmdutil.GetFlagBool(cmd, "validate") {
|
||||
client, err := clients.ClientForVersion("")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -217,6 +218,62 @@ Find more information at https://github.com/GoogleCloudPlatform/kubernetes.`,
|
||||
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:
|
||||
// 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:
|
||||
@@ -266,13 +323,6 @@ func DefaultClientConfig(flags *pflag.FlagSet) clientcmd.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) {
|
||||
if err != nil {
|
||||
glog.FatalDepth(1, err)
|
||||
|
@@ -21,6 +21,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"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"
|
||||
"os"
|
||||
|
||||
"github.com/ghodss/yaml"
|
||||
"github.com/golang/glog"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/client/clientcmd"
|
||||
clientcmdapi "github.com/GoogleCloudPlatform/kubernetes/pkg/client/clientcmd/api"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||
)
|
||||
|
||||
type viewOptions struct {
|
||||
@@ -38,40 +39,45 @@ func NewCmdConfigView(out io.Writer, pathOptions *pathOptions) *cobra.Command {
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "view",
|
||||
Short: "displays the specified .kubeconfig file or a merged result",
|
||||
Long: `displays the specified .kubeconfig file or a merged result`,
|
||||
Short: "displays merged .kubeconfig settings or a specified .kubeconfig file.",
|
||||
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) {
|
||||
err := options.run()
|
||||
printer, _, err := util.PrinterForCommand(cmd)
|
||||
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
|
||||
}
|
||||
|
||||
func (o viewOptions) run() error {
|
||||
func (o viewOptions) loadConfig() (*clientcmdapi.Config, error) {
|
||||
err := o.validate()
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
config, _, err := o.getStartingConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
content, err := yaml.Marshal(config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("%v", string(content))
|
||||
|
||||
return nil
|
||||
return config, err
|
||||
}
|
||||
|
||||
func (o viewOptions) validate() error {
|
||||
|
@@ -51,7 +51,7 @@ Examples:
|
||||
checkErr(err)
|
||||
|
||||
mapper, typer := f.Object(cmd)
|
||||
r := resource.NewBuilder(mapper, typer, ClientMapperForCommand(cmd, f)).
|
||||
r := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand(cmd)).
|
||||
ContinueOnError().
|
||||
NamespaceParam(cmdNamespace).RequireNamespace().
|
||||
FilenameParam(flags.Filenames...).
|
||||
|
@@ -23,6 +23,7 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"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/util"
|
||||
)
|
||||
@@ -62,11 +63,11 @@ Examples:
|
||||
checkErr(err)
|
||||
|
||||
mapper, typer := f.Object(cmd)
|
||||
r := resource.NewBuilder(mapper, typer, ClientMapperForCommand(cmd, f)).
|
||||
r := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand(cmd)).
|
||||
ContinueOnError().
|
||||
NamespaceParam(cmdNamespace).DefaultNamespace().
|
||||
FilenameParam(flags.Filenames...).
|
||||
SelectorParam(GetFlagString(cmd, "selector")).
|
||||
SelectorParam(cmdutil.GetFlagString(cmd, "selector")).
|
||||
ResourceTypeOrNameArgs(args...).
|
||||
Flatten().
|
||||
Do()
|
||||
|
@@ -20,6 +20,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@@ -36,7 +37,7 @@ given resource.`,
|
||||
checkErr(err)
|
||||
|
||||
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)
|
||||
checkErr(err)
|
||||
|
@@ -22,6 +22,7 @@ import (
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@@ -51,27 +52,28 @@ $ kubectl expose streamer --port=4100 --protocol=udp --service-name=video-stream
|
||||
client, err := f.Client(cmd)
|
||||
checkErr(err)
|
||||
|
||||
generatorName := GetFlagString(cmd, "generator")
|
||||
generatorName := util.GetFlagString(cmd, "generator")
|
||||
|
||||
generator, found := kubectl.Generators[generatorName]
|
||||
if !found {
|
||||
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.")
|
||||
}
|
||||
names := generator.ParamNames()
|
||||
params := kubectl.MakeParams(cmd, names)
|
||||
if len(GetFlagString(cmd, "service-name")) == 0 {
|
||||
if len(util.GetFlagString(cmd, "service-name")) == 0 {
|
||||
params["name"] = args[0]
|
||||
} else {
|
||||
params["name"] = GetFlagString(cmd, "service-name")
|
||||
params["name"] = util.GetFlagString(cmd, "service-name")
|
||||
}
|
||||
if _, found := params["selector"]; !found {
|
||||
rc, err := client.ReplicationControllers(namespace).Get(args[0])
|
||||
checkErr(err)
|
||||
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"
|
||||
}
|
||||
|
||||
@@ -81,22 +83,22 @@ $ kubectl expose streamer --port=4100 --protocol=udp --service-name=video-stream
|
||||
service, err := generator.Generate(params)
|
||||
checkErr(err)
|
||||
|
||||
inline := GetFlagString(cmd, "overrides")
|
||||
inline := util.GetFlagString(cmd, "overrides")
|
||||
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.
|
||||
if !GetFlagBool(cmd, "dry-run") {
|
||||
if !util.GetFlagBool(cmd, "dry-run") {
|
||||
service, err = client.Services(namespace).Create(service.(*api.Service))
|
||||
checkErr(err)
|
||||
}
|
||||
|
||||
err = PrintObject(cmd, service, f, out)
|
||||
err = f.PrintObject(cmd, service, out)
|
||||
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("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.")
|
||||
|
@@ -23,6 +23,7 @@ import (
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
|
||||
"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/watch"
|
||||
|
||||
@@ -59,7 +60,7 @@ Examples:
|
||||
RunGet(f, out, cmd, args)
|
||||
},
|
||||
}
|
||||
AddPrinterFlags(cmd)
|
||||
util.AddPrinterFlags(cmd)
|
||||
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().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: return an error instead of using glog.Fatal and checkErr
|
||||
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)
|
||||
|
||||
cmdNamespace, err := f.DefaultNamespace(cmd)
|
||||
checkErr(err)
|
||||
|
||||
// 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 {
|
||||
r := resource.NewBuilder(mapper, typer, ClientMapperForCommand(cmd, f)).
|
||||
r := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand(cmd)).
|
||||
NamespaceParam(cmdNamespace).DefaultNamespace().
|
||||
SelectorParam(selector).
|
||||
ResourceTypeOrNameArgs(args...).
|
||||
@@ -89,7 +90,7 @@ func RunGet(f *Factory, out io.Writer, cmd *cobra.Command, args []string) {
|
||||
mapping, err := r.ResourceMapping()
|
||||
checkErr(err)
|
||||
|
||||
printer, err := PrinterForMapping(f, cmd, mapping)
|
||||
printer, err := f.PrinterForMapping(cmd, mapping)
|
||||
checkErr(err)
|
||||
|
||||
obj, err := r.Object()
|
||||
@@ -115,12 +116,12 @@ func RunGet(f *Factory, out io.Writer, cmd *cobra.Command, args []string) {
|
||||
return
|
||||
}
|
||||
|
||||
b := resource.NewBuilder(mapper, typer, ClientMapperForCommand(cmd, f)).
|
||||
b := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand(cmd)).
|
||||
NamespaceParam(cmdNamespace).DefaultNamespace().
|
||||
SelectorParam(selector).
|
||||
ResourceTypeOrNameArgs(args...).
|
||||
Latest()
|
||||
printer, generic, err := PrinterForCommand(cmd)
|
||||
printer, generic, err := util.PrinterForCommand(cmd)
|
||||
checkErr(err)
|
||||
|
||||
if generic {
|
||||
@@ -129,7 +130,7 @@ func RunGet(f *Factory, out io.Writer, cmd *cobra.Command, args []string) {
|
||||
defaultVersion := clientConfig.Version
|
||||
|
||||
// the outermost object will be converted to the output-version
|
||||
version := outputVersion(cmd, defaultVersion)
|
||||
version := util.OutputVersion(cmd, defaultVersion)
|
||||
if len(version) == 0 {
|
||||
// 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).
|
||||
@@ -149,7 +150,7 @@ func RunGet(f *Factory, out io.Writer, cmd *cobra.Command, args []string) {
|
||||
|
||||
// use the default printer for each object
|
||||
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 {
|
||||
return err
|
||||
}
|
||||
|
@@ -20,6 +20,7 @@ import (
|
||||
"io"
|
||||
"strconv"
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@@ -66,7 +67,7 @@ Examples:
|
||||
}
|
||||
|
||||
follow := false
|
||||
if GetFlagBool(cmd, "follow") {
|
||||
if util.GetFlagBool(cmd, "follow") {
|
||||
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 (
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||
"github.com/golang/glog"
|
||||
"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",
|
||||
Long: `Run a proxy to the Kubernetes API server.`,
|
||||
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)
|
||||
|
||||
clientConfig, err := f.ClientConfig(cmd)
|
||||
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)
|
||||
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")
|
||||
return cmd
|
||||
}
|
||||
|
@@ -21,6 +21,7 @@ import (
|
||||
"io"
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@@ -44,7 +45,7 @@ Examples:
|
||||
$ kubectl resize --current-replicas=2 --replicas=3 replicationcontrollers foo
|
||||
`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
count := GetFlagInt(cmd, "replicas")
|
||||
count := util.GetFlagInt(cmd, "replicas")
|
||||
if len(args) != 2 || count < 0 {
|
||||
usageError(cmd, "--replicas=<count> <resource> <id>")
|
||||
}
|
||||
@@ -53,13 +54,13 @@ Examples:
|
||||
checkErr(err)
|
||||
|
||||
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)
|
||||
checkErr(err)
|
||||
|
||||
resourceVersion := GetFlagString(cmd, "resource-version")
|
||||
currentSize := GetFlagInt(cmd, "current-replicas")
|
||||
resourceVersion := util.GetFlagString(cmd, "resource-version")
|
||||
currentSize := util.GetFlagInt(cmd, "current-replicas")
|
||||
s, err := resizer.Resize(namespace, name, &kubectl.ResizePrecondition{currentSize, resourceVersion}, uint(count))
|
||||
checkErr(err)
|
||||
fmt.Fprintf(out, "%s\n", s)
|
||||
|
@@ -22,6 +22,7 @@ import (
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||
"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 -
|
||||
<update pods of frontend-v1 using json data passed into stdin>`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
filename := GetFlagString(cmd, "filename")
|
||||
filename := util.GetFlagString(cmd, "filename")
|
||||
if len(filename) == 0 {
|
||||
usageError(cmd, "Must specify filename for new controller")
|
||||
}
|
||||
period := GetFlagDuration(cmd, "update-period")
|
||||
interval := GetFlagDuration(cmd, "poll-interval")
|
||||
timeout := GetFlagDuration(cmd, "timeout")
|
||||
period := util.GetFlagDuration(cmd, "update-period")
|
||||
interval := util.GetFlagDuration(cmd, "poll-interval")
|
||||
timeout := util.GetFlagDuration(cmd, "timeout")
|
||||
if len(args) != 1 {
|
||||
usageError(cmd, "Must specify the controller to update")
|
||||
}
|
||||
@@ -67,7 +68,7 @@ $ cat frontend-v2.json | kubectl rollingupdate frontend-v1 -f -
|
||||
cmdApiVersion := clientConfig.Version
|
||||
|
||||
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" {
|
||||
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)
|
||||
checkErr(err)
|
||||
err = CompareNamespace(cmdNamespace, namespace)
|
||||
err = util.CompareNamespace(cmdNamespace, namespace)
|
||||
checkErr(err)
|
||||
|
||||
client, err := f.Client(cmd)
|
||||
|
@@ -22,6 +22,7 @@ import (
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@@ -55,7 +56,7 @@ Examples:
|
||||
client, err := f.Client(cmd)
|
||||
checkErr(err)
|
||||
|
||||
generatorName := GetFlagString(cmd, "generator")
|
||||
generatorName := util.GetFlagString(cmd, "generator")
|
||||
generator, found := kubectl.Generators[generatorName]
|
||||
if !found {
|
||||
usageError(cmd, fmt.Sprintf("Generator: %s not found.", generator))
|
||||
@@ -70,22 +71,22 @@ Examples:
|
||||
controller, err := generator.Generate(params)
|
||||
checkErr(err)
|
||||
|
||||
inline := GetFlagString(cmd, "overrides")
|
||||
inline := util.GetFlagString(cmd, "overrides")
|
||||
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.
|
||||
if !GetFlagBool(cmd, "dry-run") {
|
||||
if !util.GetFlagBool(cmd, "dry-run") {
|
||||
controller, err = client.ReplicationControllers(namespace).Create(controller.(*api.ReplicationController))
|
||||
checkErr(err)
|
||||
}
|
||||
|
||||
err = PrintObject(cmd, controller, f, out)
|
||||
err = f.PrintObject(cmd, controller, out)
|
||||
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("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")
|
||||
|
@@ -20,6 +20,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@@ -42,7 +43,7 @@ Examples:
|
||||
}
|
||||
cmdNamespace, err := f.DefaultNamespace(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)
|
||||
checkErr(err)
|
||||
|
@@ -20,6 +20,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
cmdutil "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/resource"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
||||
"github.com/spf13/cobra"
|
||||
@@ -53,14 +54,14 @@ Examples:
|
||||
checkErr(err)
|
||||
|
||||
mapper, typer := f.Object(cmd)
|
||||
r := resource.NewBuilder(mapper, typer, ClientMapperForCommand(cmd, f)).
|
||||
r := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand(cmd)).
|
||||
ContinueOnError().
|
||||
NamespaceParam(cmdNamespace).RequireNamespace().
|
||||
FilenameParam(flags.Filenames...).
|
||||
Flatten().
|
||||
Do()
|
||||
|
||||
patch := GetFlagString(cmd, "patch")
|
||||
patch := cmdutil.GetFlagString(cmd, "patch")
|
||||
if len(flags.Filenames) == 0 && len(patch) == 0 {
|
||||
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)
|
||||
|
||||
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)
|
||||
checkErr(err)
|
||||
|
||||
@@ -110,7 +111,7 @@ func updateWithPatch(cmd *cobra.Command, args []string, f *Factory, patch string
|
||||
obj, err := helper.Get(namespace, name)
|
||||
checkErr(err)
|
||||
|
||||
Merge(obj, patch, mapping.Kind)
|
||||
cmdutil.Merge(obj, patch, mapping.Kind)
|
||||
|
||||
data, err := helper.Codec.Encode(obj)
|
||||
checkErr(err)
|
||||
|
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package cmd
|
||||
package util
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
@@ -34,6 +34,18 @@ import (
|
||||
"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 {
|
||||
f := cmd.Flags().Lookup(flag)
|
||||
if f == nil {
|
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package cmd
|
||||
package util
|
||||
|
||||
import (
|
||||
"reflect"
|
@@ -14,16 +14,10 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package cmd
|
||||
package util
|
||||
|
||||
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/runtime"
|
||||
|
||||
"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.")
|
||||
}
|
||||
|
||||
// PrintObject prints an api object given command line flags to modify the output format
|
||||
func PrintObject(cmd *cobra.Command, obj runtime.Object, f *Factory, 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 := 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 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")
|
||||
if len(outputVersion) == 0 {
|
||||
outputVersion = defaultVersion
|
||||
@@ -75,32 +49,3 @@ func PrinterForCommand(cmd *cobra.Command) (kubectl.ResourcePrinter, bool, error
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
package cmd
|
||||
package util
|
||||
|
||||
import (
|
||||
"fmt"
|
@@ -22,6 +22,7 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||
)
|
||||
|
||||
func (f *Factory) NewCmdVersion(out io.Writer) *cobra.Command {
|
||||
@@ -29,7 +30,7 @@ func (f *Factory) NewCmdVersion(out io.Writer) *cobra.Command {
|
||||
Use: "version",
|
||||
Short: "Print version of client and server",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if GetFlagBool(cmd, "client") {
|
||||
if util.GetFlagBool(cmd, "client") {
|
||||
kubectl.GetClientVersion(out)
|
||||
return
|
||||
}
|
||||
|
@@ -33,7 +33,7 @@ type ProxyServer struct {
|
||||
|
||||
// NewProxyServer creates and installs a new ProxyServer.
|
||||
// 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
|
||||
if prefix == "" {
|
||||
prefix = "/api"
|
||||
@@ -47,7 +47,7 @@ func NewProxyServer(filebase string, cfg *client.Config) (*ProxyServer, error) {
|
||||
return nil, err
|
||||
}
|
||||
http.Handle("/api/", http.StripPrefix("/api/", proxy))
|
||||
http.Handle("/static/", newFileHandler("/static/", filebase))
|
||||
http.Handle(staticPrefix, newFileHandler(staticPrefix, filebase))
|
||||
return proxy, nil
|
||||
}
|
||||
|
||||
|
@@ -25,6 +25,7 @@ import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"math/rand"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -104,7 +105,7 @@ type dockerContainerCommandRunner struct {
|
||||
var dockerAPIVersionWithExec = []uint{1, 15}
|
||||
|
||||
// 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()
|
||||
if err != nil {
|
||||
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) {
|
||||
version, err := d.getDockerServerVersion()
|
||||
version, err := d.GetDockerServerVersion()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -641,6 +642,35 @@ func parseImageName(image string) (string, string) {
|
||||
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 {
|
||||
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