1
0
Fork 0
forked from barak/tarpoon

Add glide.yaml and vendor deps

This commit is contained in:
Dalton Hubble 2016-12-03 22:43:32 -08:00
parent db918f12ad
commit 5b3d5e81bd
18880 changed files with 5166045 additions and 1 deletions

View file

@ -0,0 +1,76 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_binary",
"go_library",
"go_test",
"cgo_library",
)
go_library(
name = "go_default_library",
srcs = [
"doc.go",
"serviceaccounts_controller.go",
"tokengetter.go",
"tokens_controller.go",
],
tags = ["automanaged"],
deps = [
"//pkg/api:go_default_library",
"//pkg/api/errors:go_default_library",
"//pkg/api/meta:go_default_library",
"//pkg/api/v1:go_default_library",
"//pkg/client/cache:go_default_library",
"//pkg/client/clientset_generated/release_1_5:go_default_library",
"//pkg/client/retry:go_default_library",
"//pkg/controller/informers:go_default_library",
"//pkg/fields:go_default_library",
"//pkg/registry/core/secret:go_default_library",
"//pkg/registry/core/secret/etcd:go_default_library",
"//pkg/registry/core/serviceaccount:go_default_library",
"//pkg/registry/core/serviceaccount/etcd:go_default_library",
"//pkg/registry/generic:go_default_library",
"//pkg/runtime:go_default_library",
"//pkg/serviceaccount:go_default_library",
"//pkg/storage/storagebackend:go_default_library",
"//pkg/types:go_default_library",
"//pkg/util/errors:go_default_library",
"//pkg/util/metrics:go_default_library",
"//pkg/util/runtime:go_default_library",
"//pkg/util/sets: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",
],
)
go_test(
name = "go_default_test",
srcs = [
"serviceaccounts_controller_test.go",
"tokens_controller_test.go",
],
library = "go_default_library",
tags = ["automanaged"],
deps = [
"//pkg/api:go_default_library",
"//pkg/api/errors:go_default_library",
"//pkg/api/v1:go_default_library",
"//pkg/client/cache:go_default_library",
"//pkg/client/clientset_generated/release_1_5/fake:go_default_library",
"//pkg/client/testing/core:go_default_library",
"//pkg/controller:go_default_library",
"//pkg/controller/informers:go_default_library",
"//pkg/runtime:go_default_library",
"//pkg/runtime/schema:go_default_library",
"//pkg/util/rand:go_default_library",
"//pkg/util/sets:go_default_library",
"//vendor:github.com/davecgh/go-spew/spew",
"//vendor:github.com/golang/glog",
],
)

View file

@ -0,0 +1,19 @@
/*
Copyright 2014 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 serviceaccount provides implementations
// to manage service accounts and service account tokens
package serviceaccount // import "k8s.io/kubernetes/pkg/controller/serviceaccount"

View file

@ -0,0 +1,226 @@
/*
Copyright 2014 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 serviceaccount
import (
"fmt"
"time"
"github.com/golang/glog"
apierrs "k8s.io/kubernetes/pkg/api/errors"
"k8s.io/kubernetes/pkg/api/meta"
"k8s.io/kubernetes/pkg/api/v1"
"k8s.io/kubernetes/pkg/client/cache"
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_5"
"k8s.io/kubernetes/pkg/controller/informers"
utilerrors "k8s.io/kubernetes/pkg/util/errors"
"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"
)
// nameIndexFunc is an index function that indexes based on an object's name
func nameIndexFunc(obj interface{}) ([]string, error) {
meta, err := meta.Accessor(obj)
if err != nil {
return []string{""}, fmt.Errorf("object has no meta: %v", err)
}
return []string{meta.GetName()}, nil
}
// ServiceAccountsControllerOptions contains options for running a ServiceAccountsController
type ServiceAccountsControllerOptions struct {
// ServiceAccounts is the list of service accounts to ensure exist in every namespace
ServiceAccounts []v1.ServiceAccount
// ServiceAccountResync is the interval between full resyncs of ServiceAccounts.
// If non-zero, all service accounts will be re-listed this often.
// Otherwise, re-list will be delayed as long as possible (until the watch is closed or times out).
ServiceAccountResync time.Duration
// NamespaceResync is the interval between full resyncs of Namespaces.
// If non-zero, all namespaces will be re-listed this often.
// Otherwise, re-list will be delayed as long as possible (until the watch is closed or times out).
NamespaceResync time.Duration
}
func DefaultServiceAccountsControllerOptions() ServiceAccountsControllerOptions {
return ServiceAccountsControllerOptions{
ServiceAccounts: []v1.ServiceAccount{
{ObjectMeta: v1.ObjectMeta{Name: "default"}},
},
}
}
// NewServiceAccountsController returns a new *ServiceAccountsController.
func NewServiceAccountsController(saInformer informers.ServiceAccountInformer, nsInformer informers.NamespaceInformer, cl clientset.Interface, options ServiceAccountsControllerOptions) *ServiceAccountsController {
e := &ServiceAccountsController{
client: cl,
serviceAccountsToEnsure: options.ServiceAccounts,
queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "serviceaccount"),
}
if cl != nil && cl.Core().RESTClient().GetRateLimiter() != nil {
metrics.RegisterMetricAndTrackRateLimiterUsage("serviceaccount_controller", cl.Core().RESTClient().GetRateLimiter())
}
saInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
DeleteFunc: e.serviceAccountDeleted,
})
nsInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
AddFunc: e.namespaceAdded,
UpdateFunc: e.namespaceUpdated,
})
e.saSynced = saInformer.Informer().HasSynced
e.saLister = saInformer.Lister()
e.nsSynced = nsInformer.Informer().HasSynced
e.nsLister = nsInformer.Lister()
e.syncHandler = e.syncNamespace
return e
}
// ServiceAccountsController manages ServiceAccount objects inside Namespaces
type ServiceAccountsController struct {
client clientset.Interface
serviceAccountsToEnsure []v1.ServiceAccount
// To allow injection for testing.
syncHandler func(key string) error
saLister *cache.StoreToServiceAccountLister
nsLister *cache.IndexerToNamespaceLister
saSynced cache.InformerSynced
nsSynced cache.InformerSynced
queue workqueue.RateLimitingInterface
}
func (c *ServiceAccountsController) Run(workers int, stopCh <-chan struct{}) {
defer utilruntime.HandleCrash()
defer c.queue.ShutDown()
glog.Infof("Starting ServiceAccount controller")
if !cache.WaitForCacheSync(stopCh, c.saSynced) {
return
}
for i := 0; i < workers; i++ {
go wait.Until(c.runWorker, time.Second, stopCh)
}
<-stopCh
glog.Infof("Shutting down ServiceAccount controller")
}
// serviceAccountDeleted reacts to a ServiceAccount deletion by recreating a default ServiceAccount in the namespace if needed
func (c *ServiceAccountsController) serviceAccountDeleted(obj interface{}) {
sa, ok := obj.(*v1.ServiceAccount)
if !ok {
tombstone, ok := obj.(cache.DeletedFinalStateUnknown)
if !ok {
utilruntime.HandleError(fmt.Errorf("Couldn't get object from tombstone %#v", obj))
return
}
sa, ok = tombstone.Obj.(*v1.ServiceAccount)
if !ok {
utilruntime.HandleError(fmt.Errorf("Tombstone contained object that is not a ServiceAccount %#v", obj))
return
}
}
c.queue.Add(sa.Namespace)
}
// namespaceAdded reacts to a Namespace creation by creating a default ServiceAccount object
func (c *ServiceAccountsController) namespaceAdded(obj interface{}) {
namespace := obj.(*v1.Namespace)
c.queue.Add(namespace.Name)
}
// namespaceUpdated reacts to a Namespace update (or re-list) by creating a default ServiceAccount in the namespace if needed
func (c *ServiceAccountsController) namespaceUpdated(oldObj interface{}, newObj interface{}) {
newNamespace := newObj.(*v1.Namespace)
c.queue.Add(newNamespace.Name)
}
func (c *ServiceAccountsController) runWorker() {
for c.processNextWorkItem() {
}
}
// processNextWorkItem deals with one key off the queue. It returns false when it's time to quit.
func (c *ServiceAccountsController) processNextWorkItem() bool {
key, quit := c.queue.Get()
if quit {
return false
}
defer c.queue.Done(key)
err := c.syncHandler(key.(string))
if err == nil {
c.queue.Forget(key)
return true
}
utilruntime.HandleError(fmt.Errorf("%v failed with : %v", key, err))
c.queue.AddRateLimited(key)
return true
}
func (c *ServiceAccountsController) syncNamespace(key string) error {
startTime := time.Now()
defer func() {
glog.V(4).Infof("Finished syncing namespace %q (%v)", key, time.Now().Sub(startTime))
}()
ns, err := c.nsLister.Get(key)
if apierrs.IsNotFound(err) {
return nil
}
if err != nil {
return err
}
if ns.Status.Phase != v1.NamespaceActive {
// If namespace is not active, we shouldn't try to create anything
return nil
}
createFailures := []error{}
for i := range c.serviceAccountsToEnsure {
sa := c.serviceAccountsToEnsure[i]
switch _, err := c.saLister.ServiceAccounts(ns.Name).Get(sa.Name); {
case err == nil:
continue
case apierrs.IsNotFound(err):
case err != nil:
return err
}
// this is only safe because we never read it and we always write it
// TODO eliminate this once the fake client can handle creation without NS
sa.Namespace = ns.Name
if _, err := c.client.Core().ServiceAccounts(ns.Name).Create(&sa); err != nil && !apierrs.IsAlreadyExists(err) {
createFailures = append(createFailures, err)
}
}
return utilerrors.Flatten(utilerrors.NewAggregate(createFailures))
}

View file

@ -0,0 +1,231 @@
/*
Copyright 2014 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 serviceaccount
import (
"testing"
"time"
"k8s.io/kubernetes/pkg/api/v1"
"k8s.io/kubernetes/pkg/client/cache"
"k8s.io/kubernetes/pkg/client/clientset_generated/release_1_5/fake"
"k8s.io/kubernetes/pkg/client/testing/core"
"k8s.io/kubernetes/pkg/controller"
"k8s.io/kubernetes/pkg/controller/informers"
"k8s.io/kubernetes/pkg/util/sets"
)
type serverResponse struct {
statusCode int
obj interface{}
}
func TestServiceAccountCreation(t *testing.T) {
ns := v1.NamespaceDefault
defaultName := "default"
managedName := "managed"
activeNS := &v1.Namespace{
ObjectMeta: v1.ObjectMeta{Name: ns},
Status: v1.NamespaceStatus{
Phase: v1.NamespaceActive,
},
}
terminatingNS := &v1.Namespace{
ObjectMeta: v1.ObjectMeta{Name: ns},
Status: v1.NamespaceStatus{
Phase: v1.NamespaceTerminating,
},
}
defaultServiceAccount := &v1.ServiceAccount{
ObjectMeta: v1.ObjectMeta{
Name: defaultName,
Namespace: ns,
ResourceVersion: "1",
},
}
managedServiceAccount := &v1.ServiceAccount{
ObjectMeta: v1.ObjectMeta{
Name: managedName,
Namespace: ns,
ResourceVersion: "1",
},
}
unmanagedServiceAccount := &v1.ServiceAccount{
ObjectMeta: v1.ObjectMeta{
Name: "other-unmanaged",
Namespace: ns,
ResourceVersion: "1",
},
}
testcases := map[string]struct {
ExistingNamespace *v1.Namespace
ExistingServiceAccounts []*v1.ServiceAccount
AddedNamespace *v1.Namespace
UpdatedNamespace *v1.Namespace
DeletedServiceAccount *v1.ServiceAccount
ExpectCreatedServiceAccounts []string
}{
"new active namespace missing serviceaccounts": {
ExistingServiceAccounts: []*v1.ServiceAccount{},
AddedNamespace: activeNS,
ExpectCreatedServiceAccounts: sets.NewString(defaultName, managedName).List(),
},
"new active namespace missing serviceaccount": {
ExistingServiceAccounts: []*v1.ServiceAccount{managedServiceAccount},
AddedNamespace: activeNS,
ExpectCreatedServiceAccounts: []string{defaultName},
},
"new active namespace with serviceaccounts": {
ExistingServiceAccounts: []*v1.ServiceAccount{defaultServiceAccount, managedServiceAccount},
AddedNamespace: activeNS,
ExpectCreatedServiceAccounts: []string{},
},
"new terminating namespace": {
ExistingServiceAccounts: []*v1.ServiceAccount{},
AddedNamespace: terminatingNS,
ExpectCreatedServiceAccounts: []string{},
},
"updated active namespace missing serviceaccounts": {
ExistingServiceAccounts: []*v1.ServiceAccount{},
UpdatedNamespace: activeNS,
ExpectCreatedServiceAccounts: sets.NewString(defaultName, managedName).List(),
},
"updated active namespace missing serviceaccount": {
ExistingServiceAccounts: []*v1.ServiceAccount{defaultServiceAccount},
UpdatedNamespace: activeNS,
ExpectCreatedServiceAccounts: []string{managedName},
},
"updated active namespace with serviceaccounts": {
ExistingServiceAccounts: []*v1.ServiceAccount{defaultServiceAccount, managedServiceAccount},
UpdatedNamespace: activeNS,
ExpectCreatedServiceAccounts: []string{},
},
"updated terminating namespace": {
ExistingServiceAccounts: []*v1.ServiceAccount{},
UpdatedNamespace: terminatingNS,
ExpectCreatedServiceAccounts: []string{},
},
"deleted serviceaccount without namespace": {
DeletedServiceAccount: defaultServiceAccount,
ExpectCreatedServiceAccounts: []string{},
},
"deleted serviceaccount with active namespace": {
ExistingServiceAccounts: []*v1.ServiceAccount{managedServiceAccount},
ExistingNamespace: activeNS,
DeletedServiceAccount: defaultServiceAccount,
ExpectCreatedServiceAccounts: []string{defaultName},
},
"deleted serviceaccount with terminating namespace": {
ExistingNamespace: terminatingNS,
DeletedServiceAccount: defaultServiceAccount,
ExpectCreatedServiceAccounts: []string{},
},
"deleted unmanaged serviceaccount with active namespace": {
ExistingServiceAccounts: []*v1.ServiceAccount{defaultServiceAccount, managedServiceAccount},
ExistingNamespace: activeNS,
DeletedServiceAccount: unmanagedServiceAccount,
ExpectCreatedServiceAccounts: []string{},
},
"deleted unmanaged serviceaccount with terminating namespace": {
ExistingNamespace: terminatingNS,
DeletedServiceAccount: unmanagedServiceAccount,
ExpectCreatedServiceAccounts: []string{},
},
}
for k, tc := range testcases {
client := fake.NewSimpleClientset(defaultServiceAccount, managedServiceAccount)
informers := informers.NewSharedInformerFactory(fake.NewSimpleClientset(), nil, controller.NoResyncPeriodFunc())
options := DefaultServiceAccountsControllerOptions()
options.ServiceAccounts = []v1.ServiceAccount{
{ObjectMeta: v1.ObjectMeta{Name: defaultName}},
{ObjectMeta: v1.ObjectMeta{Name: managedName}},
}
controller := NewServiceAccountsController(informers.ServiceAccounts(), informers.Namespaces(), client, options)
controller.saLister = &cache.StoreToServiceAccountLister{Indexer: cache.NewIndexer(cache.DeletionHandlingMetaNamespaceKeyFunc, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc})}
controller.nsLister = &cache.IndexerToNamespaceLister{Indexer: cache.NewIndexer(cache.DeletionHandlingMetaNamespaceKeyFunc, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc})}
controller.saSynced = alwaysReady
controller.nsSynced = alwaysReady
syncCalls := make(chan struct{})
controller.syncHandler = func(key string) error {
err := controller.syncNamespace(key)
if err != nil {
t.Logf("%s: %v", k, err)
}
syncCalls <- struct{}{}
return err
}
stopCh := make(chan struct{})
defer close(stopCh)
go controller.Run(1, stopCh)
if tc.ExistingNamespace != nil {
controller.nsLister.Add(tc.ExistingNamespace)
}
for _, s := range tc.ExistingServiceAccounts {
controller.saLister.Indexer.Add(s)
}
if tc.AddedNamespace != nil {
controller.nsLister.Add(tc.AddedNamespace)
controller.namespaceAdded(tc.AddedNamespace)
}
if tc.UpdatedNamespace != nil {
controller.nsLister.Add(tc.UpdatedNamespace)
controller.namespaceUpdated(nil, tc.UpdatedNamespace)
}
if tc.DeletedServiceAccount != nil {
controller.serviceAccountDeleted(tc.DeletedServiceAccount)
}
// wait to be called
select {
case <-syncCalls:
case <-time.After(10 * time.Second):
t.Errorf("%s: took too long", k)
}
actions := client.Actions()
if len(tc.ExpectCreatedServiceAccounts) != len(actions) {
t.Errorf("%s: Expected to create accounts %#v. Actual actions were: %#v", k, tc.ExpectCreatedServiceAccounts, actions)
continue
}
for i, expectedName := range tc.ExpectCreatedServiceAccounts {
action := actions[i]
if !action.Matches("create", "serviceaccounts") {
t.Errorf("%s: Unexpected action %s", k, action)
break
}
createdAccount := action.(core.CreateAction).GetObject().(*v1.ServiceAccount)
if createdAccount.Name != expectedName {
t.Errorf("%s: Expected %s to be created, got %s", k, expectedName, createdAccount.Name)
}
}
}
}
var alwaysReady = func() bool { return true }

View file

@ -0,0 +1,92 @@
/*
Copyright 2014 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 serviceaccount
import (
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/v1"
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_5"
"k8s.io/kubernetes/pkg/registry/core/secret"
secretetcd "k8s.io/kubernetes/pkg/registry/core/secret/etcd"
serviceaccountregistry "k8s.io/kubernetes/pkg/registry/core/serviceaccount"
serviceaccountetcd "k8s.io/kubernetes/pkg/registry/core/serviceaccount/etcd"
"k8s.io/kubernetes/pkg/registry/generic"
"k8s.io/kubernetes/pkg/serviceaccount"
"k8s.io/kubernetes/pkg/storage/storagebackend"
)
// clientGetter implements ServiceAccountTokenGetter using a clientset.Interface
type clientGetter struct {
client clientset.Interface
}
// NewGetterFromClient returns a ServiceAccountTokenGetter that
// uses the specified client to retrieve service accounts and secrets.
// The client should NOT authenticate using a service account token
// the returned getter will be used to retrieve, or recursion will result.
func NewGetterFromClient(c clientset.Interface) serviceaccount.ServiceAccountTokenGetter {
return clientGetter{c}
}
func (c clientGetter) GetServiceAccount(namespace, name string) (*v1.ServiceAccount, error) {
return c.client.Core().ServiceAccounts(namespace).Get(name)
}
func (c clientGetter) GetSecret(namespace, name string) (*v1.Secret, error) {
return c.client.Core().Secrets(namespace).Get(name)
}
// registryGetter implements ServiceAccountTokenGetter using a service account and secret registry
type registryGetter struct {
serviceAccounts serviceaccountregistry.Registry
secrets secret.Registry
}
// NewGetterFromRegistries returns a ServiceAccountTokenGetter that
// uses the specified registries to retrieve service accounts and secrets.
func NewGetterFromRegistries(serviceAccounts serviceaccountregistry.Registry, secrets secret.Registry) serviceaccount.ServiceAccountTokenGetter {
return &registryGetter{serviceAccounts, secrets}
}
func (r *registryGetter) GetServiceAccount(namespace, name string) (*v1.ServiceAccount, error) {
ctx := api.WithNamespace(api.NewContext(), namespace)
internalServiceAccount, err := r.serviceAccounts.GetServiceAccount(ctx, name)
if err != nil {
return nil, err
}
v1ServiceAccount := v1.ServiceAccount{}
err = v1.Convert_api_ServiceAccount_To_v1_ServiceAccount(internalServiceAccount, &v1ServiceAccount, nil)
return &v1ServiceAccount, err
}
func (r *registryGetter) GetSecret(namespace, name string) (*v1.Secret, error) {
ctx := api.WithNamespace(api.NewContext(), namespace)
internalSecret, err := r.secrets.GetSecret(ctx, name)
if err != nil {
return nil, err
}
v1Secret := v1.Secret{}
err = v1.Convert_api_Secret_To_v1_Secret(internalSecret, &v1Secret, nil)
return &v1Secret, err
}
// NewGetterFromStorageInterface returns a ServiceAccountTokenGetter that
// uses the specified storage to retrieve service accounts and secrets.
func NewGetterFromStorageInterface(config *storagebackend.Config, saPrefix, secretPrefix string) serviceaccount.ServiceAccountTokenGetter {
return NewGetterFromRegistries(
serviceaccountregistry.NewRegistry(serviceaccountetcd.NewREST(generic.RESTOptions{StorageConfig: config, Decorator: generic.UndecoratedStorage, ResourcePrefix: saPrefix})),
secret.NewRegistry(secretetcd.NewREST(generic.RESTOptions{StorageConfig: config, Decorator: generic.UndecoratedStorage, ResourcePrefix: secretPrefix})),
)
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff