mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-27 13:37:30 +00:00
Merge pull request #52673 from p0lyn0mial/webhook_default_service_resolver
Automatic merge from submit-queue (batch tested with PRs 52831, 52764, 52763, 52673, 52558). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.. default service resolver for webhook admission **What this PR does / why we need it**: provides a default service resolver for webhook plugin. The rationale behind is that webhook plugins names can be resolved by a dns server working inside a cluster. **Release note**: ``` NONE ```
This commit is contained in:
commit
7f3f986402
@ -188,9 +188,6 @@ func (i *PluginInitializer) Initialize(plugin admission.Interface) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if wants, ok := plugin.(WantsServiceResolver); ok {
|
if wants, ok := plugin.(WantsServiceResolver); ok {
|
||||||
if i.serviceResolver == nil {
|
|
||||||
panic("An admission plugin wants the service resolver, but it was not provided.")
|
|
||||||
}
|
|
||||||
wants.SetServiceResolver(i.serviceResolver)
|
wants.SetServiceResolver(i.serviceResolver)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ go_test(
|
|||||||
"admission_test.go",
|
"admission_test.go",
|
||||||
"certs_test.go",
|
"certs_test.go",
|
||||||
"rules_test.go",
|
"rules_test.go",
|
||||||
|
"serviceresolver_test.go",
|
||||||
],
|
],
|
||||||
library = ":go_default_library",
|
library = ":go_default_library",
|
||||||
deps = [
|
deps = [
|
||||||
@ -32,6 +33,7 @@ go_library(
|
|||||||
"admission.go",
|
"admission.go",
|
||||||
"doc.go",
|
"doc.go",
|
||||||
"rules.go",
|
"rules.go",
|
||||||
|
"serviceresolver.go",
|
||||||
],
|
],
|
||||||
deps = [
|
deps = [
|
||||||
"//pkg/api:go_default_library",
|
"//pkg/api:go_default_library",
|
||||||
|
@ -97,6 +97,7 @@ func NewGenericAdmissionWebhook() (*GenericAdmissionWebhook, error) {
|
|||||||
negotiatedSerializer: serializer.NegotiatedSerializerWrapper(runtime.SerializerInfo{
|
negotiatedSerializer: serializer.NegotiatedSerializerWrapper(runtime.SerializerInfo{
|
||||||
Serializer: api.Codecs.LegacyCodec(admissionv1alpha1.SchemeGroupVersion),
|
Serializer: api.Codecs.LegacyCodec(admissionv1alpha1.SchemeGroupVersion),
|
||||||
}),
|
}),
|
||||||
|
serviceResolver: defaultServiceResolver{},
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,9 +122,13 @@ func (a *GenericAdmissionWebhook) SetProxyTransport(pt *http.Transport) {
|
|||||||
a.proxyTransport = pt
|
a.proxyTransport = pt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetServiceResolver sets a service resolver for the webhook admission plugin.
|
||||||
|
// Passing a nil resolver does not have an effect, instead a default one will be used.
|
||||||
func (a *GenericAdmissionWebhook) SetServiceResolver(sr admissioninit.ServiceResolver) {
|
func (a *GenericAdmissionWebhook) SetServiceResolver(sr admissioninit.ServiceResolver) {
|
||||||
|
if sr != nil {
|
||||||
a.serviceResolver = sr
|
a.serviceResolver = sr
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (a *GenericAdmissionWebhook) SetClientCert(cert, key []byte) {
|
func (a *GenericAdmissionWebhook) SetClientCert(cert, key []byte) {
|
||||||
a.clientCert = cert
|
a.clientCert = cert
|
||||||
|
42
plugin/pkg/admission/webhook/serviceresolver.go
Normal file
42
plugin/pkg/admission/webhook/serviceresolver.go
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2017 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 webhook checks a webhook for configured operation admission
|
||||||
|
package webhook
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
|
||||||
|
admissioninit "k8s.io/kubernetes/pkg/kubeapiserver/admission"
|
||||||
|
)
|
||||||
|
|
||||||
|
type defaultServiceResolver struct{}
|
||||||
|
|
||||||
|
var _ admissioninit.ServiceResolver = defaultServiceResolver{}
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
// for example:
|
||||||
|
// name=ross namespace=andromeda resolves to https://ross.andromeda.svc
|
||||||
|
func (sr defaultServiceResolver) ResolveEndpoint(namespace, name string) (*url.URL, error) {
|
||||||
|
if len(name) == 0 || len(namespace) == 0 {
|
||||||
|
return &url.URL{}, errors.New("cannot resolve an empty service name or namespace")
|
||||||
|
}
|
||||||
|
|
||||||
|
return url.Parse(fmt.Sprintf("https://%s.%s.svc", name, namespace))
|
||||||
|
}
|
57
plugin/pkg/admission/webhook/serviceresolver_test.go
Normal file
57
plugin/pkg/admission/webhook/serviceresolver_test.go
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2017 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 webhook checks a webhook for configured operation admission
|
||||||
|
package webhook
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDefaultServiceResolver(t *testing.T) {
|
||||||
|
scenarios := []struct {
|
||||||
|
serviceName string
|
||||||
|
serviceNamespace string
|
||||||
|
expectedOutput string
|
||||||
|
expectError bool
|
||||||
|
}{
|
||||||
|
// scenario 1: a service name along with a namespace resolves
|
||||||
|
{serviceName: "ross", serviceNamespace: "andromeda", expectedOutput: "https://ross.andromeda.svc"},
|
||||||
|
// scenario 2: a service name without a namespace does not resolve
|
||||||
|
{serviceName: "ross", expectError: true},
|
||||||
|
// scenario 3: cannot resolve an empty service name
|
||||||
|
{serviceNamespace: "andromeda", expectError: true},
|
||||||
|
}
|
||||||
|
|
||||||
|
// act
|
||||||
|
for index, scenario := range scenarios {
|
||||||
|
t.Run(fmt.Sprintf("scenario %d", index), func(t *testing.T) {
|
||||||
|
target := defaultServiceResolver{}
|
||||||
|
serviceURL, err := target.ResolveEndpoint(scenario.serviceNamespace, scenario.serviceName)
|
||||||
|
|
||||||
|
if err != nil && !scenario.expectError {
|
||||||
|
t.Errorf("unexpected error has occurred = %v", err)
|
||||||
|
}
|
||||||
|
if err == nil && scenario.expectError {
|
||||||
|
t.Error("expected an error but got nothing")
|
||||||
|
}
|
||||||
|
if serviceURL.String() != scenario.expectedOutput {
|
||||||
|
t.Errorf("expected = %s, got = %s", scenario.expectedOutput, serviceURL.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user