Merge pull request #16028 from derekwaynecarr/make_cmd

Auto commit by PR queue bot
pull/6/head
k8s-merge-robot 2015-12-16 08:41:59 -08:00
commit 5a579a2555
29 changed files with 2576 additions and 17 deletions

View File

@ -20,6 +20,10 @@ docs/man/man1/kubectl-config-use-context.1
docs/man/man1/kubectl-config-view.1
docs/man/man1/kubectl-config.1
docs/man/man1/kubectl-convert.1
docs/man/man1/kubectl-create-namespace.1
docs/man/man1/kubectl-create-secret-docker-registry.1
docs/man/man1/kubectl-create-secret-generic.1
docs/man/man1/kubectl-create-secret.1
docs/man/man1/kubectl-create.1
docs/man/man1/kubectl-delete.1
docs/man/man1/kubectl-describe.1
@ -58,6 +62,10 @@ docs/user-guide/kubectl/kubectl_config_use-context.md
docs/user-guide/kubectl/kubectl_config_view.md
docs/user-guide/kubectl/kubectl_convert.md
docs/user-guide/kubectl/kubectl_create.md
docs/user-guide/kubectl/kubectl_create_namespace.md
docs/user-guide/kubectl/kubectl_create_secret.md
docs/user-guide/kubectl/kubectl_create_secret_docker-registry.md
docs/user-guide/kubectl/kubectl_create_secret_generic.md
docs/user-guide/kubectl/kubectl_delete.md
docs/user-guide/kubectl/kubectl_describe.md
docs/user-guide/kubectl/kubectl_edit.md

View File

@ -401,10 +401,204 @@ _kubectl_describe()
must_have_one_noun+=("serviceaccount")
}
_kubectl_create_namespace()
{
last_command="kubectl_create_namespace"
commands=()
flags=()
two_word_flags=()
flags_with_completion=()
flags_completion=()
flags+=("--dry-run")
flags+=("--generator=")
flags+=("--output=")
two_word_flags+=("-o")
flags+=("--output-version=")
flags+=("--save-config")
flags+=("--schema-cache-dir=")
flags+=("--validate")
flags+=("--alsologtostderr")
flags+=("--api-version=")
flags+=("--certificate-authority=")
flags+=("--client-certificate=")
flags+=("--client-key=")
flags+=("--cluster=")
flags+=("--context=")
flags+=("--insecure-skip-tls-verify")
flags+=("--kubeconfig=")
flags+=("--log-backtrace-at=")
flags+=("--log-dir=")
flags+=("--log-flush-frequency=")
flags+=("--logtostderr")
flags+=("--match-server-version")
flags+=("--namespace=")
flags+=("--password=")
flags+=("--server=")
two_word_flags+=("-s")
flags+=("--stderrthreshold=")
flags+=("--token=")
flags+=("--user=")
flags+=("--username=")
flags+=("--v=")
flags+=("--vmodule=")
must_have_one_flag=()
must_have_one_noun=()
}
_kubectl_create_secret_docker-registry()
{
last_command="kubectl_create_secret_docker-registry"
commands=()
flags=()
two_word_flags=()
flags_with_completion=()
flags_completion=()
flags+=("--docker-email=")
flags+=("--docker-password=")
flags+=("--docker-server=")
flags+=("--docker-username=")
flags+=("--dry-run")
flags+=("--generator=")
flags+=("--output=")
two_word_flags+=("-o")
flags+=("--output-version=")
flags+=("--save-config")
flags+=("--schema-cache-dir=")
flags+=("--validate")
flags+=("--alsologtostderr")
flags+=("--api-version=")
flags+=("--certificate-authority=")
flags+=("--client-certificate=")
flags+=("--client-key=")
flags+=("--cluster=")
flags+=("--context=")
flags+=("--insecure-skip-tls-verify")
flags+=("--kubeconfig=")
flags+=("--log-backtrace-at=")
flags+=("--log-dir=")
flags+=("--log-flush-frequency=")
flags+=("--logtostderr")
flags+=("--match-server-version")
flags+=("--namespace=")
flags+=("--password=")
flags+=("--server=")
two_word_flags+=("-s")
flags+=("--stderrthreshold=")
flags+=("--token=")
flags+=("--user=")
flags+=("--username=")
flags+=("--v=")
flags+=("--vmodule=")
must_have_one_flag=()
must_have_one_flag+=("--docker-email=")
must_have_one_flag+=("--docker-password=")
must_have_one_flag+=("--docker-username=")
must_have_one_noun=()
}
_kubectl_create_secret_generic()
{
last_command="kubectl_create_secret_generic"
commands=()
flags=()
two_word_flags=()
flags_with_completion=()
flags_completion=()
flags+=("--dry-run")
flags+=("--from-file=")
flags+=("--from-literal=")
flags+=("--generator=")
flags+=("--output=")
two_word_flags+=("-o")
flags+=("--output-version=")
flags+=("--save-config")
flags+=("--schema-cache-dir=")
flags+=("--type=")
flags+=("--validate")
flags+=("--alsologtostderr")
flags+=("--api-version=")
flags+=("--certificate-authority=")
flags+=("--client-certificate=")
flags+=("--client-key=")
flags+=("--cluster=")
flags+=("--context=")
flags+=("--insecure-skip-tls-verify")
flags+=("--kubeconfig=")
flags+=("--log-backtrace-at=")
flags+=("--log-dir=")
flags+=("--log-flush-frequency=")
flags+=("--logtostderr")
flags+=("--match-server-version")
flags+=("--namespace=")
flags+=("--password=")
flags+=("--server=")
two_word_flags+=("-s")
flags+=("--stderrthreshold=")
flags+=("--token=")
flags+=("--user=")
flags+=("--username=")
flags+=("--v=")
flags+=("--vmodule=")
must_have_one_flag=()
must_have_one_noun=()
}
_kubectl_create_secret()
{
last_command="kubectl_create_secret"
commands=()
commands+=("docker-registry")
commands+=("generic")
flags=()
two_word_flags=()
flags_with_completion=()
flags_completion=()
flags+=("--alsologtostderr")
flags+=("--api-version=")
flags+=("--certificate-authority=")
flags+=("--client-certificate=")
flags+=("--client-key=")
flags+=("--cluster=")
flags+=("--context=")
flags+=("--insecure-skip-tls-verify")
flags+=("--kubeconfig=")
flags+=("--log-backtrace-at=")
flags+=("--log-dir=")
flags+=("--log-flush-frequency=")
flags+=("--logtostderr")
flags+=("--match-server-version")
flags+=("--namespace=")
flags+=("--password=")
flags+=("--server=")
two_word_flags+=("-s")
flags+=("--stderrthreshold=")
flags+=("--token=")
flags+=("--user=")
flags+=("--username=")
flags+=("--v=")
flags+=("--vmodule=")
must_have_one_flag=()
must_have_one_noun=()
}
_kubectl_create()
{
last_command="kubectl_create"
commands=()
commands+=("namespace")
commands+=("secret")
flags=()
two_word_flags=()

View File

@ -0,0 +1,164 @@
.TH "KUBERNETES" "1" " kubernetes User Manuals" "Eric Paris" "Jan 2015" ""
.SH NAME
.PP
kubectl create namespace \- Create a namespace with the specified name.
.SH SYNOPSIS
.PP
\fBkubectl create namespace\fP [OPTIONS]
.SH DESCRIPTION
.PP
Create a namespace with the specified name.
.SH OPTIONS
.PP
\fB\-\-dry\-run\fP=false
If true, only print the object that would be sent, without sending it.
.PP
\fB\-\-generator\fP="namespace/v1"
The name of the API generator to use.
.PP
\fB\-o\fP, \fB\-\-output\fP=""
Output format. One of: json|yaml|wide|name|go\-template=...|go\-template\-file=...|jsonpath=...|jsonpath\-file=... See golang template [
\[la]http://golang.org/pkg/text/template/#pkg-overview\[ra]] and jsonpath template [
\[la]http://releases.k8s.io/HEAD/docs/user-guide/jsonpath.md\[ra]].
.PP
\fB\-\-output\-version\fP=""
Output the formatted object with the given version (default api\-version).
.PP
\fB\-\-save\-config\fP=false
If true, the configuration of current object will be saved in its annotation. This is useful when you want to perform kubectl apply on this object in the future.
.PP
\fB\-\-schema\-cache\-dir\fP="\~/.kube/schema"
If non\-empty, load/store cached API schemas in this directory, default is '$HOME/.kube/schema'
.PP
\fB\-\-validate\fP=true
If true, use a schema to validate the input before sending it
.SH OPTIONS INHERITED FROM PARENT COMMANDS
.PP
\fB\-\-alsologtostderr\fP=false
log to standard error as well as files
.PP
\fB\-\-api\-version\fP=""
The API version to use when talking to the server
.PP
\fB\-\-certificate\-authority\fP=""
Path to a cert. file for the certificate authority.
.PP
\fB\-\-client\-certificate\fP=""
Path to a client certificate file for TLS.
.PP
\fB\-\-client\-key\fP=""
Path to a client key file for TLS.
.PP
\fB\-\-cluster\fP=""
The name of the kubeconfig cluster to use
.PP
\fB\-\-context\fP=""
The name of the kubeconfig context to use
.PP
\fB\-\-insecure\-skip\-tls\-verify\fP=false
If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure.
.PP
\fB\-\-kubeconfig\fP=""
Path to the kubeconfig file to use for CLI requests.
.PP
\fB\-\-log\-backtrace\-at\fP=:0
when logging hits line file:N, emit a stack trace
.PP
\fB\-\-log\-dir\fP=""
If non\-empty, write log files in this directory
.PP
\fB\-\-log\-flush\-frequency\fP=5s
Maximum number of seconds between log flushes
.PP
\fB\-\-logtostderr\fP=true
log to standard error instead of files
.PP
\fB\-\-match\-server\-version\fP=false
Require server version to match client version
.PP
\fB\-\-namespace\fP=""
If present, the namespace scope for this CLI request.
.PP
\fB\-\-password\fP=""
Password for basic authentication to the API server.
.PP
\fB\-s\fP, \fB\-\-server\fP=""
The address and port of the Kubernetes API server
.PP
\fB\-\-stderrthreshold\fP=2
logs at or above this threshold go to stderr
.PP
\fB\-\-token\fP=""
Bearer token for authentication to the API server.
.PP
\fB\-\-user\fP=""
The name of the kubeconfig user to use
.PP
\fB\-\-username\fP=""
Username for basic authentication to the API server.
.PP
\fB\-\-v\fP=0
log level for V logs
.PP
\fB\-\-vmodule\fP=
comma\-separated list of pattern=N settings for file\-filtered logging
.SH EXAMPLE
.PP
.RS
.nf
# Create a new namespace named my\-namespace
$ kubectl create namespace my\-namespace
.fi
.RE
.SH SEE ALSO
.PP
\fBkubectl\-create(1)\fP,
.SH HISTORY
.PP
January 2015, Originally compiled by Eric Paris (eparis at redhat dot com) based on the kubernetes source material, but hopefully they have been automatically generated since!

View File

@ -0,0 +1,195 @@
.TH "KUBERNETES" "1" " kubernetes User Manuals" "Eric Paris" "Jan 2015" ""
.SH NAME
.PP
kubectl create secret docker\-registry \- Create a secret for use with a Docker registry.
.SH SYNOPSIS
.PP
\fBkubectl create secret docker\-registry\fP [OPTIONS]
.SH DESCRIPTION
.PP
Create a new secret for use with Docker registries.
.PP
Dockercfg secrets are used to authenticate against Docker registries.
.PP
When using the Docker command line to push images, you can authenticate to a given registry by running
'docker login DOCKER\_REGISTRY\_SERVER \-\-username=DOCKER\_USER \-\-password=DOCKER\_PASSWORD \-\-email=DOCKER\_EMAIL'.
That produces a \~/.dockercfg file that is used by subsequent 'docker push' and 'docker pull' commands to
authenticate to the registry.
.PP
When creating applications, you may have a Docker registry that requires authentication. In order for the
nodes to pull images on your behalf, they have to have the credentials. You can provide this information
by creating a dockercfg secret and attaching it to your service account.
.SH OPTIONS
.PP
\fB\-\-docker\-email\fP=""
Email for Docker registry
.PP
\fB\-\-docker\-password\fP=""
Password for Docker registry authentication
.PP
\fB\-\-docker\-server\fP="
\[la]https://index.docker.io/v1/"\[ra]
Server location for Docker registry
.PP
\fB\-\-docker\-username\fP=""
Username for Docker registry authentication
.PP
\fB\-\-dry\-run\fP=false
If true, only print the object that would be sent, without sending it.
.PP
\fB\-\-generator\fP="secret\-for\-docker\-registry/v1"
The name of the API generator to use.
.PP
\fB\-o\fP, \fB\-\-output\fP=""
Output format. One of: json|yaml|wide|name|go\-template=...|go\-template\-file=...|jsonpath=...|jsonpath\-file=... See golang template [
\[la]http://golang.org/pkg/text/template/#pkg-overview\[ra]] and jsonpath template [
\[la]http://releases.k8s.io/HEAD/docs/user-guide/jsonpath.md\[ra]].
.PP
\fB\-\-output\-version\fP=""
Output the formatted object with the given version (default api\-version).
.PP
\fB\-\-save\-config\fP=false
If true, the configuration of current object will be saved in its annotation. This is useful when you want to perform kubectl apply on this object in the future.
.PP
\fB\-\-schema\-cache\-dir\fP="\~/.kube/schema"
If non\-empty, load/store cached API schemas in this directory, default is '$HOME/.kube/schema'
.PP
\fB\-\-validate\fP=true
If true, use a schema to validate the input before sending it
.SH OPTIONS INHERITED FROM PARENT COMMANDS
.PP
\fB\-\-alsologtostderr\fP=false
log to standard error as well as files
.PP
\fB\-\-api\-version\fP=""
The API version to use when talking to the server
.PP
\fB\-\-certificate\-authority\fP=""
Path to a cert. file for the certificate authority.
.PP
\fB\-\-client\-certificate\fP=""
Path to a client certificate file for TLS.
.PP
\fB\-\-client\-key\fP=""
Path to a client key file for TLS.
.PP
\fB\-\-cluster\fP=""
The name of the kubeconfig cluster to use
.PP
\fB\-\-context\fP=""
The name of the kubeconfig context to use
.PP
\fB\-\-insecure\-skip\-tls\-verify\fP=false
If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure.
.PP
\fB\-\-kubeconfig\fP=""
Path to the kubeconfig file to use for CLI requests.
.PP
\fB\-\-log\-backtrace\-at\fP=:0
when logging hits line file:N, emit a stack trace
.PP
\fB\-\-log\-dir\fP=""
If non\-empty, write log files in this directory
.PP
\fB\-\-log\-flush\-frequency\fP=5s
Maximum number of seconds between log flushes
.PP
\fB\-\-logtostderr\fP=true
log to standard error instead of files
.PP
\fB\-\-match\-server\-version\fP=false
Require server version to match client version
.PP
\fB\-\-namespace\fP=""
If present, the namespace scope for this CLI request.
.PP
\fB\-\-password\fP=""
Password for basic authentication to the API server.
.PP
\fB\-s\fP, \fB\-\-server\fP=""
The address and port of the Kubernetes API server
.PP
\fB\-\-stderrthreshold\fP=2
logs at or above this threshold go to stderr
.PP
\fB\-\-token\fP=""
Bearer token for authentication to the API server.
.PP
\fB\-\-user\fP=""
The name of the kubeconfig user to use
.PP
\fB\-\-username\fP=""
Username for basic authentication to the API server.
.PP
\fB\-\-v\fP=0
log level for V logs
.PP
\fB\-\-vmodule\fP=
comma\-separated list of pattern=N settings for file\-filtered logging
.SH EXAMPLE
.PP
.RS
.nf
# If you don't already have a .dockercfg file, you can create a dockercfg secret directly by using:
$ kubectl create secret docker\-registry my\-secret \-\-docker\-server=DOCKER\_REGISTRY\_SERVER \-\-docker\-username=DOCKER\_USER \-\-docker\-password=DOCKER\_PASSWORD \-\-docker\-email=DOCKER\_EMAIL
.fi
.RE
.SH SEE ALSO
.PP
\fBkubectl\-create\-secret(1)\fP,
.SH HISTORY
.PP
January 2015, Originally compiled by Eric Paris (eparis at redhat dot com) based on the kubernetes source material, but hopefully they have been automatically generated since!

View File

@ -0,0 +1,194 @@
.TH "KUBERNETES" "1" " kubernetes User Manuals" "Eric Paris" "Jan 2015" ""
.SH NAME
.PP
kubectl create secret generic \- Create a secret from a local file, directory or literal value.
.SH SYNOPSIS
.PP
\fBkubectl create secret generic\fP [OPTIONS]
.SH DESCRIPTION
.PP
Create a secret based on a file, directory, or specified literal value
.PP
A single secret may package one or more key/value pairs.
.PP
When creating a secret based on a file, the key will default to the basename of the file, and the value will
default to the file content. If the basename is an invalid key, you may specify an alternate key.
.PP
When creating a secret based on a directory, each file whose basename is a valid key in the directory will be
packaged into the secret. Any directory entries except regular files are ignored (e.g. subdirectories,
symlinks, devices, pipes, etc).
.SH OPTIONS
.PP
\fB\-\-dry\-run\fP=false
If true, only print the object that would be sent, without sending it.
.PP
\fB\-\-from\-file\fP=[]
Key files can be specified using their file path, in which case a default name will be given to them, or optionally with a name and file path, in which case the given name will be used. Specifying a directory will iterate each named file in the directory that is a valid secret key.
.PP
\fB\-\-from\-literal\fP=[]
Specify a key and literal value to insert in secret (i.e. mykey=somevalue)
.PP
\fB\-\-generator\fP="secret/v1"
The name of the API generator to use.
.PP
\fB\-o\fP, \fB\-\-output\fP=""
Output format. One of: json|yaml|wide|name|go\-template=...|go\-template\-file=...|jsonpath=...|jsonpath\-file=... See golang template [
\[la]http://golang.org/pkg/text/template/#pkg-overview\[ra]] and jsonpath template [
\[la]http://releases.k8s.io/HEAD/docs/user-guide/jsonpath.md\[ra]].
.PP
\fB\-\-output\-version\fP=""
Output the formatted object with the given version (default api\-version).
.PP
\fB\-\-save\-config\fP=false
If true, the configuration of current object will be saved in its annotation. This is useful when you want to perform kubectl apply on this object in the future.
.PP
\fB\-\-schema\-cache\-dir\fP="\~/.kube/schema"
If non\-empty, load/store cached API schemas in this directory, default is '$HOME/.kube/schema'
.PP
\fB\-\-type\fP=""
The type of secret to create
.PP
\fB\-\-validate\fP=true
If true, use a schema to validate the input before sending it
.SH OPTIONS INHERITED FROM PARENT COMMANDS
.PP
\fB\-\-alsologtostderr\fP=false
log to standard error as well as files
.PP
\fB\-\-api\-version\fP=""
The API version to use when talking to the server
.PP
\fB\-\-certificate\-authority\fP=""
Path to a cert. file for the certificate authority.
.PP
\fB\-\-client\-certificate\fP=""
Path to a client certificate file for TLS.
.PP
\fB\-\-client\-key\fP=""
Path to a client key file for TLS.
.PP
\fB\-\-cluster\fP=""
The name of the kubeconfig cluster to use
.PP
\fB\-\-context\fP=""
The name of the kubeconfig context to use
.PP
\fB\-\-insecure\-skip\-tls\-verify\fP=false
If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure.
.PP
\fB\-\-kubeconfig\fP=""
Path to the kubeconfig file to use for CLI requests.
.PP
\fB\-\-log\-backtrace\-at\fP=:0
when logging hits line file:N, emit a stack trace
.PP
\fB\-\-log\-dir\fP=""
If non\-empty, write log files in this directory
.PP
\fB\-\-log\-flush\-frequency\fP=5s
Maximum number of seconds between log flushes
.PP
\fB\-\-logtostderr\fP=true
log to standard error instead of files
.PP
\fB\-\-match\-server\-version\fP=false
Require server version to match client version
.PP
\fB\-\-namespace\fP=""
If present, the namespace scope for this CLI request.
.PP
\fB\-\-password\fP=""
Password for basic authentication to the API server.
.PP
\fB\-s\fP, \fB\-\-server\fP=""
The address and port of the Kubernetes API server
.PP
\fB\-\-stderrthreshold\fP=2
logs at or above this threshold go to stderr
.PP
\fB\-\-token\fP=""
Bearer token for authentication to the API server.
.PP
\fB\-\-user\fP=""
The name of the kubeconfig user to use
.PP
\fB\-\-username\fP=""
Username for basic authentication to the API server.
.PP
\fB\-\-v\fP=0
log level for V logs
.PP
\fB\-\-vmodule\fP=
comma\-separated list of pattern=N settings for file\-filtered logging
.SH EXAMPLE
.PP
.RS
.nf
# Create a new secret named my\-secret with keys for each file in folder bar
$ kubectl create secret generic my\-secret \-\-from\-file=path/to/bar
# Create a new secret named my\-secret with specified keys instead of names on disk
$ kubectl create secret generic my\-secret \-\-from\-file=ssh\-privatekey=\~/.ssh/id\_rsa \-\-from\-file=ssh\-publickey=\~/.ssh/id\_rsa.pub
# Create a new secret named my\-secret with key1=supersecret and key2=topsecret
$ kubectl create secret generic my\-secret \-\-from\-literal=key1=supersecret \-\-from\-literal=key2=topsecret
.fi
.RE
.SH SEE ALSO
.PP
\fBkubectl\-create\-secret(1)\fP,
.SH HISTORY
.PP
January 2015, Originally compiled by Eric Paris (eparis at redhat dot com) based on the kubernetes source material, but hopefully they have been automatically generated since!

View File

@ -0,0 +1,120 @@
.TH "KUBERNETES" "1" " kubernetes User Manuals" "Eric Paris" "Jan 2015" ""
.SH NAME
.PP
kubectl create secret \- Create a secret using specified subcommand.
.SH SYNOPSIS
.PP
\fBkubectl create secret\fP [OPTIONS]
.SH DESCRIPTION
.PP
Create a secret using specified subcommand.
.SH OPTIONS INHERITED FROM PARENT COMMANDS
.PP
\fB\-\-alsologtostderr\fP=false
log to standard error as well as files
.PP
\fB\-\-api\-version\fP=""
The API version to use when talking to the server
.PP
\fB\-\-certificate\-authority\fP=""
Path to a cert. file for the certificate authority.
.PP
\fB\-\-client\-certificate\fP=""
Path to a client certificate file for TLS.
.PP
\fB\-\-client\-key\fP=""
Path to a client key file for TLS.
.PP
\fB\-\-cluster\fP=""
The name of the kubeconfig cluster to use
.PP
\fB\-\-context\fP=""
The name of the kubeconfig context to use
.PP
\fB\-\-insecure\-skip\-tls\-verify\fP=false
If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure.
.PP
\fB\-\-kubeconfig\fP=""
Path to the kubeconfig file to use for CLI requests.
.PP
\fB\-\-log\-backtrace\-at\fP=:0
when logging hits line file:N, emit a stack trace
.PP
\fB\-\-log\-dir\fP=""
If non\-empty, write log files in this directory
.PP
\fB\-\-log\-flush\-frequency\fP=5s
Maximum number of seconds between log flushes
.PP
\fB\-\-logtostderr\fP=true
log to standard error instead of files
.PP
\fB\-\-match\-server\-version\fP=false
Require server version to match client version
.PP
\fB\-\-namespace\fP=""
If present, the namespace scope for this CLI request.
.PP
\fB\-\-password\fP=""
Password for basic authentication to the API server.
.PP
\fB\-s\fP, \fB\-\-server\fP=""
The address and port of the Kubernetes API server
.PP
\fB\-\-stderrthreshold\fP=2
logs at or above this threshold go to stderr
.PP
\fB\-\-token\fP=""
Bearer token for authentication to the API server.
.PP
\fB\-\-user\fP=""
The name of the kubeconfig user to use
.PP
\fB\-\-username\fP=""
Username for basic authentication to the API server.
.PP
\fB\-\-v\fP=0
log level for V logs
.PP
\fB\-\-vmodule\fP=
comma\-separated list of pattern=N settings for file\-filtered logging
.SH SEE ALSO
.PP
\fBkubectl\-create(1)\fP, \fBkubectl\-create\-secret\-docker\-registry(1)\fP, \fBkubectl\-create\-secret\-generic(1)\fP,
.SH HISTORY
.PP
January 2015, Originally compiled by Eric Paris (eparis at redhat dot com) based on the kubernetes source material, but hopefully they have been automatically generated since!

View File

@ -152,7 +152,7 @@ $ cat pod.json | kubectl create \-f \-
.SH SEE ALSO
.PP
\fBkubectl(1)\fP,
\fBkubectl(1)\fP, \fBkubectl\-create\-namespace(1)\fP, \fBkubectl\-create\-secret(1)\fP,
.SH HISTORY

View File

@ -97,6 +97,8 @@ $ cat pod.json | kubectl create -f -
### SEE ALSO
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager
* [kubectl create namespace](kubectl_create_namespace.md) - Create a namespace with the specified name.
* [kubectl create secret](kubectl_create_secret.md) - Create a secret using specified subcommand.
###### Auto generated by spf13/cobra on 24-Nov-2015

View File

@ -0,0 +1,103 @@
<!-- BEGIN MUNGE: UNVERSIONED_WARNING -->
<!-- BEGIN STRIP_FOR_RELEASE -->
<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
width="25" height="25">
<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
width="25" height="25">
<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
width="25" height="25">
<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
width="25" height="25">
<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
width="25" height="25">
<h2>PLEASE NOTE: This document applies to the HEAD of the source tree</h2>
If you are using a released version of Kubernetes, you should
refer to the docs that go with that version.
<strong>
The latest release of this document can be found
[here](http://releases.k8s.io/release-1.1/docs/user-guide/kubectl/kubectl_create_namespace.md).
Documentation for other releases can be found at
[releases.k8s.io](http://releases.k8s.io).
</strong>
--
<!-- END STRIP_FOR_RELEASE -->
<!-- END MUNGE: UNVERSIONED_WARNING -->
## kubectl create namespace
Create a namespace with the specified name.
### Synopsis
Create a namespace with the specified name.
```
kubectl create namespace NAME [--dry-run]
```
### Examples
```
# Create a new namespace named my-namespace
$ kubectl create namespace my-namespace
```
### Options
```
--dry-run[=false]: If true, only print the object that would be sent, without sending it.
--generator="namespace/v1": The name of the API generator to use.
-o, --output="": Output format. One of: json|yaml|wide|name|go-template=...|go-template-file=...|jsonpath=...|jsonpath-file=... See golang template [http://golang.org/pkg/text/template/#pkg-overview] and jsonpath template [http://releases.k8s.io/HEAD/docs/user-guide/jsonpath.md].
--output-version="": Output the formatted object with the given version (default api-version).
--save-config[=false]: If true, the configuration of current object will be saved in its annotation. This is useful when you want to perform kubectl apply on this object in the future.
--schema-cache-dir="~/.kube/schema": If non-empty, load/store cached API schemas in this directory, default is '$HOME/.kube/schema'
--validate[=true]: If true, use a schema to validate the input before sending it
```
### Options inherited from parent commands
```
--alsologtostderr[=false]: log to standard error as well as files
--api-version="": The API version to use when talking to the server
--certificate-authority="": Path to a cert. file for the certificate authority.
--client-certificate="": Path to a client certificate file for TLS.
--client-key="": Path to a client key file for TLS.
--cluster="": The name of the kubeconfig cluster to use
--context="": The name of the kubeconfig context to use
--insecure-skip-tls-verify[=false]: If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure.
--kubeconfig="": Path to the kubeconfig file to use for CLI requests.
--log-backtrace-at=:0: when logging hits line file:N, emit a stack trace
--log-dir="": If non-empty, write log files in this directory
--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
--namespace="": If present, the namespace scope for this CLI request.
--password="": Password for basic authentication to the API server.
-s, --server="": The address and port of the Kubernetes API server
--stderrthreshold=2: logs at or above this threshold go to stderr
--token="": Bearer token for authentication to the API server.
--user="": The name of the kubeconfig user to use
--username="": Username for basic authentication to the API server.
--v=0: log level for V logs
--vmodule=: comma-separated list of pattern=N settings for file-filtered logging
```
### SEE ALSO
* [kubectl create](kubectl_create.md) - Create a resource by filename or stdin
###### Auto generated by spf13/cobra on 14-Dec-2015
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/user-guide/kubectl/kubectl_create_namespace.md?pixel)]()
<!-- END MUNGE: GENERATED_ANALYTICS -->

View File

@ -0,0 +1,85 @@
<!-- BEGIN MUNGE: UNVERSIONED_WARNING -->
<!-- BEGIN STRIP_FOR_RELEASE -->
<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
width="25" height="25">
<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
width="25" height="25">
<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
width="25" height="25">
<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
width="25" height="25">
<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
width="25" height="25">
<h2>PLEASE NOTE: This document applies to the HEAD of the source tree</h2>
If you are using a released version of Kubernetes, you should
refer to the docs that go with that version.
<strong>
The latest release of this document can be found
[here](http://releases.k8s.io/release-1.1/docs/user-guide/kubectl/kubectl_create_secret.md).
Documentation for other releases can be found at
[releases.k8s.io](http://releases.k8s.io).
</strong>
--
<!-- END STRIP_FOR_RELEASE -->
<!-- END MUNGE: UNVERSIONED_WARNING -->
## kubectl create secret
Create a secret using specified subcommand.
### Synopsis
Create a secret using specified subcommand.
```
kubectl create secret
```
### Options inherited from parent commands
```
--alsologtostderr[=false]: log to standard error as well as files
--api-version="": The API version to use when talking to the server
--certificate-authority="": Path to a cert. file for the certificate authority.
--client-certificate="": Path to a client certificate file for TLS.
--client-key="": Path to a client key file for TLS.
--cluster="": The name of the kubeconfig cluster to use
--context="": The name of the kubeconfig context to use
--insecure-skip-tls-verify[=false]: If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure.
--kubeconfig="": Path to the kubeconfig file to use for CLI requests.
--log-backtrace-at=:0: when logging hits line file:N, emit a stack trace
--log-dir="": If non-empty, write log files in this directory
--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
--namespace="": If present, the namespace scope for this CLI request.
--password="": Password for basic authentication to the API server.
-s, --server="": The address and port of the Kubernetes API server
--stderrthreshold=2: logs at or above this threshold go to stderr
--token="": Bearer token for authentication to the API server.
--user="": The name of the kubeconfig user to use
--username="": Username for basic authentication to the API server.
--v=0: log level for V logs
--vmodule=: comma-separated list of pattern=N settings for file-filtered logging
```
### SEE ALSO
* [kubectl create](kubectl_create.md) - Create a resource by filename or stdin
* [kubectl create secret docker-registry](kubectl_create_secret_docker-registry.md) - Create a secret for use with a Docker registry.
* [kubectl create secret generic](kubectl_create_secret_generic.md) - Create a secret from a local file, directory or literal value.
###### Auto generated by spf13/cobra on 14-Dec-2015
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/user-guide/kubectl/kubectl_create_secret.md?pixel)]()
<!-- END MUNGE: GENERATED_ANALYTICS -->

View File

@ -0,0 +1,118 @@
<!-- BEGIN MUNGE: UNVERSIONED_WARNING -->
<!-- BEGIN STRIP_FOR_RELEASE -->
<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
width="25" height="25">
<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
width="25" height="25">
<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
width="25" height="25">
<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
width="25" height="25">
<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
width="25" height="25">
<h2>PLEASE NOTE: This document applies to the HEAD of the source tree</h2>
If you are using a released version of Kubernetes, you should
refer to the docs that go with that version.
<strong>
The latest release of this document can be found
[here](http://releases.k8s.io/release-1.1/docs/user-guide/kubectl/kubectl_create_secret_docker-registry.md).
Documentation for other releases can be found at
[releases.k8s.io](http://releases.k8s.io).
</strong>
--
<!-- END STRIP_FOR_RELEASE -->
<!-- END MUNGE: UNVERSIONED_WARNING -->
## kubectl create secret docker-registry
Create a secret for use with a Docker registry.
### Synopsis
Create a new secret for use with Docker registries.
Dockercfg secrets are used to authenticate against Docker registries.
When using the Docker command line to push images, you can authenticate to a given registry by running
'docker login DOCKER_REGISTRY_SERVER --username=DOCKER_USER --password=DOCKER_PASSWORD --email=DOCKER_EMAIL'.
That produces a ~/.dockercfg file that is used by subsequent 'docker push' and 'docker pull' commands to
authenticate to the registry.
When creating applications, you may have a Docker registry that requires authentication. In order for the
nodes to pull images on your behalf, they have to have the credentials. You can provide this information
by creating a dockercfg secret and attaching it to your service account.
```
kubectl create secret docker-registry NAME --docker-username=user --docker-password=password --docker-email=email [--docker-server=string] [--from-literal=key1=value1] [--dry-run]
```
### Examples
```
# If you don't already have a .dockercfg file, you can create a dockercfg secret directly by using:
$ kubectl create secret docker-registry my-secret --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL
```
### Options
```
--docker-email="": Email for Docker registry
--docker-password="": Password for Docker registry authentication
--docker-server="https://index.docker.io/v1/": Server location for Docker registry
--docker-username="": Username for Docker registry authentication
--dry-run[=false]: If true, only print the object that would be sent, without sending it.
--generator="secret-for-docker-registry/v1": The name of the API generator to use.
-o, --output="": Output format. One of: json|yaml|wide|name|go-template=...|go-template-file=...|jsonpath=...|jsonpath-file=... See golang template [http://golang.org/pkg/text/template/#pkg-overview] and jsonpath template [http://releases.k8s.io/HEAD/docs/user-guide/jsonpath.md].
--output-version="": Output the formatted object with the given version (default api-version).
--save-config[=false]: If true, the configuration of current object will be saved in its annotation. This is useful when you want to perform kubectl apply on this object in the future.
--schema-cache-dir="~/.kube/schema": If non-empty, load/store cached API schemas in this directory, default is '$HOME/.kube/schema'
--validate[=true]: If true, use a schema to validate the input before sending it
```
### Options inherited from parent commands
```
--alsologtostderr[=false]: log to standard error as well as files
--api-version="": The API version to use when talking to the server
--certificate-authority="": Path to a cert. file for the certificate authority.
--client-certificate="": Path to a client certificate file for TLS.
--client-key="": Path to a client key file for TLS.
--cluster="": The name of the kubeconfig cluster to use
--context="": The name of the kubeconfig context to use
--insecure-skip-tls-verify[=false]: If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure.
--kubeconfig="": Path to the kubeconfig file to use for CLI requests.
--log-backtrace-at=:0: when logging hits line file:N, emit a stack trace
--log-dir="": If non-empty, write log files in this directory
--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
--namespace="": If present, the namespace scope for this CLI request.
--password="": Password for basic authentication to the API server.
-s, --server="": The address and port of the Kubernetes API server
--stderrthreshold=2: logs at or above this threshold go to stderr
--token="": Bearer token for authentication to the API server.
--user="": The name of the kubeconfig user to use
--username="": Username for basic authentication to the API server.
--v=0: log level for V logs
--vmodule=: comma-separated list of pattern=N settings for file-filtered logging
```
### SEE ALSO
* [kubectl create secret](kubectl_create_secret.md) - Create a secret using specified subcommand.
###### Auto generated by spf13/cobra on 14-Dec-2015
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/user-guide/kubectl/kubectl_create_secret_docker-registry.md?pixel)]()
<!-- END MUNGE: GENERATED_ANALYTICS -->

View File

@ -0,0 +1,122 @@
<!-- BEGIN MUNGE: UNVERSIONED_WARNING -->
<!-- BEGIN STRIP_FOR_RELEASE -->
<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
width="25" height="25">
<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
width="25" height="25">
<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
width="25" height="25">
<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
width="25" height="25">
<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
width="25" height="25">
<h2>PLEASE NOTE: This document applies to the HEAD of the source tree</h2>
If you are using a released version of Kubernetes, you should
refer to the docs that go with that version.
<strong>
The latest release of this document can be found
[here](http://releases.k8s.io/release-1.1/docs/user-guide/kubectl/kubectl_create_secret_generic.md).
Documentation for other releases can be found at
[releases.k8s.io](http://releases.k8s.io).
</strong>
--
<!-- END STRIP_FOR_RELEASE -->
<!-- END MUNGE: UNVERSIONED_WARNING -->
## kubectl create secret generic
Create a secret from a local file, directory or literal value.
### Synopsis
Create a secret based on a file, directory, or specified literal value
A single secret may package one or more key/value pairs.
When creating a secret based on a file, the key will default to the basename of the file, and the value will
default to the file content. If the basename is an invalid key, you may specify an alternate key.
When creating a secret based on a directory, each file whose basename is a valid key in the directory will be
packaged into the secret. Any directory entries except regular files are ignored (e.g. subdirectories,
symlinks, devices, pipes, etc).
```
kubectl create secret generic NAME [--type=string] [--from-file=[key=]source] [--from-literal=key1=value1] [--dry-run]
```
### Examples
```
# Create a new secret named my-secret with keys for each file in folder bar
$ kubectl create secret generic my-secret --from-file=path/to/bar
# Create a new secret named my-secret with specified keys instead of names on disk
$ kubectl create secret generic my-secret --from-file=ssh-privatekey=~/.ssh/id_rsa --from-file=ssh-publickey=~/.ssh/id_rsa.pub
# Create a new secret named my-secret with key1=supersecret and key2=topsecret
$ kubectl create secret generic my-secret --from-literal=key1=supersecret --from-literal=key2=topsecret
```
### Options
```
--dry-run[=false]: If true, only print the object that would be sent, without sending it.
--from-file=[]: Key files can be specified using their file path, in which case a default name will be given to them, or optionally with a name and file path, in which case the given name will be used. Specifying a directory will iterate each named file in the directory that is a valid secret key.
--from-literal=[]: Specify a key and literal value to insert in secret (i.e. mykey=somevalue)
--generator="secret/v1": The name of the API generator to use.
-o, --output="": Output format. One of: json|yaml|wide|name|go-template=...|go-template-file=...|jsonpath=...|jsonpath-file=... See golang template [http://golang.org/pkg/text/template/#pkg-overview] and jsonpath template [http://releases.k8s.io/HEAD/docs/user-guide/jsonpath.md].
--output-version="": Output the formatted object with the given version (default api-version).
--save-config[=false]: If true, the configuration of current object will be saved in its annotation. This is useful when you want to perform kubectl apply on this object in the future.
--schema-cache-dir="~/.kube/schema": If non-empty, load/store cached API schemas in this directory, default is '$HOME/.kube/schema'
--type="": The type of secret to create
--validate[=true]: If true, use a schema to validate the input before sending it
```
### Options inherited from parent commands
```
--alsologtostderr[=false]: log to standard error as well as files
--api-version="": The API version to use when talking to the server
--certificate-authority="": Path to a cert. file for the certificate authority.
--client-certificate="": Path to a client certificate file for TLS.
--client-key="": Path to a client key file for TLS.
--cluster="": The name of the kubeconfig cluster to use
--context="": The name of the kubeconfig context to use
--insecure-skip-tls-verify[=false]: If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure.
--kubeconfig="": Path to the kubeconfig file to use for CLI requests.
--log-backtrace-at=:0: when logging hits line file:N, emit a stack trace
--log-dir="": If non-empty, write log files in this directory
--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
--namespace="": If present, the namespace scope for this CLI request.
--password="": Password for basic authentication to the API server.
-s, --server="": The address and port of the Kubernetes API server
--stderrthreshold=2: logs at or above this threshold go to stderr
--token="": Bearer token for authentication to the API server.
--user="": The name of the kubeconfig user to use
--username="": Username for basic authentication to the API server.
--v=0: log level for V logs
--vmodule=: comma-separated list of pattern=N settings for file-filtered logging
```
### SEE ALSO
* [kubectl create secret](kubectl_create_secret.md) - Create a secret using specified subcommand.
###### Auto generated by spf13/cobra on 14-Dec-2015
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/user-guide/kubectl/kubectl_create_secret_generic.md?pixel)]()
<!-- END MUNGE: GENERATED_ANALYTICS -->

View File

@ -224,6 +224,8 @@ runTests() {
hpa_cpu_field=".spec.cpuUtilization.targetPercentage"
job_parallelism_field=".spec.parallelism"
deployment_replicas=".spec.replicas"
secret_data=".data"
secret_type=".type"
# Passing no arguments to create is an error
! kubectl create
@ -674,6 +676,20 @@ runTests() {
# Namespaces #
##############
### Create a new namespace
# Pre-condition: only the "default" namespace exists
kube::test::get_object_assert 'namespaces' "{{range.items}}{{$id_field}}:{{end}}" 'default:'
# Command
kubectl create namespace my-namespace
# Post-condition: namespace 'my-namespace' is created.
kube::test::get_object_assert 'namespaces/my-namespace' "{{$id_field}}" 'my-namespace'
# Clean up
kubectl delete namespace my-namespace
##############
# Pods in Namespaces #
##############
### Create POD valid-pod in specific namespace
# Pre-condition: no POD is running
kube::test::get_object_assert 'pods --namespace=other' "{{range.items}}{{$id_field}}:{{end}}" ''
@ -690,6 +706,33 @@ runTests() {
# Post-condition: no POD is running
kube::test::get_object_assert 'pods --namespace=other' "{{range.items}}{{$id_field}}:{{end}}" ''
##############
# Secrets #
##############
### Create a generic secret in a specific namespace
# Pre-condition: no SECRET exists
kube::test::get_object_assert 'secrets --namespace=test-secrets' "{{range.items}}{{$id_field}}:{{end}}" ''
# Command
kubectl create secret generic test-secret --from-literal=key1=value1 --type=test-type --namespace=test-secrets
# Post-condition: secret exists and has expected values
kube::test::get_object_assert 'secret/test-secret --namespace=test-secrets' "{{$id_field}}" 'test-secret'
kube::test::get_object_assert 'secret/test-secret --namespace=test-secrets' "{{$secret_type}}" 'test-type'
[[ "$(kubectl get secret/test-secret --namespace=test-secrets -o yaml "${kube_flags[@]}" | grep 'key1: dmFsdWUx')" ]]
# Clean-up
kubectl delete secret test-secret --namespace=test-secrets
### Create a docker-registry secret in a specific namespace
# Pre-condition: no SECRET exists
kube::test::get_object_assert 'secrets --namespace=test-secrets' "{{range.items}}{{$id_field}}:{{end}}" ''
# Command
kubectl create secret docker-registry test-secret --docker-username=test-user --docker-password=test-password --docker-email='test-user@test.com' --namespace=test-secrets
# Post-condition: secret exists and has expected values
kube::test::get_object_assert 'secret/test-secret --namespace=test-secrets' "{{$id_field}}" 'test-secret'
kube::test::get_object_assert 'secret/test-secret --namespace=test-secrets' "{{$secret_type}}" 'kubernetes.io/dockercfg'
[[ "$(kubectl get secret/test-secret --namespace=test-secrets -o yaml "${kube_flags[@]}" | grep '.dockercfg:')" ]]
# Clean-up
kubectl delete secret test-secret --namespace=test-secrets
#################
# Pod templates #

View File

@ -70,8 +70,12 @@ dest-file
disable-filter
dockercfg-path
docker-endpoint
docker-email
docker-exec-handler
docker-password
driver-port
docker-server
docker-username
dry-run
duration-sec
e2e-output-dir
@ -102,6 +106,8 @@ file-suffix
forward-services
framework-name
framework-weburi
from-file
from-literal
func-dest
fuzz-iters
gather-logs-sizes

View File

@ -218,13 +218,8 @@ func NewAPIFactory() (*cmdutil.Factory, *testFactory, runtime.Codec) {
t := &testFactory{
Validator: validation.NullSchema{},
}
generators := map[string]kubectl.Generator{
"run/v1": kubectl.BasicReplicationController{},
"run-pod/v1": kubectl.BasicPod{},
"service/v1": kubectl.ServiceGeneratorV1{},
"service/v2": kubectl.ServiceGeneratorV2{},
"service/test": testServiceGenerator{},
}
generators := cmdutil.DefaultGenerators()
generators["service/test"] = testServiceGenerator{}
f := &cmdutil.Factory{
Object: func() (meta.RESTMapper, runtime.ObjectTyper) {
return testapi.Default.RESTMapper(), api.Scheme

View File

@ -24,6 +24,7 @@ import (
"github.com/spf13/cobra"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/kubectl"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/kubectl/resource"
@ -56,6 +57,10 @@ func NewCmdCreate(f *cmdutil.Factory, out io.Writer) *cobra.Command {
Long: create_long,
Example: create_example,
Run: func(cmd *cobra.Command, args []string) {
if len(options.Filenames) == 0 {
cmd.Help()
return
}
cmdutil.CheckErr(ValidateArgs(cmd, args))
cmdutil.CheckErr(cmdutil.ValidateOutputArgs(cmd))
cmdutil.CheckErr(RunCreate(f, cmd, out, options))
@ -68,6 +73,10 @@ func NewCmdCreate(f *cmdutil.Factory, out io.Writer) *cobra.Command {
cmdutil.AddValidateFlags(cmd)
cmdutil.AddOutputFlagsForMutation(cmd)
cmdutil.AddApplyAnnotationFlags(cmd)
// create subcommands
cmd.AddCommand(NewCmdCreateNamespace(f, out))
cmd.AddCommand(NewCmdCreateSecret(f, out))
return cmd
}
@ -172,3 +181,66 @@ func createAndRefresh(info *resource.Info) error {
info.Refresh(obj, true)
return nil
}
// NameFromCommandArgs is a utility function for commands that assume the first argument is a resource name
func NameFromCommandArgs(cmd *cobra.Command, args []string) (string, error) {
if len(args) == 0 {
return "", cmdutil.UsageError(cmd, "NAME is required")
}
return args[0], nil
}
// CreateSubcommandOptions is an options struct to support create subcommands
type CreateSubcommandOptions struct {
// Name of resource being created
Name string
// StructuredGenerator is the resource generator for the object being created
StructuredGenerator kubectl.StructuredGenerator
// DryRun is true if the command should be simulated but not run against the server
DryRun bool
// OutputFormat
OutputFormat string
}
// RunCreateSubcommand executes a create subcommand using the specified options
func RunCreateSubcommand(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer, options *CreateSubcommandOptions) error {
namespace, _, err := f.DefaultNamespace()
if err != nil {
return err
}
obj, err := options.StructuredGenerator.StructuredGenerate()
if err != nil {
return err
}
mapper, typer := f.Object()
gvk, err := typer.ObjectKind(obj)
mapping, err := mapper.RESTMapping(unversioned.GroupKind{Group: gvk.Group, Kind: gvk.Kind}, gvk.Version)
if err != nil {
return err
}
client, err := f.RESTClient(mapping)
if err != nil {
return err
}
resourceMapper := &resource.Mapper{ObjectTyper: typer, RESTMapper: mapper, ClientMapper: f.ClientMapperForCommand()}
info, err := resourceMapper.InfoForObject(obj)
if err != nil {
return err
}
if err := kubectl.UpdateApplyAnnotation(info); err != nil {
return err
}
if !options.DryRun {
obj, err = resource.NewHelper(client, mapping).Create(namespace, false, info.Object)
if err != nil {
return err
}
}
if useShortOutput := options.OutputFormat == "name"; useShortOutput || len(options.OutputFormat) == 0 {
cmdutil.PrintSuccess(mapper, useShortOutput, out, mapping.Resource, options.Name, "created")
return nil
}
return f.PrintObject(cmd, obj, out)
}

View File

@ -0,0 +1,75 @@
/*
Copyright 2015 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cmd
import (
"fmt"
"io"
"github.com/spf13/cobra"
"k8s.io/kubernetes/pkg/kubectl"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
)
const (
namespaceLong = `
Create a namespace with the specified name.`
namespaceExample = ` # Create a new namespace named my-namespace
$ kubectl create namespace my-namespace`
)
// NewCmdCreateNamespace is a macro command to create a new namespace
func NewCmdCreateNamespace(f *cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
cmd := &cobra.Command{
Use: "namespace NAME [--dry-run]",
Aliases: []string{"ns"},
Short: "Create a namespace with the specified name.",
Long: namespaceLong,
Example: namespaceExample,
Run: func(cmd *cobra.Command, args []string) {
err := CreateNamespace(f, cmdOut, cmd, args)
cmdutil.CheckErr(err)
},
}
cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddValidateFlags(cmd)
cmdutil.AddGeneratorFlags(cmd, cmdutil.NamespaceV1GeneratorName)
return cmd
}
// CreateNamespace implements the behavior to run the create namespace command
func CreateNamespace(f *cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, args []string) error {
name, err := NameFromCommandArgs(cmd, args)
if err != nil {
return err
}
var generator kubectl.StructuredGenerator
switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName {
case cmdutil.NamespaceV1GeneratorName:
generator = &kubectl.NamespaceGeneratorV1{Name: name}
default:
return cmdutil.UsageError(cmd, fmt.Sprintf("Generator: %s not supported.", generatorName))
}
return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{
Name: name,
StructuredGenerator: generator,
DryRun: cmdutil.GetFlagBool(cmd, "dry-run"),
OutputFormat: cmdutil.GetFlagString(cmd, "output"),
})
}

View File

@ -0,0 +1,53 @@
/*
Copyright 2014 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cmd
import (
"bytes"
"net/http"
"testing"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/client/unversioned/fake"
)
func TestCreateNamespace(t *testing.T) {
namespaceObject := &api.Namespace{}
namespaceObject.Name = "my-namespace"
f, tf, codec := NewAPIFactory()
tf.Printer = &testPrinter{}
tf.Client = &fake.RESTClient{
Codec: codec,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; {
case p == "/namespaces" && m == "POST":
return &http.Response{StatusCode: 201, Body: objBody(codec, namespaceObject)}, nil
default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil
}
}),
}
buf := bytes.NewBuffer([]byte{})
cmd := NewCmdCreateNamespace(f, buf)
cmd.Flags().Set("output", "name")
cmd.Run(cmd, []string{namespaceObject.Name})
expectedOutput := "namespace/" + namespaceObject.Name + "\n"
if buf.String() != expectedOutput {
t.Errorf("expected output: %s, but got: %s", buf.String(), expectedOutput)
}
}

View File

@ -0,0 +1,190 @@
/*
Copyright 2015 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cmd
import (
"fmt"
"io"
"github.com/spf13/cobra"
"k8s.io/kubernetes/pkg/kubectl"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
)
// NewCmdCreateSecret groups subcommands to create various types of secrets
func NewCmdCreateSecret(f *cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
cmd := &cobra.Command{
Use: "secret",
Short: "Create a secret using specified subcommand.",
Long: "Create a secret using specified subcommand.",
Run: func(cmd *cobra.Command, args []string) {
cmd.Help()
},
}
cmd.AddCommand(NewCmdCreateSecretDockerRegistry(f, cmdOut))
cmd.AddCommand(NewCmdCreateSecretGeneric(f, cmdOut))
return cmd
}
const (
secretLong = `
Create a secret based on a file, directory, or specified literal value
A single secret may package one or more key/value pairs.
When creating a secret based on a file, the key will default to the basename of the file, and the value will
default to the file content. If the basename is an invalid key, you may specify an alternate key.
When creating a secret based on a directory, each file whose basename is a valid key in the directory will be
packaged into the secret. Any directory entries except regular files are ignored (e.g. subdirectories,
symlinks, devices, pipes, etc).
`
secretExample = ` # Create a new secret named my-secret with keys for each file in folder bar
$ kubectl create secret generic my-secret --from-file=path/to/bar
# Create a new secret named my-secret with specified keys instead of names on disk
$ kubectl create secret generic my-secret --from-file=ssh-privatekey=~/.ssh/id_rsa --from-file=ssh-publickey=~/.ssh/id_rsa.pub
# Create a new secret named my-secret with key1=supersecret and key2=topsecret
$ kubectl create secret generic my-secret --from-literal=key1=supersecret --from-literal=key2=topsecret`
)
// NewCmdCreateSecretGeneric is a command to create generic secrets from files, directories, or literal values
func NewCmdCreateSecretGeneric(f *cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
cmd := &cobra.Command{
Use: "generic NAME [--type=string] [--from-file=[key=]source] [--from-literal=key1=value1] [--dry-run]",
Short: "Create a secret from a local file, directory or literal value.",
Long: secretLong,
Example: secretExample,
Run: func(cmd *cobra.Command, args []string) {
err := CreateSecretGeneric(f, cmdOut, cmd, args)
cmdutil.CheckErr(err)
},
}
cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddValidateFlags(cmd)
cmdutil.AddGeneratorFlags(cmd, cmdutil.SecretV1GeneratorName)
cmd.Flags().StringSlice("from-file", []string{}, "Key files can be specified using their file path, in which case a default name will be given to them, or optionally with a name and file path, in which case the given name will be used. Specifying a directory will iterate each named file in the directory that is a valid secret key.")
cmd.Flags().StringSlice("from-literal", []string{}, "Specify a key and literal value to insert in secret (i.e. mykey=somevalue)")
cmd.Flags().String("type", "", "The type of secret to create")
return cmd
}
// CreateSecretGeneric is the implementation the create secret generic command
func CreateSecretGeneric(f *cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, args []string) error {
name, err := NameFromCommandArgs(cmd, args)
if err != nil {
return err
}
var generator kubectl.StructuredGenerator
switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName {
case cmdutil.SecretV1GeneratorName:
generator = &kubectl.SecretGeneratorV1{
Name: name,
Type: cmdutil.GetFlagString(cmd, "type"),
FileSources: cmdutil.GetFlagStringSlice(cmd, "from-file"),
LiteralSources: cmdutil.GetFlagStringSlice(cmd, "from-literal"),
}
default:
return cmdutil.UsageError(cmd, fmt.Sprintf("Generator: %s not supported.", generatorName))
}
return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{
Name: name,
StructuredGenerator: generator,
DryRun: cmdutil.GetFlagBool(cmd, "dry-run"),
OutputFormat: cmdutil.GetFlagString(cmd, "output"),
})
}
const (
secretForDockerRegistryLong = `
Create a new secret for use with Docker registries.
Dockercfg secrets are used to authenticate against Docker registries.
When using the Docker command line to push images, you can authenticate to a given registry by running
'docker login DOCKER_REGISTRY_SERVER --username=DOCKER_USER --password=DOCKER_PASSWORD --email=DOCKER_EMAIL'.
That produces a ~/.dockercfg file that is used by subsequent 'docker push' and 'docker pull' commands to
authenticate to the registry.
When creating applications, you may have a Docker registry that requires authentication. In order for the
nodes to pull images on your behalf, they have to have the credentials. You can provide this information
by creating a dockercfg secret and attaching it to your service account.`
secretForDockerRegistryExample = ` # If you don't already have a .dockercfg file, you can create a dockercfg secret directly by using:
$ kubectl create secret docker-registry my-secret --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL`
)
// NewCmdCreateSecretDockerRegistry is a macro command for creating secrets to work with Docker registries
func NewCmdCreateSecretDockerRegistry(f *cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
cmd := &cobra.Command{
Use: "docker-registry NAME --docker-username=user --docker-password=password --docker-email=email [--docker-server=string] [--from-literal=key1=value1] [--dry-run]",
Short: "Create a secret for use with a Docker registry.",
Long: secretForDockerRegistryLong,
Example: secretForDockerRegistryExample,
Run: func(cmd *cobra.Command, args []string) {
err := CreateSecretDockerRegistry(f, cmdOut, cmd, args)
cmdutil.CheckErr(err)
},
}
cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddValidateFlags(cmd)
cmdutil.AddGeneratorFlags(cmd, cmdutil.SecretForDockerRegistryV1GeneratorName)
cmd.Flags().String("docker-username", "", "Username for Docker registry authentication")
cmd.MarkFlagRequired("docker-username")
cmd.Flags().String("docker-password", "", "Password for Docker registry authentication")
cmd.MarkFlagRequired("docker-password")
cmd.Flags().String("docker-email", "", "Email for Docker registry")
cmd.MarkFlagRequired("docker-email")
cmd.Flags().String("docker-server", "https://index.docker.io/v1/", "Server location for Docker registry")
return cmd
}
// CreateSecretDockerRegistry is the implementation of the create secret docker-registry command
func CreateSecretDockerRegistry(f *cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, args []string) error {
name, err := NameFromCommandArgs(cmd, args)
if err != nil {
return err
}
requiredFlags := []string{"docker-username", "docker-password", "docker-email", "docker-server"}
for _, requiredFlag := range requiredFlags {
if value := cmdutil.GetFlagString(cmd, requiredFlag); len(value) == 0 {
return cmdutil.UsageError(cmd, "flag %s is required", requiredFlag)
}
}
var generator kubectl.StructuredGenerator
switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName {
case cmdutil.SecretForDockerRegistryV1GeneratorName:
generator = &kubectl.SecretForDockerRegistryGeneratorV1{
Name: name,
Username: cmdutil.GetFlagString(cmd, "docker-username"),
Email: cmdutil.GetFlagString(cmd, "docker-email"),
Password: cmdutil.GetFlagString(cmd, "docker-password"),
Server: cmdutil.GetFlagString(cmd, "docker-server"),
}
default:
return cmdutil.UsageError(cmd, fmt.Sprintf("Generator: %s not supported.", generatorName))
}
return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{
Name: name,
StructuredGenerator: generator,
DryRun: cmdutil.GetFlagBool(cmd, "dry-run"),
OutputFormat: cmdutil.GetFlagString(cmd, "output"),
})
}

View File

@ -0,0 +1,85 @@
/*
Copyright 2014 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cmd
import (
"bytes"
"net/http"
"testing"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/client/unversioned/fake"
)
func TestCreateSecretGeneric(t *testing.T) {
secretObject := &api.Secret{}
secretObject.Name = "my-secret"
f, tf, codec := NewAPIFactory()
tf.Printer = &testPrinter{}
tf.Client = &fake.RESTClient{
Codec: codec,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; {
case p == "/namespaces/test/secrets" && m == "POST":
return &http.Response{StatusCode: 201, Body: objBody(codec, secretObject)}, nil
default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil
}
}),
}
tf.Namespace = "test"
buf := bytes.NewBuffer([]byte{})
cmd := NewCmdCreateSecretGeneric(f, buf)
cmd.Flags().Set("output", "name")
cmd.Run(cmd, []string{secretObject.Name})
expectedOutput := "secret/" + secretObject.Name + "\n"
if buf.String() != expectedOutput {
t.Errorf("expected output: %s, but got: %s", buf.String(), expectedOutput)
}
}
func TestCreateSecretDockerRegistry(t *testing.T) {
secretObject := &api.Secret{}
secretObject.Name = "my-secret"
f, tf, codec := NewAPIFactory()
tf.Printer = &testPrinter{}
tf.Client = &fake.RESTClient{
Codec: codec,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; {
case p == "/namespaces/test/secrets" && m == "POST":
return &http.Response{StatusCode: 201, Body: objBody(codec, secretObject)}, nil
default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil
}
}),
}
tf.Namespace = "test"
buf := bytes.NewBuffer([]byte{})
cmd := NewCmdCreateSecretDockerRegistry(f, buf)
cmd.Flags().Set("docker-username", "test-user")
cmd.Flags().Set("docker-password", "test-pass")
cmd.Flags().Set("docker-email", "test-email")
cmd.Flags().Set("output", "name")
cmd.Run(cmd, []string{secretObject.Name})
expectedOutput := "secret/" + secretObject.Name + "\n"
if buf.String() != expectedOutput {
t.Errorf("expected output: %s, but got: %s", buf.String(), expectedOutput)
}
}

View File

@ -106,6 +106,35 @@ type Factory struct {
EditorEnvs func() []string
}
const (
RunV1GeneratorName = "run/v1"
RunPodV1GeneratorName = "run-pod/v1"
ServiceV1GeneratorName = "service/v1"
ServiceV2GeneratorName = "service/v2"
HorizontalPodAutoscalerV1Beta1GeneratorName = "horizontalpodautoscaler/v1beta1"
DeploymentV1Beta1GeneratorName = "deployment/v1beta1"
JobV1Beta1GeneratorName = "job/v1beta1"
NamespaceV1GeneratorName = "namespace/v1"
SecretV1GeneratorName = "secret/v1"
SecretForDockerRegistryV1GeneratorName = "secret-for-docker-registry/v1"
)
// DefaultGenerators returns the set of default generators for use in Factory instances
func DefaultGenerators() map[string]kubectl.Generator {
return map[string]kubectl.Generator{
RunV1GeneratorName: kubectl.BasicReplicationController{},
RunPodV1GeneratorName: kubectl.BasicPod{},
ServiceV1GeneratorName: kubectl.ServiceGeneratorV1{},
ServiceV2GeneratorName: kubectl.ServiceGeneratorV2{},
HorizontalPodAutoscalerV1Beta1GeneratorName: kubectl.HorizontalPodAutoscalerV1Beta1{},
DeploymentV1Beta1GeneratorName: kubectl.DeploymentV1Beta1{},
JobV1Beta1GeneratorName: kubectl.JobV1Beta1{},
NamespaceV1GeneratorName: kubectl.NamespaceGeneratorV1{},
SecretV1GeneratorName: kubectl.SecretGeneratorV1{},
SecretForDockerRegistryV1GeneratorName: kubectl.SecretForDockerRegistryGeneratorV1{},
}
}
// NewFactory creates a factory with the default Kubernetes resources defined
// if optionalClientConfig is nil, then flags will be bound to a new clientcmd.ClientConfig.
// if optionalClientConfig is not nil, then this factory will make use of it.
@ -115,15 +144,7 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory {
flags := pflag.NewFlagSet("", pflag.ContinueOnError)
flags.SetNormalizeFunc(util.WarnWordSepNormalizeFunc) // Warn for "_" flags
generators := map[string]kubectl.Generator{
"run/v1": kubectl.BasicReplicationController{},
"run-pod/v1": kubectl.BasicPod{},
"service/v1": kubectl.ServiceGeneratorV1{},
"service/v2": kubectl.ServiceGeneratorV2{},
"horizontalpodautoscaler/v1beta1": kubectl.HorizontalPodAutoscalerV1Beta1{},
"deployment/v1beta1": kubectl.DeploymentV1Beta1{},
"job/v1beta1": kubectl.JobV1Beta1{},
}
generators := DefaultGenerators()
clientConfig := optionalClientConfig
if optionalClientConfig == nil {

View File

@ -304,6 +304,15 @@ func AddApplyAnnotationFlags(cmd *cobra.Command) {
cmd.Flags().Bool(ApplyAnnotationsFlag, false, "If true, the configuration of current object will be saved in its annotation. This is useful when you want to perform kubectl apply on this object in the future.")
}
// AddGeneratorFlags adds flags common to resource generation commands
// TODO: need to take a pass at other generator commands to use this set of flags
func AddGeneratorFlags(cmd *cobra.Command, defaultGenerator string) {
cmd.Flags().String("generator", defaultGenerator, "The name of the API generator to use.")
cmd.Flags().Bool("dry-run", false, "If true, only print the object that would be sent, without sending it.")
cmd.Flags().StringP("output", "o", "", "Output format. One of: json|yaml|wide|name|go-template=...|go-template-file=...|jsonpath=...|jsonpath-file=... See golang template [http://golang.org/pkg/text/template/#pkg-overview] and jsonpath template [http://releases.k8s.io/HEAD/docs/user-guide/jsonpath.md].")
cmd.Flags().String("output-version", "", "Output the formatted object with the given version (default api-version).")
}
func ReadConfigDataFromReader(reader io.Reader, source string) ([]byte, error) {
data, err := ioutil.ReadAll(reader)
if err != nil {

View File

@ -42,6 +42,12 @@ type Generator interface {
ParamNames() []GeneratorParam
}
// StructuredGenerator is an interface for things that can generate API objects not using parameter injection
type StructuredGenerator interface {
// StructuredGenerator creates an API object using pre-configured parameters
StructuredGenerate() (runtime.Object, error)
}
func IsZero(i interface{}) bool {
if i == nil {
return true

79
pkg/kubectl/namespace.go Normal file
View File

@ -0,0 +1,79 @@
/*
Copyright 2015 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package kubectl
import (
"fmt"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/runtime"
)
// NamespaceGeneratorV1 supports stable generation of a namespace
type NamespaceGeneratorV1 struct {
// Name of namespace
Name string
}
// Ensure it supports the generator pattern that uses parameter injection
var _ Generator = &NamespaceGeneratorV1{}
// Ensure it supports the generator pattern that uses parameters specified during construction
var _ StructuredGenerator = &NamespaceGeneratorV1{}
// Generate returns a namespace using the specified parameters
func (g NamespaceGeneratorV1) Generate(genericParams map[string]interface{}) (runtime.Object, error) {
err := ValidateParams(g.ParamNames(), genericParams)
if err != nil {
return nil, err
}
params := map[string]string{}
for key, value := range genericParams {
strVal, isString := value.(string)
if !isString {
return nil, fmt.Errorf("expected string, saw %v for '%s'", value, key)
}
params[key] = strVal
}
delegate := &NamespaceGeneratorV1{Name: params["name"]}
return delegate.StructuredGenerate()
}
// ParamNames returns the set of supported input parameters when using the parameter injection generator pattern
func (g NamespaceGeneratorV1) ParamNames() []GeneratorParam {
return []GeneratorParam{
{"name", true},
}
}
// StructuredGenerate outputs a namespace object using the configured fields
func (g *NamespaceGeneratorV1) StructuredGenerate() (runtime.Object, error) {
if err := g.validate(); err != nil {
return nil, err
}
namespace := &api.Namespace{}
namespace.Name = g.Name
return namespace, nil
}
// validate validates required fields are set to support structured generation
func (g *NamespaceGeneratorV1) validate() error {
if len(g.Name) == 0 {
return fmt.Errorf("name must be specified")
}
return nil
}

View File

@ -0,0 +1,61 @@
/*
Copyright 2015 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package kubectl
import (
"reflect"
"testing"
"k8s.io/kubernetes/pkg/api"
)
func TestNamespaceGenerate(t *testing.T) {
tests := []struct {
params map[string]interface{}
expected *api.Namespace
expectErr bool
}{
{
params: map[string]interface{}{
"name": "foo",
},
expected: &api.Namespace{
ObjectMeta: api.ObjectMeta{
Name: "foo",
},
},
expectErr: false,
},
{
params: map[string]interface{}{},
expectErr: true,
},
}
generator := NamespaceGeneratorV1{}
for _, test := range tests {
obj, err := generator.Generate(test.params)
if !test.expectErr && err != nil {
t.Errorf("unexpected error: %v", err)
}
if test.expectErr && err != nil {
continue
}
if !reflect.DeepEqual(obj.(*api.Namespace), test.expected) {
t.Errorf("\nexpected:\n%#v\nsaw:\n%#v", test.expected, obj.(*api.Namespace))
}
}
}

238
pkg/kubectl/secret.go Normal file
View File

@ -0,0 +1,238 @@
/*
Copyright 2015 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package kubectl
import (
"errors"
"fmt"
"io/ioutil"
"os"
"path"
"strings"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/validation"
"k8s.io/kubernetes/pkg/runtime"
)
// SecretGeneratorV1 supports stable generation of an opaque secret
type SecretGeneratorV1 struct {
// Name of secret (required)
Name string
// Type of secret (optional)
Type string
// FileSources to derive the secret from (optional)
FileSources []string
// LiteralSources to derive the secret from (optional)
LiteralSources []string
}
// Ensure it supports the generator pattern that uses parameter injection
var _ Generator = &SecretGeneratorV1{}
// Ensure it supports the generator pattern that uses parameters specified during construction
var _ StructuredGenerator = &SecretGeneratorV1{}
// Generate returns a secret using the specified parameters
func (s SecretGeneratorV1) Generate(genericParams map[string]interface{}) (runtime.Object, error) {
err := ValidateParams(s.ParamNames(), genericParams)
if err != nil {
return nil, err
}
delegate := &SecretGeneratorV1{}
fromFileStrings, found := genericParams["from-file"]
if found {
fromFileArray, isArray := fromFileStrings.([]string)
if !isArray {
return nil, fmt.Errorf("expected []string, found :%v", fromFileStrings)
}
delegate.FileSources = fromFileArray
delete(genericParams, "from-file")
}
fromLiteralStrings, found := genericParams["from-literal"]
if found {
fromLiteralArray, isArray := fromLiteralStrings.([]string)
if !isArray {
return nil, fmt.Errorf("expected []string, found :%v", fromFileStrings)
}
delegate.LiteralSources = fromLiteralArray
delete(genericParams, "from-literal")
}
params := map[string]string{}
for key, value := range genericParams {
strVal, isString := value.(string)
if !isString {
return nil, fmt.Errorf("expected string, saw %v for '%s'", value, key)
}
params[key] = strVal
}
delegate.Name = params["name"]
delegate.Type = params["type"]
return delegate.StructuredGenerate()
}
// ParamNames returns the set of supported input parameters when using the parameter injection generator pattern
func (s SecretGeneratorV1) ParamNames() []GeneratorParam {
return []GeneratorParam{
{"name", true},
{"type", false},
{"from-file", false},
{"from-literal", false},
{"force", false},
}
}
// StructuredGenerate outputs a secret object using the configured fields
func (s SecretGeneratorV1) StructuredGenerate() (runtime.Object, error) {
if err := s.validate(); err != nil {
return nil, err
}
secret := &api.Secret{}
secret.Name = s.Name
secret.Data = map[string][]byte{}
if len(s.Type) > 0 {
secret.Type = api.SecretType(s.Type)
}
if len(s.FileSources) > 0 {
if err := handleFromFileSources(secret, s.FileSources); err != nil {
return nil, err
}
}
if len(s.LiteralSources) > 0 {
if err := handleFromLiteralSources(secret, s.LiteralSources); err != nil {
return nil, err
}
}
return secret, nil
}
// validate validates required fields are set to support structured generation
func (s SecretGeneratorV1) validate() error {
if len(s.Name) == 0 {
return fmt.Errorf("name must be specified")
}
return nil
}
// handleFromLiteralSources adds the specified literal source information into the provided secret
func handleFromLiteralSources(secret *api.Secret, literalSources []string) error {
for _, literalSource := range literalSources {
keyName, value, err := parseLiteralSource(literalSource)
if err != nil {
return err
}
err = addKeyFromLiteralToSecret(secret, keyName, []byte(value))
if err != nil {
return err
}
}
return nil
}
// handleFromFileSources adds the specified file source information into the provided secret
func handleFromFileSources(secret *api.Secret, fileSources []string) error {
for _, fileSource := range fileSources {
keyName, filePath, err := parseFileSource(fileSource)
if err != nil {
return err
}
info, err := os.Stat(filePath)
if err != nil {
switch err := err.(type) {
case *os.PathError:
return fmt.Errorf("error reading %s: %v", filePath, err.Err)
default:
return fmt.Errorf("error reading %s: %v", filePath, err)
}
}
if info.IsDir() {
if strings.Contains(fileSource, "=") {
return fmt.Errorf("cannot give a key name for a directory path.")
}
fileList, err := ioutil.ReadDir(filePath)
if err != nil {
return fmt.Errorf("error listing files in %s: %v", filePath, err)
}
for _, item := range fileList {
itemPath := path.Join(filePath, item.Name())
if item.Mode().IsRegular() {
keyName = item.Name()
err = addKeyFromFileToSecret(secret, keyName, itemPath)
if err != nil {
return err
}
}
}
} else {
err = addKeyFromFileToSecret(secret, keyName, filePath)
if err != nil {
return err
}
}
}
return nil
}
func addKeyFromFileToSecret(secret *api.Secret, keyName, filePath string) error {
data, err := ioutil.ReadFile(filePath)
if err != nil {
return err
}
return addKeyFromLiteralToSecret(secret, keyName, data)
}
func addKeyFromLiteralToSecret(secret *api.Secret, keyName string, data []byte) error {
if !validation.IsSecretKey(keyName) {
return fmt.Errorf("%v is not a valid key name for a secret", keyName)
}
if _, entryExists := secret.Data[keyName]; entryExists {
return fmt.Errorf("cannot add key %s, another key by that name already exists: %v.", keyName, secret.Data)
}
secret.Data[keyName] = data
return nil
}
// parseFileSource parses the source given. Acceptable formats include:
// source-name=source-path, where source-name will become the key name and source-path is the path to the key file
// source-path, where source-path is a path to a file or directory, and key names will default to file names
// Key names cannot include '='.
func parseFileSource(source string) (keyName, filePath string, err error) {
numSeparators := strings.Count(source, "=")
switch {
case numSeparators == 0:
return path.Base(source), source, nil
case numSeparators == 1 && strings.HasPrefix(source, "="):
return "", "", fmt.Errorf("key name for file path %v missing.", strings.TrimPrefix(source, "="))
case numSeparators == 1 && strings.HasSuffix(source, "="):
return "", "", fmt.Errorf("file path for key name %v missing.", strings.TrimSuffix(source, "="))
case numSeparators > 1:
return "", "", errors.New("Key names or file paths cannot contain '='.")
default:
components := strings.Split(source, "=")
return components[0], components[1], nil
}
}
// parseLiteralSource parses the source key=val pair
func parseLiteralSource(source string) (keyName, value string, err error) {
items := strings.Split(source, "=")
if len(items) != 2 {
return "", "", fmt.Errorf("invalid literal source %v, expected key=value", source)
}
return items[0], items[1], nil
}

View File

@ -0,0 +1,131 @@
/*
Copyright 2015 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package kubectl
import (
"encoding/json"
"fmt"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/credentialprovider"
"k8s.io/kubernetes/pkg/runtime"
)
// SecretForDockerRegistryGeneratorV1 supports stable generation of a docker registry secret
type SecretForDockerRegistryGeneratorV1 struct {
// Name of secret (required)
Name string
// Username for registry (required)
Username string
// Email for registry (required)
Email string
// Password for registry (required)
Password string
// Server for registry (required)
Server string
}
// Ensure it supports the generator pattern that uses parameter injection
var _ Generator = &SecretForDockerRegistryGeneratorV1{}
// Ensure it supports the generator pattern that uses parameters specified during construction
var _ StructuredGenerator = &SecretForDockerRegistryGeneratorV1{}
// Generate returns a secret using the specified parameters
func (s SecretForDockerRegistryGeneratorV1) Generate(genericParams map[string]interface{}) (runtime.Object, error) {
err := ValidateParams(s.ParamNames(), genericParams)
if err != nil {
return nil, err
}
params := map[string]string{}
for key, value := range genericParams {
strVal, isString := value.(string)
if !isString {
return nil, fmt.Errorf("expected string, saw %v for '%s'", value, key)
}
params[key] = strVal
}
delegate := &SecretForDockerRegistryGeneratorV1{
Name: params["name"],
Username: params["docker-username"],
Email: params["docker-email"],
Password: params["docker-password"],
Server: params["docker-server"],
}
return delegate.StructuredGenerate()
}
// StructuredGenerate outputs a secret object using the configured fields
func (s SecretForDockerRegistryGeneratorV1) StructuredGenerate() (runtime.Object, error) {
if err := s.validate(); err != nil {
return nil, err
}
dockercfgContent, err := handleDockercfgContent(s.Username, s.Password, s.Email, s.Server)
if err != nil {
return nil, err
}
secret := &api.Secret{}
secret.Name = s.Name
secret.Type = api.SecretTypeDockercfg
secret.Data = map[string][]byte{}
secret.Data[api.DockerConfigKey] = dockercfgContent
return secret, nil
}
// ParamNames returns the set of supported input parameters when using the parameter injection generator pattern
func (s SecretForDockerRegistryGeneratorV1) ParamNames() []GeneratorParam {
return []GeneratorParam{
{"name", true},
{"docker-username", true},
{"docker-email", true},
{"docker-password", true},
{"docker-server", true},
}
}
// validate validates required fields are set to support structured generation
func (s SecretForDockerRegistryGeneratorV1) validate() error {
if len(s.Name) == 0 {
return fmt.Errorf("name must be specified")
}
if len(s.Username) == 0 {
return fmt.Errorf("username must be specified")
}
if len(s.Email) == 0 {
return fmt.Errorf("email must be specified")
}
if len(s.Password) == 0 {
return fmt.Errorf("password must be specified")
}
if len(s.Server) == 0 {
return fmt.Errorf("server must be specified")
}
return nil
}
// handleDockercfgContent serializes a dockercfg json file
func handleDockercfgContent(username, password, email, server string) ([]byte, error) {
dockercfgAuth := credentialprovider.DockerConfigEntry{
Username: username,
Password: password,
Email: email,
}
dockerCfg := map[string]credentialprovider.DockerConfigEntry{server: dockercfgAuth}
return json.Marshal(dockerCfg)
}

View File

@ -0,0 +1,81 @@
/*
Copyright 2015 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package kubectl
import (
"reflect"
"testing"
"k8s.io/kubernetes/pkg/api"
)
func TestSecretForDockerRegistryGenerate(t *testing.T) {
username, password, email, server := "test-user", "test-password", "test-user@example.org", "https://index.docker.io/v1/"
secretData, err := handleDockercfgContent(username, password, email, server)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
tests := map[string]struct {
params map[string]interface{}
expected *api.Secret
expectErr bool
}{
"test-valid-use": {
params: map[string]interface{}{
"name": "foo",
"docker-server": server,
"docker-username": username,
"docker-password": password,
"docker-email": email,
},
expected: &api.Secret{
ObjectMeta: api.ObjectMeta{
Name: "foo",
},
Data: map[string][]byte{
api.DockerConfigKey: secretData,
},
Type: api.SecretTypeDockercfg,
},
expectErr: false,
},
"test-missing-required-param": {
params: map[string]interface{}{
"name": "foo",
"docker-server": server,
"docker-password": password,
"docker-email": email,
},
expectErr: true,
},
}
generator := SecretForDockerRegistryGeneratorV1{}
for _, test := range tests {
obj, err := generator.Generate(test.params)
if !test.expectErr && err != nil {
t.Errorf("unexpected error: %v", err)
}
if test.expectErr && err != nil {
continue
}
if !reflect.DeepEqual(obj.(*api.Secret), test.expected) {
t.Errorf("\nexpected:\n%#v\nsaw:\n%#v", test.expected, obj.(*api.Secret))
}
}
}

109
pkg/kubectl/secret_test.go Normal file
View File

@ -0,0 +1,109 @@
/*
Copyright 2015 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package kubectl
import (
"reflect"
"testing"
"k8s.io/kubernetes/pkg/api"
)
func TestSecretGenerate(t *testing.T) {
tests := []struct {
params map[string]interface{}
expected *api.Secret
expectErr bool
}{
{
params: map[string]interface{}{
"name": "foo",
},
expected: &api.Secret{
ObjectMeta: api.ObjectMeta{
Name: "foo",
},
Data: map[string][]byte{},
},
expectErr: false,
},
{
params: map[string]interface{}{
"name": "foo",
"type": "my-type",
},
expected: &api.Secret{
ObjectMeta: api.ObjectMeta{
Name: "foo",
},
Data: map[string][]byte{},
Type: "my-type",
},
expectErr: false,
},
{
params: map[string]interface{}{
"name": "foo",
"from-literal": []string{"key1=value1", "key2=value2"},
},
expected: &api.Secret{
ObjectMeta: api.ObjectMeta{
Name: "foo",
},
Data: map[string][]byte{
"key1": []byte("value1"),
"key2": []byte("value2"),
},
},
expectErr: false,
},
{
params: map[string]interface{}{
"name": "foo",
"from-literal": []string{"key1value1"},
},
expectErr: true,
},
{
params: map[string]interface{}{
"name": "foo",
"from-file": []string{"key1=/file=2"},
},
expectErr: true,
},
{
params: map[string]interface{}{
"name": "foo",
"from-file": []string{"key1==value"},
},
expectErr: true,
},
}
generator := SecretGeneratorV1{}
for _, test := range tests {
obj, err := generator.Generate(test.params)
if !test.expectErr && err != nil {
t.Errorf("unexpected error: %v", err)
}
if test.expectErr && err != nil {
continue
}
if !reflect.DeepEqual(obj.(*api.Secret), test.expected) {
t.Errorf("\nexpected:\n%#v\nsaw:\n%#v", test.expected, obj.(*api.Secret))
}
}
}