provider.go 3.1 KB

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