Kubernetes SD: Introduce ingressAdaptor

Signed-off-by: Takashi Kusumi <tkusumi@zlab.co.jp>
This commit is contained in:
Takashi Kusumi 2021-08-20 13:31:33 +09:00
parent 6634a570cf
commit 40981c422b
2 changed files with 176 additions and 109 deletions

View file

@ -114,26 +114,23 @@ func (i *Ingress) process(ctx context.Context, ch chan<- []*targetgroup.Group) b
return true
}
var ia ingressAdaptor
switch ingress := o.(type) {
case *v1.Ingress:
send(ctx, ch, i.buildIngress(ingress))
return true
ia = newIngressAdaptorFromV1(ingress)
case *v1beta1.Ingress:
send(ctx, ch, i.buildIngressV1beta1(ingress))
ia = newIngressAdaptorFromV1beta1(ingress)
default:
level.Error(i.logger).Log("msg", "converting to Ingress object failed", "err",
errors.Errorf("received unexpected object: %v", o))
return true
}
level.Error(i.logger).Log("msg", "converting to Ingress object failed", "err",
errors.Errorf("received unexpected object: %v", o))
send(ctx, ch, i.buildIngress(ia))
return true
}
func ingressSource(s *v1.Ingress) string {
return ingressSourceFromNamespaceAndName(s.Namespace, s.Name)
}
func ingressSourceV1beta1(s *v1beta1.Ingress) string {
return ingressSourceFromNamespaceAndName(s.Namespace, s.Name)
func ingressSource(s ingressAdaptor) string {
return ingressSourceFromNamespaceAndName(s.namespace(), s.name())
}
func ingressSourceFromNamespaceAndName(namespace, name string) string {
@ -152,22 +149,22 @@ const (
ingressClassNameLabel = metaLabelPrefix + "ingress_class_name"
)
func ingressLabels(ingress *v1.Ingress) model.LabelSet {
func ingressLabels(ingress ingressAdaptor) model.LabelSet {
// Each label and annotation will create two key-value pairs in the map.
ls := make(model.LabelSet, 2*(len(ingress.Labels)+len(ingress.Annotations))+2)
ls[ingressNameLabel] = lv(ingress.Name)
ls[namespaceLabel] = lv(ingress.Namespace)
if ingress.Spec.IngressClassName != nil {
ls[ingressClassNameLabel] = lv(*ingress.Spec.IngressClassName)
ls := make(model.LabelSet, 2*(len(ingress.labels())+len(ingress.annotations()))+2)
ls[ingressNameLabel] = lv(ingress.name())
ls[namespaceLabel] = lv(ingress.namespace())
if cls := ingress.ingressClassName(); cls != nil {
ls[ingressClassNameLabel] = lv(*cls)
}
for k, v := range ingress.Labels {
for k, v := range ingress.labels() {
ln := strutil.SanitizeLabelName(k)
ls[model.LabelName(ingressLabelPrefix+ln)] = lv(v)
ls[model.LabelName(ingressLabelPresentPrefix+ln)] = presentValue
}
for k, v := range ingress.Annotations {
for k, v := range ingress.annotations() {
ln := strutil.SanitizeLabelName(k)
ls[model.LabelName(ingressAnnotationPrefix+ln)] = lv(v)
ls[model.LabelName(ingressAnnotationPresentPrefix+ln)] = presentValue
@ -175,37 +172,14 @@ func ingressLabels(ingress *v1.Ingress) model.LabelSet {
return ls
}
func ingressLabelsV1beta1(ingress *v1beta1.Ingress) model.LabelSet {
// Each label and annotation will create two key-value pairs in the map.
ls := make(model.LabelSet, 2*(len(ingress.Labels)+len(ingress.Annotations))+2)
ls[ingressNameLabel] = lv(ingress.Name)
ls[namespaceLabel] = lv(ingress.Namespace)
if ingress.Spec.IngressClassName != nil {
ls[ingressClassNameLabel] = lv(*ingress.Spec.IngressClassName)
}
for k, v := range ingress.Labels {
ln := strutil.SanitizeLabelName(k)
ls[model.LabelName(ingressLabelPrefix+ln)] = lv(v)
ls[model.LabelName(ingressLabelPresentPrefix+ln)] = presentValue
}
for k, v := range ingress.Annotations {
ln := strutil.SanitizeLabelName(k)
ls[model.LabelName(ingressAnnotationPrefix+ln)] = lv(v)
ls[model.LabelName(ingressAnnotationPresentPrefix+ln)] = presentValue
}
return ls
}
func pathsFromIngressRule(rv *v1.IngressRuleValue) []string {
if rv.HTTP == nil {
func pathsFromIngressPaths(ingressPaths []string) []string {
if ingressPaths == nil {
return []string{"/"}
}
paths := make([]string, len(rv.HTTP.Paths))
for n, p := range rv.HTTP.Paths {
path := p.Path
if path == "" {
paths := make([]string, len(ingressPaths))
for n, p := range ingressPaths {
path := p
if p == "" {
path = "/"
}
paths[n] = path
@ -213,83 +187,31 @@ func pathsFromIngressRule(rv *v1.IngressRuleValue) []string {
return paths
}
func pathsFromIngressRuleV1beta1(rv *v1beta1.IngressRuleValue) []string {
if rv.HTTP == nil {
return []string{"/"}
}
paths := make([]string, len(rv.HTTP.Paths))
for n, p := range rv.HTTP.Paths {
path := p.Path
if path == "" {
path = "/"
}
paths[n] = path
}
return paths
}
func (i *Ingress) buildIngress(ingress *v1.Ingress) *targetgroup.Group {
func (i *Ingress) buildIngress(ingress ingressAdaptor) *targetgroup.Group {
tg := &targetgroup.Group{
Source: ingressSource(ingress),
}
tg.Labels = ingressLabels(ingress)
tlsHosts := make(map[string]struct{})
for _, tls := range ingress.Spec.TLS {
for _, host := range tls.Hosts {
tlsHosts[host] = struct{}{}
}
for _, host := range ingress.tlsHosts() {
tlsHosts[host] = struct{}{}
}
for _, rule := range ingress.Spec.Rules {
paths := pathsFromIngressRule(&rule.IngressRuleValue)
for _, rule := range ingress.rules() {
paths := pathsFromIngressPaths(rule.paths())
scheme := "http"
_, isTLS := tlsHosts[rule.Host]
_, isTLS := tlsHosts[rule.host()]
if isTLS {
scheme = "https"
}
for _, path := range paths {
tg.Targets = append(tg.Targets, model.LabelSet{
model.AddressLabel: lv(rule.Host),
model.AddressLabel: lv(rule.host()),
ingressSchemeLabel: lv(scheme),
ingressHostLabel: lv(rule.Host),
ingressPathLabel: lv(path),
})
}
}
return tg
}
func (i *Ingress) buildIngressV1beta1(ingress *v1beta1.Ingress) *targetgroup.Group {
tg := &targetgroup.Group{
Source: ingressSourceV1beta1(ingress),
}
tg.Labels = ingressLabelsV1beta1(ingress)
tlsHosts := make(map[string]struct{})
for _, tls := range ingress.Spec.TLS {
for _, host := range tls.Hosts {
tlsHosts[host] = struct{}{}
}
}
for _, rule := range ingress.Spec.Rules {
paths := pathsFromIngressRuleV1beta1(&rule.IngressRuleValue)
scheme := "http"
_, isTLS := tlsHosts[rule.Host]
if isTLS {
scheme = "https"
}
for _, path := range paths {
tg.Targets = append(tg.Targets, model.LabelSet{
model.AddressLabel: lv(rule.Host),
ingressSchemeLabel: lv(scheme),
ingressHostLabel: lv(rule.Host),
ingressHostLabel: lv(rule.host()),
ingressPathLabel: lv(path),
})
}

View file

@ -0,0 +1,145 @@
// Copyright 2016 The Prometheus 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 kubernetes
import (
v1 "k8s.io/api/networking/v1"
"k8s.io/api/networking/v1beta1"
)
// ingressAdaptor is an adaptor for the different Ingress versions
type ingressAdaptor interface {
name() string
namespace() string
labels() map[string]string
annotations() map[string]string
tlsHosts() []string
ingressClassName() *string
rules() []ingressRuleAdaptor
}
type ingressRuleAdaptor interface {
paths() []string
host() string
}
// Adaptor for networking.k8s.io/v1
type ingressAdaptorV1 struct {
ingress *v1.Ingress
}
func newIngressAdaptorFromV1(ingress *v1.Ingress) ingressAdaptor {
return &ingressAdaptorV1{ingress: ingress}
}
func (i *ingressAdaptorV1) name() string { return i.ingress.Name }
func (i *ingressAdaptorV1) namespace() string { return i.ingress.Namespace }
func (i *ingressAdaptorV1) labels() map[string]string { return i.ingress.Labels }
func (i *ingressAdaptorV1) annotations() map[string]string { return i.ingress.Annotations }
func (i *ingressAdaptorV1) ingressClassName() *string { return i.ingress.Spec.IngressClassName }
func (i *ingressAdaptorV1) tlsHosts() []string {
var hosts []string
for _, tls := range i.ingress.Spec.TLS {
for _, host := range tls.Hosts {
hosts = append(hosts, host)
}
}
return hosts
}
func (i *ingressAdaptorV1) rules() []ingressRuleAdaptor {
var rules []ingressRuleAdaptor
for _, rule := range i.ingress.Spec.Rules {
rules = append(rules, newIngressRuleAdaptorFromV1(rule))
}
return rules
}
type ingressRuleAdaptorV1 struct {
rule v1.IngressRule
}
func newIngressRuleAdaptorFromV1(rule v1.IngressRule) ingressRuleAdaptor {
return &ingressRuleAdaptorV1{rule: rule}
}
func (i *ingressRuleAdaptorV1) paths() []string {
rv := i.rule.IngressRuleValue
if rv.HTTP == nil {
return nil
}
paths := make([]string, len(rv.HTTP.Paths))
for n, p := range rv.HTTP.Paths {
paths[n] = p.Path
}
return paths
}
func (i *ingressRuleAdaptorV1) host() string { return i.rule.Host }
// Adaptor for networking.k8s.io/v1beta1
type ingressAdaptorV1Beta1 struct {
ingress *v1beta1.Ingress
}
func newIngressAdaptorFromV1beta1(ingress *v1beta1.Ingress) ingressAdaptor {
return &ingressAdaptorV1Beta1{ingress: ingress}
}
func (i *ingressAdaptorV1Beta1) name() string { return i.ingress.Name }
func (i *ingressAdaptorV1Beta1) namespace() string { return i.ingress.Namespace }
func (i *ingressAdaptorV1Beta1) labels() map[string]string { return i.ingress.Labels }
func (i *ingressAdaptorV1Beta1) annotations() map[string]string { return i.ingress.Annotations }
func (i *ingressAdaptorV1Beta1) ingressClassName() *string { return i.ingress.Spec.IngressClassName }
func (i *ingressAdaptorV1Beta1) tlsHosts() []string {
var hosts []string
for _, tls := range i.ingress.Spec.TLS {
for _, host := range tls.Hosts {
hosts = append(hosts, host)
}
}
return hosts
}
func (i *ingressAdaptorV1Beta1) rules() []ingressRuleAdaptor {
var rules []ingressRuleAdaptor
for _, rule := range i.ingress.Spec.Rules {
rules = append(rules, newIngressRuleAdaptorFromV1Beta1(rule))
}
return rules
}
type ingressRuleAdaptorV1Beta1 struct {
rule v1beta1.IngressRule
}
func newIngressRuleAdaptorFromV1Beta1(rule v1beta1.IngressRule) ingressRuleAdaptor {
return &ingressRuleAdaptorV1Beta1{rule: rule}
}
func (i *ingressRuleAdaptorV1Beta1) paths() []string {
rv := i.rule.IngressRuleValue
if rv.HTTP == nil {
return nil
}
paths := make([]string, len(rv.HTTP.Paths))
for n, p := range rv.HTTP.Paths {
paths[n] = p.Path
}
return paths
}
func (i *ingressRuleAdaptorV1Beta1) host() string { return i.rule.Host }