clientcache.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  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 util
  14. import (
  15. fed_clientset "k8s.io/kubernetes/federation/client/clientset_generated/federation_internalclientset"
  16. "k8s.io/kubernetes/pkg/api/unversioned"
  17. "k8s.io/kubernetes/pkg/apimachinery/registered"
  18. "k8s.io/kubernetes/pkg/client/restclient"
  19. client "k8s.io/kubernetes/pkg/client/unversioned"
  20. "k8s.io/kubernetes/pkg/client/unversioned/clientcmd"
  21. )
  22. func NewClientCache(loader clientcmd.ClientConfig) *ClientCache {
  23. return &ClientCache{
  24. clients: make(map[unversioned.GroupVersion]*client.Client),
  25. configs: make(map[unversioned.GroupVersion]*restclient.Config),
  26. fedClientSets: make(map[unversioned.GroupVersion]fed_clientset.Interface),
  27. loader: loader,
  28. }
  29. }
  30. // ClientCache caches previously loaded clients for reuse, and ensures MatchServerVersion
  31. // is invoked only once
  32. type ClientCache struct {
  33. loader clientcmd.ClientConfig
  34. clients map[unversioned.GroupVersion]*client.Client
  35. fedClientSets map[unversioned.GroupVersion]fed_clientset.Interface
  36. configs map[unversioned.GroupVersion]*restclient.Config
  37. defaultConfig *restclient.Config
  38. defaultClient *client.Client
  39. matchVersion bool
  40. }
  41. // ClientConfigForVersion returns the correct config for a server
  42. func (c *ClientCache) ClientConfigForVersion(version *unversioned.GroupVersion) (*restclient.Config, error) {
  43. if c.defaultConfig == nil {
  44. config, err := c.loader.ClientConfig()
  45. if err != nil {
  46. return nil, err
  47. }
  48. c.defaultConfig = config
  49. if c.matchVersion {
  50. if err := client.MatchesServerVersion(c.defaultClient, config); err != nil {
  51. return nil, err
  52. }
  53. }
  54. }
  55. if version != nil {
  56. if config, ok := c.configs[*version]; ok {
  57. return config, nil
  58. }
  59. }
  60. // TODO: have a better config copy method
  61. config := *c.defaultConfig
  62. // TODO these fall out when we finish the refactor
  63. var preferredGV *unversioned.GroupVersion
  64. if version != nil {
  65. versionCopy := *version
  66. preferredGV = &versionCopy
  67. }
  68. client.SetKubernetesDefaults(&config)
  69. negotiatedVersion, err := client.NegotiateVersion(c.defaultClient, &config, preferredGV, registered.EnabledVersions())
  70. if err != nil {
  71. return nil, err
  72. }
  73. config.GroupVersion = negotiatedVersion
  74. if version != nil {
  75. c.configs[*version] = &config
  76. }
  77. // `version` does not necessarily equal `config.Version`. However, we know that we call this method again with
  78. // `config.Version`, we should get the config we've just built.
  79. configCopy := config
  80. c.configs[*config.GroupVersion] = &configCopy
  81. return &config, nil
  82. }
  83. // ClientForVersion initializes or reuses a client for the specified version, or returns an
  84. // error if that is not possible
  85. func (c *ClientCache) ClientForVersion(version *unversioned.GroupVersion) (*client.Client, error) {
  86. if version != nil {
  87. if client, ok := c.clients[*version]; ok {
  88. return client, nil
  89. }
  90. }
  91. config, err := c.ClientConfigForVersion(version)
  92. if err != nil {
  93. return nil, err
  94. }
  95. kubeclient, err := client.New(config)
  96. if err != nil {
  97. return nil, err
  98. }
  99. c.clients[*config.GroupVersion] = kubeclient
  100. // `version` does not necessarily equal `config.Version`. However, we know that if we call this method again with
  101. // `version`, we should get a client based on the same config we just found. There's no guarantee that a client
  102. // is copiable, so create a new client and save it in the cache.
  103. if version != nil {
  104. configCopy := *config
  105. kubeclient, err := client.New(&configCopy)
  106. if err != nil {
  107. return nil, err
  108. }
  109. c.clients[*version] = kubeclient
  110. }
  111. return kubeclient, nil
  112. }
  113. func (c *ClientCache) FederationClientSetForVersion(version *unversioned.GroupVersion) (fed_clientset.Interface, error) {
  114. if version != nil {
  115. if clientSet, found := c.fedClientSets[*version]; found {
  116. return clientSet, nil
  117. }
  118. }
  119. config, err := c.ClientConfigForVersion(version)
  120. if err != nil {
  121. return nil, err
  122. }
  123. // TODO: support multi versions of client with clientset
  124. clientSet, err := fed_clientset.NewForConfig(config)
  125. if err != nil {
  126. return nil, err
  127. }
  128. c.fedClientSets[*config.GroupVersion] = clientSet
  129. if version != nil {
  130. configCopy := *config
  131. clientSet, err := fed_clientset.NewForConfig(&configCopy)
  132. if err != nil {
  133. return nil, err
  134. }
  135. c.fedClientSets[*version] = clientSet
  136. }
  137. return clientSet, nil
  138. }
  139. func (c *ClientCache) FederationClientForVersion(version *unversioned.GroupVersion) (*restclient.RESTClient, error) {
  140. fedClientSet, err := c.FederationClientSetForVersion(version)
  141. if err != nil {
  142. return nil, err
  143. }
  144. return fedClientSet.(*fed_clientset.Clientset).FederationClient.RESTClient, nil
  145. }