Merge pull request #13254 from soltysh/job_controller_kubectl
Job resource - kubectl part
This commit is contained in:
		| @@ -291,6 +291,7 @@ _kubectl_get() | ||||
|     must_have_one_noun+=("endpoints") | ||||
|     must_have_one_noun+=("event") | ||||
|     must_have_one_noun+=("horizontalpodautoscaler") | ||||
|     must_have_one_noun+=("job") | ||||
|     must_have_one_noun+=("limitrange") | ||||
|     must_have_one_noun+=("namespace") | ||||
|     must_have_one_noun+=("node") | ||||
| @@ -459,6 +460,7 @@ _kubectl_delete() | ||||
|     must_have_one_noun+=("endpoints") | ||||
|     must_have_one_noun+=("event") | ||||
|     must_have_one_noun+=("horizontalpodautoscaler") | ||||
|     must_have_one_noun+=("job") | ||||
|     must_have_one_noun+=("limitrange") | ||||
|     must_have_one_noun+=("namespace") | ||||
|     must_have_one_noun+=("node") | ||||
| @@ -829,6 +831,7 @@ _kubectl_label() | ||||
|     must_have_one_noun+=("endpoints") | ||||
|     must_have_one_noun+=("event") | ||||
|     must_have_one_noun+=("horizontalpodautoscaler") | ||||
|     must_have_one_noun+=("job") | ||||
|     must_have_one_noun+=("limitrange") | ||||
|     must_have_one_noun+=("namespace") | ||||
|     must_have_one_noun+=("node") | ||||
|   | ||||
| @@ -36,6 +36,7 @@ type ExperimentalInterface interface { | ||||
| 	ScaleNamespacer | ||||
| 	DaemonSetsNamespacer | ||||
| 	DeploymentsNamespacer | ||||
| 	JobsNamespacer | ||||
| } | ||||
|  | ||||
| // ExperimentalClient is used to interact with experimental Kubernetes features. | ||||
| @@ -90,6 +91,10 @@ func (c *ExperimentalClient) Deployments(namespace string) DeploymentInterface { | ||||
| 	return newDeployments(c, namespace) | ||||
| } | ||||
|  | ||||
| func (c *ExperimentalClient) Jobs(namespace string) JobInterface { | ||||
| 	return newJobs(c, namespace) | ||||
| } | ||||
|  | ||||
| // NewExperimental creates a new ExperimentalClient for the given config. This client | ||||
| // provides access to experimental Kubernetes features. | ||||
| // Experimental features are not supported and may be changed or removed in | ||||
|   | ||||
							
								
								
									
										112
									
								
								pkg/client/unversioned/jobs.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								pkg/client/unversioned/jobs.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,112 @@ | ||||
| /* | ||||
| 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 unversioned | ||||
|  | ||||
| import ( | ||||
| 	"k8s.io/kubernetes/pkg/api" | ||||
| 	"k8s.io/kubernetes/pkg/apis/experimental" | ||||
| 	"k8s.io/kubernetes/pkg/fields" | ||||
| 	"k8s.io/kubernetes/pkg/labels" | ||||
| 	"k8s.io/kubernetes/pkg/watch" | ||||
| ) | ||||
|  | ||||
| // JobsNamespacer has methods to work with Job resources in a namespace | ||||
| type JobsNamespacer interface { | ||||
| 	Jobs(namespace string) JobInterface | ||||
| } | ||||
|  | ||||
| // JobInterface exposes methods to work on Job resources. | ||||
| type JobInterface interface { | ||||
| 	List(label labels.Selector, field fields.Selector) (*experimental.JobList, error) | ||||
| 	Get(name string) (*experimental.Job, error) | ||||
| 	Create(job *experimental.Job) (*experimental.Job, error) | ||||
| 	Update(job *experimental.Job) (*experimental.Job, error) | ||||
| 	Delete(name string, options *api.DeleteOptions) error | ||||
| 	Watch(label labels.Selector, field fields.Selector, resourceVersion string) (watch.Interface, error) | ||||
| 	UpdateStatus(job *experimental.Job) (*experimental.Job, error) | ||||
| } | ||||
|  | ||||
| // jobs implements JobsNamespacer interface | ||||
| type jobs struct { | ||||
| 	r  *ExperimentalClient | ||||
| 	ns string | ||||
| } | ||||
|  | ||||
| // newJobs returns a jobs | ||||
| func newJobs(c *ExperimentalClient, namespace string) *jobs { | ||||
| 	return &jobs{c, namespace} | ||||
| } | ||||
|  | ||||
| // List returns a list of jobs that match the label and field selectors. | ||||
| func (c *jobs) List(label labels.Selector, field fields.Selector) (result *experimental.JobList, err error) { | ||||
| 	result = &experimental.JobList{} | ||||
| 	err = c.r.Get().Namespace(c.ns).Resource("jobs").LabelsSelectorParam(label).FieldsSelectorParam(field).Do().Into(result) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // Get returns information about a particular job. | ||||
| func (c *jobs) Get(name string) (result *experimental.Job, err error) { | ||||
| 	result = &experimental.Job{} | ||||
| 	err = c.r.Get().Namespace(c.ns).Resource("jobs").Name(name).Do().Into(result) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // Create creates a new job. | ||||
| func (c *jobs) Create(job *experimental.Job) (result *experimental.Job, err error) { | ||||
| 	result = &experimental.Job{} | ||||
| 	err = c.r.Post().Namespace(c.ns).Resource("jobs").Body(job).Do().Into(result) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // Update updates an existing job. | ||||
| func (c *jobs) Update(job *experimental.Job) (result *experimental.Job, err error) { | ||||
| 	result = &experimental.Job{} | ||||
| 	err = c.r.Put().Namespace(c.ns).Resource("jobs").Name(job.Name).Body(job).Do().Into(result) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // Delete deletes a job, returns error if one occurs. | ||||
| func (c *jobs) Delete(name string, options *api.DeleteOptions) (err error) { | ||||
| 	if options == nil { | ||||
| 		return c.r.Delete().Namespace(c.ns).Resource("jobs").Name(name).Do().Error() | ||||
| 	} | ||||
|  | ||||
| 	body, err := api.Scheme.EncodeToVersion(options, c.r.APIVersion()) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return c.r.Delete().Namespace(c.ns).Resource("jobs").Name(name).Body(body).Do().Error() | ||||
| } | ||||
|  | ||||
| // Watch returns a watch.Interface that watches the requested jobs. | ||||
| func (c *jobs) Watch(label labels.Selector, field fields.Selector, resourceVersion string) (watch.Interface, error) { | ||||
| 	return c.r.Get(). | ||||
| 		Prefix("watch"). | ||||
| 		Namespace(c.ns). | ||||
| 		Resource("jobs"). | ||||
| 		Param("resourceVersion", resourceVersion). | ||||
| 		LabelsSelectorParam(label). | ||||
| 		FieldsSelectorParam(field). | ||||
| 		Watch() | ||||
| } | ||||
|  | ||||
| // UpdateStatus takes the name of the job and the new status.  Returns the server's representation of the job, and an error, if it occurs. | ||||
| func (c *jobs) UpdateStatus(job *experimental.Job) (result *experimental.Job, err error) { | ||||
| 	result = &experimental.Job{} | ||||
| 	err = c.r.Put().Namespace(c.ns).Resource("jobs").Name(job.Name).SubResource("status").Body(job).Do().Into(result) | ||||
| 	return | ||||
| } | ||||
							
								
								
									
										222
									
								
								pkg/client/unversioned/jobs_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										222
									
								
								pkg/client/unversioned/jobs_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,222 @@ | ||||
| /* | ||||
| 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 unversioned | ||||
|  | ||||
| import ( | ||||
| 	"testing" | ||||
|  | ||||
| 	"k8s.io/kubernetes/pkg/api" | ||||
| 	"k8s.io/kubernetes/pkg/api/testapi" | ||||
| 	"k8s.io/kubernetes/pkg/apis/experimental" | ||||
| 	"k8s.io/kubernetes/pkg/fields" | ||||
| 	"k8s.io/kubernetes/pkg/labels" | ||||
| ) | ||||
|  | ||||
| func getJobResourceName() string { | ||||
| 	return "jobs" | ||||
| } | ||||
|  | ||||
| func TestListJobs(t *testing.T) { | ||||
| 	ns := api.NamespaceAll | ||||
| 	c := &testClient{ | ||||
| 		Request: testRequest{ | ||||
| 			Method: "GET", | ||||
| 			Path:   testapi.Experimental.ResourcePath(getJobResourceName(), ns, ""), | ||||
| 		}, | ||||
| 		Response: Response{StatusCode: 200, | ||||
| 			Body: &experimental.JobList{ | ||||
| 				Items: []experimental.Job{ | ||||
| 					{ | ||||
| 						ObjectMeta: api.ObjectMeta{ | ||||
| 							Name: "foo", | ||||
| 							Labels: map[string]string{ | ||||
| 								"foo":  "bar", | ||||
| 								"name": "baz", | ||||
| 							}, | ||||
| 						}, | ||||
| 						Spec: experimental.JobSpec{ | ||||
| 							Template: &api.PodTemplateSpec{}, | ||||
| 						}, | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 	} | ||||
| 	receivedJobList, err := c.Setup(t).Experimental().Jobs(ns).List(labels.Everything(), fields.Everything()) | ||||
| 	c.Validate(t, receivedJobList, err) | ||||
| } | ||||
|  | ||||
| func TestGetJob(t *testing.T) { | ||||
| 	ns := api.NamespaceDefault | ||||
| 	c := &testClient{ | ||||
| 		Request: testRequest{ | ||||
| 			Method: "GET", | ||||
| 			Path:   testapi.Experimental.ResourcePath(getJobResourceName(), ns, "foo"), | ||||
| 			Query:  buildQueryValues(nil), | ||||
| 		}, | ||||
| 		Response: Response{ | ||||
| 			StatusCode: 200, | ||||
| 			Body: &experimental.Job{ | ||||
| 				ObjectMeta: api.ObjectMeta{ | ||||
| 					Name: "foo", | ||||
| 					Labels: map[string]string{ | ||||
| 						"foo":  "bar", | ||||
| 						"name": "baz", | ||||
| 					}, | ||||
| 				}, | ||||
| 				Spec: experimental.JobSpec{ | ||||
| 					Template: &api.PodTemplateSpec{}, | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 	} | ||||
| 	receivedJob, err := c.Setup(t).Experimental().Jobs(ns).Get("foo") | ||||
| 	c.Validate(t, receivedJob, err) | ||||
| } | ||||
|  | ||||
| func TestGetJobWithNoName(t *testing.T) { | ||||
| 	ns := api.NamespaceDefault | ||||
| 	c := &testClient{Error: true} | ||||
| 	receivedJob, err := c.Setup(t).Experimental().Jobs(ns).Get("") | ||||
| 	if (err != nil) && (err.Error() != nameRequiredError) { | ||||
| 		t.Errorf("Expected error: %v, but got %v", nameRequiredError, err) | ||||
| 	} | ||||
|  | ||||
| 	c.Validate(t, receivedJob, err) | ||||
| } | ||||
|  | ||||
| func TestUpdateJob(t *testing.T) { | ||||
| 	ns := api.NamespaceDefault | ||||
| 	requestJob := &experimental.Job{ | ||||
| 		ObjectMeta: api.ObjectMeta{ | ||||
| 			Name:            "foo", | ||||
| 			Namespace:       ns, | ||||
| 			ResourceVersion: "1", | ||||
| 		}, | ||||
| 	} | ||||
| 	c := &testClient{ | ||||
| 		Request: testRequest{ | ||||
| 			Method: "PUT", | ||||
| 			Path:   testapi.Experimental.ResourcePath(getJobResourceName(), ns, "foo"), | ||||
| 			Query:  buildQueryValues(nil), | ||||
| 		}, | ||||
| 		Response: Response{ | ||||
| 			StatusCode: 200, | ||||
| 			Body: &experimental.Job{ | ||||
| 				ObjectMeta: api.ObjectMeta{ | ||||
| 					Name: "foo", | ||||
| 					Labels: map[string]string{ | ||||
| 						"foo":  "bar", | ||||
| 						"name": "baz", | ||||
| 					}, | ||||
| 				}, | ||||
| 				Spec: experimental.JobSpec{ | ||||
| 					Template: &api.PodTemplateSpec{}, | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 	} | ||||
| 	receivedJob, err := c.Setup(t).Experimental().Jobs(ns).Update(requestJob) | ||||
| 	c.Validate(t, receivedJob, err) | ||||
| } | ||||
|  | ||||
| func TestUpdateJobStatus(t *testing.T) { | ||||
| 	ns := api.NamespaceDefault | ||||
| 	requestJob := &experimental.Job{ | ||||
| 		ObjectMeta: api.ObjectMeta{ | ||||
| 			Name:            "foo", | ||||
| 			Namespace:       ns, | ||||
| 			ResourceVersion: "1", | ||||
| 		}, | ||||
| 	} | ||||
| 	c := &testClient{ | ||||
| 		Request: testRequest{ | ||||
| 			Method: "PUT", | ||||
| 			Path:   testapi.Experimental.ResourcePath(getJobResourceName(), ns, "foo") + "/status", | ||||
| 			Query:  buildQueryValues(nil), | ||||
| 		}, | ||||
| 		Response: Response{ | ||||
| 			StatusCode: 200, | ||||
| 			Body: &experimental.Job{ | ||||
| 				ObjectMeta: api.ObjectMeta{ | ||||
| 					Name: "foo", | ||||
| 					Labels: map[string]string{ | ||||
| 						"foo":  "bar", | ||||
| 						"name": "baz", | ||||
| 					}, | ||||
| 				}, | ||||
| 				Spec: experimental.JobSpec{ | ||||
| 					Template: &api.PodTemplateSpec{}, | ||||
| 				}, | ||||
| 				Status: experimental.JobStatus{ | ||||
| 					Active: 1, | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 	} | ||||
| 	receivedJob, err := c.Setup(t).Experimental().Jobs(ns).UpdateStatus(requestJob) | ||||
| 	c.Validate(t, receivedJob, err) | ||||
| } | ||||
|  | ||||
| func TestDeleteJob(t *testing.T) { | ||||
| 	ns := api.NamespaceDefault | ||||
| 	c := &testClient{ | ||||
| 		Request: testRequest{ | ||||
| 			Method: "DELETE", | ||||
| 			Path:   testapi.Experimental.ResourcePath(getJobResourceName(), ns, "foo"), | ||||
| 			Query:  buildQueryValues(nil), | ||||
| 		}, | ||||
| 		Response: Response{StatusCode: 200}, | ||||
| 	} | ||||
| 	err := c.Setup(t).Experimental().Jobs(ns).Delete("foo", nil) | ||||
| 	c.Validate(t, nil, err) | ||||
| } | ||||
|  | ||||
| func TestCreateJob(t *testing.T) { | ||||
| 	ns := api.NamespaceDefault | ||||
| 	requestJob := &experimental.Job{ | ||||
| 		ObjectMeta: api.ObjectMeta{ | ||||
| 			Name:      "foo", | ||||
| 			Namespace: ns, | ||||
| 		}, | ||||
| 	} | ||||
| 	c := &testClient{ | ||||
| 		Request: testRequest{ | ||||
| 			Method: "POST", | ||||
| 			Path:   testapi.Experimental.ResourcePath(getJobResourceName(), ns, ""), | ||||
| 			Body:   requestJob, | ||||
| 			Query:  buildQueryValues(nil), | ||||
| 		}, | ||||
| 		Response: Response{ | ||||
| 			StatusCode: 200, | ||||
| 			Body: &experimental.Job{ | ||||
| 				ObjectMeta: api.ObjectMeta{ | ||||
| 					Name: "foo", | ||||
| 					Labels: map[string]string{ | ||||
| 						"foo":  "bar", | ||||
| 						"name": "baz", | ||||
| 					}, | ||||
| 				}, | ||||
| 				Spec: experimental.JobSpec{ | ||||
| 					Template: &api.PodTemplateSpec{}, | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 	} | ||||
| 	receivedJob, err := c.Setup(t).Experimental().Jobs(ns).Create(requestJob) | ||||
| 	c.Validate(t, receivedJob, err) | ||||
| } | ||||
| @@ -261,3 +261,7 @@ func (c *FakeExperimental) Deployments(namespace string) client.DeploymentInterf | ||||
| func (c *FakeExperimental) Scales(namespace string) client.ScaleInterface { | ||||
| 	return &FakeScales{Fake: c, Namespace: namespace} | ||||
| } | ||||
|  | ||||
| func (c *FakeExperimental) Jobs(namespace string) client.JobInterface { | ||||
| 	panic("unimplemented") | ||||
| } | ||||
|   | ||||
| @@ -28,6 +28,7 @@ import ( | ||||
| 	"github.com/golang/glog" | ||||
| 	"k8s.io/kubernetes/pkg/api" | ||||
| 	"k8s.io/kubernetes/pkg/api/resource" | ||||
| 	"k8s.io/kubernetes/pkg/apis/experimental" | ||||
| 	client "k8s.io/kubernetes/pkg/client/unversioned" | ||||
| 	"k8s.io/kubernetes/pkg/fieldpath" | ||||
| 	"k8s.io/kubernetes/pkg/fields" | ||||
| @@ -85,6 +86,7 @@ func describerMap(c *client.Client) map[string]Describer { | ||||
| func expDescriberMap(c *client.Client) map[string]Describer { | ||||
| 	return map[string]Describer{ | ||||
| 		"HorizontalPodAutoscaler": &HorizontalPodAutoscalerDescriber{c}, | ||||
| 		"Job": &JobDescriber{c}, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -854,6 +856,46 @@ func describeReplicationController(controller *api.ReplicationController, events | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| // JobDescriber generates information about a job and the pods it has created. | ||||
| type JobDescriber struct { | ||||
| 	client *client.Client | ||||
| } | ||||
|  | ||||
| func (d *JobDescriber) Describe(namespace, name string) (string, error) { | ||||
| 	job, err := d.client.Experimental().Jobs(namespace).Get(name) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
|  | ||||
| 	events, _ := d.client.Events(namespace).Search(job) | ||||
|  | ||||
| 	return describeJob(job, events) | ||||
| } | ||||
|  | ||||
| func describeJob(job *experimental.Job, events *api.EventList) (string, error) { | ||||
| 	return tabbedString(func(out io.Writer) error { | ||||
| 		fmt.Fprintf(out, "Name:\t%s\n", job.Name) | ||||
| 		fmt.Fprintf(out, "Namespace:\t%s\n", job.Namespace) | ||||
| 		if job.Spec.Template != nil { | ||||
| 			fmt.Fprintf(out, "Image(s):\t%s\n", makeImageList(&job.Spec.Template.Spec)) | ||||
| 		} else { | ||||
| 			fmt.Fprintf(out, "Image(s):\t%s\n", "<no template>") | ||||
| 		} | ||||
| 		fmt.Fprintf(out, "Selector:\t%s\n", labels.FormatLabels(job.Spec.Selector)) | ||||
| 		fmt.Fprintf(out, "Parallelism:\t%d\n", job.Spec.Parallelism) | ||||
| 		fmt.Fprintf(out, "Completions:\t%d\n", job.Spec.Completions) | ||||
| 		fmt.Fprintf(out, "Labels:\t%s\n", labels.FormatLabels(job.Labels)) | ||||
| 		fmt.Fprintf(out, "Pods Statuses:\t%d Running / %d Succeeded / %d Failed\n", job.Status.Active, job.Status.Successful, job.Status.Unsuccessful) | ||||
| 		if job.Spec.Template != nil { | ||||
| 			describeVolumes(job.Spec.Template.Spec.Volumes, out) | ||||
| 		} | ||||
| 		if events != nil { | ||||
| 			DescribeEvents(events, out) | ||||
| 		} | ||||
| 		return nil | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| // SecretDescriber generates information about a secret | ||||
| type SecretDescriber struct { | ||||
| 	client.Interface | ||||
|   | ||||
| @@ -380,6 +380,7 @@ func (h *HumanReadablePrinter) HandledResources() []string { | ||||
| var podColumns = []string{"NAME", "READY", "STATUS", "RESTARTS", "AGE"} | ||||
| var podTemplateColumns = []string{"TEMPLATE", "CONTAINER(S)", "IMAGE(S)", "PODLABELS"} | ||||
| var replicationControllerColumns = []string{"CONTROLLER", "CONTAINER(S)", "IMAGE(S)", "SELECTOR", "REPLICAS", "AGE"} | ||||
| var jobColumns = []string{"JOB", "CONTAINER(S)", "IMAGE(S)", "SELECTOR", "SUCCESSFUL"} | ||||
| var serviceColumns = []string{"NAME", "CLUSTER_IP", "EXTERNAL_IP", "PORT(S)", "SELECTOR", "AGE"} | ||||
| var endpointColumns = []string{"NAME", "ENDPOINTS", "AGE"} | ||||
| var nodeColumns = []string{"NAME", "LABELS", "STATUS", "AGE"} | ||||
| @@ -405,6 +406,8 @@ func (h *HumanReadablePrinter) addDefaultHandlers() { | ||||
| 	h.Handler(podTemplateColumns, printPodTemplateList) | ||||
| 	h.Handler(replicationControllerColumns, printReplicationController) | ||||
| 	h.Handler(replicationControllerColumns, printReplicationControllerList) | ||||
| 	h.Handler(jobColumns, printJob) | ||||
| 	h.Handler(jobColumns, printJobList) | ||||
| 	h.Handler(serviceColumns, printService) | ||||
| 	h.Handler(serviceColumns, printServiceList) | ||||
| 	h.Handler(endpointColumns, printEndpoints) | ||||
| @@ -655,7 +658,6 @@ func printPodTemplateList(podList *api.PodTemplateList, w io.Writer, withNamespa | ||||
| func printReplicationController(controller *api.ReplicationController, w io.Writer, withNamespace bool, wide bool, showAll bool, columnLabels []string) error { | ||||
| 	name := controller.Name | ||||
| 	namespace := controller.Namespace | ||||
|  | ||||
| 	containers := controller.Spec.Template.Spec.Containers | ||||
| 	var firstContainer api.Container | ||||
| 	if len(containers) > 0 { | ||||
| @@ -707,6 +709,33 @@ func printReplicationControllerList(list *api.ReplicationControllerList, w io.Wr | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func printJob(job *experimental.Job, w io.Writer, withNamespace bool, wide bool, showAll bool, columnLabels []string) error { | ||||
| 	containers := job.Spec.Template.Spec.Containers | ||||
| 	var firstContainer api.Container | ||||
| 	if len(containers) > 0 { | ||||
| 		firstContainer = containers[0] | ||||
| 	} | ||||
| 	_, err := fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%d\n", | ||||
| 		job.Name, | ||||
| 		firstContainer.Name, | ||||
| 		firstContainer.Image, | ||||
| 		labels.FormatLabels(job.Spec.Selector), | ||||
| 		job.Status.Successful) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func printJobList(list *experimental.JobList, w io.Writer, withNamespace bool, wide bool, showAll bool, columnLabels []string) error { | ||||
| 	for _, job := range list.Items { | ||||
| 		if err := printJob(&job, w, withNamespace, wide, showAll, columnLabels); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func getServiceExternalIP(svc *api.Service) string { | ||||
| 	switch svc.Spec.Type { | ||||
| 	case api.ServiceTypeClusterIP: | ||||
|   | ||||
| @@ -14,6 +14,6 @@ See the License for the specific language governing permissions and | ||||
| limitations under the License. | ||||
| */ | ||||
|  | ||||
| // Package controller provides Registry interface and it's RESTStorage | ||||
| // Package job provides Registry interface and it's RESTStorage | ||||
| // implementation for storing Job api objects. | ||||
| package job | ||||
|   | ||||
| @@ -28,7 +28,7 @@ import ( | ||||
| 	"k8s.io/kubernetes/pkg/storage" | ||||
| ) | ||||
|  | ||||
| // rest implements a RESTStorage for jobs against etcd | ||||
| // REST implements a RESTStorage for jobs against etcd | ||||
| type REST struct { | ||||
| 	*etcdgeneric.Etcd | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Jeff Lowdermilk
					Jeff Lowdermilk