Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
K
k3s
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Jacklull
k3s
Commits
8c923faf
Commit
8c923faf
authored
Nov 01, 2016
by
Andy Goldstein
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Switch to JobLister
parent
8e104134
Show whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
497 additions
and
336 deletions
+497
-336
controllermanager.go
cmd/kube-controller-manager/app/controllermanager.go
+1
-1
BUILD
pkg/client/cache/BUILD
+0
-2
listers.go
pkg/client/cache/listers.go
+0
-51
listers_test.go
pkg/client/cache/listers_test.go
+0
-172
BUILD
pkg/client/listers/batch/internalversion/BUILD
+18
-0
expansion_generated.go
...ient/listers/batch/internalversion/expansion_generated.go
+0
-8
job_expansion.go
pkg/client/listers/batch/internalversion/job_expansion.go
+64
-0
job_test.go
pkg/client/listers/batch/internalversion/job_test.go
+219
-0
BUILD
pkg/controller/informers/BUILD
+3
-0
batch.go
pkg/controller/informers/batch.go
+83
-0
factory.go
pkg/controller/informers/factory.go
+7
-0
generic.go
pkg/controller/informers/generic.go
+4
-0
BUILD
pkg/controller/job/BUILD
+4
-3
jobcontroller.go
pkg/controller/job/jobcontroller.go
+26
-50
jobcontroller_test.go
pkg/controller/job/jobcontroller_test.go
+67
-49
test_owners.csv
test/test_owners.csv
+1
-0
No files found.
cmd/kube-controller-manager/app/controllermanager.go
View file @
8c923faf
...
...
@@ -406,7 +406,7 @@ func StartControllers(s *options.CMServer, kubeconfig *restclient.Config, rootCl
if
containsResource
(
resources
,
"jobs"
)
{
glog
.
Infof
(
"Starting job controller"
)
go
job
.
NewJobController
(
sharedInformers
.
Pods
()
.
Informer
(),
client
(
"job-controller"
))
.
go
job
.
NewJobController
(
sharedInformers
.
Pods
()
.
Informer
(),
sharedInformers
.
Jobs
(),
client
(
"job-controller"
))
.
Run
(
int
(
s
.
ConcurrentJobSyncs
),
wait
.
NeverStop
)
time
.
Sleep
(
wait
.
Jitter
(
s
.
ControllerStartInterval
.
Duration
,
ControllerStartJitter
))
}
...
...
pkg/client/cache/BUILD
View file @
8c923faf
...
...
@@ -40,7 +40,6 @@ go_library(
"//pkg/api/meta:go_default_library",
"//pkg/api/unversioned:go_default_library",
"//pkg/apis/apps:go_default_library",
"//pkg/apis/batch:go_default_library",
"//pkg/apis/certificates:go_default_library",
"//pkg/apis/extensions:go_default_library",
"//pkg/apis/policy:go_default_library",
...
...
@@ -84,7 +83,6 @@ go_test(
"//pkg/api/testapi:go_default_library",
"//pkg/api/unversioned:go_default_library",
"//pkg/apimachinery/registered:go_default_library",
"//pkg/apis/batch:go_default_library",
"//pkg/apis/extensions:go_default_library",
"//pkg/client/clientset_generated/internalclientset:go_default_library",
"//pkg/client/restclient:go_default_library",
...
...
pkg/client/cache/listers.go
View file @
8c923faf
...
...
@@ -25,7 +25,6 @@ import (
"k8s.io/kubernetes/pkg/api/meta"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/apis/apps"
"k8s.io/kubernetes/pkg/apis/batch"
"k8s.io/kubernetes/pkg/apis/certificates"
"k8s.io/kubernetes/pkg/apis/extensions"
"k8s.io/kubernetes/pkg/apis/policy"
...
...
@@ -294,56 +293,6 @@ func (s *StoreToEndpointsLister) GetServiceEndpoints(svc *api.Service) (ep api.E
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
*
batch
.
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
batch
.
JobList
,
err
error
)
{
for
_
,
c
:=
range
s
.
Store
.
List
()
{
jobs
.
Items
=
append
(
jobs
.
Items
,
*
(
c
.
(
*
batch
.
Job
)))
}
return
jobs
,
nil
}
// GetPodJobs 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
[]
batch
.
Job
,
err
error
)
{
var
selector
labels
.
Selector
var
job
batch
.
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
.
(
*
batch
.
Job
)
if
job
.
Namespace
!=
pod
.
Namespace
{
continue
}
selector
,
_
=
unversioned
.
LabelSelectorAsSelector
(
job
.
Spec
.
Selector
)
if
!
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
}
// Typed wrapper around a store of PersistentVolumes
type
StoreToPVFetcher
struct
{
Store
...
...
pkg/client/cache/listers_test.go
View file @
8c923faf
...
...
@@ -22,7 +22,6 @@ import (
"k8s.io/kubernetes/pkg/api"
apierrors
"k8s.io/kubernetes/pkg/api/errors"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/apis/batch"
"k8s.io/kubernetes/pkg/apis/extensions"
"k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/util/sets"
...
...
@@ -517,177 +516,6 @@ func TestStoreToDaemonSetLister(t *testing.T) {
}
}
func
TestStoreToJobLister
(
t
*
testing
.
T
)
{
store
:=
NewStore
(
MetaNamespaceKeyFunc
)
lister
:=
StoreToJobLister
{
store
}
testCases
:=
[]
struct
{
inJobs
[]
*
batch
.
Job
list
func
()
([]
batch
.
Job
,
error
)
outJobNames
sets
.
String
expectErr
bool
msg
string
}{
// Basic listing
{
inJobs
:
[]
*
batch
.
Job
{
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"basic"
}},
},
list
:
func
()
([]
batch
.
Job
,
error
)
{
list
,
err
:=
lister
.
List
()
return
list
.
Items
,
err
},
outJobNames
:
sets
.
NewString
(
"basic"
),
msg
:
"basic listing failed"
,
},
// Listing multiple jobs
{
inJobs
:
[]
*
batch
.
Job
{
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"basic"
}},
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"complex"
}},
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"complex2"
}},
},
list
:
func
()
([]
batch
.
Job
,
error
)
{
list
,
err
:=
lister
.
List
()
return
list
.
Items
,
err
},
outJobNames
:
sets
.
NewString
(
"basic"
,
"complex"
,
"complex2"
),
msg
:
"listing multiple jobs failed"
,
},
// No pod labels
{
inJobs
:
[]
*
batch
.
Job
{
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"basic"
,
Namespace
:
"ns"
},
Spec
:
batch
.
JobSpec
{
Selector
:
&
unversioned
.
LabelSelector
{
MatchLabels
:
map
[
string
]
string
{
"foo"
:
"baz"
},
},
},
},
},
list
:
func
()
([]
batch
.
Job
,
error
)
{
pod
:=
&
api
.
Pod
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"pod"
,
Namespace
:
"ns"
},
}
return
lister
.
GetPodJobs
(
pod
)
},
outJobNames
:
sets
.
NewString
(),
expectErr
:
true
,
msg
:
"listing jobs failed when pod has no labels: expected error, got none"
,
},
// No Job selectors
{
inJobs
:
[]
*
batch
.
Job
{
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"basic"
,
Namespace
:
"ns"
},
},
},
list
:
func
()
([]
batch
.
Job
,
error
)
{
pod
:=
&
api
.
Pod
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"pod"
,
Namespace
:
"ns"
,
Labels
:
map
[
string
]
string
{
"foo"
:
"bar"
},
},
}
return
lister
.
GetPodJobs
(
pod
)
},
outJobNames
:
sets
.
NewString
(),
expectErr
:
true
,
msg
:
"listing jobs failed when job has no selector: expected error, got none"
,
},
// Matching labels to selectors and namespace
{
inJobs
:
[]
*
batch
.
Job
{
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"foo"
},
Spec
:
batch
.
JobSpec
{
Selector
:
&
unversioned
.
LabelSelector
{
MatchLabels
:
map
[
string
]
string
{
"foo"
:
"bar"
},
},
},
},
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"bar"
,
Namespace
:
"ns"
},
Spec
:
batch
.
JobSpec
{
Selector
:
&
unversioned
.
LabelSelector
{
MatchLabels
:
map
[
string
]
string
{
"foo"
:
"bar"
},
},
},
},
},
list
:
func
()
([]
batch
.
Job
,
error
)
{
pod
:=
&
api
.
Pod
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"pod"
,
Labels
:
map
[
string
]
string
{
"foo"
:
"bar"
},
Namespace
:
"ns"
,
},
}
return
lister
.
GetPodJobs
(
pod
)
},
outJobNames
:
sets
.
NewString
(
"bar"
),
msg
:
"listing jobs with namespace and selector failed"
,
},
// Matching labels to selectors and namespace, error case
{
inJobs
:
[]
*
batch
.
Job
{
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"foo"
,
Namespace
:
"foo"
},
Spec
:
batch
.
JobSpec
{
Selector
:
&
unversioned
.
LabelSelector
{
MatchLabels
:
map
[
string
]
string
{
"foo"
:
"bar"
},
},
},
},
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"bar"
,
Namespace
:
"bar"
},
Spec
:
batch
.
JobSpec
{
Selector
:
&
unversioned
.
LabelSelector
{
MatchLabels
:
map
[
string
]
string
{
"foo"
:
"bar"
},
},
},
},
},
list
:
func
()
([]
batch
.
Job
,
error
)
{
pod
:=
&
api
.
Pod
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"pod"
,
Labels
:
map
[
string
]
string
{
"foo"
:
"bar"
},
Namespace
:
"baz"
,
},
}
return
lister
.
GetPodJobs
(
pod
)
},
expectErr
:
true
,
msg
:
"listing jobs with namespace and selector failed: expected error, got none"
,
},
}
for
_
,
c
:=
range
testCases
{
for
_
,
r
:=
range
c
.
inJobs
{
store
.
Add
(
r
)
}
Jobs
,
err
:=
c
.
list
()
if
err
!=
nil
&&
c
.
expectErr
{
continue
}
else
if
c
.
expectErr
{
t
.
Errorf
(
"%v"
,
c
.
msg
)
continue
}
else
if
err
!=
nil
{
t
.
Errorf
(
"Unexpected error %#v"
,
err
)
continue
}
JobNames
:=
make
([]
string
,
len
(
Jobs
))
for
ix
:=
range
Jobs
{
JobNames
[
ix
]
=
Jobs
[
ix
]
.
Name
}
if
!
c
.
outJobNames
.
HasAll
(
JobNames
...
)
||
len
(
JobNames
)
!=
len
(
c
.
outJobNames
)
{
t
.
Errorf
(
"%v : expected %v, got %v"
,
c
.
msg
,
JobNames
,
c
.
outJobNames
)
}
}
}
func
TestStoreToPodLister
(
t
*
testing
.
T
)
{
// We test with and without a namespace index, because StoreToPodLister has
// special logic to work on namespaces even when no namespace index is
...
...
pkg/client/listers/batch/internalversion/BUILD
View file @
8c923faf
...
...
@@ -15,13 +15,31 @@ go_library(
srcs = [
"expansion_generated.go",
"job.go",
"job_expansion.go",
"scheduledjob.go",
],
tags = ["automanaged"],
deps = [
"//pkg/api:go_default_library",
"//pkg/api/errors:go_default_library",
"//pkg/api/unversioned:go_default_library",
"//pkg/apis/batch:go_default_library",
"//pkg/client/cache:go_default_library",
"//pkg/labels:go_default_library",
],
)
go_test(
name = "go_default_test",
srcs = ["job_test.go"],
library = "go_default_library",
tags = ["automanaged"],
deps = [
"//pkg/api:go_default_library",
"//pkg/api/unversioned:go_default_library",
"//pkg/apis/batch:go_default_library",
"//pkg/client/cache:go_default_library",
"//pkg/labels:go_default_library",
"//pkg/util/sets:go_default_library",
],
)
pkg/client/listers/batch/internalversion/expansion_generated.go
View file @
8c923faf
...
...
@@ -18,14 +18,6 @@ limitations under the License.
package
internalversion
// JobListerExpansion allows custom methods to be added to
// JobLister.
type
JobListerExpansion
interface
{}
// JobNamespaceListerExpansion allows custom methods to be added to
// JobNamespaeLister.
type
JobNamespaceListerExpansion
interface
{}
// ScheduledJobListerExpansion allows custom methods to be added to
// ScheduledJobLister.
type
ScheduledJobListerExpansion
interface
{}
...
...
pkg/client/listers/batch/internalversion/job_expansion.go
0 → 100644
View file @
8c923faf
/*
Copyright 2016 The Kubernetes Authors.
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
internalversion
import
(
"fmt"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/apis/batch"
"k8s.io/kubernetes/pkg/labels"
)
// JobListerExpansion allows custom methods to be added to
// JobLister.
type
JobListerExpansion
interface
{
// GetPodJobs returns a list of jobs managing a pod. An error is returned only
// if no matching jobs are found.
GetPodJobs
(
pod
*
api
.
Pod
)
(
jobs
[]
batch
.
Job
,
err
error
)
}
// GetPodJobs returns a list of jobs managing a pod. An error is returned only
// if no matching jobs are found.
func
(
l
*
jobLister
)
GetPodJobs
(
pod
*
api
.
Pod
)
(
jobs
[]
batch
.
Job
,
err
error
)
{
if
len
(
pod
.
Labels
)
==
0
{
err
=
fmt
.
Errorf
(
"no jobs found for pod %v because it has no labels"
,
pod
.
Name
)
return
}
var
list
[]
*
batch
.
Job
list
,
err
=
l
.
Jobs
(
pod
.
Namespace
)
.
List
(
labels
.
Everything
())
if
err
!=
nil
{
return
}
for
_
,
job
:=
range
list
{
selector
,
_
:=
unversioned
.
LabelSelectorAsSelector
(
job
.
Spec
.
Selector
)
if
!
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
}
// JobNamespaceListerExpansion allows custom methods to be added to
// JobNamespaceLister.
type
JobNamespaceListerExpansion
interface
{}
pkg/client/listers/batch/internalversion/job_test.go
0 → 100644
View file @
8c923faf
/*
Copyright 2016 The Kubernetes Authors.
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
internalversion
import
(
"testing"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/apis/batch"
"k8s.io/kubernetes/pkg/client/cache"
"k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/util/sets"
)
func
TestJobLister
(
t
*
testing
.
T
)
{
indexer
:=
cache
.
NewIndexer
(
cache
.
MetaNamespaceKeyFunc
,
cache
.
Indexers
{
cache
.
NamespaceIndex
:
cache
.
MetaNamespaceIndexFunc
})
lister
:=
NewJobLister
(
indexer
)
testCases
:=
[]
struct
{
inJobs
[]
*
batch
.
Job
list
func
()
([]
*
batch
.
Job
,
error
)
outJobNames
sets
.
String
expectErr
bool
msg
string
}{
// Basic listing
{
inJobs
:
[]
*
batch
.
Job
{
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"basic"
}},
},
list
:
func
()
([]
*
batch
.
Job
,
error
)
{
list
,
err
:=
lister
.
List
(
labels
.
Everything
())
return
list
,
err
},
outJobNames
:
sets
.
NewString
(
"basic"
),
msg
:
"basic listing failed"
,
},
// Listing multiple jobs
{
inJobs
:
[]
*
batch
.
Job
{
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"basic"
}},
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"complex"
}},
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"complex2"
}},
},
list
:
func
()
([]
*
batch
.
Job
,
error
)
{
list
,
err
:=
lister
.
List
(
labels
.
Everything
())
return
list
,
err
},
outJobNames
:
sets
.
NewString
(
"basic"
,
"complex"
,
"complex2"
),
msg
:
"listing multiple jobs failed"
,
},
// No pod labels
{
inJobs
:
[]
*
batch
.
Job
{
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"basic"
,
Namespace
:
"ns"
},
Spec
:
batch
.
JobSpec
{
Selector
:
&
unversioned
.
LabelSelector
{
MatchLabels
:
map
[
string
]
string
{
"foo"
:
"baz"
},
},
},
},
},
list
:
func
()
([]
*
batch
.
Job
,
error
)
{
pod
:=
&
api
.
Pod
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"pod"
,
Namespace
:
"ns"
},
}
podJobs
,
err
:=
lister
.
GetPodJobs
(
pod
)
jobs
:=
make
([]
*
batch
.
Job
,
0
,
len
(
podJobs
))
for
i
:=
range
podJobs
{
jobs
=
append
(
jobs
,
&
podJobs
[
i
])
}
return
jobs
,
err
},
outJobNames
:
sets
.
NewString
(),
expectErr
:
true
,
msg
:
"listing jobs failed when pod has no labels: expected error, got none"
,
},
// No Job selectors
{
inJobs
:
[]
*
batch
.
Job
{
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"basic"
,
Namespace
:
"ns"
},
},
},
list
:
func
()
([]
*
batch
.
Job
,
error
)
{
pod
:=
&
api
.
Pod
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"pod"
,
Namespace
:
"ns"
,
Labels
:
map
[
string
]
string
{
"foo"
:
"bar"
},
},
}
podJobs
,
err
:=
lister
.
GetPodJobs
(
pod
)
jobs
:=
make
([]
*
batch
.
Job
,
0
,
len
(
podJobs
))
for
i
:=
range
podJobs
{
jobs
=
append
(
jobs
,
&
podJobs
[
i
])
}
return
jobs
,
err
},
outJobNames
:
sets
.
NewString
(),
expectErr
:
true
,
msg
:
"listing jobs failed when job has no selector: expected error, got none"
,
},
// Matching labels to selectors and namespace
{
inJobs
:
[]
*
batch
.
Job
{
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"foo"
},
Spec
:
batch
.
JobSpec
{
Selector
:
&
unversioned
.
LabelSelector
{
MatchLabels
:
map
[
string
]
string
{
"foo"
:
"bar"
},
},
},
},
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"bar"
,
Namespace
:
"ns"
},
Spec
:
batch
.
JobSpec
{
Selector
:
&
unversioned
.
LabelSelector
{
MatchLabels
:
map
[
string
]
string
{
"foo"
:
"bar"
},
},
},
},
},
list
:
func
()
([]
*
batch
.
Job
,
error
)
{
pod
:=
&
api
.
Pod
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"pod"
,
Labels
:
map
[
string
]
string
{
"foo"
:
"bar"
},
Namespace
:
"ns"
,
},
}
podJobs
,
err
:=
lister
.
GetPodJobs
(
pod
)
jobs
:=
make
([]
*
batch
.
Job
,
0
,
len
(
podJobs
))
for
i
:=
range
podJobs
{
jobs
=
append
(
jobs
,
&
podJobs
[
i
])
}
return
jobs
,
err
},
outJobNames
:
sets
.
NewString
(
"bar"
),
msg
:
"listing jobs with namespace and selector failed"
,
},
// Matching labels to selectors and namespace, error case
{
inJobs
:
[]
*
batch
.
Job
{
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"foo"
,
Namespace
:
"foo"
},
Spec
:
batch
.
JobSpec
{
Selector
:
&
unversioned
.
LabelSelector
{
MatchLabels
:
map
[
string
]
string
{
"foo"
:
"bar"
},
},
},
},
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"bar"
,
Namespace
:
"bar"
},
Spec
:
batch
.
JobSpec
{
Selector
:
&
unversioned
.
LabelSelector
{
MatchLabels
:
map
[
string
]
string
{
"foo"
:
"bar"
},
},
},
},
},
list
:
func
()
([]
*
batch
.
Job
,
error
)
{
pod
:=
&
api
.
Pod
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"pod"
,
Labels
:
map
[
string
]
string
{
"foo"
:
"bar"
},
Namespace
:
"baz"
,
},
}
podJobs
,
err
:=
lister
.
GetPodJobs
(
pod
)
jobs
:=
make
([]
*
batch
.
Job
,
0
,
len
(
podJobs
))
for
i
:=
range
podJobs
{
jobs
=
append
(
jobs
,
&
podJobs
[
i
])
}
return
jobs
,
err
},
expectErr
:
true
,
msg
:
"listing jobs with namespace and selector failed: expected error, got none"
,
},
}
for
_
,
c
:=
range
testCases
{
for
_
,
r
:=
range
c
.
inJobs
{
indexer
.
Add
(
r
)
}
Jobs
,
err
:=
c
.
list
()
if
err
!=
nil
&&
c
.
expectErr
{
continue
}
else
if
c
.
expectErr
{
t
.
Errorf
(
"%v"
,
c
.
msg
)
continue
}
else
if
err
!=
nil
{
t
.
Errorf
(
"Unexpected error %#v"
,
err
)
continue
}
JobNames
:=
make
([]
string
,
len
(
Jobs
))
for
ix
:=
range
Jobs
{
JobNames
[
ix
]
=
Jobs
[
ix
]
.
Name
}
if
!
c
.
outJobNames
.
HasAll
(
JobNames
...
)
||
len
(
JobNames
)
!=
len
(
c
.
outJobNames
)
{
t
.
Errorf
(
"%v : expected %v, got %v"
,
c
.
msg
,
JobNames
,
c
.
outJobNames
)
}
}
}
pkg/controller/informers/BUILD
View file @
8c923faf
...
...
@@ -13,6 +13,7 @@ load(
go_library(
name = "go_default_library",
srcs = [
"batch.go",
"core.go",
"extensions.go",
"factory.go",
...
...
@@ -24,11 +25,13 @@ go_library(
deps = [
"//pkg/api:go_default_library",
"//pkg/api/unversioned:go_default_library",
"//pkg/apis/batch:go_default_library",
"//pkg/apis/extensions:go_default_library",
"//pkg/apis/rbac:go_default_library",
"//pkg/apis/storage:go_default_library",
"//pkg/client/cache:go_default_library",
"//pkg/client/clientset_generated/internalclientset:go_default_library",
"//pkg/client/listers/batch/internalversion:go_default_library",
"//pkg/client/listers/core/internalversion:go_default_library",
"//pkg/runtime:go_default_library",
"//pkg/watch:go_default_library",
...
...
pkg/controller/informers/batch.go
0 → 100644
View file @
8c923faf
/*
Copyright 2016 The Kubernetes Authors.
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
informers
import
(
"reflect"
"time"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/apis/batch"
"k8s.io/kubernetes/pkg/client/cache"
clientset
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
batchinternallisters
"k8s.io/kubernetes/pkg/client/listers/batch/internalversion"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/watch"
)
// JobInformer is type of SharedIndexInformer which watches and lists all jobs.
// Interface provides constructor for informer and lister for jobs
type
JobInformer
interface
{
Informer
()
cache
.
SharedIndexInformer
Lister
()
batchinternallisters
.
JobLister
}
type
jobInformer
struct
{
*
sharedInformerFactory
}
// Informer checks whether jobInformer exists in sharedInformerFactory and if not, it creates new informer of type
// jobInformer and connects it to sharedInformerFactory
func
(
f
*
jobInformer
)
Informer
()
cache
.
SharedIndexInformer
{
f
.
lock
.
Lock
()
defer
f
.
lock
.
Unlock
()
informerType
:=
reflect
.
TypeOf
(
&
batch
.
Job
{})
informer
,
exists
:=
f
.
informers
[
informerType
]
if
exists
{
return
informer
}
informer
=
NewJobInformer
(
f
.
client
,
f
.
defaultResync
)
f
.
informers
[
informerType
]
=
informer
return
informer
}
// NewJobInformer returns a SharedIndexInformer that lists and watches all jobs
func
NewJobInformer
(
client
clientset
.
Interface
,
resyncPeriod
time
.
Duration
)
cache
.
SharedIndexInformer
{
sharedIndexInformer
:=
cache
.
NewSharedIndexInformer
(
&
cache
.
ListWatch
{
ListFunc
:
func
(
options
api
.
ListOptions
)
(
runtime
.
Object
,
error
)
{
return
client
.
Batch
()
.
Jobs
(
api
.
NamespaceAll
)
.
List
(
options
)
},
WatchFunc
:
func
(
options
api
.
ListOptions
)
(
watch
.
Interface
,
error
)
{
return
client
.
Batch
()
.
Jobs
(
api
.
NamespaceAll
)
.
Watch
(
options
)
},
},
&
batch
.
Job
{},
resyncPeriod
,
cache
.
Indexers
{
cache
.
NamespaceIndex
:
cache
.
MetaNamespaceIndexFunc
},
)
return
sharedIndexInformer
}
// Lister returns lister for jobInformer
func
(
f
*
jobInformer
)
Lister
()
batchinternallisters
.
JobLister
{
informer
:=
f
.
Informer
()
return
batchinternallisters
.
NewJobLister
(
informer
.
GetIndexer
())
}
pkg/controller/informers/factory.go
View file @
8c923faf
...
...
@@ -54,6 +54,8 @@ type SharedInformerFactory interface {
Roles
()
RoleInformer
StorageClasses
()
StorageClassInformer
Jobs
()
JobInformer
}
type
sharedInformerFactory
struct
{
...
...
@@ -158,3 +160,8 @@ func (f *sharedInformerFactory) LimitRanges() LimitRangeInformer {
func
(
f
*
sharedInformerFactory
)
StorageClasses
()
StorageClassInformer
{
return
&
storageClassInformer
{
sharedInformerFactory
:
f
}
}
// Jobs returns a SharedIndexInformer that lists and watches all storage jobs
func
(
f
*
sharedInformerFactory
)
Jobs
()
JobInformer
{
return
&
jobInformer
{
sharedInformerFactory
:
f
}
}
pkg/controller/informers/generic.go
View file @
8c923faf
...
...
@@ -21,6 +21,7 @@ import (
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/apis/batch"
"k8s.io/kubernetes/pkg/apis/extensions"
"k8s.io/kubernetes/pkg/apis/rbac"
"k8s.io/kubernetes/pkg/client/cache"
...
...
@@ -67,6 +68,9 @@ func (f *sharedInformerFactory) ForResource(resource unversioned.GroupResource)
return
&
genericInformer
{
resource
:
resource
,
informer
:
f
.
RoleBindings
()
.
Informer
()},
nil
case
rbac
.
Resource
(
"roles"
)
:
return
&
genericInformer
{
resource
:
resource
,
informer
:
f
.
Roles
()
.
Informer
()},
nil
case
batch
.
Resource
(
"jobs"
)
:
return
&
genericInformer
{
resource
:
resource
,
informer
:
f
.
Jobs
()
.
Informer
()},
nil
}
return
nil
,
fmt
.
Errorf
(
"no informer found for %v"
,
resource
)
...
...
pkg/controller/job/BUILD
View file @
8c923faf
...
...
@@ -20,21 +20,20 @@ go_library(
tags = ["automanaged"],
deps = [
"//pkg/api:go_default_library",
"//pkg/api/errors:go_default_library",
"//pkg/api/unversioned:go_default_library",
"//pkg/apis/batch:go_default_library",
"//pkg/client/cache:go_default_library",
"//pkg/client/clientset_generated/internalclientset:go_default_library",
"//pkg/client/clientset_generated/internalclientset/typed/core/internalversion:go_default_library",
"//pkg/client/listers/batch/internalversion:go_default_library",
"//pkg/client/record:go_default_library",
"//pkg/controller:go_default_library",
"//pkg/controller/informers:go_default_library",
"//pkg/controller/replication:go_default_library",
"//pkg/runtime:go_default_library",
"//pkg/util/metrics:go_default_library",
"//pkg/util/runtime:go_default_library",
"//pkg/util/wait:go_default_library",
"//pkg/util/workqueue:go_default_library",
"//pkg/watch:go_default_library",
"//vendor:github.com/golang/glog",
],
)
...
...
@@ -52,11 +51,13 @@ go_test(
"//pkg/api/unversioned:go_default_library",
"//pkg/apimachinery/registered:go_default_library",
"//pkg/apis/batch:go_default_library",
"//pkg/client/cache:go_default_library",
"//pkg/client/clientset_generated/internalclientset:go_default_library",
"//pkg/client/clientset_generated/internalclientset/fake:go_default_library",
"//pkg/client/restclient:go_default_library",
"//pkg/client/testing/core:go_default_library",
"//pkg/controller:go_default_library",
"//pkg/controller/informers:go_default_library",
"//pkg/util/rand:go_default_library",
"//pkg/util/wait:go_default_library",
"//pkg/watch:go_default_library",
...
...
pkg/controller/job/jobcontroller.go
View file @
8c923faf
...
...
@@ -24,21 +24,20 @@ import (
"time"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/errors"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/apis/batch"
"k8s.io/kubernetes/pkg/client/cache"
clientset
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
unversionedcore
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion"
batchinternallisters
"k8s.io/kubernetes/pkg/client/listers/batch/internalversion"
"k8s.io/kubernetes/pkg/client/record"
"k8s.io/kubernetes/pkg/controller"
"k8s.io/kubernetes/pkg/controller/informers"
replicationcontroller
"k8s.io/kubernetes/pkg/controller/replication"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util/metrics"
utilruntime
"k8s.io/kubernetes/pkg/util/runtime"
"k8s.io/kubernetes/pkg/util/wait"
"k8s.io/kubernetes/pkg/util/workqueue"
"k8s.io/kubernetes/pkg/watch"
"github.com/golang/glog"
)
...
...
@@ -47,27 +46,21 @@ type JobController struct {
kubeClient
clientset
.
Interface
podControl
controller
.
PodControlInterface
// internalPodInformer is used to hold a personal informer. If we're using
// a normal shared informer, then the informer will be started for us. If
// we have a personal informer, we must start it ourselves. If you start
// the controller using NewJobController(passing SharedInformer), this
// will be null
internalPodInformer
cache
.
SharedInformer
// To allow injection of updateJobStatus for testing.
updateHandler
func
(
job
*
batch
.
Job
)
error
syncHandler
func
(
jobKey
string
)
error
// podStoreSynced returns true if the pod store has been synced at least once.
// Added as a member to the struct to allow injection for testing.
podStoreSynced
func
()
bool
podStoreSynced
cache
.
InformerSynced
// jobStoreSynced returns true if the job store has been synced at least once.
// Added as a member to the struct to allow injection for testing.
jobStoreSynced
cache
.
InformerSynced
// A TTLCache of pod creates/deletes each rc expects to see
expectations
controller
.
ControllerExpectationsInterface
// A store of job, populated by the jobController
jobStore
cache
.
StoreToJobLister
// Watches changes to all jobs
jobController
*
cache
.
Controller
// A store of jobs
jobLister
batchinternallisters
.
JobLister
// A store of pods, populated by the podController
podStore
cache
.
StoreToPodLister
...
...
@@ -78,7 +71,7 @@ type JobController struct {
recorder
record
.
EventRecorder
}
func
NewJobController
(
podInformer
cache
.
SharedIndexInformer
,
kubeClient
clientset
.
Interface
)
*
JobController
{
func
NewJobController
(
podInformer
cache
.
SharedIndexInformer
,
jobInformer
informers
.
JobInformer
,
kubeClient
clientset
.
Interface
)
*
JobController
{
eventBroadcaster
:=
record
.
NewBroadcaster
()
eventBroadcaster
.
StartLogging
(
glog
.
Infof
)
// TODO: remove the wrapper when every clients have moved to use the clientset.
...
...
@@ -99,19 +92,7 @@ func NewJobController(podInformer cache.SharedIndexInformer, kubeClient clientse
recorder
:
eventBroadcaster
.
NewRecorder
(
api
.
EventSource
{
Component
:
"job-controller"
}),
}
jm
.
jobStore
.
Store
,
jm
.
jobController
=
cache
.
NewInformer
(
&
cache
.
ListWatch
{
ListFunc
:
func
(
options
api
.
ListOptions
)
(
runtime
.
Object
,
error
)
{
return
jm
.
kubeClient
.
Batch
()
.
Jobs
(
api
.
NamespaceAll
)
.
List
(
options
)
},
WatchFunc
:
func
(
options
api
.
ListOptions
)
(
watch
.
Interface
,
error
)
{
return
jm
.
kubeClient
.
Batch
()
.
Jobs
(
api
.
NamespaceAll
)
.
Watch
(
options
)
},
},
&
batch
.
Job
{},
// TODO: Can we have much longer period here?
replicationcontroller
.
FullControllerResyncPeriod
,
cache
.
ResourceEventHandlerFuncs
{
jobInformer
.
Informer
()
.
AddEventHandler
(
cache
.
ResourceEventHandlerFuncs
{
AddFunc
:
jm
.
enqueueController
,
UpdateFunc
:
func
(
old
,
cur
interface
{})
{
if
job
:=
cur
.
(
*
batch
.
Job
);
!
IsJobFinished
(
job
)
{
...
...
@@ -119,8 +100,9 @@ func NewJobController(podInformer cache.SharedIndexInformer, kubeClient clientse
}
},
DeleteFunc
:
jm
.
enqueueController
,
},
)
})
jm
.
jobLister
=
jobInformer
.
Lister
()
jm
.
jobStoreSynced
=
jobInformer
.
Informer
()
.
HasSynced
podInformer
.
AddEventHandler
(
cache
.
ResourceEventHandlerFuncs
{
AddFunc
:
jm
.
addPod
,
...
...
@@ -135,39 +117,26 @@ func NewJobController(podInformer cache.SharedIndexInformer, kubeClient clientse
return
jm
}
func
NewJobControllerFromClient
(
kubeClient
clientset
.
Interface
,
resyncPeriod
controller
.
ResyncPeriodFunc
)
*
JobController
{
podInformer
:=
informers
.
NewPodInformer
(
kubeClient
,
resyncPeriod
())
jm
:=
NewJobController
(
podInformer
,
kubeClient
)
jm
.
internalPodInformer
=
podInformer
return
jm
}
// Run the main goroutine responsible for watching and syncing jobs.
func
(
jm
*
JobController
)
Run
(
workers
int
,
stopCh
<-
chan
struct
{})
{
defer
utilruntime
.
HandleCrash
()
defer
jm
.
queue
.
ShutDown
()
if
!
cache
.
WaitForCacheSync
(
stopCh
,
jm
.
podStoreSynced
)
{
if
!
cache
.
WaitForCacheSync
(
stopCh
,
jm
.
podStoreSynced
,
jm
.
jobStoreSynced
)
{
return
}
go
jm
.
jobController
.
Run
(
stopCh
)
for
i
:=
0
;
i
<
workers
;
i
++
{
go
wait
.
Until
(
jm
.
worker
,
time
.
Second
,
stopCh
)
}
if
jm
.
internalPodInformer
!=
nil
{
go
jm
.
internalPodInformer
.
Run
(
stopCh
)
}
<-
stopCh
glog
.
Infof
(
"Shutting down Job Manager"
)
}
// getPodJob returns the job managing the given pod.
func
(
jm
*
JobController
)
getPodJob
(
pod
*
api
.
Pod
)
*
batch
.
Job
{
jobs
,
err
:=
jm
.
job
Store
.
GetPodJobs
(
pod
)
jobs
,
err
:=
jm
.
job
Lister
.
GetPodJobs
(
pod
)
if
err
!=
nil
{
glog
.
V
(
4
)
.
Infof
(
"No jobs found for pod %v, job controller will avoid syncing"
,
pod
.
Name
)
return
nil
...
...
@@ -315,16 +284,23 @@ func (jm *JobController) syncJob(key string) error {
glog
.
V
(
4
)
.
Infof
(
"Finished syncing job %q (%v)"
,
key
,
time
.
Now
()
.
Sub
(
startTime
))
}()
obj
,
exists
,
err
:=
jm
.
jobStore
.
Store
.
GetByKey
(
key
)
if
!
exists
{
ns
,
name
,
err
:=
cache
.
SplitMetaNamespaceKey
(
key
)
if
err
!=
nil
{
return
err
}
if
len
(
ns
)
==
0
||
len
(
name
)
==
0
{
return
fmt
.
Errorf
(
"invalid job key %q: either namespace or name is missing"
,
key
)
}
sharedJob
,
err
:=
jm
.
jobLister
.
Jobs
(
ns
)
.
Get
(
name
)
if
err
!=
nil
{
if
errors
.
IsNotFound
(
err
)
{
glog
.
V
(
4
)
.
Infof
(
"Job has been deleted: %v"
,
key
)
jm
.
expectations
.
DeleteExpectations
(
key
)
return
nil
}
if
err
!=
nil
{
return
err
}
job
:=
*
obj
.
(
*
batch
.
Job
)
job
:=
*
sharedJob
// Check the expectations of the job before counting active pods, otherwise a new pod can sneak in
// and update the expectations after we've retrieved active pods from the store. If a new pod enters
...
...
pkg/controller/job/jobcontroller_test.go
View file @
8c923faf
...
...
@@ -18,7 +18,6 @@ package job
import
(
"fmt"
"reflect"
"testing"
"time"
...
...
@@ -26,11 +25,13 @@ import (
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/apimachinery/registered"
"k8s.io/kubernetes/pkg/apis/batch"
"k8s.io/kubernetes/pkg/client/cache"
clientset
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake"
"k8s.io/kubernetes/pkg/client/restclient"
"k8s.io/kubernetes/pkg/client/testing/core"
"k8s.io/kubernetes/pkg/controller"
"k8s.io/kubernetes/pkg/controller/informers"
"k8s.io/kubernetes/pkg/util/rand"
"k8s.io/kubernetes/pkg/util/wait"
"k8s.io/kubernetes/pkg/watch"
...
...
@@ -86,6 +87,13 @@ func getKey(job *batch.Job, t *testing.T) string {
}
}
func
newJobControllerFromClient
(
kubeClient
clientset
.
Interface
,
resyncPeriod
controller
.
ResyncPeriodFunc
)
(
*
JobController
,
informers
.
SharedInformerFactory
)
{
sharedInformers
:=
informers
.
NewSharedInformerFactory
(
kubeClient
,
resyncPeriod
())
jm
:=
NewJobController
(
sharedInformers
.
Pods
()
.
Informer
(),
sharedInformers
.
Jobs
(),
kubeClient
)
return
jm
,
sharedInformers
}
// create count pods with the given phase for the given job
func
newPodList
(
count
int32
,
status
api
.
PodPhase
,
job
*
batch
.
Job
)
[]
api
.
Pod
{
pods
:=
[]
api
.
Pod
{}
...
...
@@ -220,10 +228,11 @@ func TestControllerSyncJob(t *testing.T) {
for
name
,
tc
:=
range
testCases
{
// job manager setup
clientset
:=
clientset
.
NewForConfigOrDie
(
&
restclient
.
Config
{
Host
:
""
,
ContentConfig
:
restclient
.
ContentConfig
{
GroupVersion
:
&
registered
.
GroupOrDie
(
api
.
GroupName
)
.
GroupVersion
}})
manager
:=
N
ewJobControllerFromClient
(
clientset
,
controller
.
NoResyncPeriodFunc
)
manager
,
sharedInformerFactory
:=
n
ewJobControllerFromClient
(
clientset
,
controller
.
NoResyncPeriodFunc
)
fakePodControl
:=
controller
.
FakePodControl
{
Err
:
tc
.
podControllerError
}
manager
.
podControl
=
&
fakePodControl
manager
.
podStoreSynced
=
alwaysReady
manager
.
jobStoreSynced
=
alwaysReady
var
actual
*
batch
.
Job
manager
.
updateHandler
=
func
(
job
*
batch
.
Job
)
error
{
actual
=
job
...
...
@@ -236,18 +245,19 @@ func TestControllerSyncJob(t *testing.T) {
now
:=
unversioned
.
Now
()
job
.
DeletionTimestamp
=
&
now
}
manager
.
jobStore
.
Store
.
Add
(
job
)
sharedInformerFactory
.
Jobs
()
.
Informer
()
.
GetIndexer
()
.
Add
(
job
)
podIndexer
:=
sharedInformerFactory
.
Pods
()
.
Informer
()
.
GetIndexer
()
for
_
,
pod
:=
range
newPodList
(
tc
.
pendingPods
,
api
.
PodPending
,
job
)
{
manager
.
podStore
.
Indexer
.
Add
(
&
pod
)
pod
Indexer
.
Add
(
&
pod
)
}
for
_
,
pod
:=
range
newPodList
(
tc
.
activePods
,
api
.
PodRunning
,
job
)
{
manager
.
podStore
.
Indexer
.
Add
(
&
pod
)
pod
Indexer
.
Add
(
&
pod
)
}
for
_
,
pod
:=
range
newPodList
(
tc
.
succeededPods
,
api
.
PodSucceeded
,
job
)
{
manager
.
podStore
.
Indexer
.
Add
(
&
pod
)
pod
Indexer
.
Add
(
&
pod
)
}
for
_
,
pod
:=
range
newPodList
(
tc
.
failedPods
,
api
.
PodFailed
,
job
)
{
manager
.
podStore
.
Indexer
.
Add
(
&
pod
)
pod
Indexer
.
Add
(
&
pod
)
}
// run
...
...
@@ -322,10 +332,11 @@ func TestSyncJobPastDeadline(t *testing.T) {
for
name
,
tc
:=
range
testCases
{
// job manager setup
clientset
:=
clientset
.
NewForConfigOrDie
(
&
restclient
.
Config
{
Host
:
""
,
ContentConfig
:
restclient
.
ContentConfig
{
GroupVersion
:
&
registered
.
GroupOrDie
(
api
.
GroupName
)
.
GroupVersion
}})
manager
:=
N
ewJobControllerFromClient
(
clientset
,
controller
.
NoResyncPeriodFunc
)
manager
,
sharedInformerFactory
:=
n
ewJobControllerFromClient
(
clientset
,
controller
.
NoResyncPeriodFunc
)
fakePodControl
:=
controller
.
FakePodControl
{}
manager
.
podControl
=
&
fakePodControl
manager
.
podStoreSynced
=
alwaysReady
manager
.
jobStoreSynced
=
alwaysReady
var
actual
*
batch
.
Job
manager
.
updateHandler
=
func
(
job
*
batch
.
Job
)
error
{
actual
=
job
...
...
@@ -337,15 +348,16 @@ func TestSyncJobPastDeadline(t *testing.T) {
job
.
Spec
.
ActiveDeadlineSeconds
=
&
tc
.
activeDeadlineSeconds
start
:=
unversioned
.
Unix
(
unversioned
.
Now
()
.
Time
.
Unix
()
-
tc
.
startTime
,
0
)
job
.
Status
.
StartTime
=
&
start
manager
.
jobStore
.
Store
.
Add
(
job
)
sharedInformerFactory
.
Jobs
()
.
Informer
()
.
GetIndexer
()
.
Add
(
job
)
podIndexer
:=
sharedInformerFactory
.
Pods
()
.
Informer
()
.
GetIndexer
()
for
_
,
pod
:=
range
newPodList
(
tc
.
activePods
,
api
.
PodRunning
,
job
)
{
manager
.
podStore
.
Indexer
.
Add
(
&
pod
)
pod
Indexer
.
Add
(
&
pod
)
}
for
_
,
pod
:=
range
newPodList
(
tc
.
succeededPods
,
api
.
PodSucceeded
,
job
)
{
manager
.
podStore
.
Indexer
.
Add
(
&
pod
)
pod
Indexer
.
Add
(
&
pod
)
}
for
_
,
pod
:=
range
newPodList
(
tc
.
failedPods
,
api
.
PodFailed
,
job
)
{
manager
.
podStore
.
Indexer
.
Add
(
&
pod
)
pod
Indexer
.
Add
(
&
pod
)
}
// run
...
...
@@ -392,10 +404,11 @@ func getCondition(job *batch.Job, condition batch.JobConditionType) bool {
func
TestSyncPastDeadlineJobFinished
(
t
*
testing
.
T
)
{
clientset
:=
clientset
.
NewForConfigOrDie
(
&
restclient
.
Config
{
Host
:
""
,
ContentConfig
:
restclient
.
ContentConfig
{
GroupVersion
:
&
registered
.
GroupOrDie
(
api
.
GroupName
)
.
GroupVersion
}})
manager
:=
N
ewJobControllerFromClient
(
clientset
,
controller
.
NoResyncPeriodFunc
)
manager
,
sharedInformerFactory
:=
n
ewJobControllerFromClient
(
clientset
,
controller
.
NoResyncPeriodFunc
)
fakePodControl
:=
controller
.
FakePodControl
{}
manager
.
podControl
=
&
fakePodControl
manager
.
podStoreSynced
=
alwaysReady
manager
.
jobStoreSynced
=
alwaysReady
var
actual
*
batch
.
Job
manager
.
updateHandler
=
func
(
job
*
batch
.
Job
)
error
{
actual
=
job
...
...
@@ -408,7 +421,7 @@ func TestSyncPastDeadlineJobFinished(t *testing.T) {
start
:=
unversioned
.
Unix
(
unversioned
.
Now
()
.
Time
.
Unix
()
-
15
,
0
)
job
.
Status
.
StartTime
=
&
start
job
.
Status
.
Conditions
=
append
(
job
.
Status
.
Conditions
,
newCondition
(
batch
.
JobFailed
,
"DeadlineExceeded"
,
"Job was active longer than specified deadline"
))
manager
.
jobStore
.
Store
.
Add
(
job
)
sharedInformerFactory
.
Jobs
()
.
Informer
()
.
GetIndexer
()
.
Add
(
job
)
err
:=
manager
.
syncJob
(
getKey
(
job
,
t
))
if
err
!=
nil
{
t
.
Errorf
(
"Unexpected error when syncing jobs %v"
,
err
)
...
...
@@ -426,23 +439,23 @@ func TestSyncPastDeadlineJobFinished(t *testing.T) {
func
TestSyncJobComplete
(
t
*
testing
.
T
)
{
clientset
:=
clientset
.
NewForConfigOrDie
(
&
restclient
.
Config
{
Host
:
""
,
ContentConfig
:
restclient
.
ContentConfig
{
GroupVersion
:
&
registered
.
GroupOrDie
(
api
.
GroupName
)
.
GroupVersion
}})
manager
:=
N
ewJobControllerFromClient
(
clientset
,
controller
.
NoResyncPeriodFunc
)
manager
,
sharedInformerFactory
:=
n
ewJobControllerFromClient
(
clientset
,
controller
.
NoResyncPeriodFunc
)
fakePodControl
:=
controller
.
FakePodControl
{}
manager
.
podControl
=
&
fakePodControl
manager
.
podStoreSynced
=
alwaysReady
manager
.
jobStoreSynced
=
alwaysReady
job
:=
newJob
(
1
,
1
)
job
.
Status
.
Conditions
=
append
(
job
.
Status
.
Conditions
,
newCondition
(
batch
.
JobComplete
,
""
,
""
))
manager
.
jobStore
.
Store
.
Add
(
job
)
sharedInformerFactory
.
Jobs
()
.
Informer
()
.
GetIndexer
()
.
Add
(
job
)
err
:=
manager
.
syncJob
(
getKey
(
job
,
t
))
if
err
!=
nil
{
t
.
Fatalf
(
"Unexpected error when syncing jobs %v"
,
err
)
}
uncastJob
,
_
,
err
:=
manager
.
jobStore
.
Store
.
Get
(
job
)
actual
,
err
:=
manager
.
jobLister
.
Jobs
(
job
.
Namespace
)
.
Get
(
job
.
Name
)
if
err
!=
nil
{
t
.
Fatalf
(
"Unexpected error when trying to get job from the store: %v"
,
err
)
}
actual
:=
uncastJob
.
(
*
batch
.
Job
)
// Verify that after syncing a complete job, the conditions are the same.
if
got
,
expected
:=
len
(
actual
.
Status
.
Conditions
),
1
;
got
!=
expected
{
t
.
Fatalf
(
"Unexpected job status conditions amount; expected %d, got %d"
,
expected
,
got
)
...
...
@@ -451,10 +464,11 @@ func TestSyncJobComplete(t *testing.T) {
func
TestSyncJobDeleted
(
t
*
testing
.
T
)
{
clientset
:=
clientset
.
NewForConfigOrDie
(
&
restclient
.
Config
{
Host
:
""
,
ContentConfig
:
restclient
.
ContentConfig
{
GroupVersion
:
&
registered
.
GroupOrDie
(
api
.
GroupName
)
.
GroupVersion
}})
manager
:=
N
ewJobControllerFromClient
(
clientset
,
controller
.
NoResyncPeriodFunc
)
manager
,
_
:=
n
ewJobControllerFromClient
(
clientset
,
controller
.
NoResyncPeriodFunc
)
fakePodControl
:=
controller
.
FakePodControl
{}
manager
.
podControl
=
&
fakePodControl
manager
.
podStoreSynced
=
alwaysReady
manager
.
jobStoreSynced
=
alwaysReady
manager
.
updateHandler
=
func
(
job
*
batch
.
Job
)
error
{
return
nil
}
job
:=
newJob
(
2
,
2
)
err
:=
manager
.
syncJob
(
getKey
(
job
,
t
))
...
...
@@ -471,17 +485,18 @@ func TestSyncJobDeleted(t *testing.T) {
func
TestSyncJobUpdateRequeue
(
t
*
testing
.
T
)
{
clientset
:=
clientset
.
NewForConfigOrDie
(
&
restclient
.
Config
{
Host
:
""
,
ContentConfig
:
restclient
.
ContentConfig
{
GroupVersion
:
&
registered
.
GroupOrDie
(
api
.
GroupName
)
.
GroupVersion
}})
manager
:=
N
ewJobControllerFromClient
(
clientset
,
controller
.
NoResyncPeriodFunc
)
manager
,
sharedInformerFactory
:=
n
ewJobControllerFromClient
(
clientset
,
controller
.
NoResyncPeriodFunc
)
fakePodControl
:=
controller
.
FakePodControl
{}
manager
.
podControl
=
&
fakePodControl
manager
.
podStoreSynced
=
alwaysReady
manager
.
jobStoreSynced
=
alwaysReady
updateError
:=
fmt
.
Errorf
(
"Update error"
)
manager
.
updateHandler
=
func
(
job
*
batch
.
Job
)
error
{
manager
.
queue
.
AddRateLimited
(
getKey
(
job
,
t
))
return
updateError
}
job
:=
newJob
(
2
,
2
)
manager
.
jobStore
.
Store
.
Add
(
job
)
sharedInformerFactory
.
Jobs
()
.
Informer
()
.
GetIndexer
()
.
Add
(
job
)
err
:=
manager
.
syncJob
(
getKey
(
job
,
t
))
if
err
==
nil
||
err
!=
updateError
{
t
.
Errorf
(
"Expected error %v when syncing jobs, got %v"
,
updateError
,
err
)
...
...
@@ -496,8 +511,9 @@ func TestSyncJobUpdateRequeue(t *testing.T) {
func
TestJobPodLookup
(
t
*
testing
.
T
)
{
clientset
:=
clientset
.
NewForConfigOrDie
(
&
restclient
.
Config
{
Host
:
""
,
ContentConfig
:
restclient
.
ContentConfig
{
GroupVersion
:
&
registered
.
GroupOrDie
(
api
.
GroupName
)
.
GroupVersion
}})
manager
:=
N
ewJobControllerFromClient
(
clientset
,
controller
.
NoResyncPeriodFunc
)
manager
,
sharedInformerFactory
:=
n
ewJobControllerFromClient
(
clientset
,
controller
.
NoResyncPeriodFunc
)
manager
.
podStoreSynced
=
alwaysReady
manager
.
jobStoreSynced
=
alwaysReady
testCases
:=
[]
struct
{
job
*
batch
.
Job
pod
*
api
.
Pod
...
...
@@ -560,7 +576,7 @@ func TestJobPodLookup(t *testing.T) {
},
}
for
_
,
tc
:=
range
testCases
{
manager
.
jobStore
.
Add
(
tc
.
job
)
sharedInformerFactory
.
Jobs
()
.
Informer
()
.
GetIndexer
()
.
Add
(
tc
.
job
)
if
job
:=
manager
.
getPodJob
(
tc
.
pod
);
job
!=
nil
{
if
tc
.
expectedName
!=
job
.
Name
{
t
.
Errorf
(
"Got job %+v expected %+v"
,
job
.
Name
,
tc
.
expectedName
)
...
...
@@ -586,23 +602,25 @@ func (fe FakeJobExpectations) SatisfiedExpectations(controllerKey string) bool {
// and checking expectations.
func
TestSyncJobExpectations
(
t
*
testing
.
T
)
{
clientset
:=
clientset
.
NewForConfigOrDie
(
&
restclient
.
Config
{
Host
:
""
,
ContentConfig
:
restclient
.
ContentConfig
{
GroupVersion
:
&
registered
.
GroupOrDie
(
api
.
GroupName
)
.
GroupVersion
}})
manager
:=
N
ewJobControllerFromClient
(
clientset
,
controller
.
NoResyncPeriodFunc
)
manager
,
sharedInformerFactory
:=
n
ewJobControllerFromClient
(
clientset
,
controller
.
NoResyncPeriodFunc
)
fakePodControl
:=
controller
.
FakePodControl
{}
manager
.
podControl
=
&
fakePodControl
manager
.
podStoreSynced
=
alwaysReady
manager
.
jobStoreSynced
=
alwaysReady
manager
.
updateHandler
=
func
(
job
*
batch
.
Job
)
error
{
return
nil
}
job
:=
newJob
(
2
,
2
)
manager
.
jobStore
.
Store
.
Add
(
job
)
sharedInformerFactory
.
Jobs
()
.
Informer
()
.
GetIndexer
()
.
Add
(
job
)
pods
:=
newPodList
(
2
,
api
.
PodPending
,
job
)
manager
.
podStore
.
Indexer
.
Add
(
&
pods
[
0
])
podIndexer
:=
sharedInformerFactory
.
Pods
()
.
Informer
()
.
GetIndexer
()
podIndexer
.
Add
(
&
pods
[
0
])
manager
.
expectations
=
FakeJobExpectations
{
controller
.
NewControllerExpectations
(),
true
,
func
()
{
// If we check active pods before checking expectataions, the job
// will create a new replica because it doesn't see this pod, but
// has fulfilled its expectations.
manager
.
podStore
.
Indexer
.
Add
(
&
pods
[
1
])
pod
Indexer
.
Add
(
&
pods
[
1
])
},
}
manager
.
syncJob
(
getKey
(
job
,
t
))
...
...
@@ -618,8 +636,9 @@ func TestWatchJobs(t *testing.T) {
clientset
:=
fake
.
NewSimpleClientset
()
fakeWatch
:=
watch
.
NewFake
()
clientset
.
PrependWatchReactor
(
"jobs"
,
core
.
DefaultWatchReactor
(
fakeWatch
,
nil
))
manager
:=
N
ewJobControllerFromClient
(
clientset
,
controller
.
NoResyncPeriodFunc
)
manager
,
sharedInformerFactory
:=
n
ewJobControllerFromClient
(
clientset
,
controller
.
NoResyncPeriodFunc
)
manager
.
podStoreSynced
=
alwaysReady
manager
.
jobStoreSynced
=
alwaysReady
var
testJob
batch
.
Job
received
:=
make
(
chan
struct
{})
...
...
@@ -627,28 +646,30 @@ func TestWatchJobs(t *testing.T) {
// The update sent through the fakeWatcher should make its way into the workqueue,
// and eventually into the syncHandler.
manager
.
syncHandler
=
func
(
key
string
)
error
{
obj
,
exists
,
err
:=
manager
.
jobStore
.
Store
.
GetBy
Key
(
key
)
if
!
exists
||
err
!=
nil
{
t
.
Errorf
(
"E
xpected to find job under key %v"
,
key
)
defer
close
(
received
)
ns
,
name
,
err
:=
cache
.
SplitMetaNamespace
Key
(
key
)
if
err
!=
nil
{
t
.
Errorf
(
"E
rror getting namespace/name from key %v: %v"
,
key
,
err
)
}
job
,
ok
:=
obj
.
(
*
batch
.
Job
)
if
!
ok
{
t
.
Fatalf
(
"unexpected type: %v %#v"
,
reflect
.
TypeOf
(
obj
),
obj
)
job
,
err
:=
manager
.
jobLister
.
Jobs
(
ns
)
.
Get
(
name
)
if
err
!=
nil
||
job
==
nil
{
t
.
Errorf
(
"Expected to find job under key %v: %v"
,
key
,
err
)
return
nil
}
if
!
api
.
Semantic
.
DeepDerivative
(
*
job
,
testJob
)
{
t
.
Errorf
(
"Expected %#v, but got %#v"
,
testJob
,
*
job
)
}
close
(
received
)
return
nil
}
// Start only the job watcher and the workqueue, send a watch event,
// and make sure it hits the sync method.
stopCh
:=
make
(
chan
struct
{})
defer
close
(
stopCh
)
sharedInformerFactory
.
Start
(
stopCh
)
go
manager
.
Run
(
1
,
stopCh
)
// We're sending new job to see if it reaches syncHandler.
testJob
.
Namespace
=
"bar"
testJob
.
Name
=
"foo"
fakeWatch
.
Add
(
&
testJob
)
t
.
Log
(
"Waiting for job to reach syncHandler"
)
...
...
@@ -660,26 +681,23 @@ func TestWatchPods(t *testing.T) {
clientset
:=
fake
.
NewSimpleClientset
(
testJob
)
fakeWatch
:=
watch
.
NewFake
()
clientset
.
PrependWatchReactor
(
"pods"
,
core
.
DefaultWatchReactor
(
fakeWatch
,
nil
))
manager
:=
N
ewJobControllerFromClient
(
clientset
,
controller
.
NoResyncPeriodFunc
)
manager
,
sharedInformerFactory
:=
n
ewJobControllerFromClient
(
clientset
,
controller
.
NoResyncPeriodFunc
)
manager
.
podStoreSynced
=
alwaysReady
manager
.
jobStoreSynced
=
alwaysReady
// Put one job and one pod into the store
manager
.
jobStore
.
Store
.
Add
(
testJob
)
sharedInformerFactory
.
Jobs
()
.
Informer
()
.
GetIndexer
()
.
Add
(
testJob
)
received
:=
make
(
chan
struct
{})
// The pod update sent through the fakeWatcher should figure out the managing job and
// send it into the syncHandler.
manager
.
syncHandler
=
func
(
key
string
)
error
{
obj
,
exists
,
err
:=
manager
.
jobStore
.
Store
.
GetByKey
(
key
)
if
!
exists
||
err
!=
nil
{
t
.
Errorf
(
"Expected to find job under key %v"
,
key
)
close
(
received
)
return
nil
ns
,
name
,
err
:=
cache
.
SplitMetaNamespaceKey
(
key
)
if
err
!=
nil
{
t
.
Errorf
(
"Error getting namespace/name from key %v: %v"
,
key
,
err
)
}
job
,
ok
:=
obj
.
(
*
batch
.
Job
)
if
!
ok
{
t
.
Errorf
(
"unexpected type: %v %#v"
,
reflect
.
TypeOf
(
obj
),
obj
)
close
(
received
)
return
nil
job
,
err
:=
manager
.
jobLister
.
Jobs
(
ns
)
.
Get
(
name
)
if
err
!=
nil
{
t
.
Errorf
(
"Expected to find job under key %v: %v"
,
key
,
err
)
}
if
!
api
.
Semantic
.
DeepDerivative
(
job
,
testJob
)
{
t
.
Errorf
(
"
\n
Expected %#v,
\n
but got %#v"
,
testJob
,
job
)
...
...
@@ -693,7 +711,7 @@ func TestWatchPods(t *testing.T) {
// and make sure it hits the sync method for the right job.
stopCh
:=
make
(
chan
struct
{})
defer
close
(
stopCh
)
go
manager
.
internalPodInformer
.
Run
(
stopCh
)
go
sharedInformerFactory
.
Pods
()
.
Informer
()
.
Run
(
stopCh
)
go
wait
.
Until
(
manager
.
worker
,
10
*
time
.
Millisecond
,
stopCh
)
pods
:=
newPodList
(
1
,
api
.
PodRunning
,
testJob
)
...
...
test/test_owners.csv
View file @
8c923faf
...
...
@@ -535,6 +535,7 @@ k8s.io/kubernetes/pkg/auth/handlers,liggitt,0
k8s.io/kubernetes/pkg/client/cache,xiang90,1
k8s.io/kubernetes/pkg/client/chaosclient,deads2k,1
k8s.io/kubernetes/pkg/client/leaderelection,xiang90,1
k8s.io/kubernetes/pkg/client/listers/batch/internalversion,mqliang,0
k8s.io/kubernetes/pkg/client/record,karlkfi,1
k8s.io/kubernetes/pkg/client/restclient,kargakis,1
k8s.io/kubernetes/pkg/client/retry,caesarxuchao,1
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment