Update nginx and generic controller

This commit is contained in:
Manuel de Brito Fontes 2017-04-01 11:39:42 -03:00
parent c7c2a564a9
commit e0561ddeb9
62 changed files with 1043 additions and 510 deletions

View file

@ -21,8 +21,8 @@ import (
"github.com/golang/glog"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/apis/extensions"
api "k8s.io/client-go/pkg/api/v1"
extensions "k8s.io/client-go/pkg/apis/extensions/v1beta1"
"k8s.io/ingress/core/pkg/ingress/annotations/auth"
"k8s.io/ingress/core/pkg/ingress/annotations/authreq"

View file

@ -19,9 +19,10 @@ package controller
import (
"testing"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/apis/extensions"
"k8s.io/kubernetes/pkg/util/intstr"
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
api "k8s.io/client-go/pkg/api/v1"
extensions "k8s.io/client-go/pkg/apis/extensions/v1beta1"
"k8s.io/ingress/core/pkg/ingress/defaults"
"k8s.io/ingress/core/pkg/ingress/resolver"
@ -75,7 +76,7 @@ func buildIngress() *extensions.Ingress {
}
return &extensions.Ingress{
ObjectMeta: api.ObjectMeta{
ObjectMeta: meta_v1.ObjectMeta{
Name: "foo",
Namespace: api.NamespaceDefault,
},
@ -251,7 +252,7 @@ func TestCertificateAuthSecret(t *testing.T) {
resolver := mockCfg{}
resolver.MockSecrets = map[string]*api.Secret{
"default/foo_secret": {
ObjectMeta: api.ObjectMeta{
ObjectMeta: meta_v1.ObjectMeta{
Name: "foo_secret_name",
},
},

View file

@ -24,9 +24,9 @@ import (
"github.com/golang/glog"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/apis/extensions"
"k8s.io/kubernetes/pkg/client/cache"
api "k8s.io/client-go/pkg/api/v1"
extensions "k8s.io/client-go/pkg/apis/extensions/v1beta1"
"k8s.io/client-go/tools/cache"
"k8s.io/ingress/core/pkg/ingress"
"k8s.io/ingress/core/pkg/ingress/annotations/parser"

View file

@ -29,17 +29,17 @@ import (
"github.com/golang/glog"
"github.com/kylelemons/godebug/pretty"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/apis/extensions"
"k8s.io/kubernetes/pkg/client/cache"
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
unversionedcore "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion"
"k8s.io/kubernetes/pkg/client/record"
"k8s.io/kubernetes/pkg/fields"
"k8s.io/kubernetes/pkg/util/flowcontrol"
"k8s.io/kubernetes/pkg/util/intstr"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/util/intstr"
clientset "k8s.io/client-go/kubernetes"
unversionedcore "k8s.io/client-go/kubernetes/typed/core/v1"
def_api "k8s.io/client-go/pkg/api"
api "k8s.io/client-go/pkg/api/v1"
extensions "k8s.io/client-go/pkg/apis/extensions/v1beta1"
"k8s.io/client-go/tools/cache"
"k8s.io/client-go/tools/record"
"k8s.io/client-go/util/flowcontrol"
cache_store "k8s.io/ingress/core/pkg/cache"
"k8s.io/ingress/core/pkg/ingress"
"k8s.io/ingress/core/pkg/ingress/annotations/class"
"k8s.io/ingress/core/pkg/ingress/annotations/healthcheck"
@ -48,6 +48,7 @@ import (
"k8s.io/ingress/core/pkg/ingress/defaults"
"k8s.io/ingress/core/pkg/ingress/resolver"
"k8s.io/ingress/core/pkg/ingress/status"
"k8s.io/ingress/core/pkg/ingress/store"
"k8s.io/ingress/core/pkg/k8s"
ssl "k8s.io/ingress/core/pkg/net/ssl"
local_strings "k8s.io/ingress/core/pkg/strings"
@ -70,19 +71,19 @@ var (
type GenericController struct {
cfg *Configuration
ingController *cache.Controller
endpController *cache.Controller
svcController *cache.Controller
nodeController *cache.Controller
secrController *cache.Controller
mapController *cache.Controller
ingController cache.Controller
endpController cache.Controller
svcController cache.Controller
nodeController cache.Controller
secrController cache.Controller
mapController cache.Controller
ingLister cache_store.StoreToIngressLister
svcLister cache.StoreToServiceLister
nodeLister cache.StoreToNodeLister
endpLister cache.StoreToEndpointsLister
secrLister cache_store.StoreToSecretsLister
mapLister cache_store.StoreToConfigmapLister
ingLister store.IngressLister
svcLister store.ServiceLister
nodeLister store.NodeLister
endpLister store.EndpointLister
secrLister store.SecretLister
mapLister store.ConfigMapLister
annotations annotationExtractor
@ -149,7 +150,7 @@ func newIngressController(config *Configuration) *GenericController {
stopLock: &sync.Mutex{},
stopCh: make(chan struct{}),
syncRateLimiter: flowcontrol.NewTokenBucketRateLimiter(0.1, 1),
recorder: eventBroadcaster.NewRecorder(api.EventSource{
recorder: eventBroadcaster.NewRecorder(def_api.Scheme, api.EventSource{
Component: "ingress-controller",
}),
sslCertTracker: newSSLCertTracker(),
@ -306,12 +307,9 @@ func newIngressController(config *Configuration) *GenericController {
cache.NewListWatchFromClient(ic.cfg.Client.Core().RESTClient(), "configmaps", api.NamespaceAll, fields.Everything()),
&api.ConfigMap{}, ic.cfg.ResyncPeriod, mapEventHandler)
ic.svcLister.Indexer, ic.svcController = cache.NewIndexerInformer(
ic.svcLister.Store, ic.svcController = cache.NewInformer(
cache.NewListWatchFromClient(ic.cfg.Client.Core().RESTClient(), "services", ic.cfg.Namespace, fields.Everything()),
&api.Service{},
ic.cfg.ResyncPeriod,
cache.ResourceEventHandlerFuncs{},
cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc})
&api.Service{}, ic.cfg.ResyncPeriod, cache.ResourceEventHandlerFuncs{})
ic.nodeLister.Store, ic.nodeController = cache.NewInformer(
cache.NewListWatchFromClient(ic.cfg.Client.Core().RESTClient(), "nodes", api.NamespaceAll, fields.Everything()),
@ -498,7 +496,7 @@ func (ic *GenericController) getStreamServices(configmapName string, proto api.P
continue
}
svcObj, svcExists, err := ic.svcLister.Indexer.GetByKey(nsName)
svcObj, svcExists, err := ic.svcLister.Store.GetByKey(nsName)
if err != nil {
glog.Warningf("error getting service %v: %v", nsName, err)
continue
@ -562,7 +560,7 @@ func (ic *GenericController) getDefaultUpstream() *ingress.Backend {
Name: defUpstreamName,
}
svcKey := ic.cfg.DefaultService
svcObj, svcExists, err := ic.svcLister.Indexer.GetByKey(svcKey)
svcObj, svcExists, err := ic.svcLister.Store.GetByKey(svcKey)
if err != nil {
glog.Warningf("unexpected error searching the default backend %v: %v", ic.cfg.DefaultService, err)
upstream.Endpoints = append(upstream.Endpoints, newDefaultServer())
@ -809,7 +807,7 @@ func (ic *GenericController) createUpstreams(data []interface{}) map[string]*ing
// to a service.
func (ic *GenericController) serviceEndpoints(svcKey, backendPort string,
hz *healthcheck.Upstream) ([]ingress.Endpoint, error) {
svcObj, svcExists, err := ic.svcLister.Indexer.GetByKey(svcKey)
svcObj, svcExists, err := ic.svcLister.Store.GetByKey(svcKey)
var upstreams []ingress.Endpoint
if err != nil {

View file

@ -14,11 +14,12 @@ import (
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/spf13/pflag"
"k8s.io/kubernetes/pkg/api"
client "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
"k8s.io/kubernetes/pkg/client/unversioned/clientcmd"
clientcmdapi "k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api"
"k8s.io/kubernetes/pkg/healthz"
"k8s.io/apiserver/pkg/server/healthz"
"k8s.io/client-go/kubernetes"
api "k8s.io/client-go/pkg/api/v1"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
clientcmd_api "k8s.io/client-go/tools/clientcmd/api"
"k8s.io/ingress/core/pkg/ingress"
"k8s.io/ingress/core/pkg/k8s"
@ -208,19 +209,35 @@ const (
defaultBurst = 1e6
)
// buildConfigFromFlags builds REST config based on master URL and kubeconfig path.
// If both of them are empty then in cluster config is used.
func buildConfigFromFlags(masterURL, kubeconfigPath string) (*rest.Config, error) {
if kubeconfigPath == "" && masterURL == "" {
kubeconfig, err := rest.InClusterConfig()
if err != nil {
return nil, err
}
return kubeconfig, nil
}
return clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
&clientcmd.ClientConfigLoadingRules{ExplicitPath: kubeconfigPath},
&clientcmd.ConfigOverrides{
ClusterInfo: clientcmd_api.Cluster{
Server: masterURL,
},
}).ClientConfig()
}
// createApiserverClient creates new Kubernetes Apiserver client. When kubeconfig or apiserverHost param is empty
// the function assumes that it is running inside a Kubernetes cluster and attempts to
// discover the Apiserver. Otherwise, it connects to the Apiserver specified.
//
// apiserverHost param is in the format of protocol://address:port/pathPrefix, e.g.http://localhost:8001.
// kubeConfig location of kubeconfig file
func createApiserverClient(apiserverHost string, kubeConfig string) (*client.Clientset, error) {
clientConfig := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
&clientcmd.ClientConfigLoadingRules{ExplicitPath: kubeConfig},
&clientcmd.ConfigOverrides{ClusterInfo: clientcmdapi.Cluster{Server: apiserverHost}})
cfg, err := clientConfig.ClientConfig()
func createApiserverClient(apiserverHost string, kubeConfig string) (*kubernetes.Clientset, error) {
cfg, err := buildConfigFromFlags(apiserverHost, kubeConfig)
if err != nil {
return nil, err
}
@ -231,7 +248,7 @@ func createApiserverClient(apiserverHost string, kubeConfig string) (*client.Cli
glog.Infof("Creating API server client for %s", cfg.Host)
client, err := client.NewForConfig(cfg)
client, err := kubernetes.NewForConfig(cfg)
if err != nil {
return nil, err

View file

@ -24,9 +24,10 @@ import (
"github.com/golang/glog"
"k8s.io/kubernetes/pkg/api"
podutil "k8s.io/kubernetes/pkg/api/pod"
"k8s.io/kubernetes/pkg/labels"
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/util/intstr"
api_v1 "k8s.io/client-go/pkg/api/v1"
"k8s.io/ingress/core/pkg/ingress/annotations/service"
)
@ -35,11 +36,11 @@ import (
// named port. If the annotation in the service does not exist or is not equals
// to the port mapping obtained from the pod the service must be updated to reflect
// the current state
func (ic *GenericController) checkSvcForUpdate(svc *api.Service) error {
func (ic *GenericController) checkSvcForUpdate(svc *api_v1.Service) error {
// get the pods associated with the service
// TODO: switch this to a watch
pods, err := ic.cfg.Client.Core().Pods(svc.Namespace).List(api.ListOptions{
LabelSelector: labels.Set(svc.Spec.Selector).AsSelector(),
pods, err := ic.cfg.Client.Core().Pods(svc.Namespace).List(meta_v1.ListOptions{
LabelSelector: labels.Set(svc.Spec.Selector).AsSelector().String(),
})
if err != nil {
@ -60,7 +61,7 @@ func (ic *GenericController) checkSvcForUpdate(svc *api.Service) error {
_, err := strconv.Atoi(servicePort.TargetPort.StrVal)
if err != nil {
portNum, err := podutil.FindPort(pod, servicePort)
portNum, err := findPort(pod, servicePort)
if err != nil {
glog.V(4).Infof("failed to find port for service %s/%s: %v", portNum, svc.Namespace, svc.Name, err)
continue
@ -82,7 +83,7 @@ func (ic *GenericController) checkSvcForUpdate(svc *api.Service) error {
if len(namedPorts) > 0 && !reflect.DeepEqual(curNamedPort, namedPorts) {
data, _ := json.Marshal(namedPorts)
newSvc, err := ic.cfg.Client.Core().Services(svc.Namespace).Get(svc.Name)
newSvc, err := ic.cfg.Client.Core().Services(svc.Namespace).Get(svc.Name, meta_v1.GetOptions{})
if err != nil {
return fmt.Errorf("error getting service %v/%v: %v", svc.Namespace, svc.Name, err)
}
@ -103,3 +104,26 @@ func (ic *GenericController) checkSvcForUpdate(svc *api.Service) error {
return nil
}
// FindPort locates the container port for the given pod and portName. If the
// targetPort is a number, use that. If the targetPort is a string, look that
// string up in all named ports in all containers in the target pod. If no
// match is found, fail.
func findPort(pod *api_v1.Pod, svcPort *api_v1.ServicePort) (int, error) {
portName := svcPort.TargetPort
switch portName.Type {
case intstr.String:
name := portName.StrVal
for _, container := range pod.Spec.Containers {
for _, port := range container.Ports {
if port.Name == name && port.Protocol == svcPort.Protocol {
return int(port.ContainerPort), nil
}
}
}
case intstr.Int:
return portName.IntValue(), nil
}
return 0, fmt.Errorf("no suitable port for manifest: %s", pod.UID)
}

View file

@ -20,51 +20,55 @@ import (
"reflect"
"testing"
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/client-go/kubernetes/fake"
"k8s.io/client-go/pkg/api"
api_v1 "k8s.io/client-go/pkg/api/v1"
"k8s.io/ingress/core/pkg/ingress/annotations/service"
"k8s.io/kubernetes/pkg/api"
testclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake"
"k8s.io/kubernetes/pkg/util/intstr"
)
func buildSimpleClientSet() *testclient.Clientset {
return testclient.NewSimpleClientset(
&api.PodList{Items: []api.Pod{
{
ObjectMeta: api.ObjectMeta{
Name: "foo1",
Namespace: api.NamespaceDefault,
Labels: map[string]string{
"lable_sig": "foo_pod",
func buildSimpleClientSet() *fake.Clientset {
return fake.NewSimpleClientset(
&api_v1.PodList{
Items: []api_v1.Pod{
{
ObjectMeta: meta_v1.ObjectMeta{
Name: "foo1",
Namespace: api.NamespaceDefault,
Labels: map[string]string{
"lable_sig": "foo_pod",
},
},
},
Spec: api.PodSpec{
NodeName: "foo_node_1",
Containers: []api.Container{
{
Ports: []api.ContainerPort{
{
Name: "foo1_named_port_c1",
Protocol: api.ProtocolTCP,
ContainerPort: 80,
Spec: api_v1.PodSpec{
NodeName: "foo_node_1",
Containers: []api_v1.Container{
{
Ports: []api_v1.ContainerPort{
{
Name: "foo1_named_port_c1",
Protocol: api_v1.ProtocolTCP,
ContainerPort: 80,
},
},
},
},
},
},
},
{
ObjectMeta: api.ObjectMeta{
Name: "foo1",
Namespace: api.NamespaceSystem,
Labels: map[string]string{
"lable_sig": "foo_pod",
{
ObjectMeta: meta_v1.ObjectMeta{
Name: "foo1",
Namespace: api.NamespaceSystem,
Labels: map[string]string{
"lable_sig": "foo_pod",
},
},
},
},
}},
&api.ServiceList{Items: []api.Service{
},
&api_v1.ServiceList{Items: []api_v1.Service{
{
ObjectMeta: api.ObjectMeta{
ObjectMeta: meta_v1.ObjectMeta{
Namespace: api.NamespaceDefault,
Name: "named_port_test_service",
},
@ -81,14 +85,13 @@ func buildGenericController() *GenericController {
}
}
func buildService() *api.Service {
return &api.Service{
ObjectMeta: api.ObjectMeta{
func buildService() *api_v1.Service {
return &api_v1.Service{
ObjectMeta: meta_v1.ObjectMeta{
Namespace: api.NamespaceSystem,
Name: "named_port_test_service",
},
Spec: api.ServiceSpec{
Spec: api_v1.ServiceSpec{
ClusterIP: "10.10.10.10",
},
}
@ -98,17 +101,17 @@ func TestCheckSvcForUpdate(t *testing.T) {
foos := []struct {
n string
ns string
sps []api.ServicePort
sps []api_v1.ServicePort
sl map[string]string
er string
}{
{
"pods_have_not_been_found_in_this_namespace",
api.NamespaceSystem,
[]api.ServicePort{
{Name: "foo_port_1", Port: 8080, Protocol: api.ProtocolTCP, TargetPort: intstr.FromString("foo1_named_port_c1")},
{Name: "foo_port_2", Port: 8181, Protocol: api.ProtocolTCP, TargetPort: intstr.FromInt(81)},
{Name: "foo_port_3", Port: 8282, Protocol: api.ProtocolTCP, TargetPort: intstr.FromString("")},
[]api_v1.ServicePort{
{Name: "foo_port_1", Port: 8080, Protocol: api_v1.ProtocolTCP, TargetPort: intstr.FromString("foo1_named_port_c1")},
{Name: "foo_port_2", Port: 8181, Protocol: api_v1.ProtocolTCP, TargetPort: intstr.FromInt(81)},
{Name: "foo_port_3", Port: 8282, Protocol: api_v1.ProtocolTCP, TargetPort: intstr.FromString("")},
},
map[string]string{
"lable_sig": "foo_pod",
@ -118,10 +121,10 @@ func TestCheckSvcForUpdate(t *testing.T) {
{
"ports_have_not_been_found_in_this_pod",
api.NamespaceDefault,
[]api.ServicePort{
{Name: "foo_port_1", Port: 8080, Protocol: api.ProtocolTCP, TargetPort: intstr.FromString("foo1_named_port_cXX")},
{Name: "foo_port_2", Port: 8181, Protocol: api.ProtocolTCP, TargetPort: intstr.FromInt(81)},
{Name: "foo_port_3", Port: 8282, Protocol: api.ProtocolTCP, TargetPort: intstr.FromString("")},
[]api_v1.ServicePort{
{Name: "foo_port_1", Port: 8080, Protocol: api_v1.ProtocolTCP, TargetPort: intstr.FromString("foo1_named_port_cXX")},
{Name: "foo_port_2", Port: 8181, Protocol: api_v1.ProtocolTCP, TargetPort: intstr.FromInt(81)},
{Name: "foo_port_3", Port: 8282, Protocol: api_v1.ProtocolTCP, TargetPort: intstr.FromString("")},
},
map[string]string{
"lable_sig": "foo_pod",
@ -132,10 +135,10 @@ func TestCheckSvcForUpdate(t *testing.T) {
{
"ports_fixed",
api.NamespaceDefault,
[]api.ServicePort{
{Name: "foo_port_1", Port: 8080, Protocol: api.ProtocolTCP, TargetPort: intstr.FromInt(80)},
{Name: "foo_port_2", Port: 8181, Protocol: api.ProtocolTCP, TargetPort: intstr.FromInt(81)},
{Name: "foo_port_3", Port: 8282, Protocol: api.ProtocolTCP, TargetPort: intstr.FromString("")},
[]api_v1.ServicePort{
{Name: "foo_port_1", Port: 8080, Protocol: api_v1.ProtocolTCP, TargetPort: intstr.FromInt(80)},
{Name: "foo_port_2", Port: 8181, Protocol: api_v1.ProtocolTCP, TargetPort: intstr.FromInt(81)},
{Name: "foo_port_3", Port: 8282, Protocol: api_v1.ProtocolTCP, TargetPort: intstr.FromString("")},
},
map[string]string{
"lable_sig": "foo_pod",
@ -145,10 +148,10 @@ func TestCheckSvcForUpdate(t *testing.T) {
{
"nil_selector",
api.NamespaceDefault,
[]api.ServicePort{
{Name: "foo_port_1", Port: 8080, Protocol: api.ProtocolTCP, TargetPort: intstr.FromString("foo1_named_port_c1")},
{Name: "foo_port_2", Port: 8181, Protocol: api.ProtocolTCP, TargetPort: intstr.FromInt(81)},
{Name: "foo_port_3", Port: 8282, Protocol: api.ProtocolTCP, TargetPort: intstr.FromString("")},
[]api_v1.ServicePort{
{Name: "foo_port_1", Port: 8080, Protocol: api_v1.ProtocolTCP, TargetPort: intstr.FromString("foo1_named_port_c1")},
{Name: "foo_port_2", Port: 8181, Protocol: api_v1.ProtocolTCP, TargetPort: intstr.FromInt(81)},
{Name: "foo_port_3", Port: 8282, Protocol: api_v1.ProtocolTCP, TargetPort: intstr.FromString("")},
},
nil,
"{\"foo1_named_port_c1\":\"80\"}",
@ -156,10 +159,10 @@ func TestCheckSvcForUpdate(t *testing.T) {
{
"normal_update",
api.NamespaceDefault,
[]api.ServicePort{
{Name: "foo_port_1", Port: 8080, Protocol: api.ProtocolTCP, TargetPort: intstr.FromString("foo1_named_port_c1")},
{Name: "foo_port_2", Port: 8181, Protocol: api.ProtocolTCP, TargetPort: intstr.FromInt(81)},
{Name: "foo_port_3", Port: 8282, Protocol: api.ProtocolTCP, TargetPort: intstr.FromString("")},
[]api_v1.ServicePort{
{Name: "foo_port_1", Port: 8080, Protocol: api_v1.ProtocolTCP, TargetPort: intstr.FromString("foo1_named_port_c1")},
{Name: "foo_port_2", Port: 8181, Protocol: api_v1.ProtocolTCP, TargetPort: intstr.FromInt(81)},
{Name: "foo_port_3", Port: 8282, Protocol: api_v1.ProtocolTCP, TargetPort: intstr.FromString("")},
},
map[string]string{
"lable_sig": "foo_pod",
@ -181,7 +184,7 @@ func TestCheckSvcForUpdate(t *testing.T) {
t.Fatalf("unexpected error: %v", err)
}
rs, _ := gc.cfg.Client.Core().Services(api.NamespaceDefault).Get("named_port_test_service")
rs, _ := gc.cfg.Client.Core().Services(api.NamespaceDefault).Get("named_port_test_service", meta_v1.GetOptions{})
rr := rs.ObjectMeta.Annotations[service.NamedPortAnnotation]
if !reflect.DeepEqual(rr, foo.er) {
t.Errorf("Returned %s, but expected %s for %s", rr, foo.er, foo.n)

View file

@ -17,9 +17,8 @@ limitations under the License.
package controller
import (
"testing"
"reflect"
"testing"
"k8s.io/ingress/core/pkg/ingress"
"k8s.io/ingress/core/pkg/ingress/annotations/auth"