mirror of https://github.com/k3s-io/k3s
admission/webhook: move webhook initializer into plugin
parent
3df3c580b7
commit
e19257f2ec
|
@ -61,6 +61,7 @@ go_library(
|
|||
"//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/config:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/initializer:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/authentication/authenticator:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/server:go_default_library",
|
||||
|
|
|
@ -55,13 +55,16 @@ import (
|
|||
aggregatorapiserver "k8s.io/kube-aggregator/pkg/apiserver"
|
||||
openapi "k8s.io/kube-openapi/pkg/common"
|
||||
|
||||
webhookinit "k8s.io/apiserver/pkg/admission/plugin/webhook/initializer"
|
||||
"k8s.io/apiserver/pkg/storage/etcd3/preflight"
|
||||
clientgoinformers "k8s.io/client-go/informers"
|
||||
clientgoclientset "k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/kubernetes/cmd/kube-apiserver/app/options"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
"k8s.io/kubernetes/pkg/apis/apps"
|
||||
"k8s.io/kubernetes/pkg/apis/batch"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/apis/networking"
|
||||
"k8s.io/kubernetes/pkg/apis/storage"
|
||||
|
@ -86,8 +89,6 @@ import (
|
|||
"k8s.io/kubernetes/pkg/version"
|
||||
"k8s.io/kubernetes/plugin/pkg/auth/authenticator/token/bootstrap"
|
||||
|
||||
"k8s.io/client-go/rest"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
_ "k8s.io/kubernetes/pkg/util/reflector/prometheus" // for reflector metric registration
|
||||
_ "k8s.io/kubernetes/pkg/util/workqueue/prometheus" // for workqueue metric registration
|
||||
)
|
||||
|
@ -462,7 +463,7 @@ func BuildGenericConfig(s *options.ServerRunOptions, proxyTransport *http.Transp
|
|||
return ret, err
|
||||
})
|
||||
}
|
||||
pluginInitializer, err := BuildAdmissionPluginInitializer(
|
||||
pluginInitializers, err := BuildAdmissionPluginInitializers(
|
||||
s,
|
||||
client,
|
||||
sharedInformers,
|
||||
|
@ -478,7 +479,7 @@ func BuildGenericConfig(s *options.ServerRunOptions, proxyTransport *http.Transp
|
|||
versionedInformers,
|
||||
kubeClientConfig,
|
||||
legacyscheme.Scheme,
|
||||
pluginInitializer)
|
||||
pluginInitializers...)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, nil, fmt.Errorf("failed to initialize admission: %v", err)
|
||||
}
|
||||
|
@ -486,8 +487,8 @@ func BuildGenericConfig(s *options.ServerRunOptions, proxyTransport *http.Transp
|
|||
return genericConfig, sharedInformers, versionedInformers, insecureServingOptions, serviceResolver, nil
|
||||
}
|
||||
|
||||
// BuildAdmissionPluginInitializer constructs the admission plugin initializer
|
||||
func BuildAdmissionPluginInitializer(s *options.ServerRunOptions, client internalclientset.Interface, sharedInformers informers.SharedInformerFactory, serviceResolver aggregatorapiserver.ServiceResolver, webhookAuthWrapper webhookconfig.AuthenticationInfoResolverWrapper) (admission.PluginInitializer, error) {
|
||||
// BuildAdmissionPluginInitializers constructs the admission plugin initializer
|
||||
func BuildAdmissionPluginInitializers(s *options.ServerRunOptions, client internalclientset.Interface, sharedInformers informers.SharedInformerFactory, serviceResolver aggregatorapiserver.ServiceResolver, webhookAuthWrapper webhookconfig.AuthenticationInfoResolverWrapper) ([]admission.PluginInitializer, error) {
|
||||
var cloudConfig []byte
|
||||
|
||||
if s.CloudProvider.CloudConfigFile != "" {
|
||||
|
@ -503,9 +504,10 @@ func BuildAdmissionPluginInitializer(s *options.ServerRunOptions, client interna
|
|||
|
||||
quotaConfiguration := quotainstall.NewQuotaConfigurationForAdmission()
|
||||
|
||||
pluginInitializer := kubeapiserveradmission.NewPluginInitializer(client, sharedInformers, cloudConfig, restMapper, quotaConfiguration, webhookAuthWrapper, serviceResolver)
|
||||
kubePluginInitializer := kubeapiserveradmission.NewPluginInitializer(client, sharedInformers, cloudConfig, restMapper, quotaConfiguration)
|
||||
webhookPluginInitializer := webhookinit.NewPluginInitializer(webhookAuthWrapper, serviceResolver)
|
||||
|
||||
return pluginInitializer, nil
|
||||
return []admission.PluginInitializer{webhookPluginInitializer, kubePluginInitializer}, nil
|
||||
}
|
||||
|
||||
// BuildAuthenticator constructs the authenticator
|
||||
|
|
|
@ -8,13 +8,10 @@ load(
|
|||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["init_test.go"],
|
||||
srcs = ["initializer_test.go"],
|
||||
importpath = "k8s.io/kubernetes/pkg/kubeapiserver/admission",
|
||||
library = ":go_default_library",
|
||||
deps = [
|
||||
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/config:go_default_library",
|
||||
],
|
||||
deps = ["//vendor/k8s.io/apiserver/pkg/admission:go_default_library"],
|
||||
)
|
||||
|
||||
go_library(
|
||||
|
|
|
@ -17,8 +17,6 @@ limitations under the License.
|
|||
package admission
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
webhookconfig "k8s.io/apiserver/pkg/admission/plugin/webhook/config"
|
||||
|
@ -59,25 +57,7 @@ type WantsQuotaConfiguration interface {
|
|||
admission.InitializationValidator
|
||||
}
|
||||
|
||||
// WantsServiceResolver defines a fuction that accepts a ServiceResolver for
|
||||
// admission plugins that need to make calls to services.
|
||||
type WantsServiceResolver interface {
|
||||
SetServiceResolver(webhookconfig.ServiceResolver)
|
||||
}
|
||||
|
||||
// ServiceResolver knows how to convert a service reference into an actual
|
||||
// location.
|
||||
type ServiceResolver interface {
|
||||
ResolveEndpoint(namespace, name string) (*url.URL, error)
|
||||
}
|
||||
|
||||
// WantsAuthenticationInfoResolverWrapper defines a function that wraps the standard AuthenticationInfoResolver
|
||||
// to allow the apiserver to control what is returned as auth info
|
||||
type WantsAuthenticationInfoResolverWrapper interface {
|
||||
SetAuthenticationInfoResolverWrapper(webhookconfig.AuthenticationInfoResolverWrapper)
|
||||
admission.InitializationValidator
|
||||
}
|
||||
|
||||
// PluginInitializer is used for initialization of the Kubernetes specific admission plugins.
|
||||
type PluginInitializer struct {
|
||||
internalClient internalclientset.Interface
|
||||
externalClient clientset.Interface
|
||||
|
@ -101,17 +81,13 @@ func NewPluginInitializer(
|
|||
cloudConfig []byte,
|
||||
restMapper meta.RESTMapper,
|
||||
quotaConfiguration quota.Configuration,
|
||||
authenticationInfoResolverWrapper webhookconfig.AuthenticationInfoResolverWrapper,
|
||||
serviceResolver webhookconfig.ServiceResolver,
|
||||
) *PluginInitializer {
|
||||
return &PluginInitializer{
|
||||
internalClient: internalClient,
|
||||
informers: sharedInformers,
|
||||
cloudConfig: cloudConfig,
|
||||
restMapper: restMapper,
|
||||
quotaConfiguration: quotaConfiguration,
|
||||
authenticationInfoResolverWrapper: authenticationInfoResolverWrapper,
|
||||
serviceResolver: serviceResolver,
|
||||
internalClient: internalClient,
|
||||
informers: sharedInformers,
|
||||
cloudConfig: cloudConfig,
|
||||
restMapper: restMapper,
|
||||
quotaConfiguration: quotaConfiguration,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -137,14 +113,4 @@ func (i *PluginInitializer) Initialize(plugin admission.Interface) {
|
|||
if wants, ok := plugin.(WantsQuotaConfiguration); ok {
|
||||
wants.SetQuotaConfiguration(i.quotaConfiguration)
|
||||
}
|
||||
|
||||
if wants, ok := plugin.(WantsServiceResolver); ok {
|
||||
wants.SetServiceResolver(i.serviceResolver)
|
||||
}
|
||||
|
||||
if wants, ok := plugin.(WantsAuthenticationInfoResolverWrapper); ok {
|
||||
if i.authenticationInfoResolverWrapper != nil {
|
||||
wants.SetAuthenticationInfoResolverWrapper(i.authenticationInfoResolverWrapper)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,11 +17,9 @@ limitations under the License.
|
|||
package admission
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
"k8s.io/apiserver/pkg/admission/plugin/webhook/config"
|
||||
)
|
||||
|
||||
type doNothingAdmission struct{}
|
||||
|
@ -41,7 +39,7 @@ func (self *WantsCloudConfigAdmissionPlugin) SetCloudConfig(cloudConfig []byte)
|
|||
|
||||
func TestCloudConfigAdmissionPlugin(t *testing.T) {
|
||||
cloudConfig := []byte("cloud-configuration")
|
||||
initializer := NewPluginInitializer(nil, nil, cloudConfig, nil, nil, nil, nil)
|
||||
initializer := NewPluginInitializer(nil, nil, cloudConfig, nil, nil)
|
||||
wantsCloudConfigAdmission := &WantsCloudConfigAdmissionPlugin{}
|
||||
initializer.Initialize(wantsCloudConfigAdmission)
|
||||
|
||||
|
@ -49,26 +47,3 @@ func TestCloudConfigAdmissionPlugin(t *testing.T) {
|
|||
t.Errorf("Expected cloud config to be initialized but found nil")
|
||||
}
|
||||
}
|
||||
|
||||
type fakeServiceResolver struct{}
|
||||
|
||||
func (f *fakeServiceResolver) ResolveEndpoint(namespace, name string) (*url.URL, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
type serviceWanter struct {
|
||||
doNothingAdmission
|
||||
got ServiceResolver
|
||||
}
|
||||
|
||||
func (s *serviceWanter) SetServiceResolver(sr config.ServiceResolver) { s.got = sr }
|
||||
|
||||
func TestWantsServiceResolver(t *testing.T) {
|
||||
sw := &serviceWanter{}
|
||||
fsr := &fakeServiceResolver{}
|
||||
i := NewPluginInitializer(nil, nil, nil, nil, nil, nil, fsr)
|
||||
i.Initialize(sw)
|
||||
if got, ok := sw.got.(*fakeServiceResolver); !ok || got != fsr {
|
||||
t.Errorf("plumbing fail - %v %v#", ok, got)
|
||||
}
|
||||
}
|
|
@ -87,7 +87,7 @@ func newGCPermissionsEnforcement() (*gcPermissionsEnforcement, error) {
|
|||
}
|
||||
|
||||
genericPluginInitializer := initializer.New(nil, nil, fakeAuthorizer{}, nil)
|
||||
pluginInitializer := kubeadmission.NewPluginInitializer(nil, nil, nil, legacyscheme.Registry.RESTMapper(), nil, nil, nil)
|
||||
pluginInitializer := kubeadmission.NewPluginInitializer(nil, nil, nil, legacyscheme.Registry.RESTMapper(), nil)
|
||||
initializersChain := admission.PluginInitializers{}
|
||||
initializersChain = append(initializersChain, genericPluginInitializer)
|
||||
initializersChain = append(initializersChain, pluginInitializer)
|
||||
|
|
|
@ -760,7 +760,7 @@ func newHandlerForTest(c clientset.Interface) (*LimitRanger, informers.SharedInf
|
|||
if err != nil {
|
||||
return nil, f, err
|
||||
}
|
||||
pluginInitializer := kubeadmission.NewPluginInitializer(c, f, nil, nil, nil, nil, nil)
|
||||
pluginInitializer := kubeadmission.NewPluginInitializer(c, f, nil, nil, nil)
|
||||
pluginInitializer.Initialize(handler)
|
||||
err = admission.ValidateInitialization(handler)
|
||||
return handler, f, err
|
||||
|
|
|
@ -38,7 +38,7 @@ import (
|
|||
func newHandlerForTest(c clientset.Interface) (admission.MutationInterface, informers.SharedInformerFactory, error) {
|
||||
f := informers.NewSharedInformerFactory(c, 5*time.Minute)
|
||||
handler := NewProvision()
|
||||
pluginInitializer := kubeadmission.NewPluginInitializer(c, f, nil, nil, nil, nil, nil)
|
||||
pluginInitializer := kubeadmission.NewPluginInitializer(c, f, nil, nil, nil)
|
||||
pluginInitializer.Initialize(handler)
|
||||
err := admission.ValidateInitialization(handler)
|
||||
return handler, f, err
|
||||
|
|
|
@ -37,7 +37,7 @@ import (
|
|||
func newHandlerForTest(c clientset.Interface) (admission.ValidationInterface, informers.SharedInformerFactory, error) {
|
||||
f := informers.NewSharedInformerFactory(c, 5*time.Minute)
|
||||
handler := NewExists()
|
||||
pluginInitializer := kubeadmission.NewPluginInitializer(c, f, nil, nil, nil, nil, nil)
|
||||
pluginInitializer := kubeadmission.NewPluginInitializer(c, f, nil, nil, nil)
|
||||
pluginInitializer.Initialize(handler)
|
||||
err := admission.ValidateInitialization(handler)
|
||||
return handler, f, err
|
||||
|
|
|
@ -253,7 +253,7 @@ func TestIgnoreUpdatingInitializedPod(t *testing.T) {
|
|||
func newHandlerForTest(c clientset.Interface) (*podNodeSelector, informers.SharedInformerFactory, error) {
|
||||
f := informers.NewSharedInformerFactory(c, 5*time.Minute)
|
||||
handler := NewPodNodeSelector(nil)
|
||||
pluginInitializer := kubeadmission.NewPluginInitializer(c, f, nil, nil, nil, nil, nil)
|
||||
pluginInitializer := kubeadmission.NewPluginInitializer(c, f, nil, nil, nil)
|
||||
pluginInitializer.Initialize(handler)
|
||||
err := admission.ValidateInitialization(handler)
|
||||
return handler, f, err
|
||||
|
|
|
@ -361,7 +361,7 @@ func newHandlerForTest(c clientset.Interface) (*podTolerationsPlugin, informers.
|
|||
return nil, nil, err
|
||||
}
|
||||
handler := NewPodTolerationsPlugin(pluginConfig)
|
||||
pluginInitializer := kubeadmission.NewPluginInitializer(c, f, nil, nil, nil, nil, nil)
|
||||
pluginInitializer := kubeadmission.NewPluginInitializer(c, f, nil, nil, nil)
|
||||
pluginInitializer.Initialize(handler)
|
||||
err = admission.ValidateInitialization(handler)
|
||||
return handler, f, err
|
||||
|
|
|
@ -80,6 +80,7 @@ filegroup(
|
|||
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/namespace/lifecycle:all-srcs",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/config:all-srcs",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/errors:all-srcs",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/initializer:all-srcs",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating:all-srcs",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/namespace:all-srcs",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/request:all-srcs",
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["initializer.go"],
|
||||
importpath = "k8s.io/apiserver/pkg/admission/plugin/webhook/initializer",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/config:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["initializer_test.go"],
|
||||
importpath = "k8s.io/apiserver/pkg/admission/plugin/webhook/initializer",
|
||||
library = ":go_default_library",
|
||||
deps = [
|
||||
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/config:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
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 initializer
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
webhookconfig "k8s.io/apiserver/pkg/admission/plugin/webhook/config"
|
||||
)
|
||||
|
||||
// WantsServiceResolver defines a fuction that accepts a ServiceResolver for
|
||||
// admission plugins that need to make calls to services.
|
||||
type WantsServiceResolver interface {
|
||||
SetServiceResolver(webhookconfig.ServiceResolver)
|
||||
}
|
||||
|
||||
// ServiceResolver knows how to convert a service reference into an actual
|
||||
// location.
|
||||
type ServiceResolver interface {
|
||||
ResolveEndpoint(namespace, name string) (*url.URL, error)
|
||||
}
|
||||
|
||||
// WantsAuthenticationInfoResolverWrapper defines a function that wraps the standard AuthenticationInfoResolver
|
||||
// to allow the apiserver to control what is returned as auth info
|
||||
type WantsAuthenticationInfoResolverWrapper interface {
|
||||
SetAuthenticationInfoResolverWrapper(webhookconfig.AuthenticationInfoResolverWrapper)
|
||||
admission.InitializationValidator
|
||||
}
|
||||
|
||||
// PluginInitializer is used for initialization of the webhook admission plugin.
|
||||
type PluginInitializer struct {
|
||||
serviceResolver webhookconfig.ServiceResolver
|
||||
authenticationInfoResolverWrapper webhookconfig.AuthenticationInfoResolverWrapper
|
||||
}
|
||||
|
||||
var _ admission.PluginInitializer = &PluginInitializer{}
|
||||
|
||||
// NewPluginInitializer constructs new instance of PluginInitializer
|
||||
func NewPluginInitializer(
|
||||
authenticationInfoResolverWrapper webhookconfig.AuthenticationInfoResolverWrapper,
|
||||
serviceResolver webhookconfig.ServiceResolver,
|
||||
) *PluginInitializer {
|
||||
return &PluginInitializer{
|
||||
authenticationInfoResolverWrapper: authenticationInfoResolverWrapper,
|
||||
serviceResolver: serviceResolver,
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize checks the initialization interfaces implemented by each plugin
|
||||
// and provide the appropriate initialization data
|
||||
func (i *PluginInitializer) Initialize(plugin admission.Interface) {
|
||||
if wants, ok := plugin.(WantsServiceResolver); ok {
|
||||
wants.SetServiceResolver(i.serviceResolver)
|
||||
}
|
||||
|
||||
if wants, ok := plugin.(WantsAuthenticationInfoResolverWrapper); ok {
|
||||
if i.authenticationInfoResolverWrapper != nil {
|
||||
wants.SetAuthenticationInfoResolverWrapper(i.authenticationInfoResolverWrapper)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
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 initializer
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
"k8s.io/apiserver/pkg/admission/plugin/webhook/config"
|
||||
)
|
||||
|
||||
type doNothingAdmission struct{}
|
||||
|
||||
func (doNothingAdmission) Admit(a admission.Attributes) error { return nil }
|
||||
func (doNothingAdmission) Handles(o admission.Operation) bool { return false }
|
||||
func (doNothingAdmission) Validate() error { return nil }
|
||||
|
||||
type fakeServiceResolver struct{}
|
||||
|
||||
func (f *fakeServiceResolver) ResolveEndpoint(namespace, name string) (*url.URL, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
type serviceWanter struct {
|
||||
doNothingAdmission
|
||||
got ServiceResolver
|
||||
}
|
||||
|
||||
func (s *serviceWanter) SetServiceResolver(sr config.ServiceResolver) { s.got = sr }
|
||||
|
||||
func TestWantsServiceResolver(t *testing.T) {
|
||||
sw := &serviceWanter{}
|
||||
fsr := &fakeServiceResolver{}
|
||||
i := NewPluginInitializer(nil, fsr)
|
||||
i.Initialize(sw)
|
||||
if got, ok := sw.got.(*fakeServiceResolver); !ok || got != fsr {
|
||||
t.Errorf("plumbing fail - %v %v#", ok, got)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue