mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 19:56:01 +00:00
Merge pull request #51900 from sttts/sttts-informer-stratification
Automatic merge from submit-queue (batch tested with PRs 51900, 51782, 52030) apiservers: stratify versioned informer construction The versioned share informer factory has been part of the GenericApiServer config, but its construction depended on other fields of that config (e.g. the loopback client config). Hence, the order of changes to the config mattered. This PR stratifies this by moving the SharedInformerFactory from the generic Config to the CompleteConfig struct. Hence, it is only filled during completion when it is guaranteed that the loopback client config is set. While doing this, the CompletedConfig construction is made more type-safe again, i.e. the use of SkipCompletion() is considereably reduced. This is archieved by splitting the derived apiserver Configs into the GenericConfig and the ExtraConfig part. Then the completion is structural again because CompleteConfig is again of the same structure: generic CompletedConfig and local completed ExtraConfig. Fixes #50661.
This commit is contained in:
commit
63d6bdb58c
@ -76,12 +76,16 @@ func createAggregatorConfig(kubeAPIServerConfig genericapiserver.Config, command
|
||||
}
|
||||
|
||||
aggregatorConfig := &aggregatorapiserver.Config{
|
||||
GenericConfig: &genericConfig,
|
||||
CoreKubeInformers: externalInformers,
|
||||
ProxyClientCert: certBytes,
|
||||
ProxyClientKey: keyBytes,
|
||||
ServiceResolver: serviceResolver,
|
||||
ProxyTransport: proxyTransport,
|
||||
GenericConfig: &genericapiserver.RecommendedConfig{
|
||||
Config: genericConfig,
|
||||
SharedInformerFactory: externalInformers,
|
||||
},
|
||||
ExtraConfig: aggregatorapiserver.ExtraConfig{
|
||||
ProxyClientCert: certBytes,
|
||||
ProxyClientKey: keyBytes,
|
||||
ServiceResolver: serviceResolver,
|
||||
ProxyTransport: proxyTransport,
|
||||
},
|
||||
}
|
||||
|
||||
return aggregatorConfig, nil
|
||||
|
@ -25,10 +25,11 @@ import (
|
||||
apiextensionscmd "k8s.io/apiextensions-apiserver/pkg/cmd/server"
|
||||
genericapiserver "k8s.io/apiserver/pkg/server"
|
||||
genericoptions "k8s.io/apiserver/pkg/server/options"
|
||||
kubeexternalinformers "k8s.io/client-go/informers"
|
||||
"k8s.io/kubernetes/cmd/kube-apiserver/app/options"
|
||||
)
|
||||
|
||||
func createAPIExtensionsConfig(kubeAPIServerConfig genericapiserver.Config, commandOptions *options.ServerRunOptions) (*apiextensionsapiserver.Config, error) {
|
||||
func createAPIExtensionsConfig(kubeAPIServerConfig genericapiserver.Config, externalInformers kubeexternalinformers.SharedInformerFactory, commandOptions *options.ServerRunOptions) (*apiextensionsapiserver.Config, error) {
|
||||
// make a shallow copy to let us twiddle a few things
|
||||
// most of the config actually remains the same. We only need to mess with a couple items related to the particulars of the apiextensions
|
||||
genericConfig := kubeAPIServerConfig
|
||||
@ -40,12 +41,16 @@ func createAPIExtensionsConfig(kubeAPIServerConfig genericapiserver.Config, comm
|
||||
genericConfig.RESTOptionsGetter = &genericoptions.SimpleRestOptionsFactory{Options: etcdOptions}
|
||||
|
||||
apiextensionsConfig := &apiextensionsapiserver.Config{
|
||||
GenericConfig: &genericConfig,
|
||||
CRDRESTOptionsGetter: apiextensionscmd.NewCRDRESTOptionsGetter(etcdOptions),
|
||||
GenericConfig: &genericapiserver.RecommendedConfig{
|
||||
Config: genericConfig,
|
||||
SharedInformerFactory: externalInformers,
|
||||
},
|
||||
ExtraConfig: apiextensionsapiserver.ExtraConfig{
|
||||
CRDRESTOptionsGetter: apiextensionscmd.NewCRDRESTOptionsGetter(etcdOptions),
|
||||
},
|
||||
}
|
||||
|
||||
return apiextensionsConfig, nil
|
||||
|
||||
}
|
||||
|
||||
func createAPIExtensionsServer(apiextensionsConfig *apiextensionsapiserver.Config, delegateAPIServer genericapiserver.DelegationTarget) (*apiextensionsapiserver.CustomResourceDefinitions, error) {
|
||||
|
@ -133,7 +133,7 @@ func CreateServerChain(runOptions *options.ServerRunOptions, stopCh <-chan struc
|
||||
|
||||
// TPRs are enabled and not yet beta, since this these are the successor, they fall under the same enablement rule
|
||||
// If additional API servers are added, they should be gated.
|
||||
apiExtensionsConfig, err := createAPIExtensionsConfig(*kubeAPIServerConfig.GenericConfig, runOptions)
|
||||
apiExtensionsConfig, err := createAPIExtensionsConfig(*kubeAPIServerConfig.GenericConfig, versionedInformers, runOptions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -142,7 +142,7 @@ func CreateServerChain(runOptions *options.ServerRunOptions, stopCh <-chan struc
|
||||
return nil, err
|
||||
}
|
||||
|
||||
kubeAPIServer, err := CreateKubeAPIServer(kubeAPIServerConfig, apiExtensionsServer.GenericAPIServer, sharedInformers)
|
||||
kubeAPIServer, err := CreateKubeAPIServer(kubeAPIServerConfig, apiExtensionsServer.GenericAPIServer, sharedInformers, versionedInformers)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -172,8 +172,8 @@ func CreateServerChain(runOptions *options.ServerRunOptions, stopCh <-chan struc
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
aggregatorConfig.ProxyTransport = proxyTransport
|
||||
aggregatorConfig.ServiceResolver = serviceResolver
|
||||
aggregatorConfig.ExtraConfig.ProxyTransport = proxyTransport
|
||||
aggregatorConfig.ExtraConfig.ServiceResolver = serviceResolver
|
||||
aggregatorServer, err := createAggregatorServer(aggregatorConfig, kubeAPIServer.GenericAPIServer, apiExtensionsServer.Informers)
|
||||
if err != nil {
|
||||
// we don't need special handling for innerStopCh because the aggregator server doesn't create any go routines
|
||||
@ -191,8 +191,8 @@ func CreateServerChain(runOptions *options.ServerRunOptions, stopCh <-chan struc
|
||||
}
|
||||
|
||||
// CreateKubeAPIServer creates and wires a workable kube-apiserver
|
||||
func CreateKubeAPIServer(kubeAPIServerConfig *master.Config, delegateAPIServer genericapiserver.DelegationTarget, sharedInformers informers.SharedInformerFactory) (*master.Master, error) {
|
||||
kubeAPIServer, err := kubeAPIServerConfig.Complete().New(delegateAPIServer)
|
||||
func CreateKubeAPIServer(kubeAPIServerConfig *master.Config, delegateAPIServer genericapiserver.DelegationTarget, sharedInformers informers.SharedInformerFactory, versionedInformers clientgoinformers.SharedInformerFactory) (*master.Master, error) {
|
||||
kubeAPIServer, err := kubeAPIServerConfig.Complete(versionedInformers).New(delegateAPIServer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -312,40 +312,41 @@ func CreateKubeAPIServerConfig(s *options.ServerRunOptions, nodeTunneler tunnele
|
||||
|
||||
config := &master.Config{
|
||||
GenericConfig: genericConfig,
|
||||
ExtraConfig: master.ExtraConfig{
|
||||
ClientCARegistrationHook: master.ClientCARegistrationHook{
|
||||
ClientCA: clientCA,
|
||||
RequestHeaderUsernameHeaders: s.Authentication.RequestHeader.UsernameHeaders,
|
||||
RequestHeaderGroupHeaders: s.Authentication.RequestHeader.GroupHeaders,
|
||||
RequestHeaderExtraHeaderPrefixes: s.Authentication.RequestHeader.ExtraHeaderPrefixes,
|
||||
RequestHeaderCA: requestHeaderProxyCA,
|
||||
RequestHeaderAllowedNames: s.Authentication.RequestHeader.AllowedNames,
|
||||
},
|
||||
|
||||
ClientCARegistrationHook: master.ClientCARegistrationHook{
|
||||
ClientCA: clientCA,
|
||||
RequestHeaderUsernameHeaders: s.Authentication.RequestHeader.UsernameHeaders,
|
||||
RequestHeaderGroupHeaders: s.Authentication.RequestHeader.GroupHeaders,
|
||||
RequestHeaderExtraHeaderPrefixes: s.Authentication.RequestHeader.ExtraHeaderPrefixes,
|
||||
RequestHeaderCA: requestHeaderProxyCA,
|
||||
RequestHeaderAllowedNames: s.Authentication.RequestHeader.AllowedNames,
|
||||
APIResourceConfigSource: storageFactory.APIResourceConfigSource,
|
||||
StorageFactory: storageFactory,
|
||||
EnableCoreControllers: true,
|
||||
EventTTL: s.EventTTL,
|
||||
KubeletClientConfig: s.KubeletConfig,
|
||||
EnableUISupport: true,
|
||||
EnableLogsSupport: s.EnableLogsHandler,
|
||||
ProxyTransport: proxyTransport,
|
||||
|
||||
Tunneler: nodeTunneler,
|
||||
|
||||
ServiceIPRange: serviceIPRange,
|
||||
APIServerServiceIP: apiServerServiceIP,
|
||||
APIServerServicePort: 443,
|
||||
|
||||
ServiceNodePortRange: s.ServiceNodePortRange,
|
||||
KubernetesServiceNodePort: s.KubernetesServiceNodePort,
|
||||
|
||||
MasterCount: s.MasterCount,
|
||||
},
|
||||
|
||||
APIResourceConfigSource: storageFactory.APIResourceConfigSource,
|
||||
StorageFactory: storageFactory,
|
||||
EnableCoreControllers: true,
|
||||
EventTTL: s.EventTTL,
|
||||
KubeletClientConfig: s.KubeletConfig,
|
||||
EnableUISupport: true,
|
||||
EnableLogsSupport: s.EnableLogsHandler,
|
||||
ProxyTransport: proxyTransport,
|
||||
|
||||
Tunneler: nodeTunneler,
|
||||
|
||||
ServiceIPRange: serviceIPRange,
|
||||
APIServerServiceIP: apiServerServiceIP,
|
||||
APIServerServicePort: 443,
|
||||
|
||||
ServiceNodePortRange: s.ServiceNodePortRange,
|
||||
KubernetesServiceNodePort: s.KubernetesServiceNodePort,
|
||||
|
||||
MasterCount: s.MasterCount,
|
||||
}
|
||||
|
||||
if nodeTunneler != nil {
|
||||
// Use the nodeTunneler's dialer to connect to the kubelet
|
||||
config.KubeletClientConfig.Dial = nodeTunneler.Dial
|
||||
config.ExtraConfig.KubeletClientConfig.Dial = nodeTunneler.Dial
|
||||
}
|
||||
|
||||
return config, sharedInformers, versionedInformers, insecureServingOptions, serviceResolver, nil
|
||||
@ -465,6 +466,7 @@ func BuildGenericConfig(s *options.ServerRunOptions) (*genericapiserver.Config,
|
||||
|
||||
err = s.Admission.ApplyTo(
|
||||
genericConfig,
|
||||
versionedInformers,
|
||||
pluginInitializer)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, nil, fmt.Errorf("failed to initialize admission: %v", err)
|
||||
@ -616,8 +618,6 @@ func defaultOptions(s *options.ServerRunOptions) error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("error determining service IP ranges: %v", err)
|
||||
}
|
||||
s.SecureServing.ForceLoopbackConfigUsage()
|
||||
|
||||
if err := s.SecureServing.MaybeDefaultWithSelfSignedCerts(s.GenericServerRunOptions.AdvertiseAddress.String(), []string{"kubernetes.default.svc", "kubernetes.default", "kubernetes"}, []net.IP{apiServerServiceIP}); err != nil {
|
||||
return fmt.Errorf("error creating self-signed certificates: %v", err)
|
||||
}
|
||||
|
@ -80,6 +80,7 @@ go_library(
|
||||
"//vendor/k8s.io/apiserver/pkg/server:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/server/filters:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/server/storage:go_default_library",
|
||||
"//vendor/k8s.io/client-go/informers:go_default_library",
|
||||
"//vendor/k8s.io/client-go/kubernetes:go_default_library",
|
||||
"//vendor/k8s.io/kube-openapi/pkg/common:go_default_library",
|
||||
],
|
||||
|
@ -39,6 +39,8 @@ import (
|
||||
genericapiserver "k8s.io/apiserver/pkg/server"
|
||||
"k8s.io/apiserver/pkg/server/filters"
|
||||
serverstorage "k8s.io/apiserver/pkg/server/storage"
|
||||
clientgoinformers "k8s.io/client-go/informers"
|
||||
clientgoclientset "k8s.io/client-go/kubernetes"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
openapicommon "k8s.io/kube-openapi/pkg/common"
|
||||
federationv1beta1 "k8s.io/kubernetes/federation/apis/federation/v1beta1"
|
||||
@ -103,7 +105,6 @@ func NonBlockingRun(s *options.ServerRunOptions, stopCh <-chan struct{}) error {
|
||||
if err := s.CloudProvider.DefaultExternalHost(s.GenericServerRunOptions); err != nil {
|
||||
return fmt.Errorf("error setting the external host value: %v", err)
|
||||
}
|
||||
s.SecureServing.ForceLoopbackConfigUsage()
|
||||
|
||||
s.Authentication.ApplyAuthorization(s.Authorization)
|
||||
|
||||
@ -189,6 +190,12 @@ func NonBlockingRun(s *options.ServerRunOptions, stopCh <-chan struct{}) error {
|
||||
}
|
||||
sharedInformers := informers.NewSharedInformerFactory(client, 10*time.Minute)
|
||||
|
||||
clientgoExternalClient, err := clientgoclientset.NewForConfig(genericConfig.LoopbackClientConfig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create real external clientset: %v", err)
|
||||
}
|
||||
versionedInformers := clientgoinformers.NewSharedInformerFactory(clientgoExternalClient, 10*time.Minute)
|
||||
|
||||
authorizationConfig := s.Authorization.ToAuthorizationConfig(sharedInformers)
|
||||
apiAuthorizer, _, err := authorizationConfig.New()
|
||||
if err != nil {
|
||||
@ -210,6 +217,7 @@ func NonBlockingRun(s *options.ServerRunOptions, stopCh <-chan struct{}) error {
|
||||
|
||||
err = s.Admission.ApplyTo(
|
||||
genericConfig,
|
||||
versionedInformers,
|
||||
pluginInitializer,
|
||||
)
|
||||
if err != nil {
|
||||
@ -235,7 +243,7 @@ func NonBlockingRun(s *options.ServerRunOptions, stopCh <-chan struct{}) error {
|
||||
cachesize.SetWatchCacheSizes(s.GenericServerRunOptions.WatchCacheSizes)
|
||||
}
|
||||
|
||||
m, err := genericConfig.Complete().New("federation", genericapiserver.EmptyDelegate)
|
||||
m, err := genericConfig.Complete(versionedInformers).New("federation", genericapiserver.EmptyDelegate)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -94,6 +94,7 @@ go_library(
|
||||
"//vendor/k8s.io/apiserver/pkg/server:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/server/healthz:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/server/storage:go_default_library",
|
||||
"//vendor/k8s.io/client-go/informers:go_default_library",
|
||||
"//vendor/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library",
|
||||
],
|
||||
)
|
||||
|
@ -77,33 +77,33 @@ type Controller struct {
|
||||
}
|
||||
|
||||
// NewBootstrapController returns a controller for watching the core capabilities of the master
|
||||
func (c *Config) NewBootstrapController(legacyRESTStorage corerest.LegacyRESTStorage, serviceClient coreclient.ServicesGetter, nsClient coreclient.NamespacesGetter) *Controller {
|
||||
func (c *completedConfig) NewBootstrapController(legacyRESTStorage corerest.LegacyRESTStorage, serviceClient coreclient.ServicesGetter, nsClient coreclient.NamespacesGetter) *Controller {
|
||||
return &Controller{
|
||||
ServiceClient: serviceClient,
|
||||
NamespaceClient: nsClient,
|
||||
|
||||
EndpointReconciler: c.EndpointReconcilerConfig.Reconciler,
|
||||
EndpointInterval: c.EndpointReconcilerConfig.Interval,
|
||||
EndpointReconciler: c.ExtraConfig.EndpointReconcilerConfig.Reconciler,
|
||||
EndpointInterval: c.ExtraConfig.EndpointReconcilerConfig.Interval,
|
||||
|
||||
SystemNamespaces: []string{metav1.NamespaceSystem, metav1.NamespacePublic},
|
||||
SystemNamespacesInterval: 1 * time.Minute,
|
||||
|
||||
ServiceClusterIPRegistry: legacyRESTStorage.ServiceClusterIPAllocator,
|
||||
ServiceClusterIPRange: c.ServiceIPRange,
|
||||
ServiceClusterIPRange: c.ExtraConfig.ServiceIPRange,
|
||||
ServiceClusterIPInterval: 3 * time.Minute,
|
||||
|
||||
ServiceNodePortRegistry: legacyRESTStorage.ServiceNodePortAllocator,
|
||||
ServiceNodePortRange: c.ServiceNodePortRange,
|
||||
ServiceNodePortRange: c.ExtraConfig.ServiceNodePortRange,
|
||||
ServiceNodePortInterval: 3 * time.Minute,
|
||||
|
||||
PublicIP: c.GenericConfig.PublicAddress,
|
||||
|
||||
ServiceIP: c.APIServerServiceIP,
|
||||
ServicePort: c.APIServerServicePort,
|
||||
ExtraServicePorts: c.ExtraServicePorts,
|
||||
ExtraEndpointPorts: c.ExtraEndpointPorts,
|
||||
ServiceIP: c.ExtraConfig.APIServerServiceIP,
|
||||
ServicePort: c.ExtraConfig.APIServerServicePort,
|
||||
ExtraServicePorts: c.ExtraConfig.ExtraServicePorts,
|
||||
ExtraEndpointPorts: c.ExtraConfig.ExtraEndpointPorts,
|
||||
PublicServicePort: c.GenericConfig.ReadWritePort,
|
||||
KubernetesServiceNodePort: c.KubernetesServiceNodePort,
|
||||
KubernetesServiceNodePort: c.ExtraConfig.KubernetesServiceNodePort,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -62,6 +62,7 @@ import (
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
|
||||
// RESTStorage installers
|
||||
"k8s.io/client-go/informers"
|
||||
admissionregistrationrest "k8s.io/kubernetes/pkg/registry/admissionregistration/rest"
|
||||
appsrest "k8s.io/kubernetes/pkg/registry/apps/rest"
|
||||
authenticationrest "k8s.io/kubernetes/pkg/registry/authentication/rest"
|
||||
@ -85,9 +86,7 @@ const (
|
||||
DefaultEndpointReconcilerInterval = 10 * time.Second
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
GenericConfig *genericapiserver.Config
|
||||
|
||||
type ExtraConfig struct {
|
||||
ClientCARegistrationHook ClientCARegistrationHook
|
||||
|
||||
APIResourceConfigSource serverstorage.APIResourceConfigSource
|
||||
@ -135,6 +134,21 @@ type Config struct {
|
||||
MasterCount int
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
GenericConfig *genericapiserver.Config
|
||||
ExtraConfig ExtraConfig
|
||||
}
|
||||
|
||||
type completedConfig struct {
|
||||
GenericConfig genericapiserver.CompletedConfig
|
||||
ExtraConfig *ExtraConfig
|
||||
}
|
||||
|
||||
type CompletedConfig struct {
|
||||
// Embed a private pointer that cannot be instantiated outside of this package.
|
||||
*completedConfig
|
||||
}
|
||||
|
||||
// EndpointReconcilerConfig holds the endpoint reconciler and endpoint reconciliation interval to be
|
||||
// used by the master.
|
||||
type EndpointReconcilerConfig struct {
|
||||
@ -149,61 +163,55 @@ type Master struct {
|
||||
ClientCARegistrationHook ClientCARegistrationHook
|
||||
}
|
||||
|
||||
type completedConfig struct {
|
||||
*Config
|
||||
}
|
||||
|
||||
// Complete fills in any fields not set that are required to have valid data. It's mutating the receiver.
|
||||
func (c *Config) Complete() completedConfig {
|
||||
c.GenericConfig.Complete()
|
||||
func (cfg *Config) Complete(informers informers.SharedInformerFactory) CompletedConfig {
|
||||
c := completedConfig{
|
||||
cfg.GenericConfig.Complete(informers),
|
||||
&cfg.ExtraConfig,
|
||||
}
|
||||
|
||||
serviceIPRange, apiServerServiceIP, err := DefaultServiceIPRange(c.ServiceIPRange)
|
||||
serviceIPRange, apiServerServiceIP, err := DefaultServiceIPRange(c.ExtraConfig.ServiceIPRange)
|
||||
if err != nil {
|
||||
glog.Fatalf("Error determining service IP ranges: %v", err)
|
||||
}
|
||||
if c.ServiceIPRange.IP == nil {
|
||||
c.ServiceIPRange = serviceIPRange
|
||||
if c.ExtraConfig.ServiceIPRange.IP == nil {
|
||||
c.ExtraConfig.ServiceIPRange = serviceIPRange
|
||||
}
|
||||
if c.APIServerServiceIP == nil {
|
||||
c.APIServerServiceIP = apiServerServiceIP
|
||||
if c.ExtraConfig.APIServerServiceIP == nil {
|
||||
c.ExtraConfig.APIServerServiceIP = apiServerServiceIP
|
||||
}
|
||||
|
||||
discoveryAddresses := discovery.DefaultAddresses{DefaultAddress: c.GenericConfig.ExternalAddress}
|
||||
discoveryAddresses.CIDRRules = append(discoveryAddresses.CIDRRules,
|
||||
discovery.CIDRRule{IPRange: c.ServiceIPRange, Address: net.JoinHostPort(c.APIServerServiceIP.String(), strconv.Itoa(c.APIServerServicePort))})
|
||||
discovery.CIDRRule{IPRange: c.ExtraConfig.ServiceIPRange, Address: net.JoinHostPort(c.ExtraConfig.APIServerServiceIP.String(), strconv.Itoa(c.ExtraConfig.APIServerServicePort))})
|
||||
c.GenericConfig.DiscoveryAddresses = discoveryAddresses
|
||||
|
||||
if c.ServiceNodePortRange.Size == 0 {
|
||||
if c.ExtraConfig.ServiceNodePortRange.Size == 0 {
|
||||
// TODO: Currently no way to specify an empty range (do we need to allow this?)
|
||||
// We should probably allow this for clouds that don't require NodePort to do load-balancing (GCE)
|
||||
// but then that breaks the strict nestedness of ServiceType.
|
||||
// Review post-v1
|
||||
c.ServiceNodePortRange = options.DefaultServiceNodePortRange
|
||||
glog.Infof("Node port range unspecified. Defaulting to %v.", c.ServiceNodePortRange)
|
||||
c.ExtraConfig.ServiceNodePortRange = options.DefaultServiceNodePortRange
|
||||
glog.Infof("Node port range unspecified. Defaulting to %v.", c.ExtraConfig.ServiceNodePortRange)
|
||||
}
|
||||
|
||||
// enable swagger UI only if general UI support is on
|
||||
c.GenericConfig.EnableSwaggerUI = c.GenericConfig.EnableSwaggerUI && c.EnableUISupport
|
||||
c.GenericConfig.EnableSwaggerUI = c.GenericConfig.EnableSwaggerUI && c.ExtraConfig.EnableUISupport
|
||||
|
||||
if c.EndpointReconcilerConfig.Interval == 0 {
|
||||
c.EndpointReconcilerConfig.Interval = DefaultEndpointReconcilerInterval
|
||||
if c.ExtraConfig.EndpointReconcilerConfig.Interval == 0 {
|
||||
c.ExtraConfig.EndpointReconcilerConfig.Interval = DefaultEndpointReconcilerInterval
|
||||
}
|
||||
|
||||
if c.EndpointReconcilerConfig.Reconciler == nil {
|
||||
if c.ExtraConfig.EndpointReconcilerConfig.Reconciler == nil {
|
||||
// use a default endpoint reconciler if nothing is set
|
||||
endpointClient := coreclient.NewForConfigOrDie(c.GenericConfig.LoopbackClientConfig)
|
||||
c.EndpointReconcilerConfig.Reconciler = NewMasterCountEndpointReconciler(c.MasterCount, endpointClient)
|
||||
c.ExtraConfig.EndpointReconcilerConfig.Reconciler = NewMasterCountEndpointReconciler(c.ExtraConfig.MasterCount, endpointClient)
|
||||
}
|
||||
|
||||
// this has always been hardcoded true in the past
|
||||
c.GenericConfig.EnableMetrics = true
|
||||
|
||||
return completedConfig{c}
|
||||
}
|
||||
|
||||
// SkipComplete provides a way to construct a server instance without config completion.
|
||||
func (c *Config) SkipComplete() completedConfig {
|
||||
return completedConfig{c}
|
||||
return CompletedConfig{&c}
|
||||
}
|
||||
|
||||
// New returns a new instance of Master from the given config.
|
||||
@ -211,19 +219,19 @@ func (c *Config) SkipComplete() completedConfig {
|
||||
// Certain config fields must be specified, including:
|
||||
// KubeletClientConfig
|
||||
func (c completedConfig) New(delegationTarget genericapiserver.DelegationTarget) (*Master, error) {
|
||||
if reflect.DeepEqual(c.KubeletClientConfig, kubeletclient.KubeletClientConfig{}) {
|
||||
if reflect.DeepEqual(c.ExtraConfig.KubeletClientConfig, kubeletclient.KubeletClientConfig{}) {
|
||||
return nil, fmt.Errorf("Master.New() called with empty config.KubeletClientConfig")
|
||||
}
|
||||
|
||||
s, err := c.Config.GenericConfig.SkipComplete().New("kube-apiserver", delegationTarget) // completion is done in Complete, no need for a second time
|
||||
s, err := c.GenericConfig.New("kube-apiserver", delegationTarget)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if c.EnableUISupport {
|
||||
if c.ExtraConfig.EnableUISupport {
|
||||
routes.UIRedirect{}.Install(s.Handler.NonGoRestfulMux)
|
||||
}
|
||||
if c.EnableLogsSupport {
|
||||
if c.ExtraConfig.EnableLogsSupport {
|
||||
routes.Logs{}.Install(s.Handler.GoRestfulContainer)
|
||||
}
|
||||
|
||||
@ -232,17 +240,17 @@ func (c completedConfig) New(delegationTarget genericapiserver.DelegationTarget)
|
||||
}
|
||||
|
||||
// install legacy rest storage
|
||||
if c.APIResourceConfigSource.AnyResourcesForVersionEnabled(apiv1.SchemeGroupVersion) {
|
||||
if c.ExtraConfig.APIResourceConfigSource.AnyResourcesForVersionEnabled(apiv1.SchemeGroupVersion) {
|
||||
legacyRESTStorageProvider := corerest.LegacyRESTStorageProvider{
|
||||
StorageFactory: c.StorageFactory,
|
||||
ProxyTransport: c.ProxyTransport,
|
||||
KubeletClientConfig: c.KubeletClientConfig,
|
||||
EventTTL: c.EventTTL,
|
||||
ServiceIPRange: c.ServiceIPRange,
|
||||
ServiceNodePortRange: c.ServiceNodePortRange,
|
||||
StorageFactory: c.ExtraConfig.StorageFactory,
|
||||
ProxyTransport: c.ExtraConfig.ProxyTransport,
|
||||
KubeletClientConfig: c.ExtraConfig.KubeletClientConfig,
|
||||
EventTTL: c.ExtraConfig.EventTTL,
|
||||
ServiceIPRange: c.ExtraConfig.ServiceIPRange,
|
||||
ServiceNodePortRange: c.ExtraConfig.ServiceNodePortRange,
|
||||
LoopbackClientConfig: c.GenericConfig.LoopbackClientConfig,
|
||||
}
|
||||
m.InstallLegacyAPI(c.Config, c.Config.GenericConfig.RESTOptionsGetter, legacyRESTStorageProvider)
|
||||
m.InstallLegacyAPI(&c, c.GenericConfig.RESTOptionsGetter, legacyRESTStorageProvider)
|
||||
}
|
||||
|
||||
// The order here is preserved in discovery.
|
||||
@ -270,24 +278,24 @@ func (c completedConfig) New(delegationTarget genericapiserver.DelegationTarget)
|
||||
appsrest.RESTStorageProvider{},
|
||||
admissionregistrationrest.RESTStorageProvider{},
|
||||
}
|
||||
m.InstallAPIs(c.Config.APIResourceConfigSource, c.Config.GenericConfig.RESTOptionsGetter, restStorageProviders...)
|
||||
m.InstallAPIs(c.ExtraConfig.APIResourceConfigSource, c.GenericConfig.RESTOptionsGetter, restStorageProviders...)
|
||||
|
||||
if c.Tunneler != nil {
|
||||
m.installTunneler(c.Tunneler, corev1client.NewForConfigOrDie(c.GenericConfig.LoopbackClientConfig).Nodes())
|
||||
if c.ExtraConfig.Tunneler != nil {
|
||||
m.installTunneler(c.ExtraConfig.Tunneler, corev1client.NewForConfigOrDie(c.GenericConfig.LoopbackClientConfig).Nodes())
|
||||
}
|
||||
|
||||
m.GenericAPIServer.AddPostStartHookOrDie("ca-registration", c.ClientCARegistrationHook.PostStartHook)
|
||||
m.GenericAPIServer.AddPostStartHookOrDie("ca-registration", c.ExtraConfig.ClientCARegistrationHook.PostStartHook)
|
||||
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (m *Master) InstallLegacyAPI(c *Config, restOptionsGetter generic.RESTOptionsGetter, legacyRESTStorageProvider corerest.LegacyRESTStorageProvider) {
|
||||
func (m *Master) InstallLegacyAPI(c *completedConfig, restOptionsGetter generic.RESTOptionsGetter, legacyRESTStorageProvider corerest.LegacyRESTStorageProvider) {
|
||||
legacyRESTStorage, apiGroupInfo, err := legacyRESTStorageProvider.NewLegacyRESTStorage(restOptionsGetter)
|
||||
if err != nil {
|
||||
glog.Fatalf("Error building core storage: %v", err)
|
||||
}
|
||||
|
||||
if c.EnableCoreControllers {
|
||||
if c.ExtraConfig.EnableCoreControllers {
|
||||
coreClient := coreclient.NewForConfigOrDie(c.GenericConfig.LoopbackClientConfig)
|
||||
bootstrapController := c.NewBootstrapController(legacyRESTStorage, coreClient, coreClient)
|
||||
m.GenericAPIServer.AddPostStartHookOrDie("bootstrap-controller", bootstrapController.PostStartHook)
|
||||
|
@ -41,7 +41,7 @@ import (
|
||||
// TestValidOpenAPISpec verifies that the open api is added
|
||||
// at the proper endpoint and the spec is valid.
|
||||
func TestValidOpenAPISpec(t *testing.T) {
|
||||
etcdserver, config, assert := setUp(t)
|
||||
etcdserver, config, sharedInformers, assert := setUp(t)
|
||||
defer etcdserver.Terminate(t)
|
||||
|
||||
config.GenericConfig.EnableIndex = true
|
||||
@ -54,7 +54,7 @@ func TestValidOpenAPISpec(t *testing.T) {
|
||||
}
|
||||
config.GenericConfig.SwaggerConfig = genericapiserver.DefaultSwaggerConfig()
|
||||
|
||||
master, err := config.Complete().New(genericapiserver.EmptyDelegate)
|
||||
master, err := config.Complete(sharedInformers).New(genericapiserver.EmptyDelegate)
|
||||
if err != nil {
|
||||
t.Fatalf("Error in bringing up the master: %v", err)
|
||||
}
|
||||
|
@ -66,14 +66,16 @@ import (
|
||||
)
|
||||
|
||||
// setUp is a convience function for setting up for (most) tests.
|
||||
func setUp(t *testing.T) (*etcdtesting.EtcdTestServer, Config, *assert.Assertions) {
|
||||
func setUp(t *testing.T) (*etcdtesting.EtcdTestServer, Config, informers.SharedInformerFactory, *assert.Assertions) {
|
||||
server, storageConfig := etcdtesting.NewUnsecuredEtcd3TestClientServer(t, api.Scheme)
|
||||
|
||||
config := &Config{
|
||||
GenericConfig: genericapiserver.NewConfig(api.Codecs),
|
||||
APIResourceConfigSource: DefaultAPIResourceConfigSource(),
|
||||
APIServerServicePort: 443,
|
||||
MasterCount: 1,
|
||||
GenericConfig: genericapiserver.NewConfig(api.Codecs),
|
||||
ExtraConfig: ExtraConfig{
|
||||
APIResourceConfigSource: DefaultAPIResourceConfigSource(),
|
||||
APIServerServicePort: 443,
|
||||
MasterCount: 1,
|
||||
},
|
||||
}
|
||||
|
||||
resourceEncoding := serverstorage.NewDefaultResourceEncodingConfig(api.Registry)
|
||||
@ -95,16 +97,16 @@ func setUp(t *testing.T) (*etcdtesting.EtcdTestServer, Config, *assert.Assertion
|
||||
|
||||
kubeVersion := kubeversion.Get()
|
||||
config.GenericConfig.Version = &kubeVersion
|
||||
config.StorageFactory = storageFactory
|
||||
config.ExtraConfig.StorageFactory = storageFactory
|
||||
config.GenericConfig.LoopbackClientConfig = &restclient.Config{APIPath: "/api", ContentConfig: restclient.ContentConfig{NegotiatedSerializer: api.Codecs}}
|
||||
config.GenericConfig.PublicAddress = net.ParseIP("192.168.10.4")
|
||||
config.GenericConfig.LegacyAPIGroupPrefixes = sets.NewString("/api")
|
||||
config.GenericConfig.RequestContextMapper = genericapirequest.NewRequestContextMapper()
|
||||
config.GenericConfig.LoopbackClientConfig = &restclient.Config{APIPath: "/api", ContentConfig: restclient.ContentConfig{NegotiatedSerializer: api.Codecs}}
|
||||
config.GenericConfig.EnableMetrics = true
|
||||
config.EnableCoreControllers = false
|
||||
config.KubeletClientConfig = kubeletclient.KubeletClientConfig{Port: 10250}
|
||||
config.ProxyTransport = utilnet.SetTransportDefaults(&http.Transport{
|
||||
config.ExtraConfig.EnableCoreControllers = false
|
||||
config.ExtraConfig.KubeletClientConfig = kubeletclient.KubeletClientConfig{Port: 10250}
|
||||
config.ExtraConfig.ProxyTransport = utilnet.SetTransportDefaults(&http.Transport{
|
||||
Dial: func(network, addr string) (net.Conn, error) { return nil, nil },
|
||||
TLSClientConfig: &tls.Config{},
|
||||
})
|
||||
@ -113,9 +115,9 @@ func setUp(t *testing.T) (*etcdtesting.EtcdTestServer, Config, *assert.Assertion
|
||||
if err != nil {
|
||||
t.Fatalf("unable to create client set due to %v", err)
|
||||
}
|
||||
config.GenericConfig.SharedInformerFactory = informers.NewSharedInformerFactory(clientset, config.GenericConfig.LoopbackClientConfig.Timeout)
|
||||
sharedInformers := informers.NewSharedInformerFactory(clientset, config.GenericConfig.LoopbackClientConfig.Timeout)
|
||||
|
||||
return server, *config, assert.New(t)
|
||||
return server, *config, sharedInformers, assert.New(t)
|
||||
}
|
||||
|
||||
// TestLegacyRestStorageStrategies ensures that all Storage objects which are using the generic registry Store have
|
||||
@ -126,12 +128,12 @@ func TestLegacyRestStorageStrategies(t *testing.T) {
|
||||
defer etcdserver.Terminate(t)
|
||||
|
||||
storageProvider := corerest.LegacyRESTStorageProvider{
|
||||
StorageFactory: masterCfg.StorageFactory,
|
||||
ProxyTransport: masterCfg.ProxyTransport,
|
||||
KubeletClientConfig: masterCfg.KubeletClientConfig,
|
||||
EventTTL: masterCfg.EventTTL,
|
||||
ServiceIPRange: masterCfg.ServiceIPRange,
|
||||
ServiceNodePortRange: masterCfg.ServiceNodePortRange,
|
||||
StorageFactory: masterCfg.ExtraConfig.StorageFactory,
|
||||
ProxyTransport: masterCfg.ExtraConfig.ProxyTransport,
|
||||
KubeletClientConfig: masterCfg.ExtraConfig.KubeletClientConfig,
|
||||
EventTTL: masterCfg.ExtraConfig.EventTTL,
|
||||
ServiceIPRange: masterCfg.ExtraConfig.ServiceIPRange,
|
||||
ServiceNodePortRange: masterCfg.ExtraConfig.ServiceNodePortRange,
|
||||
LoopbackClientConfig: masterCfg.GenericConfig.LoopbackClientConfig,
|
||||
}
|
||||
|
||||
@ -162,7 +164,7 @@ func TestCertificatesRestStorageStrategies(t *testing.T) {
|
||||
defer etcdserver.Terminate(t)
|
||||
|
||||
certStorageProvider := certificatesrest.RESTStorageProvider{}
|
||||
apiGroupInfo, _ := certStorageProvider.NewRESTStorage(masterCfg.APIResourceConfigSource, masterCfg.GenericConfig.RESTOptionsGetter)
|
||||
apiGroupInfo, _ := certStorageProvider.NewRESTStorage(masterCfg.ExtraConfig.APIResourceConfigSource, masterCfg.GenericConfig.RESTOptionsGetter)
|
||||
|
||||
exceptions := registrytest.StrategyExceptions{
|
||||
HasExportStrategy: []string{
|
||||
@ -178,9 +180,9 @@ func TestCertificatesRestStorageStrategies(t *testing.T) {
|
||||
}
|
||||
|
||||
func newMaster(t *testing.T) (*Master, *etcdtesting.EtcdTestServer, Config, *assert.Assertions) {
|
||||
etcdserver, config, assert := setUp(t)
|
||||
etcdserver, config, sharedInformers, assert := setUp(t)
|
||||
|
||||
master, err := config.Complete().New(genericapiserver.EmptyDelegate)
|
||||
master, err := config.Complete(sharedInformers).New(genericapiserver.EmptyDelegate)
|
||||
if err != nil {
|
||||
t.Fatalf("Error in bringing up the master: %v", err)
|
||||
}
|
||||
@ -204,9 +206,9 @@ func limitedAPIResourceConfigSource() *serverstorage.ResourceConfig {
|
||||
|
||||
// newLimitedMaster only enables the core group, the extensions group, the batch group, and the autoscaling group.
|
||||
func newLimitedMaster(t *testing.T) (*Master, *etcdtesting.EtcdTestServer, Config, *assert.Assertions) {
|
||||
etcdserver, config, assert := setUp(t)
|
||||
config.APIResourceConfigSource = limitedAPIResourceConfigSource()
|
||||
master, err := config.Complete().New(genericapiserver.EmptyDelegate)
|
||||
etcdserver, config, sharedInformers, assert := setUp(t)
|
||||
config.ExtraConfig.APIResourceConfigSource = limitedAPIResourceConfigSource()
|
||||
master, err := config.Complete(sharedInformers).New(genericapiserver.EmptyDelegate)
|
||||
if err != nil {
|
||||
t.Fatalf("Error in bringing up the master: %v", err)
|
||||
}
|
||||
|
@ -78,12 +78,25 @@ func init() {
|
||||
Scheme.AddUnversionedTypes(unversionedVersion, unversionedTypes...)
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
GenericConfig *genericapiserver.Config
|
||||
|
||||
type ExtraConfig struct {
|
||||
CRDRESTOptionsGetter genericregistry.RESTOptionsGetter
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
GenericConfig *genericapiserver.RecommendedConfig
|
||||
ExtraConfig ExtraConfig
|
||||
}
|
||||
|
||||
type completedConfig struct {
|
||||
GenericConfig genericapiserver.CompletedConfig
|
||||
ExtraConfig *ExtraConfig
|
||||
}
|
||||
|
||||
type CompletedConfig struct {
|
||||
// Embed a private pointer that cannot be instantiated outside of this package.
|
||||
*completedConfig
|
||||
}
|
||||
|
||||
type CustomResourceDefinitions struct {
|
||||
GenericAPIServer *genericapiserver.GenericAPIServer
|
||||
|
||||
@ -91,31 +104,25 @@ type CustomResourceDefinitions struct {
|
||||
Informers internalinformers.SharedInformerFactory
|
||||
}
|
||||
|
||||
type completedConfig struct {
|
||||
*Config
|
||||
}
|
||||
|
||||
// Complete fills in any fields not set that are required to have valid data. It's mutating the receiver.
|
||||
func (c *Config) Complete() completedConfig {
|
||||
c.GenericConfig.EnableDiscovery = false
|
||||
c.GenericConfig.Complete()
|
||||
func (cfg *Config) Complete() CompletedConfig {
|
||||
c := completedConfig{
|
||||
cfg.GenericConfig.Complete(),
|
||||
&cfg.ExtraConfig,
|
||||
}
|
||||
|
||||
c.GenericConfig.EnableDiscovery = false
|
||||
c.GenericConfig.Version = &version.Info{
|
||||
Major: "0",
|
||||
Minor: "1",
|
||||
}
|
||||
|
||||
return completedConfig{c}
|
||||
}
|
||||
|
||||
// SkipComplete provides a way to construct a server instance without config completion.
|
||||
func (c *Config) SkipComplete() completedConfig {
|
||||
return completedConfig{c}
|
||||
return CompletedConfig{&c}
|
||||
}
|
||||
|
||||
// New returns a new instance of CustomResourceDefinitions from the given config.
|
||||
func (c completedConfig) New(delegationTarget genericapiserver.DelegationTarget) (*CustomResourceDefinitions, error) {
|
||||
genericServer, err := c.Config.GenericConfig.SkipComplete().New("apiextensions-apiserver", delegationTarget) // completion is done in Complete, no need for a second time
|
||||
genericServer, err := c.GenericConfig.New("apiextensions-apiserver", delegationTarget)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -173,7 +180,7 @@ func (c completedConfig) New(delegationTarget genericapiserver.DelegationTarget)
|
||||
s.Informers.Apiextensions().InternalVersion().CustomResourceDefinitions().Lister(),
|
||||
s.Informers.Apiextensions().InternalVersion().CustomResourceDefinitions(),
|
||||
delegateHandler,
|
||||
c.CRDRESTOptionsGetter,
|
||||
c.ExtraConfig.CRDRESTOptionsGetter,
|
||||
c.GenericConfig.AdmissionControl,
|
||||
)
|
||||
s.GenericAPIServer.Handler.NonGoRestfulMux.Handle("/apis", crdHandler)
|
||||
|
@ -49,6 +49,9 @@ func NewCustomResourceDefinitionsServerOptions(out, errOut io.Writer) *CustomRes
|
||||
StdErr: errOut,
|
||||
}
|
||||
|
||||
// the shared informer is not needed for kube-aggregator. Disable the kubeconfig flag and the client creation.
|
||||
o.RecommendedOptions.CoreAPI = nil
|
||||
|
||||
return o
|
||||
}
|
||||
|
||||
@ -94,14 +97,16 @@ func (o CustomResourceDefinitionsServerOptions) Config() (*apiserver.Config, err
|
||||
return nil, fmt.Errorf("error creating self-signed certificates: %v", err)
|
||||
}
|
||||
|
||||
serverConfig := genericapiserver.NewConfig(apiserver.Codecs)
|
||||
serverConfig := genericapiserver.NewRecommendedConfig(apiserver.Codecs)
|
||||
if err := o.RecommendedOptions.ApplyTo(serverConfig); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
config := &apiserver.Config{
|
||||
GenericConfig: serverConfig,
|
||||
CRDRESTOptionsGetter: NewCRDRESTOptionsGetter(*o.RecommendedOptions.Etcd),
|
||||
GenericConfig: serverConfig,
|
||||
ExtraConfig: apiserver.ExtraConfig{
|
||||
CRDRESTOptionsGetter: NewCRDRESTOptionsGetter(*o.RecommendedOptions.Etcd),
|
||||
},
|
||||
}
|
||||
return config, nil
|
||||
}
|
||||
|
@ -457,7 +457,7 @@ func TestEtcdStorage(t *testing.T) {
|
||||
}
|
||||
|
||||
func getPrefixFromConfig(t *testing.T, config *extensionsapiserver.Config) string {
|
||||
extensionsOptionsGetter, ok := config.CRDRESTOptionsGetter.(extensionsapiserver.CRDRESTOptionsGetter)
|
||||
extensionsOptionsGetter, ok := config.ExtraConfig.CRDRESTOptionsGetter.(extensionsapiserver.CRDRESTOptionsGetter)
|
||||
if !ok {
|
||||
t.Fatal("can't obtain etcd prefix: unable to cast config.CRDRESTOptionsGetter to extensionsapiserver.CRDRESTOptionsGetter")
|
||||
}
|
||||
|
@ -24,7 +24,6 @@ go_library(
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/watch:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/authorization/authorizerfactory:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/server:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/storage/names:go_default_library",
|
||||
"//vendor/k8s.io/client-go/dynamic:go_default_library",
|
||||
|
@ -30,7 +30,6 @@ import (
|
||||
"k8s.io/apiextensions-apiserver/pkg/cmd/server"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"k8s.io/apiserver/pkg/authorization/authorizerfactory"
|
||||
genericapiserver "k8s.io/apiserver/pkg/server"
|
||||
"k8s.io/client-go/dynamic"
|
||||
)
|
||||
@ -44,7 +43,8 @@ func DefaultServerConfig() (*extensionsapiserver.Config, error) {
|
||||
options := server.NewCustomResourceDefinitionsServerOptions(os.Stdout, os.Stderr)
|
||||
options.RecommendedOptions.Audit.LogOptions.Path = "-"
|
||||
options.RecommendedOptions.SecureServing.BindPort = port
|
||||
options.RecommendedOptions.Authentication.SkipInClusterLookup = true
|
||||
options.RecommendedOptions.Authentication = nil // disable
|
||||
options.RecommendedOptions.Authorization = nil // disable
|
||||
options.RecommendedOptions.SecureServing.BindAddress = net.ParseIP("127.0.0.1")
|
||||
etcdURL, ok := os.LookupEnv("KUBE_INTEGRATION_ETCD_URL")
|
||||
if !ok {
|
||||
@ -53,26 +53,12 @@ func DefaultServerConfig() (*extensionsapiserver.Config, error) {
|
||||
options.RecommendedOptions.Etcd.StorageConfig.ServerList = []string{etcdURL}
|
||||
options.RecommendedOptions.Etcd.StorageConfig.Prefix = uuid.New()
|
||||
|
||||
// TODO stop copying this
|
||||
// because there isn't currently a way to disable authentication or authorization from options
|
||||
// explode options.Config here
|
||||
genericConfig := genericapiserver.NewConfig(extensionsapiserver.Codecs)
|
||||
genericConfig.Authenticator = nil
|
||||
genericConfig.Authorizer = authorizerfactory.NewAlwaysAllowAuthorizer()
|
||||
genericConfig := genericapiserver.NewRecommendedConfig(extensionsapiserver.Codecs)
|
||||
|
||||
if err := options.RecommendedOptions.SecureServing.MaybeDefaultWithSelfSignedCerts("localhost", nil, []net.IP{net.ParseIP("127.0.0.1")}); err != nil {
|
||||
return nil, fmt.Errorf("error creating self-signed certificates: %v", err)
|
||||
}
|
||||
if err := options.RecommendedOptions.Etcd.ApplyTo(genericConfig); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := options.RecommendedOptions.SecureServing.ApplyTo(genericConfig); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := options.RecommendedOptions.Audit.ApplyTo(genericConfig); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := options.RecommendedOptions.Features.ApplyTo(genericConfig); err != nil {
|
||||
if err := options.RecommendedOptions.ApplyTo(genericConfig); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@ -88,8 +74,10 @@ func DefaultServerConfig() (*extensionsapiserver.Config, error) {
|
||||
customResourceDefinitionRESTOptionsGetter.StorageConfig.Copier = extensionsapiserver.UnstructuredCopier{}
|
||||
|
||||
config := &extensionsapiserver.Config{
|
||||
GenericConfig: genericConfig,
|
||||
CRDRESTOptionsGetter: customResourceDefinitionRESTOptionsGetter,
|
||||
GenericConfig: genericConfig,
|
||||
ExtraConfig: extensionsapiserver.ExtraConfig{
|
||||
CRDRESTOptionsGetter: customResourceDefinitionRESTOptionsGetter,
|
||||
},
|
||||
}
|
||||
|
||||
return config, nil
|
||||
|
@ -62,6 +62,7 @@ import (
|
||||
certutil "k8s.io/client-go/util/cert"
|
||||
openapicommon "k8s.io/kube-openapi/pkg/common"
|
||||
|
||||
// install apis
|
||||
_ "k8s.io/apiserver/pkg/apis/apiserver/install"
|
||||
)
|
||||
|
||||
@ -121,8 +122,6 @@ type Config struct {
|
||||
// Will default to a value based on secure serving info and available ipv4 IPs.
|
||||
ExternalAddress string
|
||||
|
||||
// SharedInformerFactory provides shared informers for resources
|
||||
SharedInformerFactory informers.SharedInformerFactory
|
||||
//===========================================================================
|
||||
// Fields you probably don't care about changing
|
||||
//===========================================================================
|
||||
@ -186,6 +185,15 @@ type Config struct {
|
||||
PublicAddress net.IP
|
||||
}
|
||||
|
||||
type RecommendedConfig struct {
|
||||
Config
|
||||
|
||||
// SharedInformerFactory provides shared informers for Kubernetes resources. This value is set by
|
||||
// RecommendedOptions.CoreAPI.ApplyTo called by RecommendedOptions.ApplyTo. It uses an in-cluster client config
|
||||
// by default, or the kubeconfig given with kubeconfig command line flag.
|
||||
SharedInformerFactory informers.SharedInformerFactory
|
||||
}
|
||||
|
||||
type SecureServingInfo struct {
|
||||
// BindAddress is the ip:port to serve on
|
||||
BindAddress string
|
||||
@ -241,6 +249,13 @@ func NewConfig(codecs serializer.CodecFactory) *Config {
|
||||
}
|
||||
}
|
||||
|
||||
// NewRecommendedConfig returns a RecommendedConfig struct with the default values
|
||||
func NewRecommendedConfig(codecs serializer.CodecFactory) *RecommendedConfig {
|
||||
return &RecommendedConfig{
|
||||
Config: *NewConfig(codecs),
|
||||
}
|
||||
}
|
||||
|
||||
func DefaultOpenAPIConfig(getDefinitions openapicommon.GetOpenAPIDefinitions, scheme *runtime.Scheme) *openapicommon.Config {
|
||||
defNamer := apiopenapi.NewDefinitionNamer(scheme)
|
||||
return &openapicommon.Config{
|
||||
@ -300,11 +315,23 @@ func (c *Config) ApplyClientCert(clientCAFile string) (*Config, error) {
|
||||
|
||||
type completedConfig struct {
|
||||
*Config
|
||||
|
||||
//===========================================================================
|
||||
// values below here are filled in during completion
|
||||
//===========================================================================
|
||||
|
||||
// SharedInformerFactory provides shared informers for resources
|
||||
SharedInformerFactory informers.SharedInformerFactory
|
||||
}
|
||||
|
||||
type CompletedConfig struct {
|
||||
// Embed a private pointer that cannot be instantiated outside of this package.
|
||||
*completedConfig
|
||||
}
|
||||
|
||||
// Complete fills in any fields not set that are required to have valid data and can be derived
|
||||
// from other fields. If you're going to `ApplyOptions`, do that first. It's mutating the receiver.
|
||||
func (c *Config) Complete() completedConfig {
|
||||
func (c *Config) Complete(informers informers.SharedInformerFactory) CompletedConfig {
|
||||
if len(c.ExternalAddress) == 0 && c.PublicAddress != nil {
|
||||
hostAndPort := c.PublicAddress.String()
|
||||
if c.ReadWritePort != 0 {
|
||||
@ -379,12 +406,13 @@ func (c *Config) Complete() completedConfig {
|
||||
c.RequestInfoResolver = NewRequestInfoResolver(c)
|
||||
}
|
||||
|
||||
return completedConfig{c}
|
||||
return CompletedConfig{&completedConfig{c, informers}}
|
||||
}
|
||||
|
||||
// SkipComplete provides a way to construct a server instance without config completion.
|
||||
func (c *Config) SkipComplete() completedConfig {
|
||||
return completedConfig{c}
|
||||
// Complete fills in any fields not set that are required to have valid data and can be derived
|
||||
// from other fields. If you're going to `ApplyOptions`, do that first. It's mutating the receiver.
|
||||
func (c *RecommendedConfig) Complete() CompletedConfig {
|
||||
return c.Config.Complete(c.SharedInformerFactory)
|
||||
}
|
||||
|
||||
// New creates a new server which logically combines the handling chain with the passed server.
|
||||
|
@ -44,7 +44,6 @@ func TestNewWithDelegate(t *testing.T) {
|
||||
if clientset == nil {
|
||||
t.Fatal("unable to create fake client set")
|
||||
}
|
||||
delegateConfig.SharedInformerFactory = informers.NewSharedInformerFactory(clientset, delegateConfig.LoopbackClientConfig.Timeout)
|
||||
|
||||
delegateHealthzCalled := false
|
||||
delegateConfig.HealthzChecks = append(delegateConfig.HealthzChecks, healthz.NamedCheck("delegate-health", func(r *http.Request) error {
|
||||
@ -52,7 +51,8 @@ func TestNewWithDelegate(t *testing.T) {
|
||||
return fmt.Errorf("delegate failed healthcheck")
|
||||
}))
|
||||
|
||||
delegateServer, err := delegateConfig.SkipComplete().New("test", EmptyDelegate)
|
||||
sharedInformers := informers.NewSharedInformerFactory(clientset, delegateConfig.LoopbackClientConfig.Timeout)
|
||||
delegateServer, err := delegateConfig.Complete(sharedInformers).New("test", EmptyDelegate)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -73,7 +73,6 @@ func TestNewWithDelegate(t *testing.T) {
|
||||
wrappingConfig.LegacyAPIGroupPrefixes = sets.NewString("/api")
|
||||
wrappingConfig.LoopbackClientConfig = &rest.Config{}
|
||||
wrappingConfig.SwaggerConfig = DefaultSwaggerConfig()
|
||||
wrappingConfig.SharedInformerFactory = informers.NewSharedInformerFactory(clientset, wrappingConfig.LoopbackClientConfig.Timeout)
|
||||
|
||||
wrappingHealthzCalled := false
|
||||
wrappingConfig.HealthzChecks = append(wrappingConfig.HealthzChecks, healthz.NamedCheck("wrapping-health", func(r *http.Request) error {
|
||||
@ -81,7 +80,8 @@ func TestNewWithDelegate(t *testing.T) {
|
||||
return fmt.Errorf("wrapping failed healthcheck")
|
||||
}))
|
||||
|
||||
wrappingServer, err := wrappingConfig.Complete().New("test", delegateServer)
|
||||
sharedInformers = informers.NewSharedInformerFactory(clientset, wrappingConfig.LoopbackClientConfig.Timeout)
|
||||
wrappingServer, err := wrappingConfig.Complete(sharedInformers).New("test", delegateServer)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -96,7 +96,6 @@ func setUp(t *testing.T) (*etcdtesting.EtcdTestServer, Config, *assert.Assertion
|
||||
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
|
||||
// config.OpenAPIConfig = DefaultOpenAPIConfig(testGetOpenAPIDefinitions, runtime.NewScheme())
|
||||
@ -107,7 +106,8 @@ func setUp(t *testing.T) (*etcdtesting.EtcdTestServer, Config, *assert.Assertion
|
||||
// },
|
||||
// }
|
||||
config.SwaggerConfig = DefaultSwaggerConfig()
|
||||
config.Complete()
|
||||
sharedInformers := informers.NewSharedInformerFactory(clientset, config.LoopbackClientConfig.Timeout)
|
||||
config.Complete(sharedInformers)
|
||||
|
||||
return etcdServer, *config, assert.New(t)
|
||||
}
|
||||
@ -115,7 +115,7 @@ func setUp(t *testing.T) (*etcdtesting.EtcdTestServer, Config, *assert.Assertion
|
||||
func newMaster(t *testing.T) (*GenericAPIServer, *etcdtesting.EtcdTestServer, Config, *assert.Assertions) {
|
||||
etcdserver, config, assert := setUp(t)
|
||||
|
||||
s, err := config.Complete().New("test", EmptyDelegate)
|
||||
s, err := config.Complete(nil).New("test", EmptyDelegate)
|
||||
if err != nil {
|
||||
t.Fatalf("Error in bringing up the server: %v", err)
|
||||
}
|
||||
@ -147,7 +147,7 @@ func TestInstallAPIGroups(t *testing.T) {
|
||||
config.LegacyAPIGroupPrefixes = sets.NewString("/apiPrefix")
|
||||
config.DiscoveryAddresses = discovery.DefaultAddresses{DefaultAddress: "ExternalAddress"}
|
||||
|
||||
s, err := config.SkipComplete().New("test", EmptyDelegate)
|
||||
s, err := config.Complete(nil).New("test", EmptyDelegate)
|
||||
if err != nil {
|
||||
t.Fatalf("Error in bringing up the server: %v", err)
|
||||
}
|
||||
@ -351,7 +351,7 @@ func TestCustomHandlerChain(t *testing.T) {
|
||||
called = true
|
||||
})
|
||||
|
||||
s, err := config.SkipComplete().New("test", EmptyDelegate)
|
||||
s, err := config.Complete(nil).New("test", EmptyDelegate)
|
||||
if err != nil {
|
||||
t.Fatalf("Error in bringing up the server: %v", err)
|
||||
}
|
||||
@ -406,7 +406,7 @@ func TestNotRestRoutesHaveAuth(t *testing.T) {
|
||||
kubeVersion := fakeVersion()
|
||||
config.Version = &kubeVersion
|
||||
|
||||
s, err := config.SkipComplete().New("test", EmptyDelegate)
|
||||
s, err := config.Complete(nil).New("test", EmptyDelegate)
|
||||
if err != nil {
|
||||
t.Fatalf("Error in bringing up the server: %v", err)
|
||||
}
|
||||
|
@ -31,6 +31,7 @@ go_library(
|
||||
"audit.go",
|
||||
"authentication.go",
|
||||
"authorization.go",
|
||||
"coreapi.go",
|
||||
"doc.go",
|
||||
"etcd.go",
|
||||
"feature.go",
|
||||
|
@ -24,6 +24,7 @@ import (
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
"k8s.io/apiserver/pkg/admission/initializer"
|
||||
"k8s.io/apiserver/pkg/server"
|
||||
"k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
)
|
||||
|
||||
@ -63,17 +64,17 @@ func (a *AdmissionOptions) AddFlags(fs *pflag.FlagSet) {
|
||||
// genericconfig.LoopbackClientConfig
|
||||
// genericconfig.SharedInformerFactory
|
||||
// genericconfig.Authorizer
|
||||
func (a *AdmissionOptions) ApplyTo(serverCfg *server.Config, pluginInitializers ...admission.PluginInitializer) error {
|
||||
func (a *AdmissionOptions) ApplyTo(c *server.Config, informers informers.SharedInformerFactory, 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)
|
||||
clientset, err := kubernetes.NewForConfig(c.LoopbackClientConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
genericInitializer, err := initializer.New(clientset, serverCfg.SharedInformerFactory, serverCfg.Authorizer)
|
||||
genericInitializer, err := initializer.New(clientset, informers, c.Authorizer)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -86,7 +87,7 @@ func (a *AdmissionOptions) ApplyTo(serverCfg *server.Config, pluginInitializers
|
||||
return err
|
||||
}
|
||||
|
||||
serverCfg.AdmissionControl = admissionChain
|
||||
c.AdmissionControl = admissionChain
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -88,6 +88,10 @@ func NewAuditOptions() *AuditOptions {
|
||||
|
||||
// Validate checks invalid config combination
|
||||
func (o *AuditOptions) Validate() []error {
|
||||
if o == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
allErrors := []error{}
|
||||
|
||||
if !advancedAuditingEnabled() {
|
||||
@ -138,6 +142,10 @@ func (o *AuditOptions) Validate() []error {
|
||||
}
|
||||
|
||||
func (o *AuditOptions) AddFlags(fs *pflag.FlagSet) {
|
||||
if o == nil {
|
||||
return
|
||||
}
|
||||
|
||||
fs.StringVar(&o.PolicyFile, "audit-policy-file", o.PolicyFile,
|
||||
"Path to the file that defines the audit policy configuration. Requires the 'AdvancedAuditing' feature gate."+
|
||||
" With AdvancedAuditing, a profile is required to enable auditing.")
|
||||
@ -147,6 +155,10 @@ func (o *AuditOptions) AddFlags(fs *pflag.FlagSet) {
|
||||
}
|
||||
|
||||
func (o *AuditOptions) ApplyTo(c *server.Config) error {
|
||||
if o == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Apply legacy audit options if advanced audit is not enabled.
|
||||
if !advancedAuditingEnabled() {
|
||||
return o.LogOptions.legacyApplyTo(c)
|
||||
|
@ -43,6 +43,10 @@ type RequestHeaderAuthenticationOptions struct {
|
||||
}
|
||||
|
||||
func (s *RequestHeaderAuthenticationOptions) AddFlags(fs *pflag.FlagSet) {
|
||||
if s == nil {
|
||||
return
|
||||
}
|
||||
|
||||
fs.StringSliceVar(&s.UsernameHeaders, "requestheader-username-headers", s.UsernameHeaders, ""+
|
||||
"List of request headers to inspect for usernames. X-Remote-User is common.")
|
||||
|
||||
@ -143,6 +147,11 @@ func (s *DelegatingAuthenticationOptions) AddFlags(fs *pflag.FlagSet) {
|
||||
}
|
||||
|
||||
func (s *DelegatingAuthenticationOptions) ApplyTo(c *server.Config) error {
|
||||
if s == nil {
|
||||
c.Authenticator = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
clientCA, err := s.getClientCA()
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -57,6 +57,10 @@ func (s *DelegatingAuthorizationOptions) Validate() []error {
|
||||
}
|
||||
|
||||
func (s *DelegatingAuthorizationOptions) AddFlags(fs *pflag.FlagSet) {
|
||||
if s == nil {
|
||||
return
|
||||
}
|
||||
|
||||
fs.StringVar(&s.RemoteKubeConfigFile, "authorization-kubeconfig", s.RemoteKubeConfigFile, ""+
|
||||
"kubeconfig file pointing at the 'core' kubernetes server with enough rights to create "+
|
||||
" subjectaccessreviews.authorization.k8s.io.")
|
||||
@ -71,6 +75,11 @@ func (s *DelegatingAuthorizationOptions) AddFlags(fs *pflag.FlagSet) {
|
||||
}
|
||||
|
||||
func (s *DelegatingAuthorizationOptions) ApplyTo(c *server.Config) error {
|
||||
if s == nil {
|
||||
c.Authorizer = authorizerfactory.NewAlwaysAllowAuthorizer()
|
||||
return nil
|
||||
}
|
||||
|
||||
cfg, err := s.ToAuthorizationConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
|
83
staging/src/k8s.io/apiserver/pkg/server/options/coreapi.go
Normal file
83
staging/src/k8s.io/apiserver/pkg/server/options/coreapi.go
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
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 options
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
"k8s.io/apiserver/pkg/server"
|
||||
clientgoinformers "k8s.io/client-go/informers"
|
||||
clientgoclientset "k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
)
|
||||
|
||||
// CoreAPIOptions contains options to configure the connection to a core API Kubernetes apiserver.
|
||||
type CoreAPIOptions struct {
|
||||
// CoreAPIKubeconfigPath is a filename for a kubeconfig file to contact the core API server with.
|
||||
// If it is not set, the in cluster config is used.
|
||||
CoreAPIKubeconfigPath string
|
||||
}
|
||||
|
||||
func NewCoreAPIOptions() *CoreAPIOptions {
|
||||
return &CoreAPIOptions{}
|
||||
}
|
||||
|
||||
func (o *CoreAPIOptions) AddFlags(fs *pflag.FlagSet) {
|
||||
if o == nil {
|
||||
return
|
||||
}
|
||||
|
||||
fs.StringVar(&o.CoreAPIKubeconfigPath, "kubeconfig", o.CoreAPIKubeconfigPath,
|
||||
"kubeconfig file pointing at the 'core' kubernetes server.")
|
||||
}
|
||||
|
||||
func (o *CoreAPIOptions) ApplyTo(config *server.RecommendedConfig) error {
|
||||
if o == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// create shared informer for Kubernetes APIs
|
||||
var kubeconfig *rest.Config
|
||||
var err error
|
||||
if len(o.CoreAPIKubeconfigPath) > 0 {
|
||||
loadingRules := &clientcmd.ClientConfigLoadingRules{ExplicitPath: o.CoreAPIKubeconfigPath}
|
||||
loader := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingRules, &clientcmd.ConfigOverrides{})
|
||||
kubeconfig, err = loader.ClientConfig()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to load kubeconfig at %q: %v", o.CoreAPIKubeconfigPath, err)
|
||||
}
|
||||
} else {
|
||||
kubeconfig, err = rest.InClusterConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
clientgoExternalClient, err := clientgoclientset.NewForConfig(kubeconfig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create Kubernetes clientset: %v", err)
|
||||
}
|
||||
config.SharedInformerFactory = clientgoinformers.NewSharedInformerFactory(clientgoExternalClient, 10*time.Minute)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *CoreAPIOptions) Validate() []error {
|
||||
return nil
|
||||
}
|
@ -71,6 +71,10 @@ func NewEtcdOptions(backendConfig *storagebackend.Config) *EtcdOptions {
|
||||
}
|
||||
|
||||
func (s *EtcdOptions) Validate() []error {
|
||||
if s == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
allErrors := []error{}
|
||||
if len(s.StorageConfig.ServerList) == 0 {
|
||||
allErrors = append(allErrors, fmt.Errorf("--etcd-servers must be specified"))
|
||||
@ -85,6 +89,10 @@ func (s *EtcdOptions) Validate() []error {
|
||||
|
||||
// AddEtcdFlags adds flags related to etcd storage for a specific APIServer to the specified FlagSet
|
||||
func (s *EtcdOptions) AddFlags(fs *pflag.FlagSet) {
|
||||
if s == nil {
|
||||
return
|
||||
}
|
||||
|
||||
fs.StringSliceVar(&s.EtcdServersOverrides, "etcd-servers-overrides", s.EtcdServersOverrides, ""+
|
||||
"Per-resource etcd servers overrides, comma separated. The individual override "+
|
||||
"format: group/resource#servers, where servers are http://ip:port, semicolon separated.")
|
||||
@ -132,6 +140,10 @@ func (s *EtcdOptions) AddFlags(fs *pflag.FlagSet) {
|
||||
}
|
||||
|
||||
func (s *EtcdOptions) ApplyTo(c *server.Config) error {
|
||||
if s == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
s.addEtcdHealthEndpoint(c)
|
||||
c.RESTOptionsGetter = &SimpleRestOptionsFactory{Options: *s}
|
||||
return nil
|
||||
|
@ -40,6 +40,10 @@ func NewFeatureOptions() *FeatureOptions {
|
||||
}
|
||||
|
||||
func (o *FeatureOptions) AddFlags(fs *pflag.FlagSet) {
|
||||
if o == nil {
|
||||
return
|
||||
}
|
||||
|
||||
fs.BoolVar(&o.EnableProfiling, "profiling", o.EnableProfiling,
|
||||
"Enable profiling via web interface host:port/debug/pprof/")
|
||||
fs.BoolVar(&o.EnableContentionProfiling, "contention-profiling", o.EnableContentionProfiling,
|
||||
@ -49,6 +53,10 @@ func (o *FeatureOptions) AddFlags(fs *pflag.FlagSet) {
|
||||
}
|
||||
|
||||
func (o *FeatureOptions) ApplyTo(c *server.Config) error {
|
||||
if o == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
c.EnableProfiling = o.EnableProfiling
|
||||
c.EnableContentionProfiling = o.EnableContentionProfiling
|
||||
c.EnableSwaggerUI = o.EnableSwaggerUI
|
||||
@ -57,6 +65,10 @@ func (o *FeatureOptions) ApplyTo(c *server.Config) error {
|
||||
}
|
||||
|
||||
func (o *FeatureOptions) Validate() []error {
|
||||
if o == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
errs := []error{}
|
||||
return errs
|
||||
}
|
||||
|
@ -24,8 +24,9 @@ import (
|
||||
"k8s.io/apiserver/pkg/storage/storagebackend"
|
||||
)
|
||||
|
||||
// RecommendedOptions contains the recommended options for running an API server
|
||||
// If you add something to this list, it should be in a logical grouping
|
||||
// RecommendedOptions contains the recommended options for running an API server.
|
||||
// If you add something to this list, it should be in a logical grouping.
|
||||
// Each of them can be nil to leave the feature unconfigured on ApplyTo.
|
||||
type RecommendedOptions struct {
|
||||
Etcd *EtcdOptions
|
||||
SecureServing *SecureServingOptions
|
||||
@ -33,6 +34,7 @@ type RecommendedOptions struct {
|
||||
Authorization *DelegatingAuthorizationOptions
|
||||
Audit *AuditOptions
|
||||
Features *FeatureOptions
|
||||
CoreAPI *CoreAPIOptions
|
||||
}
|
||||
|
||||
func NewRecommendedOptions(prefix string, copier runtime.ObjectCopier, codec runtime.Codec) *RecommendedOptions {
|
||||
@ -43,6 +45,7 @@ func NewRecommendedOptions(prefix string, copier runtime.ObjectCopier, codec run
|
||||
Authorization: NewDelegatingAuthorizationOptions(),
|
||||
Audit: NewAuditOptions(),
|
||||
Features: NewFeatureOptions(),
|
||||
CoreAPI: NewCoreAPIOptions(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -53,28 +56,31 @@ func (o *RecommendedOptions) AddFlags(fs *pflag.FlagSet) {
|
||||
o.Authorization.AddFlags(fs)
|
||||
o.Audit.AddFlags(fs)
|
||||
o.Features.AddFlags(fs)
|
||||
o.CoreAPI.AddFlags(fs)
|
||||
}
|
||||
|
||||
func (o *RecommendedOptions) ApplyTo(config *server.Config) error {
|
||||
if err := o.Etcd.ApplyTo(config); err != nil {
|
||||
func (o *RecommendedOptions) ApplyTo(config *server.RecommendedConfig) error {
|
||||
if err := o.Etcd.ApplyTo(&config.Config); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := o.SecureServing.ApplyTo(config); err != nil {
|
||||
if err := o.SecureServing.ApplyTo(&config.Config); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := o.Authentication.ApplyTo(config); err != nil {
|
||||
if err := o.Authentication.ApplyTo(&config.Config); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := o.Authorization.ApplyTo(config); err != nil {
|
||||
if err := o.Authorization.ApplyTo(&config.Config); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := o.Audit.ApplyTo(config); err != nil {
|
||||
if err := o.Audit.ApplyTo(&config.Config); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := o.Features.ApplyTo(config); err != nil {
|
||||
if err := o.Features.ApplyTo(&config.Config); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := o.CoreAPI.ApplyTo(config); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -86,6 +92,7 @@ func (o *RecommendedOptions) Validate() []error {
|
||||
errors = append(errors, o.Authorization.Validate()...)
|
||||
errors = append(errors, o.Audit.Validate()...)
|
||||
errors = append(errors, o.Features.Validate()...)
|
||||
errors = append(errors, o.CoreAPI.Validate()...)
|
||||
|
||||
return errors
|
||||
}
|
||||
|
@ -24,7 +24,6 @@ import (
|
||||
"net"
|
||||
"path"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/pborman/uuid"
|
||||
@ -33,9 +32,6 @@ import (
|
||||
utilnet "k8s.io/apimachinery/pkg/util/net"
|
||||
"k8s.io/apiserver/pkg/server"
|
||||
utilflag "k8s.io/apiserver/pkg/util/flag"
|
||||
"k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
certutil "k8s.io/client-go/util/cert"
|
||||
)
|
||||
|
||||
@ -47,9 +43,6 @@ type SecureServingOptions struct {
|
||||
ServerCert GeneratableKeyCert
|
||||
// SNICertKeys are named CertKeys for serving secure traffic with SNI support.
|
||||
SNICertKeys []utilflag.NamedCertKey
|
||||
|
||||
// when set determines whether to use loopback configuration to create shared informers.
|
||||
useLoopbackCfg bool
|
||||
}
|
||||
|
||||
type CertKey struct {
|
||||
@ -88,6 +81,10 @@ func (s *SecureServingOptions) DefaultExternalAddress() (net.IP, error) {
|
||||
}
|
||||
|
||||
func (s *SecureServingOptions) Validate() []error {
|
||||
if s == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
errors := []error{}
|
||||
|
||||
if s.BindPort < 0 || s.BindPort > 65535 {
|
||||
@ -98,6 +95,10 @@ func (s *SecureServingOptions) Validate() []error {
|
||||
}
|
||||
|
||||
func (s *SecureServingOptions) AddFlags(fs *pflag.FlagSet) {
|
||||
if s == nil {
|
||||
return
|
||||
}
|
||||
|
||||
fs.IPVar(&s.BindAddress, "bind-address", s.BindAddress, ""+
|
||||
"The IP address on which to listen for the --secure-port port. The "+
|
||||
"associated interface(s) must be reachable by the rest of the cluster, and by CLI/web "+
|
||||
@ -143,6 +144,10 @@ func (s *SecureServingOptions) AddDeprecatedFlags(fs *pflag.FlagSet) {
|
||||
|
||||
// ApplyTo fills up serving information in the server configuration.
|
||||
func (s *SecureServingOptions) ApplyTo(c *server.Config) error {
|
||||
if s == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if s.BindPort <= 0 {
|
||||
return nil
|
||||
}
|
||||
@ -175,39 +180,9 @@ func (s *SecureServingOptions) ApplyTo(c *server.Config) error {
|
||||
c.SecureServingInfo.SNICerts[server.LoopbackClientServerNameOverride] = &tlsCert
|
||||
}
|
||||
|
||||
// create shared informers, if not explicitly set use in cluster config.
|
||||
// do not fail on an error, this allows an external API server to startup
|
||||
// outside of a kube cluster.
|
||||
var clientCfg *rest.Config
|
||||
err = nil
|
||||
if s.useLoopbackCfg {
|
||||
clientCfg = c.LoopbackClientConfig
|
||||
} else {
|
||||
clientCfg, err = rest.InClusterConfig()
|
||||
}
|
||||
if err != nil {
|
||||
glog.Errorf("Couldn't create in cluster config due to %v. SharedInformerFactory will not be set.", err)
|
||||
return nil
|
||||
}
|
||||
clientset, err := kubernetes.NewForConfig(clientCfg)
|
||||
if err != nil {
|
||||
glog.Errorf("Couldn't create clientset due to %v. SharedInformerFactory will not be set.", err)
|
||||
return nil
|
||||
}
|
||||
c.SharedInformerFactory = informers.NewSharedInformerFactory(clientset, 10*time.Minute)
|
||||
return nil
|
||||
}
|
||||
|
||||
// ForceLoopbackConfigUsage forces the usage of the loopback configuration
|
||||
// to create SharedInformerFactory. The primary client of this method
|
||||
// is kube API server, no other API server is the source of truth for kube APIs.
|
||||
//
|
||||
// Note:
|
||||
// this method MUST be called prior to ApplyTo to take an effect.
|
||||
func (s *SecureServingOptions) ForceLoopbackConfigUsage() {
|
||||
s.useLoopbackCfg = true
|
||||
}
|
||||
|
||||
func (s *SecureServingOptions) applyServingInfoTo(c *server.Config) error {
|
||||
if s.BindPort <= 0 {
|
||||
return nil
|
||||
|
@ -487,7 +487,7 @@ NextTest:
|
||||
return
|
||||
}
|
||||
|
||||
s, err := config.Complete().New("test", server.EmptyDelegate)
|
||||
s, err := config.Complete(nil).New("test", server.EmptyDelegate)
|
||||
if err != nil {
|
||||
t.Errorf("%q - failed creating the server: %v", title, err)
|
||||
return
|
||||
|
@ -12,7 +12,7 @@ spec:
|
||||
args:
|
||||
- "/usr/local/bin/kube-aggregator"
|
||||
- "--secure-port=9443"
|
||||
- "--core-kubeconfig=/var/run/auth-client/kube-aggregator.kubeconfig"
|
||||
- "--kubeconfig=/var/run/auth-client/kube-aggregator.kubeconfig"
|
||||
- "--authentication-kubeconfig=/var/run/auth-client/kube-aggregator.kubeconfig"
|
||||
- "--authorization-kubeconfig=/var/run/auth-client/kube-aggregator.kubeconfig"
|
||||
- "--proxy-client-cert-file=/var/run/auth-proxy-client/client-auth-proxy.crt"
|
||||
|
@ -62,7 +62,6 @@ go_library(
|
||||
"//vendor/k8s.io/apiserver/pkg/server:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/util/proxy:go_default_library",
|
||||
"//vendor/k8s.io/client-go/informers:go_default_library",
|
||||
"//vendor/k8s.io/client-go/informers/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/client-go/listers/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/client-go/pkg/version:go_default_library",
|
||||
|
@ -30,7 +30,6 @@ import (
|
||||
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
|
||||
"k8s.io/apiserver/pkg/registry/rest"
|
||||
genericapiserver "k8s.io/apiserver/pkg/server"
|
||||
kubeinformers "k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/pkg/version"
|
||||
|
||||
"k8s.io/kube-aggregator/pkg/apis/apiregistration"
|
||||
@ -70,12 +69,7 @@ func init() {
|
||||
// legacyAPIServiceName is the fixed name of the only non-groupified API version
|
||||
const legacyAPIServiceName = "v1."
|
||||
|
||||
type Config struct {
|
||||
GenericConfig *genericapiserver.Config
|
||||
|
||||
// CoreKubeInformers is used to watch kube resources
|
||||
CoreKubeInformers kubeinformers.SharedInformerFactory
|
||||
|
||||
type ExtraConfig struct {
|
||||
// ProxyClientCert/Key are the client cert used to identify this proxy. Backing APIServices use
|
||||
// this to confirm the proxy's identity
|
||||
ProxyClientCert []byte
|
||||
@ -89,6 +83,21 @@ type Config struct {
|
||||
ServiceResolver ServiceResolver
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
GenericConfig *genericapiserver.RecommendedConfig
|
||||
ExtraConfig ExtraConfig
|
||||
}
|
||||
|
||||
type completedConfig struct {
|
||||
GenericConfig genericapiserver.CompletedConfig
|
||||
ExtraConfig *ExtraConfig
|
||||
}
|
||||
|
||||
type CompletedConfig struct {
|
||||
// Embed a private pointer that cannot be instantiated outside of this package.
|
||||
*completedConfig
|
||||
}
|
||||
|
||||
// APIAggregator contains state for a Kubernetes cluster master/api server.
|
||||
type APIAggregator struct {
|
||||
GenericAPIServer *genericapiserver.GenericAPIServer
|
||||
@ -121,41 +130,35 @@ type APIAggregator struct {
|
||||
openAPIAggregationController *openapicontroller.AggregationController
|
||||
}
|
||||
|
||||
type completedConfig struct {
|
||||
*Config
|
||||
}
|
||||
|
||||
// Complete fills in any fields not set that are required to have valid data. It's mutating the receiver.
|
||||
func (c *Config) Complete() completedConfig {
|
||||
func (cfg *Config) Complete() CompletedConfig {
|
||||
c := completedConfig{
|
||||
cfg.GenericConfig.Complete(),
|
||||
&cfg.ExtraConfig,
|
||||
}
|
||||
|
||||
// the kube aggregator wires its own discovery mechanism
|
||||
// TODO eventually collapse this by extracting all of the discovery out
|
||||
c.GenericConfig.EnableDiscovery = false
|
||||
c.GenericConfig.Complete()
|
||||
|
||||
version := version.Get()
|
||||
c.GenericConfig.Version = &version
|
||||
|
||||
return completedConfig{c}
|
||||
}
|
||||
|
||||
// SkipComplete provides a way to construct a server instance without config completion.
|
||||
func (c *Config) SkipComplete() completedConfig {
|
||||
return completedConfig{c}
|
||||
return CompletedConfig{&c}
|
||||
}
|
||||
|
||||
// New returns a new instance of APIAggregator from the given config.
|
||||
func (c completedConfig) NewWithDelegate(delegationTarget genericapiserver.DelegationTarget) (*APIAggregator, error) {
|
||||
// Prevent generic API server to install OpenAPI handler. Aggregator server
|
||||
// has its own customized OpenAPI handler.
|
||||
openApiConfig := c.Config.GenericConfig.OpenAPIConfig
|
||||
c.Config.GenericConfig.OpenAPIConfig = nil
|
||||
openApiConfig := c.GenericConfig.OpenAPIConfig
|
||||
c.GenericConfig.OpenAPIConfig = nil
|
||||
|
||||
genericServer, err := c.Config.GenericConfig.SkipComplete().New("kube-aggregator", delegationTarget) // completion is done in Complete, no need for a second time
|
||||
genericServer, err := c.GenericConfig.New("kube-aggregator", delegationTarget)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
apiregistrationClient, err := internalclientset.NewForConfig(c.Config.GenericConfig.LoopbackClientConfig)
|
||||
apiregistrationClient, err := internalclientset.NewForConfig(c.GenericConfig.LoopbackClientConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -168,14 +171,14 @@ func (c completedConfig) NewWithDelegate(delegationTarget genericapiserver.Deleg
|
||||
GenericAPIServer: genericServer,
|
||||
delegateHandler: delegationTarget.UnprotectedHandler(),
|
||||
contextMapper: c.GenericConfig.RequestContextMapper,
|
||||
proxyClientCert: c.ProxyClientCert,
|
||||
proxyClientKey: c.ProxyClientKey,
|
||||
proxyTransport: c.ProxyTransport,
|
||||
proxyClientCert: c.ExtraConfig.ProxyClientCert,
|
||||
proxyClientKey: c.ExtraConfig.ProxyClientKey,
|
||||
proxyTransport: c.ExtraConfig.ProxyTransport,
|
||||
proxyHandlers: map[string]*proxyHandler{},
|
||||
handledGroups: sets.String{},
|
||||
lister: informerFactory.Apiregistration().InternalVersion().APIServices().Lister(),
|
||||
APIRegistrationInformers: informerFactory,
|
||||
serviceResolver: c.ServiceResolver,
|
||||
serviceResolver: c.ExtraConfig.ServiceResolver,
|
||||
}
|
||||
|
||||
apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(apiregistration.GroupName, registry, Scheme, metav1.ParameterCodec, Codecs)
|
||||
@ -198,17 +201,17 @@ func (c completedConfig) NewWithDelegate(delegationTarget genericapiserver.Deleg
|
||||
s.GenericAPIServer.Handler.NonGoRestfulMux.Handle("/apis", apisHandler)
|
||||
s.GenericAPIServer.Handler.NonGoRestfulMux.UnlistedHandle("/apis/", apisHandler)
|
||||
|
||||
apiserviceRegistrationController := NewAPIServiceRegistrationController(informerFactory.Apiregistration().InternalVersion().APIServices(), c.CoreKubeInformers.Core().V1().Services(), s)
|
||||
apiserviceRegistrationController := NewAPIServiceRegistrationController(informerFactory.Apiregistration().InternalVersion().APIServices(), c.GenericConfig.SharedInformerFactory.Core().V1().Services(), s)
|
||||
availableController := statuscontrollers.NewAvailableConditionController(
|
||||
informerFactory.Apiregistration().InternalVersion().APIServices(),
|
||||
c.CoreKubeInformers.Core().V1().Services(),
|
||||
c.CoreKubeInformers.Core().V1().Endpoints(),
|
||||
c.GenericConfig.SharedInformerFactory.Core().V1().Services(),
|
||||
c.GenericConfig.SharedInformerFactory.Core().V1().Endpoints(),
|
||||
apiregistrationClient.Apiregistration(),
|
||||
)
|
||||
|
||||
s.GenericAPIServer.AddPostStartHook("start-kube-aggregator-informers", func(context genericapiserver.PostStartHookContext) error {
|
||||
informerFactory.Start(context.StopCh)
|
||||
c.CoreKubeInformers.Start(context.StopCh)
|
||||
c.GenericConfig.SharedInformerFactory.Start(context.StopCh)
|
||||
return nil
|
||||
})
|
||||
s.GenericAPIServer.AddPostStartHook("apiservice-registration-controller", func(context genericapiserver.PostStartHookContext) error {
|
||||
|
@ -16,10 +16,6 @@ go_library(
|
||||
"//vendor/k8s.io/apiserver/pkg/server:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/server/filters:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/server/options:go_default_library",
|
||||
"//vendor/k8s.io/client-go/informers:go_default_library",
|
||||
"//vendor/k8s.io/client-go/kubernetes:go_default_library",
|
||||
"//vendor/k8s.io/client-go/rest:go_default_library",
|
||||
"//vendor/k8s.io/client-go/tools/clientcmd:go_default_library",
|
||||
"//vendor/k8s.io/kube-aggregator/pkg/apis/apiregistration/v1beta1:go_default_library",
|
||||
"//vendor/k8s.io/kube-aggregator/pkg/apiserver:go_default_library",
|
||||
],
|
||||
|
@ -20,7 +20,6 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
@ -30,10 +29,6 @@ import (
|
||||
genericapiserver "k8s.io/apiserver/pkg/server"
|
||||
"k8s.io/apiserver/pkg/server/filters"
|
||||
genericoptions "k8s.io/apiserver/pkg/server/options"
|
||||
kubeinformers "k8s.io/client-go/informers"
|
||||
kubeclientset "k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
"k8s.io/kube-aggregator/pkg/apis/apiregistration/v1beta1"
|
||||
"k8s.io/kube-aggregator/pkg/apiserver"
|
||||
)
|
||||
@ -48,10 +43,6 @@ type AggregatorOptions struct {
|
||||
ProxyClientCertFile string
|
||||
ProxyClientKeyFile string
|
||||
|
||||
// CoreAPIKubeconfig is a filename for a kubeconfig file to contact the core API server with
|
||||
// If it is not set, the in cluster config is used
|
||||
CoreAPIKubeconfig string
|
||||
|
||||
StdOut io.Writer
|
||||
StdErr io.Writer
|
||||
}
|
||||
@ -86,9 +77,6 @@ func (o *AggregatorOptions) AddFlags(fs *pflag.FlagSet) {
|
||||
o.RecommendedOptions.AddFlags(fs)
|
||||
fs.StringVar(&o.ProxyClientCertFile, "proxy-client-cert-file", o.ProxyClientCertFile, "client certificate used identify the proxy to the API server")
|
||||
fs.StringVar(&o.ProxyClientKeyFile, "proxy-client-key-file", o.ProxyClientKeyFile, "client certificate key used identify the proxy to the API server")
|
||||
fs.StringVar(&o.CoreAPIKubeconfig, "core-kubeconfig", o.CoreAPIKubeconfig, ""+
|
||||
"kubeconfig file pointing at the 'core' kubernetes server with enough rights to get,list,watch "+
|
||||
" services,endpoints. If not set, the in-cluster config is used")
|
||||
}
|
||||
|
||||
// NewDefaultOptions builds a "normal" set of options. You wouldn't normally expose this, but hyperkube isn't cobra compatible
|
||||
@ -99,6 +87,7 @@ func NewDefaultOptions(out, err io.Writer) *AggregatorOptions {
|
||||
StdOut: out,
|
||||
StdErr: err,
|
||||
}
|
||||
|
||||
return o
|
||||
}
|
||||
|
||||
@ -118,7 +107,7 @@ func (o AggregatorOptions) RunAggregator(stopCh <-chan struct{}) error {
|
||||
return fmt.Errorf("error creating self-signed certificates: %v", err)
|
||||
}
|
||||
|
||||
serverConfig := genericapiserver.NewConfig(apiserver.Codecs)
|
||||
serverConfig := genericapiserver.NewRecommendedConfig(apiserver.Codecs)
|
||||
|
||||
if err := o.RecommendedOptions.ApplyTo(serverConfig); err != nil {
|
||||
return err
|
||||
@ -128,39 +117,21 @@ func (o AggregatorOptions) RunAggregator(stopCh <-chan struct{}) error {
|
||||
sets.NewString("attach", "exec", "proxy", "log", "portforward"),
|
||||
)
|
||||
|
||||
var kubeconfig *rest.Config
|
||||
var err error
|
||||
if len(o.CoreAPIKubeconfig) > 0 {
|
||||
loadingRules := &clientcmd.ClientConfigLoadingRules{ExplicitPath: o.CoreAPIKubeconfig}
|
||||
loader := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingRules, &clientcmd.ConfigOverrides{})
|
||||
|
||||
kubeconfig, err = loader.ClientConfig()
|
||||
|
||||
} else {
|
||||
kubeconfig, err = rest.InClusterConfig()
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
coreAPIServerClient, err := kubeclientset.NewForConfig(kubeconfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
kubeInformers := kubeinformers.NewSharedInformerFactory(coreAPIServerClient, 5*time.Minute)
|
||||
serviceResolver := apiserver.NewClusterIPServiceResolver(kubeInformers.Core().V1().Services().Lister())
|
||||
serviceResolver := apiserver.NewClusterIPServiceResolver(serverConfig.SharedInformerFactory.Core().V1().Services().Lister())
|
||||
|
||||
config := apiserver.Config{
|
||||
GenericConfig: serverConfig,
|
||||
CoreKubeInformers: kubeInformers,
|
||||
ServiceResolver: serviceResolver,
|
||||
GenericConfig: serverConfig,
|
||||
ExtraConfig: apiserver.ExtraConfig{
|
||||
ServiceResolver: serviceResolver,
|
||||
},
|
||||
}
|
||||
|
||||
config.ProxyClientCert, err = ioutil.ReadFile(o.ProxyClientCertFile)
|
||||
var err error
|
||||
config.ExtraConfig.ProxyClientCert, err = ioutil.ReadFile(o.ProxyClientCertFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
config.ProxyClientKey, err = ioutil.ReadFile(o.ProxyClientKeyFile)
|
||||
config.ExtraConfig.ProxyClientKey, err = ioutil.ReadFile(o.ProxyClientKeyFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -29,7 +29,6 @@ go_library(
|
||||
"//vendor/k8s.io/sample-apiserver/pkg/apis/wardle:go_default_library",
|
||||
"//vendor/k8s.io/sample-apiserver/pkg/apis/wardle/install:go_default_library",
|
||||
"//vendor/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1:go_default_library",
|
||||
"//vendor/k8s.io/sample-apiserver/pkg/client/informers_generated/internalversion:go_default_library",
|
||||
"//vendor/k8s.io/sample-apiserver/pkg/registry:go_default_library",
|
||||
"//vendor/k8s.io/sample-apiserver/pkg/registry/wardle/fischer:go_default_library",
|
||||
"//vendor/k8s.io/sample-apiserver/pkg/registry/wardle/flunder:go_default_library",
|
||||
|
@ -30,7 +30,6 @@ import (
|
||||
"k8s.io/sample-apiserver/pkg/apis/wardle"
|
||||
"k8s.io/sample-apiserver/pkg/apis/wardle/install"
|
||||
"k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1"
|
||||
informers "k8s.io/sample-apiserver/pkg/client/informers_generated/internalversion"
|
||||
wardleregistry "k8s.io/sample-apiserver/pkg/registry"
|
||||
fischerstorage "k8s.io/sample-apiserver/pkg/registry/wardle/fischer"
|
||||
flunderstorage "k8s.io/sample-apiserver/pkg/registry/wardle/flunder"
|
||||
@ -61,10 +60,13 @@ func init() {
|
||||
)
|
||||
}
|
||||
|
||||
type ExtraConfig struct {
|
||||
// Place you custom config here.
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
GenericConfig *genericapiserver.Config
|
||||
// SharedInformerFactory provides shared informers for resources
|
||||
SharedInformerFactory informers.SharedInformerFactory
|
||||
GenericConfig *genericapiserver.RecommendedConfig
|
||||
ExtraConfig ExtraConfig
|
||||
}
|
||||
|
||||
// WardleServer contains state for a Kubernetes cluster master/api server.
|
||||
@ -73,29 +75,33 @@ type WardleServer struct {
|
||||
}
|
||||
|
||||
type completedConfig struct {
|
||||
*Config
|
||||
GenericConfig genericapiserver.CompletedConfig
|
||||
ExtraConfig *ExtraConfig
|
||||
}
|
||||
|
||||
type CompletedConfig struct {
|
||||
// Embed a private pointer that cannot be instantiated outside of this package.
|
||||
*completedConfig
|
||||
}
|
||||
|
||||
// Complete fills in any fields not set that are required to have valid data. It's mutating the receiver.
|
||||
func (c *Config) Complete() completedConfig {
|
||||
c.GenericConfig.Complete()
|
||||
func (cfg *Config) Complete() CompletedConfig {
|
||||
c := completedConfig{
|
||||
cfg.GenericConfig.Complete(),
|
||||
&cfg.ExtraConfig,
|
||||
}
|
||||
|
||||
c.GenericConfig.Version = &version.Info{
|
||||
Major: "1",
|
||||
Minor: "0",
|
||||
}
|
||||
|
||||
return completedConfig{c}
|
||||
}
|
||||
|
||||
// SkipComplete provides a way to construct a server instance without config completion.
|
||||
func (c *Config) SkipComplete() completedConfig {
|
||||
return completedConfig{c}
|
||||
return CompletedConfig{&c}
|
||||
}
|
||||
|
||||
// New returns a new instance of WardleServer from the given config.
|
||||
func (c completedConfig) New() (*WardleServer, error) {
|
||||
genericServer, err := c.Config.GenericConfig.SkipComplete().New("sample-apiserver", genericapiserver.EmptyDelegate) // completion is done in Complete, no need for a second time
|
||||
genericServer, err := c.GenericConfig.New("sample-apiserver", genericapiserver.EmptyDelegate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -104,7 +104,7 @@ func (o WardleServerOptions) Config() (*apiserver.Config, error) {
|
||||
return nil, fmt.Errorf("error creating self-signed certificates: %v", err)
|
||||
}
|
||||
|
||||
serverConfig := genericapiserver.NewConfig(apiserver.Codecs)
|
||||
serverConfig := genericapiserver.NewRecommendedConfig(apiserver.Codecs)
|
||||
if err := o.RecommendedOptions.ApplyTo(serverConfig); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -119,13 +119,13 @@ func (o WardleServerOptions) Config() (*apiserver.Config, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := o.Admission.ApplyTo(serverConfig, admissionInitializer); err != nil {
|
||||
if err := o.Admission.ApplyTo(&serverConfig.Config, serverConfig.SharedInformerFactory, admissionInitializer); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
config := &apiserver.Config{
|
||||
GenericConfig: serverConfig,
|
||||
SharedInformerFactory: informerFactory,
|
||||
GenericConfig: serverConfig,
|
||||
ExtraConfig: apiserver.ExtraConfig{},
|
||||
}
|
||||
return config, nil
|
||||
}
|
||||
@ -142,7 +142,7 @@ func (o WardleServerOptions) RunWardleServer(stopCh <-chan struct{}) error {
|
||||
}
|
||||
|
||||
server.GenericAPIServer.AddPostStartHook("start-sample-server-informers", func(context genericapiserver.PostStartHookContext) error {
|
||||
config.SharedInformerFactory.Start(context.StopCh)
|
||||
config.GenericConfig.SharedInformerFactory.Start(context.StopCh)
|
||||
return nil
|
||||
})
|
||||
|
||||
|
@ -44,7 +44,7 @@ import (
|
||||
|
||||
func setup(t *testing.T) (*httptest.Server, clientset.Interface, framework.CloseFunc) {
|
||||
masterConfig := framework.NewIntegrationTestMasterConfig()
|
||||
masterConfig.EnableCoreControllers = false
|
||||
masterConfig.ExtraConfig.EnableCoreControllers = false
|
||||
_, s, closeFn := framework.RunAMaster(masterConfig)
|
||||
|
||||
clientSet, err := clientset.NewForConfig(&restclient.Config{Host: s.URL})
|
||||
|
@ -75,7 +75,7 @@ type testRESTOptionsGetter struct {
|
||||
}
|
||||
|
||||
func (getter *testRESTOptionsGetter) GetRESTOptions(resource schema.GroupResource) (generic.RESTOptions, error) {
|
||||
storageConfig, err := getter.config.StorageFactory.NewConfig(resource)
|
||||
storageConfig, err := getter.config.ExtraConfig.StorageFactory.NewConfig(resource)
|
||||
if err != nil {
|
||||
return generic.RESTOptions{}, fmt.Errorf("failed to get storage: %v", err)
|
||||
}
|
||||
|
@ -685,14 +685,14 @@ func startRealMasterOrDie(t *testing.T, certDir string) (*allClient, clientv3.KV
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
kubeAPIServerConfig, sharedInformers, _, _, _, err := app.CreateKubeAPIServerConfig(kubeAPIServerOptions, tunneler, proxyTransport)
|
||||
kubeAPIServerConfig, sharedInformers, versionedInformers, _, _, err := app.CreateKubeAPIServerConfig(kubeAPIServerOptions, tunneler, proxyTransport)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
kubeAPIServerConfig.APIResourceConfigSource = &allResourceSource{} // force enable all resources
|
||||
kubeAPIServerConfig.ExtraConfig.APIResourceConfigSource = &allResourceSource{} // force enable all resources
|
||||
|
||||
kubeAPIServer, err := app.CreateKubeAPIServer(kubeAPIServerConfig, genericapiserver.EmptyDelegate, sharedInformers)
|
||||
kubeAPIServer, err := app.CreateKubeAPIServer(kubeAPIServerConfig, genericapiserver.EmptyDelegate, sharedInformers, versionedInformers)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -116,13 +116,13 @@ func TestAggregatedAPIServer(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
kubeAPIServerConfig, sharedInformers, _, _, _, err := app.CreateKubeAPIServerConfig(kubeAPIServerOptions, tunneler, proxyTransport)
|
||||
kubeAPIServerConfig, sharedInformers, versionedInformers, _, _, err := app.CreateKubeAPIServerConfig(kubeAPIServerOptions, tunneler, proxyTransport)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
kubeClientConfigValue.Store(kubeAPIServerConfig.GenericConfig.LoopbackClientConfig)
|
||||
|
||||
kubeAPIServer, err := app.CreateKubeAPIServer(kubeAPIServerConfig, genericapiserver.EmptyDelegate, sharedInformers)
|
||||
kubeAPIServer, err := app.CreateKubeAPIServer(kubeAPIServerConfig, genericapiserver.EmptyDelegate, sharedInformers, versionedInformers)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -192,6 +192,7 @@ func TestAggregatedAPIServer(t *testing.T) {
|
||||
"--authorization-kubeconfig", kubeconfigFile.Name(),
|
||||
"--etcd-servers", framework.GetEtcdURL(),
|
||||
"--cert-dir", wardleCertDir,
|
||||
"--kubeconfig", kubeconfigFile.Name(),
|
||||
})
|
||||
if err := wardleCmd.Execute(); err != nil {
|
||||
t.Log(err)
|
||||
@ -263,7 +264,7 @@ func TestAggregatedAPIServer(t *testing.T) {
|
||||
"--requestheader-username-headers", "",
|
||||
"--proxy-client-cert-file", proxyClientCertFile.Name(),
|
||||
"--proxy-client-key-file", proxyClientKeyFile.Name(),
|
||||
"--core-kubeconfig", kubeconfigFile.Name(),
|
||||
"--kubeconfig", kubeconfigFile.Name(),
|
||||
"--authentication-kubeconfig", kubeconfigFile.Name(),
|
||||
"--authorization-kubeconfig", kubeconfigFile.Name(),
|
||||
"--etcd-servers", framework.GetEtcdURL(),
|
||||
|
@ -248,9 +248,9 @@ func startMasterOrDie(masterConfig *master.Config, incomingServer *httptest.Serv
|
||||
if err != nil {
|
||||
glog.Fatal(err)
|
||||
}
|
||||
masterConfig.GenericConfig.SharedInformerFactory = extinformers.NewSharedInformerFactory(clientset, masterConfig.GenericConfig.LoopbackClientConfig.Timeout)
|
||||
|
||||
m, err = masterConfig.Complete().New(genericapiserver.EmptyDelegate)
|
||||
sharedInformers := extinformers.NewSharedInformerFactory(clientset, masterConfig.GenericConfig.LoopbackClientConfig.Timeout)
|
||||
m, err = masterConfig.Complete(sharedInformers).New(genericapiserver.EmptyDelegate)
|
||||
if err != nil {
|
||||
closeFn()
|
||||
glog.Fatalf("error in bringing up the master: %v", err)
|
||||
@ -357,22 +357,24 @@ func NewMasterConfig() *master.Config {
|
||||
}
|
||||
|
||||
return &master.Config{
|
||||
GenericConfig: genericConfig,
|
||||
APIResourceConfigSource: master.DefaultAPIResourceConfigSource(),
|
||||
StorageFactory: storageFactory,
|
||||
EnableCoreControllers: true,
|
||||
KubeletClientConfig: kubeletclient.KubeletClientConfig{Port: 10250},
|
||||
APIServerServicePort: 443,
|
||||
MasterCount: 1,
|
||||
GenericConfig: genericConfig,
|
||||
ExtraConfig: master.ExtraConfig{
|
||||
APIResourceConfigSource: master.DefaultAPIResourceConfigSource(),
|
||||
StorageFactory: storageFactory,
|
||||
EnableCoreControllers: true,
|
||||
KubeletClientConfig: kubeletclient.KubeletClientConfig{Port: 10250},
|
||||
APIServerServicePort: 443,
|
||||
MasterCount: 1,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the master config appropriate for most integration tests.
|
||||
func NewIntegrationTestMasterConfig() *master.Config {
|
||||
masterConfig := NewMasterConfig()
|
||||
masterConfig.EnableCoreControllers = true
|
||||
masterConfig.ExtraConfig.EnableCoreControllers = true
|
||||
masterConfig.GenericConfig.PublicAddress = net.ParseIP("192.168.10.4")
|
||||
masterConfig.APIResourceConfigSource = master.DefaultAPIResourceConfigSource()
|
||||
masterConfig.ExtraConfig.APIResourceConfigSource = master.DefaultAPIResourceConfigSource()
|
||||
return masterConfig
|
||||
}
|
||||
|
||||
|
@ -548,7 +548,7 @@ func TestServiceAlloc(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("bad cidr: %v", err)
|
||||
}
|
||||
cfg.ServiceIPRange = *cidr
|
||||
cfg.ExtraConfig.ServiceIPRange = *cidr
|
||||
_, s, closeFn := framework.RunAMaster(cfg)
|
||||
defer closeFn()
|
||||
|
||||
|
@ -30,9 +30,11 @@ func TestMasterExportsSymbols(t *testing.T) {
|
||||
GenericConfig: &genericapiserver.Config{
|
||||
EnableMetrics: true,
|
||||
},
|
||||
EnableCoreControllers: false,
|
||||
EnableUISupport: false,
|
||||
EnableLogsSupport: false,
|
||||
ExtraConfig: master.ExtraConfig{
|
||||
EnableCoreControllers: false,
|
||||
EnableUISupport: false,
|
||||
EnableLogsSupport: false,
|
||||
},
|
||||
}
|
||||
_ = &master.Master{
|
||||
GenericAPIServer: &genericapiserver.GenericAPIServer{},
|
||||
|
Loading…
Reference in New Issue
Block a user