provider.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  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. // LazyProvide gets called after URL matches have been
  34. // performed, so the location used as the key in DockerConfig would be
  35. // redundant.
  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. LazyProvide(image string) *DockerConfigEntry
  40. }
  41. //LazyProvide returns an Lazy AuthConfig
  42. func LazyProvide(creds LazyAuthConfiguration, image string) AuthConfig {
  43. if creds.Provider != nil {
  44. entry := *creds.Provider.LazyProvide(image)
  45. return DockerConfigEntryToLazyAuthConfiguration(entry).AuthConfig
  46. }
  47. return creds.AuthConfig
  48. }
  49. // A DockerConfigProvider that simply reads the .dockercfg file
  50. type defaultDockerConfigProvider struct{}
  51. // init registers our default provider, which simply reads the .dockercfg file.
  52. func init() {
  53. RegisterCredentialProvider(".dockercfg",
  54. &CachingDockerConfigProvider{
  55. Provider: &defaultDockerConfigProvider{},
  56. Lifetime: 5 * time.Minute,
  57. })
  58. }
  59. // CachingDockerConfigProvider implements DockerConfigProvider by composing
  60. // with another DockerConfigProvider and caching the DockerConfig it provides
  61. // for a pre-specified lifetime.
  62. type CachingDockerConfigProvider struct {
  63. Provider DockerConfigProvider
  64. Lifetime time.Duration
  65. // cache fields
  66. cacheDockerConfig DockerConfig
  67. expiration time.Time
  68. mu sync.Mutex
  69. }
  70. // Enabled implements dockerConfigProvider
  71. func (d *defaultDockerConfigProvider) Enabled() bool {
  72. return true
  73. }
  74. // LazyProvide implements dockerConfigProvider
  75. func (d *defaultDockerConfigProvider) Provide(image string) DockerConfig {
  76. // Read the standard Docker credentials from .dockercfg
  77. if cfg, err := ReadDockerConfigFile(); err == nil {
  78. return cfg
  79. } else if !os.IsNotExist(err) {
  80. klog.V(4).Infof("Unable to parse Docker config file: %v", err)
  81. }
  82. return DockerConfig{}
  83. }
  84. // LazyProvide implements dockerConfigProvider. Should never be called.
  85. func (d *defaultDockerConfigProvider) LazyProvide(image string) *DockerConfigEntry {
  86. return nil
  87. }
  88. // Enabled implements dockerConfigProvider
  89. func (d *CachingDockerConfigProvider) Enabled() bool {
  90. return d.Provider.Enabled()
  91. }
  92. // LazyProvide implements dockerConfigProvider. Should never be called.
  93. func (d *CachingDockerConfigProvider) LazyProvide(image string) *DockerConfigEntry {
  94. return nil
  95. }
  96. // Provide implements dockerConfigProvider
  97. func (d *CachingDockerConfigProvider) Provide(image string) DockerConfig {
  98. d.mu.Lock()
  99. defer d.mu.Unlock()
  100. // If the cache hasn't expired, return our cache
  101. if time.Now().Before(d.expiration) {
  102. return d.cacheDockerConfig
  103. }
  104. klog.V(2).Infof("Refreshing cache for provider: %v", reflect.TypeOf(d.Provider).String())
  105. d.cacheDockerConfig = d.Provider.Provide(image)
  106. d.expiration = time.Now().Add(d.Lifetime)
  107. return d.cacheDockerConfig
  108. }