subresources.go 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  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 rest
  14. import (
  15. "fmt"
  16. "net/http"
  17. "net/url"
  18. "path"
  19. "k8s.io/kubernetes/pkg/api"
  20. "k8s.io/kubernetes/pkg/api/rest"
  21. "k8s.io/kubernetes/pkg/capabilities"
  22. "k8s.io/kubernetes/pkg/kubelet/client"
  23. "k8s.io/kubernetes/pkg/registry/generic/registry"
  24. genericrest "k8s.io/kubernetes/pkg/registry/generic/rest"
  25. "k8s.io/kubernetes/pkg/registry/pod"
  26. "k8s.io/kubernetes/pkg/runtime"
  27. )
  28. // ProxyREST implements the proxy subresource for a Pod
  29. type ProxyREST struct {
  30. Store *registry.Store
  31. ProxyTransport http.RoundTripper
  32. }
  33. // Implement Connecter
  34. var _ = rest.Connecter(&ProxyREST{})
  35. var proxyMethods = []string{"GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS"}
  36. // New returns an empty pod resource
  37. func (r *ProxyREST) New() runtime.Object {
  38. return &api.Pod{}
  39. }
  40. // ConnectMethods returns the list of HTTP methods that can be proxied
  41. func (r *ProxyREST) ConnectMethods() []string {
  42. return proxyMethods
  43. }
  44. // NewConnectOptions returns versioned resource that represents proxy parameters
  45. func (r *ProxyREST) NewConnectOptions() (runtime.Object, bool, string) {
  46. return &api.PodProxyOptions{}, true, "path"
  47. }
  48. // Connect returns a handler for the pod proxy
  49. func (r *ProxyREST) Connect(ctx api.Context, id string, opts runtime.Object, responder rest.Responder) (http.Handler, error) {
  50. proxyOpts, ok := opts.(*api.PodProxyOptions)
  51. if !ok {
  52. return nil, fmt.Errorf("Invalid options object: %#v", opts)
  53. }
  54. location, transport, err := pod.ResourceLocation(r.Store, r.ProxyTransport, ctx, id)
  55. if err != nil {
  56. return nil, err
  57. }
  58. location.Path = path.Join(location.Path, proxyOpts.Path)
  59. // Return a proxy handler that uses the desired transport, wrapped with additional proxy handling (to get URL rewriting, X-Forwarded-* headers, etc)
  60. return newThrottledUpgradeAwareProxyHandler(location, transport, true, false, responder), nil
  61. }
  62. // Support both GET and POST methods. We must support GET for browsers that want to use WebSockets.
  63. var upgradeableMethods = []string{"GET", "POST"}
  64. // AttachREST implements the attach subresource for a Pod
  65. type AttachREST struct {
  66. Store *registry.Store
  67. KubeletConn client.ConnectionInfoGetter
  68. }
  69. // Implement Connecter
  70. var _ = rest.Connecter(&AttachREST{})
  71. // New creates a new Pod object
  72. func (r *AttachREST) New() runtime.Object {
  73. return &api.Pod{}
  74. }
  75. // Connect returns a handler for the pod exec proxy
  76. func (r *AttachREST) Connect(ctx api.Context, name string, opts runtime.Object, responder rest.Responder) (http.Handler, error) {
  77. attachOpts, ok := opts.(*api.PodAttachOptions)
  78. if !ok {
  79. return nil, fmt.Errorf("Invalid options object: %#v", opts)
  80. }
  81. location, transport, err := pod.AttachLocation(r.Store, r.KubeletConn, ctx, name, attachOpts)
  82. if err != nil {
  83. return nil, err
  84. }
  85. return newThrottledUpgradeAwareProxyHandler(location, transport, false, true, responder), nil
  86. }
  87. // NewConnectOptions returns the versioned object that represents exec parameters
  88. func (r *AttachREST) NewConnectOptions() (runtime.Object, bool, string) {
  89. return &api.PodAttachOptions{}, false, ""
  90. }
  91. // ConnectMethods returns the methods supported by exec
  92. func (r *AttachREST) ConnectMethods() []string {
  93. return upgradeableMethods
  94. }
  95. // ExecREST implements the exec subresource for a Pod
  96. type ExecREST struct {
  97. Store *registry.Store
  98. KubeletConn client.ConnectionInfoGetter
  99. }
  100. // Implement Connecter
  101. var _ = rest.Connecter(&ExecREST{})
  102. // New creates a new Pod object
  103. func (r *ExecREST) New() runtime.Object {
  104. return &api.Pod{}
  105. }
  106. // Connect returns a handler for the pod exec proxy
  107. func (r *ExecREST) Connect(ctx api.Context, name string, opts runtime.Object, responder rest.Responder) (http.Handler, error) {
  108. execOpts, ok := opts.(*api.PodExecOptions)
  109. if !ok {
  110. return nil, fmt.Errorf("invalid options object: %#v", opts)
  111. }
  112. location, transport, err := pod.ExecLocation(r.Store, r.KubeletConn, ctx, name, execOpts)
  113. if err != nil {
  114. return nil, err
  115. }
  116. return newThrottledUpgradeAwareProxyHandler(location, transport, false, true, responder), nil
  117. }
  118. // NewConnectOptions returns the versioned object that represents exec parameters
  119. func (r *ExecREST) NewConnectOptions() (runtime.Object, bool, string) {
  120. return &api.PodExecOptions{}, false, ""
  121. }
  122. // ConnectMethods returns the methods supported by exec
  123. func (r *ExecREST) ConnectMethods() []string {
  124. return upgradeableMethods
  125. }
  126. // PortForwardREST implements the portforward subresource for a Pod
  127. type PortForwardREST struct {
  128. Store *registry.Store
  129. KubeletConn client.ConnectionInfoGetter
  130. }
  131. // Implement Connecter
  132. var _ = rest.Connecter(&PortForwardREST{})
  133. // New returns an empty pod object
  134. func (r *PortForwardREST) New() runtime.Object {
  135. return &api.Pod{}
  136. }
  137. // NewConnectOptions returns nil since portforward doesn't take additional parameters
  138. func (r *PortForwardREST) NewConnectOptions() (runtime.Object, bool, string) {
  139. return nil, false, ""
  140. }
  141. // ConnectMethods returns the methods supported by portforward
  142. func (r *PortForwardREST) ConnectMethods() []string {
  143. return upgradeableMethods
  144. }
  145. // Connect returns a handler for the pod portforward proxy
  146. func (r *PortForwardREST) Connect(ctx api.Context, name string, opts runtime.Object, responder rest.Responder) (http.Handler, error) {
  147. location, transport, err := pod.PortForwardLocation(r.Store, r.KubeletConn, ctx, name)
  148. if err != nil {
  149. return nil, err
  150. }
  151. return newThrottledUpgradeAwareProxyHandler(location, transport, false, true, responder), nil
  152. }
  153. func newThrottledUpgradeAwareProxyHandler(location *url.URL, transport http.RoundTripper, wrapTransport, upgradeRequired bool, responder rest.Responder) *genericrest.UpgradeAwareProxyHandler {
  154. handler := genericrest.NewUpgradeAwareProxyHandler(location, transport, wrapTransport, upgradeRequired, responder)
  155. handler.MaxBytesPerSec = capabilities.Get().PerConnectionBandwidthLimitBytesPerSec
  156. return handler
  157. }