func TestEtcdWatchEndpoints(t *testing.T) { ctx := api.NewDefaultContext() fakeClient := tools.NewFakeEtcdClient(t) registry := NewTestEtcdRegistryWithPods(fakeClient) watching, err := registry.endpoints.WatchEndpoints( ctx, labels.Everything(), fields.SelectorFromSet(fields.Set{"name": "foo"}), "1", ) if err != nil { t.Fatalf("unexpected error: %v", err) } fakeClient.WaitForWatchCompletion() select { case _, ok := <-watching.ResultChan(): if !ok { t.Errorf("watching channel should be open") } default: } fakeClient.WatchInjectError <- nil if _, ok := <-watching.ResultChan(); ok { t.Errorf("watching channel should be closed") } watching.Stop() }
// NewTokensController returns a new *TokensController. func NewTokensController(cl client.Interface, options TokensControllerOptions) *TokensController { e := &TokensController{ client: cl, token: options.TokenGenerator, } e.serviceAccounts, e.serviceAccountController = framework.NewIndexerInformer( &cache.ListWatch{ ListFunc: func() (runtime.Object, error) { return e.client.ServiceAccounts(api.NamespaceAll).List(labels.Everything(), fields.Everything()) }, WatchFunc: func(rv string) (watch.Interface, error) { return e.client.ServiceAccounts(api.NamespaceAll).Watch(labels.Everything(), fields.Everything(), rv) }, }, &api.ServiceAccount{}, options.ServiceAccountResync, framework.ResourceEventHandlerFuncs{ AddFunc: e.serviceAccountAdded, UpdateFunc: e.serviceAccountUpdated, DeleteFunc: e.serviceAccountDeleted, }, cache.Indexers{"namespace": cache.MetaNamespaceIndexFunc}, ) tokenSelector := fields.SelectorFromSet(map[string]string{client.SecretType: string(api.SecretTypeServiceAccountToken)}) e.secrets, e.secretController = framework.NewIndexerInformer( &cache.ListWatch{ ListFunc: func() (runtime.Object, error) { return e.client.Secrets(api.NamespaceAll).List(labels.Everything(), tokenSelector) }, WatchFunc: func(rv string) (watch.Interface, error) { return e.client.Secrets(api.NamespaceAll).Watch(labels.Everything(), tokenSelector, rv) }, }, &api.Secret{}, options.SecretResync, framework.ResourceEventHandlerFuncs{ AddFunc: e.secretAdded, UpdateFunc: e.secretUpdated, DeleteFunc: e.secretDeleted, }, cache.Indexers{"namespace": cache.MetaNamespaceIndexFunc}, ) e.serviceAccountsSynced = e.serviceAccountController.HasSynced e.secretsSynced = e.secretController.HasSynced return e }
// NewServiceAccountsController returns a new *ServiceAccountsController. func NewServiceAccountsController(cl client.Interface, options ServiceAccountsControllerOptions) *ServiceAccountsController { e := &ServiceAccountsController{ client: cl, names: options.Names, } accountSelector := fields.Everything() if len(options.Names) == 1 { // If we're maintaining a single account, we can scope the accounts we watch to just that name accountSelector = fields.SelectorFromSet(map[string]string{client.ObjectNameField: options.Names.List()[0]}) } e.serviceAccounts, e.serviceAccountController = framework.NewIndexerInformer( &cache.ListWatch{ ListFunc: func() (runtime.Object, error) { return e.client.ServiceAccounts(api.NamespaceAll).List(labels.Everything(), accountSelector) }, WatchFunc: func(rv string) (watch.Interface, error) { return e.client.ServiceAccounts(api.NamespaceAll).Watch(labels.Everything(), accountSelector, rv) }, }, &api.ServiceAccount{}, options.ServiceAccountResync, framework.ResourceEventHandlerFuncs{ DeleteFunc: e.serviceAccountDeleted, }, cache.Indexers{"namespace": cache.MetaNamespaceIndexFunc}, ) e.namespaces, e.namespaceController = framework.NewIndexerInformer( &cache.ListWatch{ ListFunc: func() (runtime.Object, error) { return e.client.Namespaces().List(labels.Everything(), fields.Everything()) }, WatchFunc: func(rv string) (watch.Interface, error) { return e.client.Namespaces().Watch(labels.Everything(), fields.Everything(), rv) }, }, &api.Namespace{}, options.NamespaceResync, framework.ResourceEventHandlerFuncs{ AddFunc: e.namespaceAdded, UpdateFunc: e.namespaceUpdated, }, cache.Indexers{"name": nameIndexFunc}, ) return e }
// NewServiceAccount returns an admission.Interface implementation which limits admission of Pod CREATE requests based on the pod's ServiceAccount: // 1. If the pod does not specify a ServiceAccount, it sets the pod's ServiceAccount to "default" // 2. It ensures the ServiceAccount referenced by the pod exists // 3. If LimitSecretReferences is true, it rejects the pod if the pod references Secret objects which the pod's ServiceAccount does not reference // 4. If the pod does not contain any ImagePullSecrets, the ImagePullSecrets of the service account are added. // 5. If MountServiceAccountToken is true, it adds a VolumeMount with the pod's ServiceAccount's api token secret to containers func NewServiceAccount(cl client.Interface) *serviceAccount { serviceAccountsIndexer, serviceAccountsReflector := cache.NewNamespaceKeyedIndexerAndReflector( &cache.ListWatch{ ListFunc: func() (runtime.Object, error) { return cl.ServiceAccounts(api.NamespaceAll).List(labels.Everything(), fields.Everything()) }, WatchFunc: func(resourceVersion string) (watch.Interface, error) { return cl.ServiceAccounts(api.NamespaceAll).Watch(labels.Everything(), fields.Everything(), resourceVersion) }, }, &api.ServiceAccount{}, 0, ) tokenSelector := fields.SelectorFromSet(map[string]string{client.SecretType: string(api.SecretTypeServiceAccountToken)}) secretsIndexer, secretsReflector := cache.NewNamespaceKeyedIndexerAndReflector( &cache.ListWatch{ ListFunc: func() (runtime.Object, error) { return cl.Secrets(api.NamespaceAll).List(labels.Everything(), tokenSelector) }, WatchFunc: func(resourceVersion string) (watch.Interface, error) { return cl.Secrets(api.NamespaceAll).Watch(labels.Everything(), tokenSelector, resourceVersion) }, }, &api.Secret{}, 0, ) return &serviceAccount{ Handler: admission.NewHandler(admission.Create), // TODO: enable this once we've swept secret usage to account for adding secret references to service accounts LimitSecretReferences: false, // Auto mount service account API token secrets MountServiceAccountToken: true, client: cl, serviceAccounts: serviceAccountsIndexer, serviceAccountsReflector: serviceAccountsReflector, secrets: secretsIndexer, secretsReflector: secretsReflector, } }
func (d *ServiceAccountDescriber) Describe(namespace, name string) (string, error) { c := d.ServiceAccounts(namespace) serviceAccount, err := c.Get(name) if err != nil { return "", err } tokens := []api.Secret{} tokenSelector := fields.SelectorFromSet(map[string]string{client.SecretType: string(api.SecretTypeServiceAccountToken)}) secrets, err := d.Secrets(namespace).List(labels.Everything(), tokenSelector) if err == nil { for _, s := range secrets.Items { name, _ := s.Annotations[api.ServiceAccountNameKey] uid, _ := s.Annotations[api.ServiceAccountUIDKey] if name == serviceAccount.Name && uid == string(serviceAccount.UID) { tokens = append(tokens, s) } } } return describeServiceAccount(serviceAccount, tokens) }
func TestEtcdWatchServicesBadSelector(t *testing.T) { ctx := api.NewDefaultContext() fakeClient := tools.NewFakeEtcdClient(t) registry := NewTestEtcdRegistry(fakeClient) _, err := registry.WatchServices( ctx, labels.Everything(), fields.SelectorFromSet(fields.Set{"Field.Selector": "foo"}), "", ) if err == nil { t.Errorf("unexpected non-error: %v", err) } _, err = registry.WatchServices( ctx, labels.SelectorFromSet(labels.Set{"Label.Selector": "foo"}), fields.Everything(), "", ) if err == nil { t.Errorf("unexpected non-error: %v", err) } }
"github.com/qingyuancloud/QingYuan/plugin/pkg/admission/serviceaccount" . "github.com/onsi/ginkgo" ) var _ = Describe("ServiceAccounts", func() { f := NewFramework("svcaccounts") It("should mount an API token into pods", func() { var tokenName string var tokenContent string // Standard get, update retry loop expectNoError(wait.Poll(time.Millisecond*500, time.Second*10, func() (bool, error) { By("getting the auto-created API token") tokenSelector := fields.SelectorFromSet(map[string]string{client.SecretType: string(api.SecretTypeServiceAccountToken)}) secrets, err := f.Client.Secrets(f.Namespace.Name).List(labels.Everything(), tokenSelector) if err != nil { return false, err } if len(secrets.Items) == 0 { return false, nil } if len(secrets.Items) > 1 { return false, fmt.Errorf("Expected 1 token secret, got %d", len(secrets.Items)) } tokenName = secrets.Items[0].Name tokenContent = string(secrets.Items[0].Data[api.ServiceAccountTokenKey]) return true, nil }))