mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-18 08:09:58 +00:00
kubectl run to produce deployment and job
This commit is contained in:
parent
f3753c02ed
commit
c0c02c95c4
@ -14,7 +14,7 @@ kubectl run \- Run a particular image on the cluster.
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
Create and run a particular image, possibly replicated.
|
||||
Creates a replication controller to manage the created container(s).
|
||||
Creates a replication controller or job to manage the created container(s).
|
||||
|
||||
|
||||
.SH OPTIONS
|
||||
@ -40,7 +40,7 @@ Creates a replication controller to manage the created container(s).
|
||||
|
||||
.PP
|
||||
\fB\-\-generator\fP=""
|
||||
The name of the API generator to use. Default is 'run/v1' if \-\-restart=Always, otherwise the default is 'run\-pod/v1'.
|
||||
The name of the API generator to use. Default is 'run/v1' if \-\-restart=Always, otherwise the default is 'job/v1beta1'.
|
||||
|
||||
.PP
|
||||
\fB\-\-hostport\fP=\-1
|
||||
@ -94,7 +94,7 @@ Creates a replication controller to manage the created container(s).
|
||||
|
||||
.PP
|
||||
\fB\-\-restart\fP="Always"
|
||||
The restart policy for this Pod. Legal values [Always, OnFailure, Never]. If set to 'Always' a replication controller is created for this pod, if set to OnFailure or Never, only the Pod is created and \-\-replicas must be 1. Default 'Always'
|
||||
The restart policy for this Pod. Legal values [Always, OnFailure, Never]. If set to 'Always' a replication controller is created for this pod, if set to OnFailure or Never, a job is created for this pod and \-\-replicas must be 1. Default 'Always'
|
||||
|
||||
.PP
|
||||
\fB\-\-save\-config\fP=false
|
||||
@ -247,15 +247,18 @@ $ kubectl run nginx \-\-image=nginx \-\-dry\-run
|
||||
# Start a single instance of nginx, but overload the spec of the replication controller with a partial set of values parsed from JSON.
|
||||
$ kubectl run nginx \-\-image=nginx \-\-overrides='{ "apiVersion": "v1", "spec": { ... } }'
|
||||
|
||||
# Start a single instance of nginx and keep it in the foreground, don't restart it if it exits.
|
||||
$ kubectl run \-i \-\-tty nginx \-\-image=nginx \-\-restart=Never
|
||||
# Start a single instance of busybox and keep it in the foreground, don't restart it if it exits.
|
||||
$ kubectl run \-i \-\-tty busybox \-\-image=busybox \-\-restart=Never
|
||||
|
||||
# Start the nginx container using the default command, but use custom arguments (arg1 .. argN) for that command.
|
||||
$ kubectl run nginx \-\-image=nginx \-\- <arg1> <arg2> ... <argN>
|
||||
|
||||
# Start the nginx container using a different command and custom arguments
|
||||
# Start the nginx container using a different command and custom arguments.
|
||||
$ kubectl run nginx \-\-image=nginx \-\-command \-\- <cmd> <arg1> ... <argN>
|
||||
|
||||
# Start the perl container to compute π to 2000 places and print it out.
|
||||
$ kubectl run pi \-\-image=perl \-\-restart=OnFailure \-\- perl \-Mbignum=bpi \-wle 'print bpi(2000)'
|
||||
|
||||
.fi
|
||||
.RE
|
||||
|
||||
|
@ -39,7 +39,7 @@ Run a particular image on the cluster.
|
||||
|
||||
|
||||
Create and run a particular image, possibly replicated.
|
||||
Creates a replication controller to manage the created container(s).
|
||||
Creates a replication controller or job to manage the created container(s).
|
||||
|
||||
```
|
||||
kubectl run NAME --image=image [--env="key=value"] [--port=port] [--replicas=replicas] [--dry-run=bool] [--overrides=inline-json] [--command] -- [COMMAND] [args...]
|
||||
@ -66,14 +66,17 @@ $ kubectl run nginx --image=nginx --dry-run
|
||||
# Start a single instance of nginx, but overload the spec of the replication controller with a partial set of values parsed from JSON.
|
||||
$ kubectl run nginx --image=nginx --overrides='{ "apiVersion": "v1", "spec": { ... } }'
|
||||
|
||||
# Start a single instance of nginx and keep it in the foreground, don't restart it if it exits.
|
||||
$ kubectl run -i --tty nginx --image=nginx --restart=Never
|
||||
# Start a single instance of busybox and keep it in the foreground, don't restart it if it exits.
|
||||
$ kubectl run -i --tty busybox --image=busybox --restart=Never
|
||||
|
||||
# Start the nginx container using the default command, but use custom arguments (arg1 .. argN) for that command.
|
||||
$ kubectl run nginx --image=nginx -- <arg1> <arg2> ... <argN>
|
||||
|
||||
# Start the nginx container using a different command and custom arguments
|
||||
# Start the nginx container using a different command and custom arguments.
|
||||
$ kubectl run nginx --image=nginx --command -- <cmd> <arg1> ... <argN>
|
||||
|
||||
# Start the perl container to compute π to 2000 places and print it out.
|
||||
$ kubectl run pi --image=perl --restart=OnFailure -- perl -Mbignum=bpi -wle 'print bpi(2000)'
|
||||
```
|
||||
|
||||
### Options
|
||||
@ -84,7 +87,7 @@ $ kubectl run nginx --image=nginx --command -- <cmd> <arg1> ... <argN>
|
||||
--dry-run[=false]: If true, only print the object that would be sent, without sending it.
|
||||
--env=[]: Environment variables to set in the container
|
||||
--expose[=false]: If true, a public, external service is created for the container(s) which are run
|
||||
--generator="": The name of the API generator to use. Default is 'run/v1' if --restart=Always, otherwise the default is 'run-pod/v1'.
|
||||
--generator="": The name of the API generator to use. Default is 'run/v1' if --restart=Always, otherwise the default is 'job/v1beta1'.
|
||||
--hostport=-1: The host port mapping for the container port. To demonstrate a single-machine container.
|
||||
--image="": The image for the container to run.
|
||||
-l, --labels="": Labels to apply to the pod(s).
|
||||
@ -97,7 +100,7 @@ $ kubectl run nginx --image=nginx --command -- <cmd> <arg1> ... <argN>
|
||||
--port=-1: The port that this container exposes. If --expose is true, this is also the port used by the service that is created.
|
||||
-r, --replicas=1: Number of replicas to create for this container. Default is 1.
|
||||
--requests="": The resource requirement requests for this container. For example, 'cpu=100m,memory=256Mi'
|
||||
--restart="Always": The restart policy for this Pod. Legal values [Always, OnFailure, Never]. If set to 'Always' a replication controller is created for this pod, if set to OnFailure or Never, only the Pod is created and --replicas must be 1. Default 'Always'
|
||||
--restart="Always": The restart policy for this Pod. Legal values [Always, OnFailure, Never]. If set to 'Always' a replication controller is created for this pod, if set to OnFailure or Never, a job is created for this pod and --replicas must be 1. Default 'Always'
|
||||
--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.
|
||||
--service-generator="service/v2": The name of the generator to use for creating a service. Only used if --expose is true
|
||||
--service-overrides="": An inline JSON override for the generated service object. If this is non-empty, it is used to override the generated object. Requires that the object supply a valid apiVersion field. Only used if --expose is true.
|
||||
|
@ -611,7 +611,7 @@ runTests() {
|
||||
# Pre-Condition: no RC is running
|
||||
kube::test::get_object_assert rc "{{range.items}}{{$id_field}}:{{end}}" ''
|
||||
# Command: create the rc "nginx" with image nginx
|
||||
kubectl run nginx --image=nginx --save-config "${kube_flags[@]}"
|
||||
kubectl run nginx --image=nginx --save-config --generator=run/v1 "${kube_flags[@]}"
|
||||
# Post-Condition: rc "nginx" has configuration annotation
|
||||
[[ "$(kubectl get rc nginx -o yaml "${kube_flags[@]}" | grep kubectl.kubernetes.io/last-applied-configuration)" ]]
|
||||
## 5. kubectl expose --save-config should generate configuration annotation
|
||||
@ -647,6 +647,24 @@ runTests() {
|
||||
# Clean up
|
||||
kubectl delete pods test-pod "${kube_flags[@]}"
|
||||
|
||||
## kubectl run should create deployments or jobs
|
||||
# Pre-Condition: no Job is running
|
||||
kube::test::get_object_assert jobs "{{range.items}}{{$id_field}}:{{end}}" ''
|
||||
# Command
|
||||
kubectl run pi --image=perl --restart=OnFailure -- perl -Mbignum=bpi -wle 'print bpi(20)'
|
||||
# Post-Condition: Job "pi" is created
|
||||
kube::test::get_object_assert jobs "{{range.items}}{{$id_field}}:{{end}}" 'pi:'
|
||||
# Clean up
|
||||
kubectl delete jobs pi
|
||||
# Pre-Condition: no Deployment is running
|
||||
kube::test::get_object_assert deployment "{{range.items}}{{$id_field}}:{{end}}" ''
|
||||
# Command
|
||||
kubectl run nginx --image=nginx --generator=deployment/v1beta1
|
||||
# Post-Condition: Deployment "nginx" is created
|
||||
kube::test::get_object_assert deployment "{{range.items}}{{$id_field}}:{{end}}" 'nginx:'
|
||||
# Clean up
|
||||
kubectl delete deployment nginx
|
||||
|
||||
##############
|
||||
# Namespaces #
|
||||
##############
|
||||
|
@ -297,7 +297,10 @@ func ValidateDeploymentSpec(spec *extensions.DeploymentSpec) validation.ErrorLis
|
||||
allErrs = append(allErrs, apivalidation.ValidatePositiveField(int64(spec.Replicas), "replicas")...)
|
||||
allErrs = append(allErrs, apivalidation.ValidatePodTemplateSpecForRC(&spec.Template, spec.Selector, spec.Replicas, "template")...)
|
||||
allErrs = append(allErrs, ValidateDeploymentStrategy(&spec.Strategy, "strategy")...)
|
||||
allErrs = append(allErrs, apivalidation.ValidateLabelName(spec.UniqueLabelKey, "uniqueLabel")...)
|
||||
// empty string is a valid UniqueLabelKey
|
||||
if len(spec.UniqueLabelKey) > 0 {
|
||||
allErrs = append(allErrs, apivalidation.ValidateLabelName(spec.UniqueLabelKey, "uniqueLabel")...)
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
|
@ -34,7 +34,7 @@ import (
|
||||
|
||||
const (
|
||||
run_long = `Create and run a particular image, possibly replicated.
|
||||
Creates a replication controller to manage the created container(s).`
|
||||
Creates a replication controller or job to manage the created container(s).`
|
||||
run_example = `# Start a single instance of nginx.
|
||||
$ kubectl run nginx --image=nginx
|
||||
|
||||
@ -53,14 +53,17 @@ $ kubectl run nginx --image=nginx --dry-run
|
||||
# Start a single instance of nginx, but overload the spec of the replication controller with a partial set of values parsed from JSON.
|
||||
$ kubectl run nginx --image=nginx --overrides='{ "apiVersion": "v1", "spec": { ... } }'
|
||||
|
||||
# Start a single instance of nginx and keep it in the foreground, don't restart it if it exits.
|
||||
$ kubectl run -i --tty nginx --image=nginx --restart=Never
|
||||
# Start a single instance of busybox and keep it in the foreground, don't restart it if it exits.
|
||||
$ kubectl run -i --tty busybox --image=busybox --restart=Never
|
||||
|
||||
# Start the nginx container using the default command, but use custom arguments (arg1 .. argN) for that command.
|
||||
$ kubectl run nginx --image=nginx -- <arg1> <arg2> ... <argN>
|
||||
|
||||
# Start the nginx container using a different command and custom arguments
|
||||
$ kubectl run nginx --image=nginx --command -- <cmd> <arg1> ... <argN>`
|
||||
# Start the nginx container using a different command and custom arguments.
|
||||
$ kubectl run nginx --image=nginx --command -- <cmd> <arg1> ... <argN>
|
||||
|
||||
# Start the perl container to compute π to 2000 places and print it out.
|
||||
$ kubectl run pi --image=perl --restart=OnFailure -- perl -Mbignum=bpi -wle 'print bpi(2000)'`
|
||||
)
|
||||
|
||||
func NewCmdRun(f *cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer) *cobra.Command {
|
||||
@ -84,7 +87,8 @@ func NewCmdRun(f *cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer) *c
|
||||
}
|
||||
|
||||
func addRunFlags(cmd *cobra.Command) {
|
||||
cmd.Flags().String("generator", "", "The name of the API generator to use. Default is 'run/v1' if --restart=Always, otherwise the default is 'run-pod/v1'.")
|
||||
// TODO: Change the default to "deployment/v1beta1" (which is a valid generator) when deployment reaches beta (#15313)
|
||||
cmd.Flags().String("generator", "", "The name of the API generator to use. Default is 'run/v1' if --restart=Always, otherwise the default is 'job/v1beta1'.")
|
||||
cmd.Flags().String("image", "", "The image for the container to run.")
|
||||
cmd.MarkFlagRequired("image")
|
||||
cmd.Flags().IntP("replicas", "r", 1, "Number of replicas to create for this container. Default is 1.")
|
||||
@ -98,7 +102,7 @@ func addRunFlags(cmd *cobra.Command) {
|
||||
cmd.Flags().Bool("tty", false, "Allocated a TTY for each container in the pod. Because -t is currently shorthand for --template, -t is not supported for --tty. This shorthand is deprecated and we expect to adopt -t for --tty soon.")
|
||||
cmd.Flags().Bool("attach", false, "If true, wait for the Pod to start running, and then attach to the Pod as if 'kubectl attach ...' were called. Default false, unless '-i/--interactive' is set, in which case the default is true.")
|
||||
cmd.Flags().Bool("leave-stdin-open", false, "If the pod is started in interactive mode or with stdin, leave stdin open after the first attach completes. By default, stdin will be closed after the first attach completes.")
|
||||
cmd.Flags().String("restart", "Always", "The restart policy for this Pod. Legal values [Always, OnFailure, Never]. If set to 'Always' a replication controller is created for this pod, if set to OnFailure or Never, only the Pod is created and --replicas must be 1. Default 'Always'")
|
||||
cmd.Flags().String("restart", "Always", "The restart policy for this Pod. Legal values [Always, OnFailure, Never]. If set to 'Always' a replication controller is created for this pod, if set to OnFailure or Never, a job is created for this pod and --replicas must be 1. Default 'Always'")
|
||||
cmd.Flags().Bool("command", false, "If true and extra arguments are present, use them as the 'command' field in the container, rather than the 'args' field which is the default.")
|
||||
cmd.Flags().String("requests", "", "The resource requirement requests for this container. For example, 'cpu=100m,memory=256Mi'")
|
||||
cmd.Flags().String("limits", "", "The resource requirement limits for this container. For example, 'cpu=200m,memory=512Mi'")
|
||||
@ -142,10 +146,11 @@ func Run(f *cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer, cmd *cob
|
||||
|
||||
generatorName := cmdutil.GetFlagString(cmd, "generator")
|
||||
if len(generatorName) == 0 {
|
||||
// TODO: Change the default to "deployment/v1beta1" when deployment reaches beta (#15313)
|
||||
if restartPolicy == api.RestartPolicyAlways {
|
||||
generatorName = "run/v1"
|
||||
} else {
|
||||
generatorName = "run-pod/v1"
|
||||
generatorName = "job/v1beta1"
|
||||
}
|
||||
}
|
||||
generator, found := f.Generator(generatorName)
|
||||
|
@ -36,6 +36,7 @@ import (
|
||||
"k8s.io/kubernetes/pkg/api/meta"
|
||||
"k8s.io/kubernetes/pkg/api/registered"
|
||||
"k8s.io/kubernetes/pkg/api/validation"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
client "k8s.io/kubernetes/pkg/client/unversioned"
|
||||
"k8s.io/kubernetes/pkg/client/unversioned/clientcmd"
|
||||
"k8s.io/kubernetes/pkg/fields"
|
||||
@ -116,6 +117,8 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory {
|
||||
"service/v1": kubectl.ServiceGeneratorV1{},
|
||||
"service/v2": kubectl.ServiceGeneratorV2{},
|
||||
"horizontalpodautoscaler/v1beta1": kubectl.HorizontalPodAutoscalerV1Beta1{},
|
||||
"deployment/v1beta1": kubectl.DeploymentV1Beta1{},
|
||||
"job/v1beta1": kubectl.JobV1Beta1{},
|
||||
}
|
||||
|
||||
clientConfig := optionalClientConfig
|
||||
@ -312,18 +315,11 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory {
|
||||
}
|
||||
switch t := object.(type) {
|
||||
case *api.ReplicationController:
|
||||
var pods *api.PodList
|
||||
for pods == nil || len(pods.Items) == 0 {
|
||||
var err error
|
||||
if pods, err = client.Pods(t.Namespace).List(labels.SelectorFromSet(t.Spec.Selector), fields.Everything()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(pods.Items) == 0 {
|
||||
time.Sleep(2 * time.Second)
|
||||
}
|
||||
}
|
||||
pod := &pods.Items[0]
|
||||
return pod, nil
|
||||
return GetFirstPod(client, t.Namespace, t.Spec.Selector)
|
||||
case *extensions.Deployment:
|
||||
return GetFirstPod(client, t.Namespace, t.Spec.Selector)
|
||||
case *extensions.Job:
|
||||
return GetFirstPod(client, t.Namespace, t.Spec.Selector.MatchLabels)
|
||||
case *api.Pod:
|
||||
return t, nil
|
||||
default:
|
||||
@ -337,6 +333,22 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory {
|
||||
}
|
||||
}
|
||||
|
||||
// GetFirstPod returns the first pod of an object from its namespace and selector
|
||||
func GetFirstPod(client *client.Client, namespace string, selector map[string]string) (*api.Pod, error) {
|
||||
var pods *api.PodList
|
||||
for pods == nil || len(pods.Items) == 0 {
|
||||
var err error
|
||||
if pods, err = client.Pods(namespace).List(labels.SelectorFromSet(selector), fields.Everything()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(pods.Items) == 0 {
|
||||
time.Sleep(2 * time.Second)
|
||||
}
|
||||
}
|
||||
pod := &pods.Items[0]
|
||||
return pod, nil
|
||||
}
|
||||
|
||||
// BindFlags adds any flags that are common to all kubectl sub commands.
|
||||
func (f *Factory) BindFlags(flags *pflag.FlagSet) {
|
||||
// any flags defined by external projects (not part of pflags)
|
||||
|
@ -23,10 +23,264 @@ import (
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/resource"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
"k8s.io/kubernetes/pkg/util/validation"
|
||||
)
|
||||
|
||||
type DeploymentV1Beta1 struct{}
|
||||
|
||||
func (DeploymentV1Beta1) ParamNames() []GeneratorParam {
|
||||
return []GeneratorParam{
|
||||
{"labels", false},
|
||||
{"default-name", false},
|
||||
{"name", true},
|
||||
{"replicas", true},
|
||||
{"image", true},
|
||||
{"port", false},
|
||||
{"hostport", false},
|
||||
{"stdin", false},
|
||||
{"tty", false},
|
||||
{"command", false},
|
||||
{"args", false},
|
||||
{"env", false},
|
||||
{"requests", false},
|
||||
{"limits", false},
|
||||
}
|
||||
}
|
||||
|
||||
func (DeploymentV1Beta1) Generate(genericParams map[string]interface{}) (runtime.Object, error) {
|
||||
args, err := getArgs(genericParams)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
envs, err := getEnvs(genericParams)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
params, err := getParams(genericParams)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
name, err := getName(params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
labels, err := getLabels(params, true, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
count, err := strconv.Atoi(params["replicas"])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
podSpec, err := makePodSpec(params, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err = updatePodContainers(params, args, envs, podSpec); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := updatePodPorts(params, podSpec); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// TODO: use versioned types for generators so that we don't need to
|
||||
// set default values manually (see issue #17384)
|
||||
deployment := extensions.Deployment{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: name,
|
||||
Labels: labels,
|
||||
},
|
||||
Spec: extensions.DeploymentSpec{
|
||||
Replicas: count,
|
||||
Selector: labels,
|
||||
Template: api.PodTemplateSpec{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Labels: labels,
|
||||
},
|
||||
Spec: *podSpec,
|
||||
},
|
||||
UniqueLabelKey: "deployment.kubernetes.io/podTemplateHash",
|
||||
},
|
||||
}
|
||||
return &deployment, nil
|
||||
}
|
||||
|
||||
func getLabels(params map[string]string, defaultRunLabel bool, name string) (map[string]string, error) {
|
||||
labelString, found := params["labels"]
|
||||
var labels map[string]string
|
||||
var err error
|
||||
if found && len(labelString) > 0 {
|
||||
labels, err = ParseLabels(labelString)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else if defaultRunLabel {
|
||||
labels = map[string]string{
|
||||
"run": name,
|
||||
}
|
||||
}
|
||||
return labels, nil
|
||||
}
|
||||
|
||||
func getName(params map[string]string) (string, error) {
|
||||
name, found := params["name"]
|
||||
if !found || len(name) == 0 {
|
||||
name, found = params["default-name"]
|
||||
if !found || len(name) == 0 {
|
||||
return "", fmt.Errorf("'name' is a required parameter.")
|
||||
}
|
||||
}
|
||||
return name, nil
|
||||
}
|
||||
|
||||
func getParams(genericParams map[string]interface{}) (map[string]string, error) {
|
||||
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
|
||||
}
|
||||
return params, nil
|
||||
}
|
||||
|
||||
func getArgs(genericParams map[string]interface{}) ([]string, error) {
|
||||
args := []string{}
|
||||
val, found := genericParams["args"]
|
||||
if found {
|
||||
var isArray bool
|
||||
args, isArray = val.([]string)
|
||||
if !isArray {
|
||||
return nil, fmt.Errorf("expected []string, found: %v", val)
|
||||
}
|
||||
delete(genericParams, "args")
|
||||
}
|
||||
return args, nil
|
||||
}
|
||||
|
||||
func getEnvs(genericParams map[string]interface{}) ([]api.EnvVar, error) {
|
||||
var envs []api.EnvVar
|
||||
envStrings, found := genericParams["env"]
|
||||
if found {
|
||||
if envStringArray, isArray := envStrings.([]string); isArray {
|
||||
var err error
|
||||
envs, err = parseEnvs(envStringArray)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
delete(genericParams, "env")
|
||||
} else {
|
||||
return nil, fmt.Errorf("expected []string, found: %v", envStrings)
|
||||
}
|
||||
}
|
||||
return envs, nil
|
||||
}
|
||||
|
||||
type JobV1Beta1 struct{}
|
||||
|
||||
func (JobV1Beta1) ParamNames() []GeneratorParam {
|
||||
return []GeneratorParam{
|
||||
{"labels", false},
|
||||
{"default-name", false},
|
||||
{"name", true},
|
||||
{"image", true},
|
||||
{"port", false},
|
||||
{"hostport", false},
|
||||
{"stdin", false},
|
||||
{"leave-stdin-open", false},
|
||||
{"tty", false},
|
||||
{"command", false},
|
||||
{"args", false},
|
||||
{"env", false},
|
||||
{"requests", false},
|
||||
{"limits", false},
|
||||
{"restart", false},
|
||||
}
|
||||
}
|
||||
|
||||
func (JobV1Beta1) Generate(genericParams map[string]interface{}) (runtime.Object, error) {
|
||||
args, err := getArgs(genericParams)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
envs, err := getEnvs(genericParams)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
params, err := getParams(genericParams)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
name, err := getName(params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
labels, err := getLabels(params, true, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
podSpec, err := makePodSpec(params, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err = updatePodContainers(params, args, envs, podSpec); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
leaveStdinOpen, err := GetBool(params, "leave-stdin-open", false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
podSpec.Containers[0].StdinOnce = !leaveStdinOpen && podSpec.Containers[0].Stdin
|
||||
|
||||
if err := updatePodPorts(params, podSpec); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
restartPolicy := api.RestartPolicy(params["restart"])
|
||||
if len(restartPolicy) == 0 {
|
||||
restartPolicy = api.RestartPolicyAlways
|
||||
}
|
||||
podSpec.RestartPolicy = restartPolicy
|
||||
|
||||
job := extensions.Job{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: name,
|
||||
Labels: labels,
|
||||
},
|
||||
Spec: extensions.JobSpec{
|
||||
Selector: &extensions.PodSelector{
|
||||
MatchLabels: labels,
|
||||
},
|
||||
Template: api.PodTemplateSpec{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Labels: labels,
|
||||
},
|
||||
Spec: *podSpec,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return &job, nil
|
||||
}
|
||||
|
||||
type BasicReplicationController struct{}
|
||||
|
||||
func (BasicReplicationController) ParamNames() []GeneratorParam {
|
||||
@ -119,62 +373,31 @@ func makePodSpec(params map[string]string, name string) (*api.PodSpec, error) {
|
||||
}
|
||||
|
||||
func (BasicReplicationController) Generate(genericParams map[string]interface{}) (runtime.Object, error) {
|
||||
args := []string{}
|
||||
val, found := genericParams["args"]
|
||||
if found {
|
||||
var isArray bool
|
||||
args, isArray = val.([]string)
|
||||
if !isArray {
|
||||
return nil, fmt.Errorf("expected []string, found: %v", val)
|
||||
}
|
||||
delete(genericParams, "args")
|
||||
args, err := getArgs(genericParams)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// TODO: abstract this logic so that multiple generators can handle env in the same way. Same for parse envs.
|
||||
var envs []api.EnvVar
|
||||
envStrings, found := genericParams["env"]
|
||||
if found {
|
||||
if envStringArray, isArray := envStrings.([]string); isArray {
|
||||
var err error
|
||||
envs, err = parseEnvs(envStringArray)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
delete(genericParams, "env")
|
||||
} else {
|
||||
return nil, fmt.Errorf("expected []string, found: %v", envStrings)
|
||||
}
|
||||
envs, err := getEnvs(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
|
||||
params, err := getParams(genericParams)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
name, found := params["name"]
|
||||
if !found || len(name) == 0 {
|
||||
name, found = params["default-name"]
|
||||
if !found || len(name) == 0 {
|
||||
return nil, fmt.Errorf("'name' is a required parameter.")
|
||||
}
|
||||
|
||||
name, err := getName(params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// TODO: extract this flag to a central location.
|
||||
labelString, found := params["labels"]
|
||||
var labels map[string]string
|
||||
var err error
|
||||
if found && len(labelString) > 0 {
|
||||
labels, err = ParseLabels(labelString)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
labels = map[string]string{
|
||||
"run": name,
|
||||
}
|
||||
|
||||
labels, err := getLabels(params, true, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
count, err := strconv.Atoi(params["replicas"])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -184,20 +407,13 @@ func (BasicReplicationController) Generate(genericParams map[string]interface{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(args) > 0 {
|
||||
command, err := GetBool(params, "command", false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if command {
|
||||
podSpec.Containers[0].Command = args
|
||||
} else {
|
||||
podSpec.Containers[0].Args = args
|
||||
}
|
||||
|
||||
if err = updatePodContainers(params, args, envs, podSpec); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(envs) > 0 {
|
||||
podSpec.Containers[0].Env = envs
|
||||
if err := updatePodPorts(params, podSpec); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
controller := api.ReplicationController{
|
||||
@ -216,12 +432,28 @@ func (BasicReplicationController) Generate(genericParams map[string]interface{})
|
||||
},
|
||||
},
|
||||
}
|
||||
if err := updatePodPorts(params, &controller.Spec.Template.Spec); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &controller, nil
|
||||
}
|
||||
|
||||
func updatePodContainers(params map[string]string, args []string, envs []api.EnvVar, podSpec *api.PodSpec) error {
|
||||
if len(args) > 0 {
|
||||
command, err := GetBool(params, "command", false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if command {
|
||||
podSpec.Containers[0].Command = args
|
||||
} else {
|
||||
podSpec.Containers[0].Args = args
|
||||
}
|
||||
}
|
||||
|
||||
if len(envs) > 0 {
|
||||
podSpec.Containers[0].Env = envs
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func updatePodPorts(params map[string]string, podSpec *api.PodSpec) (err error) {
|
||||
port := -1
|
||||
hostPort := -1
|
||||
@ -279,57 +511,31 @@ func (BasicPod) ParamNames() []GeneratorParam {
|
||||
}
|
||||
|
||||
func (BasicPod) Generate(genericParams map[string]interface{}) (runtime.Object, error) {
|
||||
args := []string{}
|
||||
val, found := genericParams["args"]
|
||||
if found {
|
||||
var isArray bool
|
||||
args, isArray = val.([]string)
|
||||
if !isArray {
|
||||
return nil, fmt.Errorf("expected []string, found: %v", val)
|
||||
}
|
||||
delete(genericParams, "args")
|
||||
}
|
||||
// TODO: abstract this logic so that multiple generators can handle env in the same way. Same for parse envs.
|
||||
var envs []api.EnvVar
|
||||
envStrings, found := genericParams["env"]
|
||||
if found {
|
||||
if envStringArray, isArray := envStrings.([]string); isArray {
|
||||
var err error
|
||||
envs, err = parseEnvs(envStringArray)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
delete(genericParams, "env")
|
||||
} else {
|
||||
return nil, fmt.Errorf("expected []string, found: %v", envStrings)
|
||||
}
|
||||
args, err := getArgs(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
|
||||
envs, err := getEnvs(genericParams)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
name, found := params["name"]
|
||||
if !found || len(name) == 0 {
|
||||
name, found = params["default-name"]
|
||||
if !found || len(name) == 0 {
|
||||
return nil, fmt.Errorf("'name' is a required parameter.")
|
||||
}
|
||||
|
||||
params, err := getParams(genericParams)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// TODO: extract this flag to a central location.
|
||||
labelString, found := params["labels"]
|
||||
var labels map[string]string
|
||||
var err error
|
||||
if found && len(labelString) > 0 {
|
||||
labels, err = ParseLabels(labelString)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
name, err := getName(params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
labels, err := getLabels(params, false, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
stdin, err := GetBool(params, "stdin", false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -374,20 +580,8 @@ func (BasicPod) Generate(genericParams map[string]interface{}) (runtime.Object,
|
||||
RestartPolicy: restartPolicy,
|
||||
},
|
||||
}
|
||||
if len(args) > 0 {
|
||||
command, err := GetBool(params, "command", false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if command {
|
||||
pod.Spec.Containers[0].Command = args
|
||||
} else {
|
||||
pod.Spec.Containers[0].Args = args
|
||||
}
|
||||
}
|
||||
|
||||
if len(envs) > 0 {
|
||||
pod.Spec.Containers[0].Env = envs
|
||||
if err = updatePodContainers(params, args, envs, &pod.Spec); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := updatePodPorts(params, &pod.Spec); err != nil {
|
||||
|
@ -22,6 +22,7 @@ import (
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/resource"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
)
|
||||
|
||||
func TestGenerate(t *testing.T) {
|
||||
@ -625,3 +626,188 @@ func TestGeneratePod(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenerateDeployment(t *testing.T) {
|
||||
tests := []struct {
|
||||
params map[string]interface{}
|
||||
expected *extensions.Deployment
|
||||
expectErr bool
|
||||
}{
|
||||
{
|
||||
params: map[string]interface{}{
|
||||
"labels": "foo=bar,baz=blah",
|
||||
"name": "foo",
|
||||
"replicas": "3",
|
||||
"image": "someimage",
|
||||
"port": "80",
|
||||
"hostport": "80",
|
||||
"stdin": "true",
|
||||
"command": "true",
|
||||
"args": []string{"bar", "baz", "blah"},
|
||||
"env": []string{"a=b", "c=d"},
|
||||
"requests": "cpu=100m,memory=100Mi",
|
||||
"limits": "cpu=400m,memory=200Mi",
|
||||
},
|
||||
expected: &extensions.Deployment{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: "foo",
|
||||
Labels: map[string]string{"foo": "bar", "baz": "blah"},
|
||||
},
|
||||
Spec: extensions.DeploymentSpec{
|
||||
Replicas: 3,
|
||||
Selector: map[string]string{"foo": "bar", "baz": "blah"},
|
||||
UniqueLabelKey: "deployment.kubernetes.io/podTemplateHash",
|
||||
Template: api.PodTemplateSpec{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Labels: map[string]string{"foo": "bar", "baz": "blah"},
|
||||
},
|
||||
Spec: api.PodSpec{
|
||||
Containers: []api.Container{
|
||||
{
|
||||
Name: "foo",
|
||||
Image: "someimage",
|
||||
Stdin: true,
|
||||
Ports: []api.ContainerPort{
|
||||
{
|
||||
ContainerPort: 80,
|
||||
HostPort: 80,
|
||||
},
|
||||
},
|
||||
Command: []string{"bar", "baz", "blah"},
|
||||
Env: []api.EnvVar{
|
||||
{
|
||||
Name: "a",
|
||||
Value: "b",
|
||||
},
|
||||
{
|
||||
Name: "c",
|
||||
Value: "d",
|
||||
},
|
||||
},
|
||||
Resources: api.ResourceRequirements{
|
||||
Requests: api.ResourceList{
|
||||
api.ResourceCPU: resource.MustParse("100m"),
|
||||
api.ResourceMemory: resource.MustParse("100Mi"),
|
||||
},
|
||||
Limits: api.ResourceList{
|
||||
api.ResourceCPU: resource.MustParse("400m"),
|
||||
api.ResourceMemory: resource.MustParse("200Mi"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
generator := DeploymentV1Beta1{}
|
||||
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.(*extensions.Deployment), test.expected) {
|
||||
t.Errorf("\nexpected:\n%#v\nsaw:\n%#v", test.expected, obj.(*extensions.Deployment))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenerateJob(t *testing.T) {
|
||||
tests := []struct {
|
||||
params map[string]interface{}
|
||||
expected *extensions.Job
|
||||
expectErr bool
|
||||
}{
|
||||
{
|
||||
params: map[string]interface{}{
|
||||
"labels": "foo=bar,baz=blah",
|
||||
"name": "foo",
|
||||
"image": "someimage",
|
||||
"port": "80",
|
||||
"hostport": "80",
|
||||
"stdin": "true",
|
||||
"leave-stdin-open": "true",
|
||||
"command": "true",
|
||||
"args": []string{"bar", "baz", "blah"},
|
||||
"env": []string{"a=b", "c=d"},
|
||||
"requests": "cpu=100m,memory=100Mi",
|
||||
"limits": "cpu=400m,memory=200Mi",
|
||||
"restart": "OnFailure",
|
||||
},
|
||||
expected: &extensions.Job{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: "foo",
|
||||
Labels: map[string]string{"foo": "bar", "baz": "blah"},
|
||||
},
|
||||
Spec: extensions.JobSpec{
|
||||
Selector: &extensions.PodSelector{
|
||||
MatchLabels: map[string]string{"foo": "bar", "baz": "blah"},
|
||||
},
|
||||
Template: api.PodTemplateSpec{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Labels: map[string]string{"foo": "bar", "baz": "blah"},
|
||||
},
|
||||
Spec: api.PodSpec{
|
||||
RestartPolicy: api.RestartPolicyOnFailure,
|
||||
Containers: []api.Container{
|
||||
{
|
||||
Name: "foo",
|
||||
Image: "someimage",
|
||||
Stdin: true,
|
||||
StdinOnce: false,
|
||||
Ports: []api.ContainerPort{
|
||||
{
|
||||
ContainerPort: 80,
|
||||
HostPort: 80,
|
||||
},
|
||||
},
|
||||
Command: []string{"bar", "baz", "blah"},
|
||||
Env: []api.EnvVar{
|
||||
{
|
||||
Name: "a",
|
||||
Value: "b",
|
||||
},
|
||||
{
|
||||
Name: "c",
|
||||
Value: "d",
|
||||
},
|
||||
},
|
||||
Resources: api.ResourceRequirements{
|
||||
Requests: api.ResourceList{
|
||||
api.ResourceCPU: resource.MustParse("100m"),
|
||||
api.ResourceMemory: resource.MustParse("100Mi"),
|
||||
},
|
||||
Limits: api.ResourceList{
|
||||
api.ResourceCPU: resource.MustParse("400m"),
|
||||
api.ResourceMemory: resource.MustParse("200Mi"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
generator := JobV1Beta1{}
|
||||
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.(*extensions.Job), test.expected) {
|
||||
t.Errorf("\nexpected:\n%#v\nsaw:\n%#v", test.expected, obj.(*extensions.Job))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -44,6 +44,7 @@ import (
|
||||
client "k8s.io/kubernetes/pkg/client/unversioned"
|
||||
"k8s.io/kubernetes/pkg/fields"
|
||||
"k8s.io/kubernetes/pkg/kubectl"
|
||||
"k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||
"k8s.io/kubernetes/pkg/labels"
|
||||
"k8s.io/kubernetes/pkg/util/wait"
|
||||
|
||||
@ -367,7 +368,7 @@ var _ = Describe("Kubectl client", func() {
|
||||
execOrDie()
|
||||
Expect(runOutput).To(ContainSubstring("abcd1234"))
|
||||
Expect(runOutput).To(ContainSubstring("stdin closed"))
|
||||
Expect(c.Pods(ns).Delete("run-test", api.NewDeleteOptions(0))).To(BeNil())
|
||||
Expect(c.Extensions().Jobs(ns).Delete("run-test", api.NewDeleteOptions(0))).To(BeNil())
|
||||
|
||||
By("executing a command with run and attach without stdin")
|
||||
runOutput = newKubectlCommand(fmt.Sprintf("--namespace=%v", ns), "run", "run-test-2", "--image=busybox", "--restart=Never", "--attach=true", "--leave-stdin-open=true", "--", "sh", "-c", "cat && echo 'stdin closed'").
|
||||
@ -375,24 +376,28 @@ var _ = Describe("Kubectl client", func() {
|
||||
execOrDie()
|
||||
Expect(runOutput).ToNot(ContainSubstring("abcd1234"))
|
||||
Expect(runOutput).To(ContainSubstring("stdin closed"))
|
||||
Expect(c.Pods(ns).Delete("run-test-2", api.NewDeleteOptions(0))).To(BeNil())
|
||||
Expect(c.Extensions().Jobs(ns).Delete("run-test-2", api.NewDeleteOptions(0))).To(BeNil())
|
||||
|
||||
By("executing a command with run and attach with stdin with open stdin should remain running")
|
||||
runOutput = newKubectlCommand(nsFlag, "run", "run-test-3", "--image=busybox", "--restart=Never", "--attach=true", "--leave-stdin-open=true", "--stdin", "--", "sh", "-c", "cat && echo 'stdin closed'").
|
||||
withStdinData("abcd1234\n").
|
||||
execOrDie()
|
||||
Expect(runOutput).ToNot(ContainSubstring("stdin closed"))
|
||||
if !checkPodsRunningReady(c, ns, []string{"run-test-3"}, time.Minute) {
|
||||
Failf("Pod %q should still be running", "run-test-3")
|
||||
runTestPod, err := util.GetFirstPod(c, ns, map[string]string{"run": "run-test-3"})
|
||||
if err != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
if !checkPodsRunningReady(c, ns, []string{runTestPod.Name}, time.Minute) {
|
||||
Failf("Pod %q of Job %q should still be running", runTestPod.Name, "run-test-3")
|
||||
}
|
||||
|
||||
// NOTE: we cannot guarantee our output showed up in the container logs before stdin was closed, so we have
|
||||
// to loop test.
|
||||
err := wait.PollImmediate(time.Second, time.Minute, func() (bool, error) {
|
||||
if !checkPodsRunningReady(c, ns, []string{"run-test-3"}, 1*time.Second) {
|
||||
Failf("Pod %q should still be running", "run-test-3")
|
||||
err = wait.PollImmediate(time.Second, time.Minute, func() (bool, error) {
|
||||
if !checkPodsRunningReady(c, ns, []string{runTestPod.Name}, 1*time.Second) {
|
||||
Failf("Pod %q of Job %q should still be running", runTestPod.Name, "run-test-3")
|
||||
}
|
||||
logOutput := runKubectlOrDie(nsFlag, "logs", "run-test-3")
|
||||
logOutput := runKubectlOrDie(nsFlag, "logs", runTestPod.Name)
|
||||
Expect(logOutput).ToNot(ContainSubstring("stdin closed"))
|
||||
return strings.Contains(logOutput, "abcd1234"), nil
|
||||
})
|
||||
@ -401,7 +406,7 @@ var _ = Describe("Kubectl client", func() {
|
||||
}
|
||||
Expect(err).To(BeNil())
|
||||
|
||||
Expect(c.Pods(ns).Delete("run-test-3", api.NewDeleteOptions(0))).To(BeNil())
|
||||
Expect(c.Extensions().Jobs(ns).Delete("run-test-3", api.NewDeleteOptions(0))).To(BeNil())
|
||||
})
|
||||
|
||||
It("should support port-forward", func() {
|
||||
@ -804,54 +809,54 @@ var _ = Describe("Kubectl client", func() {
|
||||
|
||||
})
|
||||
|
||||
Describe("Kubectl run pod", func() {
|
||||
Describe("Kubectl run job", func() {
|
||||
var nsFlag string
|
||||
var podName string
|
||||
var jobName string
|
||||
|
||||
BeforeEach(func() {
|
||||
nsFlag = fmt.Sprintf("--namespace=%v", ns)
|
||||
podName = "e2e-test-nginx-pod"
|
||||
jobName = "e2e-test-nginx-job"
|
||||
})
|
||||
|
||||
AfterEach(func() {
|
||||
runKubectlOrDie("stop", "pods", podName, nsFlag)
|
||||
runKubectlOrDie("stop", "jobs", jobName, nsFlag)
|
||||
})
|
||||
|
||||
It("should create a pod from an image when restart is OnFailure [Conformance]", func() {
|
||||
It("should create a job from an image when restart is OnFailure [Conformance]", func() {
|
||||
image := "nginx"
|
||||
|
||||
By("running the image " + image)
|
||||
runKubectlOrDie("run", podName, "--restart=OnFailure", "--image="+image, nsFlag)
|
||||
By("verifying the pod " + podName + " was created")
|
||||
pod, err := c.Pods(ns).Get(podName)
|
||||
runKubectlOrDie("run", jobName, "--restart=OnFailure", "--image="+image, nsFlag)
|
||||
By("verifying the job " + jobName + " was created")
|
||||
job, err := c.Extensions().Jobs(ns).Get(jobName)
|
||||
if err != nil {
|
||||
Failf("Failed getting pod %s: %v", podName, err)
|
||||
Failf("Failed getting job %s: %v", jobName, err)
|
||||
}
|
||||
containers := pod.Spec.Containers
|
||||
containers := job.Spec.Template.Spec.Containers
|
||||
if containers == nil || len(containers) != 1 || containers[0].Image != image {
|
||||
Failf("Failed creating pod %s for 1 pod with expected image %s", podName, image)
|
||||
Failf("Failed creating job %s for 1 pod with expected image %s", jobName, image)
|
||||
}
|
||||
if pod.Spec.RestartPolicy != api.RestartPolicyOnFailure {
|
||||
Failf("Failed creating a pod with correct restart policy for --restart=OnFailure")
|
||||
if job.Spec.Template.Spec.RestartPolicy != api.RestartPolicyOnFailure {
|
||||
Failf("Failed creating a job with correct restart policy for --restart=OnFailure")
|
||||
}
|
||||
})
|
||||
|
||||
It("should create a pod from an image when restart is Never [Conformance]", func() {
|
||||
It("should create a job from an image when restart is Never [Conformance]", func() {
|
||||
image := "nginx"
|
||||
|
||||
By("running the image " + image)
|
||||
runKubectlOrDie("run", podName, "--restart=Never", "--image="+image, nsFlag)
|
||||
By("verifying the pod " + podName + " was created")
|
||||
pod, err := c.Pods(ns).Get(podName)
|
||||
runKubectlOrDie("run", jobName, "--restart=Never", "--image="+image, nsFlag)
|
||||
By("verifying the job " + jobName + " was created")
|
||||
job, err := c.Extensions().Jobs(ns).Get(jobName)
|
||||
if err != nil {
|
||||
Failf("Failed getting pod %s: %v", podName, err)
|
||||
Failf("Failed getting job %s: %v", jobName, err)
|
||||
}
|
||||
containers := pod.Spec.Containers
|
||||
containers := job.Spec.Template.Spec.Containers
|
||||
if containers == nil || len(containers) != 1 || containers[0].Image != image {
|
||||
Failf("Failed creating pod %s for 1 pod with expected image %s", podName, image)
|
||||
Failf("Failed creating job %s for 1 pod with expected image %s", jobName, image)
|
||||
}
|
||||
if pod.Spec.RestartPolicy != api.RestartPolicyNever {
|
||||
Failf("Failed creating a pod with correct restart policy for --restart=OnFailure")
|
||||
if job.Spec.Template.Spec.RestartPolicy != api.RestartPolicyNever {
|
||||
Failf("Failed creating a job with correct restart policy for --restart=OnFailure")
|
||||
}
|
||||
})
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user