k3s/pkg/kubelet/secret/secret_manager.go

153 lines
4.6 KiB
Go
Raw Normal View History

2016-11-18 12:14:03 +00:00
/*
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 secret
import (
"sync"
2017-06-22 17:25:57 +00:00
"k8s.io/api/core/v1"
clientset "k8s.io/client-go/kubernetes"
podutil "k8s.io/kubernetes/pkg/api/v1/pod"
2016-11-18 12:14:03 +00:00
2017-01-06 19:47:43 +00:00
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/sets"
2016-11-18 12:14:03 +00:00
)
type Manager interface {
// Get secret by secret namespace and name.
GetSecret(namespace, name string) (*v1.Secret, error)
2017-01-06 19:47:43 +00:00
// WARNING: Register/UnregisterPod functions should be efficient,
// i.e. should not block on network operations.
2016-11-18 12:14:03 +00:00
// RegisterPod registers all secrets from a given pod.
RegisterPod(pod *v1.Pod)
// UnregisterPod unregisters secrets from a given pod that are not
2017-01-06 19:47:43 +00:00
// used by any other registered pod.
2016-11-18 12:14:03 +00:00
UnregisterPod(pod *v1.Pod)
}
2018-05-01 17:47:38 +00:00
type objectKey struct {
namespace string
name string
}
2016-11-18 12:14:03 +00:00
// simpleSecretManager implements SecretManager interfaces with
// simple operations to apiserver.
type simpleSecretManager struct {
kubeClient clientset.Interface
}
func NewSimpleSecretManager(kubeClient clientset.Interface) Manager {
return &simpleSecretManager{kubeClient: kubeClient}
2016-11-18 12:14:03 +00:00
}
func (s *simpleSecretManager) GetSecret(namespace, name string) (*v1.Secret, error) {
return s.kubeClient.CoreV1().Secrets(namespace).Get(name, metav1.GetOptions{})
2016-11-18 12:14:03 +00:00
}
func (s *simpleSecretManager) RegisterPod(pod *v1.Pod) {
}
func (s *simpleSecretManager) UnregisterPod(pod *v1.Pod) {
}
2018-05-01 17:47:38 +00:00
// store is the interface for a secrets cache that
// can be used by cacheBasedSecretManager.
type store interface {
2018-05-09 16:14:50 +00:00
// AddReference adds a reference to the secret to the store.
2018-05-01 17:47:38 +00:00
// Note that multiple additions to the store has to be allowed
// in the implementations and effectively treated as refcounted.
2018-05-09 16:14:50 +00:00
AddReference(namespace, name string)
// DeleteReference deletes reference to the secret from the store.
2018-05-01 17:47:38 +00:00
// Note that secret should be deleted only when there was a
// corresponding Delete call for each of Add calls (effectively
// when refcount was reduced to zero).
2018-05-09 16:14:50 +00:00
DeleteReference(namespace, name string)
2018-05-01 17:47:38 +00:00
// Get a secret from a store.
Get(namespace, name string) (*v1.Secret, error)
}
// cachingBasedSecretManager keeps a store with secrets necessary
// for registered pods. Different implementations of the store
// may result in different semantics for freshness of secrets
// (e.g. ttl-based implementation vs watch-based implementation).
type cacheBasedSecretManager struct {
secretStore store
2016-11-18 12:14:03 +00:00
lock sync.Mutex
registeredPods map[objectKey]*v1.Pod
}
2018-05-01 17:47:38 +00:00
func newCacheBasedSecretManager(secretStore store) Manager {
return &cacheBasedSecretManager{
secretStore: secretStore,
2016-11-18 12:14:03 +00:00
registeredPods: make(map[objectKey]*v1.Pod),
}
}
2018-05-01 17:47:38 +00:00
func (c *cacheBasedSecretManager) GetSecret(namespace, name string) (*v1.Secret, error) {
2016-11-18 12:14:03 +00:00
return c.secretStore.Get(namespace, name)
}
func getSecretNames(pod *v1.Pod) sets.String {
result := sets.NewString()
podutil.VisitPodSecretNames(pod, func(name string) bool {
result.Insert(name)
return true
})
2016-11-18 12:14:03 +00:00
return result
}
2018-05-01 17:47:38 +00:00
func (c *cacheBasedSecretManager) RegisterPod(pod *v1.Pod) {
2017-01-06 19:47:43 +00:00
names := getSecretNames(pod)
c.lock.Lock()
defer c.lock.Unlock()
for name := range names {
2018-05-09 16:14:50 +00:00
c.secretStore.AddReference(pod.Namespace, name)
2016-11-18 12:14:03 +00:00
}
var prev *v1.Pod
2017-01-06 19:47:43 +00:00
key := objectKey{namespace: pod.Namespace, name: pod.Name}
prev = c.registeredPods[key]
c.registeredPods[key] = pod
2016-11-18 12:14:03 +00:00
if prev != nil {
2017-01-06 19:47:43 +00:00
for name := range getSecretNames(prev) {
// On an update, the .Add() call above will have re-incremented the
// ref count of any existing secrets, so any secrets that are in both
// names and prev need to have their ref counts decremented. Any that
// are only in prev need to be completely removed. This unconditional
// call takes care of both cases.
2018-05-09 16:14:50 +00:00
c.secretStore.DeleteReference(prev.Namespace, name)
2016-11-18 12:14:03 +00:00
}
}
}
2018-05-01 17:47:38 +00:00
func (c *cacheBasedSecretManager) UnregisterPod(pod *v1.Pod) {
2016-11-18 12:14:03 +00:00
var prev *v1.Pod
2017-01-06 19:47:43 +00:00
key := objectKey{namespace: pod.Namespace, name: pod.Name}
c.lock.Lock()
defer c.lock.Unlock()
prev = c.registeredPods[key]
delete(c.registeredPods, key)
2016-11-18 12:14:03 +00:00
if prev != nil {
2017-01-06 19:47:43 +00:00
for name := range getSecretNames(prev) {
2018-05-09 16:14:50 +00:00
c.secretStore.DeleteReference(prev.Namespace, name)
2016-11-18 12:14:03 +00:00
}
}
}