Support the subresource of service proxy

This commit is contained in:
feihujiang 2015-11-18 11:42:03 +08:00
parent bcabc096f2
commit ac9f890238
31 changed files with 6434 additions and 4240 deletions

View File

@ -13978,6 +13978,522 @@
}
]
},
{
"path": "/api/v1/namespaces/{namespace}/services/{name}/proxy",
"description": "API at /api/v1",
"operations": [
{
"type": "string",
"method": "GET",
"summary": "connect GET requests to proxy of Service",
"nickname": "connectGetNamespacedServiceProxy",
"parameters": [
{
"type": "string",
"paramType": "query",
"name": "path",
"description": "Path is the part of URLs that include service endpoints, suffixes, and parameters to use for the current proxy request to service. For example, the whole request URL is http://localhost/api/v1/namespaces/kube-system/services/elasticsearch-logging/_search?q=user:kimchy. Path is _search?q=user:kimchy.",
"required": false,
"allowMultiple": false
},
{
"type": "string",
"paramType": "path",
"name": "namespace",
"description": "object name and auth scope, such as for teams and projects",
"required": true,
"allowMultiple": false
},
{
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the Service",
"required": true,
"allowMultiple": false
}
],
"produces": [
"*/*"
],
"consumes": [
"*/*"
]
},
{
"type": "string",
"method": "POST",
"summary": "connect POST requests to proxy of Service",
"nickname": "connectPostNamespacedServiceProxy",
"parameters": [
{
"type": "string",
"paramType": "query",
"name": "path",
"description": "Path is the part of URLs that include service endpoints, suffixes, and parameters to use for the current proxy request to service. For example, the whole request URL is http://localhost/api/v1/namespaces/kube-system/services/elasticsearch-logging/_search?q=user:kimchy. Path is _search?q=user:kimchy.",
"required": false,
"allowMultiple": false
},
{
"type": "string",
"paramType": "path",
"name": "namespace",
"description": "object name and auth scope, such as for teams and projects",
"required": true,
"allowMultiple": false
},
{
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the Service",
"required": true,
"allowMultiple": false
}
],
"produces": [
"*/*"
],
"consumes": [
"*/*"
]
},
{
"type": "string",
"method": "PUT",
"summary": "connect PUT requests to proxy of Service",
"nickname": "connectPutNamespacedServiceProxy",
"parameters": [
{
"type": "string",
"paramType": "query",
"name": "path",
"description": "Path is the part of URLs that include service endpoints, suffixes, and parameters to use for the current proxy request to service. For example, the whole request URL is http://localhost/api/v1/namespaces/kube-system/services/elasticsearch-logging/_search?q=user:kimchy. Path is _search?q=user:kimchy.",
"required": false,
"allowMultiple": false
},
{
"type": "string",
"paramType": "path",
"name": "namespace",
"description": "object name and auth scope, such as for teams and projects",
"required": true,
"allowMultiple": false
},
{
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the Service",
"required": true,
"allowMultiple": false
}
],
"produces": [
"*/*"
],
"consumes": [
"*/*"
]
},
{
"type": "string",
"method": "DELETE",
"summary": "connect DELETE requests to proxy of Service",
"nickname": "connectDeleteNamespacedServiceProxy",
"parameters": [
{
"type": "string",
"paramType": "query",
"name": "path",
"description": "Path is the part of URLs that include service endpoints, suffixes, and parameters to use for the current proxy request to service. For example, the whole request URL is http://localhost/api/v1/namespaces/kube-system/services/elasticsearch-logging/_search?q=user:kimchy. Path is _search?q=user:kimchy.",
"required": false,
"allowMultiple": false
},
{
"type": "string",
"paramType": "path",
"name": "namespace",
"description": "object name and auth scope, such as for teams and projects",
"required": true,
"allowMultiple": false
},
{
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the Service",
"required": true,
"allowMultiple": false
}
],
"produces": [
"*/*"
],
"consumes": [
"*/*"
]
},
{
"type": "string",
"method": "HEAD",
"summary": "connect HEAD requests to proxy of Service",
"nickname": "connectHeadNamespacedServiceProxy",
"parameters": [
{
"type": "string",
"paramType": "query",
"name": "path",
"description": "Path is the part of URLs that include service endpoints, suffixes, and parameters to use for the current proxy request to service. For example, the whole request URL is http://localhost/api/v1/namespaces/kube-system/services/elasticsearch-logging/_search?q=user:kimchy. Path is _search?q=user:kimchy.",
"required": false,
"allowMultiple": false
},
{
"type": "string",
"paramType": "path",
"name": "namespace",
"description": "object name and auth scope, such as for teams and projects",
"required": true,
"allowMultiple": false
},
{
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the Service",
"required": true,
"allowMultiple": false
}
],
"produces": [
"*/*"
],
"consumes": [
"*/*"
]
},
{
"type": "string",
"method": "OPTIONS",
"summary": "connect OPTIONS requests to proxy of Service",
"nickname": "connectOptionsNamespacedServiceProxy",
"parameters": [
{
"type": "string",
"paramType": "query",
"name": "path",
"description": "Path is the part of URLs that include service endpoints, suffixes, and parameters to use for the current proxy request to service. For example, the whole request URL is http://localhost/api/v1/namespaces/kube-system/services/elasticsearch-logging/_search?q=user:kimchy. Path is _search?q=user:kimchy.",
"required": false,
"allowMultiple": false
},
{
"type": "string",
"paramType": "path",
"name": "namespace",
"description": "object name and auth scope, such as for teams and projects",
"required": true,
"allowMultiple": false
},
{
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the Service",
"required": true,
"allowMultiple": false
}
],
"produces": [
"*/*"
],
"consumes": [
"*/*"
]
}
]
},
{
"path": "/api/v1/namespaces/{namespace}/services/{name}/proxy/{path}",
"description": "API at /api/v1",
"operations": [
{
"type": "string",
"method": "GET",
"summary": "connect GET requests to proxy of Service",
"nickname": "connectGetNamespacedServiceProxy",
"parameters": [
{
"type": "string",
"paramType": "query",
"name": "path",
"description": "Path is the part of URLs that include service endpoints, suffixes, and parameters to use for the current proxy request to service. For example, the whole request URL is http://localhost/api/v1/namespaces/kube-system/services/elasticsearch-logging/_search?q=user:kimchy. Path is _search?q=user:kimchy.",
"required": false,
"allowMultiple": false
},
{
"type": "string",
"paramType": "path",
"name": "namespace",
"description": "object name and auth scope, such as for teams and projects",
"required": true,
"allowMultiple": false
},
{
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the Service",
"required": true,
"allowMultiple": false
},
{
"type": "string",
"paramType": "path",
"name": "path",
"description": "path to the resource",
"required": true,
"allowMultiple": false
}
],
"produces": [
"*/*"
],
"consumes": [
"*/*"
]
},
{
"type": "string",
"method": "POST",
"summary": "connect POST requests to proxy of Service",
"nickname": "connectPostNamespacedServiceProxy",
"parameters": [
{
"type": "string",
"paramType": "query",
"name": "path",
"description": "Path is the part of URLs that include service endpoints, suffixes, and parameters to use for the current proxy request to service. For example, the whole request URL is http://localhost/api/v1/namespaces/kube-system/services/elasticsearch-logging/_search?q=user:kimchy. Path is _search?q=user:kimchy.",
"required": false,
"allowMultiple": false
},
{
"type": "string",
"paramType": "path",
"name": "namespace",
"description": "object name and auth scope, such as for teams and projects",
"required": true,
"allowMultiple": false
},
{
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the Service",
"required": true,
"allowMultiple": false
},
{
"type": "string",
"paramType": "path",
"name": "path",
"description": "path to the resource",
"required": true,
"allowMultiple": false
}
],
"produces": [
"*/*"
],
"consumes": [
"*/*"
]
},
{
"type": "string",
"method": "PUT",
"summary": "connect PUT requests to proxy of Service",
"nickname": "connectPutNamespacedServiceProxy",
"parameters": [
{
"type": "string",
"paramType": "query",
"name": "path",
"description": "Path is the part of URLs that include service endpoints, suffixes, and parameters to use for the current proxy request to service. For example, the whole request URL is http://localhost/api/v1/namespaces/kube-system/services/elasticsearch-logging/_search?q=user:kimchy. Path is _search?q=user:kimchy.",
"required": false,
"allowMultiple": false
},
{
"type": "string",
"paramType": "path",
"name": "namespace",
"description": "object name and auth scope, such as for teams and projects",
"required": true,
"allowMultiple": false
},
{
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the Service",
"required": true,
"allowMultiple": false
},
{
"type": "string",
"paramType": "path",
"name": "path",
"description": "path to the resource",
"required": true,
"allowMultiple": false
}
],
"produces": [
"*/*"
],
"consumes": [
"*/*"
]
},
{
"type": "string",
"method": "DELETE",
"summary": "connect DELETE requests to proxy of Service",
"nickname": "connectDeleteNamespacedServiceProxy",
"parameters": [
{
"type": "string",
"paramType": "query",
"name": "path",
"description": "Path is the part of URLs that include service endpoints, suffixes, and parameters to use for the current proxy request to service. For example, the whole request URL is http://localhost/api/v1/namespaces/kube-system/services/elasticsearch-logging/_search?q=user:kimchy. Path is _search?q=user:kimchy.",
"required": false,
"allowMultiple": false
},
{
"type": "string",
"paramType": "path",
"name": "namespace",
"description": "object name and auth scope, such as for teams and projects",
"required": true,
"allowMultiple": false
},
{
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the Service",
"required": true,
"allowMultiple": false
},
{
"type": "string",
"paramType": "path",
"name": "path",
"description": "path to the resource",
"required": true,
"allowMultiple": false
}
],
"produces": [
"*/*"
],
"consumes": [
"*/*"
]
},
{
"type": "string",
"method": "HEAD",
"summary": "connect HEAD requests to proxy of Service",
"nickname": "connectHeadNamespacedServiceProxy",
"parameters": [
{
"type": "string",
"paramType": "query",
"name": "path",
"description": "Path is the part of URLs that include service endpoints, suffixes, and parameters to use for the current proxy request to service. For example, the whole request URL is http://localhost/api/v1/namespaces/kube-system/services/elasticsearch-logging/_search?q=user:kimchy. Path is _search?q=user:kimchy.",
"required": false,
"allowMultiple": false
},
{
"type": "string",
"paramType": "path",
"name": "namespace",
"description": "object name and auth scope, such as for teams and projects",
"required": true,
"allowMultiple": false
},
{
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the Service",
"required": true,
"allowMultiple": false
},
{
"type": "string",
"paramType": "path",
"name": "path",
"description": "path to the resource",
"required": true,
"allowMultiple": false
}
],
"produces": [
"*/*"
],
"consumes": [
"*/*"
]
},
{
"type": "string",
"method": "OPTIONS",
"summary": "connect OPTIONS requests to proxy of Service",
"nickname": "connectOptionsNamespacedServiceProxy",
"parameters": [
{
"type": "string",
"paramType": "query",
"name": "path",
"description": "Path is the part of URLs that include service endpoints, suffixes, and parameters to use for the current proxy request to service. For example, the whole request URL is http://localhost/api/v1/namespaces/kube-system/services/elasticsearch-logging/_search?q=user:kimchy. Path is _search?q=user:kimchy.",
"required": false,
"allowMultiple": false
},
{
"type": "string",
"paramType": "path",
"name": "namespace",
"description": "object name and auth scope, such as for teams and projects",
"required": true,
"allowMultiple": false
},
{
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the Service",
"required": true,
"allowMultiple": false
},
{
"type": "string",
"paramType": "path",
"name": "path",
"description": "path to the resource",
"required": true,
"allowMultiple": false
}
],
"produces": [
"*/*"
],
"consumes": [
"*/*"
]
}
]
},
{
"path": "/api/v1/namespaces/{namespace}/services/{name}/status",
"description": "API at /api/v1",

View File

@ -5577,7 +5577,7 @@ Populated by the system when a graceful deletion is requested. Read-only. More i
</div>
<div id="footer">
<div id="footer-text">
Last updated 2016-02-15 20:37:50 UTC
Last updated 2016-02-18 07:15:38 UTC
</div>
</div>
</body>

File diff suppressed because it is too large Load Diff

View File

@ -164,6 +164,7 @@ func init() {
DeepCopy_api_ServiceAccountList,
DeepCopy_api_ServiceList,
DeepCopy_api_ServicePort,
DeepCopy_api_ServiceProxyOptions,
DeepCopy_api_ServiceSpec,
DeepCopy_api_ServiceStatus,
DeepCopy_api_TCPSocketAction,
@ -2744,6 +2745,14 @@ func DeepCopy_api_ServicePort(in ServicePort, out *ServicePort, c *conversion.Cl
return nil
}
func DeepCopy_api_ServiceProxyOptions(in ServiceProxyOptions, out *ServiceProxyOptions, c *conversion.Cloner) error {
if err := DeepCopy_unversioned_TypeMeta(in.TypeMeta, &out.TypeMeta, c); err != nil {
return err
}
out.Path = in.Path
return nil
}
func DeepCopy_api_ServiceSpec(in ServiceSpec, out *ServiceSpec, c *conversion.Cloner) error {
out.Type = in.Type
if in.Ports != nil {

View File

@ -109,6 +109,7 @@ func newRESTMapper(externalVersions []unversioned.GroupVersion) meta.RESTMapper
"PodAttachOptions",
"PodProxyOptions",
"NodeProxyOptions",
"ServiceProxyOptions",
"ThirdPartyResource",
"ThirdPartyResourceData",
"ThirdPartyResourceList")

View File

@ -66,6 +66,7 @@ func AddToScheme(scheme *runtime.Scheme) {
&ReplicationController{},
&ServiceList{},
&Service{},
&ServiceProxyOptions{},
&NodeList{},
&Node{},
&NodeProxyOptions{},
@ -168,6 +169,7 @@ func (obj *PodAttachOptions) GetObjectKind() unversioned.ObjectKind { r
func (obj *PodLogOptions) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *PodExecOptions) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *PodProxyOptions) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *ServiceProxyOptions) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *ComponentStatus) GetObjectMeta() meta.Object { return &obj.ObjectMeta }
func (obj *ComponentStatus) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *ComponentStatusList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }

View File

@ -40193,6 +40193,264 @@ func (x *NodeProxyOptions) codecDecodeSelfFromArray(l int, d *codec1978.Decoder)
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
}
func (x *ServiceProxyOptions) CodecEncodeSelf(e *codec1978.Encoder) {
var h codecSelfer1234
z, r := codec1978.GenHelperEncoder(e)
_, _, _ = h, z, r
if x == nil {
r.EncodeNil()
} else {
yym1 := z.EncBinary()
_ = yym1
if false {
} else if z.HasExtensions() && z.EncExt(x) {
} else {
yysep2 := !z.EncBinary()
yy2arr2 := z.EncBasicHandle().StructToArray
var yyq2 [3]bool
_, _, _ = yysep2, yyq2, yy2arr2
const yyr2 bool = false
yyq2[1] = x.Kind != ""
yyq2[2] = x.APIVersion != ""
var yynn2 int
if yyr2 || yy2arr2 {
r.EncodeArrayStart(3)
} else {
yynn2 = 1
for _, b := range yyq2 {
if b {
yynn2++
}
}
r.EncodeMapStart(yynn2)
yynn2 = 0
}
if yyr2 || yy2arr2 {
z.EncSendContainerState(codecSelfer_containerArrayElem1234)
yym4 := z.EncBinary()
_ = yym4
if false {
} else {
r.EncodeString(codecSelferC_UTF81234, string(x.Path))
}
} else {
z.EncSendContainerState(codecSelfer_containerMapKey1234)
r.EncodeString(codecSelferC_UTF81234, string("Path"))
z.EncSendContainerState(codecSelfer_containerMapValue1234)
yym5 := z.EncBinary()
_ = yym5
if false {
} else {
r.EncodeString(codecSelferC_UTF81234, string(x.Path))
}
}
if yyr2 || yy2arr2 {
z.EncSendContainerState(codecSelfer_containerArrayElem1234)
if yyq2[1] {
yym7 := z.EncBinary()
_ = yym7
if false {
} else {
r.EncodeString(codecSelferC_UTF81234, string(x.Kind))
}
} else {
r.EncodeString(codecSelferC_UTF81234, "")
}
} else {
if yyq2[1] {
z.EncSendContainerState(codecSelfer_containerMapKey1234)
r.EncodeString(codecSelferC_UTF81234, string("kind"))
z.EncSendContainerState(codecSelfer_containerMapValue1234)
yym8 := z.EncBinary()
_ = yym8
if false {
} else {
r.EncodeString(codecSelferC_UTF81234, string(x.Kind))
}
}
}
if yyr2 || yy2arr2 {
z.EncSendContainerState(codecSelfer_containerArrayElem1234)
if yyq2[2] {
yym10 := z.EncBinary()
_ = yym10
if false {
} else {
r.EncodeString(codecSelferC_UTF81234, string(x.APIVersion))
}
} else {
r.EncodeString(codecSelferC_UTF81234, "")
}
} else {
if yyq2[2] {
z.EncSendContainerState(codecSelfer_containerMapKey1234)
r.EncodeString(codecSelferC_UTF81234, string("apiVersion"))
z.EncSendContainerState(codecSelfer_containerMapValue1234)
yym11 := z.EncBinary()
_ = yym11
if false {
} else {
r.EncodeString(codecSelferC_UTF81234, string(x.APIVersion))
}
}
}
if yyr2 || yy2arr2 {
z.EncSendContainerState(codecSelfer_containerArrayEnd1234)
} else {
z.EncSendContainerState(codecSelfer_containerMapEnd1234)
}
}
}
}
func (x *ServiceProxyOptions) CodecDecodeSelf(d *codec1978.Decoder) {
var h codecSelfer1234
z, r := codec1978.GenHelperDecoder(d)
_, _, _ = h, z, r
yym1 := z.DecBinary()
_ = yym1
if false {
} else if z.HasExtensions() && z.DecExt(x) {
} else {
yyct2 := r.ContainerType()
if yyct2 == codecSelferValueTypeMap1234 {
yyl2 := r.ReadMapStart()
if yyl2 == 0 {
z.DecSendContainerState(codecSelfer_containerMapEnd1234)
} else {
x.codecDecodeSelfFromMap(yyl2, d)
}
} else if yyct2 == codecSelferValueTypeArray1234 {
yyl2 := r.ReadArrayStart()
if yyl2 == 0 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
} else {
x.codecDecodeSelfFromArray(yyl2, d)
}
} else {
panic(codecSelferOnlyMapOrArrayEncodeToStructErr1234)
}
}
}
func (x *ServiceProxyOptions) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) {
var h codecSelfer1234
z, r := codec1978.GenHelperDecoder(d)
_, _, _ = h, z, r
var yys3Slc = z.DecScratchBuffer() // default slice to decode into
_ = yys3Slc
var yyhl3 bool = l >= 0
for yyj3 := 0; ; yyj3++ {
if yyhl3 {
if yyj3 >= l {
break
}
} else {
if r.CheckBreak() {
break
}
}
z.DecSendContainerState(codecSelfer_containerMapKey1234)
yys3Slc = r.DecodeBytes(yys3Slc, true, true)
yys3 := string(yys3Slc)
z.DecSendContainerState(codecSelfer_containerMapValue1234)
switch yys3 {
case "Path":
if r.TryDecodeAsNil() {
x.Path = ""
} else {
x.Path = string(r.DecodeString())
}
case "kind":
if r.TryDecodeAsNil() {
x.Kind = ""
} else {
x.Kind = string(r.DecodeString())
}
case "apiVersion":
if r.TryDecodeAsNil() {
x.APIVersion = ""
} else {
x.APIVersion = string(r.DecodeString())
}
default:
z.DecStructFieldNotFound(-1, yys3)
} // end switch yys3
} // end for yyj3
z.DecSendContainerState(codecSelfer_containerMapEnd1234)
}
func (x *ServiceProxyOptions) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
var h codecSelfer1234
z, r := codec1978.GenHelperDecoder(d)
_, _, _ = h, z, r
var yyj7 int
var yyb7 bool
var yyhl7 bool = l >= 0
yyj7++
if yyhl7 {
yyb7 = yyj7 > l
} else {
yyb7 = r.CheckBreak()
}
if yyb7 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return
}
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
if r.TryDecodeAsNil() {
x.Path = ""
} else {
x.Path = string(r.DecodeString())
}
yyj7++
if yyhl7 {
yyb7 = yyj7 > l
} else {
yyb7 = r.CheckBreak()
}
if yyb7 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return
}
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
if r.TryDecodeAsNil() {
x.Kind = ""
} else {
x.Kind = string(r.DecodeString())
}
yyj7++
if yyhl7 {
yyb7 = yyj7 > l
} else {
yyb7 = r.CheckBreak()
}
if yyb7 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return
}
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
if r.TryDecodeAsNil() {
x.APIVersion = ""
} else {
x.APIVersion = string(r.DecodeString())
}
for {
yyj7++
if yyhl7 {
yyb7 = yyj7 > l
} else {
yyb7 = r.CheckBreak()
}
if yyb7 {
break
}
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
z.DecStructFieldNotFound(yyj7-1, "")
}
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
}
func (x *ObjectReference) CodecEncodeSelf(e *codec1978.Encoder) {
var h codecSelfer1234
z, r := codec1978.GenHelperEncoder(e)

View File

@ -2010,6 +2010,18 @@ type NodeProxyOptions struct {
Path string
}
// ServiceProxyOptions is the query options to a Service's proxy call.
type ServiceProxyOptions struct {
unversioned.TypeMeta
// Path is the part of URLs that include service endpoints, suffixes,
// and parameters to use for the current proxy request to service.
// For example, the whole request URL is
// http://localhost/api/v1/namespaces/kube-system/services/elasticsearch-logging/_search?q=user:kimchy.
// Path is _search?q=user:kimchy.
Path string
}
// ObjectReference contains enough information to let you inspect or modify the referred object.
type ObjectReference struct {
Kind string `json:"kind,omitempty"`

View File

@ -3023,6 +3023,18 @@ func Convert_api_ServicePort_To_v1_ServicePort(in *api.ServicePort, out *Service
return autoConvert_api_ServicePort_To_v1_ServicePort(in, out, s)
}
func autoConvert_api_ServiceProxyOptions_To_v1_ServiceProxyOptions(in *api.ServiceProxyOptions, out *ServiceProxyOptions, s conversion.Scope) error {
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
defaulting.(func(*api.ServiceProxyOptions))(in)
}
out.Path = in.Path
return nil
}
func Convert_api_ServiceProxyOptions_To_v1_ServiceProxyOptions(in *api.ServiceProxyOptions, out *ServiceProxyOptions, s conversion.Scope) error {
return autoConvert_api_ServiceProxyOptions_To_v1_ServiceProxyOptions(in, out, s)
}
func autoConvert_api_ServiceSpec_To_v1_ServiceSpec(in *api.ServiceSpec, out *ServiceSpec, s conversion.Scope) error {
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
defaulting.(func(*api.ServiceSpec))(in)
@ -6196,6 +6208,18 @@ func Convert_v1_ServicePort_To_api_ServicePort(in *ServicePort, out *api.Service
return autoConvert_v1_ServicePort_To_api_ServicePort(in, out, s)
}
func autoConvert_v1_ServiceProxyOptions_To_api_ServiceProxyOptions(in *ServiceProxyOptions, out *api.ServiceProxyOptions, s conversion.Scope) error {
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
defaulting.(func(*ServiceProxyOptions))(in)
}
out.Path = in.Path
return nil
}
func Convert_v1_ServiceProxyOptions_To_api_ServiceProxyOptions(in *ServiceProxyOptions, out *api.ServiceProxyOptions, s conversion.Scope) error {
return autoConvert_v1_ServiceProxyOptions_To_api_ServiceProxyOptions(in, out, s)
}
func autoConvert_v1_ServiceSpec_To_api_ServiceSpec(in *ServiceSpec, out *api.ServiceSpec, s conversion.Scope) error {
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
defaulting.(func(*ServiceSpec))(in)
@ -6597,6 +6621,7 @@ func init() {
autoConvert_api_ServiceAccount_To_v1_ServiceAccount,
autoConvert_api_ServiceList_To_v1_ServiceList,
autoConvert_api_ServicePort_To_v1_ServicePort,
autoConvert_api_ServiceProxyOptions_To_v1_ServiceProxyOptions,
autoConvert_api_ServiceSpec_To_v1_ServiceSpec,
autoConvert_api_ServiceStatus_To_v1_ServiceStatus,
autoConvert_api_Service_To_v1_Service,
@ -6728,6 +6753,7 @@ func init() {
autoConvert_v1_ServiceAccount_To_api_ServiceAccount,
autoConvert_v1_ServiceList_To_api_ServiceList,
autoConvert_v1_ServicePort_To_api_ServicePort,
autoConvert_v1_ServiceProxyOptions_To_api_ServiceProxyOptions,
autoConvert_v1_ServiceSpec_To_api_ServiceSpec,
autoConvert_v1_ServiceStatus_To_api_ServiceStatus,
autoConvert_v1_Service_To_api_Service,

View File

@ -2358,6 +2358,14 @@ func deepCopy_v1_ServicePort(in ServicePort, out *ServicePort, c *conversion.Clo
return nil
}
func deepCopy_v1_ServiceProxyOptions(in ServiceProxyOptions, out *ServiceProxyOptions, c *conversion.Cloner) error {
if err := deepCopy_unversioned_TypeMeta(in.TypeMeta, &out.TypeMeta, c); err != nil {
return err
}
out.Path = in.Path
return nil
}
func deepCopy_v1_ServiceSpec(in ServiceSpec, out *ServiceSpec, c *conversion.Cloner) error {
if in.Ports != nil {
out.Ports = make([]ServicePort, len(in.Ports))
@ -2742,6 +2750,7 @@ func init() {
deepCopy_v1_ServiceAccountList,
deepCopy_v1_ServiceList,
deepCopy_v1_ServicePort,
deepCopy_v1_ServiceProxyOptions,
deepCopy_v1_ServiceSpec,
deepCopy_v1_ServiceStatus,
deepCopy_v1_TCPSocketAction,

View File

@ -45,6 +45,7 @@ func addKnownTypes(scheme *runtime.Scheme) {
&ReplicationController{},
&ReplicationControllerList{},
&Service{},
&ServiceProxyOptions{},
&ServiceList{},
&Endpoints{},
&EndpointsList{},
@ -126,6 +127,7 @@ func (obj *PodAttachOptions) GetObjectKind() unversioned.ObjectKind { r
func (obj *PodLogOptions) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *PodExecOptions) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *PodProxyOptions) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *ServiceProxyOptions) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *ComponentStatus) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *ComponentStatusList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *SerializedReference) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }

View File

@ -40005,6 +40005,271 @@ func (x *NodeProxyOptions) codecDecodeSelfFromArray(l int, d *codec1978.Decoder)
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
}
func (x *ServiceProxyOptions) CodecEncodeSelf(e *codec1978.Encoder) {
var h codecSelfer1234
z, r := codec1978.GenHelperEncoder(e)
_, _, _ = h, z, r
if x == nil {
r.EncodeNil()
} else {
yym1 := z.EncBinary()
_ = yym1
if false {
} else if z.HasExtensions() && z.EncExt(x) {
} else {
yysep2 := !z.EncBinary()
yy2arr2 := z.EncBasicHandle().StructToArray
var yyq2 [3]bool
_, _, _ = yysep2, yyq2, yy2arr2
const yyr2 bool = false
yyq2[0] = x.Path != ""
yyq2[1] = x.Kind != ""
yyq2[2] = x.APIVersion != ""
var yynn2 int
if yyr2 || yy2arr2 {
r.EncodeArrayStart(3)
} else {
yynn2 = 0
for _, b := range yyq2 {
if b {
yynn2++
}
}
r.EncodeMapStart(yynn2)
yynn2 = 0
}
if yyr2 || yy2arr2 {
z.EncSendContainerState(codecSelfer_containerArrayElem1234)
if yyq2[0] {
yym4 := z.EncBinary()
_ = yym4
if false {
} else {
r.EncodeString(codecSelferC_UTF81234, string(x.Path))
}
} else {
r.EncodeString(codecSelferC_UTF81234, "")
}
} else {
if yyq2[0] {
z.EncSendContainerState(codecSelfer_containerMapKey1234)
r.EncodeString(codecSelferC_UTF81234, string("path"))
z.EncSendContainerState(codecSelfer_containerMapValue1234)
yym5 := z.EncBinary()
_ = yym5
if false {
} else {
r.EncodeString(codecSelferC_UTF81234, string(x.Path))
}
}
}
if yyr2 || yy2arr2 {
z.EncSendContainerState(codecSelfer_containerArrayElem1234)
if yyq2[1] {
yym7 := z.EncBinary()
_ = yym7
if false {
} else {
r.EncodeString(codecSelferC_UTF81234, string(x.Kind))
}
} else {
r.EncodeString(codecSelferC_UTF81234, "")
}
} else {
if yyq2[1] {
z.EncSendContainerState(codecSelfer_containerMapKey1234)
r.EncodeString(codecSelferC_UTF81234, string("kind"))
z.EncSendContainerState(codecSelfer_containerMapValue1234)
yym8 := z.EncBinary()
_ = yym8
if false {
} else {
r.EncodeString(codecSelferC_UTF81234, string(x.Kind))
}
}
}
if yyr2 || yy2arr2 {
z.EncSendContainerState(codecSelfer_containerArrayElem1234)
if yyq2[2] {
yym10 := z.EncBinary()
_ = yym10
if false {
} else {
r.EncodeString(codecSelferC_UTF81234, string(x.APIVersion))
}
} else {
r.EncodeString(codecSelferC_UTF81234, "")
}
} else {
if yyq2[2] {
z.EncSendContainerState(codecSelfer_containerMapKey1234)
r.EncodeString(codecSelferC_UTF81234, string("apiVersion"))
z.EncSendContainerState(codecSelfer_containerMapValue1234)
yym11 := z.EncBinary()
_ = yym11
if false {
} else {
r.EncodeString(codecSelferC_UTF81234, string(x.APIVersion))
}
}
}
if yyr2 || yy2arr2 {
z.EncSendContainerState(codecSelfer_containerArrayEnd1234)
} else {
z.EncSendContainerState(codecSelfer_containerMapEnd1234)
}
}
}
}
func (x *ServiceProxyOptions) CodecDecodeSelf(d *codec1978.Decoder) {
var h codecSelfer1234
z, r := codec1978.GenHelperDecoder(d)
_, _, _ = h, z, r
yym1 := z.DecBinary()
_ = yym1
if false {
} else if z.HasExtensions() && z.DecExt(x) {
} else {
yyct2 := r.ContainerType()
if yyct2 == codecSelferValueTypeMap1234 {
yyl2 := r.ReadMapStart()
if yyl2 == 0 {
z.DecSendContainerState(codecSelfer_containerMapEnd1234)
} else {
x.codecDecodeSelfFromMap(yyl2, d)
}
} else if yyct2 == codecSelferValueTypeArray1234 {
yyl2 := r.ReadArrayStart()
if yyl2 == 0 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
} else {
x.codecDecodeSelfFromArray(yyl2, d)
}
} else {
panic(codecSelferOnlyMapOrArrayEncodeToStructErr1234)
}
}
}
func (x *ServiceProxyOptions) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) {
var h codecSelfer1234
z, r := codec1978.GenHelperDecoder(d)
_, _, _ = h, z, r
var yys3Slc = z.DecScratchBuffer() // default slice to decode into
_ = yys3Slc
var yyhl3 bool = l >= 0
for yyj3 := 0; ; yyj3++ {
if yyhl3 {
if yyj3 >= l {
break
}
} else {
if r.CheckBreak() {
break
}
}
z.DecSendContainerState(codecSelfer_containerMapKey1234)
yys3Slc = r.DecodeBytes(yys3Slc, true, true)
yys3 := string(yys3Slc)
z.DecSendContainerState(codecSelfer_containerMapValue1234)
switch yys3 {
case "path":
if r.TryDecodeAsNil() {
x.Path = ""
} else {
x.Path = string(r.DecodeString())
}
case "kind":
if r.TryDecodeAsNil() {
x.Kind = ""
} else {
x.Kind = string(r.DecodeString())
}
case "apiVersion":
if r.TryDecodeAsNil() {
x.APIVersion = ""
} else {
x.APIVersion = string(r.DecodeString())
}
default:
z.DecStructFieldNotFound(-1, yys3)
} // end switch yys3
} // end for yyj3
z.DecSendContainerState(codecSelfer_containerMapEnd1234)
}
func (x *ServiceProxyOptions) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
var h codecSelfer1234
z, r := codec1978.GenHelperDecoder(d)
_, _, _ = h, z, r
var yyj7 int
var yyb7 bool
var yyhl7 bool = l >= 0
yyj7++
if yyhl7 {
yyb7 = yyj7 > l
} else {
yyb7 = r.CheckBreak()
}
if yyb7 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return
}
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
if r.TryDecodeAsNil() {
x.Path = ""
} else {
x.Path = string(r.DecodeString())
}
yyj7++
if yyhl7 {
yyb7 = yyj7 > l
} else {
yyb7 = r.CheckBreak()
}
if yyb7 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return
}
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
if r.TryDecodeAsNil() {
x.Kind = ""
} else {
x.Kind = string(r.DecodeString())
}
yyj7++
if yyhl7 {
yyb7 = yyj7 > l
} else {
yyb7 = r.CheckBreak()
}
if yyb7 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return
}
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
if r.TryDecodeAsNil() {
x.APIVersion = ""
} else {
x.APIVersion = string(r.DecodeString())
}
for {
yyj7++
if yyhl7 {
yyb7 = yyj7 > l
} else {
yyb7 = r.CheckBreak()
}
if yyb7 {
break
}
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
z.DecStructFieldNotFound(yyj7-1, "")
}
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
}
func (x *ObjectReference) CodecEncodeSelf(e *codec1978.Encoder) {
var h codecSelfer1234
z, r := codec1978.GenHelperEncoder(e)

View File

@ -2439,6 +2439,18 @@ type NodeProxyOptions struct {
Path string `json:"path,omitempty"`
}
// ServiceProxyOptions is the query options to a Service's proxy call.
type ServiceProxyOptions struct {
unversioned.TypeMeta `json:",inline"`
// Path is the part of URLs that include service endpoints, suffixes,
// and parameters to use for the current proxy request to service.
// For example, the whole request URL is
// http://localhost/api/v1/namespaces/kube-system/services/elasticsearch-logging/_search?q=user:kimchy.
// Path is _search?q=user:kimchy.
Path string `json:"path,omitempty"`
}
// ObjectReference contains enough information to let you inspect or modify the referred object.
type ObjectReference struct {
// Kind of the referent.

View File

@ -1508,6 +1508,15 @@ func (ServicePort) SwaggerDoc() map[string]string {
return map_ServicePort
}
var map_ServiceProxyOptions = map[string]string{
"": "ServiceProxyOptions is the query options to a Service's proxy call.",
"path": "Path is the part of URLs that include service endpoints, suffixes, and parameters to use for the current proxy request to service. For example, the whole request URL is http://localhost/api/v1/namespaces/kube-system/services/elasticsearch-logging/_search?q=user:kimchy. Path is _search?q=user:kimchy.",
}
func (ServiceProxyOptions) SwaggerDoc() map[string]string {
return map_ServiceProxyOptions
}
var map_ServiceSpec = map[string]string{
"": "ServiceSpec describes the attributes that a user creates on a service.",
"ports": "The list of ports that are exposed by this service. More info: http://releases.k8s.io/HEAD/docs/user-guide/services.md#virtual-ips-and-service-proxies",

View File

@ -108,9 +108,9 @@ func (c *services) Watch(opts api.ListOptions) (watch.Interface, error) {
// ProxyGet returns a response of the service by calling it through the proxy.
func (c *services) ProxyGet(scheme, name, port, path string, params map[string]string) ResponseWrapper {
request := c.r.Get().
Prefix("proxy").
Namespace(c.ns).
Resource("services").
SubResource("proxy").
Name(net.JoinSchemeNamePort(scheme, name, port)).
Suffix(path)
for k, v := range params {

View File

@ -218,7 +218,7 @@ func TestServiceProxyGet(t *testing.T) {
c := &simple.Client{
Request: simple.Request{
Method: "GET",
Path: testapi.Default.ResourcePathWithPrefix("proxy", "services", ns, "service-1") + "/foo",
Path: testapi.Default.ResourcePath("services", ns, "service-1") + "/proxy/foo",
Query: simple.BuildQueryValues(url.Values{"param-name": []string{"param-value"}}),
},
Response: simple.Response{StatusCode: 200, RawBody: &body},
@ -231,7 +231,7 @@ func TestServiceProxyGet(t *testing.T) {
c = &simple.Client{
Request: simple.Request{
Method: "GET",
Path: testapi.Default.ResourcePathWithPrefix("proxy", "services", ns, "https:service-1:my-port") + "/foo",
Path: testapi.Default.ResourcePath("services", ns, "https:service-1:my-port") + "/proxy/foo",
Query: simple.BuildQueryValues(url.Values{"param-name": []string{"param-value"}}),
},
Response: simple.Response{StatusCode: 200, RawBody: &body},

View File

@ -315,6 +315,9 @@ func (m *Master) initV1ResourcesStorage(c *Config) {
controllerStorage, controllerStatusStorage := controlleretcd.NewREST(dbClient("replicationControllers"), storageDecorator)
serviceRest := service.NewStorage(m.serviceRegistry, m.endpointRegistry, serviceClusterIPAllocator, serviceNodePortAllocator, m.ProxyTransport)
// TODO: Factor out the core API registration
m.v1ResourcesStorage = map[string]rest.Storage{
"pods": podStorage.Pod,
"pods/attach": podStorage.Attach,
@ -330,12 +333,17 @@ func (m *Master) initV1ResourcesStorage(c *Config) {
"replicationControllers": controllerStorage,
"replicationControllers/status": controllerStatusStorage,
"services": service.NewStorage(m.serviceRegistry, m.endpointRegistry, serviceClusterIPAllocator, serviceNodePortAllocator, m.ProxyTransport),
"services": serviceRest.Service,
"services/proxy": serviceRest.Proxy,
"services/status": serviceStatusStorage,
"endpoints": endpointsStorage,
"nodes": nodeStorage.Node,
"nodes/status": nodeStorage.Status,
"nodes/proxy": nodeStorage.Proxy,
"events": eventStorage,
"limitRanges": limitRangeStorage,

View File

@ -0,0 +1,77 @@
/*
Copyright 2015 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package service
import (
"fmt"
"net/http"
"net/url"
"path"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/rest"
"k8s.io/kubernetes/pkg/capabilities"
genericrest "k8s.io/kubernetes/pkg/registry/generic/rest"
"k8s.io/kubernetes/pkg/runtime"
)
// ProxyREST implements the proxy subresource for a Service
type ProxyREST struct {
ServiceRest *REST
ProxyTransport http.RoundTripper
}
// Implement Connecter
var _ = rest.Connecter(&ProxyREST{})
var proxyMethods = []string{"GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS"}
// New returns an empty service resource
func (r *ProxyREST) New() runtime.Object {
return &api.Service{}
}
// ConnectMethods returns the list of HTTP methods that can be proxied
func (r *ProxyREST) ConnectMethods() []string {
return proxyMethods
}
// NewConnectOptions returns versioned resource that represents proxy parameters
func (r *ProxyREST) NewConnectOptions() (runtime.Object, bool, string) {
return &api.ServiceProxyOptions{}, true, "path"
}
// Connect returns a handler for the service proxy
func (r *ProxyREST) Connect(ctx api.Context, id string, opts runtime.Object, responder rest.Responder) (http.Handler, error) {
proxyOpts, ok := opts.(*api.ServiceProxyOptions)
if !ok {
return nil, fmt.Errorf("Invalid options object: %#v", opts)
}
location, transport, err := r.ServiceRest.ResourceLocation(ctx, id)
if err != nil {
return nil, err
}
location.Path = path.Join(location.Path, proxyOpts.Path)
// Return a proxy handler that uses the desired transport, wrapped with additional proxy handling (to get URL rewriting, X-Forwarded-* headers, etc)
return newThrottledUpgradeAwareProxyHandler(location, transport, true, false, responder), nil
}
func newThrottledUpgradeAwareProxyHandler(location *url.URL, transport http.RoundTripper, wrapTransport, upgradeRequired bool, responder rest.Responder) *genericrest.UpgradeAwareProxyHandler {
handler := genericrest.NewUpgradeAwareProxyHandler(location, transport, wrapTransport, upgradeRequired, responder)
handler.MaxBytesPerSec = capabilities.Get().PerConnectionBandwidthLimitBytesPerSec
return handler
}

View File

@ -39,6 +39,12 @@ import (
"k8s.io/kubernetes/pkg/watch"
)
// ServiceRest includes storage for services and all sub resources
type ServiceRest struct {
Service *REST
Proxy *ProxyREST
}
// REST adapts a service registry into apiserver's RESTStorage model.
type REST struct {
registry Registry
@ -50,14 +56,18 @@ type REST struct {
// NewStorage returns a new REST.
func NewStorage(registry Registry, endpoints endpoint.Registry, serviceIPs ipallocator.Interface,
serviceNodePorts portallocator.Interface, proxyTransport http.RoundTripper) *REST {
return &REST{
serviceNodePorts portallocator.Interface, proxyTransport http.RoundTripper) *ServiceRest {
rest := &REST{
registry: registry,
endpoints: endpoints,
serviceIPs: serviceIPs,
serviceNodePorts: serviceNodePorts,
proxyTransport: proxyTransport,
}
return &ServiceRest{
Service: rest,
Proxy: &ProxyREST{ServiceRest: rest, ProxyTransport: proxyTransport},
}
}
func (rs *REST) Create(ctx api.Context, obj runtime.Object) (runtime.Object, error) {

View File

@ -48,7 +48,7 @@ func NewTestREST(t *testing.T, endpoints *api.EndpointsList) (*REST, *registryte
storage := NewStorage(registry, endpointRegistry, r, portAllocator, nil)
return storage, registry
return storage.Service, registry
}
func makeIPNet(t *testing.T) *net.IPNet {

View File

@ -187,10 +187,9 @@ func (rc *ResourceConsumer) sendConsumeMemRequests(requests, megabytes, duration
// sendOneConsumeCPURequest sends POST request for cpu consumption
func (rc *ResourceConsumer) sendOneConsumeCPURequest(millicores int, durationSec int) {
defer GinkgoRecover()
_, err := rc.framework.Client.Post().
Prefix("proxy").
Namespace(rc.framework.Namespace.Name).
Resource("services").
proxyRequest, err := getServicesProxyRequest(rc.framework.Client, rc.framework.Client.Post())
expectNoError(err)
_, err = proxyRequest.Namespace(rc.framework.Namespace.Name).
Name(rc.name).
Suffix("ConsumeCPU").
Param("millicores", strconv.Itoa(millicores)).
@ -202,10 +201,9 @@ func (rc *ResourceConsumer) sendOneConsumeCPURequest(millicores int, durationSec
// sendOneConsumeMemRequest sends POST request for memory consumption
func (rc *ResourceConsumer) sendOneConsumeMemRequest(megabytes int, durationSec int) {
defer GinkgoRecover()
_, err := rc.framework.Client.Post().
Prefix("proxy").
Namespace(rc.framework.Namespace.Name).
Resource("services").
proxyRequest, err := getServicesProxyRequest(rc.framework.Client, rc.framework.Client.Post())
expectNoError(err)
_, err = proxyRequest.Namespace(rc.framework.Namespace.Name).
Name(rc.name).
Suffix("ConsumeMem").
Param("megabytes", strconv.Itoa(megabytes)).

View File

@ -52,11 +52,12 @@ var _ = Describe("Kubernetes Dashboard", func() {
By("Checking to make sure we get a response from the kubernetes-dashboard.")
err = wait.Poll(poll, serverStartTimeout, func() (bool, error) {
var status int
proxyRequest, errProxy := getServicesProxyRequest(f.Client, f.Client.Get())
if errProxy != nil {
Logf("Get services proxy request failed: %v", errProxy)
}
// Query against the proxy URL for the kube-ui service.
err := f.Client.Get().
Namespace(uiNamespace).
Prefix("proxy").
Resource("services").
err := proxyRequest.Namespace(uiNamespace).
Name(uiServiceName).
Timeout(singleCallTimeout).
Do().

View File

@ -110,11 +110,13 @@ func ClusterLevelLoggingWithElasticsearch(f *Framework) {
err = nil
var body []byte
for start := time.Now(); time.Since(start) < graceTime; time.Sleep(10 * time.Second) {
proxyRequest, errProxy := getServicesProxyRequest(f.Client, f.Client.Get())
if errProxy != nil {
Logf("After %v failed to get services proxy request: %v", time.Since(start), errProxy)
continue
}
// Query against the root URL for Elasticsearch.
body, err = f.Client.Get().
Namespace(api.NamespaceSystem).
Prefix("proxy").
Resource("services").
body, err = proxyRequest.Namespace(api.NamespaceSystem).
Name("elasticsearch-logging").
DoRaw()
if err != nil {
@ -161,10 +163,12 @@ func ClusterLevelLoggingWithElasticsearch(f *Framework) {
By("Checking health of Elasticsearch service.")
healthy := false
for start := time.Now(); time.Since(start) < graceTime; time.Sleep(5 * time.Second) {
body, err = f.Client.Get().
Namespace(api.NamespaceSystem).
Prefix("proxy").
Resource("services").
proxyRequest, errProxy := getServicesProxyRequest(f.Client, f.Client.Get())
if errProxy != nil {
Logf("After %v failed to get services proxy request: %v", time.Since(start), errProxy)
continue
}
body, err = proxyRequest.Namespace(api.NamespaceSystem).
Name("elasticsearch-logging").
Suffix("_cluster/health").
Param("level", "indices").
@ -321,13 +325,15 @@ func ClusterLevelLoggingWithElasticsearch(f *Framework) {
}
}
proxyRequest, errProxy := getServicesProxyRequest(f.Client, f.Client.Get())
if errProxy != nil {
Logf("After %v failed to get services proxy request: %v", time.Since(start), errProxy)
continue
}
// Ask Elasticsearch to return all the log lines that were tagged with the underscore
// version of the name. Ask for twice as many log lines as we expect to check for
// duplication bugs.
body, err = f.Client.Get().
Namespace(api.NamespaceSystem).
Prefix("proxy").
Resource("services").
body, err = proxyRequest.Namespace(api.NamespaceSystem).
Name("elasticsearch-logging").
Suffix("_search").
Param("q", fmt.Sprintf("log:%s", taintName)).

View File

@ -47,10 +47,11 @@ const (
// readTransactions reads # of transactions from the k8petstore web server endpoint.
// for more details see the source of the k8petstore web server.
func readTransactions(c *client.Client, ns string) (error, int) {
body, err := c.Get().
Namespace(ns).
Prefix("proxy").
Resource("services").
proxyRequest, errProxy := getServicesProxyRequest(c, c.Get())
if errProxy != nil {
return errProxy, -1
}
body, err := proxyRequest.Namespace(ns).
Name("frontend").
Suffix("llen").
DoRaw()

View File

@ -432,10 +432,11 @@ func makeHttpRequestToService(c *client.Client, ns, service, path string, timeou
var result []byte
var err error
for t := time.Now(); time.Since(t) < timeout; time.Sleep(poll) {
result, err = c.Get().
Prefix("proxy").
Namespace(ns).
Resource("services").
proxyRequest, errProxy := getServicesProxyRequest(c, c.Get())
if errProxy != nil {
break
}
result, err = proxyRequest.Namespace(ns).
Name(service).
Suffix(path).
Do().

View File

@ -79,11 +79,13 @@ func ClusterLevelLoggingWithKibana(f *Framework) {
By("Checking to make sure we get a response from the Kibana UI.")
err = nil
for start := time.Now(); time.Since(start) < graceTime; time.Sleep(5 * time.Second) {
proxyRequest, errProxy := getServicesProxyRequest(f.Client, f.Client.Get())
if errProxy != nil {
Logf("After %v failed to get services proxy request: %v", time.Since(start), errProxy)
continue
}
// Query against the root URL for Kibana.
_, err = f.Client.Get().
Namespace(api.NamespaceSystem).
Prefix("proxy").
Resource("services").
_, err = proxyRequest.Namespace(api.NamespaceSystem).
Name("kibana-logging").
DoRaw()
if err != nil {

View File

@ -1185,10 +1185,11 @@ func waitForGuestbookResponse(c *client.Client, cmd, arg, expectedResponse strin
}
func makeRequestToGuestbook(c *client.Client, cmd, value string, ns string) (string, error) {
result, err := c.Get().
Prefix("proxy").
Namespace(ns).
Resource("services").
proxyRequest, errProxy := getServicesProxyRequest(c, c.Get())
if errProxy != nil {
return "", errProxy
}
result, err := proxyRequest.Namespace(ns).
Name("frontend").
Suffix("/guestbook.php").
Param("cmd", cmd).

View File

@ -150,20 +150,22 @@ var _ = Describe("Networking", func() {
//once response OK, evaluate response body for pass/fail.
var body []byte
getDetails := func() ([]byte, error) {
return f.Client.Get().
Namespace(f.Namespace.Name).
Prefix("proxy").
Resource("services").
proxyRequest, errProxy := getServicesProxyRequest(f.Client, f.Client.Get())
if errProxy != nil {
return nil, errProxy
}
return proxyRequest.Namespace(f.Namespace.Name).
Name(svc.Name).
Suffix("read").
DoRaw()
}
getStatus := func() ([]byte, error) {
return f.Client.Get().
Namespace(f.Namespace.Name).
Prefix("proxy").
Resource("services").
proxyRequest, errProxy := getServicesProxyRequest(f.Client, f.Client.Get())
if errProxy != nil {
return nil, errProxy
}
return proxyRequest.Namespace(f.Namespace.Name).
Name(svc.Name).
Suffix("status").
DoRaw()

View File

@ -137,6 +137,9 @@ func proxyContext(version string) {
svcProxyURL := func(scheme, port string) string {
return prefix + "/proxy/namespaces/" + f.Namespace.Name + "/services/" + net.JoinSchemeNamePort(scheme, service.Name, port)
}
subresourceServiceProxyURL := func(scheme, port string) string {
return prefix + "/namespaces/" + f.Namespace.Name + "/services/" + net.JoinSchemeNamePort(scheme, service.Name, port) + "/proxy"
}
podProxyURL := func(scheme, port string) string {
return prefix + "/proxy/namespaces/" + f.Namespace.Name + "/pods/" + net.JoinSchemeNamePort(scheme, pods[0].Name, port)
}
@ -159,6 +162,13 @@ func proxyContext(version string) {
svcProxyURL("https", "tlsportname2") + "/": "tls qux",
svcProxyURL("https", "444") + "/": "tls qux",
subresourceServiceProxyURL("", "portname1") + "/": "foo",
subresourceServiceProxyURL("http", "portname1") + "/": "foo",
subresourceServiceProxyURL("", "portname2") + "/": "bar",
subresourceServiceProxyURL("http", "portname2") + "/": "bar",
subresourceServiceProxyURL("https", "tlsportname1") + "/": "tls baz",
subresourceServiceProxyURL("https", "tlsportname2") + "/": "tls qux",
podProxyURL("", "80") + "/": `<a href="` + podProxyURL("", "80") + `/rewriteme">test</a>`,
podProxyURL("", "160") + "/": "foo",
podProxyURL("", "162") + "/": "bar",

View File

@ -121,6 +121,21 @@ const (
var subResourcePodProxyVersion = version.MustParse("v1.1.0")
var subResourceServiceAndNodeProxyVersion = version.MustParse("v1.2.0")
func getServicesProxyRequest(c *client.Client, request *client.Request) (*client.Request, error) {
subResourceProxyAvailable, err := serverVersionGTE(subResourceServiceAndNodeProxyVersion, c)
if err != nil {
return nil, err
}
if subResourceProxyAvailable {
return request.Resource("services").SubResource("proxy"), nil
}
return request.Prefix("proxy").Resource("services"), nil
}
func GetServicesProxyRequest(c *client.Client, request *client.Request) (*client.Request, error) {
return getServicesProxyRequest(c, request)
}
type CloudConfig struct {
ProjectID string
Zone string
@ -1081,10 +1096,12 @@ func serviceResponding(c *client.Client, ns, name string) error {
By(fmt.Sprintf("trying to dial the service %s.%s via the proxy", ns, name))
return wait.PollImmediate(poll, serviceRespondingTimeout, func() (done bool, err error) {
body, err := c.Get().
Prefix("proxy").
Namespace(ns).
Resource("services").
proxyRequest, errProxy := getServicesProxyRequest(c, c.Get())
if errProxy != nil {
Logf("Failed to get services proxy request: %v:", errProxy)
return false, nil
}
body, err := proxyRequest.Namespace(ns).
Name(name).
Do().
Raw()

View File

@ -37,6 +37,7 @@ import (
"k8s.io/kubernetes/pkg/client/unversioned/clientcmd"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util/intstr"
"k8s.io/kubernetes/test/e2e"
)
var (
@ -252,12 +253,16 @@ func main() {
}
}
proxyRequest, errProxy := e2e.GetServicesProxyRequest(c, c.Get())
if errProxy != nil {
glog.Warningf("Get services proxy request failed: %v", errProxy)
return
}
// Wait for the endpoints to propagate.
for start := time.Now(); time.Since(start) < endpointTimeout; time.Sleep(10 * time.Second) {
hostname, err := c.Get().
hostname, err := proxyRequest.
Namespace(ns).
Prefix("proxy").
Resource("services").
Name("serve-hostnames").
DoRaw()
if err != nil {
@ -286,10 +291,8 @@ func main() {
go func(i int, query int) {
inFlight <- struct{}{}
t := time.Now()
hostname, err := c.Get().
hostname, err := proxyRequest.
Namespace(ns).
Prefix("proxy").
Resource("services").
Name("serve-hostnames").
DoRaw()
glog.V(4).Infof("Proxy call in namespace %s took %v", ns, time.Since(t))