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
b34f03e9
Commit
b34f03e9
authored
Mar 07, 2017
by
deads2k
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add controller to autoregister APIServices
parent
0a6d82d8
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
287 additions
and
0 deletions
+287
-0
autoregister_controller.go
...r/pkg/controllers/autoregister/autoregister_controller.go
+249
-0
autoregister_controller_test.go
.../controllers/autoregister/autoregister_controller_test.go
+0
-0
BUILD
vendor/BUILD
+38
-0
No files found.
staging/src/k8s.io/kube-aggregator/pkg/controllers/autoregister/autoregister_controller.go
0 → 100644
View file @
b34f03e9
/*
Copyright 2017 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
autoregister
import
(
"fmt"
"reflect"
"sync"
"time"
"github.com/golang/glog"
apierrors
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/conversion"
utilruntime
"k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/tools/cache"
"k8s.io/client-go/util/workqueue"
"k8s.io/kube-aggregator/pkg/apis/apiregistration"
apiregistrationclient
"k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/typed/apiregistration/internalversion"
informers
"k8s.io/kube-aggregator/pkg/client/informers/internalversion/apiregistration/internalversion"
listers
"k8s.io/kube-aggregator/pkg/client/listers/apiregistration/internalversion"
)
const
(
AutoRegisterManagedLabel
=
"kube-aggregator.kubernetes.io/automanaged"
)
var
(
cloner
=
conversion
.
NewCloner
()
)
// AutoAPIServiceRegistration is an interface which callers can re-declare locally and properly cast to for
// adding and removing APIServices
type
AutoAPIServiceRegistration
interface
{
// AddAPIServiceToSync adds an API service to auto-register.
AddAPIServiceToSync
(
in
*
apiregistration
.
APIService
)
// RemoveAPIServiceToSync removes an API service to auto-register.
RemoveAPIServiceToSync
(
name
string
)
}
// autoRegisterController is used to keep a particular set of APIServices present in the API. It is useful
// for cases where you want to auto-register APIs like TPRs or groups from the core kube-apiserver
type
autoRegisterController
struct
{
apiServiceLister
listers
.
APIServiceLister
apiServiceSynced
cache
.
InformerSynced
apiServiceClient
apiregistrationclient
.
APIServicesGetter
apiServicesToSyncLock
sync
.
RWMutex
apiServicesToSync
map
[
string
]
*
apiregistration
.
APIService
syncHandler
func
(
apiServiceName
string
)
error
// queue is where incoming work is placed to de-dup and to allow "easy" rate limited requeues on errors
queue
workqueue
.
RateLimitingInterface
}
func
NewAutoRegisterController
(
apiServiceInformer
informers
.
APIServiceInformer
,
apiServiceClient
apiregistrationclient
.
APIServicesGetter
)
*
autoRegisterController
{
c
:=
&
autoRegisterController
{
apiServiceLister
:
apiServiceInformer
.
Lister
(),
apiServiceSynced
:
apiServiceInformer
.
Informer
()
.
HasSynced
,
apiServiceClient
:
apiServiceClient
,
apiServicesToSync
:
map
[
string
]
*
apiregistration
.
APIService
{},
queue
:
workqueue
.
NewNamedRateLimitingQueue
(
workqueue
.
DefaultControllerRateLimiter
(),
"autoregister"
),
}
c
.
syncHandler
=
c
.
checkAPIService
apiServiceInformer
.
Informer
()
.
AddEventHandler
(
cache
.
ResourceEventHandlerFuncs
{
AddFunc
:
func
(
obj
interface
{})
{
cast
:=
obj
.
(
*
apiregistration
.
APIService
)
c
.
queue
.
Add
(
cast
.
Name
)
},
UpdateFunc
:
func
(
_
,
obj
interface
{})
{
cast
:=
obj
.
(
*
apiregistration
.
APIService
)
c
.
queue
.
Add
(
cast
.
Name
)
},
DeleteFunc
:
func
(
obj
interface
{})
{
cast
,
ok
:=
obj
.
(
*
apiregistration
.
APIService
)
if
!
ok
{
tombstone
,
ok
:=
obj
.
(
cache
.
DeletedFinalStateUnknown
)
if
!
ok
{
glog
.
V
(
2
)
.
Infof
(
"Couldn't get object from tombstone %#v"
,
obj
)
return
}
cast
,
ok
=
tombstone
.
Obj
.
(
*
apiregistration
.
APIService
)
if
!
ok
{
glog
.
V
(
2
)
.
Infof
(
"Tombstone contained unexpected object: %#v"
,
obj
)
return
}
}
c
.
queue
.
Add
(
cast
.
Name
)
},
})
return
c
}
func
(
c
*
autoRegisterController
)
Run
(
threadiness
int
,
stopCh
chan
struct
{})
{
// don't let panics crash the process
defer
utilruntime
.
HandleCrash
()
// make sure the work queue is shutdown which will trigger workers to end
defer
c
.
queue
.
ShutDown
()
glog
.
Infof
(
"Starting autoregister controller"
)
defer
glog
.
Infof
(
"Shutting down autoregister controller"
)
// wait for your secondary caches to fill before starting your work
if
!
cache
.
WaitForCacheSync
(
stopCh
,
c
.
apiServiceSynced
)
{
return
}
// start up your worker threads based on threadiness. Some controllers have multiple kinds of workers
for
i
:=
0
;
i
<
threadiness
;
i
++
{
// runWorker will loop until "something bad" happens. The .Until will then rekick the worker
// after one second
go
wait
.
Until
(
c
.
runWorker
,
time
.
Second
,
stopCh
)
}
// wait until we're told to stop
<-
stopCh
}
func
(
c
*
autoRegisterController
)
runWorker
()
{
// hot loop until we're told to stop. processNextWorkItem will automatically wait until there's work
// available, so we don't worry about secondary waits
for
c
.
processNextWorkItem
()
{
}
}
// processNextWorkItem deals with one key off the queue. It returns false when it's time to quit.
func
(
c
*
autoRegisterController
)
processNextWorkItem
()
bool
{
// pull the next work item from queue. It should be a key we use to lookup something in a cache
key
,
quit
:=
c
.
queue
.
Get
()
if
quit
{
return
false
}
// you always have to indicate to the queue that you've completed a piece of work
defer
c
.
queue
.
Done
(
key
)
// do your work on the key. This method will contains your "do stuff" logic
err
:=
c
.
syncHandler
(
key
.
(
string
))
if
err
==
nil
{
// if you had no error, tell the queue to stop tracking history for your key. This will
// reset things like failure counts for per-item rate limiting
c
.
queue
.
Forget
(
key
)
return
true
}
// there was a failure so be sure to report it. This method allows for pluggable error handling
// which can be used for things like cluster-monitoring
utilruntime
.
HandleError
(
fmt
.
Errorf
(
"%v failed with : %v"
,
key
,
err
))
// since we failed, we should requeue the item to work on later. This method will add a backoff
// to avoid hotlooping on particular items (they're probably still not going to work right away)
// and overall controller protection (everything I've done is broken, this controller needs to
// calm down or it can starve other useful work) cases.
c
.
queue
.
AddRateLimited
(
key
)
return
true
}
func
(
c
*
autoRegisterController
)
checkAPIService
(
name
string
)
error
{
desired
:=
c
.
GetAPIServiceToSync
(
name
)
curr
,
err
:=
c
.
apiServiceLister
.
Get
(
name
)
switch
{
// we had a real error, just return it
case
err
!=
nil
&&
!
apierrors
.
IsNotFound
(
err
)
:
return
err
// we don't have an entry and we don't want one
case
apierrors
.
IsNotFound
(
err
)
&&
desired
==
nil
:
return
nil
// we don't have an entry and we do want one
case
apierrors
.
IsNotFound
(
err
)
&&
desired
!=
nil
:
_
,
err
:=
c
.
apiServiceClient
.
APIServices
()
.
Create
(
desired
)
return
err
// we aren't trying to manage this APIService. If the user removes the label, he's taken over management himself
case
curr
.
Labels
[
AutoRegisterManagedLabel
]
!=
"true"
:
return
nil
// we have a spurious APIService that we're managing, delete it
case
desired
==
nil
:
return
c
.
apiServiceClient
.
APIServices
()
.
Delete
(
curr
.
Name
,
nil
)
// if the specs already match, nothing for us to do
case
reflect
.
DeepEqual
(
curr
.
Spec
,
desired
.
Spec
)
:
return
nil
}
// we have an entry and we have a desired, now we deconflict. Only a few fields matter.
apiService
:=
&
apiregistration
.
APIService
{}
if
err
:=
apiregistration
.
DeepCopy_apiregistration_APIService
(
curr
,
apiService
,
cloner
);
err
!=
nil
{
return
err
}
apiService
.
Spec
=
desired
.
Spec
_
,
err
=
c
.
apiServiceClient
.
APIServices
()
.
Update
(
apiService
)
return
err
}
func
(
c
*
autoRegisterController
)
GetAPIServiceToSync
(
name
string
)
*
apiregistration
.
APIService
{
c
.
apiServicesToSyncLock
.
RLock
()
defer
c
.
apiServicesToSyncLock
.
RUnlock
()
return
c
.
apiServicesToSync
[
name
]
}
func
(
c
*
autoRegisterController
)
AddAPIServiceToSync
(
in
*
apiregistration
.
APIService
)
{
c
.
apiServicesToSyncLock
.
Lock
()
defer
c
.
apiServicesToSyncLock
.
Unlock
()
apiService
:=
&
apiregistration
.
APIService
{}
if
err
:=
apiregistration
.
DeepCopy_apiregistration_APIService
(
in
,
apiService
,
cloner
);
err
!=
nil
{
// this shouldn't happen
utilruntime
.
HandleError
(
err
)
return
}
if
apiService
.
Labels
==
nil
{
apiService
.
Labels
=
map
[
string
]
string
{}
}
apiService
.
Labels
[
AutoRegisterManagedLabel
]
=
"true"
c
.
apiServicesToSync
[
apiService
.
Name
]
=
apiService
c
.
queue
.
Add
(
apiService
.
Name
)
}
func
(
c
*
autoRegisterController
)
RemoveAPIServiceToSync
(
name
string
)
{
c
.
apiServicesToSyncLock
.
Lock
()
defer
c
.
apiServicesToSyncLock
.
Unlock
()
delete
(
c
.
apiServicesToSync
,
name
)
c
.
queue
.
Add
(
name
)
}
staging/src/k8s.io/kube-aggregator/pkg/controllers/autoregister/autoregister_controller_test.go
0 → 100644
View file @
b34f03e9
This diff is collapsed.
Click to expand it.
vendor/BUILD
View file @
b34f03e9
...
...
@@ -16312,3 +16312,41 @@ filegroup(
srcs = [":package-srcs"],
tags = ["automanaged"],
)
go_test(
name = "k8s.io/kube-aggregator/pkg/controllers/autoregister_test",
srcs = ["k8s.io/kube-aggregator/pkg/controllers/autoregister/autoregister_controller_test.go"],
library = ":k8s.io/kube-aggregator/pkg/controllers/autoregister",
tags = ["automanaged"],
deps = [
"//vendor:k8s.io/apimachinery/pkg/api/errors",
"//vendor:k8s.io/apimachinery/pkg/api/meta",
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
"//vendor:k8s.io/apimachinery/pkg/util/wait",
"//vendor:k8s.io/apimachinery/pkg/watch",
"//vendor:k8s.io/client-go/testing",
"//vendor:k8s.io/kube-aggregator/pkg/apis/apiregistration",
"//vendor:k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset",
"//vendor:k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/fake",
"//vendor:k8s.io/kube-aggregator/pkg/client/informers/internalversion",
],
)
go_library(
name = "k8s.io/kube-aggregator/pkg/controllers/autoregister",
srcs = ["k8s.io/kube-aggregator/pkg/controllers/autoregister/autoregister_controller.go"],
tags = ["automanaged"],
deps = [
"//vendor:github.com/golang/glog",
"//vendor:k8s.io/apimachinery/pkg/api/errors",
"//vendor:k8s.io/apimachinery/pkg/conversion",
"//vendor:k8s.io/apimachinery/pkg/util/runtime",
"//vendor:k8s.io/apimachinery/pkg/util/wait",
"//vendor:k8s.io/client-go/tools/cache",
"//vendor:k8s.io/client-go/util/workqueue",
"//vendor:k8s.io/kube-aggregator/pkg/apis/apiregistration",
"//vendor:k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/typed/apiregistration/internalversion",
"//vendor:k8s.io/kube-aggregator/pkg/client/informers/internalversion/apiregistration/internalversion",
"//vendor:k8s.io/kube-aggregator/pkg/client/listers/apiregistration/internalversion",
],
)
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