Merge pull request #46812 from lavalamp/whitlockjc-plumbing

Automatic merge from submit-queue (batch tested with PRs 47726, 47693, 46909, 46812)

Plumb service resolver into webhook AC

This is the last piece of plumbing needed for https://github.com/kubernetes/features/issues/209
This commit is contained in:
Kubernetes Submit Queue
2017-06-19 18:34:06 -07:00
committed by GitHub
7 changed files with 144 additions and 66 deletions

View File

@@ -37,6 +37,7 @@ go_library(
"apiservice_controller.go",
"handler_apis.go",
"handler_proxy.go",
"resolvers.go",
],
tags = ["automanaged"],
deps = [

View File

@@ -20,7 +20,6 @@ import (
"context"
"encoding/json"
"net/http"
"net/url"
"sync"
"time"
@@ -34,10 +33,8 @@ import (
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
"k8s.io/apiserver/pkg/registry/rest"
genericapiserver "k8s.io/apiserver/pkg/server"
"k8s.io/apiserver/pkg/util/proxy"
kubeinformers "k8s.io/client-go/informers"
kubeclientset "k8s.io/client-go/kubernetes"
listersv1 "k8s.io/client-go/listers/core/v1"
"k8s.io/client-go/pkg/version"
"bytes"
@@ -89,19 +86,6 @@ func init() {
// legacyAPIServiceName is the fixed name of the only non-groupified API version
const legacyAPIServiceName = "v1."
type ServiceResolver interface {
ResolveEndpoint(namespace, name string) (*url.URL, error)
}
type aggregatorEndpointRouting struct {
services listersv1.ServiceLister
endpoints listersv1.EndpointsLister
}
type aggregatorClusterRouting struct {
services listersv1.ServiceLister
}
type Config struct {
GenericConfig *genericapiserver.Config
CoreAPIServerClient kubeclientset.Interface
@@ -110,10 +94,19 @@ type Config struct {
// this to confirm the proxy's identity
ProxyClientCert []byte
ProxyClientKey []byte
ProxyTransport *http.Transport
// Indicates if the Aggregator should send to the cluster IP (false) or route to the endpoints IP (true)
// If present, the Dial method will be used for dialing out to delegate
// apiservers.
ProxyTransport *http.Transport
// Indicates if the Aggregator should send to the service's cluster IP
// (false) or route to the one of the service's endpoint's IP (true);
// if ServiceResolver is provided, then this is ignored.
EnableAggregatorRouting bool
// Mechanism by which the Aggregator will resolve services. If nil,
// constructed based on the value of EnableAggregatorRouting.
ServiceResolver ServiceResolver
}
// APIAggregator contains state for a Kubernetes cluster master/api server.
@@ -186,14 +179,6 @@ func (c *Config) SkipComplete() completedConfig {
return completedConfig{c}
}
func (r *aggregatorEndpointRouting) ResolveEndpoint(namespace, name string) (*url.URL, error) {
return proxy.ResolveEndpoint(r.services, r.endpoints, namespace, name)
}
func (r *aggregatorClusterRouting) ResolveEndpoint(namespace, name string) (*url.URL, error) {
return proxy.ResolveCluster(r.services, namespace, name)
}
// New returns a new instance of APIAggregator from the given config.
func (c completedConfig) NewWithDelegate(delegationTarget genericapiserver.DelegationTarget) (*APIAggregator, error) {
genericServer, err := c.Config.GenericConfig.SkipComplete().New("kube-aggregator", delegationTarget) // completion is done in Complete, no need for a second time
@@ -211,15 +196,15 @@ func (c completedConfig) NewWithDelegate(delegationTarget genericapiserver.Deleg
)
kubeInformers := kubeinformers.NewSharedInformerFactory(c.CoreAPIServerClient, 5*time.Minute)
var routing ServiceResolver
if c.EnableAggregatorRouting {
routing = &aggregatorEndpointRouting{
services: kubeInformers.Core().V1().Services().Lister(),
endpoints: kubeInformers.Core().V1().Endpoints().Lister(),
}
} else {
routing = &aggregatorClusterRouting{
services: kubeInformers.Core().V1().Services().Lister(),
var routing ServiceResolver = c.ServiceResolver
if routing == nil {
if c.EnableAggregatorRouting {
routing = NewEndpointServiceResolver(
kubeInformers.Core().V1().Services().Lister(),
kubeInformers.Core().V1().Endpoints().Lister(),
)
} else {
routing = NewClusterIPServiceResolver(kubeInformers.Core().V1().Services().Lister())
}
}

View File

@@ -0,0 +1,63 @@
/*
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 apiserver
import (
"net/url"
"k8s.io/apiserver/pkg/util/proxy"
listersv1 "k8s.io/client-go/listers/core/v1"
)
// A ServiceResolver knows how to get a URL given a service.
type ServiceResolver interface {
ResolveEndpoint(namespace, name string) (*url.URL, error)
}
// NewEndpointServiceResolver returns a ServiceResolver that chooses one of the
// service's endpoints.
func NewEndpointServiceResolver(services listersv1.ServiceLister, endpoints listersv1.EndpointsLister) ServiceResolver {
return &aggregatorEndpointRouting{
services: services,
endpoints: endpoints,
}
}
type aggregatorEndpointRouting struct {
services listersv1.ServiceLister
endpoints listersv1.EndpointsLister
}
func (r *aggregatorEndpointRouting) ResolveEndpoint(namespace, name string) (*url.URL, error) {
return proxy.ResolveEndpoint(r.services, r.endpoints, namespace, name)
}
// NewEndpointServiceResolver returns a ServiceResolver that directly calls the
// service's cluster IP.
func NewClusterIPServiceResolver(services listersv1.ServiceLister) ServiceResolver {
return &aggregatorClusterRouting{
services: services,
}
}
type aggregatorClusterRouting struct {
services listersv1.ServiceLister
}
func (r *aggregatorClusterRouting) ResolveEndpoint(namespace, name string) (*url.URL, error) {
return proxy.ResolveCluster(r.services, namespace, name)
}