Commit 8cefa2ee authored by Maciej Szulik's avatar Maciej Szulik

Job controller logic

parent bdec7da4
...@@ -38,6 +38,7 @@ import ( ...@@ -38,6 +38,7 @@ import (
"k8s.io/kubernetes/pkg/controller/daemon" "k8s.io/kubernetes/pkg/controller/daemon"
"k8s.io/kubernetes/pkg/controller/deployment" "k8s.io/kubernetes/pkg/controller/deployment"
"k8s.io/kubernetes/pkg/controller/endpoint" "k8s.io/kubernetes/pkg/controller/endpoint"
"k8s.io/kubernetes/pkg/controller/job"
"k8s.io/kubernetes/pkg/controller/namespace" "k8s.io/kubernetes/pkg/controller/namespace"
"k8s.io/kubernetes/pkg/controller/node" "k8s.io/kubernetes/pkg/controller/node"
"k8s.io/kubernetes/pkg/controller/persistentvolume" "k8s.io/kubernetes/pkg/controller/persistentvolume"
...@@ -66,6 +67,7 @@ type CMServer struct { ...@@ -66,6 +67,7 @@ type CMServer struct {
ConcurrentEndpointSyncs int ConcurrentEndpointSyncs int
ConcurrentRCSyncs int ConcurrentRCSyncs int
ConcurrentDSCSyncs int ConcurrentDSCSyncs int
ConcurrentJobSyncs int
ServiceSyncPeriod time.Duration ServiceSyncPeriod time.Duration
NodeSyncPeriod time.Duration NodeSyncPeriod time.Duration
ResourceQuotaSyncPeriod time.Duration ResourceQuotaSyncPeriod time.Duration
...@@ -104,6 +106,7 @@ func NewCMServer() *CMServer { ...@@ -104,6 +106,7 @@ func NewCMServer() *CMServer {
ConcurrentEndpointSyncs: 5, ConcurrentEndpointSyncs: 5,
ConcurrentRCSyncs: 5, ConcurrentRCSyncs: 5,
ConcurrentDSCSyncs: 2, ConcurrentDSCSyncs: 2,
ConcurrentJobSyncs: 5,
ServiceSyncPeriod: 5 * time.Minute, ServiceSyncPeriod: 5 * time.Minute,
NodeSyncPeriod: 10 * time.Second, NodeSyncPeriod: 10 * time.Second,
ResourceQuotaSyncPeriod: 10 * time.Second, ResourceQuotaSyncPeriod: 10 * time.Second,
...@@ -238,6 +241,9 @@ func (s *CMServer) Run(_ []string) error { ...@@ -238,6 +241,9 @@ func (s *CMServer) Run(_ []string) error {
go daemon.NewDaemonSetsController(kubeClient). go daemon.NewDaemonSetsController(kubeClient).
Run(s.ConcurrentDSCSyncs, util.NeverStop) Run(s.ConcurrentDSCSyncs, util.NeverStop)
go job.NewJobManager(kubeClient).
Run(s.ConcurrentJobSyncs, util.NeverStop)
cloud, err := cloudprovider.InitCloudProvider(s.CloudProvider, s.CloudConfigFile) cloud, err := cloudprovider.InitCloudProvider(s.CloudProvider, s.CloudConfigFile)
if err != nil { if err != nil {
glog.Fatalf("Cloud provider could not be initialized: %v", err) glog.Fatalf("Cloud provider could not be initialized: %v", err)
......
...@@ -139,6 +139,13 @@ func FuzzerFor(t *testing.T, version string, src rand.Source) *fuzz.Fuzzer { ...@@ -139,6 +139,13 @@ func FuzzerFor(t *testing.T, version string, src rand.Source) *fuzz.Fuzzer {
j.RollingUpdate = &rollingUpdate j.RollingUpdate = &rollingUpdate
} }
}, },
func(j *experimental.JobSpec, c fuzz.Continue) {
c.FuzzNoCustom(j) // fuzz self without calling this function again
completions := c.Rand.Int()
parallelism := c.Rand.Int()
j.Completions = &completions
j.Parallelism = &parallelism
},
func(j *api.List, c fuzz.Continue) { func(j *api.List, c fuzz.Continue) {
c.FuzzNoCustom(j) // fuzz self without calling this function again c.FuzzNoCustom(j) // fuzz self without calling this function again
// TODO: uncomment when round trip starts from a versioned object // TODO: uncomment when round trip starts from a versioned object
......
...@@ -75,5 +75,15 @@ func addDefaultingFuncs() { ...@@ -75,5 +75,15 @@ func addDefaultingFuncs() {
*obj.Spec.UniqueLabelKey = "deployment.kubernetes.io/podTemplateHash" *obj.Spec.UniqueLabelKey = "deployment.kubernetes.io/podTemplateHash"
} }
}, },
func(obj *Job) {
if obj.Spec.Completions == nil {
completions := 1
obj.Spec.Completions = &completions
}
if obj.Spec.Parallelism == nil {
parallelism := 2
obj.Spec.Parallelism = &parallelism
}
},
) )
} }
...@@ -189,6 +189,43 @@ func TestSetDefaultDeployment(t *testing.T) { ...@@ -189,6 +189,43 @@ func TestSetDefaultDeployment(t *testing.T) {
} }
} }
func TestSetDefaultJob(t *testing.T) {
expected := &Job{
Spec: JobSpec{
Completions: newInt(1),
Parallelism: newInt(2),
},
}
tests := []*Job{
{},
{
Spec: JobSpec{
Completions: newInt(1),
},
},
{
Spec: JobSpec{
Parallelism: newInt(2),
},
},
}
for _, original := range tests {
obj2 := roundTrip(t, runtime.Object(original))
got, ok := obj2.(*Job)
if !ok {
t.Errorf("unexpected object: %v", got)
t.FailNow()
}
if *got.Spec.Completions != *expected.Spec.Completions {
t.Errorf("got different completions than expected: %d %d", *got.Spec.Completions, *expected.Spec.Completions)
}
if *got.Spec.Parallelism != *expected.Spec.Parallelism {
t.Errorf("got different parallelism than expected: %d %d", *got.Spec.Parallelism, *expected.Spec.Parallelism)
}
}
}
func roundTrip(t *testing.T, obj runtime.Object) runtime.Object { func roundTrip(t *testing.T, obj runtime.Object) runtime.Object {
data, err := v1.Codec.Encode(obj) data, err := v1.Codec.Encode(obj)
if err != nil { if err != nil {
......
...@@ -344,3 +344,55 @@ func (s *StoreToEndpointsLister) GetServiceEndpoints(svc *api.Service) (ep api.E ...@@ -344,3 +344,55 @@ func (s *StoreToEndpointsLister) GetServiceEndpoints(svc *api.Service) (ep api.E
err = fmt.Errorf("Could not find endpoints for service: %v", svc.Name) err = fmt.Errorf("Could not find endpoints for service: %v", svc.Name)
return return
} }
// StoreToJobLister gives a store List and Exists methods. The store must contain only Jobs.
type StoreToJobLister struct {
Store
}
// Exists checks if the given job exists in the store.
func (s *StoreToJobLister) Exists(job *experimental.Job) (bool, error) {
_, exists, err := s.Store.Get(job)
if err != nil {
return false, err
}
return exists, nil
}
// StoreToJobLister lists all jobs in the store.
func (s *StoreToJobLister) List() (jobs []experimental.Job, err error) {
for _, c := range s.Store.List() {
jobs = append(jobs, *(c.(*experimental.Job)))
}
return jobs, nil
}
// GetPodControllers returns a list of jobs managing a pod. Returns an error only if no matching jobs are found.
func (s *StoreToJobLister) GetPodJobs(pod *api.Pod) (jobs []experimental.Job, err error) {
var selector labels.Selector
var job experimental.Job
if len(pod.Labels) == 0 {
err = fmt.Errorf("No jobs found for pod %v because it has no labels", pod.Name)
return
}
for _, m := range s.Store.List() {
job = *m.(*experimental.Job)
if job.Namespace != pod.Namespace {
continue
}
labelSet := labels.Set(job.Spec.Selector)
selector = labels.Set(job.Spec.Selector).AsSelector()
// Job with a nil or empty selector match nothing
if labelSet.AsSelector().Empty() || !selector.Matches(labels.Set(pod.Labels)) {
continue
}
jobs = append(jobs, job)
}
if len(jobs) == 0 {
err = fmt.Errorf("Could not find jobs for pod %s in namespace %s with labels: %v", pod.Name, pod.Namespace, pod.Labels)
}
return
}
/*
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 testclient
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"
)
// FakeJobs implements JobInterface. Meant to be embedded into a struct to get a default
// implementation. This makes faking out just the method you want to test easier.
type FakeJobs struct {
Fake *FakeExperimental
Namespace string
}
func (c *FakeJobs) Get(name string) (*experimental.Job, error) {
obj, err := c.Fake.Invokes(NewGetAction("jobs", c.Namespace, name), &experimental.Job{})
if obj == nil {
return nil, err
}
return obj.(*experimental.Job), err
}
func (c *FakeJobs) List(label labels.Selector, fields fields.Selector) (*experimental.JobList, error) {
obj, err := c.Fake.Invokes(NewListAction("jobs", c.Namespace, label, nil), &experimental.JobList{})
if obj == nil {
return nil, err
}
return obj.(*experimental.JobList), err
}
func (c *FakeJobs) Create(job *experimental.Job) (*experimental.Job, error) {
obj, err := c.Fake.Invokes(NewCreateAction("jobs", c.Namespace, job), job)
if obj == nil {
return nil, err
}
return obj.(*experimental.Job), err
}
func (c *FakeJobs) Update(job *experimental.Job) (*experimental.Job, error) {
obj, err := c.Fake.Invokes(NewUpdateAction("jobs", c.Namespace, job), job)
if obj == nil {
return nil, err
}
return obj.(*experimental.Job), err
}
func (c *FakeJobs) Delete(name string, options *api.DeleteOptions) error {
_, err := c.Fake.Invokes(NewDeleteAction("jobs", c.Namespace, name), &experimental.Job{})
return err
}
func (c *FakeJobs) Watch(label labels.Selector, field fields.Selector, resourceVersion string) (watch.Interface, error) {
return c.Fake.InvokesWatch(NewWatchAction("jobs", c.Namespace, label, field, resourceVersion))
}
func (c *FakeJobs) UpdateStatus(job *experimental.Job) (result *experimental.Job, err error) {
obj, err := c.Fake.Invokes(NewUpdateSubresourceAction("jobs", "status", c.Namespace, job), job)
if obj == nil {
return nil, err
}
return obj.(*experimental.Job), err
}
...@@ -263,5 +263,5 @@ func (c *FakeExperimental) Scales(namespace string) client.ScaleInterface { ...@@ -263,5 +263,5 @@ func (c *FakeExperimental) Scales(namespace string) client.ScaleInterface {
} }
func (c *FakeExperimental) Jobs(namespace string) client.JobInterface { func (c *FakeExperimental) Jobs(namespace string) client.JobInterface {
panic("unimplemented") return &FakeJobs{Fake: c, Namespace: namespace}
} }
...@@ -26,7 +26,6 @@ import ( ...@@ -26,7 +26,6 @@ import (
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/latest" "k8s.io/kubernetes/pkg/api/latest"
"k8s.io/kubernetes/pkg/api/validation" "k8s.io/kubernetes/pkg/api/validation"
"k8s.io/kubernetes/pkg/apis/experimental"
"k8s.io/kubernetes/pkg/client/cache" "k8s.io/kubernetes/pkg/client/cache"
"k8s.io/kubernetes/pkg/client/record" "k8s.io/kubernetes/pkg/client/record"
client "k8s.io/kubernetes/pkg/client/unversioned" client "k8s.io/kubernetes/pkg/client/unversioned"
...@@ -213,10 +212,10 @@ func NewControllerExpectations() *ControllerExpectations { ...@@ -213,10 +212,10 @@ func NewControllerExpectations() *ControllerExpectations {
// PodControlInterface is an interface that knows how to add or delete pods // PodControlInterface is an interface that knows how to add or delete pods
// created as an interface to allow testing. // created as an interface to allow testing.
type PodControlInterface interface { type PodControlInterface interface {
// CreateReplica creates new replicated pods according to the spec. // CreatePods creates new pods according to the spec.
CreateReplica(namespace string, controller *api.ReplicationController) error CreatePods(namespace string, template *api.PodTemplateSpec, object runtime.Object) error
// CreateReplicaOnNode creates a new pod according to the spec on the specified node. // CreatePodsOnNode creates a new pod accorting to the spec on the specified node.
CreateReplicaOnNode(namespace string, ds *experimental.DaemonSet, nodeName string) error CreatePodsOnNode(nodeName, namespace string, template *api.PodTemplateSpec, object runtime.Object) error
// DeletePod deletes the pod identified by podID. // DeletePod deletes the pod identified by podID.
DeletePod(namespace string, podID string) error DeletePod(namespace string, podID string) error
} }
...@@ -227,7 +226,7 @@ type RealPodControl struct { ...@@ -227,7 +226,7 @@ type RealPodControl struct {
Recorder record.EventRecorder Recorder record.EventRecorder
} }
func getReplicaLabelSet(template *api.PodTemplateSpec) labels.Set { func getPodsLabelSet(template *api.PodTemplateSpec) labels.Set {
desiredLabels := make(labels.Set) desiredLabels := make(labels.Set)
for k, v := range template.Labels { for k, v := range template.Labels {
desiredLabels[k] = v desiredLabels[k] = v
...@@ -235,7 +234,7 @@ func getReplicaLabelSet(template *api.PodTemplateSpec) labels.Set { ...@@ -235,7 +234,7 @@ func getReplicaLabelSet(template *api.PodTemplateSpec) labels.Set {
return desiredLabels return desiredLabels
} }
func getReplicaAnnotationSet(template *api.PodTemplateSpec, object runtime.Object) (labels.Set, error) { func getPodsAnnotationSet(template *api.PodTemplateSpec, object runtime.Object) (labels.Set, error) {
desiredAnnotations := make(labels.Set) desiredAnnotations := make(labels.Set)
for k, v := range template.Annotations { for k, v := range template.Annotations {
desiredAnnotations[k] = v desiredAnnotations[k] = v
...@@ -254,7 +253,7 @@ func getReplicaAnnotationSet(template *api.PodTemplateSpec, object runtime.Objec ...@@ -254,7 +253,7 @@ func getReplicaAnnotationSet(template *api.PodTemplateSpec, object runtime.Objec
return desiredAnnotations, nil return desiredAnnotations, nil
} }
func getReplicaPrefix(controllerName string) string { func getPodsPrefix(controllerName string) string {
// use the dash (if the name isn't too long) to make the pod name a bit prettier // use the dash (if the name isn't too long) to make the pod name a bit prettier
prefix := fmt.Sprintf("%s-", controllerName) prefix := fmt.Sprintf("%s-", controllerName)
if ok, _ := validation.ValidatePodName(prefix, true); !ok { if ok, _ := validation.ValidatePodName(prefix, true); !ok {
...@@ -263,44 +262,25 @@ func getReplicaPrefix(controllerName string) string { ...@@ -263,44 +262,25 @@ func getReplicaPrefix(controllerName string) string {
return prefix return prefix
} }
func (r RealPodControl) CreateReplica(namespace string, controller *api.ReplicationController) error { func (r RealPodControl) CreatePods(namespace string, template *api.PodTemplateSpec, object runtime.Object) error {
desiredLabels := getReplicaLabelSet(controller.Spec.Template) return r.createPods("", namespace, template, object)
desiredAnnotations, err := getReplicaAnnotationSet(controller.Spec.Template, controller) }
if err != nil {
return err
}
prefix := getReplicaPrefix(controller.Name)
pod := &api.Pod{ func (r RealPodControl) CreatePodsOnNode(nodeName, namespace string, template *api.PodTemplateSpec, object runtime.Object) error {
ObjectMeta: api.ObjectMeta{ return r.createPods(nodeName, namespace, template, object)
Labels: desiredLabels,
Annotations: desiredAnnotations,
GenerateName: prefix,
},
}
if err := api.Scheme.Convert(&controller.Spec.Template.Spec, &pod.Spec); err != nil {
return fmt.Errorf("unable to convert pod template: %v", err)
}
if labels.Set(pod.Labels).AsSelector().Empty() {
return fmt.Errorf("unable to create pod replica, no labels")
}
if newPod, err := r.KubeClient.Pods(namespace).Create(pod); err != nil {
r.Recorder.Eventf(controller, "FailedCreate", "Error creating: %v", err)
return fmt.Errorf("unable to create pod replica: %v", err)
} else {
glog.V(4).Infof("Controller %v created pod %v", controller.Name, newPod.Name)
r.Recorder.Eventf(controller, "SuccessfulCreate", "Created pod: %v", newPod.Name)
}
return nil
} }
func (r RealPodControl) CreateReplicaOnNode(namespace string, ds *experimental.DaemonSet, nodeName string) error { func (r RealPodControl) createPods(nodeName, namespace string, template *api.PodTemplateSpec, object runtime.Object) error {
desiredLabels := getReplicaLabelSet(ds.Spec.Template) desiredLabels := getPodsLabelSet(template)
desiredAnnotations, err := getReplicaAnnotationSet(ds.Spec.Template, ds) desiredAnnotations, err := getPodsAnnotationSet(template, object)
if err != nil { if err != nil {
return err return err
} }
prefix := getReplicaPrefix(ds.Name) meta, err := api.ObjectMetaFor(object)
if err != nil {
return fmt.Errorf("object does not have ObjectMeta, %v", err)
}
prefix := getPodsPrefix(meta.Name)
pod := &api.Pod{ pod := &api.Pod{
ObjectMeta: api.ObjectMeta{ ObjectMeta: api.ObjectMeta{
...@@ -309,22 +289,22 @@ func (r RealPodControl) CreateReplicaOnNode(namespace string, ds *experimental.D ...@@ -309,22 +289,22 @@ func (r RealPodControl) CreateReplicaOnNode(namespace string, ds *experimental.D
GenerateName: prefix, GenerateName: prefix,
}, },
} }
if err := api.Scheme.Convert(&ds.Spec.Template.Spec, &pod.Spec); err != nil { if len(nodeName) != 0 {
pod.Spec.NodeName = nodeName
}
if err := api.Scheme.Convert(&template.Spec, &pod.Spec); err != nil {
return fmt.Errorf("unable to convert pod template: %v", err) return fmt.Errorf("unable to convert pod template: %v", err)
} }
// if a pod does not have labels then it cannot be controlled by any controller
if labels.Set(pod.Labels).AsSelector().Empty() { if labels.Set(pod.Labels).AsSelector().Empty() {
return fmt.Errorf("unable to create pod replica, no labels") return fmt.Errorf("unable to create pods, no labels")
} }
pod.Spec.NodeName = nodeName
if newPod, err := r.KubeClient.Pods(namespace).Create(pod); err != nil { if newPod, err := r.KubeClient.Pods(namespace).Create(pod); err != nil {
r.Recorder.Eventf(ds, "FailedCreate", "Error creating: %v", err) r.Recorder.Eventf(object, "FailedCreate", "Error creating: %v", err)
return fmt.Errorf("unable to create pod replica: %v", err) return fmt.Errorf("unable to create pods: %v", err)
} else { } else {
glog.V(4).Infof("Controller %v created pod %v", ds.Name, newPod.Name) glog.V(4).Infof("Controller %v created pod %v", meta.Name, newPod.Name)
r.Recorder.Eventf(ds, "SuccessfulCreate", "Created pod: %v", newPod.Name) r.Recorder.Eventf(object, "SuccessfulCreate", "Created pod: %v", newPod.Name)
} }
return nil return nil
} }
......
...@@ -180,7 +180,7 @@ func TestControllerExpectations(t *testing.T) { ...@@ -180,7 +180,7 @@ func TestControllerExpectations(t *testing.T) {
} }
} }
func TestCreateReplica(t *testing.T) { func TestCreatePods(t *testing.T) {
ns := api.NamespaceDefault ns := api.NamespaceDefault
body := runtime.EncodeOrDie(testapi.Default.Codec(), &api.Pod{ObjectMeta: api.ObjectMeta{Name: "empty_pod"}}) body := runtime.EncodeOrDie(testapi.Default.Codec(), &api.Pod{ObjectMeta: api.ObjectMeta{Name: "empty_pod"}})
fakeHandler := util.FakeHandler{ fakeHandler := util.FakeHandler{
...@@ -199,7 +199,7 @@ func TestCreateReplica(t *testing.T) { ...@@ -199,7 +199,7 @@ func TestCreateReplica(t *testing.T) {
controllerSpec := newReplicationController(1) controllerSpec := newReplicationController(1)
// Make sure createReplica sends a POST to the apiserver with a pod from the controllers pod template // Make sure createReplica sends a POST to the apiserver with a pod from the controllers pod template
podControl.CreateReplica(ns, controllerSpec) podControl.CreatePods(ns, controllerSpec.Spec.Template, controllerSpec)
expectedPod := api.Pod{ expectedPod := api.Pod{
ObjectMeta: api.ObjectMeta{ ObjectMeta: api.ObjectMeta{
......
...@@ -371,7 +371,7 @@ func (dsc *DaemonSetsController) manage(ds *experimental.DaemonSet) { ...@@ -371,7 +371,7 @@ func (dsc *DaemonSetsController) manage(ds *experimental.DaemonSet) {
glog.V(4).Infof("Nodes needing daemon pods for daemon set %s: %+v", ds.Name, nodesNeedingDaemonPods) glog.V(4).Infof("Nodes needing daemon pods for daemon set %s: %+v", ds.Name, nodesNeedingDaemonPods)
for i := range nodesNeedingDaemonPods { for i := range nodesNeedingDaemonPods {
if err := dsc.podControl.CreateReplicaOnNode(ds.Namespace, ds, nodesNeedingDaemonPods[i]); err != nil { if err := dsc.podControl.CreatePodsOnNode(nodesNeedingDaemonPods[i], ds.Namespace, ds.Spec.Template, ds); err != nil {
glog.V(2).Infof("Failed creation, decrementing expectations for set %q/%q", ds.Namespace, ds.Name) glog.V(2).Infof("Failed creation, decrementing expectations for set %q/%q", ds.Namespace, ds.Name)
dsc.expectations.CreationObserved(dsKey) dsc.expectations.CreationObserved(dsKey)
util.HandleError(err) util.HandleError(err)
......
...@@ -27,6 +27,7 @@ import ( ...@@ -27,6 +27,7 @@ import (
"k8s.io/kubernetes/pkg/client/cache" "k8s.io/kubernetes/pkg/client/cache"
client "k8s.io/kubernetes/pkg/client/unversioned" client "k8s.io/kubernetes/pkg/client/unversioned"
"k8s.io/kubernetes/pkg/controller" "k8s.io/kubernetes/pkg/controller"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/securitycontext" "k8s.io/kubernetes/pkg/securitycontext"
) )
...@@ -38,7 +39,7 @@ var ( ...@@ -38,7 +39,7 @@ var (
) )
type FakePodControl struct { type FakePodControl struct {
daemonSet []experimental.DaemonSet podSpec []api.PodTemplateSpec
deletePodName []string deletePodName []string
lock sync.Mutex lock sync.Mutex
err error err error
...@@ -48,17 +49,17 @@ func init() { ...@@ -48,17 +49,17 @@ func init() {
api.ForTesting_ReferencesAllowBlankSelfLinks = true api.ForTesting_ReferencesAllowBlankSelfLinks = true
} }
func (f *FakePodControl) CreateReplica(namespace string, spec *api.ReplicationController) error { func (f *FakePodControl) CreatePods(namespace string, spec *api.PodTemplateSpec, object runtime.Object) error {
return nil return nil
} }
func (f *FakePodControl) CreateReplicaOnNode(namespace string, ds *experimental.DaemonSet, nodeName string) error { func (f *FakePodControl) CreatePodsOnNode(nodeName, namespace string, spec *api.PodTemplateSpec, object runtime.Object) error {
f.lock.Lock() f.lock.Lock()
defer f.lock.Unlock() defer f.lock.Unlock()
if f.err != nil { if f.err != nil {
return f.err return f.err
} }
f.daemonSet = append(f.daemonSet, *ds) f.podSpec = append(f.podSpec, *spec)
return nil return nil
} }
...@@ -75,7 +76,7 @@ func (f *FakePodControl) clear() { ...@@ -75,7 +76,7 @@ func (f *FakePodControl) clear() {
f.lock.Lock() f.lock.Lock()
defer f.lock.Unlock() defer f.lock.Unlock()
f.deletePodName = []string{} f.deletePodName = []string{}
f.daemonSet = []experimental.DaemonSet{} f.podSpec = []api.PodTemplateSpec{}
} }
func newDaemonSet(name string) *experimental.DaemonSet { func newDaemonSet(name string) *experimental.DaemonSet {
...@@ -164,8 +165,8 @@ func newTestController() (*DaemonSetsController, *FakePodControl) { ...@@ -164,8 +165,8 @@ func newTestController() (*DaemonSetsController, *FakePodControl) {
} }
func validateSyncDaemonSets(t *testing.T, fakePodControl *FakePodControl, expectedCreates, expectedDeletes int) { func validateSyncDaemonSets(t *testing.T, fakePodControl *FakePodControl, expectedCreates, expectedDeletes int) {
if len(fakePodControl.daemonSet) != expectedCreates { if len(fakePodControl.podSpec) != expectedCreates {
t.Errorf("Unexpected number of creates. Expected %d, saw %d\n", expectedCreates, len(fakePodControl.daemonSet)) t.Errorf("Unexpected number of creates. Expected %d, saw %d\n", expectedCreates, len(fakePodControl.podSpec))
} }
if len(fakePodControl.deletePodName) != expectedDeletes { if len(fakePodControl.deletePodName) != expectedDeletes {
t.Errorf("Unexpected number of deletes. Expected %d, saw %d\n", expectedDeletes, len(fakePodControl.deletePodName)) t.Errorf("Unexpected number of deletes. Expected %d, saw %d\n", expectedDeletes, len(fakePodControl.deletePodName))
......
/*
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 job contains logic for watching and synchronizing jobs.
package job
...@@ -350,7 +350,7 @@ func (rm *ReplicationManager) manageReplicas(filteredPods []*api.Pod, rc *api.Re ...@@ -350,7 +350,7 @@ func (rm *ReplicationManager) manageReplicas(filteredPods []*api.Pod, rc *api.Re
for i := 0; i < diff; i++ { for i := 0; i < diff; i++ {
go func() { go func() {
defer wait.Done() defer wait.Done()
if err := rm.podControl.CreateReplica(rc.Namespace, rc); err != nil { if err := rm.podControl.CreatePods(rc.Namespace, rc.Spec.Template, rc); err != nil {
// Decrement the expected number of creates because the informer won't observe this pod // Decrement the expected number of creates because the informer won't observe this pod
glog.V(2).Infof("Failed creation, decrementing expectations for controller %q/%q", rc.Namespace, rc.Name) glog.V(2).Infof("Failed creation, decrementing expectations for controller %q/%q", rc.Namespace, rc.Name)
rm.expectations.CreationObserved(rcKey) rm.expectations.CreationObserved(rcKey)
......
...@@ -27,7 +27,6 @@ import ( ...@@ -27,7 +27,6 @@ import (
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/pkg/api/testapi"
"k8s.io/kubernetes/pkg/apis/experimental"
"k8s.io/kubernetes/pkg/client/cache" "k8s.io/kubernetes/pkg/client/cache"
client "k8s.io/kubernetes/pkg/client/unversioned" client "k8s.io/kubernetes/pkg/client/unversioned"
"k8s.io/kubernetes/pkg/client/unversioned/testclient" "k8s.io/kubernetes/pkg/client/unversioned/testclient"
...@@ -42,7 +41,7 @@ import ( ...@@ -42,7 +41,7 @@ import (
) )
type FakePodControl struct { type FakePodControl struct {
controllerSpec []api.ReplicationController controllerSpec []api.PodTemplateSpec
deletePodName []string deletePodName []string
lock sync.Mutex lock sync.Mutex
err error err error
...@@ -60,7 +59,7 @@ func init() { ...@@ -60,7 +59,7 @@ func init() {
api.ForTesting_ReferencesAllowBlankSelfLinks = true api.ForTesting_ReferencesAllowBlankSelfLinks = true
} }
func (f *FakePodControl) CreateReplica(namespace string, spec *api.ReplicationController) error { func (f *FakePodControl) CreatePods(namespace string, spec *api.PodTemplateSpec, object runtime.Object) error {
f.lock.Lock() f.lock.Lock()
defer f.lock.Unlock() defer f.lock.Unlock()
if f.err != nil { if f.err != nil {
...@@ -70,7 +69,7 @@ func (f *FakePodControl) CreateReplica(namespace string, spec *api.ReplicationCo ...@@ -70,7 +69,7 @@ func (f *FakePodControl) CreateReplica(namespace string, spec *api.ReplicationCo
return nil return nil
} }
func (f *FakePodControl) CreateReplicaOnNode(namespace string, daemon *experimental.DaemonSet, nodeName string) error { func (f *FakePodControl) CreatePodsOnNode(nodeName, namespace string, template *api.PodTemplateSpec, object runtime.Object) error {
return nil return nil
} }
...@@ -87,7 +86,7 @@ func (f *FakePodControl) clear() { ...@@ -87,7 +86,7 @@ func (f *FakePodControl) clear() {
f.lock.Lock() f.lock.Lock()
defer f.lock.Unlock() defer f.lock.Unlock()
f.deletePodName = []string{} f.deletePodName = []string{}
f.controllerSpec = []api.ReplicationController{} f.controllerSpec = []api.PodTemplateSpec{}
} }
func getKey(rc *api.ReplicationController, t *testing.T) string { func getKey(rc *api.ReplicationController, t *testing.T) string {
......
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