Implemented Batch client

This commit is contained in:
Eric Tune 2016-02-17 15:07:38 -08:00
parent d5f303d3d7
commit 175addf2a3
12 changed files with 334 additions and 238 deletions

View File

@ -33,6 +33,7 @@ import (
_ "k8s.io/kubernetes/pkg/api/install"
_ "k8s.io/kubernetes/pkg/apis/autoscaling/install"
_ "k8s.io/kubernetes/pkg/apis/batch/install"
_ "k8s.io/kubernetes/pkg/apis/componentconfig/install"
_ "k8s.io/kubernetes/pkg/apis/extensions/install"
_ "k8s.io/kubernetes/pkg/apis/metrics/install"

View File

@ -0,0 +1,82 @@
/*
Copyright 2016 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/apimachinery/registered"
"k8s.io/kubernetes/pkg/apis/batch"
)
type BatchInterface interface {
JobsNamespacer
}
// BatchClient is used to interact with Kubernetes batch features.
type BatchClient struct {
*RESTClient
}
func (c *BatchClient) Jobs(namespace string) JobInterface {
return newJobsV1(c, namespace)
}
func NewBatch(c *Config) (*BatchClient, error) {
config := *c
if err := setBatchDefaults(&config); err != nil {
return nil, err
}
client, err := RESTClientFor(&config)
if err != nil {
return nil, err
}
return &BatchClient{client}, nil
}
func NewBatchOrDie(c *Config) *BatchClient {
client, err := NewBatch(c)
if err != nil {
panic(err)
}
return client
}
func setBatchDefaults(config *Config) error {
// if batch group is not registered, return an error
g, err := registered.Group(batch.GroupName)
if err != nil {
return err
}
config.APIPath = defaultAPIPath
if config.UserAgent == "" {
config.UserAgent = DefaultKubernetesUserAgent()
}
// TODO: Unconditionally set the config.Version, until we fix the config.
//if config.Version == "" {
copyGroupVersion := g.GroupVersion
config.GroupVersion = &copyGroupVersion
//}
config.Codec = api.Codecs.LegacyCodec(*config.GroupVersion)
if config.QPS == 0 {
config.QPS = 5
}
if config.Burst == 0 {
config.Burst = 10
}
return nil
}

View File

@ -42,6 +42,7 @@ type Interface interface {
ComponentStatusesInterface
ConfigMapsNamespacer
Autoscaling() AutoscalingInterface
Batch() BatchInterface
Extensions() ExtensionsInterface
Discovery() DiscoveryInterface
}
@ -113,6 +114,7 @@ func (c *Client) ConfigMaps(namespace string) ConfigMapsInterface {
type Client struct {
*RESTClient
*AutoscalingClient
*BatchClient
*ExtensionsClient
*DiscoveryClient
}
@ -152,6 +154,10 @@ func (c *Client) Autoscaling() AutoscalingInterface {
return c.AutoscalingClient
}
func (c *Client) Batch() BatchInterface {
return c.BatchClient
}
func (c *Client) Extensions() ExtensionsInterface {
return c.ExtensionsClient
}

View File

@ -34,6 +34,7 @@ import (
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/apimachinery/registered"
"k8s.io/kubernetes/pkg/apis/autoscaling"
"k8s.io/kubernetes/pkg/apis/batch"
"k8s.io/kubernetes/pkg/apis/extensions"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util"
@ -165,6 +166,15 @@ func New(c *Config) (*Client, error) {
}
}
var batchClient *BatchClient
if registered.IsRegistered(batch.GroupName) {
batchConfig := *c
batchClient, err = NewBatch(&batchConfig)
if err != nil {
return nil, err
}
}
var extensionsClient *ExtensionsClient
if registered.IsRegistered(extensions.GroupName) {
extensionsConfig := *c
@ -174,7 +184,7 @@ func New(c *Config) (*Client, error) {
}
}
return &Client{RESTClient: client, AutoscalingClient: autoscalingClient, ExtensionsClient: extensionsClient, DiscoveryClient: discoveryClient}, nil
return &Client{RESTClient: client, AutoscalingClient: autoscalingClient, BatchClient: batchClient, ExtensionsClient: extensionsClient, DiscoveryClient: discoveryClient}, nil
}
// MatchesServerVersion queries the server to compares the build version

View File

@ -35,7 +35,7 @@ func getHorizontalPodAutoscalersResoureName() string {
return "horizontalpodautoscalers"
}
func getClient(t *testing.T, c *simple.Client, ns, resourceGroup string) HorizontalPodAutoscalerInterface {
func getHPAClient(t *testing.T, c *simple.Client, ns, resourceGroup string) HorizontalPodAutoscalerInterface {
switch resourceGroup {
case autoscaling.GroupName:
return c.Setup(t).Autoscaling().HorizontalPodAutoscalers(ns)
@ -66,7 +66,7 @@ func testHorizontalPodAutoscalerCreate(t *testing.T, group testapi.TestGroup, re
ResourceGroup: resourceGroup,
}
response, err := getClient(t, c, ns, resourceGroup).Create(&horizontalPodAutoscaler)
response, err := getHPAClient(t, c, ns, resourceGroup).Create(&horizontalPodAutoscaler)
defer c.Close()
if err != nil {
t.Fatalf("unexpected error: %v", err)
@ -98,7 +98,7 @@ func testHorizontalPodAutoscalerGet(t *testing.T, group testapi.TestGroup, resou
ResourceGroup: resourceGroup,
}
response, err := getClient(t, c, ns, resourceGroup).Get("abc")
response, err := getHPAClient(t, c, ns, resourceGroup).Get("abc")
defer c.Close()
c.Validate(t, response, err)
}
@ -130,7 +130,7 @@ func testHorizontalPodAutoscalerList(t *testing.T, group testapi.TestGroup, reso
Response: simple.Response{StatusCode: 200, Body: horizontalPodAutoscalerList},
ResourceGroup: resourceGroup,
}
response, err := getClient(t, c, ns, resourceGroup).List(api.ListOptions{})
response, err := getHPAClient(t, c, ns, resourceGroup).List(api.ListOptions{})
defer c.Close()
c.Validate(t, response, err)
}
@ -154,7 +154,7 @@ func testHorizontalPodAutoscalerUpdate(t *testing.T, group testapi.TestGroup, re
Response: simple.Response{StatusCode: 200, Body: horizontalPodAutoscaler},
ResourceGroup: resourceGroup,
}
response, err := getClient(t, c, ns, resourceGroup).Update(horizontalPodAutoscaler)
response, err := getHPAClient(t, c, ns, resourceGroup).Update(horizontalPodAutoscaler)
defer c.Close()
c.Validate(t, response, err)
}
@ -178,7 +178,7 @@ func testHorizontalPodAutoscalerUpdateStatus(t *testing.T, group testapi.TestGro
Response: simple.Response{StatusCode: 200, Body: horizontalPodAutoscaler},
ResourceGroup: resourceGroup,
}
response, err := getClient(t, c, ns, resourceGroup).UpdateStatus(horizontalPodAutoscaler)
response, err := getHPAClient(t, c, ns, resourceGroup).UpdateStatus(horizontalPodAutoscaler)
defer c.Close()
c.Validate(t, response, err)
}
@ -195,7 +195,7 @@ func testHorizontalPodAutoscalerDelete(t *testing.T, group testapi.TestGroup, re
Response: simple.Response{StatusCode: 200},
ResourceGroup: resourceGroup,
}
err := getClient(t, c, ns, resourceGroup).Delete("foo", nil)
err := getHPAClient(t, c, ns, resourceGroup).Delete("foo", nil)
defer c.Close()
c.Validate(t, nil, err)
}
@ -214,7 +214,7 @@ func testHorizontalPodAutoscalerWatch(t *testing.T, group testapi.TestGroup, res
Response: simple.Response{StatusCode: 200},
ResourceGroup: resourceGroup,
}
_, err := getClient(t, c, api.NamespaceAll, resourceGroup).Watch(api.ListOptions{})
_, err := getHPAClient(t, c, api.NamespaceAll, resourceGroup).Watch(api.ListOptions{})
defer c.Close()
c.Validate(t, nil, err)
}

View File

@ -101,3 +101,67 @@ func (c *jobs) UpdateStatus(job *extensions.Job) (result *extensions.Job, err er
err = c.r.Put().Namespace(c.ns).Resource("jobs").Name(job.Name).SubResource("status").Body(job).Do().Into(result)
return
}
// jobsV1 implements JobsNamespacer interface using BatchClient internally
type jobsV1 struct {
r *BatchClient
ns string
}
// newJobsV1 returns a jobsV1
func newJobsV1(c *BatchClient, namespace string) *jobsV1 {
return &jobsV1{c, namespace}
}
// Ensure statically that jobsV1 implements JobInterface.
var _ JobInterface = &jobsV1{}
// List returns a list of jobs that match the label and field selectors.
func (c *jobsV1) List(opts api.ListOptions) (result *extensions.JobList, err error) {
result = &extensions.JobList{}
err = c.r.Get().Namespace(c.ns).Resource("jobs").VersionedParams(&opts, api.ParameterCodec).Do().Into(result)
return
}
// Get returns information about a particular job.
func (c *jobsV1) Get(name string) (result *extensions.Job, err error) {
result = &extensions.Job{}
err = c.r.Get().Namespace(c.ns).Resource("jobs").Name(name).Do().Into(result)
return
}
// Create creates a new job.
func (c *jobsV1) Create(job *extensions.Job) (result *extensions.Job, err error) {
result = &extensions.Job{}
err = c.r.Post().Namespace(c.ns).Resource("jobs").Body(job).Do().Into(result)
return
}
// Update updates an existing job.
func (c *jobsV1) Update(job *extensions.Job) (result *extensions.Job, err error) {
result = &extensions.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 *jobsV1) Delete(name string, options *api.DeleteOptions) (err error) {
return c.r.Delete().Namespace(c.ns).Resource("jobs").Name(name).Body(options).Do().Error()
}
// Watch returns a watch.Interface that watches the requested jobs.
func (c *jobsV1) Watch(opts api.ListOptions) (watch.Interface, error) {
return c.r.Get().
Prefix("watch").
Namespace(c.ns).
Resource("jobs").
VersionedParams(&opts, api.ParameterCodec).
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 *jobsV1) UpdateStatus(job *extensions.Job) (result *extensions.Job, err error) {
result = &extensions.Job{}
err = c.r.Put().Namespace(c.ns).Resource("jobs").Name(job.Name).SubResource("status").Body(job).Do().Into(result)
return
}

View File

@ -26,19 +26,32 @@ import (
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/testapi"
"k8s.io/kubernetes/pkg/apis/batch"
"k8s.io/kubernetes/pkg/apis/extensions"
)
func getJobResourceName() string {
func getJobsResourceName() string {
return "jobs"
}
func TestListJobsViaExtensions(t *testing.T) {
func getJobClient(t *testing.T, c *simple.Client, ns, resourceGroup string) JobInterface {
switch resourceGroup {
case batch.GroupName:
return c.Setup(t).Batch().Jobs(ns)
case extensions.GroupName:
return c.Setup(t).Extensions().Jobs(ns)
default:
t.Fatalf("Unknown group %v", resourceGroup)
}
return nil
}
func testListJob(t *testing.T, group testapi.TestGroup, resourceGroup string) {
ns := api.NamespaceAll
c := &simple.Client{
Request: simple.Request{
Method: "GET",
Path: testapi.Extensions.ResourcePath(getJobResourceName(), ns, ""),
Path: group.ResourcePath(getJobsResourceName(), ns, ""),
},
Response: simple.Response{StatusCode: 200,
Body: &extensions.JobList{
@ -58,18 +71,24 @@ func TestListJobsViaExtensions(t *testing.T) {
},
},
},
ResourceGroup: resourceGroup,
}
receivedJobList, err := c.Setup(t).Extensions().Jobs(ns).List(api.ListOptions{})
receivedJobList, err := getJobClient(t, c, ns, resourceGroup).List(api.ListOptions{})
defer c.Close()
c.Validate(t, receivedJobList, err)
}
func TestGetJobViaExtensions(t *testing.T) {
func TestListJob(t *testing.T) {
testListJob(t, testapi.Extensions, extensions.GroupName)
testListJob(t, testapi.Batch, batch.GroupName)
}
func testGetJob(t *testing.T, group testapi.TestGroup, resourceGroup string) {
ns := api.NamespaceDefault
c := &simple.Client{
Request: simple.Request{
Method: "GET",
Path: testapi.Extensions.ResourcePath(getJobResourceName(), ns, "foo"),
Path: group.ResourcePath(getJobsResourceName(), ns, "foo"),
Query: simple.BuildQueryValues(nil),
},
Response: simple.Response{
@ -87,25 +106,19 @@ func TestGetJobViaExtensions(t *testing.T) {
},
},
},
ResourceGroup: resourceGroup,
}
receivedJob, err := c.Setup(t).Extensions().Jobs(ns).Get("foo")
receivedJob, err := getJobClient(t, c, ns, resourceGroup).Get("foo")
defer c.Close()
c.Validate(t, receivedJob, err)
}
func TestGetJobWithNoNameViaExtensions(t *testing.T) {
ns := api.NamespaceDefault
c := &simple.Client{Error: true}
receivedJob, err := c.Setup(t).Extensions().Jobs(ns).Get("")
defer c.Close()
if (err != nil) && (err.Error() != simple.NameRequiredError) {
t.Errorf("Expected error: %v, but got %v", simple.NameRequiredError, err)
}
c.Validate(t, receivedJob, err)
func TestGetJob(t *testing.T) {
testGetJob(t, testapi.Extensions, extensions.GroupName)
testGetJob(t, testapi.Batch, batch.GroupName)
}
func TestUpdateJobViaExtensions(t *testing.T) {
func testUpdateJob(t *testing.T, group testapi.TestGroup, resourceGroup string) {
ns := api.NamespaceDefault
requestJob := &extensions.Job{
ObjectMeta: api.ObjectMeta{
@ -117,7 +130,7 @@ func TestUpdateJobViaExtensions(t *testing.T) {
c := &simple.Client{
Request: simple.Request{
Method: "PUT",
Path: testapi.Extensions.ResourcePath(getJobResourceName(), ns, "foo"),
Path: group.ResourcePath(getJobsResourceName(), ns, "foo"),
Query: simple.BuildQueryValues(nil),
},
Response: simple.Response{
@ -135,13 +148,19 @@ func TestUpdateJobViaExtensions(t *testing.T) {
},
},
},
ResourceGroup: resourceGroup,
}
receivedJob, err := c.Setup(t).Extensions().Jobs(ns).Update(requestJob)
receivedJob, err := getJobClient(t, c, ns, resourceGroup).Update(requestJob)
defer c.Close()
c.Validate(t, receivedJob, err)
}
func TestUpdateJobStatusViaExtensions(t *testing.T) {
func TestUpdateJob(t *testing.T) {
testUpdateJob(t, testapi.Extensions, extensions.GroupName)
testUpdateJob(t, testapi.Batch, batch.GroupName)
}
func testUpdateJobStatus(t *testing.T, group testapi.TestGroup, resourceGroup string) {
ns := api.NamespaceDefault
requestJob := &extensions.Job{
ObjectMeta: api.ObjectMeta{
@ -153,7 +172,7 @@ func TestUpdateJobStatusViaExtensions(t *testing.T) {
c := &simple.Client{
Request: simple.Request{
Method: "PUT",
Path: testapi.Extensions.ResourcePath(getJobResourceName(), ns, "foo") + "/status",
Path: group.ResourcePath(getJobsResourceName(), ns, "foo") + "/status",
Query: simple.BuildQueryValues(nil),
},
Response: simple.Response{
@ -174,28 +193,40 @@ func TestUpdateJobStatusViaExtensions(t *testing.T) {
},
},
},
ResourceGroup: resourceGroup,
}
receivedJob, err := c.Setup(t).Extensions().Jobs(ns).UpdateStatus(requestJob)
receivedJob, err := getJobClient(t, c, ns, resourceGroup).UpdateStatus(requestJob)
defer c.Close()
c.Validate(t, receivedJob, err)
}
func TestDeleteJobViaExtensions(t *testing.T) {
func TestUpdateJobStatus(t *testing.T) {
testUpdateJobStatus(t, testapi.Extensions, extensions.GroupName)
testUpdateJobStatus(t, testapi.Batch, batch.GroupName)
}
func testDeleteJob(t *testing.T, group testapi.TestGroup, resourceGroup string) {
ns := api.NamespaceDefault
c := &simple.Client{
Request: simple.Request{
Method: "DELETE",
Path: testapi.Extensions.ResourcePath(getJobResourceName(), ns, "foo"),
Path: group.ResourcePath(getJobsResourceName(), ns, "foo"),
Query: simple.BuildQueryValues(nil),
},
Response: simple.Response{StatusCode: 200},
Response: simple.Response{StatusCode: 200},
ResourceGroup: resourceGroup,
}
err := c.Setup(t).Extensions().Jobs(ns).Delete("foo", nil)
err := getJobClient(t, c, ns, resourceGroup).Delete("foo", nil)
defer c.Close()
c.Validate(t, nil, err)
}
func TestCreateJobViaExtensions(t *testing.T) {
func TestDeleteJob(t *testing.T) {
testDeleteJob(t, testapi.Extensions, extensions.GroupName)
testDeleteJob(t, testapi.Batch, batch.GroupName)
}
func testCreateJob(t *testing.T, group testapi.TestGroup, resourceGroup string) {
ns := api.NamespaceDefault
requestJob := &extensions.Job{
ObjectMeta: api.ObjectMeta{
@ -206,7 +237,7 @@ func TestCreateJobViaExtensions(t *testing.T) {
c := &simple.Client{
Request: simple.Request{
Method: "POST",
Path: testapi.Extensions.ResourcePath(getJobResourceName(), ns, ""),
Path: group.ResourcePath(getJobsResourceName(), ns, ""),
Body: requestJob,
Query: simple.BuildQueryValues(nil),
},
@ -225,208 +256,17 @@ func TestCreateJobViaExtensions(t *testing.T) {
},
},
},
ResourceGroup: resourceGroup,
}
receivedJob, err := c.Setup(t).Extensions().Jobs(ns).Create(requestJob)
receivedJob, err := getJobClient(t, c, ns, resourceGroup).Create(requestJob)
defer c.Close()
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
c.Validate(t, receivedJob, err)
}
// Tests below are a copy of the above tests. Once job is removed from extensions, above test cases can be deleted.
func TestListJobsViaBatch(t *testing.T) {
ns := api.NamespaceAll
c := &simple.Client{
Request: simple.Request{
Method: "GET",
Path: testapi.Batch.ResourcePath(getJobResourceName(), ns, ""),
},
Response: simple.Response{StatusCode: 200,
Body: &extensions.JobList{
Items: []extensions.Job{
{
ObjectMeta: api.ObjectMeta{
Name: "foo",
Labels: map[string]string{
"foo": "bar",
"name": "baz",
},
},
Spec: extensions.JobSpec{
Template: api.PodTemplateSpec{},
},
},
},
},
},
}
receivedJobList, err := c.Setup(t).Batch().Jobs(ns).List(api.ListOptions{})
defer c.Close()
c.Validate(t, receivedJobList, err)
}
func TestGetJobViaBatch(t *testing.T) {
ns := api.NamespaceDefault
c := &simple.Client{
Request: simple.Request{
Method: "GET",
Path: testapi.Batch.ResourcePath(getJobResourceName(), ns, "foo"),
Query: simple.BuildQueryValues(nil),
},
Response: simple.Response{
StatusCode: 200,
Body: &extensions.Job{
ObjectMeta: api.ObjectMeta{
Name: "foo",
Labels: map[string]string{
"foo": "bar",
"name": "baz",
},
},
Spec: extensions.JobSpec{
Template: api.PodTemplateSpec{},
},
},
},
}
receivedJob, err := c.Setup(t).Batch().Jobs(ns).Get("foo")
defer c.Close()
c.Validate(t, receivedJob, err)
}
func TestGetJobWithNoNameViaBatch(t *testing.T) {
ns := api.NamespaceDefault
c := &simple.Client{Error: true}
receivedJob, err := c.Setup(t).Batch().Jobs(ns).Get("")
defer c.Close()
if (err != nil) && (err.Error() != simple.NameRequiredError) {
t.Errorf("Expected error: %v, but got %v", simple.NameRequiredError, err)
}
c.Validate(t, receivedJob, err)
}
func TestUpdateJobViaBatch(t *testing.T) {
ns := api.NamespaceDefault
requestJob := &extensions.Job{
ObjectMeta: api.ObjectMeta{
Name: "foo",
Namespace: ns,
ResourceVersion: "1",
},
}
c := &simple.Client{
Request: simple.Request{
Method: "PUT",
Path: testapi.Batch.ResourcePath(getJobResourceName(), ns, "foo"),
Query: simple.BuildQueryValues(nil),
},
Response: simple.Response{
StatusCode: 200,
Body: &extensions.Job{
ObjectMeta: api.ObjectMeta{
Name: "foo",
Labels: map[string]string{
"foo": "bar",
"name": "baz",
},
},
Spec: extensions.JobSpec{
Template: api.PodTemplateSpec{},
},
},
},
}
receivedJob, err := c.Setup(t).Batch().Jobs(ns).Update(requestJob)
defer c.Close()
c.Validate(t, receivedJob, err)
}
func TestUpdateJobStatusViaBatch(t *testing.T) {
ns := api.NamespaceDefault
requestJob := &extensions.Job{
ObjectMeta: api.ObjectMeta{
Name: "foo",
Namespace: ns,
ResourceVersion: "1",
},
}
c := &simple.Client{
Request: simple.Request{
Method: "PUT",
Path: testapi.Batch.ResourcePath(getJobResourceName(), ns, "foo") + "/status",
Query: simple.BuildQueryValues(nil),
},
Response: simple.Response{
StatusCode: 200,
Body: &extensions.Job{
ObjectMeta: api.ObjectMeta{
Name: "foo",
Labels: map[string]string{
"foo": "bar",
"name": "baz",
},
},
Spec: extensions.JobSpec{
Template: api.PodTemplateSpec{},
},
Status: extensions.JobStatus{
Active: 1,
},
},
},
}
receivedJob, err := c.Setup(t).Batch().Jobs(ns).UpdateStatus(requestJob)
defer c.Close()
c.Validate(t, receivedJob, err)
}
func TestDeleteJobViaBatch(t *testing.T) {
ns := api.NamespaceDefault
c := &simple.Client{
Request: simple.Request{
Method: "DELETE",
Path: testapi.Batch.ResourcePath(getJobResourceName(), ns, "foo"),
Query: simple.BuildQueryValues(nil),
},
Response: simple.Response{StatusCode: 200},
}
err := c.Setup(t).Batch().Jobs(ns).Delete("foo", nil)
defer c.Close()
c.Validate(t, nil, err)
}
func TestCreateJobViaBatch(t *testing.T) {
ns := api.NamespaceDefault
requestJob := &extensions.Job{
ObjectMeta: api.ObjectMeta{
Name: "foo",
Namespace: ns,
},
}
c := &simple.Client{
Request: simple.Request{
Method: "POST",
Path: testapi.Batch.ResourcePath(getJobResourceName(), ns, ""),
Body: requestJob,
Query: simple.BuildQueryValues(nil),
},
Response: simple.Response{
StatusCode: 200,
Body: &extensions.Job{
ObjectMeta: api.ObjectMeta{
Name: "foo",
Labels: map[string]string{
"foo": "bar",
"name": "baz",
},
},
Spec: extensions.JobSpec{
Template: api.PodTemplateSpec{},
},
},
},
}
receivedJob, err := c.Setup(t).Batch().Jobs(ns).Create(requestJob)
defer c.Close()
c.Validate(t, receivedJob, err)
func TestCreateJob(t *testing.T) {
testCreateJob(t, testapi.Extensions, extensions.GroupName)
testCreateJob(t, testapi.Batch, batch.GroupName)
}

View File

@ -82,3 +82,66 @@ func (c *FakeJobs) UpdateStatus(job *extensions.Job) (result *extensions.Job, er
return obj.(*extensions.Job), err
}
// FakeJobs implements JobInterface. Meant to be embedded into a struct to get a default
// implementation. This makes faking out just the methods you want to test easier.
// This is a test implementation of JobsV1
// TODO(piosz): get back to one client implementation once HPA will be graduated to GA completely
type FakeJobsV1 struct {
Fake *FakeBatch
Namespace string
}
func (c *FakeJobsV1) Get(name string) (*extensions.Job, error) {
obj, err := c.Fake.Invokes(NewGetAction("jobs", c.Namespace, name), &extensions.Job{})
if obj == nil {
return nil, err
}
return obj.(*extensions.Job), err
}
func (c *FakeJobsV1) List(opts api.ListOptions) (*extensions.JobList, error) {
obj, err := c.Fake.Invokes(NewListAction("jobs", c.Namespace, opts), &extensions.JobList{})
if obj == nil {
return nil, err
}
return obj.(*extensions.JobList), err
}
func (c *FakeJobsV1) Create(job *extensions.Job) (*extensions.Job, error) {
obj, err := c.Fake.Invokes(NewCreateAction("jobs", c.Namespace, job), job)
if obj == nil {
return nil, err
}
return obj.(*extensions.Job), err
}
func (c *FakeJobsV1) Update(job *extensions.Job) (*extensions.Job, error) {
obj, err := c.Fake.Invokes(NewUpdateAction("jobs", c.Namespace, job), job)
if obj == nil {
return nil, err
}
return obj.(*extensions.Job), err
}
func (c *FakeJobsV1) Delete(name string, options *api.DeleteOptions) error {
_, err := c.Fake.Invokes(NewDeleteAction("jobs", c.Namespace, name), &extensions.Job{})
return err
}
func (c *FakeJobsV1) Watch(opts api.ListOptions) (watch.Interface, error) {
return c.Fake.InvokesWatch(NewWatchAction("jobs", c.Namespace, opts))
}
func (c *FakeJobsV1) UpdateStatus(job *extensions.Job) (result *extensions.Job, err error) {
obj, err := c.Fake.Invokes(NewUpdateSubresourceAction("jobs", "status", c.Namespace, job), job)
if obj == nil {
return nil, err
}
return obj.(*extensions.Job), err
}

View File

@ -92,6 +92,10 @@ func (c *Client) Setup(t *testing.T) *Client {
Host: c.server.URL,
ContentConfig: client.ContentConfig{GroupVersion: testapi.Autoscaling.GroupVersion()},
})
c.BatchClient = client.NewBatchOrDie(&client.Config{
Host: c.server.URL,
ContentConfig: client.ContentConfig{GroupVersion: testapi.Batch.GroupVersion()},
})
c.ExtensionsClient = client.NewExtensionsOrDie(&client.Config{
Host: c.server.URL,
ContentConfig: client.ContentConfig{GroupVersion: testapi.Extensions.GroupVersion()},

View File

@ -278,6 +278,10 @@ func (c *Fake) Autoscaling() client.AutoscalingInterface {
return &FakeAutoscaling{c}
}
func (c *Fake) Batch() client.BatchInterface {
return &FakeBatch{c}
}
func (c *Fake) Extensions() client.ExtensionsInterface {
return &FakeExperimental{c}
}
@ -321,6 +325,19 @@ func (c *FakeAutoscaling) HorizontalPodAutoscalers(namespace string) client.Hori
return &FakeHorizontalPodAutoscalersV1{Fake: c, Namespace: namespace}
}
// NewSimpleFakeBatch returns a client that will respond with the provided objects
func NewSimpleFakeBatch(objects ...runtime.Object) *FakeBatch {
return &FakeBatch{Fake: NewSimpleFake(objects...)}
}
type FakeBatch struct {
*Fake
}
func (c *FakeBatch) Jobs(namespace string) client.JobInterface {
return &FakeJobsV1{Fake: c, Namespace: namespace}
}
// NewSimpleFakeExp returns a client that will respond with the provided objects
func NewSimpleFakeExp(objects ...runtime.Object) *FakeExperimental {
return &FakeExperimental{Fake: NewSimpleFake(objects...)}

View File

@ -242,7 +242,7 @@ func (o *DrainOptions) getPodsForDeletion() ([]api.Pod, error) {
daemonset_pod = true
}
} else if sr.Reference.Kind == "Job" {
job, err := o.client.Jobs(sr.Reference.Namespace).Get(sr.Reference.Name)
job, err := o.client.ExtensionsClient.Jobs(sr.Reference.Namespace).Get(sr.Reference.Name)
// Assume the only reason for an error is because the Job is
// gone/missing, not for any other cause. TODO(mml): something more

View File

@ -40,6 +40,7 @@ import (
"k8s.io/kubernetes/pkg/api/validation"
"k8s.io/kubernetes/pkg/apimachinery/registered"
"k8s.io/kubernetes/pkg/apis/autoscaling"
"k8s.io/kubernetes/pkg/apis/batch"
"k8s.io/kubernetes/pkg/apis/extensions"
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
client "k8s.io/kubernetes/pkg/client/unversioned"
@ -221,6 +222,8 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory {
return client.RESTClient, nil
case autoscaling.GroupName:
return client.AutoscalingClient.RESTClient, nil
case batch.GroupName:
return client.BatchClient.RESTClient, nil
case extensions.GroupName:
return client.ExtensionsClient.RESTClient, nil
}
@ -710,6 +713,12 @@ func (c *clientSwaggerSchema) ValidateBytes(data []byte) error {
}
return getSchemaAndValidate(c.c.AutoscalingClient.RESTClient, data, "apis/", gvk.GroupVersion().String(), c.cacheDir)
}
if gvk.Group == batch.GroupName {
if c.c.BatchClient == nil {
return errors.New("unable to validate: no batch client")
}
return getSchemaAndValidate(c.c.BatchClient.RESTClient, data, "apis/", gvk.GroupVersion().String(), c.cacheDir)
}
if gvk.Group == extensions.GroupName {
if c.c.ExtensionsClient == nil {
return errors.New("unable to validate: no experimental client")