...

Source file src/k8s.io/kubernetes/pkg/credentialprovider/provider.go

Documentation: k8s.io/kubernetes/pkg/credentialprovider

     1  /*
     2  Copyright 2014 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package credentialprovider
    18  
    19  import (
    20  	"os"
    21  	"reflect"
    22  	"sync"
    23  	"time"
    24  
    25  	"k8s.io/klog/v2"
    26  )
    27  
    28  // DockerConfigProvider is the interface that registered extensions implement
    29  // to materialize 'dockercfg' credentials.
    30  type DockerConfigProvider interface {
    31  	// Enabled returns true if the config provider is enabled.
    32  	// Implementations can be blocking - e.g. metadata server unavailable.
    33  	Enabled() bool
    34  	// Provide returns docker configuration.
    35  	// Implementations can be blocking - e.g. metadata server unavailable.
    36  	// The image is passed in as context in the event that the
    37  	// implementation depends on information in the image name to return
    38  	// credentials; implementations are safe to ignore the image.
    39  	Provide(image string) DockerConfig
    40  }
    41  
    42  // A DockerConfigProvider that simply reads the .dockercfg file
    43  type defaultDockerConfigProvider struct{}
    44  
    45  // init registers our default provider, which simply reads the .dockercfg file.
    46  func init() {
    47  	RegisterCredentialProvider(".dockercfg",
    48  		&CachingDockerConfigProvider{
    49  			Provider: &defaultDockerConfigProvider{},
    50  			Lifetime: 5 * time.Minute,
    51  		})
    52  }
    53  
    54  // CachingDockerConfigProvider implements DockerConfigProvider by composing
    55  // with another DockerConfigProvider and caching the DockerConfig it provides
    56  // for a pre-specified lifetime.
    57  type CachingDockerConfigProvider struct {
    58  	Provider DockerConfigProvider
    59  	Lifetime time.Duration
    60  
    61  	// ShouldCache is an optional function that returns true if the specific config should be cached.
    62  	// If nil, all configs are treated as cacheable.
    63  	ShouldCache func(DockerConfig) bool
    64  
    65  	// cache fields
    66  	cacheDockerConfig DockerConfig
    67  	expiration        time.Time
    68  	mu                sync.Mutex
    69  }
    70  
    71  // Enabled implements dockerConfigProvider
    72  func (d *defaultDockerConfigProvider) Enabled() bool {
    73  	return true
    74  }
    75  
    76  // Provide implements dockerConfigProvider
    77  func (d *defaultDockerConfigProvider) Provide(image string) DockerConfig {
    78  	// Read the standard Docker credentials from .dockercfg
    79  	if cfg, err := ReadDockerConfigFile(); err == nil {
    80  		return cfg
    81  	} else if !os.IsNotExist(err) {
    82  		klog.V(2).Infof("Docker config file not found: %v", err)
    83  	}
    84  	return DockerConfig{}
    85  }
    86  
    87  // Enabled implements dockerConfigProvider
    88  func (d *CachingDockerConfigProvider) Enabled() bool {
    89  	return d.Provider.Enabled()
    90  }
    91  
    92  // Provide implements dockerConfigProvider
    93  func (d *CachingDockerConfigProvider) Provide(image string) DockerConfig {
    94  	d.mu.Lock()
    95  	defer d.mu.Unlock()
    96  
    97  	// If the cache hasn't expired, return our cache
    98  	if time.Now().Before(d.expiration) {
    99  		return d.cacheDockerConfig
   100  	}
   101  
   102  	klog.V(2).Infof("Refreshing cache for provider: %v", reflect.TypeOf(d.Provider).String())
   103  	config := d.Provider.Provide(image)
   104  	if d.ShouldCache == nil || d.ShouldCache(config) {
   105  		d.cacheDockerConfig = config
   106  		d.expiration = time.Now().Add(d.Lifetime)
   107  	}
   108  	return config
   109  }
   110  

View as plain text