123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171 |
- /*
- Copyright 2019 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 cache implements data structures used by the kubelet plugin manager to
- keep track of registered plugins.
- */
- package cache
- import (
- "fmt"
- "sync"
- "time"
- "k8s.io/klog"
- )
- // DesiredStateOfWorld defines a set of thread-safe operations for the kubelet
- // plugin manager's desired state of the world cache.
- // This cache contains a map of socket file path to plugin information of
- // all plugins attached to this node.
- type DesiredStateOfWorld interface {
- // AddOrUpdatePlugin add the given plugin in the cache if it doesn't already exist.
- // If it does exist in the cache, then the timestamp and foundInDeprecatedDir of the PluginInfo object in the cache will be updated.
- // An error will be returned if socketPath is empty.
- AddOrUpdatePlugin(socketPath string, foundInDeprecatedDir bool) error
- // RemovePlugin deletes the plugin with the given socket path from the desired
- // state of world.
- // If a plugin does not exist with the given socket path, this is a no-op.
- RemovePlugin(socketPath string)
- // GetPluginsToRegister generates and returns a list of plugins
- // in the current desired state of world.
- GetPluginsToRegister() []PluginInfo
- // PluginExists checks if the given socket path exists in the current desired
- // state of world cache
- PluginExists(socketPath string) bool
- }
- // NewDesiredStateOfWorld returns a new instance of DesiredStateOfWorld.
- func NewDesiredStateOfWorld() DesiredStateOfWorld {
- return &desiredStateOfWorld{
- socketFileToInfo: make(map[string]PluginInfo),
- }
- }
- type desiredStateOfWorld struct {
- // socketFileToInfo is a map containing the set of successfully registered plugins
- // The keys are plugin socket file paths. The values are PluginInfo objects
- socketFileToInfo map[string]PluginInfo
- sync.RWMutex
- }
- var _ DesiredStateOfWorld = &desiredStateOfWorld{}
- // Generate a detailed error msg for logs
- func generatePluginMsgDetailed(prefixMsg, suffixMsg, socketPath, details string) (detailedMsg string) {
- return fmt.Sprintf("%v for plugin at %q %v %v", prefixMsg, socketPath, details, suffixMsg)
- }
- // Generate a simplified error msg for events and a detailed error msg for logs
- func generatePluginMsg(prefixMsg, suffixMsg, socketPath, details string) (simpleMsg, detailedMsg string) {
- simpleMsg = fmt.Sprintf("%v for plugin at %q %v", prefixMsg, socketPath, suffixMsg)
- return simpleMsg, generatePluginMsgDetailed(prefixMsg, suffixMsg, socketPath, details)
- }
- // GenerateMsgDetailed returns detailed msgs for plugins to register
- // that can be used in logs.
- // The msg format follows the pattern "<prefixMsg> <plugin details> <suffixMsg>"
- func (plugin *PluginInfo) GenerateMsgDetailed(prefixMsg, suffixMsg string) (detailedMsg string) {
- detailedStr := fmt.Sprintf("(plugin details: %v)", plugin)
- return generatePluginMsgDetailed(prefixMsg, suffixMsg, plugin.SocketPath, detailedStr)
- }
- // GenerateMsg returns simple and detailed msgs for plugins to register
- // that is user friendly and a detailed msg that can be used in logs.
- // The msg format follows the pattern "<prefixMsg> <plugin details> <suffixMsg>".
- func (plugin *PluginInfo) GenerateMsg(prefixMsg, suffixMsg string) (simpleMsg, detailedMsg string) {
- detailedStr := fmt.Sprintf("(plugin details: %v)", plugin)
- return generatePluginMsg(prefixMsg, suffixMsg, plugin.SocketPath, detailedStr)
- }
- // GenerateErrorDetailed returns detailed errors for plugins to register
- // that can be used in logs.
- // The msg format follows the pattern "<prefixMsg> <plugin details>: <err> ",
- func (plugin *PluginInfo) GenerateErrorDetailed(prefixMsg string, err error) (detailedErr error) {
- return fmt.Errorf(plugin.GenerateMsgDetailed(prefixMsg, errSuffix(err)))
- }
- // GenerateError returns simple and detailed errors for plugins to register
- // that is user friendly and a detailed error that can be used in logs.
- // The msg format follows the pattern "<prefixMsg> <plugin details>: <err> ".
- func (plugin *PluginInfo) GenerateError(prefixMsg string, err error) (simpleErr, detailedErr error) {
- simpleMsg, detailedMsg := plugin.GenerateMsg(prefixMsg, errSuffix(err))
- return fmt.Errorf(simpleMsg), fmt.Errorf(detailedMsg)
- }
- // Generates an error string with the format ": <err>" if err exists
- func errSuffix(err error) string {
- errStr := ""
- if err != nil {
- errStr = fmt.Sprintf(": %v", err)
- }
- return errStr
- }
- func (dsw *desiredStateOfWorld) AddOrUpdatePlugin(socketPath string, foundInDeprecatedDir bool) error {
- dsw.Lock()
- defer dsw.Unlock()
- if socketPath == "" {
- return fmt.Errorf("Socket path is empty")
- }
- if _, ok := dsw.socketFileToInfo[socketPath]; ok {
- klog.V(2).Infof("Plugin (Path %s) exists in actual state cache, timestamp will be updated", socketPath)
- }
- // Update the the PluginInfo object.
- // Note that we only update the timestamp in the desired state of world, not the actual state of world
- // because in the reconciler, we need to check if the plugin in the actual state of world is the same
- // version as the plugin in the desired state of world
- dsw.socketFileToInfo[socketPath] = PluginInfo{
- SocketPath: socketPath,
- FoundInDeprecatedDir: foundInDeprecatedDir,
- Timestamp: time.Now(),
- }
- return nil
- }
- func (dsw *desiredStateOfWorld) RemovePlugin(socketPath string) {
- dsw.Lock()
- defer dsw.Unlock()
- delete(dsw.socketFileToInfo, socketPath)
- }
- func (dsw *desiredStateOfWorld) GetPluginsToRegister() []PluginInfo {
- dsw.RLock()
- defer dsw.RUnlock()
- pluginsToRegister := []PluginInfo{}
- for _, pluginInfo := range dsw.socketFileToInfo {
- pluginsToRegister = append(pluginsToRegister, pluginInfo)
- }
- return pluginsToRegister
- }
- func (dsw *desiredStateOfWorld) PluginExists(socketPath string) bool {
- dsw.RLock()
- defer dsw.RUnlock()
- _, exists := dsw.socketFileToInfo[socketPath]
- return exists
- }
|