Unverified Commit eb65eacf authored by Kubernetes Prow Robot's avatar Kubernetes Prow Robot Committed by GitHub

Merge pull request #74855 from mbohlool/sam

Add Port configuration to ServiceReference of Admission webhooks, CRD Conversion Webhooks, AuditSink Webhooks and kube-aggregator
parents c082ace1 e6f5f4f6
...@@ -121,6 +121,11 @@ ...@@ -121,6 +121,11 @@
"path": { "path": {
"description": "`path` is an optional URL path which will be sent in any request to this service.", "description": "`path` is an optional URL path which will be sent in any request to this service.",
"type": "string" "type": "string"
},
"port": {
"description": "If specified, the port on the service that hosting webhook. Default to 443 for backward compatibility. `port` should be a valid port number (1-65535, inclusive).",
"format": "int32",
"type": "integer"
} }
}, },
"required": [ "required": [
...@@ -257,7 +262,7 @@ ...@@ -257,7 +262,7 @@
}, },
"service": { "service": {
"$ref": "#/definitions/io.k8s.api.admissionregistration.v1beta1.ServiceReference", "$ref": "#/definitions/io.k8s.api.admissionregistration.v1beta1.ServiceReference",
"description": "`service` is a reference to the service for this webhook. Either `service` or `url` must be specified.\n\nIf the webhook is running within the cluster, then you should use `service`.\n\nPort 443 will be used if it is open, otherwise it is an error." "description": "`service` is a reference to the service for this webhook. Either `service` or `url` must be specified.\n\nIf the webhook is running within the cluster, then you should use `service`."
}, },
"url": { "url": {
"description": "`url` gives the location of the webhook, in standard URL form (`scheme://host:port/path`). Exactly one of `url` or `service` must be specified.\n\nThe `host` should not refer to a service running in the cluster; use the `service` field instead. The host might be resolved via external DNS in some apiservers (e.g., `kube-apiserver` cannot resolve in-cluster DNS as that would be a layering violation). `host` may also be an IP address.\n\nPlease note that using `localhost` or `127.0.0.1` as a `host` is risky unless you take great care to run this webhook on all hosts which run an apiserver which might need to make calls to this webhook. Such installs are likely to be non-portable, i.e., not easy to turn up in a new cluster.\n\nThe scheme must be \"https\"; the URL must begin with \"https://\".\n\nA path is optional, and if present may be any string permissible in a URL. You may use the path to pass an arbitrary string to the webhook, for example, a cluster identifier.\n\nAttempting to use a user or basic auth e.g. \"user:password@\" is not allowed. Fragments (\"#...\") and query parameters (\"?...\") are not allowed, either.", "description": "`url` gives the location of the webhook, in standard URL form (`scheme://host:port/path`). Exactly one of `url` or `service` must be specified.\n\nThe `host` should not refer to a service running in the cluster; use the `service` field instead. The host might be resolved via external DNS in some apiservers (e.g., `kube-apiserver` cannot resolve in-cluster DNS as that would be a layering violation). `host` may also be an IP address.\n\nPlease note that using `localhost` or `127.0.0.1` as a `host` is risky unless you take great care to run this webhook on all hosts which run an apiserver which might need to make calls to this webhook. Such installs are likely to be non-portable, i.e., not easy to turn up in a new cluster.\n\nThe scheme must be \"https\"; the URL must begin with \"https://\".\n\nA path is optional, and if present may be any string permissible in a URL. You may use the path to pass an arbitrary string to the webhook, for example, a cluster identifier.\n\nAttempting to use a user or basic auth e.g. \"user:password@\" is not allowed. Fragments (\"#...\") and query parameters (\"?...\") are not allowed, either.",
...@@ -2916,6 +2921,11 @@ ...@@ -2916,6 +2921,11 @@
"path": { "path": {
"description": "`path` is an optional URL path which will be sent in any request to this service.", "description": "`path` is an optional URL path which will be sent in any request to this service.",
"type": "string" "type": "string"
},
"port": {
"description": "If specified, the port on the service that hosting webhook. Default to 443 for backward compatibility. `port` should be a valid port number (1-65535, inclusive).",
"format": "int32",
"type": "integer"
} }
}, },
"required": [ "required": [
...@@ -2951,7 +2961,7 @@ ...@@ -2951,7 +2961,7 @@
}, },
"service": { "service": {
"$ref": "#/definitions/io.k8s.api.auditregistration.v1alpha1.ServiceReference", "$ref": "#/definitions/io.k8s.api.auditregistration.v1alpha1.ServiceReference",
"description": "`service` is a reference to the service for this webhook. Either `service` or `url` must be specified.\n\nIf the webhook is running within the cluster, then you should use `service`.\n\nPort 443 will be used if it is open, otherwise it is an error." "description": "`service` is a reference to the service for this webhook. Either `service` or `url` must be specified.\n\nIf the webhook is running within the cluster, then you should use `service`."
}, },
"url": { "url": {
"description": "`url` gives the location of the webhook, in standard URL form (`scheme://host:port/path`). Exactly one of `url` or `service` must be specified.\n\nThe `host` should not refer to a service running in the cluster; use the `service` field instead. The host might be resolved via external DNS in some apiservers (e.g., `kube-apiserver` cannot resolve in-cluster DNS as that would be a layering violation). `host` may also be an IP address.\n\nPlease note that using `localhost` or `127.0.0.1` as a `host` is risky unless you take great care to run this webhook on all hosts which run an apiserver which might need to make calls to this webhook. Such installs are likely to be non-portable, i.e., not easy to turn up in a new cluster.\n\nThe scheme must be \"https\"; the URL must begin with \"https://\".\n\nA path is optional, and if present may be any string permissible in a URL. You may use the path to pass an arbitrary string to the webhook, for example, a cluster identifier.\n\nAttempting to use a user or basic auth e.g. \"user:password@\" is not allowed. Fragments (\"#...\") and query parameters (\"?...\") are not allowed, either.", "description": "`url` gives the location of the webhook, in standard URL form (`scheme://host:port/path`). Exactly one of `url` or `service` must be specified.\n\nThe `host` should not refer to a service running in the cluster; use the `service` field instead. The host might be resolved via external DNS in some apiservers (e.g., `kube-apiserver` cannot resolve in-cluster DNS as that would be a layering violation). `host` may also be an IP address.\n\nPlease note that using `localhost` or `127.0.0.1` as a `host` is risky unless you take great care to run this webhook on all hosts which run an apiserver which might need to make calls to this webhook. Such installs are likely to be non-portable, i.e., not easy to turn up in a new cluster.\n\nThe scheme must be \"https\"; the URL must begin with \"https://\".\n\nA path is optional, and if present may be any string permissible in a URL. You may use the path to pass an arbitrary string to the webhook, for example, a cluster identifier.\n\nAttempting to use a user or basic auth e.g. \"user:password@\" is not allowed. Fragments (\"#...\") and query parameters (\"?...\") are not allowed, either.",
...@@ -16765,6 +16775,11 @@ ...@@ -16765,6 +16775,11 @@
"path": { "path": {
"description": "`path` is an optional URL path which will be sent in any request to this service.", "description": "`path` is an optional URL path which will be sent in any request to this service.",
"type": "string" "type": "string"
},
"port": {
"description": "If specified, the port on the service that hosting webhook. Default to 443 for backward compatibility. `port` should be a valid port number (1-65535, inclusive).",
"format": "int32",
"type": "integer"
} }
}, },
"required": [ "required": [
...@@ -16783,7 +16798,7 @@ ...@@ -16783,7 +16798,7 @@
}, },
"service": { "service": {
"$ref": "#/definitions/io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.ServiceReference", "$ref": "#/definitions/io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.ServiceReference",
"description": "`service` is a reference to the service for this webhook. Either `service` or `url` must be specified.\n\nIf the webhook is running within the cluster, then you should use `service`.\n\nPort 443 will be used if it is open, otherwise it is an error." "description": "`service` is a reference to the service for this webhook. Either `service` or `url` must be specified.\n\nIf the webhook is running within the cluster, then you should use `service`."
}, },
"url": { "url": {
"description": "`url` gives the location of the webhook, in standard URL form (`scheme://host:port/path`). Exactly one of `url` or `service` must be specified.\n\nThe `host` should not refer to a service running in the cluster; use the `service` field instead. The host might be resolved via external DNS in some apiservers (e.g., `kube-apiserver` cannot resolve in-cluster DNS as that would be a layering violation). `host` may also be an IP address.\n\nPlease note that using `localhost` or `127.0.0.1` as a `host` is risky unless you take great care to run this webhook on all hosts which run an apiserver which might need to make calls to this webhook. Such installs are likely to be non-portable, i.e., not easy to turn up in a new cluster.\n\nThe scheme must be \"https\"; the URL must begin with \"https://\".\n\nA path is optional, and if present may be any string permissible in a URL. You may use the path to pass an arbitrary string to the webhook, for example, a cluster identifier.\n\nAttempting to use a user or basic auth e.g. \"user:password@\" is not allowed. Fragments (\"#...\") and query parameters (\"?...\") are not allowed, either.", "description": "`url` gives the location of the webhook, in standard URL form (`scheme://host:port/path`). Exactly one of `url` or `service` must be specified.\n\nThe `host` should not refer to a service running in the cluster; use the `service` field instead. The host might be resolved via external DNS in some apiservers (e.g., `kube-apiserver` cannot resolve in-cluster DNS as that would be a layering violation). `host` may also be an IP address.\n\nPlease note that using `localhost` or `127.0.0.1` as a `host` is risky unless you take great care to run this webhook on all hosts which run an apiserver which might need to make calls to this webhook. Such installs are likely to be non-portable, i.e., not easy to turn up in a new cluster.\n\nThe scheme must be \"https\"; the URL must begin with \"https://\".\n\nA path is optional, and if present may be any string permissible in a URL. You may use the path to pass an arbitrary string to the webhook, for example, a cluster identifier.\n\nAttempting to use a user or basic auth e.g. \"user:password@\" is not allowed. Fragments (\"#...\") and query parameters (\"?...\") are not allowed, either.",
...@@ -18127,6 +18142,11 @@ ...@@ -18127,6 +18142,11 @@
"namespace": { "namespace": {
"description": "Namespace is the namespace of the service", "description": "Namespace is the namespace of the service",
"type": "string" "type": "string"
},
"port": {
"description": "If specified, the port on the service that hosting webhook. Default to 443 for backward compatibility. `port` should be a valid port number (1-65535, inclusive).",
"format": "int32",
"type": "integer"
} }
}, },
"type": "object" "type": "object"
...@@ -18293,6 +18313,11 @@ ...@@ -18293,6 +18313,11 @@
"namespace": { "namespace": {
"description": "Namespace is the namespace of the service", "description": "Namespace is the namespace of the service",
"type": "string" "type": "string"
},
"port": {
"description": "If specified, the port on the service that hosting webhook. Default to 443 for backward compatibility. `port` should be a valid port number (1-65535, inclusive).",
"format": "int32",
"type": "integer"
} }
}, },
"type": "object" "type": "object"
...@@ -607,6 +607,8 @@ staging/src/k8s.io/code-generator/cmd/lister-gen/generators ...@@ -607,6 +607,8 @@ staging/src/k8s.io/code-generator/cmd/lister-gen/generators
staging/src/k8s.io/component-base/cli/flag staging/src/k8s.io/component-base/cli/flag
staging/src/k8s.io/component-base/config/v1alpha1 staging/src/k8s.io/component-base/config/v1alpha1
staging/src/k8s.io/cri-api/pkg/apis/testing staging/src/k8s.io/cri-api/pkg/apis/testing
staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/v1
staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/v1beta1
staging/src/k8s.io/kube-aggregator/pkg/controllers/autoregister staging/src/k8s.io/kube-aggregator/pkg/controllers/autoregister
staging/src/k8s.io/kube-proxy/config/v1alpha1 staging/src/k8s.io/kube-proxy/config/v1alpha1
staging/src/k8s.io/kubelet/config/v1beta1 staging/src/k8s.io/kubelet/config/v1beta1
......
...@@ -311,8 +311,6 @@ type WebhookClientConfig struct { ...@@ -311,8 +311,6 @@ type WebhookClientConfig struct {
// //
// If the webhook is running within the cluster, then you should use `service`. // If the webhook is running within the cluster, then you should use `service`.
// //
// Port 443 will be used if it is open, otherwise it is an error.
//
// +optional // +optional
Service *ServiceReference Service *ServiceReference
...@@ -335,4 +333,9 @@ type ServiceReference struct { ...@@ -335,4 +333,9 @@ type ServiceReference struct {
// this service. // this service.
// +optional // +optional
Path *string Path *string
// If specified, the port on the service that hosting webhook.
// `port` should be a valid port number (1-65535, inclusive).
// +optional
Port int32
} }
...@@ -22,6 +22,7 @@ go_library( ...@@ -22,6 +22,7 @@ go_library(
"//staging/src/k8s.io/apimachinery/pkg/conversion:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/conversion:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/utils/pointer:go_default_library",
], ],
) )
......
...@@ -20,6 +20,7 @@ import ( ...@@ -20,6 +20,7 @@ import (
admissionregistrationv1beta1 "k8s.io/api/admissionregistration/v1beta1" admissionregistrationv1beta1 "k8s.io/api/admissionregistration/v1beta1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
utilpointer "k8s.io/utils/pointer"
) )
func addDefaultingFuncs(scheme *runtime.Scheme) error { func addDefaultingFuncs(scheme *runtime.Scheme) error {
...@@ -56,3 +57,10 @@ func SetDefaults_Rule(obj *admissionregistrationv1beta1.Rule) { ...@@ -56,3 +57,10 @@ func SetDefaults_Rule(obj *admissionregistrationv1beta1.Rule) {
obj.Scope = &s obj.Scope = &s
} }
} }
// SetDefaults_ServiceReference sets defaults for Webhook's ServiceReference
func SetDefaults_ServiceReference(obj *admissionregistrationv1beta1.ServiceReference) {
if obj.Port == nil {
obj.Port = utilpointer.Int32Ptr(443)
}
}
...@@ -132,7 +132,17 @@ func RegisterConversions(s *runtime.Scheme) error { ...@@ -132,7 +132,17 @@ func RegisterConversions(s *runtime.Scheme) error {
func autoConvert_v1beta1_MutatingWebhookConfiguration_To_admissionregistration_MutatingWebhookConfiguration(in *v1beta1.MutatingWebhookConfiguration, out *admissionregistration.MutatingWebhookConfiguration, s conversion.Scope) error { func autoConvert_v1beta1_MutatingWebhookConfiguration_To_admissionregistration_MutatingWebhookConfiguration(in *v1beta1.MutatingWebhookConfiguration, out *admissionregistration.MutatingWebhookConfiguration, s conversion.Scope) error {
out.ObjectMeta = in.ObjectMeta out.ObjectMeta = in.ObjectMeta
out.Webhooks = *(*[]admissionregistration.Webhook)(unsafe.Pointer(&in.Webhooks)) if in.Webhooks != nil {
in, out := &in.Webhooks, &out.Webhooks
*out = make([]admissionregistration.Webhook, len(*in))
for i := range *in {
if err := Convert_v1beta1_Webhook_To_admissionregistration_Webhook(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.Webhooks = nil
}
return nil return nil
} }
...@@ -143,7 +153,17 @@ func Convert_v1beta1_MutatingWebhookConfiguration_To_admissionregistration_Mutat ...@@ -143,7 +153,17 @@ func Convert_v1beta1_MutatingWebhookConfiguration_To_admissionregistration_Mutat
func autoConvert_admissionregistration_MutatingWebhookConfiguration_To_v1beta1_MutatingWebhookConfiguration(in *admissionregistration.MutatingWebhookConfiguration, out *v1beta1.MutatingWebhookConfiguration, s conversion.Scope) error { func autoConvert_admissionregistration_MutatingWebhookConfiguration_To_v1beta1_MutatingWebhookConfiguration(in *admissionregistration.MutatingWebhookConfiguration, out *v1beta1.MutatingWebhookConfiguration, s conversion.Scope) error {
out.ObjectMeta = in.ObjectMeta out.ObjectMeta = in.ObjectMeta
out.Webhooks = *(*[]v1beta1.Webhook)(unsafe.Pointer(&in.Webhooks)) if in.Webhooks != nil {
in, out := &in.Webhooks, &out.Webhooks
*out = make([]v1beta1.Webhook, len(*in))
for i := range *in {
if err := Convert_admissionregistration_Webhook_To_v1beta1_Webhook(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.Webhooks = nil
}
return nil return nil
} }
...@@ -154,7 +174,17 @@ func Convert_admissionregistration_MutatingWebhookConfiguration_To_v1beta1_Mutat ...@@ -154,7 +174,17 @@ func Convert_admissionregistration_MutatingWebhookConfiguration_To_v1beta1_Mutat
func autoConvert_v1beta1_MutatingWebhookConfigurationList_To_admissionregistration_MutatingWebhookConfigurationList(in *v1beta1.MutatingWebhookConfigurationList, out *admissionregistration.MutatingWebhookConfigurationList, s conversion.Scope) error { func autoConvert_v1beta1_MutatingWebhookConfigurationList_To_admissionregistration_MutatingWebhookConfigurationList(in *v1beta1.MutatingWebhookConfigurationList, out *admissionregistration.MutatingWebhookConfigurationList, s conversion.Scope) error {
out.ListMeta = in.ListMeta out.ListMeta = in.ListMeta
out.Items = *(*[]admissionregistration.MutatingWebhookConfiguration)(unsafe.Pointer(&in.Items)) if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]admissionregistration.MutatingWebhookConfiguration, len(*in))
for i := range *in {
if err := Convert_v1beta1_MutatingWebhookConfiguration_To_admissionregistration_MutatingWebhookConfiguration(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.Items = nil
}
return nil return nil
} }
...@@ -165,7 +195,17 @@ func Convert_v1beta1_MutatingWebhookConfigurationList_To_admissionregistration_M ...@@ -165,7 +195,17 @@ func Convert_v1beta1_MutatingWebhookConfigurationList_To_admissionregistration_M
func autoConvert_admissionregistration_MutatingWebhookConfigurationList_To_v1beta1_MutatingWebhookConfigurationList(in *admissionregistration.MutatingWebhookConfigurationList, out *v1beta1.MutatingWebhookConfigurationList, s conversion.Scope) error { func autoConvert_admissionregistration_MutatingWebhookConfigurationList_To_v1beta1_MutatingWebhookConfigurationList(in *admissionregistration.MutatingWebhookConfigurationList, out *v1beta1.MutatingWebhookConfigurationList, s conversion.Scope) error {
out.ListMeta = in.ListMeta out.ListMeta = in.ListMeta
out.Items = *(*[]v1beta1.MutatingWebhookConfiguration)(unsafe.Pointer(&in.Items)) if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]v1beta1.MutatingWebhookConfiguration, len(*in))
for i := range *in {
if err := Convert_admissionregistration_MutatingWebhookConfiguration_To_v1beta1_MutatingWebhookConfiguration(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.Items = nil
}
return nil return nil
} }
...@@ -230,6 +270,9 @@ func autoConvert_v1beta1_ServiceReference_To_admissionregistration_ServiceRefere ...@@ -230,6 +270,9 @@ func autoConvert_v1beta1_ServiceReference_To_admissionregistration_ServiceRefere
out.Namespace = in.Namespace out.Namespace = in.Namespace
out.Name = in.Name out.Name = in.Name
out.Path = (*string)(unsafe.Pointer(in.Path)) out.Path = (*string)(unsafe.Pointer(in.Path))
if err := v1.Convert_Pointer_int32_To_int32(&in.Port, &out.Port, s); err != nil {
return err
}
return nil return nil
} }
...@@ -242,6 +285,9 @@ func autoConvert_admissionregistration_ServiceReference_To_v1beta1_ServiceRefere ...@@ -242,6 +285,9 @@ func autoConvert_admissionregistration_ServiceReference_To_v1beta1_ServiceRefere
out.Namespace = in.Namespace out.Namespace = in.Namespace
out.Name = in.Name out.Name = in.Name
out.Path = (*string)(unsafe.Pointer(in.Path)) out.Path = (*string)(unsafe.Pointer(in.Path))
if err := v1.Convert_int32_To_Pointer_int32(&in.Port, &out.Port, s); err != nil {
return err
}
return nil return nil
} }
...@@ -252,7 +298,17 @@ func Convert_admissionregistration_ServiceReference_To_v1beta1_ServiceReference( ...@@ -252,7 +298,17 @@ func Convert_admissionregistration_ServiceReference_To_v1beta1_ServiceReference(
func autoConvert_v1beta1_ValidatingWebhookConfiguration_To_admissionregistration_ValidatingWebhookConfiguration(in *v1beta1.ValidatingWebhookConfiguration, out *admissionregistration.ValidatingWebhookConfiguration, s conversion.Scope) error { func autoConvert_v1beta1_ValidatingWebhookConfiguration_To_admissionregistration_ValidatingWebhookConfiguration(in *v1beta1.ValidatingWebhookConfiguration, out *admissionregistration.ValidatingWebhookConfiguration, s conversion.Scope) error {
out.ObjectMeta = in.ObjectMeta out.ObjectMeta = in.ObjectMeta
out.Webhooks = *(*[]admissionregistration.Webhook)(unsafe.Pointer(&in.Webhooks)) if in.Webhooks != nil {
in, out := &in.Webhooks, &out.Webhooks
*out = make([]admissionregistration.Webhook, len(*in))
for i := range *in {
if err := Convert_v1beta1_Webhook_To_admissionregistration_Webhook(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.Webhooks = nil
}
return nil return nil
} }
...@@ -263,7 +319,17 @@ func Convert_v1beta1_ValidatingWebhookConfiguration_To_admissionregistration_Val ...@@ -263,7 +319,17 @@ func Convert_v1beta1_ValidatingWebhookConfiguration_To_admissionregistration_Val
func autoConvert_admissionregistration_ValidatingWebhookConfiguration_To_v1beta1_ValidatingWebhookConfiguration(in *admissionregistration.ValidatingWebhookConfiguration, out *v1beta1.ValidatingWebhookConfiguration, s conversion.Scope) error { func autoConvert_admissionregistration_ValidatingWebhookConfiguration_To_v1beta1_ValidatingWebhookConfiguration(in *admissionregistration.ValidatingWebhookConfiguration, out *v1beta1.ValidatingWebhookConfiguration, s conversion.Scope) error {
out.ObjectMeta = in.ObjectMeta out.ObjectMeta = in.ObjectMeta
out.Webhooks = *(*[]v1beta1.Webhook)(unsafe.Pointer(&in.Webhooks)) if in.Webhooks != nil {
in, out := &in.Webhooks, &out.Webhooks
*out = make([]v1beta1.Webhook, len(*in))
for i := range *in {
if err := Convert_admissionregistration_Webhook_To_v1beta1_Webhook(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.Webhooks = nil
}
return nil return nil
} }
...@@ -274,7 +340,17 @@ func Convert_admissionregistration_ValidatingWebhookConfiguration_To_v1beta1_Val ...@@ -274,7 +340,17 @@ func Convert_admissionregistration_ValidatingWebhookConfiguration_To_v1beta1_Val
func autoConvert_v1beta1_ValidatingWebhookConfigurationList_To_admissionregistration_ValidatingWebhookConfigurationList(in *v1beta1.ValidatingWebhookConfigurationList, out *admissionregistration.ValidatingWebhookConfigurationList, s conversion.Scope) error { func autoConvert_v1beta1_ValidatingWebhookConfigurationList_To_admissionregistration_ValidatingWebhookConfigurationList(in *v1beta1.ValidatingWebhookConfigurationList, out *admissionregistration.ValidatingWebhookConfigurationList, s conversion.Scope) error {
out.ListMeta = in.ListMeta out.ListMeta = in.ListMeta
out.Items = *(*[]admissionregistration.ValidatingWebhookConfiguration)(unsafe.Pointer(&in.Items)) if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]admissionregistration.ValidatingWebhookConfiguration, len(*in))
for i := range *in {
if err := Convert_v1beta1_ValidatingWebhookConfiguration_To_admissionregistration_ValidatingWebhookConfiguration(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.Items = nil
}
return nil return nil
} }
...@@ -285,7 +361,17 @@ func Convert_v1beta1_ValidatingWebhookConfigurationList_To_admissionregistration ...@@ -285,7 +361,17 @@ func Convert_v1beta1_ValidatingWebhookConfigurationList_To_admissionregistration
func autoConvert_admissionregistration_ValidatingWebhookConfigurationList_To_v1beta1_ValidatingWebhookConfigurationList(in *admissionregistration.ValidatingWebhookConfigurationList, out *v1beta1.ValidatingWebhookConfigurationList, s conversion.Scope) error { func autoConvert_admissionregistration_ValidatingWebhookConfigurationList_To_v1beta1_ValidatingWebhookConfigurationList(in *admissionregistration.ValidatingWebhookConfigurationList, out *v1beta1.ValidatingWebhookConfigurationList, s conversion.Scope) error {
out.ListMeta = in.ListMeta out.ListMeta = in.ListMeta
out.Items = *(*[]v1beta1.ValidatingWebhookConfiguration)(unsafe.Pointer(&in.Items)) if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]v1beta1.ValidatingWebhookConfiguration, len(*in))
for i := range *in {
if err := Convert_admissionregistration_ValidatingWebhookConfiguration_To_v1beta1_ValidatingWebhookConfiguration(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.Items = nil
}
return nil return nil
} }
...@@ -334,7 +420,15 @@ func Convert_admissionregistration_Webhook_To_v1beta1_Webhook(in *admissionregis ...@@ -334,7 +420,15 @@ func Convert_admissionregistration_Webhook_To_v1beta1_Webhook(in *admissionregis
func autoConvert_v1beta1_WebhookClientConfig_To_admissionregistration_WebhookClientConfig(in *v1beta1.WebhookClientConfig, out *admissionregistration.WebhookClientConfig, s conversion.Scope) error { func autoConvert_v1beta1_WebhookClientConfig_To_admissionregistration_WebhookClientConfig(in *v1beta1.WebhookClientConfig, out *admissionregistration.WebhookClientConfig, s conversion.Scope) error {
out.URL = (*string)(unsafe.Pointer(in.URL)) out.URL = (*string)(unsafe.Pointer(in.URL))
out.Service = (*admissionregistration.ServiceReference)(unsafe.Pointer(in.Service)) if in.Service != nil {
in, out := &in.Service, &out.Service
*out = new(admissionregistration.ServiceReference)
if err := Convert_v1beta1_ServiceReference_To_admissionregistration_ServiceReference(*in, *out, s); err != nil {
return err
}
} else {
out.Service = nil
}
out.CABundle = *(*[]byte)(unsafe.Pointer(&in.CABundle)) out.CABundle = *(*[]byte)(unsafe.Pointer(&in.CABundle))
return nil return nil
} }
...@@ -346,7 +440,15 @@ func Convert_v1beta1_WebhookClientConfig_To_admissionregistration_WebhookClientC ...@@ -346,7 +440,15 @@ func Convert_v1beta1_WebhookClientConfig_To_admissionregistration_WebhookClientC
func autoConvert_admissionregistration_WebhookClientConfig_To_v1beta1_WebhookClientConfig(in *admissionregistration.WebhookClientConfig, out *v1beta1.WebhookClientConfig, s conversion.Scope) error { func autoConvert_admissionregistration_WebhookClientConfig_To_v1beta1_WebhookClientConfig(in *admissionregistration.WebhookClientConfig, out *v1beta1.WebhookClientConfig, s conversion.Scope) error {
out.URL = (*string)(unsafe.Pointer(in.URL)) out.URL = (*string)(unsafe.Pointer(in.URL))
out.Service = (*v1beta1.ServiceReference)(unsafe.Pointer(in.Service)) if in.Service != nil {
in, out := &in.Service, &out.Service
*out = new(v1beta1.ServiceReference)
if err := Convert_admissionregistration_ServiceReference_To_v1beta1_ServiceReference(*in, *out, s); err != nil {
return err
}
} else {
out.Service = nil
}
out.CABundle = *(*[]byte)(unsafe.Pointer(&in.CABundle)) out.CABundle = *(*[]byte)(unsafe.Pointer(&in.CABundle))
return nil return nil
} }
......
...@@ -48,6 +48,9 @@ func SetObjectDefaults_MutatingWebhookConfiguration(in *v1beta1.MutatingWebhookC ...@@ -48,6 +48,9 @@ func SetObjectDefaults_MutatingWebhookConfiguration(in *v1beta1.MutatingWebhookC
for i := range in.Webhooks { for i := range in.Webhooks {
a := &in.Webhooks[i] a := &in.Webhooks[i]
SetDefaults_Webhook(a) SetDefaults_Webhook(a)
if a.ClientConfig.Service != nil {
SetDefaults_ServiceReference(a.ClientConfig.Service)
}
for j := range a.Rules { for j := range a.Rules {
b := &a.Rules[j] b := &a.Rules[j]
SetDefaults_Rule(&b.Rule) SetDefaults_Rule(&b.Rule)
...@@ -66,6 +69,9 @@ func SetObjectDefaults_ValidatingWebhookConfiguration(in *v1beta1.ValidatingWebh ...@@ -66,6 +69,9 @@ func SetObjectDefaults_ValidatingWebhookConfiguration(in *v1beta1.ValidatingWebh
for i := range in.Webhooks { for i := range in.Webhooks {
a := &in.Webhooks[i] a := &in.Webhooks[i]
SetDefaults_Webhook(a) SetDefaults_Webhook(a)
if a.ClientConfig.Service != nil {
SetDefaults_ServiceReference(a.ClientConfig.Service)
}
for j := range a.Rules { for j := range a.Rules {
b := &a.Rules[j] b := &a.Rules[j]
SetDefaults_Rule(&b.Rule) SetDefaults_Rule(&b.Rule)
......
...@@ -250,7 +250,7 @@ func validateWebhook(hook *admissionregistration.Webhook, fldPath *field.Path) f ...@@ -250,7 +250,7 @@ func validateWebhook(hook *admissionregistration.Webhook, fldPath *field.Path) f
case cc.URL != nil: case cc.URL != nil:
allErrors = append(allErrors, webhook.ValidateWebhookURL(fldPath.Child("clientConfig").Child("url"), *cc.URL, true)...) allErrors = append(allErrors, webhook.ValidateWebhookURL(fldPath.Child("clientConfig").Child("url"), *cc.URL, true)...)
case cc.Service != nil: case cc.Service != nil:
allErrors = append(allErrors, webhook.ValidateWebhookService(fldPath.Child("clientConfig").Child("service"), cc.Service.Name, cc.Service.Namespace, cc.Service.Path)...) allErrors = append(allErrors, webhook.ValidateWebhookService(fldPath.Child("clientConfig").Child("service"), cc.Service.Name, cc.Service.Namespace, cc.Service.Path, cc.Service.Port)...)
} }
return allErrors return allErrors
} }
......
...@@ -377,6 +377,7 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) { ...@@ -377,6 +377,7 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) {
Service: &admissionregistration.ServiceReference{ Service: &admissionregistration.ServiceReference{
Namespace: "ns", Namespace: "ns",
Name: "n", Name: "n",
Port: 443,
}, },
URL: strPtr("example.com/k8s/webhook"), URL: strPtr("example.com/k8s/webhook"),
}, },
...@@ -478,6 +479,7 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) { ...@@ -478,6 +479,7 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) {
Namespace: "ns", Namespace: "ns",
Name: "n", Name: "n",
Path: strPtr("foo/"), Path: strPtr("foo/"),
Port: 443,
}, },
}, },
}, },
...@@ -494,6 +496,7 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) { ...@@ -494,6 +496,7 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) {
Namespace: "ns", Namespace: "ns",
Name: "n", Name: "n",
Path: strPtr("/"), Path: strPtr("/"),
Port: 443,
}, },
}, },
}, },
...@@ -510,6 +513,7 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) { ...@@ -510,6 +513,7 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) {
Namespace: "ns", Namespace: "ns",
Name: "n", Name: "n",
Path: strPtr("/foo"), Path: strPtr("/foo"),
Port: 443,
}, },
}, },
}, },
...@@ -526,6 +530,7 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) { ...@@ -526,6 +530,7 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) {
Namespace: "ns", Namespace: "ns",
Name: "n", Name: "n",
Path: strPtr("//"), Path: strPtr("//"),
Port: 443,
}, },
}, },
}, },
...@@ -542,6 +547,7 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) { ...@@ -542,6 +547,7 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) {
Namespace: "ns", Namespace: "ns",
Name: "n", Name: "n",
Path: strPtr("/foo//bar/"), Path: strPtr("/foo//bar/"),
Port: 443,
}, },
}, },
}, },
...@@ -557,6 +563,7 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) { ...@@ -557,6 +563,7 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) {
Namespace: "ns", Namespace: "ns",
Name: "n", Name: "n",
Path: strPtr("/foo/bar//"), Path: strPtr("/foo/bar//"),
Port: 443,
}, },
}, },
}, },
...@@ -573,6 +580,7 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) { ...@@ -573,6 +580,7 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) {
Namespace: "ns", Namespace: "ns",
Name: "n", Name: "n",
Path: strPtr("/apis/foo.bar/v1alpha1/--bad"), Path: strPtr("/apis/foo.bar/v1alpha1/--bad"),
Port: 443,
}, },
}, },
}, },
...@@ -580,6 +588,42 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) { ...@@ -580,6 +588,42 @@ func TestValidateValidatingWebhookConfiguration(t *testing.T) {
expectedError: `clientConfig.service.path: Invalid value: "/apis/foo.bar/v1alpha1/--bad": segment[3]: a DNS-1123 subdomain`, expectedError: `clientConfig.service.path: Invalid value: "/apis/foo.bar/v1alpha1/--bad": segment[3]: a DNS-1123 subdomain`,
}, },
{ {
name: "invalid port 0",
config: newValidatingWebhookConfiguration(
[]admissionregistration.Webhook{
{
Name: "webhook.k8s.io",
ClientConfig: admissionregistration.WebhookClientConfig{
Service: &admissionregistration.ServiceReference{
Namespace: "ns",
Name: "n",
Path: strPtr("https://apis/foo.bar"),
Port: 0,
},
},
},
}, true),
expectedError: `Invalid value: 0: port is not valid: must be between 1 and 65535, inclusive`,
},
{
name: "invalid port >65535",
config: newValidatingWebhookConfiguration(
[]admissionregistration.Webhook{
{
Name: "webhook.k8s.io",
ClientConfig: admissionregistration.WebhookClientConfig{
Service: &admissionregistration.ServiceReference{
Namespace: "ns",
Name: "n",
Path: strPtr("https://apis/foo.bar"),
Port: 65536,
},
},
},
}, true),
expectedError: `Invalid value: 65536: port is not valid: must be between 1 and 65535, inclusive`,
},
{
name: "timeout seconds cannot be greater than 30", name: "timeout seconds cannot be greater than 30",
config: newValidatingWebhookConfiguration([]admissionregistration.Webhook{ config: newValidatingWebhookConfiguration([]admissionregistration.Webhook{
{ {
......
...@@ -168,8 +168,6 @@ type WebhookClientConfig struct { ...@@ -168,8 +168,6 @@ type WebhookClientConfig struct {
// //
// If the webhook is running within the cluster, then you should use `service`. // If the webhook is running within the cluster, then you should use `service`.
// //
// Port 443 will be used if it is open, otherwise it is an error.
//
// +optional // +optional
Service *ServiceReference Service *ServiceReference
...@@ -193,4 +191,9 @@ type ServiceReference struct { ...@@ -193,4 +191,9 @@ type ServiceReference struct {
// this service. // this service.
// +optional // +optional
Path *string Path *string
// If specified, the port on the service that hosting webhook.
// `port` should be a valid port number (1-65535, inclusive).
// +optional
Port int32
} }
...@@ -14,6 +14,7 @@ go_library( ...@@ -14,6 +14,7 @@ go_library(
deps = [ deps = [
"//pkg/apis/auditregistration:go_default_library", "//pkg/apis/auditregistration:go_default_library",
"//staging/src/k8s.io/api/auditregistration/v1alpha1:go_default_library", "//staging/src/k8s.io/api/auditregistration/v1alpha1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/conversion:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/conversion:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
......
...@@ -54,3 +54,10 @@ func SetDefaults_AuditSink(obj *auditregistrationv1alpha1.AuditSink) { ...@@ -54,3 +54,10 @@ func SetDefaults_AuditSink(obj *auditregistrationv1alpha1.AuditSink) {
obj.Spec.Webhook.Throttle = DefaultThrottle() obj.Spec.Webhook.Throttle = DefaultThrottle()
} }
} }
// SetDefaults_ServiceReference sets defaults for AuditSync Webhook's ServiceReference
func SetDefaults_ServiceReference(obj *auditregistrationv1alpha1.ServiceReference) {
if obj.Port == nil {
obj.Port = utilpointer.Int32Ptr(443)
}
}
...@@ -24,6 +24,7 @@ import ( ...@@ -24,6 +24,7 @@ import (
unsafe "unsafe" unsafe "unsafe"
v1alpha1 "k8s.io/api/auditregistration/v1alpha1" v1alpha1 "k8s.io/api/auditregistration/v1alpha1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
conversion "k8s.io/apimachinery/pkg/conversion" conversion "k8s.io/apimachinery/pkg/conversion"
runtime "k8s.io/apimachinery/pkg/runtime" runtime "k8s.io/apimachinery/pkg/runtime"
auditregistration "k8s.io/kubernetes/pkg/apis/auditregistration" auditregistration "k8s.io/kubernetes/pkg/apis/auditregistration"
...@@ -147,7 +148,17 @@ func Convert_auditregistration_AuditSink_To_v1alpha1_AuditSink(in *auditregistra ...@@ -147,7 +148,17 @@ func Convert_auditregistration_AuditSink_To_v1alpha1_AuditSink(in *auditregistra
func autoConvert_v1alpha1_AuditSinkList_To_auditregistration_AuditSinkList(in *v1alpha1.AuditSinkList, out *auditregistration.AuditSinkList, s conversion.Scope) error { func autoConvert_v1alpha1_AuditSinkList_To_auditregistration_AuditSinkList(in *v1alpha1.AuditSinkList, out *auditregistration.AuditSinkList, s conversion.Scope) error {
out.ListMeta = in.ListMeta out.ListMeta = in.ListMeta
out.Items = *(*[]auditregistration.AuditSink)(unsafe.Pointer(&in.Items)) if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]auditregistration.AuditSink, len(*in))
for i := range *in {
if err := Convert_v1alpha1_AuditSink_To_auditregistration_AuditSink(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.Items = nil
}
return nil return nil
} }
...@@ -158,7 +169,17 @@ func Convert_v1alpha1_AuditSinkList_To_auditregistration_AuditSinkList(in *v1alp ...@@ -158,7 +169,17 @@ func Convert_v1alpha1_AuditSinkList_To_auditregistration_AuditSinkList(in *v1alp
func autoConvert_auditregistration_AuditSinkList_To_v1alpha1_AuditSinkList(in *auditregistration.AuditSinkList, out *v1alpha1.AuditSinkList, s conversion.Scope) error { func autoConvert_auditregistration_AuditSinkList_To_v1alpha1_AuditSinkList(in *auditregistration.AuditSinkList, out *v1alpha1.AuditSinkList, s conversion.Scope) error {
out.ListMeta = in.ListMeta out.ListMeta = in.ListMeta
out.Items = *(*[]v1alpha1.AuditSink)(unsafe.Pointer(&in.Items)) if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]v1alpha1.AuditSink, len(*in))
for i := range *in {
if err := Convert_auditregistration_AuditSink_To_v1alpha1_AuditSink(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.Items = nil
}
return nil return nil
} }
...@@ -223,6 +244,9 @@ func autoConvert_v1alpha1_ServiceReference_To_auditregistration_ServiceReference ...@@ -223,6 +244,9 @@ func autoConvert_v1alpha1_ServiceReference_To_auditregistration_ServiceReference
out.Namespace = in.Namespace out.Namespace = in.Namespace
out.Name = in.Name out.Name = in.Name
out.Path = (*string)(unsafe.Pointer(in.Path)) out.Path = (*string)(unsafe.Pointer(in.Path))
if err := v1.Convert_Pointer_int32_To_int32(&in.Port, &out.Port, s); err != nil {
return err
}
return nil return nil
} }
...@@ -235,6 +259,9 @@ func autoConvert_auditregistration_ServiceReference_To_v1alpha1_ServiceReference ...@@ -235,6 +259,9 @@ func autoConvert_auditregistration_ServiceReference_To_v1alpha1_ServiceReference
out.Namespace = in.Namespace out.Namespace = in.Namespace
out.Name = in.Name out.Name = in.Name
out.Path = (*string)(unsafe.Pointer(in.Path)) out.Path = (*string)(unsafe.Pointer(in.Path))
if err := v1.Convert_int32_To_Pointer_int32(&in.Port, &out.Port, s); err != nil {
return err
}
return nil return nil
} }
...@@ -271,7 +298,15 @@ func Convert_auditregistration_Webhook_To_v1alpha1_Webhook(in *auditregistration ...@@ -271,7 +298,15 @@ func Convert_auditregistration_Webhook_To_v1alpha1_Webhook(in *auditregistration
func autoConvert_v1alpha1_WebhookClientConfig_To_auditregistration_WebhookClientConfig(in *v1alpha1.WebhookClientConfig, out *auditregistration.WebhookClientConfig, s conversion.Scope) error { func autoConvert_v1alpha1_WebhookClientConfig_To_auditregistration_WebhookClientConfig(in *v1alpha1.WebhookClientConfig, out *auditregistration.WebhookClientConfig, s conversion.Scope) error {
out.URL = (*string)(unsafe.Pointer(in.URL)) out.URL = (*string)(unsafe.Pointer(in.URL))
out.Service = (*auditregistration.ServiceReference)(unsafe.Pointer(in.Service)) if in.Service != nil {
in, out := &in.Service, &out.Service
*out = new(auditregistration.ServiceReference)
if err := Convert_v1alpha1_ServiceReference_To_auditregistration_ServiceReference(*in, *out, s); err != nil {
return err
}
} else {
out.Service = nil
}
out.CABundle = *(*[]byte)(unsafe.Pointer(&in.CABundle)) out.CABundle = *(*[]byte)(unsafe.Pointer(&in.CABundle))
return nil return nil
} }
...@@ -283,7 +318,15 @@ func Convert_v1alpha1_WebhookClientConfig_To_auditregistration_WebhookClientConf ...@@ -283,7 +318,15 @@ func Convert_v1alpha1_WebhookClientConfig_To_auditregistration_WebhookClientConf
func autoConvert_auditregistration_WebhookClientConfig_To_v1alpha1_WebhookClientConfig(in *auditregistration.WebhookClientConfig, out *v1alpha1.WebhookClientConfig, s conversion.Scope) error { func autoConvert_auditregistration_WebhookClientConfig_To_v1alpha1_WebhookClientConfig(in *auditregistration.WebhookClientConfig, out *v1alpha1.WebhookClientConfig, s conversion.Scope) error {
out.URL = (*string)(unsafe.Pointer(in.URL)) out.URL = (*string)(unsafe.Pointer(in.URL))
out.Service = (*v1alpha1.ServiceReference)(unsafe.Pointer(in.Service)) if in.Service != nil {
in, out := &in.Service, &out.Service
*out = new(v1alpha1.ServiceReference)
if err := Convert_auditregistration_ServiceReference_To_v1alpha1_ServiceReference(*in, *out, s); err != nil {
return err
}
} else {
out.Service = nil
}
out.CABundle = *(*[]byte)(unsafe.Pointer(&in.CABundle)) out.CABundle = *(*[]byte)(unsafe.Pointer(&in.CABundle))
return nil return nil
} }
......
...@@ -36,6 +36,9 @@ func RegisterDefaults(scheme *runtime.Scheme) error { ...@@ -36,6 +36,9 @@ func RegisterDefaults(scheme *runtime.Scheme) error {
func SetObjectDefaults_AuditSink(in *v1alpha1.AuditSink) { func SetObjectDefaults_AuditSink(in *v1alpha1.AuditSink) {
SetDefaults_AuditSink(in) SetDefaults_AuditSink(in)
if in.Spec.Webhook.ClientConfig.Service != nil {
SetDefaults_ServiceReference(in.Spec.Webhook.ClientConfig.Service)
}
} }
func SetObjectDefaults_AuditSinkList(in *v1alpha1.AuditSinkList) { func SetObjectDefaults_AuditSinkList(in *v1alpha1.AuditSinkList) {
......
...@@ -55,7 +55,7 @@ func ValidateWebhook(w auditregistration.Webhook, fldPath *field.Path) field.Err ...@@ -55,7 +55,7 @@ func ValidateWebhook(w auditregistration.Webhook, fldPath *field.Path) field.Err
case cc.URL != nil: case cc.URL != nil:
allErrs = append(allErrs, webhook.ValidateWebhookURL(fldPath.Child("clientConfig").Child("url"), *cc.URL, false)...) allErrs = append(allErrs, webhook.ValidateWebhookURL(fldPath.Child("clientConfig").Child("url"), *cc.URL, false)...)
case cc.Service != nil: case cc.Service != nil:
allErrs = append(allErrs, webhook.ValidateWebhookService(fldPath.Child("clientConfig").Child("service"), cc.Service.Name, cc.Service.Namespace, cc.Service.Path)...) allErrs = append(allErrs, webhook.ValidateWebhookService(fldPath.Child("clientConfig").Child("service"), cc.Service.Name, cc.Service.Namespace, cc.Service.Path, cc.Service.Port)...)
} }
return allErrs return allErrs
} }
......
...@@ -155,6 +155,7 @@ func TestValidateWebhookConfiguration(t *testing.T) { ...@@ -155,6 +155,7 @@ func TestValidateWebhookConfiguration(t *testing.T) {
Service: &auditregistration.ServiceReference{ Service: &auditregistration.ServiceReference{
Namespace: "ns", Namespace: "ns",
Name: "n", Name: "n",
Port: 443,
}, },
URL: strPtr("example.com/k8s/webhook"), URL: strPtr("example.com/k8s/webhook"),
}, },
...@@ -223,12 +224,41 @@ func TestValidateWebhookConfiguration(t *testing.T) { ...@@ -223,12 +224,41 @@ func TestValidateWebhookConfiguration(t *testing.T) {
Namespace: "ns", Namespace: "ns",
Name: "n", Name: "n",
Path: strPtr("foo/"), Path: strPtr("foo/"),
Port: 443,
}, },
}, },
}, },
expectedError: `clientConfig.service.path: Invalid value: "foo/": must start with a '/'`, expectedError: `clientConfig.service.path: Invalid value: "foo/": must start with a '/'`,
}, },
{ {
name: "invalid port >65535",
config: auditregistration.Webhook{
ClientConfig: auditregistration.WebhookClientConfig{
Service: &auditregistration.ServiceReference{
Namespace: "ns",
Name: "n",
Path: strPtr("foo/"),
Port: 65536,
},
},
},
expectedError: `Invalid value: 65536: port is not valid: must be between 1 and 65535, inclusive`,
},
{
name: "invalid port 0",
config: auditregistration.Webhook{
ClientConfig: auditregistration.WebhookClientConfig{
Service: &auditregistration.ServiceReference{
Namespace: "ns",
Name: "n",
Path: strPtr("foo/"),
Port: 0,
},
},
},
expectedError: `Invalid value: 0: port is not valid: must be between 1 and 65535, inclusive`,
},
{
name: "path accepts slash", name: "path accepts slash",
config: auditregistration.Webhook{ config: auditregistration.Webhook{
ClientConfig: auditregistration.WebhookClientConfig{ ClientConfig: auditregistration.WebhookClientConfig{
...@@ -236,6 +266,7 @@ func TestValidateWebhookConfiguration(t *testing.T) { ...@@ -236,6 +266,7 @@ func TestValidateWebhookConfiguration(t *testing.T) {
Namespace: "ns", Namespace: "ns",
Name: "n", Name: "n",
Path: strPtr("/"), Path: strPtr("/"),
Port: 443,
}, },
}, },
}, },
...@@ -249,6 +280,7 @@ func TestValidateWebhookConfiguration(t *testing.T) { ...@@ -249,6 +280,7 @@ func TestValidateWebhookConfiguration(t *testing.T) {
Namespace: "ns", Namespace: "ns",
Name: "n", Name: "n",
Path: strPtr("/foo"), Path: strPtr("/foo"),
Port: 443,
}, },
}, },
}, },
...@@ -262,6 +294,7 @@ func TestValidateWebhookConfiguration(t *testing.T) { ...@@ -262,6 +294,7 @@ func TestValidateWebhookConfiguration(t *testing.T) {
Namespace: "ns", Namespace: "ns",
Name: "n", Name: "n",
Path: strPtr("//"), Path: strPtr("//"),
Port: 443,
}, },
}, },
}, },
...@@ -275,6 +308,7 @@ func TestValidateWebhookConfiguration(t *testing.T) { ...@@ -275,6 +308,7 @@ func TestValidateWebhookConfiguration(t *testing.T) {
Namespace: "ns", Namespace: "ns",
Name: "n", Name: "n",
Path: strPtr("/foo//bar/"), Path: strPtr("/foo//bar/"),
Port: 443,
}, },
}, },
}, },
...@@ -287,6 +321,7 @@ func TestValidateWebhookConfiguration(t *testing.T) { ...@@ -287,6 +321,7 @@ func TestValidateWebhookConfiguration(t *testing.T) {
Namespace: "ns", Namespace: "ns",
Name: "n", Name: "n",
Path: strPtr("/foo/bar//"), Path: strPtr("/foo/bar//"),
Port: 443,
}, },
}, },
}, },
...@@ -300,6 +335,7 @@ func TestValidateWebhookConfiguration(t *testing.T) { ...@@ -300,6 +335,7 @@ func TestValidateWebhookConfiguration(t *testing.T) {
Namespace: "ns", Namespace: "ns",
Name: "n", Name: "n",
Path: strPtr("/apis/foo.bar/v1alpha1/--bad"), Path: strPtr("/apis/foo.bar/v1alpha1/--bad"),
Port: 443,
}, },
}, },
}, },
......
...@@ -119,6 +119,7 @@ ...@@ -119,6 +119,7 @@
- k8s.io/kube-aggregator - k8s.io/kube-aggregator
- k8s.io/kube-openapi - k8s.io/kube-openapi
- k8s.io/klog - k8s.io/klog
- k8s.io/utils
- baseImportPath: "./vendor/k8s.io/sample-apiserver/" - baseImportPath: "./vendor/k8s.io/sample-apiserver/"
allowedImports: allowedImports:
...@@ -142,6 +143,7 @@ ...@@ -142,6 +143,7 @@
- k8s.io/component-base - k8s.io/component-base
- k8s.io/klog - k8s.io/klog
- k8s.io/kube-openapi - k8s.io/kube-openapi
- k8s.io/utils
- baseImportPath: "./vendor/k8s.io/kube-openapi/" - baseImportPath: "./vendor/k8s.io/kube-openapi/"
allowedImports: allowedImports:
......
...@@ -123,6 +123,12 @@ message ServiceReference { ...@@ -123,6 +123,12 @@ message ServiceReference {
// this service. // this service.
// +optional // +optional
optional string path = 3; optional string path = 3;
// If specified, the port on the service that hosting webhook.
// Default to 443 for backward compatibility.
// `port` should be a valid port number (1-65535, inclusive).
// +optional
optional int32 port = 4;
} }
// ValidatingWebhookConfiguration describes the configuration of and admission webhook that accept or reject and object without changing it. // ValidatingWebhookConfiguration describes the configuration of and admission webhook that accept or reject and object without changing it.
...@@ -287,8 +293,6 @@ message WebhookClientConfig { ...@@ -287,8 +293,6 @@ message WebhookClientConfig {
// //
// If the webhook is running within the cluster, then you should use `service`. // If the webhook is running within the cluster, then you should use `service`.
// //
// Port 443 will be used if it is open, otherwise it is an error.
//
// +optional // +optional
optional ServiceReference service = 1; optional ServiceReference service = 1;
......
...@@ -322,8 +322,6 @@ type WebhookClientConfig struct { ...@@ -322,8 +322,6 @@ type WebhookClientConfig struct {
// //
// If the webhook is running within the cluster, then you should use `service`. // If the webhook is running within the cluster, then you should use `service`.
// //
// Port 443 will be used if it is open, otherwise it is an error.
//
// +optional // +optional
Service *ServiceReference `json:"service,omitempty" protobuf:"bytes,1,opt,name=service"` Service *ServiceReference `json:"service,omitempty" protobuf:"bytes,1,opt,name=service"`
...@@ -346,4 +344,10 @@ type ServiceReference struct { ...@@ -346,4 +344,10 @@ type ServiceReference struct {
// this service. // this service.
// +optional // +optional
Path *string `json:"path,omitempty" protobuf:"bytes,3,opt,name=path"` Path *string `json:"path,omitempty" protobuf:"bytes,3,opt,name=path"`
// If specified, the port on the service that hosting webhook.
// Default to 443 for backward compatibility.
// `port` should be a valid port number (1-65535, inclusive).
// +optional
Port *int32 `json:"port,omitempty" protobuf:"varint,4,opt,name=port"`
} }
...@@ -73,6 +73,7 @@ var map_ServiceReference = map[string]string{ ...@@ -73,6 +73,7 @@ var map_ServiceReference = map[string]string{
"namespace": "`namespace` is the namespace of the service. Required", "namespace": "`namespace` is the namespace of the service. Required",
"name": "`name` is the name of the service. Required", "name": "`name` is the name of the service. Required",
"path": "`path` is an optional URL path which will be sent in any request to this service.", "path": "`path` is an optional URL path which will be sent in any request to this service.",
"port": "If specified, the port on the service that hosting webhook. Default to 443 for backward compatibility. `port` should be a valid port number (1-65535, inclusive).",
} }
func (ServiceReference) SwaggerDoc() map[string]string { func (ServiceReference) SwaggerDoc() map[string]string {
...@@ -118,7 +119,7 @@ func (Webhook) SwaggerDoc() map[string]string { ...@@ -118,7 +119,7 @@ func (Webhook) SwaggerDoc() map[string]string {
var map_WebhookClientConfig = map[string]string{ var map_WebhookClientConfig = map[string]string{
"": "WebhookClientConfig contains the information to make a TLS connection with the webhook", "": "WebhookClientConfig contains the information to make a TLS connection with the webhook",
"url": "`url` gives the location of the webhook, in standard URL form (`scheme://host:port/path`). Exactly one of `url` or `service` must be specified.\n\nThe `host` should not refer to a service running in the cluster; use the `service` field instead. The host might be resolved via external DNS in some apiservers (e.g., `kube-apiserver` cannot resolve in-cluster DNS as that would be a layering violation). `host` may also be an IP address.\n\nPlease note that using `localhost` or `127.0.0.1` as a `host` is risky unless you take great care to run this webhook on all hosts which run an apiserver which might need to make calls to this webhook. Such installs are likely to be non-portable, i.e., not easy to turn up in a new cluster.\n\nThe scheme must be \"https\"; the URL must begin with \"https://\".\n\nA path is optional, and if present may be any string permissible in a URL. You may use the path to pass an arbitrary string to the webhook, for example, a cluster identifier.\n\nAttempting to use a user or basic auth e.g. \"user:password@\" is not allowed. Fragments (\"#...\") and query parameters (\"?...\") are not allowed, either.", "url": "`url` gives the location of the webhook, in standard URL form (`scheme://host:port/path`). Exactly one of `url` or `service` must be specified.\n\nThe `host` should not refer to a service running in the cluster; use the `service` field instead. The host might be resolved via external DNS in some apiservers (e.g., `kube-apiserver` cannot resolve in-cluster DNS as that would be a layering violation). `host` may also be an IP address.\n\nPlease note that using `localhost` or `127.0.0.1` as a `host` is risky unless you take great care to run this webhook on all hosts which run an apiserver which might need to make calls to this webhook. Such installs are likely to be non-portable, i.e., not easy to turn up in a new cluster.\n\nThe scheme must be \"https\"; the URL must begin with \"https://\".\n\nA path is optional, and if present may be any string permissible in a URL. You may use the path to pass an arbitrary string to the webhook, for example, a cluster identifier.\n\nAttempting to use a user or basic auth e.g. \"user:password@\" is not allowed. Fragments (\"#...\") and query parameters (\"?...\") are not allowed, either.",
"service": "`service` is a reference to the service for this webhook. Either `service` or `url` must be specified.\n\nIf the webhook is running within the cluster, then you should use `service`.\n\nPort 443 will be used if it is open, otherwise it is an error.", "service": "`service` is a reference to the service for this webhook. Either `service` or `url` must be specified.\n\nIf the webhook is running within the cluster, then you should use `service`.",
"caBundle": "`caBundle` is a PEM encoded CA bundle which will be used to validate the webhook's server certificate. If unspecified, system trust roots on the apiserver are used.", "caBundle": "`caBundle` is a PEM encoded CA bundle which will be used to validate the webhook's server certificate. If unspecified, system trust roots on the apiserver are used.",
} }
......
...@@ -157,6 +157,11 @@ func (in *ServiceReference) DeepCopyInto(out *ServiceReference) { ...@@ -157,6 +157,11 @@ func (in *ServiceReference) DeepCopyInto(out *ServiceReference) {
*out = new(string) *out = new(string)
**out = **in **out = **in
} }
if in.Port != nil {
in, out := &in.Port, &out.Port
*out = new(int32)
**out = **in
}
return return
} }
......
...@@ -83,6 +83,12 @@ message ServiceReference { ...@@ -83,6 +83,12 @@ message ServiceReference {
// this service. // this service.
// +optional // +optional
optional string path = 3; optional string path = 3;
// If specified, the port on the service that hosting webhook.
// Default to 443 for backward compatibility.
// `port` should be a valid port number (1-65535, inclusive).
// +optional
optional int32 port = 4;
} }
// Webhook holds the configuration of the webhook // Webhook holds the configuration of the webhook
...@@ -132,8 +138,6 @@ message WebhookClientConfig { ...@@ -132,8 +138,6 @@ message WebhookClientConfig {
// //
// If the webhook is running within the cluster, then you should use `service`. // If the webhook is running within the cluster, then you should use `service`.
// //
// Port 443 will be used if it is open, otherwise it is an error.
//
// +optional // +optional
optional ServiceReference service = 2; optional ServiceReference service = 2;
......
...@@ -166,8 +166,6 @@ type WebhookClientConfig struct { ...@@ -166,8 +166,6 @@ type WebhookClientConfig struct {
// //
// If the webhook is running within the cluster, then you should use `service`. // If the webhook is running within the cluster, then you should use `service`.
// //
// Port 443 will be used if it is open, otherwise it is an error.
//
// +optional // +optional
Service *ServiceReference `json:"service,omitempty" protobuf:"bytes,2,opt,name=service"` Service *ServiceReference `json:"service,omitempty" protobuf:"bytes,2,opt,name=service"`
...@@ -191,4 +189,10 @@ type ServiceReference struct { ...@@ -191,4 +189,10 @@ type ServiceReference struct {
// this service. // this service.
// +optional // +optional
Path *string `json:"path,omitempty" protobuf:"bytes,3,opt,name=path"` Path *string `json:"path,omitempty" protobuf:"bytes,3,opt,name=path"`
// If specified, the port on the service that hosting webhook.
// Default to 443 for backward compatibility.
// `port` should be a valid port number (1-65535, inclusive).
// +optional
Port *int32 `json:"port,omitempty" protobuf:"varint,4,opt,name=port"`
} }
...@@ -70,6 +70,7 @@ var map_ServiceReference = map[string]string{ ...@@ -70,6 +70,7 @@ var map_ServiceReference = map[string]string{
"namespace": "`namespace` is the namespace of the service. Required", "namespace": "`namespace` is the namespace of the service. Required",
"name": "`name` is the name of the service. Required", "name": "`name` is the name of the service. Required",
"path": "`path` is an optional URL path which will be sent in any request to this service.", "path": "`path` is an optional URL path which will be sent in any request to this service.",
"port": "If specified, the port on the service that hosting webhook. Default to 443 for backward compatibility. `port` should be a valid port number (1-65535, inclusive).",
} }
func (ServiceReference) SwaggerDoc() map[string]string { func (ServiceReference) SwaggerDoc() map[string]string {
...@@ -89,7 +90,7 @@ func (Webhook) SwaggerDoc() map[string]string { ...@@ -89,7 +90,7 @@ func (Webhook) SwaggerDoc() map[string]string {
var map_WebhookClientConfig = map[string]string{ var map_WebhookClientConfig = map[string]string{
"": "WebhookClientConfig contains the information to make a connection with the webhook", "": "WebhookClientConfig contains the information to make a connection with the webhook",
"url": "`url` gives the location of the webhook, in standard URL form (`scheme://host:port/path`). Exactly one of `url` or `service` must be specified.\n\nThe `host` should not refer to a service running in the cluster; use the `service` field instead. The host might be resolved via external DNS in some apiservers (e.g., `kube-apiserver` cannot resolve in-cluster DNS as that would be a layering violation). `host` may also be an IP address.\n\nPlease note that using `localhost` or `127.0.0.1` as a `host` is risky unless you take great care to run this webhook on all hosts which run an apiserver which might need to make calls to this webhook. Such installs are likely to be non-portable, i.e., not easy to turn up in a new cluster.\n\nThe scheme must be \"https\"; the URL must begin with \"https://\".\n\nA path is optional, and if present may be any string permissible in a URL. You may use the path to pass an arbitrary string to the webhook, for example, a cluster identifier.\n\nAttempting to use a user or basic auth e.g. \"user:password@\" is not allowed. Fragments (\"#...\") and query parameters (\"?...\") are not allowed, either.", "url": "`url` gives the location of the webhook, in standard URL form (`scheme://host:port/path`). Exactly one of `url` or `service` must be specified.\n\nThe `host` should not refer to a service running in the cluster; use the `service` field instead. The host might be resolved via external DNS in some apiservers (e.g., `kube-apiserver` cannot resolve in-cluster DNS as that would be a layering violation). `host` may also be an IP address.\n\nPlease note that using `localhost` or `127.0.0.1` as a `host` is risky unless you take great care to run this webhook on all hosts which run an apiserver which might need to make calls to this webhook. Such installs are likely to be non-portable, i.e., not easy to turn up in a new cluster.\n\nThe scheme must be \"https\"; the URL must begin with \"https://\".\n\nA path is optional, and if present may be any string permissible in a URL. You may use the path to pass an arbitrary string to the webhook, for example, a cluster identifier.\n\nAttempting to use a user or basic auth e.g. \"user:password@\" is not allowed. Fragments (\"#...\") and query parameters (\"?...\") are not allowed, either.",
"service": "`service` is a reference to the service for this webhook. Either `service` or `url` must be specified.\n\nIf the webhook is running within the cluster, then you should use `service`.\n\nPort 443 will be used if it is open, otherwise it is an error.", "service": "`service` is a reference to the service for this webhook. Either `service` or `url` must be specified.\n\nIf the webhook is running within the cluster, then you should use `service`.",
"caBundle": "`caBundle` is a PEM encoded CA bundle which will be used to validate the webhook's server certificate. If unspecified, system trust roots on the apiserver are used.", "caBundle": "`caBundle` is a PEM encoded CA bundle which will be used to validate the webhook's server certificate. If unspecified, system trust roots on the apiserver are used.",
} }
......
...@@ -131,6 +131,11 @@ func (in *ServiceReference) DeepCopyInto(out *ServiceReference) { ...@@ -131,6 +131,11 @@ func (in *ServiceReference) DeepCopyInto(out *ServiceReference) {
*out = new(string) *out = new(string)
**out = **in **out = **in
} }
if in.Port != nil {
in, out := &in.Port, &out.Port
*out = new(int32)
**out = **in
}
return return
} }
......
...@@ -33,6 +33,7 @@ require ( ...@@ -33,6 +33,7 @@ require (
k8s.io/component-base v0.0.0 k8s.io/component-base v0.0.0
k8s.io/klog v0.0.0-20190306015804-8e90cee79f82 k8s.io/klog v0.0.0-20190306015804-8e90cee79f82
k8s.io/kube-openapi v0.0.0-20190228160746-b3a7cee44a30 k8s.io/kube-openapi v0.0.0-20190228160746-b3a7cee44a30
k8s.io/utils v0.0.0-20190221042446-c2654d5206da
sigs.k8s.io/yaml v1.1.0 sigs.k8s.io/yaml v1.1.0
) )
......
...@@ -132,8 +132,6 @@ type WebhookClientConfig struct { ...@@ -132,8 +132,6 @@ type WebhookClientConfig struct {
// //
// If the webhook is running within the cluster, then you should use `service`. // If the webhook is running within the cluster, then you should use `service`.
// //
// Port 443 will be used if it is open, otherwise it is an error.
//
// +optional // +optional
Service *ServiceReference Service *ServiceReference
...@@ -156,6 +154,11 @@ type ServiceReference struct { ...@@ -156,6 +154,11 @@ type ServiceReference struct {
// this service. // this service.
// +optional // +optional
Path *string Path *string
// If specified, the port on the service that hosting webhook.
// `port` should be a valid port number (1-65535, inclusive).
// +optional
Port int32
} }
// CustomResourceDefinitionVersion describes a version for CRD. // CustomResourceDefinitionVersion describes a version for CRD.
......
...@@ -34,6 +34,7 @@ go_library( ...@@ -34,6 +34,7 @@ go_library(
"//staging/src/k8s.io/apimachinery/pkg/util/json:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/json:go_default_library",
"//vendor/github.com/gogo/protobuf/proto:go_default_library", "//vendor/github.com/gogo/protobuf/proto:go_default_library",
"//vendor/github.com/gogo/protobuf/sortkeys:go_default_library", "//vendor/github.com/gogo/protobuf/sortkeys:go_default_library",
"//vendor/k8s.io/utils/pointer:go_default_library",
], ],
) )
......
...@@ -20,6 +20,7 @@ import ( ...@@ -20,6 +20,7 @@ import (
"strings" "strings"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
utilpointer "k8s.io/utils/pointer"
) )
func addDefaultingFuncs(scheme *runtime.Scheme) error { func addDefaultingFuncs(scheme *runtime.Scheme) error {
...@@ -73,6 +74,13 @@ func SetDefaults_CustomResourceDefinitionSpec(obj *CustomResourceDefinitionSpec) ...@@ -73,6 +74,13 @@ func SetDefaults_CustomResourceDefinitionSpec(obj *CustomResourceDefinitionSpec)
} }
} }
// SetDefaults_ServiceReference sets defaults for Webhook's ServiceReference
func SetDefaults_ServiceReference(obj *ServiceReference) {
if obj.Port == nil {
obj.Port = utilpointer.Int32Ptr(443)
}
}
// hasPerVersionColumns returns true if a CRD uses per-version columns. // hasPerVersionColumns returns true if a CRD uses per-version columns.
func hasPerVersionColumns(versions []CustomResourceDefinitionVersion) bool { func hasPerVersionColumns(versions []CustomResourceDefinitionVersion) bool {
for _, v := range versions { for _, v := range versions {
......
...@@ -482,6 +482,12 @@ message ServiceReference { ...@@ -482,6 +482,12 @@ message ServiceReference {
// this service. // this service.
// +optional // +optional
optional string path = 3; optional string path = 3;
// If specified, the port on the service that hosting webhook.
// Default to 443 for backward compatibility.
// `port` should be a valid port number (1-65535, inclusive).
// +optional
optional int32 port = 4;
} }
// WebhookClientConfig contains the information to make a TLS // WebhookClientConfig contains the information to make a TLS
...@@ -521,8 +527,6 @@ message WebhookClientConfig { ...@@ -521,8 +527,6 @@ message WebhookClientConfig {
// //
// If the webhook is running within the cluster, then you should use `service`. // If the webhook is running within the cluster, then you should use `service`.
// //
// Port 443 will be used if it is open, otherwise it is an error.
//
// +optional // +optional
optional ServiceReference service = 1; optional ServiceReference service = 1;
......
...@@ -140,8 +140,6 @@ type WebhookClientConfig struct { ...@@ -140,8 +140,6 @@ type WebhookClientConfig struct {
// //
// If the webhook is running within the cluster, then you should use `service`. // If the webhook is running within the cluster, then you should use `service`.
// //
// Port 443 will be used if it is open, otherwise it is an error.
//
// +optional // +optional
Service *ServiceReference `json:"service,omitempty" protobuf:"bytes,1,opt,name=service"` Service *ServiceReference `json:"service,omitempty" protobuf:"bytes,1,opt,name=service"`
...@@ -164,6 +162,12 @@ type ServiceReference struct { ...@@ -164,6 +162,12 @@ type ServiceReference struct {
// this service. // this service.
// +optional // +optional
Path *string `json:"path,omitempty" protobuf:"bytes,3,opt,name=path"` Path *string `json:"path,omitempty" protobuf:"bytes,3,opt,name=path"`
// If specified, the port on the service that hosting webhook.
// Default to 443 for backward compatibility.
// `port` should be a valid port number (1-65535, inclusive).
// +optional
Port *int32 `json:"port,omitempty" protobuf:"varint,4,opt,name=port"`
} }
// CustomResourceDefinitionVersion describes a version for CRD. // CustomResourceDefinitionVersion describes a version for CRD.
......
...@@ -24,6 +24,7 @@ import ( ...@@ -24,6 +24,7 @@ import (
unsafe "unsafe" unsafe "unsafe"
apiextensions "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions" apiextensions "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
conversion "k8s.io/apimachinery/pkg/conversion" conversion "k8s.io/apimachinery/pkg/conversion"
runtime "k8s.io/apimachinery/pkg/runtime" runtime "k8s.io/apimachinery/pkg/runtime"
) )
...@@ -295,7 +296,15 @@ func Convert_apiextensions_CustomResourceColumnDefinition_To_v1beta1_CustomResou ...@@ -295,7 +296,15 @@ func Convert_apiextensions_CustomResourceColumnDefinition_To_v1beta1_CustomResou
func autoConvert_v1beta1_CustomResourceConversion_To_apiextensions_CustomResourceConversion(in *CustomResourceConversion, out *apiextensions.CustomResourceConversion, s conversion.Scope) error { func autoConvert_v1beta1_CustomResourceConversion_To_apiextensions_CustomResourceConversion(in *CustomResourceConversion, out *apiextensions.CustomResourceConversion, s conversion.Scope) error {
out.Strategy = apiextensions.ConversionStrategyType(in.Strategy) out.Strategy = apiextensions.ConversionStrategyType(in.Strategy)
out.WebhookClientConfig = (*apiextensions.WebhookClientConfig)(unsafe.Pointer(in.WebhookClientConfig)) if in.WebhookClientConfig != nil {
in, out := &in.WebhookClientConfig, &out.WebhookClientConfig
*out = new(apiextensions.WebhookClientConfig)
if err := Convert_v1beta1_WebhookClientConfig_To_apiextensions_WebhookClientConfig(*in, *out, s); err != nil {
return err
}
} else {
out.WebhookClientConfig = nil
}
out.ConversionReviewVersions = *(*[]string)(unsafe.Pointer(&in.ConversionReviewVersions)) out.ConversionReviewVersions = *(*[]string)(unsafe.Pointer(&in.ConversionReviewVersions))
return nil return nil
} }
...@@ -307,7 +316,15 @@ func Convert_v1beta1_CustomResourceConversion_To_apiextensions_CustomResourceCon ...@@ -307,7 +316,15 @@ func Convert_v1beta1_CustomResourceConversion_To_apiextensions_CustomResourceCon
func autoConvert_apiextensions_CustomResourceConversion_To_v1beta1_CustomResourceConversion(in *apiextensions.CustomResourceConversion, out *CustomResourceConversion, s conversion.Scope) error { func autoConvert_apiextensions_CustomResourceConversion_To_v1beta1_CustomResourceConversion(in *apiextensions.CustomResourceConversion, out *CustomResourceConversion, s conversion.Scope) error {
out.Strategy = ConversionStrategyType(in.Strategy) out.Strategy = ConversionStrategyType(in.Strategy)
out.WebhookClientConfig = (*WebhookClientConfig)(unsafe.Pointer(in.WebhookClientConfig)) if in.WebhookClientConfig != nil {
in, out := &in.WebhookClientConfig, &out.WebhookClientConfig
*out = new(WebhookClientConfig)
if err := Convert_apiextensions_WebhookClientConfig_To_v1beta1_WebhookClientConfig(*in, *out, s); err != nil {
return err
}
} else {
out.WebhookClientConfig = nil
}
out.ConversionReviewVersions = *(*[]string)(unsafe.Pointer(&in.ConversionReviewVersions)) out.ConversionReviewVersions = *(*[]string)(unsafe.Pointer(&in.ConversionReviewVersions))
return nil return nil
} }
...@@ -478,7 +495,15 @@ func autoConvert_v1beta1_CustomResourceDefinitionSpec_To_apiextensions_CustomRes ...@@ -478,7 +495,15 @@ func autoConvert_v1beta1_CustomResourceDefinitionSpec_To_apiextensions_CustomRes
out.Versions = nil out.Versions = nil
} }
out.AdditionalPrinterColumns = *(*[]apiextensions.CustomResourceColumnDefinition)(unsafe.Pointer(&in.AdditionalPrinterColumns)) out.AdditionalPrinterColumns = *(*[]apiextensions.CustomResourceColumnDefinition)(unsafe.Pointer(&in.AdditionalPrinterColumns))
out.Conversion = (*apiextensions.CustomResourceConversion)(unsafe.Pointer(in.Conversion)) if in.Conversion != nil {
in, out := &in.Conversion, &out.Conversion
*out = new(apiextensions.CustomResourceConversion)
if err := Convert_v1beta1_CustomResourceConversion_To_apiextensions_CustomResourceConversion(*in, *out, s); err != nil {
return err
}
} else {
out.Conversion = nil
}
return nil return nil
} }
...@@ -516,7 +541,15 @@ func autoConvert_apiextensions_CustomResourceDefinitionSpec_To_v1beta1_CustomRes ...@@ -516,7 +541,15 @@ func autoConvert_apiextensions_CustomResourceDefinitionSpec_To_v1beta1_CustomRes
out.Versions = nil out.Versions = nil
} }
out.AdditionalPrinterColumns = *(*[]CustomResourceColumnDefinition)(unsafe.Pointer(&in.AdditionalPrinterColumns)) out.AdditionalPrinterColumns = *(*[]CustomResourceColumnDefinition)(unsafe.Pointer(&in.AdditionalPrinterColumns))
out.Conversion = (*CustomResourceConversion)(unsafe.Pointer(in.Conversion)) if in.Conversion != nil {
in, out := &in.Conversion, &out.Conversion
*out = new(CustomResourceConversion)
if err := Convert_apiextensions_CustomResourceConversion_To_v1beta1_CustomResourceConversion(*in, *out, s); err != nil {
return err
}
} else {
out.Conversion = nil
}
return nil return nil
} }
...@@ -1228,6 +1261,9 @@ func autoConvert_v1beta1_ServiceReference_To_apiextensions_ServiceReference(in * ...@@ -1228,6 +1261,9 @@ func autoConvert_v1beta1_ServiceReference_To_apiextensions_ServiceReference(in *
out.Namespace = in.Namespace out.Namespace = in.Namespace
out.Name = in.Name out.Name = in.Name
out.Path = (*string)(unsafe.Pointer(in.Path)) out.Path = (*string)(unsafe.Pointer(in.Path))
if err := v1.Convert_Pointer_int32_To_int32(&in.Port, &out.Port, s); err != nil {
return err
}
return nil return nil
} }
...@@ -1240,6 +1276,9 @@ func autoConvert_apiextensions_ServiceReference_To_v1beta1_ServiceReference(in * ...@@ -1240,6 +1276,9 @@ func autoConvert_apiextensions_ServiceReference_To_v1beta1_ServiceReference(in *
out.Namespace = in.Namespace out.Namespace = in.Namespace
out.Name = in.Name out.Name = in.Name
out.Path = (*string)(unsafe.Pointer(in.Path)) out.Path = (*string)(unsafe.Pointer(in.Path))
if err := v1.Convert_int32_To_Pointer_int32(&in.Port, &out.Port, s); err != nil {
return err
}
return nil return nil
} }
...@@ -1250,7 +1289,15 @@ func Convert_apiextensions_ServiceReference_To_v1beta1_ServiceReference(in *apie ...@@ -1250,7 +1289,15 @@ func Convert_apiextensions_ServiceReference_To_v1beta1_ServiceReference(in *apie
func autoConvert_v1beta1_WebhookClientConfig_To_apiextensions_WebhookClientConfig(in *WebhookClientConfig, out *apiextensions.WebhookClientConfig, s conversion.Scope) error { func autoConvert_v1beta1_WebhookClientConfig_To_apiextensions_WebhookClientConfig(in *WebhookClientConfig, out *apiextensions.WebhookClientConfig, s conversion.Scope) error {
out.URL = (*string)(unsafe.Pointer(in.URL)) out.URL = (*string)(unsafe.Pointer(in.URL))
out.Service = (*apiextensions.ServiceReference)(unsafe.Pointer(in.Service)) if in.Service != nil {
in, out := &in.Service, &out.Service
*out = new(apiextensions.ServiceReference)
if err := Convert_v1beta1_ServiceReference_To_apiextensions_ServiceReference(*in, *out, s); err != nil {
return err
}
} else {
out.Service = nil
}
out.CABundle = *(*[]byte)(unsafe.Pointer(&in.CABundle)) out.CABundle = *(*[]byte)(unsafe.Pointer(&in.CABundle))
return nil return nil
} }
...@@ -1262,7 +1309,15 @@ func Convert_v1beta1_WebhookClientConfig_To_apiextensions_WebhookClientConfig(in ...@@ -1262,7 +1309,15 @@ func Convert_v1beta1_WebhookClientConfig_To_apiextensions_WebhookClientConfig(in
func autoConvert_apiextensions_WebhookClientConfig_To_v1beta1_WebhookClientConfig(in *apiextensions.WebhookClientConfig, out *WebhookClientConfig, s conversion.Scope) error { func autoConvert_apiextensions_WebhookClientConfig_To_v1beta1_WebhookClientConfig(in *apiextensions.WebhookClientConfig, out *WebhookClientConfig, s conversion.Scope) error {
out.URL = (*string)(unsafe.Pointer(in.URL)) out.URL = (*string)(unsafe.Pointer(in.URL))
out.Service = (*ServiceReference)(unsafe.Pointer(in.Service)) if in.Service != nil {
in, out := &in.Service, &out.Service
*out = new(ServiceReference)
if err := Convert_apiextensions_ServiceReference_To_v1beta1_ServiceReference(*in, *out, s); err != nil {
return err
}
} else {
out.Service = nil
}
out.CABundle = *(*[]byte)(unsafe.Pointer(&in.CABundle)) out.CABundle = *(*[]byte)(unsafe.Pointer(&in.CABundle))
return nil return nil
} }
......
...@@ -607,6 +607,11 @@ func (in *ServiceReference) DeepCopyInto(out *ServiceReference) { ...@@ -607,6 +607,11 @@ func (in *ServiceReference) DeepCopyInto(out *ServiceReference) {
*out = new(string) *out = new(string)
**out = **in **out = **in
} }
if in.Port != nil {
in, out := &in.Port, &out.Port
*out = new(int32)
**out = **in
}
return return
} }
......
...@@ -38,6 +38,13 @@ func RegisterDefaults(scheme *runtime.Scheme) error { ...@@ -38,6 +38,13 @@ func RegisterDefaults(scheme *runtime.Scheme) error {
func SetObjectDefaults_CustomResourceDefinition(in *CustomResourceDefinition) { func SetObjectDefaults_CustomResourceDefinition(in *CustomResourceDefinition) {
SetDefaults_CustomResourceDefinition(in) SetDefaults_CustomResourceDefinition(in)
SetDefaults_CustomResourceDefinitionSpec(&in.Spec) SetDefaults_CustomResourceDefinitionSpec(&in.Spec)
if in.Spec.Conversion != nil {
if in.Spec.Conversion.WebhookClientConfig != nil {
if in.Spec.Conversion.WebhookClientConfig.Service != nil {
SetDefaults_ServiceReference(in.Spec.Conversion.WebhookClientConfig.Service)
}
}
}
} }
func SetObjectDefaults_CustomResourceDefinitionList(in *CustomResourceDefinitionList) { func SetObjectDefaults_CustomResourceDefinitionList(in *CustomResourceDefinitionList) {
......
...@@ -311,7 +311,7 @@ func validateCustomResourceConversion(conversion *apiextensions.CustomResourceCo ...@@ -311,7 +311,7 @@ func validateCustomResourceConversion(conversion *apiextensions.CustomResourceCo
case cc.URL != nil: case cc.URL != nil:
allErrs = append(allErrs, webhook.ValidateWebhookURL(fldPath.Child("webhookClientConfig").Child("url"), *cc.URL, true)...) allErrs = append(allErrs, webhook.ValidateWebhookURL(fldPath.Child("webhookClientConfig").Child("url"), *cc.URL, true)...)
case cc.Service != nil: case cc.Service != nil:
allErrs = append(allErrs, webhook.ValidateWebhookService(fldPath.Child("webhookClientConfig").Child("service"), cc.Service.Name, cc.Service.Namespace, cc.Service.Path)...) allErrs = append(allErrs, webhook.ValidateWebhookService(fldPath.Child("webhookClientConfig").Child("service"), cc.Service.Name, cc.Service.Namespace, cc.Service.Path, cc.Service.Port)...)
} }
} }
allErrs = append(allErrs, validateConversionReviewVersions(conversion.ConversionReviewVersions, requireRecognizedVersion, fldPath.Child("conversionReviewVersions"))...) allErrs = append(allErrs, validateConversionReviewVersions(conversion.ConversionReviewVersions, requireRecognizedVersion, fldPath.Child("conversionReviewVersions"))...)
......
...@@ -68,6 +68,94 @@ func TestValidateCustomResourceDefinition(t *testing.T) { ...@@ -68,6 +68,94 @@ func TestValidateCustomResourceDefinition(t *testing.T) {
errors []validationMatch errors []validationMatch
}{ }{
{ {
name: "webhookconfig: invalid port 0",
resource: &apiextensions.CustomResourceDefinition{
ObjectMeta: metav1.ObjectMeta{Name: "plural.group.com"},
Spec: apiextensions.CustomResourceDefinitionSpec{
Group: "group.com",
Scope: apiextensions.ResourceScope("Cluster"),
Names: apiextensions.CustomResourceDefinitionNames{
Plural: "plural",
Singular: "singular",
Kind: "Plural",
ListKind: "PluralList",
},
Versions: []apiextensions.CustomResourceDefinitionVersion{
{
Name: "version",
Served: true,
Storage: true,
},
{
Name: "version2",
Served: true,
Storage: false,
},
},
Conversion: &apiextensions.CustomResourceConversion{
Strategy: apiextensions.ConversionStrategyType("Webhook"),
WebhookClientConfig: &apiextensions.WebhookClientConfig{
Service: &apiextensions.ServiceReference{
Name: "n",
Namespace: "ns",
Port: 0,
},
},
},
},
Status: apiextensions.CustomResourceDefinitionStatus{
StoredVersions: []string{"version"},
},
},
errors: []validationMatch{
invalid("spec", "conversion", "webhookClientConfig", "service", "port"),
},
},
{
name: "webhookconfig: invalid port 65536",
resource: &apiextensions.CustomResourceDefinition{
ObjectMeta: metav1.ObjectMeta{Name: "plural.group.com"},
Spec: apiextensions.CustomResourceDefinitionSpec{
Group: "group.com",
Scope: apiextensions.ResourceScope("Cluster"),
Names: apiextensions.CustomResourceDefinitionNames{
Plural: "plural",
Singular: "singular",
Kind: "Plural",
ListKind: "PluralList",
},
Versions: []apiextensions.CustomResourceDefinitionVersion{
{
Name: "version",
Served: true,
Storage: true,
},
{
Name: "version2",
Served: true,
Storage: false,
},
},
Conversion: &apiextensions.CustomResourceConversion{
Strategy: apiextensions.ConversionStrategyType("Webhook"),
WebhookClientConfig: &apiextensions.WebhookClientConfig{
Service: &apiextensions.ServiceReference{
Name: "n",
Namespace: "ns",
Port: 65536,
},
},
},
},
Status: apiextensions.CustomResourceDefinitionStatus{
StoredVersions: []string{"version"},
},
},
errors: []validationMatch{
invalid("spec", "conversion", "webhookClientConfig", "service", "port"),
},
},
{
name: "webhookconfig: both service and URL provided", name: "webhookconfig: both service and URL provided",
resource: &apiextensions.CustomResourceDefinition{ resource: &apiextensions.CustomResourceDefinition{
ObjectMeta: metav1.ObjectMeta{Name: "plural.group.com"}, ObjectMeta: metav1.ObjectMeta{Name: "plural.group.com"},
......
...@@ -75,6 +75,7 @@ func webhookClientConfigForCRD(crd *internal.CustomResourceDefinition) *webhook. ...@@ -75,6 +75,7 @@ func webhookClientConfigForCRD(crd *internal.CustomResourceDefinition) *webhook.
ret.Service = &webhook.ClientConfigService{ ret.Service = &webhook.ClientConfigService{
Name: apiConfig.Service.Name, Name: apiConfig.Service.Name,
Namespace: apiConfig.Service.Namespace, Namespace: apiConfig.Service.Namespace,
Port: apiConfig.Service.Port,
} }
if apiConfig.Service.Path != nil { if apiConfig.Service.Path != nil {
ret.Service.Path = *apiConfig.Service.Path ret.Service.Path = *apiConfig.Service.Path
......
...@@ -129,6 +129,6 @@ type serviceResolver struct { ...@@ -129,6 +129,6 @@ type serviceResolver struct {
services v1.ServiceLister services v1.ServiceLister
} }
func (r *serviceResolver) ResolveEndpoint(namespace, name string) (*url.URL, error) { func (r *serviceResolver) ResolveEndpoint(namespace, name string, port int32) (*url.URL, error) {
return proxy.ResolveCluster(r.services, namespace, name) return proxy.ResolveCluster(r.services, namespace, name, port)
} }
...@@ -32,7 +32,7 @@ type WantsServiceResolver interface { ...@@ -32,7 +32,7 @@ type WantsServiceResolver interface {
// ServiceResolver knows how to convert a service reference into an actual // ServiceResolver knows how to convert a service reference into an actual
// location. // location.
type ServiceResolver interface { type ServiceResolver interface {
ResolveEndpoint(namespace, name string) (*url.URL, error) ResolveEndpoint(namespace, name string, port int32) (*url.URL, error)
} }
// WantsAuthenticationInfoResolverWrapper defines a function that wraps the standard AuthenticationInfoResolver // WantsAuthenticationInfoResolverWrapper defines a function that wraps the standard AuthenticationInfoResolver
......
...@@ -30,7 +30,7 @@ func (doNothingAdmission) Handles(o admission.Operation) bool { return false } ...@@ -30,7 +30,7 @@ func (doNothingAdmission) Handles(o admission.Operation) bool { return false }
type fakeServiceResolver struct{} type fakeServiceResolver struct{}
func (f *fakeServiceResolver) ResolveEndpoint(namespace, name string) (*url.URL, error) { func (f *fakeServiceResolver) ResolveEndpoint(namespace, name string, port int32) (*url.URL, error) {
return nil, nil return nil, nil
} }
......
...@@ -33,7 +33,7 @@ func NewServiceResolver(base url.URL) webhook.ServiceResolver { ...@@ -33,7 +33,7 @@ func NewServiceResolver(base url.URL) webhook.ServiceResolver {
return &serviceResolver{base} return &serviceResolver{base}
} }
func (f serviceResolver) ResolveEndpoint(namespace, name string) (*url.URL, error) { func (f serviceResolver) ResolveEndpoint(namespace, name string, port int32) (*url.URL, error) {
if namespace == "failResolve" { if namespace == "failResolve" {
return nil, fmt.Errorf("couldn't resolve service location") return nil, fmt.Errorf("couldn't resolve service location")
} }
......
...@@ -34,6 +34,11 @@ func HookClientConfigForWebhook(w *v1beta1.Webhook) webhook.ClientConfig { ...@@ -34,6 +34,11 @@ func HookClientConfigForWebhook(w *v1beta1.Webhook) webhook.ClientConfig {
Name: w.ClientConfig.Service.Name, Name: w.ClientConfig.Service.Name,
Namespace: w.ClientConfig.Service.Namespace, Namespace: w.ClientConfig.Service.Namespace,
} }
if w.ClientConfig.Service.Port != nil {
ret.Service.Port = *w.ClientConfig.Service.Port
} else {
ret.Service.Port = 443
}
if w.ClientConfig.Service.Path != nil { if w.ClientConfig.Service.Path != nil {
ret.Service.Path = *w.ClientConfig.Service.Path ret.Service.Path = *w.ClientConfig.Service.Path
} }
......
...@@ -35,5 +35,6 @@ go_test( ...@@ -35,5 +35,6 @@ go_test(
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/util/webhook:go_default_library", "//staging/src/k8s.io/apiserver/pkg/util/webhook:go_default_library",
"//vendor/github.com/stretchr/testify/require:go_default_library", "//vendor/github.com/stretchr/testify/require:go_default_library",
"//vendor/k8s.io/utils/pointer:go_default_library",
], ],
) )
...@@ -35,6 +35,12 @@ func HookClientConfigForSink(a *v1alpha1.AuditSink) webhook.ClientConfig { ...@@ -35,6 +35,12 @@ func HookClientConfigForSink(a *v1alpha1.AuditSink) webhook.ClientConfig {
Name: c.Service.Name, Name: c.Service.Name,
Namespace: c.Service.Namespace, Namespace: c.Service.Namespace,
} }
if c.Service.Port != nil {
ret.Service.Port = *c.Service.Port
} else {
ret.Service.Port = 443
}
if c.Service.Path != nil { if c.Service.Path != nil {
ret.Service.Path = *c.Service.Path ret.Service.Path = *c.Service.Path
} }
......
...@@ -24,6 +24,7 @@ import ( ...@@ -24,6 +24,7 @@ import (
auditregv1alpha1 "k8s.io/api/auditregistration/v1alpha1" auditregv1alpha1 "k8s.io/api/auditregistration/v1alpha1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apiserver/pkg/util/webhook" "k8s.io/apiserver/pkg/util/webhook"
"k8s.io/utils/pointer"
) )
func TestHookClientConfigForSink(t *testing.T) { func TestHookClientConfigForSink(t *testing.T) {
...@@ -48,6 +49,7 @@ func TestHookClientConfigForSink(t *testing.T) { ...@@ -48,6 +49,7 @@ func TestHookClientConfigForSink(t *testing.T) {
Name: "test", Name: "test",
Path: &path, Path: &path,
Namespace: "test", Namespace: "test",
Port: pointer.Int32Ptr(123),
}, },
}, },
}, },
...@@ -60,6 +62,7 @@ func TestHookClientConfigForSink(t *testing.T) { ...@@ -60,6 +62,7 @@ func TestHookClientConfigForSink(t *testing.T) {
Name: "test", Name: "test",
Namespace: "test", Namespace: "test",
Path: path, Path: path,
Port: 123,
}, },
}, },
}, },
......
...@@ -27,7 +27,6 @@ go_library( ...@@ -27,7 +27,6 @@ go_library(
deps = [ deps = [
"//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/intstr:go_default_library",
"//staging/src/k8s.io/client-go/listers/core/v1:go_default_library", "//staging/src/k8s.io/client-go/listers/core/v1:go_default_library",
], ],
) )
......
...@@ -26,28 +26,25 @@ import ( ...@@ -26,28 +26,25 @@ import (
"k8s.io/api/core/v1" "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/errors"
listersv1 "k8s.io/client-go/listers/core/v1" listersv1 "k8s.io/client-go/listers/core/v1"
"k8s.io/apimachinery/pkg/util/intstr"
) )
// findServicePort finds the service port by name or numerically. // findServicePort finds the service port by name or numerically.
func findServicePort(svc *v1.Service, port intstr.IntOrString) (*v1.ServicePort, error) { func findServicePort(svc *v1.Service, port int32) (*v1.ServicePort, error) {
for _, svcPort := range svc.Spec.Ports { for _, svcPort := range svc.Spec.Ports {
if (port.Type == intstr.Int && int32(svcPort.Port) == port.IntVal) || (port.Type == intstr.String && svcPort.Name == port.StrVal) { if svcPort.Port == port {
return &svcPort, nil return &svcPort, nil
} }
} }
return nil, errors.NewServiceUnavailable(fmt.Sprintf("no service port %q found for service %q", port.String(), svc.Name)) return nil, errors.NewServiceUnavailable(fmt.Sprintf("no service port %q found for service %q", port, svc.Name))
} }
// ResourceLocation returns a URL to which one can send traffic for the specified service. // ResourceLocation returns a URL to which one can send traffic for the specified service.
func ResolveEndpoint(services listersv1.ServiceLister, endpoints listersv1.EndpointsLister, namespace, id string) (*url.URL, error) { func ResolveEndpoint(services listersv1.ServiceLister, endpoints listersv1.EndpointsLister, namespace, id string, port int32) (*url.URL, error) {
svc, err := services.Services(namespace).Get(id) svc, err := services.Services(namespace).Get(id)
if err != nil { if err != nil {
return nil, err return nil, err
} }
port := intstr.FromInt(443)
svcPort, err := findServicePort(svc, port) svcPort, err := findServicePort(svc, port)
if err != nil { if err != nil {
return nil, err return nil, err
...@@ -92,14 +89,12 @@ func ResolveEndpoint(services listersv1.ServiceLister, endpoints listersv1.Endpo ...@@ -92,14 +89,12 @@ func ResolveEndpoint(services listersv1.ServiceLister, endpoints listersv1.Endpo
return nil, errors.NewServiceUnavailable(fmt.Sprintf("no endpoints available for service %q", id)) return nil, errors.NewServiceUnavailable(fmt.Sprintf("no endpoints available for service %q", id))
} }
func ResolveCluster(services listersv1.ServiceLister, namespace, id string) (*url.URL, error) { func ResolveCluster(services listersv1.ServiceLister, namespace, id string, port int32) (*url.URL, error) {
svc, err := services.Services(namespace).Get(id) svc, err := services.Services(namespace).Get(id)
if err != nil { if err != nil {
return nil, err return nil, err
} }
port := intstr.FromInt(443)
switch { switch {
case svc.Spec.Type == v1.ServiceTypeClusterIP && svc.Spec.ClusterIP == v1.ClusterIPNone: case svc.Spec.Type == v1.ServiceTypeClusterIP && svc.Spec.ClusterIP == v1.ClusterIPNone:
return nil, fmt.Errorf(`cannot route to service with ClusterIP "None"`) return nil, fmt.Errorf(`cannot route to service with ClusterIP "None"`)
...@@ -114,12 +109,9 @@ func ResolveCluster(services listersv1.ServiceLister, namespace, id string) (*ur ...@@ -114,12 +109,9 @@ func ResolveCluster(services listersv1.ServiceLister, namespace, id string) (*ur
Host: net.JoinHostPort(svc.Spec.ClusterIP, fmt.Sprintf("%d", svcPort.Port)), Host: net.JoinHostPort(svc.Spec.ClusterIP, fmt.Sprintf("%d", svcPort.Port)),
}, nil }, nil
case svc.Spec.Type == v1.ServiceTypeExternalName: case svc.Spec.Type == v1.ServiceTypeExternalName:
if port.Type != intstr.Int {
return nil, fmt.Errorf("named ports not supported")
}
return &url.URL{ return &url.URL{
Scheme: "https", Scheme: "https",
Host: net.JoinHostPort(svc.Spec.ExternalName, port.String()), Host: net.JoinHostPort(svc.Spec.ExternalName, fmt.Sprintf("%d", port)),
}, nil }, nil
default: default:
return nil, fmt.Errorf("unsupported service type %q", svc.Spec.Type) return nil, fmt.Errorf("unsupported service type %q", svc.Spec.Type)
......
...@@ -234,10 +234,10 @@ func TestResolve(t *testing.T) { ...@@ -234,10 +234,10 @@ func TestResolve(t *testing.T) {
} }
} }
clusterURL, err := ResolveCluster(serviceLister, "one", "alfa") clusterURL, err := ResolveCluster(serviceLister, "one", "alfa", 443)
check("cluster", test.clusterMode, clusterURL, err) check("cluster", test.clusterMode, clusterURL, err)
endpointURL, err := ResolveEndpoint(serviceLister, endpointLister, "one", "alfa") endpointURL, err := ResolveEndpoint(serviceLister, endpointLister, "one", "alfa", 443)
check("endpoint", test.endpointMode, endpointURL, err) check("endpoint", test.endpointMode, endpointURL, err)
} }
} }
...@@ -49,6 +49,7 @@ type ClientConfigService struct { ...@@ -49,6 +49,7 @@ type ClientConfigService struct {
Name string Name string
Namespace string Namespace string
Path string Path string
Port int32
} }
// ClientManager builds REST clients to talk to webhooks. It caches the clients // ClientManager builds REST clients to talk to webhooks. It caches the clients
...@@ -164,7 +165,11 @@ func (cm *ClientManager) HookClient(cc ClientConfig) (*rest.RESTClient, error) { ...@@ -164,7 +165,11 @@ func (cm *ClientManager) HookClient(cc ClientConfig) (*rest.RESTClient, error) {
} }
cfg.Dial = func(ctx context.Context, network, addr string) (net.Conn, error) { cfg.Dial = func(ctx context.Context, network, addr string) (net.Conn, error) {
if addr == host { if addr == host {
u, err := cm.serviceResolver.ResolveEndpoint(cc.Service.Namespace, cc.Service.Name) port := cc.Service.Port
if port == 0 {
port = 443
}
u, err := cm.serviceResolver.ResolveEndpoint(cc.Service.Namespace, cc.Service.Name, port)
if err != nil { if err != nil {
return nil, err return nil, err
} }
......
...@@ -24,7 +24,7 @@ import ( ...@@ -24,7 +24,7 @@ import (
// ServiceResolver knows how to convert a service reference into an actual location. // ServiceResolver knows how to convert a service reference into an actual location.
type ServiceResolver interface { type ServiceResolver interface {
ResolveEndpoint(namespace, name string) (*url.URL, error) ResolveEndpoint(namespace, name string, port int32) (*url.URL, error)
} }
type defaultServiceResolver struct{} type defaultServiceResolver struct{}
...@@ -35,12 +35,13 @@ func NewDefaultServiceResolver() ServiceResolver { ...@@ -35,12 +35,13 @@ func NewDefaultServiceResolver() ServiceResolver {
} }
// ResolveEndpoint constructs a service URL from a given namespace and name // ResolveEndpoint constructs a service URL from a given namespace and name
// note that the name and namespace are required and by default all created addresses use HTTPS scheme. // note that the name, namespace, and port are required and by default all
// created addresses use HTTPS scheme.
// for example: // for example:
// name=ross namespace=andromeda resolves to https://ross.andromeda.svc:443 // name=ross namespace=andromeda resolves to https://ross.andromeda.svc:443
func (sr defaultServiceResolver) ResolveEndpoint(namespace, name string) (*url.URL, error) { func (sr defaultServiceResolver) ResolveEndpoint(namespace, name string, port int32) (*url.URL, error) {
if len(name) == 0 || len(namespace) == 0 { if len(name) == 0 || len(namespace) == 0 || port == 0 {
return nil, errors.New("cannot resolve an empty service name or namespace") return nil, errors.New("cannot resolve an empty service name or namespace or port")
} }
return &url.URL{Scheme: "https", Host: fmt.Sprintf("%s.%s.svc:443", name, namespace)}, nil return &url.URL{Scheme: "https", Host: fmt.Sprintf("%s.%s.svc:%d", name, namespace, port)}, nil
} }
...@@ -25,22 +25,25 @@ func TestDefaultServiceResolver(t *testing.T) { ...@@ -25,22 +25,25 @@ func TestDefaultServiceResolver(t *testing.T) {
scenarios := []struct { scenarios := []struct {
serviceName string serviceName string
serviceNamespace string serviceNamespace string
port int32
expectedOutput string expectedOutput string
expectError bool expectError bool
}{ }{
// scenario 1: a service name along with a namespace resolves // scenario 1: a service name along with a namespace resolves
{serviceName: "ross", serviceNamespace: "andromeda", expectedOutput: "https://ross.andromeda.svc:443"}, {serviceName: "ross", serviceNamespace: "andromeda", port: 443, expectedOutput: "https://ross.andromeda.svc:443"},
// scenario 2: a service name without a namespace does not resolve // scenario 2: a service name without a namespace does not resolve
{serviceName: "ross", expectError: true}, {serviceName: "ross", expectError: true},
// scenario 3: cannot resolve an empty service name // scenario 3: cannot resolve an empty service name
{serviceNamespace: "andromeda", expectError: true}, {serviceNamespace: "andromeda", expectError: true},
// scenario 1: a service name along with a namespace and different port resolves
{serviceName: "ross", serviceNamespace: "andromeda", port: 1002, expectedOutput: "https://ross.andromeda.svc:1002"},
} }
// act // act
for index, scenario := range scenarios { for index, scenario := range scenarios {
t.Run(fmt.Sprintf("scenario %d", index), func(t *testing.T) { t.Run(fmt.Sprintf("scenario %d", index), func(t *testing.T) {
target := defaultServiceResolver{} target := defaultServiceResolver{}
serviceURL, err := target.ResolveEndpoint(scenario.serviceNamespace, scenario.serviceName) serviceURL, err := target.ResolveEndpoint(scenario.serviceNamespace, scenario.serviceName, scenario.port)
if err != nil && !scenario.expectError { if err != nil && !scenario.expectError {
t.Errorf("unexpected error has occurred = %v", err) t.Errorf("unexpected error has occurred = %v", err)
......
...@@ -51,7 +51,7 @@ func ValidateWebhookURL(fldPath *field.Path, URL string, forceHttps bool) field. ...@@ -51,7 +51,7 @@ func ValidateWebhookURL(fldPath *field.Path, URL string, forceHttps bool) field.
return allErrors return allErrors
} }
func ValidateWebhookService(fldPath *field.Path, namespace, name string, path *string) field.ErrorList { func ValidateWebhookService(fldPath *field.Path, namespace, name string, path *string, port int32) field.ErrorList {
var allErrors field.ErrorList var allErrors field.ErrorList
if len(name) == 0 { if len(name) == 0 {
...@@ -62,6 +62,10 @@ func ValidateWebhookService(fldPath *field.Path, namespace, name string, path *s ...@@ -62,6 +62,10 @@ func ValidateWebhookService(fldPath *field.Path, namespace, name string, path *s
allErrors = append(allErrors, field.Required(fldPath.Child("namespace"), "service namespace is required")) allErrors = append(allErrors, field.Required(fldPath.Child("namespace"), "service namespace is required"))
} }
if errs := validation.IsValidPortNum(int(port)); errs != nil {
allErrors = append(allErrors, field.Invalid(fldPath.Child("port"), port, "port is not valid: "+strings.Join(errs, ", ")))
}
if path == nil { if path == nil {
return allErrors return allErrors
} }
......
...@@ -23,6 +23,7 @@ require ( ...@@ -23,6 +23,7 @@ require (
k8s.io/component-base v0.0.0 k8s.io/component-base v0.0.0
k8s.io/klog v0.0.0-20190306015804-8e90cee79f82 k8s.io/klog v0.0.0-20190306015804-8e90cee79f82
k8s.io/kube-openapi v0.0.0-20190228160746-b3a7cee44a30 k8s.io/kube-openapi v0.0.0-20190228160746-b3a7cee44a30
k8s.io/utils v0.0.0-20190221042446-c2654d5206da
) )
replace ( replace (
......
...@@ -34,6 +34,11 @@ type ServiceReference struct { ...@@ -34,6 +34,11 @@ type ServiceReference struct {
Namespace string Namespace string
// Name is the name of the service // Name is the name of the service
Name string Name string
// If specified, the port on the service that hosting the service.
// Default to 443 for backward compatibility.
// `port` should be a valid port number (1-65535, inclusive).
// +optional
Port int32
} }
// APIServiceSpec contains information for locating and communicating with a server. // APIServiceSpec contains information for locating and communicating with a server.
......
...@@ -8,12 +8,14 @@ load( ...@@ -8,12 +8,14 @@ load(
go_library( go_library(
name = "go_default_library", name = "go_default_library",
srcs = [ srcs = [
"defaults.go",
"doc.go", "doc.go",
"generated.pb.go", "generated.pb.go",
"register.go", "register.go",
"types.go", "types.go",
"zz_generated.conversion.go", "zz_generated.conversion.go",
"zz_generated.deepcopy.go", "zz_generated.deepcopy.go",
"zz_generated.defaults.go",
], ],
importmap = "k8s.io/kubernetes/vendor/k8s.io/kube-aggregator/pkg/apis/apiregistration/v1", importmap = "k8s.io/kubernetes/vendor/k8s.io/kube-aggregator/pkg/apis/apiregistration/v1",
importpath = "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1", importpath = "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1",
...@@ -24,6 +26,7 @@ go_library( ...@@ -24,6 +26,7 @@ go_library(
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration:go_default_library", "//staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration:go_default_library",
"//vendor/github.com/gogo/protobuf/proto:go_default_library", "//vendor/github.com/gogo/protobuf/proto:go_default_library",
"//vendor/k8s.io/utils/pointer:go_default_library",
], ],
) )
......
/*
Copyright 2019 The Kubernetes Authors.
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 v1
import (
"k8s.io/apimachinery/pkg/runtime"
utilpointer "k8s.io/utils/pointer"
)
func addDefaultingFuncs(scheme *runtime.Scheme) error {
return RegisterDefaults(scheme)
}
// SetDefaults_ServiceReference sets defaults for AuditSync Webhook's ServiceReference
func SetDefaults_ServiceReference(obj *ServiceReference) {
if obj.Port == nil {
obj.Port = utilpointer.Int32Ptr(443)
}
}
...@@ -19,6 +19,7 @@ limitations under the License. ...@@ -19,6 +19,7 @@ limitations under the License.
// +k8s:conversion-gen=k8s.io/kube-aggregator/pkg/apis/apiregistration // +k8s:conversion-gen=k8s.io/kube-aggregator/pkg/apis/apiregistration
// +k8s:openapi-gen=true // +k8s:openapi-gen=true
// +groupName=apiregistration.k8s.io // +groupName=apiregistration.k8s.io
// +k8s:defaulter-gen=TypeMeta
// Package v1 contains the API Registration API, which is responsible for // Package v1 contains the API Registration API, which is responsible for
// registering an API `Group`/`Version` with another kubernetes like API server. // registering an API `Group`/`Version` with another kubernetes like API server.
......
...@@ -130,5 +130,11 @@ message ServiceReference { ...@@ -130,5 +130,11 @@ message ServiceReference {
// Name is the name of the service // Name is the name of the service
optional string name = 2; optional string name = 2;
// If specified, the port on the service that hosting webhook.
// Default to 443 for backward compatibility.
// `port` should be a valid port number (1-65535, inclusive).
// +optional
optional int32 port = 3;
} }
...@@ -47,7 +47,7 @@ func init() { ...@@ -47,7 +47,7 @@ func init() {
// We only register manually written functions here. The registration of the // We only register manually written functions here. The registration of the
// generated functions takes place in the generated files. The separation // generated functions takes place in the generated files. The separation
// makes the code compile even when the generated files are missing. // makes the code compile even when the generated files are missing.
localSchemeBuilder.Register(addKnownTypes) localSchemeBuilder.Register(addKnownTypes, addDefaultingFuncs)
} }
// Adds the list of known types to the given scheme. // Adds the list of known types to the given scheme.
......
...@@ -34,6 +34,11 @@ type ServiceReference struct { ...@@ -34,6 +34,11 @@ type ServiceReference struct {
Namespace string `json:"namespace,omitempty" protobuf:"bytes,1,opt,name=namespace"` Namespace string `json:"namespace,omitempty" protobuf:"bytes,1,opt,name=namespace"`
// Name is the name of the service // Name is the name of the service
Name string `json:"name,omitempty" protobuf:"bytes,2,opt,name=name"` Name string `json:"name,omitempty" protobuf:"bytes,2,opt,name=name"`
// If specified, the port on the service that hosting webhook.
// Default to 443 for backward compatibility.
// `port` should be a valid port number (1-65535, inclusive).
// +optional
Port *int32 `json:"port,omitempty" protobuf:"varint,3,opt,name=port"`
} }
// APIServiceSpec contains information for locating and communicating with a server. // APIServiceSpec contains information for locating and communicating with a server.
......
...@@ -23,6 +23,7 @@ package v1 ...@@ -23,6 +23,7 @@ package v1
import ( import (
unsafe "unsafe" unsafe "unsafe"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
conversion "k8s.io/apimachinery/pkg/conversion" conversion "k8s.io/apimachinery/pkg/conversion"
runtime "k8s.io/apimachinery/pkg/runtime" runtime "k8s.io/apimachinery/pkg/runtime"
apiregistration "k8s.io/kube-aggregator/pkg/apis/apiregistration" apiregistration "k8s.io/kube-aggregator/pkg/apis/apiregistration"
...@@ -160,7 +161,17 @@ func Convert_apiregistration_APIServiceCondition_To_v1_APIServiceCondition(in *a ...@@ -160,7 +161,17 @@ func Convert_apiregistration_APIServiceCondition_To_v1_APIServiceCondition(in *a
func autoConvert_v1_APIServiceList_To_apiregistration_APIServiceList(in *APIServiceList, out *apiregistration.APIServiceList, s conversion.Scope) error { func autoConvert_v1_APIServiceList_To_apiregistration_APIServiceList(in *APIServiceList, out *apiregistration.APIServiceList, s conversion.Scope) error {
out.ListMeta = in.ListMeta out.ListMeta = in.ListMeta
out.Items = *(*[]apiregistration.APIService)(unsafe.Pointer(&in.Items)) if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]apiregistration.APIService, len(*in))
for i := range *in {
if err := Convert_v1_APIService_To_apiregistration_APIService(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.Items = nil
}
return nil return nil
} }
...@@ -171,7 +182,17 @@ func Convert_v1_APIServiceList_To_apiregistration_APIServiceList(in *APIServiceL ...@@ -171,7 +182,17 @@ func Convert_v1_APIServiceList_To_apiregistration_APIServiceList(in *APIServiceL
func autoConvert_apiregistration_APIServiceList_To_v1_APIServiceList(in *apiregistration.APIServiceList, out *APIServiceList, s conversion.Scope) error { func autoConvert_apiregistration_APIServiceList_To_v1_APIServiceList(in *apiregistration.APIServiceList, out *APIServiceList, s conversion.Scope) error {
out.ListMeta = in.ListMeta out.ListMeta = in.ListMeta
out.Items = *(*[]APIService)(unsafe.Pointer(&in.Items)) if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]APIService, len(*in))
for i := range *in {
if err := Convert_apiregistration_APIService_To_v1_APIService(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.Items = nil
}
return nil return nil
} }
...@@ -181,7 +202,15 @@ func Convert_apiregistration_APIServiceList_To_v1_APIServiceList(in *apiregistra ...@@ -181,7 +202,15 @@ func Convert_apiregistration_APIServiceList_To_v1_APIServiceList(in *apiregistra
} }
func autoConvert_v1_APIServiceSpec_To_apiregistration_APIServiceSpec(in *APIServiceSpec, out *apiregistration.APIServiceSpec, s conversion.Scope) error { func autoConvert_v1_APIServiceSpec_To_apiregistration_APIServiceSpec(in *APIServiceSpec, out *apiregistration.APIServiceSpec, s conversion.Scope) error {
out.Service = (*apiregistration.ServiceReference)(unsafe.Pointer(in.Service)) if in.Service != nil {
in, out := &in.Service, &out.Service
*out = new(apiregistration.ServiceReference)
if err := Convert_v1_ServiceReference_To_apiregistration_ServiceReference(*in, *out, s); err != nil {
return err
}
} else {
out.Service = nil
}
out.Group = in.Group out.Group = in.Group
out.Version = in.Version out.Version = in.Version
out.InsecureSkipTLSVerify = in.InsecureSkipTLSVerify out.InsecureSkipTLSVerify = in.InsecureSkipTLSVerify
...@@ -197,7 +226,15 @@ func Convert_v1_APIServiceSpec_To_apiregistration_APIServiceSpec(in *APIServiceS ...@@ -197,7 +226,15 @@ func Convert_v1_APIServiceSpec_To_apiregistration_APIServiceSpec(in *APIServiceS
} }
func autoConvert_apiregistration_APIServiceSpec_To_v1_APIServiceSpec(in *apiregistration.APIServiceSpec, out *APIServiceSpec, s conversion.Scope) error { func autoConvert_apiregistration_APIServiceSpec_To_v1_APIServiceSpec(in *apiregistration.APIServiceSpec, out *APIServiceSpec, s conversion.Scope) error {
out.Service = (*ServiceReference)(unsafe.Pointer(in.Service)) if in.Service != nil {
in, out := &in.Service, &out.Service
*out = new(ServiceReference)
if err := Convert_apiregistration_ServiceReference_To_v1_ServiceReference(*in, *out, s); err != nil {
return err
}
} else {
out.Service = nil
}
out.Group = in.Group out.Group = in.Group
out.Version = in.Version out.Version = in.Version
out.InsecureSkipTLSVerify = in.InsecureSkipTLSVerify out.InsecureSkipTLSVerify = in.InsecureSkipTLSVerify
...@@ -235,6 +272,9 @@ func Convert_apiregistration_APIServiceStatus_To_v1_APIServiceStatus(in *apiregi ...@@ -235,6 +272,9 @@ func Convert_apiregistration_APIServiceStatus_To_v1_APIServiceStatus(in *apiregi
func autoConvert_v1_ServiceReference_To_apiregistration_ServiceReference(in *ServiceReference, out *apiregistration.ServiceReference, s conversion.Scope) error { func autoConvert_v1_ServiceReference_To_apiregistration_ServiceReference(in *ServiceReference, out *apiregistration.ServiceReference, s conversion.Scope) error {
out.Namespace = in.Namespace out.Namespace = in.Namespace
out.Name = in.Name out.Name = in.Name
if err := metav1.Convert_Pointer_int32_To_int32(&in.Port, &out.Port, s); err != nil {
return err
}
return nil return nil
} }
...@@ -246,6 +286,9 @@ func Convert_v1_ServiceReference_To_apiregistration_ServiceReference(in *Service ...@@ -246,6 +286,9 @@ func Convert_v1_ServiceReference_To_apiregistration_ServiceReference(in *Service
func autoConvert_apiregistration_ServiceReference_To_v1_ServiceReference(in *apiregistration.ServiceReference, out *ServiceReference, s conversion.Scope) error { func autoConvert_apiregistration_ServiceReference_To_v1_ServiceReference(in *apiregistration.ServiceReference, out *ServiceReference, s conversion.Scope) error {
out.Namespace = in.Namespace out.Namespace = in.Namespace
out.Name = in.Name out.Name = in.Name
if err := metav1.Convert_int32_To_Pointer_int32(&in.Port, &out.Port, s); err != nil {
return err
}
return nil return nil
} }
......
...@@ -108,7 +108,7 @@ func (in *APIServiceSpec) DeepCopyInto(out *APIServiceSpec) { ...@@ -108,7 +108,7 @@ func (in *APIServiceSpec) DeepCopyInto(out *APIServiceSpec) {
if in.Service != nil { if in.Service != nil {
in, out := &in.Service, &out.Service in, out := &in.Service, &out.Service
*out = new(ServiceReference) *out = new(ServiceReference)
**out = **in (*in).DeepCopyInto(*out)
} }
if in.CABundle != nil { if in.CABundle != nil {
in, out := &in.CABundle, &out.CABundle in, out := &in.CABundle, &out.CABundle
...@@ -154,6 +154,11 @@ func (in *APIServiceStatus) DeepCopy() *APIServiceStatus { ...@@ -154,6 +154,11 @@ func (in *APIServiceStatus) DeepCopy() *APIServiceStatus {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ServiceReference) DeepCopyInto(out *ServiceReference) { func (in *ServiceReference) DeepCopyInto(out *ServiceReference) {
*out = *in *out = *in
if in.Port != nil {
in, out := &in.Port, &out.Port
*out = new(int32)
**out = **in
}
return return
} }
......
// +build !ignore_autogenerated
/*
Copyright The Kubernetes Authors.
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.
*/
// Code generated by defaulter-gen. DO NOT EDIT.
package v1
import (
runtime "k8s.io/apimachinery/pkg/runtime"
)
// RegisterDefaults adds defaulters functions to the given scheme.
// Public to allow building arbitrary schemes.
// All generated defaulters are covering - they call all nested defaulters.
func RegisterDefaults(scheme *runtime.Scheme) error {
scheme.AddTypeDefaultingFunc(&APIService{}, func(obj interface{}) { SetObjectDefaults_APIService(obj.(*APIService)) })
scheme.AddTypeDefaultingFunc(&APIServiceList{}, func(obj interface{}) { SetObjectDefaults_APIServiceList(obj.(*APIServiceList)) })
return nil
}
func SetObjectDefaults_APIService(in *APIService) {
if in.Spec.Service != nil {
SetDefaults_ServiceReference(in.Spec.Service)
}
}
func SetObjectDefaults_APIServiceList(in *APIServiceList) {
for i := range in.Items {
a := &in.Items[i]
SetObjectDefaults_APIService(a)
}
}
...@@ -8,12 +8,14 @@ load( ...@@ -8,12 +8,14 @@ load(
go_library( go_library(
name = "go_default_library", name = "go_default_library",
srcs = [ srcs = [
"defaults.go",
"doc.go", "doc.go",
"generated.pb.go", "generated.pb.go",
"register.go", "register.go",
"types.go", "types.go",
"zz_generated.conversion.go", "zz_generated.conversion.go",
"zz_generated.deepcopy.go", "zz_generated.deepcopy.go",
"zz_generated.defaults.go",
], ],
importmap = "k8s.io/kubernetes/vendor/k8s.io/kube-aggregator/pkg/apis/apiregistration/v1beta1", importmap = "k8s.io/kubernetes/vendor/k8s.io/kube-aggregator/pkg/apis/apiregistration/v1beta1",
importpath = "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1beta1", importpath = "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1beta1",
...@@ -24,6 +26,7 @@ go_library( ...@@ -24,6 +26,7 @@ go_library(
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration:go_default_library", "//staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration:go_default_library",
"//vendor/github.com/gogo/protobuf/proto:go_default_library", "//vendor/github.com/gogo/protobuf/proto:go_default_library",
"//vendor/k8s.io/utils/pointer:go_default_library",
], ],
) )
......
/*
Copyright 2019 The Kubernetes Authors.
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 v1beta1
import (
"k8s.io/apimachinery/pkg/runtime"
utilpointer "k8s.io/utils/pointer"
)
func addDefaultingFuncs(scheme *runtime.Scheme) error {
return RegisterDefaults(scheme)
}
// SetDefaults_ServiceReference sets defaults for AuditSync Webhook's ServiceReference
func SetDefaults_ServiceReference(obj *ServiceReference) {
if obj.Port == nil {
obj.Port = utilpointer.Int32Ptr(443)
}
}
...@@ -19,6 +19,7 @@ limitations under the License. ...@@ -19,6 +19,7 @@ limitations under the License.
// +k8s:conversion-gen=k8s.io/kube-aggregator/pkg/apis/apiregistration // +k8s:conversion-gen=k8s.io/kube-aggregator/pkg/apis/apiregistration
// +k8s:openapi-gen=true // +k8s:openapi-gen=true
// +groupName=apiregistration.k8s.io // +groupName=apiregistration.k8s.io
// +k8s:defaulter-gen=TypeMeta
// Package v1beta1 contains the API Registration API, which is responsible for // Package v1beta1 contains the API Registration API, which is responsible for
// registering an API `Group`/`Version` with another kubernetes like API server. // registering an API `Group`/`Version` with another kubernetes like API server.
......
...@@ -130,5 +130,11 @@ message ServiceReference { ...@@ -130,5 +130,11 @@ message ServiceReference {
// Name is the name of the service // Name is the name of the service
optional string name = 2; optional string name = 2;
// If specified, the port on the service that hosting webhook.
// Default to 443 for backward compatibility.
// `port` should be a valid port number (1-65535, inclusive).
// +optional
optional int32 port = 3;
} }
...@@ -47,7 +47,7 @@ func init() { ...@@ -47,7 +47,7 @@ func init() {
// We only register manually written functions here. The registration of the // We only register manually written functions here. The registration of the
// generated functions takes place in the generated files. The separation // generated functions takes place in the generated files. The separation
// makes the code compile even when the generated files are missing. // makes the code compile even when the generated files are missing.
localSchemeBuilder.Register(addKnownTypes) localSchemeBuilder.Register(addKnownTypes, addDefaultingFuncs)
} }
// Adds the list of known types to the given scheme. // Adds the list of known types to the given scheme.
......
...@@ -34,6 +34,11 @@ type ServiceReference struct { ...@@ -34,6 +34,11 @@ type ServiceReference struct {
Namespace string `json:"namespace,omitempty" protobuf:"bytes,1,opt,name=namespace"` Namespace string `json:"namespace,omitempty" protobuf:"bytes,1,opt,name=namespace"`
// Name is the name of the service // Name is the name of the service
Name string `json:"name,omitempty" protobuf:"bytes,2,opt,name=name"` Name string `json:"name,omitempty" protobuf:"bytes,2,opt,name=name"`
// If specified, the port on the service that hosting webhook.
// Default to 443 for backward compatibility.
// `port` should be a valid port number (1-65535, inclusive).
// +optional
Port *int32 `json:"port,omitempty" protobuf:"varint,3,opt,name=port"`
} }
// APIServiceSpec contains information for locating and communicating with a server. // APIServiceSpec contains information for locating and communicating with a server.
......
...@@ -23,6 +23,7 @@ package v1beta1 ...@@ -23,6 +23,7 @@ package v1beta1
import ( import (
unsafe "unsafe" unsafe "unsafe"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
conversion "k8s.io/apimachinery/pkg/conversion" conversion "k8s.io/apimachinery/pkg/conversion"
runtime "k8s.io/apimachinery/pkg/runtime" runtime "k8s.io/apimachinery/pkg/runtime"
apiregistration "k8s.io/kube-aggregator/pkg/apis/apiregistration" apiregistration "k8s.io/kube-aggregator/pkg/apis/apiregistration"
...@@ -160,7 +161,17 @@ func Convert_apiregistration_APIServiceCondition_To_v1beta1_APIServiceCondition( ...@@ -160,7 +161,17 @@ func Convert_apiregistration_APIServiceCondition_To_v1beta1_APIServiceCondition(
func autoConvert_v1beta1_APIServiceList_To_apiregistration_APIServiceList(in *APIServiceList, out *apiregistration.APIServiceList, s conversion.Scope) error { func autoConvert_v1beta1_APIServiceList_To_apiregistration_APIServiceList(in *APIServiceList, out *apiregistration.APIServiceList, s conversion.Scope) error {
out.ListMeta = in.ListMeta out.ListMeta = in.ListMeta
out.Items = *(*[]apiregistration.APIService)(unsafe.Pointer(&in.Items)) if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]apiregistration.APIService, len(*in))
for i := range *in {
if err := Convert_v1beta1_APIService_To_apiregistration_APIService(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.Items = nil
}
return nil return nil
} }
...@@ -171,7 +182,17 @@ func Convert_v1beta1_APIServiceList_To_apiregistration_APIServiceList(in *APISer ...@@ -171,7 +182,17 @@ func Convert_v1beta1_APIServiceList_To_apiregistration_APIServiceList(in *APISer
func autoConvert_apiregistration_APIServiceList_To_v1beta1_APIServiceList(in *apiregistration.APIServiceList, out *APIServiceList, s conversion.Scope) error { func autoConvert_apiregistration_APIServiceList_To_v1beta1_APIServiceList(in *apiregistration.APIServiceList, out *APIServiceList, s conversion.Scope) error {
out.ListMeta = in.ListMeta out.ListMeta = in.ListMeta
out.Items = *(*[]APIService)(unsafe.Pointer(&in.Items)) if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]APIService, len(*in))
for i := range *in {
if err := Convert_apiregistration_APIService_To_v1beta1_APIService(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.Items = nil
}
return nil return nil
} }
...@@ -181,7 +202,15 @@ func Convert_apiregistration_APIServiceList_To_v1beta1_APIServiceList(in *apireg ...@@ -181,7 +202,15 @@ func Convert_apiregistration_APIServiceList_To_v1beta1_APIServiceList(in *apireg
} }
func autoConvert_v1beta1_APIServiceSpec_To_apiregistration_APIServiceSpec(in *APIServiceSpec, out *apiregistration.APIServiceSpec, s conversion.Scope) error { func autoConvert_v1beta1_APIServiceSpec_To_apiregistration_APIServiceSpec(in *APIServiceSpec, out *apiregistration.APIServiceSpec, s conversion.Scope) error {
out.Service = (*apiregistration.ServiceReference)(unsafe.Pointer(in.Service)) if in.Service != nil {
in, out := &in.Service, &out.Service
*out = new(apiregistration.ServiceReference)
if err := Convert_v1beta1_ServiceReference_To_apiregistration_ServiceReference(*in, *out, s); err != nil {
return err
}
} else {
out.Service = nil
}
out.Group = in.Group out.Group = in.Group
out.Version = in.Version out.Version = in.Version
out.InsecureSkipTLSVerify = in.InsecureSkipTLSVerify out.InsecureSkipTLSVerify = in.InsecureSkipTLSVerify
...@@ -197,7 +226,15 @@ func Convert_v1beta1_APIServiceSpec_To_apiregistration_APIServiceSpec(in *APISer ...@@ -197,7 +226,15 @@ func Convert_v1beta1_APIServiceSpec_To_apiregistration_APIServiceSpec(in *APISer
} }
func autoConvert_apiregistration_APIServiceSpec_To_v1beta1_APIServiceSpec(in *apiregistration.APIServiceSpec, out *APIServiceSpec, s conversion.Scope) error { func autoConvert_apiregistration_APIServiceSpec_To_v1beta1_APIServiceSpec(in *apiregistration.APIServiceSpec, out *APIServiceSpec, s conversion.Scope) error {
out.Service = (*ServiceReference)(unsafe.Pointer(in.Service)) if in.Service != nil {
in, out := &in.Service, &out.Service
*out = new(ServiceReference)
if err := Convert_apiregistration_ServiceReference_To_v1beta1_ServiceReference(*in, *out, s); err != nil {
return err
}
} else {
out.Service = nil
}
out.Group = in.Group out.Group = in.Group
out.Version = in.Version out.Version = in.Version
out.InsecureSkipTLSVerify = in.InsecureSkipTLSVerify out.InsecureSkipTLSVerify = in.InsecureSkipTLSVerify
...@@ -235,6 +272,9 @@ func Convert_apiregistration_APIServiceStatus_To_v1beta1_APIServiceStatus(in *ap ...@@ -235,6 +272,9 @@ func Convert_apiregistration_APIServiceStatus_To_v1beta1_APIServiceStatus(in *ap
func autoConvert_v1beta1_ServiceReference_To_apiregistration_ServiceReference(in *ServiceReference, out *apiregistration.ServiceReference, s conversion.Scope) error { func autoConvert_v1beta1_ServiceReference_To_apiregistration_ServiceReference(in *ServiceReference, out *apiregistration.ServiceReference, s conversion.Scope) error {
out.Namespace = in.Namespace out.Namespace = in.Namespace
out.Name = in.Name out.Name = in.Name
if err := v1.Convert_Pointer_int32_To_int32(&in.Port, &out.Port, s); err != nil {
return err
}
return nil return nil
} }
...@@ -246,6 +286,9 @@ func Convert_v1beta1_ServiceReference_To_apiregistration_ServiceReference(in *Se ...@@ -246,6 +286,9 @@ func Convert_v1beta1_ServiceReference_To_apiregistration_ServiceReference(in *Se
func autoConvert_apiregistration_ServiceReference_To_v1beta1_ServiceReference(in *apiregistration.ServiceReference, out *ServiceReference, s conversion.Scope) error { func autoConvert_apiregistration_ServiceReference_To_v1beta1_ServiceReference(in *apiregistration.ServiceReference, out *ServiceReference, s conversion.Scope) error {
out.Namespace = in.Namespace out.Namespace = in.Namespace
out.Name = in.Name out.Name = in.Name
if err := v1.Convert_int32_To_Pointer_int32(&in.Port, &out.Port, s); err != nil {
return err
}
return nil return nil
} }
......
...@@ -108,7 +108,7 @@ func (in *APIServiceSpec) DeepCopyInto(out *APIServiceSpec) { ...@@ -108,7 +108,7 @@ func (in *APIServiceSpec) DeepCopyInto(out *APIServiceSpec) {
if in.Service != nil { if in.Service != nil {
in, out := &in.Service, &out.Service in, out := &in.Service, &out.Service
*out = new(ServiceReference) *out = new(ServiceReference)
**out = **in (*in).DeepCopyInto(*out)
} }
if in.CABundle != nil { if in.CABundle != nil {
in, out := &in.CABundle, &out.CABundle in, out := &in.CABundle, &out.CABundle
...@@ -154,6 +154,11 @@ func (in *APIServiceStatus) DeepCopy() *APIServiceStatus { ...@@ -154,6 +154,11 @@ func (in *APIServiceStatus) DeepCopy() *APIServiceStatus {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ServiceReference) DeepCopyInto(out *ServiceReference) { func (in *ServiceReference) DeepCopyInto(out *ServiceReference) {
*out = *in *out = *in
if in.Port != nil {
in, out := &in.Port, &out.Port
*out = new(int32)
**out = **in
}
return return
} }
......
// +build !ignore_autogenerated
/*
Copyright The Kubernetes Authors.
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.
*/
// Code generated by defaulter-gen. DO NOT EDIT.
package v1beta1
import (
runtime "k8s.io/apimachinery/pkg/runtime"
)
// RegisterDefaults adds defaulters functions to the given scheme.
// Public to allow building arbitrary schemes.
// All generated defaulters are covering - they call all nested defaulters.
func RegisterDefaults(scheme *runtime.Scheme) error {
scheme.AddTypeDefaultingFunc(&APIService{}, func(obj interface{}) { SetObjectDefaults_APIService(obj.(*APIService)) })
scheme.AddTypeDefaultingFunc(&APIServiceList{}, func(obj interface{}) { SetObjectDefaults_APIServiceList(obj.(*APIServiceList)) })
return nil
}
func SetObjectDefaults_APIService(in *APIService) {
if in.Spec.Service != nil {
SetDefaults_ServiceReference(in.Spec.Service)
}
}
func SetObjectDefaults_APIServiceList(in *APIServiceList) {
for i := range in.Items {
a := &in.Items[i]
SetObjectDefaults_APIService(a)
}
}
...@@ -18,6 +18,7 @@ package validation ...@@ -18,6 +18,7 @@ package validation
import ( import (
"fmt" "fmt"
"strings"
"k8s.io/apimachinery/pkg/api/validation" "k8s.io/apimachinery/pkg/api/validation"
"k8s.io/apimachinery/pkg/api/validation/path" "k8s.io/apimachinery/pkg/api/validation/path"
...@@ -82,6 +83,9 @@ func ValidateAPIService(apiService *apiregistration.APIService) field.ErrorList ...@@ -82,6 +83,9 @@ func ValidateAPIService(apiService *apiregistration.APIService) field.ErrorList
if len(apiService.Spec.Service.Name) == 0 { if len(apiService.Spec.Service.Name) == 0 {
allErrs = append(allErrs, field.Required(field.NewPath("spec", "service", "name"), "")) allErrs = append(allErrs, field.Required(field.NewPath("spec", "service", "name"), ""))
} }
if errs := utilvalidation.IsValidPortNum(int(apiService.Spec.Service.Port)); errs != nil {
allErrs = append(allErrs, field.Invalid(field.NewPath("spec", "service", "port"), apiService.Spec.Service.Port, "port is not valid: "+strings.Join(errs, ", ")))
}
if apiService.Spec.InsecureSkipTLSVerify && len(apiService.Spec.CABundle) > 0 { if apiService.Spec.InsecureSkipTLSVerify && len(apiService.Spec.CABundle) > 0 {
allErrs = append(allErrs, field.Invalid(field.NewPath("spec", "insecureSkipTLSVerify"), apiService.Spec.InsecureSkipTLSVerify, "may not be true if caBundle is present")) allErrs = append(allErrs, field.Invalid(field.NewPath("spec", "insecureSkipTLSVerify"), apiService.Spec.InsecureSkipTLSVerify, "may not be true if caBundle is present"))
} }
......
...@@ -78,6 +78,8 @@ type proxyHandlingInfo struct { ...@@ -78,6 +78,8 @@ type proxyHandlingInfo struct {
serviceNamespace string serviceNamespace string
// serviceAvailable indicates this APIService is available or not // serviceAvailable indicates this APIService is available or not
serviceAvailable bool serviceAvailable bool
// servicePort is the port of the service this handler proxies to
servicePort int32
} }
func proxyError(w http.ResponseWriter, req *http.Request, error string, code int) { func proxyError(w http.ResponseWriter, req *http.Request, error string, code int) {
...@@ -128,7 +130,7 @@ func (r *proxyHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { ...@@ -128,7 +130,7 @@ func (r *proxyHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
// write a new location based on the existing request pointed at the target service // write a new location based on the existing request pointed at the target service
location := &url.URL{} location := &url.URL{}
location.Scheme = "https" location.Scheme = "https"
rloc, err := r.serviceResolver.ResolveEndpoint(handlingInfo.serviceNamespace, handlingInfo.serviceName) rloc, err := r.serviceResolver.ResolveEndpoint(handlingInfo.serviceNamespace, handlingInfo.serviceName, handlingInfo.servicePort)
if err != nil { if err != nil {
klog.Errorf("error resolving %s/%s: %v", handlingInfo.serviceNamespace, handlingInfo.serviceName, err) klog.Errorf("error resolving %s/%s: %v", handlingInfo.serviceNamespace, handlingInfo.serviceName, err)
proxyError(w, req, "service unavailable", http.StatusServiceUnavailable) proxyError(w, req, "service unavailable", http.StatusServiceUnavailable)
...@@ -226,6 +228,7 @@ func (r *proxyHandler) updateAPIService(apiService *apiregistrationapi.APIServic ...@@ -226,6 +228,7 @@ func (r *proxyHandler) updateAPIService(apiService *apiregistrationapi.APIServic
}, },
serviceName: apiService.Spec.Service.Name, serviceName: apiService.Spec.Service.Name,
serviceNamespace: apiService.Spec.Service.Namespace, serviceNamespace: apiService.Spec.Service.Namespace,
servicePort: apiService.Spec.Service.Port,
serviceAvailable: apiregistrationapi.IsAPIServiceConditionTrue(apiService, apiregistrationapi.Available), serviceAvailable: apiregistrationapi.IsAPIServiceConditionTrue(apiService, apiregistrationapi.Available),
} }
if r.proxyTransport != nil && r.proxyTransport.DialContext != nil { if r.proxyTransport != nil && r.proxyTransport.DialContext != nil {
......
...@@ -84,7 +84,7 @@ type mockedRouter struct { ...@@ -84,7 +84,7 @@ type mockedRouter struct {
err error err error
} }
func (r *mockedRouter) ResolveEndpoint(namespace, name string) (*url.URL, error) { func (r *mockedRouter) ResolveEndpoint(namespace, name string, port int32) (*url.URL, error) {
return &url.URL{Scheme: "https", Host: r.destinationHost}, r.err return &url.URL{Scheme: "https", Host: r.destinationHost}, r.err
} }
...@@ -172,7 +172,7 @@ func TestProxyHandler(t *testing.T) { ...@@ -172,7 +172,7 @@ func TestProxyHandler(t *testing.T) {
apiService: &apiregistration.APIService{ apiService: &apiregistration.APIService{
ObjectMeta: metav1.ObjectMeta{Name: "v1.foo"}, ObjectMeta: metav1.ObjectMeta{Name: "v1.foo"},
Spec: apiregistration.APIServiceSpec{ Spec: apiregistration.APIServiceSpec{
Service: &apiregistration.ServiceReference{Name: "test-service", Namespace: "test-ns"}, Service: &apiregistration.ServiceReference{Name: "test-service", Namespace: "test-ns", Port: 443},
Group: "foo", Group: "foo",
Version: "v1", Version: "v1",
CABundle: testCACrt, CABundle: testCACrt,
...@@ -204,7 +204,7 @@ func TestProxyHandler(t *testing.T) { ...@@ -204,7 +204,7 @@ func TestProxyHandler(t *testing.T) {
apiService: &apiregistration.APIService{ apiService: &apiregistration.APIService{
ObjectMeta: metav1.ObjectMeta{Name: "v1.foo"}, ObjectMeta: metav1.ObjectMeta{Name: "v1.foo"},
Spec: apiregistration.APIServiceSpec{ Spec: apiregistration.APIServiceSpec{
Service: &apiregistration.ServiceReference{Name: "test-service", Namespace: "test-ns"}, Service: &apiregistration.ServiceReference{Name: "test-service", Namespace: "test-ns", Port: 443},
Group: "foo", Group: "foo",
Version: "v1", Version: "v1",
CABundle: testCACrt, CABundle: testCACrt,
...@@ -227,7 +227,7 @@ func TestProxyHandler(t *testing.T) { ...@@ -227,7 +227,7 @@ func TestProxyHandler(t *testing.T) {
apiService: &apiregistration.APIService{ apiService: &apiregistration.APIService{
ObjectMeta: metav1.ObjectMeta{Name: "v1.foo"}, ObjectMeta: metav1.ObjectMeta{Name: "v1.foo"},
Spec: apiregistration.APIServiceSpec{ Spec: apiregistration.APIServiceSpec{
Service: &apiregistration.ServiceReference{Name: "bad-service", Namespace: "test-ns"}, Service: &apiregistration.ServiceReference{Name: "bad-service", Namespace: "test-ns", Port: 443},
Group: "foo", Group: "foo",
Version: "v1", Version: "v1",
CABundle: testCACrt, CABundle: testCACrt,
...@@ -336,7 +336,7 @@ func TestProxyUpgrade(t *testing.T) { ...@@ -336,7 +336,7 @@ func TestProxyUpgrade(t *testing.T) {
CABundle: testCACrt, CABundle: testCACrt,
Group: "mygroup", Group: "mygroup",
Version: "v1", Version: "v1",
Service: &apiregistration.ServiceReference{Name: "test-service", Namespace: "test-ns"}, Service: &apiregistration.ServiceReference{Name: "test-service", Namespace: "test-ns", Port: 443},
}, },
Status: apiregistration.APIServiceStatus{ Status: apiregistration.APIServiceStatus{
Conditions: []apiregistration.APIServiceCondition{ Conditions: []apiregistration.APIServiceCondition{
...@@ -353,7 +353,7 @@ func TestProxyUpgrade(t *testing.T) { ...@@ -353,7 +353,7 @@ func TestProxyUpgrade(t *testing.T) {
InsecureSkipTLSVerify: true, InsecureSkipTLSVerify: true,
Group: "mygroup", Group: "mygroup",
Version: "v1", Version: "v1",
Service: &apiregistration.ServiceReference{Name: "invalid-service", Namespace: "invalid-ns"}, Service: &apiregistration.ServiceReference{Name: "invalid-service", Namespace: "invalid-ns", Port: 443},
}, },
Status: apiregistration.APIServiceStatus{ Status: apiregistration.APIServiceStatus{
Conditions: []apiregistration.APIServiceCondition{ Conditions: []apiregistration.APIServiceCondition{
...@@ -370,7 +370,7 @@ func TestProxyUpgrade(t *testing.T) { ...@@ -370,7 +370,7 @@ func TestProxyUpgrade(t *testing.T) {
CABundle: testCACrt, CABundle: testCACrt,
Group: "mygroup", Group: "mygroup",
Version: "v1", Version: "v1",
Service: &apiregistration.ServiceReference{Name: "invalid-service", Namespace: "invalid-ns"}, Service: &apiregistration.ServiceReference{Name: "invalid-service", Namespace: "invalid-ns", Port: 443},
}, },
Status: apiregistration.APIServiceStatus{ Status: apiregistration.APIServiceStatus{
Conditions: []apiregistration.APIServiceCondition{ Conditions: []apiregistration.APIServiceCondition{
......
...@@ -25,7 +25,7 @@ import ( ...@@ -25,7 +25,7 @@ import (
// A ServiceResolver knows how to get a URL given a service. // A ServiceResolver knows how to get a URL given a service.
type ServiceResolver interface { type ServiceResolver interface {
ResolveEndpoint(namespace, name string) (*url.URL, error) ResolveEndpoint(namespace, name string, port int32) (*url.URL, error)
} }
// NewEndpointServiceResolver returns a ServiceResolver that chooses one of the // NewEndpointServiceResolver returns a ServiceResolver that chooses one of the
...@@ -42,8 +42,8 @@ type aggregatorEndpointRouting struct { ...@@ -42,8 +42,8 @@ type aggregatorEndpointRouting struct {
endpoints listersv1.EndpointsLister endpoints listersv1.EndpointsLister
} }
func (r *aggregatorEndpointRouting) ResolveEndpoint(namespace, name string) (*url.URL, error) { func (r *aggregatorEndpointRouting) ResolveEndpoint(namespace, name string, port int32) (*url.URL, error) {
return proxy.ResolveEndpoint(r.services, r.endpoints, namespace, name) return proxy.ResolveEndpoint(r.services, r.endpoints, namespace, name, port)
} }
// NewClusterIPServiceResolver returns a ServiceResolver that directly calls the // NewClusterIPServiceResolver returns a ServiceResolver that directly calls the
...@@ -58,11 +58,12 @@ type aggregatorClusterRouting struct { ...@@ -58,11 +58,12 @@ type aggregatorClusterRouting struct {
services listersv1.ServiceLister services listersv1.ServiceLister
} }
func (r *aggregatorClusterRouting) ResolveEndpoint(namespace, name string) (*url.URL, error) { func (r *aggregatorClusterRouting) ResolveEndpoint(namespace, name string, port int32) (*url.URL, error) {
return proxy.ResolveCluster(r.services, namespace, name) return proxy.ResolveCluster(r.services, namespace, name, port)
} }
// NewLoopbackServiceResolver returns a ServiceResolver that routes the kubernetes/default service to loopback. // NewLoopbackServiceResolver returns a ServiceResolver that routes
// the kubernetes/default service with port 443 to loopback.
func NewLoopbackServiceResolver(delegate ServiceResolver, host *url.URL) ServiceResolver { func NewLoopbackServiceResolver(delegate ServiceResolver, host *url.URL) ServiceResolver {
return &loopbackResolver{ return &loopbackResolver{
delegate: delegate, delegate: delegate,
...@@ -75,9 +76,9 @@ type loopbackResolver struct { ...@@ -75,9 +76,9 @@ type loopbackResolver struct {
host *url.URL host *url.URL
} }
func (r *loopbackResolver) ResolveEndpoint(namespace, name string) (*url.URL, error) { func (r *loopbackResolver) ResolveEndpoint(namespace, name string, port int32) (*url.URL, error) {
if namespace == "default" && name == "kubernetes" { if namespace == "default" && name == "kubernetes" && port == 443 {
return r.host, nil return r.host, nil
} }
return r.delegate.ResolveEndpoint(namespace, name) return r.delegate.ResolveEndpoint(namespace, name, port)
} }
...@@ -48,7 +48,7 @@ import ( ...@@ -48,7 +48,7 @@ import (
// ServiceResolver knows how to convert a service reference into an actual location. // ServiceResolver knows how to convert a service reference into an actual location.
type ServiceResolver interface { type ServiceResolver interface {
ResolveEndpoint(namespace, name string) (*url.URL, error) ResolveEndpoint(namespace, name string, port int32) (*url.URL, error)
} }
// AvailableConditionController handles checking the availability of registered API services. // AvailableConditionController handles checking the availability of registered API services.
...@@ -185,17 +185,20 @@ func (c *AvailableConditionController) sync(key string) error { ...@@ -185,17 +185,20 @@ func (c *AvailableConditionController) sync(key string) error {
} }
if service.Spec.Type == v1.ServiceTypeClusterIP { if service.Spec.Type == v1.ServiceTypeClusterIP {
// if we have a cluster IP service, it must be listening on 443 and we can check that // if we have a cluster IP service, it must be listening on configured port and we can check that
servicePort := apiService.Spec.Service.Port
portName := ""
foundPort := false foundPort := false
for _, port := range service.Spec.Ports { for _, port := range service.Spec.Ports {
if port.Port == 443 { if port.Port == servicePort {
foundPort = true foundPort = true
portName = port.Name
} }
} }
if !foundPort { if !foundPort {
availableCondition.Status = apiregistration.ConditionFalse availableCondition.Status = apiregistration.ConditionFalse
availableCondition.Reason = "ServicePortError" availableCondition.Reason = "ServicePortError"
availableCondition.Message = fmt.Sprintf("service/%s in %q is not listening on port 443", apiService.Spec.Service.Name, apiService.Spec.Service.Namespace) availableCondition.Message = fmt.Sprintf("service/%s in %q is not listening on port %d", apiService.Spec.Service.Name, apiService.Spec.Service.Namespace, apiService.Spec.Service.Port)
apiregistration.SetAPIServiceCondition(apiService, availableCondition) apiregistration.SetAPIServiceCondition(apiService, availableCondition)
_, err := updateAPIServiceStatus(c.apiServiceClient, originalAPIService, apiService) _, err := updateAPIServiceStatus(c.apiServiceClient, originalAPIService, apiService)
return err return err
...@@ -219,15 +222,19 @@ func (c *AvailableConditionController) sync(key string) error { ...@@ -219,15 +222,19 @@ func (c *AvailableConditionController) sync(key string) error {
} }
hasActiveEndpoints := false hasActiveEndpoints := false
for _, subset := range endpoints.Subsets { for _, subset := range endpoints.Subsets {
if len(subset.Addresses) > 0 { if len(subset.Addresses) == 0 {
hasActiveEndpoints = true continue
break }
for _, endpointPort := range subset.Ports {
if endpointPort.Name == portName {
hasActiveEndpoints = true
}
} }
} }
if !hasActiveEndpoints { if !hasActiveEndpoints {
availableCondition.Status = apiregistration.ConditionFalse availableCondition.Status = apiregistration.ConditionFalse
availableCondition.Reason = "MissingEndpoints" availableCondition.Reason = "MissingEndpoints"
availableCondition.Message = fmt.Sprintf("endpoints for service/%s in %q have no addresses", apiService.Spec.Service.Name, apiService.Spec.Service.Namespace) availableCondition.Message = fmt.Sprintf("endpoints for service/%s in %q have no addresses with port name %q", apiService.Spec.Service.Name, apiService.Spec.Service.Namespace, portName)
apiregistration.SetAPIServiceCondition(apiService, availableCondition) apiregistration.SetAPIServiceCondition(apiService, availableCondition)
_, err := updateAPIServiceStatus(c.apiServiceClient, originalAPIService, apiService) _, err := updateAPIServiceStatus(c.apiServiceClient, originalAPIService, apiService)
return err return err
...@@ -235,7 +242,7 @@ func (c *AvailableConditionController) sync(key string) error { ...@@ -235,7 +242,7 @@ func (c *AvailableConditionController) sync(key string) error {
} }
// actually try to hit the discovery endpoint when it isn't local and when we're routing as a service. // actually try to hit the discovery endpoint when it isn't local and when we're routing as a service.
if apiService.Spec.Service != nil && c.serviceResolver != nil { if apiService.Spec.Service != nil && c.serviceResolver != nil {
discoveryURL, err := c.serviceResolver.ResolveEndpoint(apiService.Spec.Service.Namespace, apiService.Spec.Service.Name) discoveryURL, err := c.serviceResolver.ResolveEndpoint(apiService.Spec.Service.Namespace, apiService.Spec.Service.Name, apiService.Spec.Service.Port)
if err != nil { if err != nil {
return err return err
} }
......
...@@ -17,6 +17,7 @@ limitations under the License. ...@@ -17,6 +17,7 @@ limitations under the License.
package apiserver package apiserver
import ( import (
"fmt"
"testing" "testing"
"github.com/davecgh/go-spew/spew" "github.com/davecgh/go-spew/spew"
...@@ -31,13 +32,18 @@ import ( ...@@ -31,13 +32,18 @@ import (
listers "k8s.io/kube-aggregator/pkg/client/listers/apiregistration/internalversion" listers "k8s.io/kube-aggregator/pkg/client/listers/apiregistration/internalversion"
) )
const (
testServicePort = 1234
testServicePortName = "testPort"
)
func newEndpoints(namespace, name string) *v1.Endpoints { func newEndpoints(namespace, name string) *v1.Endpoints {
return &v1.Endpoints{ return &v1.Endpoints{
ObjectMeta: metav1.ObjectMeta{Namespace: namespace, Name: name}, ObjectMeta: metav1.ObjectMeta{Namespace: namespace, Name: name},
} }
} }
func newEndpointsWithAddress(namespace, name string) *v1.Endpoints { func newEndpointsWithAddress(namespace, name string, port int32, portName string) *v1.Endpoints {
return &v1.Endpoints{ return &v1.Endpoints{
ObjectMeta: metav1.ObjectMeta{Namespace: namespace, Name: name}, ObjectMeta: metav1.ObjectMeta{Namespace: namespace, Name: name},
Subsets: []v1.EndpointSubset{ Subsets: []v1.EndpointSubset{
...@@ -47,18 +53,24 @@ func newEndpointsWithAddress(namespace, name string) *v1.Endpoints { ...@@ -47,18 +53,24 @@ func newEndpointsWithAddress(namespace, name string) *v1.Endpoints {
IP: "val", IP: "val",
}, },
}, },
Ports: []v1.EndpointPort{
{
Name: portName,
Port: port,
},
},
}, },
}, },
} }
} }
func newService(namespace, name string) *v1.Service { func newService(namespace, name string, port int32, portName string) *v1.Service {
return &v1.Service{ return &v1.Service{
ObjectMeta: metav1.ObjectMeta{Namespace: namespace, Name: name}, ObjectMeta: metav1.ObjectMeta{Namespace: namespace, Name: name},
Spec: v1.ServiceSpec{ Spec: v1.ServiceSpec{
Type: v1.ServiceTypeClusterIP, Type: v1.ServiceTypeClusterIP,
Ports: []v1.ServicePort{ Ports: []v1.ServicePort{
{Port: 443}, {Port: port, Name: portName},
}, },
}, },
} }
...@@ -77,6 +89,7 @@ func newRemoteAPIService(name string) *apiregistration.APIService { ...@@ -77,6 +89,7 @@ func newRemoteAPIService(name string) *apiregistration.APIService {
Service: &apiregistration.ServiceReference{ Service: &apiregistration.ServiceReference{
Namespace: "foo", Namespace: "foo",
Name: "bar", Name: "bar",
Port: testServicePort,
}, },
}, },
} }
...@@ -107,7 +120,7 @@ func TestSync(t *testing.T) { ...@@ -107,7 +120,7 @@ func TestSync(t *testing.T) {
name: "no service", name: "no service",
apiServiceName: "remote.group", apiServiceName: "remote.group",
apiServices: []*apiregistration.APIService{newRemoteAPIService("remote.group")}, apiServices: []*apiregistration.APIService{newRemoteAPIService("remote.group")},
services: []*v1.Service{newService("foo", "not-bar")}, services: []*v1.Service{newService("foo", "not-bar", testServicePort, testServicePortName)},
expectedAvailability: apiregistration.APIServiceCondition{ expectedAvailability: apiregistration.APIServiceCondition{
Type: apiregistration.Available, Type: apiregistration.Available,
Status: apiregistration.ConditionFalse, Status: apiregistration.ConditionFalse,
...@@ -128,19 +141,19 @@ func TestSync(t *testing.T) { ...@@ -128,19 +141,19 @@ func TestSync(t *testing.T) {
}, },
}, },
}}, }},
endpoints: []*v1.Endpoints{newEndpointsWithAddress("foo", "bar")}, endpoints: []*v1.Endpoints{newEndpointsWithAddress("foo", "bar", testServicePort, testServicePortName)},
expectedAvailability: apiregistration.APIServiceCondition{ expectedAvailability: apiregistration.APIServiceCondition{
Type: apiregistration.Available, Type: apiregistration.Available,
Status: apiregistration.ConditionFalse, Status: apiregistration.ConditionFalse,
Reason: "ServicePortError", Reason: "ServicePortError",
Message: `service/bar in "foo" is not listening on port 443`, Message: fmt.Sprintf(`service/bar in "foo" is not listening on port %d`, testServicePort),
}, },
}, },
{ {
name: "no endpoints", name: "no endpoints",
apiServiceName: "remote.group", apiServiceName: "remote.group",
apiServices: []*apiregistration.APIService{newRemoteAPIService("remote.group")}, apiServices: []*apiregistration.APIService{newRemoteAPIService("remote.group")},
services: []*v1.Service{newService("foo", "bar")}, services: []*v1.Service{newService("foo", "bar", testServicePort, testServicePortName)},
expectedAvailability: apiregistration.APIServiceCondition{ expectedAvailability: apiregistration.APIServiceCondition{
Type: apiregistration.Available, Type: apiregistration.Available,
Status: apiregistration.ConditionFalse, Status: apiregistration.ConditionFalse,
...@@ -152,21 +165,34 @@ func TestSync(t *testing.T) { ...@@ -152,21 +165,34 @@ func TestSync(t *testing.T) {
name: "missing endpoints", name: "missing endpoints",
apiServiceName: "remote.group", apiServiceName: "remote.group",
apiServices: []*apiregistration.APIService{newRemoteAPIService("remote.group")}, apiServices: []*apiregistration.APIService{newRemoteAPIService("remote.group")},
services: []*v1.Service{newService("foo", "bar")}, services: []*v1.Service{newService("foo", "bar", testServicePort, testServicePortName)},
endpoints: []*v1.Endpoints{newEndpoints("foo", "bar")}, endpoints: []*v1.Endpoints{newEndpoints("foo", "bar")},
expectedAvailability: apiregistration.APIServiceCondition{ expectedAvailability: apiregistration.APIServiceCondition{
Type: apiregistration.Available, Type: apiregistration.Available,
Status: apiregistration.ConditionFalse, Status: apiregistration.ConditionFalse,
Reason: "MissingEndpoints", Reason: "MissingEndpoints",
Message: `endpoints for service/bar in "foo" have no addresses`, Message: `endpoints for service/bar in "foo" have no addresses with port name "testPort"`,
},
},
{
name: "wrong endpoint port name",
apiServiceName: "remote.group",
apiServices: []*apiregistration.APIService{newRemoteAPIService("remote.group")},
services: []*v1.Service{newService("foo", "bar", testServicePort, testServicePortName)},
endpoints: []*v1.Endpoints{newEndpointsWithAddress("foo", "bar", testServicePort, "wrongName")},
expectedAvailability: apiregistration.APIServiceCondition{
Type: apiregistration.Available,
Status: apiregistration.ConditionFalse,
Reason: "MissingEndpoints",
Message: fmt.Sprintf(`endpoints for service/bar in "foo" have no addresses with port name "%s"`, testServicePortName),
}, },
}, },
{ {
name: "remote", name: "remote",
apiServiceName: "remote.group", apiServiceName: "remote.group",
apiServices: []*apiregistration.APIService{newRemoteAPIService("remote.group")}, apiServices: []*apiregistration.APIService{newRemoteAPIService("remote.group")},
services: []*v1.Service{newService("foo", "bar")}, services: []*v1.Service{newService("foo", "bar", testServicePort, testServicePortName)},
endpoints: []*v1.Endpoints{newEndpointsWithAddress("foo", "bar")}, endpoints: []*v1.Endpoints{newEndpointsWithAddress("foo", "bar", testServicePort, testServicePortName)},
expectedAvailability: apiregistration.APIServiceCondition{ expectedAvailability: apiregistration.APIServiceCondition{
Type: apiregistration.Available, Type: apiregistration.Available,
Status: apiregistration.ConditionTrue, Status: apiregistration.ConditionTrue,
......
...@@ -88,6 +88,7 @@ go_library( ...@@ -88,6 +88,7 @@ go_library(
"//vendor/github.com/onsi/gomega:go_default_library", "//vendor/github.com/onsi/gomega:go_default_library",
"//vendor/github.com/stretchr/testify/assert:go_default_library", "//vendor/github.com/stretchr/testify/assert:go_default_library",
"//vendor/k8s.io/kube-openapi/pkg/util:go_default_library", "//vendor/k8s.io/kube-openapi/pkg/util:go_default_library",
"//vendor/k8s.io/utils/pointer:go_default_library",
"//vendor/sigs.k8s.io/yaml:go_default_library", "//vendor/sigs.k8s.io/yaml:go_default_library",
], ],
) )
......
...@@ -42,12 +42,17 @@ import ( ...@@ -42,12 +42,17 @@ import (
"k8s.io/kubernetes/test/e2e/framework" "k8s.io/kubernetes/test/e2e/framework"
imageutils "k8s.io/kubernetes/test/utils/image" imageutils "k8s.io/kubernetes/test/utils/image"
samplev1alpha1 "k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1" samplev1alpha1 "k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1"
"k8s.io/utils/pointer"
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
) )
var serverAggregatorVersion = utilversion.MustParseSemantic("v1.10.0") var serverAggregatorVersion = utilversion.MustParseSemantic("v1.10.0")
const (
aggregatorServicePort = 7443
)
var _ = SIGDescribe("Aggregator", func() { var _ = SIGDescribe("Aggregator", func() {
var ns string var ns string
var c clientset.Interface var c clientset.Interface
...@@ -266,7 +271,7 @@ func TestSampleAPIServer(f *framework.Framework, image string) { ...@@ -266,7 +271,7 @@ func TestSampleAPIServer(f *framework.Framework, image string) {
Ports: []v1.ServicePort{ Ports: []v1.ServicePort{
{ {
Protocol: "TCP", Protocol: "TCP",
Port: 443, Port: aggregatorServicePort,
TargetPort: intstr.FromInt(443), TargetPort: intstr.FromInt(443),
}, },
}, },
...@@ -317,6 +322,7 @@ func TestSampleAPIServer(f *framework.Framework, image string) { ...@@ -317,6 +322,7 @@ func TestSampleAPIServer(f *framework.Framework, image string) {
Service: &apiregistrationv1beta1.ServiceReference{ Service: &apiregistrationv1beta1.ServiceReference{
Namespace: namespace, Namespace: namespace,
Name: "sample-api", Name: "sample-api",
Port: pointer.Int32Ptr(aggregatorServicePort),
}, },
Group: "wardle.k8s.io", Group: "wardle.k8s.io",
Version: "v1alpha1", Version: "v1alpha1",
......
...@@ -34,6 +34,7 @@ import ( ...@@ -34,6 +34,7 @@ import (
"k8s.io/kubernetes/test/e2e/framework" "k8s.io/kubernetes/test/e2e/framework"
"k8s.io/kubernetes/test/utils/crd" "k8s.io/kubernetes/test/utils/crd"
imageutils "k8s.io/kubernetes/test/utils/image" imageutils "k8s.io/kubernetes/test/utils/image"
"k8s.io/utils/pointer"
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
...@@ -44,6 +45,7 @@ const ( ...@@ -44,6 +45,7 @@ const (
secretCRDName = "sample-custom-resource-conversion-webhook-secret" secretCRDName = "sample-custom-resource-conversion-webhook-secret"
deploymentCRDName = "sample-crd-conversion-webhook-deployment" deploymentCRDName = "sample-crd-conversion-webhook-deployment"
serviceCRDName = "e2e-test-crd-conversion-webhook" serviceCRDName = "e2e-test-crd-conversion-webhook"
serviceCRDPort = 9443
roleBindingCRDName = "crd-conversion-webhook-auth-reader" roleBindingCRDName = "crd-conversion-webhook-auth-reader"
) )
...@@ -107,7 +109,8 @@ var _ = SIGDescribe("CustomResourceConversionWebhook [Feature:CustomResourceWebh ...@@ -107,7 +109,8 @@ var _ = SIGDescribe("CustomResourceConversionWebhook [Feature:CustomResourceWebh
Service: &v1beta1.ServiceReference{ Service: &v1beta1.ServiceReference{
Namespace: f.Namespace.Name, Namespace: f.Namespace.Name,
Name: serviceCRDName, Name: serviceCRDName,
Path: strPtr("/crdconvert"), Path: pointer.StringPtr("/crdconvert"),
Port: pointer.Int32Ptr(serviceCRDPort),
}}) }})
if err != nil { if err != nil {
return return
...@@ -123,7 +126,8 @@ var _ = SIGDescribe("CustomResourceConversionWebhook [Feature:CustomResourceWebh ...@@ -123,7 +126,8 @@ var _ = SIGDescribe("CustomResourceConversionWebhook [Feature:CustomResourceWebh
Service: &v1beta1.ServiceReference{ Service: &v1beta1.ServiceReference{
Namespace: f.Namespace.Name, Namespace: f.Namespace.Name,
Name: serviceCRDName, Name: serviceCRDName,
Path: strPtr("/crdconvert"), Path: pointer.StringPtr("/crdconvert"),
Port: pointer.Int32Ptr(serviceCRDPort),
}}) }})
if err != nil { if err != nil {
return return
...@@ -268,7 +272,7 @@ func deployCustomResourceWebhookAndService(f *framework.Framework, image string, ...@@ -268,7 +272,7 @@ func deployCustomResourceWebhookAndService(f *framework.Framework, image string,
Ports: []v1.ServicePort{ Ports: []v1.ServicePort{
{ {
Protocol: "TCP", Protocol: "TCP",
Port: 443, Port: serviceCRDPort,
TargetPort: intstr.FromInt(443), TargetPort: intstr.FromInt(443),
}, },
}, },
......
...@@ -40,6 +40,7 @@ import ( ...@@ -40,6 +40,7 @@ import (
"k8s.io/kubernetes/test/e2e/framework" "k8s.io/kubernetes/test/e2e/framework"
"k8s.io/kubernetes/test/utils/crd" "k8s.io/kubernetes/test/utils/crd"
imageutils "k8s.io/kubernetes/test/utils/image" imageutils "k8s.io/kubernetes/test/utils/image"
"k8s.io/utils/pointer"
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
...@@ -50,6 +51,7 @@ const ( ...@@ -50,6 +51,7 @@ const (
secretName = "sample-webhook-secret" secretName = "sample-webhook-secret"
deploymentName = "sample-webhook-deployment" deploymentName = "sample-webhook-deployment"
serviceName = "e2e-test-webhook" serviceName = "e2e-test-webhook"
servicePort = 8443
roleBindingName = "webhook-auth-reader" roleBindingName = "webhook-auth-reader"
// The webhook configuration names should not be reused between test instances. // The webhook configuration names should not be reused between test instances.
...@@ -208,17 +210,17 @@ var _ = SIGDescribe("AdmissionWebhook", func() { ...@@ -208,17 +210,17 @@ var _ = SIGDescribe("AdmissionWebhook", func() {
policyIgnore := v1beta1.Ignore policyIgnore := v1beta1.Ignore
By("Setting timeout (1s) shorter than webhook latency (5s)") By("Setting timeout (1s) shorter than webhook latency (5s)")
slowWebhookCleanup := registerSlowWebhook(f, context, &policyFail, int32Ptr(1)) slowWebhookCleanup := registerSlowWebhook(f, context, &policyFail, pointer.Int32Ptr(1))
testSlowWebhookTimeoutFailEarly(f) testSlowWebhookTimeoutFailEarly(f)
slowWebhookCleanup() slowWebhookCleanup()
By("Having no error when timeout is shorter than webhook latency and failure policy is ignore") By("Having no error when timeout is shorter than webhook latency and failure policy is ignore")
slowWebhookCleanup = registerSlowWebhook(f, context, &policyIgnore, int32Ptr(1)) slowWebhookCleanup = registerSlowWebhook(f, context, &policyIgnore, pointer.Int32Ptr(1))
testSlowWebhookTimeoutNoError(f) testSlowWebhookTimeoutNoError(f)
slowWebhookCleanup() slowWebhookCleanup()
By("Having no error when timeout is longer than webhook latency") By("Having no error when timeout is longer than webhook latency")
slowWebhookCleanup = registerSlowWebhook(f, context, &policyFail, int32Ptr(10)) slowWebhookCleanup = registerSlowWebhook(f, context, &policyFail, pointer.Int32Ptr(10))
testSlowWebhookTimeoutNoError(f) testSlowWebhookTimeoutNoError(f)
slowWebhookCleanup() slowWebhookCleanup()
...@@ -368,7 +370,7 @@ func deployWebhookAndService(f *framework.Framework, image string, context *cert ...@@ -368,7 +370,7 @@ func deployWebhookAndService(f *framework.Framework, image string, context *cert
Ports: []v1.ServicePort{ Ports: []v1.ServicePort{
{ {
Protocol: "TCP", Protocol: "TCP",
Port: 443, Port: servicePort,
TargetPort: intstr.FromInt(443), TargetPort: intstr.FromInt(443),
}, },
}, },
...@@ -384,8 +386,6 @@ func deployWebhookAndService(f *framework.Framework, image string, context *cert ...@@ -384,8 +386,6 @@ func deployWebhookAndService(f *framework.Framework, image string, context *cert
func strPtr(s string) *string { return &s } func strPtr(s string) *string { return &s }
func int32Ptr(i int32) *int32 { return &i }
func registerWebhook(f *framework.Framework, context *certContext) func() { func registerWebhook(f *framework.Framework, context *certContext) func() {
client := f.ClientSet client := f.ClientSet
By("Registering the webhook via the AdmissionRegistration API") By("Registering the webhook via the AdmissionRegistration API")
...@@ -417,6 +417,7 @@ func registerWebhook(f *framework.Framework, context *certContext) func() { ...@@ -417,6 +417,7 @@ func registerWebhook(f *framework.Framework, context *certContext) func() {
Namespace: namespace, Namespace: namespace,
Name: serviceName, Name: serviceName,
Path: strPtr("/pods"), Path: strPtr("/pods"),
Port: pointer.Int32Ptr(servicePort),
}, },
CABundle: context.signingCert, CABundle: context.signingCert,
}, },
...@@ -446,6 +447,7 @@ func registerWebhook(f *framework.Framework, context *certContext) func() { ...@@ -446,6 +447,7 @@ func registerWebhook(f *framework.Framework, context *certContext) func() {
Namespace: namespace, Namespace: namespace,
Name: serviceName, Name: serviceName,
Path: strPtr("/configmaps"), Path: strPtr("/configmaps"),
Port: pointer.Int32Ptr(servicePort),
}, },
CABundle: context.signingCert, CABundle: context.signingCert,
}, },
...@@ -496,6 +498,7 @@ func registerWebhookForAttachingPod(f *framework.Framework, context *certContext ...@@ -496,6 +498,7 @@ func registerWebhookForAttachingPod(f *framework.Framework, context *certContext
Namespace: namespace, Namespace: namespace,
Name: serviceName, Name: serviceName,
Path: strPtr("/pods/attach"), Path: strPtr("/pods/attach"),
Port: pointer.Int32Ptr(servicePort),
}, },
CABundle: context.signingCert, CABundle: context.signingCert,
}, },
...@@ -539,6 +542,7 @@ func registerMutatingWebhookForConfigMap(f *framework.Framework, context *certCo ...@@ -539,6 +542,7 @@ func registerMutatingWebhookForConfigMap(f *framework.Framework, context *certCo
Namespace: namespace, Namespace: namespace,
Name: serviceName, Name: serviceName,
Path: strPtr("/mutating-configmaps"), Path: strPtr("/mutating-configmaps"),
Port: pointer.Int32Ptr(servicePort),
}, },
CABundle: context.signingCert, CABundle: context.signingCert,
}, },
...@@ -558,6 +562,7 @@ func registerMutatingWebhookForConfigMap(f *framework.Framework, context *certCo ...@@ -558,6 +562,7 @@ func registerMutatingWebhookForConfigMap(f *framework.Framework, context *certCo
Namespace: namespace, Namespace: namespace,
Name: serviceName, Name: serviceName,
Path: strPtr("/mutating-configmaps"), Path: strPtr("/mutating-configmaps"),
Port: pointer.Int32Ptr(servicePort),
}, },
CABundle: context.signingCert, CABundle: context.signingCert,
}, },
...@@ -614,6 +619,7 @@ func registerMutatingWebhookForPod(f *framework.Framework, context *certContext) ...@@ -614,6 +619,7 @@ func registerMutatingWebhookForPod(f *framework.Framework, context *certContext)
Namespace: namespace, Namespace: namespace,
Name: serviceName, Name: serviceName,
Path: strPtr("/mutating-pods"), Path: strPtr("/mutating-pods"),
Port: pointer.Int32Ptr(servicePort),
}, },
CABundle: context.signingCert, CABundle: context.signingCert,
}, },
...@@ -786,6 +792,7 @@ func failingWebhook(namespace, name string) v1beta1.Webhook { ...@@ -786,6 +792,7 @@ func failingWebhook(namespace, name string) v1beta1.Webhook {
Namespace: namespace, Namespace: namespace,
Name: serviceName, Name: serviceName,
Path: strPtr("/configmaps"), Path: strPtr("/configmaps"),
Port: pointer.Int32Ptr(servicePort),
}, },
// Without CA bundle, the call to webhook always fails // Without CA bundle, the call to webhook always fails
CABundle: nil, CABundle: nil,
...@@ -892,6 +899,7 @@ func registerValidatingWebhookForWebhookConfigurations(f *framework.Framework, c ...@@ -892,6 +899,7 @@ func registerValidatingWebhookForWebhookConfigurations(f *framework.Framework, c
Namespace: namespace, Namespace: namespace,
Name: serviceName, Name: serviceName,
Path: strPtr("/always-deny"), Path: strPtr("/always-deny"),
Port: pointer.Int32Ptr(servicePort),
}, },
CABundle: context.signingCert, CABundle: context.signingCert,
}, },
...@@ -944,6 +952,7 @@ func registerMutatingWebhookForWebhookConfigurations(f *framework.Framework, con ...@@ -944,6 +952,7 @@ func registerMutatingWebhookForWebhookConfigurations(f *framework.Framework, con
Namespace: namespace, Namespace: namespace,
Name: serviceName, Name: serviceName,
Path: strPtr("/add-label"), Path: strPtr("/add-label"),
Port: pointer.Int32Ptr(servicePort),
}, },
CABundle: context.signingCert, CABundle: context.signingCert,
}, },
...@@ -997,6 +1006,7 @@ func testWebhooksForWebhookConfigurations(f *framework.Framework) { ...@@ -997,6 +1006,7 @@ func testWebhooksForWebhookConfigurations(f *framework.Framework) {
// but because the failure policy is ignore, it will // but because the failure policy is ignore, it will
// have no effect on admission requests. // have no effect on admission requests.
Path: strPtr(""), Path: strPtr(""),
Port: pointer.Int32Ptr(servicePort),
}, },
CABundle: nil, CABundle: nil,
}, },
...@@ -1044,6 +1054,7 @@ func testWebhooksForWebhookConfigurations(f *framework.Framework) { ...@@ -1044,6 +1054,7 @@ func testWebhooksForWebhookConfigurations(f *framework.Framework) {
// but because the failure policy is ignore, it will // but because the failure policy is ignore, it will
// have no effect on admission requests. // have no effect on admission requests.
Path: strPtr(""), Path: strPtr(""),
Port: pointer.Int32Ptr(servicePort),
}, },
CABundle: nil, CABundle: nil,
}, },
...@@ -1213,6 +1224,7 @@ func registerWebhookForCustomResource(f *framework.Framework, context *certConte ...@@ -1213,6 +1224,7 @@ func registerWebhookForCustomResource(f *framework.Framework, context *certConte
Namespace: namespace, Namespace: namespace,
Name: serviceName, Name: serviceName,
Path: strPtr("/custom-resource"), Path: strPtr("/custom-resource"),
Port: pointer.Int32Ptr(servicePort),
}, },
CABundle: context.signingCert, CABundle: context.signingCert,
}, },
...@@ -1254,6 +1266,7 @@ func registerMutatingWebhookForCustomResource(f *framework.Framework, context *c ...@@ -1254,6 +1266,7 @@ func registerMutatingWebhookForCustomResource(f *framework.Framework, context *c
Namespace: namespace, Namespace: namespace,
Name: serviceName, Name: serviceName,
Path: strPtr("/mutating-custom-resource"), Path: strPtr("/mutating-custom-resource"),
Port: pointer.Int32Ptr(servicePort),
}, },
CABundle: context.signingCert, CABundle: context.signingCert,
}, },
...@@ -1273,6 +1286,7 @@ func registerMutatingWebhookForCustomResource(f *framework.Framework, context *c ...@@ -1273,6 +1286,7 @@ func registerMutatingWebhookForCustomResource(f *framework.Framework, context *c
Namespace: namespace, Namespace: namespace,
Name: serviceName, Name: serviceName,
Path: strPtr("/mutating-custom-resource"), Path: strPtr("/mutating-custom-resource"),
Port: pointer.Int32Ptr(servicePort),
}, },
CABundle: context.signingCert, CABundle: context.signingCert,
}, },
...@@ -1401,6 +1415,7 @@ func registerValidatingWebhookForCRD(f *framework.Framework, context *certContex ...@@ -1401,6 +1415,7 @@ func registerValidatingWebhookForCRD(f *framework.Framework, context *certContex
Namespace: namespace, Namespace: namespace,
Name: serviceName, Name: serviceName,
Path: strPtr("/crd"), Path: strPtr("/crd"),
Port: pointer.Int32Ptr(servicePort),
}, },
CABundle: context.signingCert, CABundle: context.signingCert,
}, },
...@@ -1512,6 +1527,7 @@ func registerSlowWebhook(f *framework.Framework, context *certContext, policy *v ...@@ -1512,6 +1527,7 @@ func registerSlowWebhook(f *framework.Framework, context *certContext, policy *v
Namespace: namespace, Namespace: namespace,
Name: serviceName, Name: serviceName,
Path: strPtr("/always-allow-delay-5s"), Path: strPtr("/always-allow-delay-5s"),
Port: pointer.Int32Ptr(servicePort),
}, },
CABundle: context.signingCert, CABundle: context.signingCert,
}, },
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment