-
Notifications
You must be signed in to change notification settings - Fork 2.8k
/
dedicated_ingress.go
162 lines (145 loc) · 5.16 KB
/
dedicated_ingress.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
// SPDX-License-Identifier: Apache-2.0
// Copyright Authors of Cilium
package ingress
import (
"fmt"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"github.com/cilium/cilium/operator/pkg/model"
"github.com/cilium/cilium/operator/pkg/model/translation"
ciliumv2 "github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2"
slim_networkingv1 "github.com/cilium/cilium/pkg/k8s/slim/k8s/api/networking/v1"
"github.com/cilium/cilium/pkg/logging/logfields"
)
const (
ciliumIngressPrefix = "cilium-ingress"
ciliumIngressLabelKey = "cilium.io/ingress"
)
var _ translation.Translator = (*DedicatedIngressTranslator)(nil)
type DedicatedIngressTranslator struct {
secretsNamespace string
enforceHTTPs bool
useProxyProtocol bool
idleTimeoutSeconds int
}
func NewDedicatedIngressTranslator(secretsNamespace string, enforceHTTPs bool, useProxyProtocol bool, idleTimeoutSeconds int) *DedicatedIngressTranslator {
return &DedicatedIngressTranslator{
secretsNamespace: secretsNamespace,
enforceHTTPs: enforceHTTPs,
useProxyProtocol: useProxyProtocol,
idleTimeoutSeconds: idleTimeoutSeconds,
}
}
func (d *DedicatedIngressTranslator) Translate(m *model.Model) (*ciliumv2.CiliumEnvoyConfig, *corev1.Service, *corev1.Endpoints, error) {
if m == nil || (len(m.HTTP) == 0 && len(m.TLS) == 0) {
return nil, nil, nil, fmt.Errorf("model source can't be empty")
}
var name string
var namespace string
var sourceResource model.FullyQualifiedResource
var modelService *model.Service
var cecName string
if len(m.HTTP) == 0 {
name = fmt.Sprintf("%s-%s", ciliumIngressPrefix, m.TLS[0].Sources[0].Name)
namespace = m.TLS[0].Sources[0].Namespace
sourceResource = m.TLS[0].Sources[0]
modelService = m.TLS[0].Service
cecName = fmt.Sprintf("%s-%s-%s", ciliumIngressPrefix, namespace, m.TLS[0].Sources[0].Name)
} else {
name = fmt.Sprintf("%s-%s", ciliumIngressPrefix, m.HTTP[0].Sources[0].Name)
namespace = m.HTTP[0].Sources[0].Namespace
sourceResource = m.HTTP[0].Sources[0]
modelService = m.HTTP[0].Service
cecName = fmt.Sprintf("%s-%s-%s", ciliumIngressPrefix, namespace, m.HTTP[0].Sources[0].Name)
}
// The logic is same as what we have with default translator, but with a different model
// (i.e. the HTTP listeners are just belonged to one Ingress resource).
translator := translation.NewTranslator(name, namespace, d.secretsNamespace, d.enforceHTTPs, d.useProxyProtocol, false, d.idleTimeoutSeconds)
cec, _, _, err := translator.Translate(m)
if err != nil {
return nil, nil, nil, err
}
// Set the name to avoid any breaking change during upgrade.
cec.Name = cecName
return cec, getService(sourceResource, modelService), getEndpoints(sourceResource), err
}
func getService(resource model.FullyQualifiedResource, service *model.Service) *corev1.Service {
serviceType := corev1.ServiceTypeLoadBalancer
ports := []corev1.ServicePort{
{
Name: "http",
Protocol: "TCP",
Port: 80,
},
{
Name: "https",
Protocol: "TCP",
Port: 443,
},
}
if service != nil {
switch service.Type {
case string(corev1.ServiceTypeNodePort):
serviceType = corev1.ServiceTypeNodePort
if service.InsecureNodePort != nil {
ports[0].NodePort = int32(*service.InsecureNodePort)
}
if service.SecureNodePort != nil {
ports[1].NodePort = int32(*service.SecureNodePort)
}
case string(corev1.ServiceTypeLoadBalancer):
// Do nothing as the port number is allocated by the cloud provider.
default:
log.WithField(logfields.ServiceType, service.Type).
Warn("only LoadBalancer and NodePort are supported. Defaulting to LoadBalancer")
}
}
return &corev1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: fmt.Sprintf("%s-%s", ciliumIngressPrefix, resource.Name),
Namespace: resource.Namespace,
Labels: map[string]string{ciliumIngressLabelKey: "true"},
OwnerReferences: []metav1.OwnerReference{
{
APIVersion: slim_networkingv1.SchemeGroupVersion.String(),
Kind: "Ingress",
Name: resource.Name,
UID: types.UID(resource.UID),
Controller: model.AddressOf(true),
},
},
},
Spec: corev1.ServiceSpec{
Type: serviceType,
Ports: ports,
},
}
}
func getEndpoints(resource model.FullyQualifiedResource) *corev1.Endpoints {
return &corev1.Endpoints{
ObjectMeta: metav1.ObjectMeta{
Name: fmt.Sprintf("%s-%s", ciliumIngressPrefix, resource.Name),
Namespace: resource.Namespace,
Labels: map[string]string{ciliumIngressLabelKey: "true"},
OwnerReferences: []metav1.OwnerReference{
{
APIVersion: slim_networkingv1.SchemeGroupVersion.String(),
Kind: "Ingress",
Name: resource.Name,
UID: types.UID(resource.UID),
Controller: model.AddressOf(true),
},
},
},
Subsets: []corev1.EndpointSubset{
{
// This dummy endpoint is required as agent refuses to push service entry
// to the lb map when the service has no backends.
// Related github issue https://github.com/cilium/cilium/issues/19262
Addresses: []corev1.EndpointAddress{{IP: "192.192.192.192"}}, // dummy
Ports: []corev1.EndpointPort{{Port: 9999}}, // dummy
},
},
}
}