GitOps for k8s
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

client_factory.go 3.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. package registry
  2. import (
  3. "context"
  4. "errors"
  5. "github.com/go-kit/kit/log"
  6. dockerregistry "github.com/heroku/docker-registry-client/registry"
  7. "github.com/jonboulle/clockwork"
  8. "github.com/weaveworks/flux/registry/memcache"
  9. "github.com/weaveworks/flux/registry/middleware"
  10. "golang.org/x/net/publicsuffix"
  11. "net/http"
  12. "net/http/cookiejar"
  13. "time"
  14. )
  15. var (
  16. ErrNoMemcache = errors.New("no memecache")
  17. )
  18. // ClientFactory creates a new client for the given host.
  19. // Each request might require a new client. E.g. when retrieving docker
  20. // images from docker hub, then a second from quay.io
  21. type ClientFactory interface {
  22. ClientFor(host string) (client Client, err error)
  23. }
  24. // ---
  25. // A new ClientFactory for a Remote.
  26. func NewRemoteClientFactory(c Credentials, l log.Logger, rlc middleware.RateLimiterConfig) ClientFactory {
  27. for host, creds := range c.m {
  28. l.Log("host", host, "username", creds.username)
  29. }
  30. return &remoteClientFactory{
  31. creds: c,
  32. Logger: l,
  33. rlConf: rlc,
  34. }
  35. }
  36. type remoteClientFactory struct {
  37. creds Credentials
  38. Logger log.Logger
  39. rlConf middleware.RateLimiterConfig
  40. }
  41. func (f *remoteClientFactory) ClientFor(host string) (Client, error) {
  42. httphost := "https://" + host
  43. // quay.io wants us to use cookies for authorisation, so we have
  44. // to construct one (the default client has none). This means a
  45. // bit more constructing things to be able to make a registry
  46. // client literal, rather than calling .New()
  47. jar, err := cookiejar.New(&cookiejar.Options{PublicSuffixList: publicsuffix.List})
  48. if err != nil {
  49. return nil, err
  50. }
  51. auth := f.creds.credsFor(host)
  52. // A context we'll use to cancel requests on error
  53. ctx, cancel := context.WithCancel(context.Background())
  54. // Add a timeout to the request
  55. ctx, cancel = context.WithTimeout(ctx, requestTimeout)
  56. // Use the wrapper to fix headers for quay.io, and remember bearer tokens
  57. var transport http.RoundTripper
  58. {
  59. transport = &middleware.WWWAuthenticateFixer{Transport: http.DefaultTransport}
  60. // Now the auth-handling wrappers that come with the library
  61. transport = dockerregistry.WrapTransport(transport, httphost, auth.username, auth.password)
  62. // Add the backoff mechanism so we don't DOS registries
  63. transport = middleware.BackoffRoundTripper(transport, middleware.InitialBackoff, middleware.MaxBackoff, clockwork.NewRealClock())
  64. // Add timeout context
  65. transport = &middleware.ContextRoundTripper{Transport: transport, Ctx: ctx}
  66. // Rate limit
  67. transport = middleware.RateLimitedRoundTripper(transport, f.rlConf, host)
  68. }
  69. herokuRegistry := herokuManifestAdaptor{
  70. &dockerregistry.Registry{
  71. URL: httphost,
  72. Client: &http.Client{
  73. Transport: transport,
  74. Jar: jar,
  75. Timeout: requestTimeout,
  76. },
  77. Logf: dockerregistry.Quiet,
  78. },
  79. }
  80. client := &Remote{
  81. Registry: &herokuRegistry,
  82. CancelFunc: cancel,
  83. }
  84. return client, nil
  85. }
  86. // ---
  87. // A new ClientFactory implementation for a Cache
  88. func NewCacheClientFactory(c Credentials, l log.Logger, mc memcache.MemcacheClient, ce time.Duration) ClientFactory {
  89. for host, creds := range c.m {
  90. l.Log("host", host, "username", creds.username)
  91. }
  92. return &cacheClientFactory{
  93. creds: c,
  94. Logger: l,
  95. MemcacheClient: mc,
  96. CacheExpiry: ce,
  97. }
  98. }
  99. type cacheClientFactory struct {
  100. creds Credentials
  101. Logger log.Logger
  102. MemcacheClient memcache.MemcacheClient
  103. CacheExpiry time.Duration
  104. }
  105. func (f *cacheClientFactory) ClientFor(host string) (Client, error) {
  106. if f.MemcacheClient == nil {
  107. return nil, ErrNoMemcache
  108. }
  109. client := NewCache(f.creds, f.MemcacheClient, f.CacheExpiry, f.Logger)
  110. return client, nil
  111. }