Commit 8cea69aa authored by p0lyn0mial's avatar p0lyn0mial

This PR implements AdmissionOptions.ApplyTo

ApplyTo adds the admission chain to the server configuration the method lazily initializes a generic plugin that is appended to the list of pluginInitializers. apiserver.Config will hold an instance of SharedInformerFactory to ensure we only have once instance. The field will be initialized in apisever.SecureServingOptions
parent 4807e6ca
...@@ -110,6 +110,8 @@ func NewServerRunOptions() *ServerRunOptions { ...@@ -110,6 +110,8 @@ func NewServerRunOptions() *ServerRunOptions {
} }
// Overwrite the default for storage data format. // Overwrite the default for storage data format.
s.Etcd.DefaultStorageMediaType = "application/vnd.kubernetes.protobuf" s.Etcd.DefaultStorageMediaType = "application/vnd.kubernetes.protobuf"
// Set the default for admission plugins names
s.Admission.PluginNames = []string{"AlwaysAdmit"}
return &s return &s
} }
......
...@@ -359,39 +359,41 @@ func BuildGenericConfig(s *options.ServerRunOptions) (*genericapiserver.Config, ...@@ -359,39 +359,41 @@ func BuildGenericConfig(s *options.ServerRunOptions) (*genericapiserver.Config,
genericConfig.DisabledPostStartHooks.Insert(rbacrest.PostStartHookName) genericConfig.DisabledPostStartHooks.Insert(rbacrest.PostStartHookName)
} }
genericConfig.AdmissionControl, err = BuildAdmission(s, pluginInitializer, err := BuildAdmissionPluginInitializer(
s.Admission.Plugins, s,
client, client,
sharedInformers, sharedInformers,
genericConfig.Authorizer, genericConfig.Authorizer,
) )
if err != nil { if err != nil {
return nil, nil, nil, fmt.Errorf("failed to initialize admission: %v", err) return nil, nil, nil, fmt.Errorf("failed to create admission plugin initializer: %v", err)
} }
err = s.Admission.ApplyTo(
genericConfig,
pluginInitializer)
if err != nil {
return nil, nil, nil, fmt.Errorf("failed to initialize admission: %v", err)
}
return genericConfig, sharedInformers, insecureServingOptions, nil return genericConfig, sharedInformers, insecureServingOptions, nil
} }
// BuildAdmission constructs the admission chain // BuildAdmissionPluginInitializer constructs the admission plugin initializer
func BuildAdmission(s *options.ServerRunOptions, plugins *admission.Plugins, client internalclientset.Interface, sharedInformers informers.SharedInformerFactory, apiAuthorizer authorizer.Authorizer) (admission.Interface, error) { func BuildAdmissionPluginInitializer(s *options.ServerRunOptions, client internalclientset.Interface, sharedInformers informers.SharedInformerFactory, apiAuthorizer authorizer.Authorizer) (admission.PluginInitializer, error) {
admissionControlPluginNames := strings.Split(s.Admission.Control, ",")
var cloudConfig []byte var cloudConfig []byte
var err error
if s.CloudProvider.CloudConfigFile != "" { if s.CloudProvider.CloudConfigFile != "" {
var err error
cloudConfig, err = ioutil.ReadFile(s.CloudProvider.CloudConfigFile) cloudConfig, err = ioutil.ReadFile(s.CloudProvider.CloudConfigFile)
if err != nil { if err != nil {
glog.Fatalf("Error reading from cloud configuration file %s: %#v", s.CloudProvider.CloudConfigFile, err) glog.Fatalf("Error reading from cloud configuration file %s: %#v", s.CloudProvider.CloudConfigFile, err)
} }
} }
// TODO: use a dynamic restmapper. See https://github.com/kubernetes/kubernetes/pull/42615. // TODO: use a dynamic restmapper. See https://github.com/kubernetes/kubernetes/pull/42615.
restMapper := api.Registry.RESTMapper() restMapper := api.Registry.RESTMapper()
pluginInitializer := kubeapiserveradmission.NewPluginInitializer(client, sharedInformers, apiAuthorizer, cloudConfig, restMapper) pluginInitializer := kubeapiserveradmission.NewPluginInitializer(client, sharedInformers, apiAuthorizer, cloudConfig, restMapper)
admissionConfigProvider, err := admission.ReadAdmissionConfiguration(admissionControlPluginNames, s.Admission.ControlConfigFile) return pluginInitializer, nil
if err != nil {
return nil, fmt.Errorf("failed to read plugin config: %v", err)
}
return plugins.NewFromPlugins(admissionControlPluginNames, admissionConfigProvider, pluginInitializer)
} }
// BuildAuthenticator constructs the authenticator // BuildAuthenticator constructs the authenticator
......
...@@ -70,6 +70,8 @@ func NewServerRunOptions() *ServerRunOptions { ...@@ -70,6 +70,8 @@ func NewServerRunOptions() *ServerRunOptions {
} }
// Overwrite the default for storage data format. // Overwrite the default for storage data format.
s.Etcd.DefaultStorageMediaType = "application/vnd.kubernetes.protobuf" s.Etcd.DefaultStorageMediaType = "application/vnd.kubernetes.protobuf"
// Set the default for admission plugins names
s.Admission.PluginNames = []string{"AlwaysAdmit"}
return &s return &s
} }
......
...@@ -34,7 +34,6 @@ import ( ...@@ -34,7 +34,6 @@ import (
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
utilerrors "k8s.io/apimachinery/pkg/util/errors" utilerrors "k8s.io/apimachinery/pkg/util/errors"
"k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apiserver/pkg/admission"
genericapiserver "k8s.io/apiserver/pkg/server" genericapiserver "k8s.io/apiserver/pkg/server"
"k8s.io/apiserver/pkg/server/filters" "k8s.io/apiserver/pkg/server/filters"
serverstorage "k8s.io/apiserver/pkg/server/storage" serverstorage "k8s.io/apiserver/pkg/server/storage"
...@@ -185,21 +184,20 @@ func NonBlockingRun(s *options.ServerRunOptions, stopCh <-chan struct{}) error { ...@@ -185,21 +184,20 @@ func NonBlockingRun(s *options.ServerRunOptions, stopCh <-chan struct{}) error {
return fmt.Errorf("invalid Authorization Config: %v", err) return fmt.Errorf("invalid Authorization Config: %v", err)
} }
admissionControlPluginNames := strings.Split(s.Admission.Control, ",")
var cloudConfig []byte var cloudConfig []byte
if s.CloudProvider.CloudConfigFile != "" { if s.CloudProvider.CloudConfigFile != "" {
cloudConfig, err = ioutil.ReadFile(s.CloudProvider.CloudConfigFile) cloudConfig, err = ioutil.ReadFile(s.CloudProvider.CloudConfigFile)
if err != nil { if err != nil {
glog.Fatalf("Error reading from cloud configuration file %s: %#v", s.CloudProvider.CloudConfigFile, err) glog.Fatalf("Error reading from cloud configuration file %s: %#v", s.CloudProvider.CloudConfigFile, err)
} }
} }
pluginInitializer := kubeapiserveradmission.NewPluginInitializer(client, sharedInformers, apiAuthorizer, cloudConfig, nil) pluginInitializer := kubeapiserveradmission.NewPluginInitializer(client, sharedInformers, apiAuthorizer, cloudConfig, nil)
admissionConfigProvider, err := admission.ReadAdmissionConfiguration(admissionControlPluginNames, s.Admission.ControlConfigFile)
if err != nil { err = s.Admission.ApplyTo(
return fmt.Errorf("failed to read plugin config: %v", err) genericConfig,
} pluginInitializer,
admissionController, err := kubeapiserveradmission.Plugins.NewFromPlugins(admissionControlPluginNames, admissionConfigProvider, pluginInitializer) )
if err != nil { if err != nil {
return fmt.Errorf("failed to initialize plugins: %v", err) return fmt.Errorf("failed to initialize plugins: %v", err)
} }
...@@ -208,7 +206,6 @@ func NonBlockingRun(s *options.ServerRunOptions, stopCh <-chan struct{}) error { ...@@ -208,7 +206,6 @@ func NonBlockingRun(s *options.ServerRunOptions, stopCh <-chan struct{}) error {
genericConfig.Version = &kubeVersion genericConfig.Version = &kubeVersion
genericConfig.Authenticator = apiAuthenticator genericConfig.Authenticator = apiAuthenticator
genericConfig.Authorizer = apiAuthorizer genericConfig.Authorizer = apiAuthorizer
genericConfig.AdmissionControl = admissionController
genericConfig.OpenAPIConfig = genericapiserver.DefaultOpenAPIConfig(openapi.GetOpenAPIDefinitions, api.Scheme) genericConfig.OpenAPIConfig = genericapiserver.DefaultOpenAPIConfig(openapi.GetOpenAPIDefinitions, api.Scheme)
genericConfig.OpenAPIConfig.PostProcessSpec = postProcessOpenAPISpecForBackwardCompatibility genericConfig.OpenAPIConfig.PostProcessSpec = postProcessOpenAPISpecForBackwardCompatibility
genericConfig.OpenAPIConfig.SecurityDefinitions = securityDefinitions genericConfig.OpenAPIConfig.SecurityDefinitions = securityDefinitions
......
...@@ -37,6 +37,8 @@ import ( ...@@ -37,6 +37,8 @@ import (
"k8s.io/apiserver/pkg/server/options" "k8s.io/apiserver/pkg/server/options"
serverstorage "k8s.io/apiserver/pkg/server/storage" serverstorage "k8s.io/apiserver/pkg/server/storage"
etcdtesting "k8s.io/apiserver/pkg/storage/etcd/testing" etcdtesting "k8s.io/apiserver/pkg/storage/etcd/testing"
"k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes"
restclient "k8s.io/client-go/rest" restclient "k8s.io/client-go/rest"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/pkg/api/testapi"
...@@ -101,6 +103,12 @@ func setUp(t *testing.T) (*etcdtesting.EtcdTestServer, Config, *assert.Assertion ...@@ -101,6 +103,12 @@ func setUp(t *testing.T) (*etcdtesting.EtcdTestServer, Config, *assert.Assertion
TLSClientConfig: &tls.Config{}, TLSClientConfig: &tls.Config{},
}) })
clientset, err := kubernetes.NewForConfig(config.GenericConfig.LoopbackClientConfig)
if err != nil {
t.Fatalf("unable to create client set due to %v", err)
}
config.GenericConfig.SharedInformerFactory = informers.NewSharedInformerFactory(clientset, config.GenericConfig.LoopbackClientConfig.Timeout)
return server, *config, assert.New(t) return server, *config, assert.New(t)
} }
......
...@@ -54,6 +54,7 @@ import ( ...@@ -54,6 +54,7 @@ import (
genericfilters "k8s.io/apiserver/pkg/server/filters" genericfilters "k8s.io/apiserver/pkg/server/filters"
"k8s.io/apiserver/pkg/server/healthz" "k8s.io/apiserver/pkg/server/healthz"
"k8s.io/apiserver/pkg/server/routes" "k8s.io/apiserver/pkg/server/routes"
"k8s.io/client-go/informers"
restclient "k8s.io/client-go/rest" restclient "k8s.io/client-go/rest"
certutil "k8s.io/client-go/util/cert" certutil "k8s.io/client-go/util/cert"
...@@ -109,6 +110,8 @@ type Config struct { ...@@ -109,6 +110,8 @@ type Config struct {
// Will default to a value based on secure serving info and available ipv4 IPs. // Will default to a value based on secure serving info and available ipv4 IPs.
ExternalAddress string ExternalAddress string
// SharedInformerFactory provides shared informers for resources
SharedInformerFactory informers.SharedInformerFactory
//=========================================================================== //===========================================================================
// Fields you probably don't care about changing // Fields you probably don't care about changing
//=========================================================================== //===========================================================================
...@@ -405,6 +408,16 @@ func (c completedConfig) New(delegationTarget DelegationTarget) (*GenericAPIServ ...@@ -405,6 +408,16 @@ func (c completedConfig) New(delegationTarget DelegationTarget) (*GenericAPIServ
s.postStartHooks[k] = v s.postStartHooks[k] = v
} }
genericApiServerHookName := "generic-apiserver-start-informers"
if c.SharedInformerFactory != nil && !s.isHookRegistered(genericApiServerHookName) {
err := s.AddPostStartHook(genericApiServerHookName, func(context PostStartHookContext) error {
c.SharedInformerFactory.Start(context.StopCh)
return nil
})
if err != nil {
return nil, err
}
}
for _, delegateCheck := range delegationTarget.HealthzChecks() { for _, delegateCheck := range delegationTarget.HealthzChecks() {
skip := false skip := false
for _, existingCheck := range c.HealthzChecks { for _, existingCheck := range c.HealthzChecks {
......
...@@ -28,6 +28,8 @@ import ( ...@@ -28,6 +28,8 @@ import (
"k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/sets"
genericapirequest "k8s.io/apiserver/pkg/endpoints/request" genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
"k8s.io/apiserver/pkg/server/healthz" "k8s.io/apiserver/pkg/server/healthz"
"k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes/fake"
"k8s.io/client-go/rest" "k8s.io/client-go/rest"
) )
...@@ -38,6 +40,11 @@ func TestNewWithDelegate(t *testing.T) { ...@@ -38,6 +40,11 @@ func TestNewWithDelegate(t *testing.T) {
delegateConfig.LegacyAPIGroupPrefixes = sets.NewString("/api") delegateConfig.LegacyAPIGroupPrefixes = sets.NewString("/api")
delegateConfig.LoopbackClientConfig = &rest.Config{} delegateConfig.LoopbackClientConfig = &rest.Config{}
delegateConfig.SwaggerConfig = DefaultSwaggerConfig() delegateConfig.SwaggerConfig = DefaultSwaggerConfig()
clientset := fake.NewSimpleClientset()
if clientset == nil {
t.Fatal("unable to create fake client set")
}
delegateConfig.SharedInformerFactory = informers.NewSharedInformerFactory(clientset, delegateConfig.LoopbackClientConfig.Timeout)
delegateHealthzCalled := false delegateHealthzCalled := false
delegateConfig.HealthzChecks = append(delegateConfig.HealthzChecks, healthz.NamedCheck("delegate-health", func(r *http.Request) error { delegateConfig.HealthzChecks = append(delegateConfig.HealthzChecks, healthz.NamedCheck("delegate-health", func(r *http.Request) error {
...@@ -66,6 +73,7 @@ func TestNewWithDelegate(t *testing.T) { ...@@ -66,6 +73,7 @@ func TestNewWithDelegate(t *testing.T) {
wrappingConfig.LegacyAPIGroupPrefixes = sets.NewString("/api") wrappingConfig.LegacyAPIGroupPrefixes = sets.NewString("/api")
wrappingConfig.LoopbackClientConfig = &rest.Config{} wrappingConfig.LoopbackClientConfig = &rest.Config{}
wrappingConfig.SwaggerConfig = DefaultSwaggerConfig() wrappingConfig.SwaggerConfig = DefaultSwaggerConfig()
wrappingConfig.SharedInformerFactory = informers.NewSharedInformerFactory(clientset, wrappingConfig.LoopbackClientConfig.Timeout)
wrappingHealthzCalled := false wrappingHealthzCalled := false
wrappingConfig.HealthzChecks = append(wrappingConfig.HealthzChecks, healthz.NamedCheck("wrapping-health", func(r *http.Request) error { wrappingConfig.HealthzChecks = append(wrappingConfig.HealthzChecks, healthz.NamedCheck("wrapping-health", func(r *http.Request) error {
...@@ -102,6 +110,7 @@ func TestNewWithDelegate(t *testing.T) { ...@@ -102,6 +110,7 @@ func TestNewWithDelegate(t *testing.T) {
"/healthz/delegate-health", "/healthz/delegate-health",
"/healthz/ping", "/healthz/ping",
"/healthz/poststarthook/delegate-post-start-hook", "/healthz/poststarthook/delegate-post-start-hook",
"/healthz/poststarthook/generic-apiserver-start-informers",
"/healthz/poststarthook/wrapping-post-start-hook", "/healthz/poststarthook/wrapping-post-start-hook",
"/healthz/wrapping-health", "/healthz/wrapping-health",
"/swaggerapi/" "/swaggerapi/"
...@@ -110,6 +119,7 @@ func TestNewWithDelegate(t *testing.T) { ...@@ -110,6 +119,7 @@ func TestNewWithDelegate(t *testing.T) {
checkPath(server.URL+"/healthz", http.StatusInternalServerError, `[+]ping ok checkPath(server.URL+"/healthz", http.StatusInternalServerError, `[+]ping ok
[-]wrapping-health failed: reason withheld [-]wrapping-health failed: reason withheld
[-]delegate-health failed: reason withheld [-]delegate-health failed: reason withheld
[+]poststarthook/generic-apiserver-start-informers ok
[+]poststarthook/delegate-post-start-hook ok [+]poststarthook/delegate-post-start-hook ok
[+]poststarthook/wrapping-post-start-hook ok [+]poststarthook/wrapping-post-start-hook ok
healthz check failed healthz check failed
......
...@@ -48,6 +48,8 @@ import ( ...@@ -48,6 +48,8 @@ import (
genericapirequest "k8s.io/apiserver/pkg/endpoints/request" genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
"k8s.io/apiserver/pkg/registry/rest" "k8s.io/apiserver/pkg/registry/rest"
etcdtesting "k8s.io/apiserver/pkg/storage/etcd/testing" etcdtesting "k8s.io/apiserver/pkg/storage/etcd/testing"
"k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes/fake"
restclient "k8s.io/client-go/rest" restclient "k8s.io/client-go/rest"
) )
...@@ -90,6 +92,12 @@ func setUp(t *testing.T) (*etcdtesting.EtcdTestServer, Config, *assert.Assertion ...@@ -90,6 +92,12 @@ func setUp(t *testing.T) (*etcdtesting.EtcdTestServer, Config, *assert.Assertion
config.LegacyAPIGroupPrefixes = sets.NewString("/api") config.LegacyAPIGroupPrefixes = sets.NewString("/api")
config.LoopbackClientConfig = &restclient.Config{} config.LoopbackClientConfig = &restclient.Config{}
clientset := fake.NewSimpleClientset()
if clientset == nil {
t.Fatal("unable to create fake client set")
}
config.SharedInformerFactory = informers.NewSharedInformerFactory(clientset, config.LoopbackClientConfig.Timeout)
// TODO restore this test, but right now, eliminate our cycle // TODO restore this test, but right now, eliminate our cycle
// config.OpenAPIConfig = DefaultOpenAPIConfig(testGetOpenAPIDefinitions, runtime.NewScheme()) // config.OpenAPIConfig = DefaultOpenAPIConfig(testGetOpenAPIDefinitions, runtime.NewScheme())
// config.OpenAPIConfig.Info = &spec.Info{ // config.OpenAPIConfig.Info = &spec.Info{
...@@ -300,17 +308,13 @@ func TestPrepareRun(t *testing.T) { ...@@ -300,17 +308,13 @@ func TestPrepareRun(t *testing.T) {
defer etcdserver.Terminate(t) defer etcdserver.Terminate(t)
assert.NotNil(config.SwaggerConfig) assert.NotNil(config.SwaggerConfig)
// assert.NotNil(config.OpenAPIConfig)
server := httptest.NewServer(s.Handler.GoRestfulContainer.ServeMux) server := httptest.NewServer(s.Handler.GoRestfulContainer.ServeMux)
defer server.Close() defer server.Close()
done := make(chan struct{})
s.PrepareRun() s.PrepareRun()
s.RunPostStartHooks(done)
// openapi is installed in PrepareRun
// resp, err := http.Get(server.URL + "/swagger.json")
// assert.NoError(err)
// assert.Equal(http.StatusOK, resp.StatusCode)
// swagger is installed in PrepareRun // swagger is installed in PrepareRun
resp, err := http.Get(server.URL + "/swaggerapi/") resp, err := http.Get(server.URL + "/swaggerapi/")
......
...@@ -106,6 +106,14 @@ func (s *GenericAPIServer) RunPostStartHooks(stopCh <-chan struct{}) { ...@@ -106,6 +106,14 @@ func (s *GenericAPIServer) RunPostStartHooks(stopCh <-chan struct{}) {
} }
} }
// isHookRegistered checks whether a given hook is registered
func (s *GenericAPIServer) isHookRegistered(name string) bool {
s.postStartHookLock.Lock()
defer s.postStartHookLock.Unlock()
_, exists := s.postStartHooks[name]
return exists
}
func runPostStartHook(name string, entry postStartHookEntry, context PostStartHookContext) { func runPostStartHook(name string, entry postStartHookEntry, context PostStartHookContext) {
var err error var err error
func() { func() {
...@@ -117,7 +125,6 @@ func runPostStartHook(name string, entry postStartHookEntry, context PostStartHo ...@@ -117,7 +125,6 @@ func runPostStartHook(name string, entry postStartHookEntry, context PostStartHo
if err != nil { if err != nil {
glog.Fatalf("PostStartHook %q failed: %v", name, err) glog.Fatalf("PostStartHook %q failed: %v", name, err)
} }
close(entry.done) close(entry.done)
} }
......
...@@ -17,33 +17,70 @@ limitations under the License. ...@@ -17,33 +17,70 @@ limitations under the License.
package options package options
import ( import (
"fmt"
"strings" "strings"
"github.com/spf13/pflag" "github.com/spf13/pflag"
"k8s.io/apiserver/pkg/admission" "k8s.io/apiserver/pkg/admission"
"k8s.io/apiserver/pkg/admission/initializer"
"k8s.io/apiserver/pkg/server"
"k8s.io/client-go/kubernetes"
) )
// AdmissionOptions holds the admission options // AdmissionOptions holds the admission options
type AdmissionOptions struct { type AdmissionOptions struct {
Control string PluginNames []string
ControlConfigFile string ConfigFile string
Plugins *admission.Plugins Plugins *admission.Plugins
} }
// NewAdmissionOptions creates a new instance of AdmissionOptions // NewAdmissionOptions creates a new instance of AdmissionOptions
func NewAdmissionOptions(plugins *admission.Plugins) *AdmissionOptions { func NewAdmissionOptions(plugins *admission.Plugins) *AdmissionOptions {
return &AdmissionOptions{ return &AdmissionOptions{
Plugins: plugins, Plugins: plugins,
Control: "AlwaysAdmit", PluginNames: []string{},
} }
} }
// AddFlags adds flags related to admission for a specific APIServer to the specified FlagSet // AddFlags adds flags related to admission for a specific APIServer to the specified FlagSet
func (a *AdmissionOptions) AddFlags(fs *pflag.FlagSet) { func (a *AdmissionOptions) AddFlags(fs *pflag.FlagSet) {
fs.StringVar(&a.Control, "admission-control", a.Control, ""+ fs.StringSliceVar(&a.PluginNames, "admission-control", a.PluginNames, ""+
"Ordered list of plug-ins to do admission control of resources into cluster. "+ "Ordered list of plug-ins to do admission control of resources into cluster. "+
"Comma-delimited list of: "+strings.Join(a.Plugins.Registered(), ", ")+".") "Comma-delimited list of: "+strings.Join(a.Plugins.Registered(), ", ")+".")
fs.StringVar(&a.ControlConfigFile, "admission-control-config-file", a.ControlConfigFile, fs.StringVar(&a.ConfigFile, "admission-control-config-file", a.ConfigFile,
"File with admission control configuration.") "File with admission control configuration.")
} }
// ApplyTo adds the admission chain to the server configuration
// the method lazily initializes a generic plugin that is appended to the list of pluginInitializers
// note this method uses:
// genericconfig.LoopbackClientConfig
// genericconfig.SharedInformerFactory
// genericconfig.Authorizer
func (a *AdmissionOptions) ApplyTo(serverCfg *server.Config, pluginInitializers ...admission.PluginInitializer) error {
pluginsConfigProvider, err := admission.ReadAdmissionConfiguration(a.PluginNames, a.ConfigFile)
if err != nil {
return fmt.Errorf("failed to read plugin config: %v", err)
}
clientset, err := kubernetes.NewForConfig(serverCfg.LoopbackClientConfig)
if err != nil {
return err
}
genericInitializer, err := initializer.New(clientset, serverCfg.SharedInformerFactory, serverCfg.Authorizer)
if err != nil {
return err
}
initializersChain := admission.PluginInitializers{}
pluginInitializers = append(pluginInitializers, genericInitializer)
initializersChain = append(initializersChain, pluginInitializers...)
admissionChain, err := a.Plugins.NewFromPlugins(a.PluginNames, pluginsConfigProvider, initializersChain)
if err != nil {
return err
}
serverCfg.AdmissionControl = admissionChain
return nil
}
...@@ -32,6 +32,8 @@ import ( ...@@ -32,6 +32,8 @@ import (
utilnet "k8s.io/apimachinery/pkg/util/net" utilnet "k8s.io/apimachinery/pkg/util/net"
"k8s.io/apiserver/pkg/server" "k8s.io/apiserver/pkg/server"
utilflag "k8s.io/apiserver/pkg/util/flag" utilflag "k8s.io/apiserver/pkg/util/flag"
"k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes"
certutil "k8s.io/client-go/util/cert" certutil "k8s.io/client-go/util/cert"
) )
...@@ -167,6 +169,13 @@ func (s *SecureServingOptions) ApplyTo(c *server.Config) error { ...@@ -167,6 +169,13 @@ func (s *SecureServingOptions) ApplyTo(c *server.Config) error {
c.SecureServingInfo.SNICerts[server.LoopbackClientServerNameOverride] = &tlsCert c.SecureServingInfo.SNICerts[server.LoopbackClientServerNameOverride] = &tlsCert
} }
// create shared informers
clientset, err := kubernetes.NewForConfig(c.LoopbackClientConfig)
if err != nil {
return err
}
c.SharedInformerFactory = informers.NewSharedInformerFactory(clientset, c.LoopbackClientConfig.Timeout)
return nil return nil
} }
......
...@@ -104,7 +104,6 @@ func startServer(t *testing.T, runOptions *options.ServerRunOptions, stopChan <- ...@@ -104,7 +104,6 @@ func startServer(t *testing.T, runOptions *options.ServerRunOptions, stopChan <-
} }
runOptions.InsecureServing.BindPort = port runOptions.InsecureServing.BindPort = port
err = app.NonBlockingRun(runOptions, stopChan) err = app.NonBlockingRun(runOptions, stopChan)
if err != nil { if err != nil {
t.Logf("Error starting the %s: %v", apiNoun, err) t.Logf("Error starting the %s: %v", apiNoun, err)
......
...@@ -47,6 +47,8 @@ import ( ...@@ -47,6 +47,8 @@ import (
"k8s.io/apiserver/pkg/server/options" "k8s.io/apiserver/pkg/server/options"
serverstorage "k8s.io/apiserver/pkg/server/storage" serverstorage "k8s.io/apiserver/pkg/server/storage"
"k8s.io/apiserver/pkg/storage/storagebackend" "k8s.io/apiserver/pkg/storage/storagebackend"
extinformers "k8s.io/client-go/informers"
extclient "k8s.io/client-go/kubernetes"
restclient "k8s.io/client-go/rest" restclient "k8s.io/client-go/rest"
"k8s.io/client-go/tools/record" "k8s.io/client-go/tools/record"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
...@@ -245,7 +247,13 @@ func startMasterOrDie(masterConfig *master.Config, incomingServer *httptest.Serv ...@@ -245,7 +247,13 @@ func startMasterOrDie(masterConfig *master.Config, incomingServer *httptest.Serv
masterConfig.GenericConfig.LoopbackClientConfig.BearerToken = privilegedLoopbackToken masterConfig.GenericConfig.LoopbackClientConfig.BearerToken = privilegedLoopbackToken
m, err := masterConfig.Complete().New(genericapiserver.EmptyDelegate) clientset, err := extclient.NewForConfig(masterConfig.GenericConfig.LoopbackClientConfig)
if err != nil {
glog.Fatal(err)
}
masterConfig.GenericConfig.SharedInformerFactory = extinformers.NewSharedInformerFactory(clientset, masterConfig.GenericConfig.LoopbackClientConfig.Timeout)
m, err = masterConfig.Complete().New(genericapiserver.EmptyDelegate)
if err != nil { if err != nil {
closeFn() closeFn()
glog.Fatalf("error in bringing up the master: %v", err) glog.Fatalf("error in bringing up the master: %v", err)
......
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