Commit 175addf2 authored by Eric Tune's avatar Eric Tune

Implemented Batch client

parent d5f303d3
......@@ -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"
......
/*
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
}
......@@ -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
}
......
......@@ -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
......
......@@ -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)
}
......
......@@ -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
}
......@@ -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
}
......@@ -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()},
......
......@@ -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...)}
......
......@@ -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
......
......@@ -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")
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment