Skip to content

Commit 2d3e218

Browse files
ronethingCopilot
andauthored
feat: support ingress translator (#78)
Signed-off-by: ashing <[email protected]> Co-authored-by: Copilot <[email protected]>
1 parent a7229ce commit 2d3e218

File tree

13 files changed

+606
-121
lines changed

13 files changed

+606
-121
lines changed

Makefile

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,20 @@ else
3030
GOBIN=$(shell go env GOBIN)
3131
endif
3232

33+
GOOS ?= linux
34+
GOARCH ?= amd64
35+
36+
ifeq ($(shell uname -s),Darwin)
37+
GOOS = darwin
38+
endif
39+
40+
ifeq ($(shell uname -m),arm64)
41+
GOARCH = arm64
42+
endif
43+
ifeq ($(shell uname -m), aarch64)
44+
GOARCH = arm64
45+
endif
46+
3347
# CONTAINER_TOOL defines the container tool to be used for building images.
3448
# Be aware that the target commands are only tested with Docker which is
3549
# scaffolded by default. However, you might want to replace it to use other
@@ -142,7 +156,7 @@ pull-infra-images:
142156

143157
.PHONY: build
144158
build: manifests generate fmt vet ## Build manager binary.
145-
CGO_ENABLED=0 go build -o bin/api7-ingress-controller -ldflags $(GO_LDFLAGS) cmd/main.go
159+
GOOS=$(GOOS) GOARCH=$(GOARCH) CGO_ENABLED=0 go build -o bin/api7-ingress-controller -ldflags $(GO_LDFLAGS) cmd/main.go
146160

147161
linux-build:
148162
GOOS=linux GOARCH=arm64 CGO_ENABLED=0 go build -o bin/api7-ingress-controller -ldflags $(GO_LDFLAGS) cmd/main.go
@@ -158,7 +172,7 @@ run: manifests generate fmt vet ## Run a controller from your host.
158172
# (i.e. docker build --platform linux/arm64). However, you must enable docker buildKit for it.
159173
# More info: https://docs.docker.com/develop/develop-images/build_enhancements/
160174
.PHONY: docker-build
161-
docker-build: build ## Build docker image with the manager.
175+
docker-build: set-e2e-goos build ## Build docker image with the manager.
162176
$(CONTAINER_TOOL) build -t ${IMG} -f Dockerfile .
163177

164178
.PHONY: docker-push
@@ -268,6 +282,11 @@ gofmt: ## Apply go fmt
268282
@go fmt ./...
269283
.PHONY: gofmt
270284

285+
set-e2e-goos:
286+
$(eval GOOS=linux)
287+
@echo "e2e GOOS: $(GOOS)"
288+
.PHONY: set-e2e-goos
289+
271290
# go-install-tool will 'go install' any package with custom target and name of binary, if it doesn't exist
272291
# $1 - target path with name of binary
273292
# $2 - package url which can be installed

api/adc/types.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ type Upstream struct {
148148

149149
HashOn string `json:"hash_on,omitempty" yaml:"hash_on,omitempty"`
150150
Key string `json:"key,omitempty" yaml:"key,omitempty"`
151-
Nodes UpstreamNodes `json:"nodes,omitempty" yaml:"nodes,omitempty"`
151+
Nodes UpstreamNodes `json:"nodes" yaml:"nodes"`
152152
PassHost *PassHost `json:"pass_host,omitempty" yaml:"pass_host,omitempty"`
153153
Retries *int64 `json:"retries,omitempty" yaml:"retries,omitempty"`
154154
RetryTimeout *float64 `json:"retry_timeout,omitempty" yaml:"retry_timeout,omitempty"`

config/samples/config.yaml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,11 @@ log_level: "info" # The log level of the API7 Ingr
44
controller_name: gateway.api7.io/api7-ingress-controller # The controller name of the API7 Ingress Controller,
55
# which is used to identify the controller in the GatewayClass.
66
# The default value is "gateway.api7.io/api7-ingress-controller".
7-
87
leader_election_id: "api7-ingress-controller-leader" # The leader election ID for the API7 Ingress Controller.
98
# The default value is "api7-ingress-controller-leader".
10-
119
ingress_class: api7 # The ingress class name of the API7 Ingress Controller.
1210
ingress_publish_service: "" # The service name of the ingress publish service.
1311
ingress_status_address: [] # The status address of the ingress.
14-
1512
gateway_configs: # The configuration of the API7 Gateway.
1613
- name: api7 # The name of the Gateway in the Gateway API.
1714
control_plane:

internal/controller/ingress_controller.go

Lines changed: 82 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"github.com/api7/api7-ingress-controller/internal/provider"
1111
"github.com/api7/gopkg/pkg/log"
1212
"github.com/go-logr/logr"
13+
"go.uber.org/zap"
1314
corev1 "k8s.io/api/core/v1"
1415
discoveryv1 "k8s.io/api/discovery/v1"
1516
networkingv1 "k8s.io/api/networking/v1"
@@ -41,7 +42,12 @@ func (r *IngressReconciler) SetupWithManager(mgr ctrl.Manager) error {
4142
predicate.NewPredicateFuncs(r.checkIngressClass),
4243
),
4344
).
44-
WithEventFilter(predicate.GenerationChangedPredicate{}).
45+
WithEventFilter(
46+
predicate.Or(
47+
predicate.GenerationChangedPredicate{},
48+
predicate.AnnotationChangedPredicate{},
49+
),
50+
).
4551
Watches(
4652
&networkingv1.IngressClass{},
4753
handler.EnqueueRequestsFromMapFunc(r.listIngressForIngressClass),
@@ -134,16 +140,19 @@ func (r *IngressReconciler) checkIngressClass(obj client.Object) bool {
134140
// find the ingress class that is marked as default
135141
for _, ic := range ingressClassList.Items {
136142
if IsDefaultIngressClass(&ic) && matchesController(ic.Spec.Controller) {
143+
log.Debugw("match the default ingress class")
137144
return true
138145
}
139146
}
140147

148+
log.Debugw("no default ingress class found")
141149
return false
142150
}
143151

144152
configuredClass := config.GetIngressClass()
145153
// if the ingress class name matches the configured ingress class name, return true
146154
if *ingress.Spec.IngressClassName == configuredClass {
155+
log.Debugw("match the configured ingress class name")
147156
return true
148157
}
149158

@@ -168,25 +177,55 @@ func (r *IngressReconciler) matchesIngressController(obj client.Object) bool {
168177
}
169178

170179
// listIngressForIngressClass list all ingresses that use a specific ingress class
171-
func (r *IngressReconciler) listIngressForIngressClass(ctx context.Context, ingressClass client.Object) []reconcile.Request {
172-
ingressList := &networkingv1.IngressList{}
173-
if err := r.List(ctx, ingressList, client.MatchingFields{
174-
indexer.IngressClassRef: ingressClass.GetName(),
175-
}); err != nil {
176-
r.Log.Error(err, "failed to list ingresses for ingress class", "ingressclass", ingressClass.GetName())
180+
func (r *IngressReconciler) listIngressForIngressClass(ctx context.Context, obj client.Object) []reconcile.Request {
181+
ingressClass, ok := obj.(*networkingv1.IngressClass)
182+
if !ok {
183+
r.Log.Error(fmt.Errorf("unexpected object type"), "failed to convert object to IngressClass")
177184
return nil
178185
}
179186

180-
requests := make([]reconcile.Request, 0, len(ingressList.Items))
181-
for _, ingress := range ingressList.Items {
182-
requests = append(requests, reconcile.Request{
183-
NamespacedName: client.ObjectKey{
184-
Namespace: ingress.Namespace,
185-
Name: ingress.Name,
186-
},
187-
})
187+
// check if the ingress class is the default ingress class
188+
if IsDefaultIngressClass(ingressClass) {
189+
ingressList := &networkingv1.IngressList{}
190+
if err := r.List(ctx, ingressList); err != nil {
191+
r.Log.Error(err, "failed to list ingresses for ingress class", "ingressclass", ingressClass.GetName())
192+
return nil
193+
}
194+
195+
requests := make([]reconcile.Request, 0, len(ingressList.Items))
196+
for _, ingress := range ingressList.Items {
197+
if ingress.Spec.IngressClassName == nil || *ingress.Spec.IngressClassName == "" ||
198+
*ingress.Spec.IngressClassName == ingressClass.GetName() {
199+
requests = append(requests, reconcile.Request{
200+
NamespacedName: client.ObjectKey{
201+
Namespace: ingress.Namespace,
202+
Name: ingress.Name,
203+
},
204+
})
205+
}
206+
}
207+
return requests
208+
} else {
209+
ingressList := &networkingv1.IngressList{}
210+
if err := r.List(ctx, ingressList, client.MatchingFields{
211+
indexer.IngressClassRef: ingressClass.GetName(),
212+
}); err != nil {
213+
r.Log.Error(err, "failed to list ingresses for ingress class", "ingressclass", ingressClass.GetName())
214+
return nil
215+
}
216+
217+
requests := make([]reconcile.Request, 0, len(ingressList.Items))
218+
for _, ingress := range ingressList.Items {
219+
requests = append(requests, reconcile.Request{
220+
NamespacedName: client.ObjectKey{
221+
Namespace: ingress.Namespace,
222+
Name: ingress.Name,
223+
},
224+
})
225+
}
226+
227+
return requests
188228
}
189-
return requests
190229
}
191230

192231
// listIngressesByService list all ingresses that use a specific service
@@ -210,12 +249,14 @@ func (r *IngressReconciler) listIngressesByService(ctx context.Context, obj clie
210249

211250
requests := make([]reconcile.Request, 0, len(ingressList.Items))
212251
for _, ingress := range ingressList.Items {
213-
requests = append(requests, reconcile.Request{
214-
NamespacedName: client.ObjectKey{
215-
Namespace: ingress.Namespace,
216-
Name: ingress.Name,
217-
},
218-
})
252+
if r.checkIngressClass(&ingress) {
253+
requests = append(requests, reconcile.Request{
254+
NamespacedName: client.ObjectKey{
255+
Namespace: ingress.Namespace,
256+
Name: ingress.Name,
257+
},
258+
})
259+
}
219260
}
220261
return requests
221262
}
@@ -241,12 +282,14 @@ func (r *IngressReconciler) listIngressesBySecret(ctx context.Context, obj clien
241282

242283
requests := make([]reconcile.Request, 0, len(ingressList.Items))
243284
for _, ingress := range ingressList.Items {
244-
requests = append(requests, reconcile.Request{
245-
NamespacedName: client.ObjectKey{
246-
Namespace: ingress.Namespace,
247-
Name: ingress.Name,
248-
},
249-
})
285+
if r.checkIngressClass(&ingress) {
286+
requests = append(requests, reconcile.Request{
287+
NamespacedName: client.ObjectKey{
288+
Namespace: ingress.Namespace,
289+
Name: ingress.Name,
290+
},
291+
})
292+
}
250293
}
251294
return requests
252295
}
@@ -267,6 +310,11 @@ func (r *IngressReconciler) processTLS(ctx context.Context, tctx *provider.Trans
267310
return err
268311
}
269312

313+
if secret.Data == nil {
314+
log.Warnw("secret data is nil", zap.String("secret", secret.Namespace+"/"+secret.Name))
315+
continue
316+
}
317+
270318
// add the secret to the translate context
271319
tctx.Secrets[types.NamespacedName{Namespace: ingress.Namespace, Name: tls.SecretName}] = &secret
272320
}
@@ -283,19 +331,16 @@ func (r *IngressReconciler) processBackends(ctx context.Context, tctx *provider.
283331
if rule.HTTP == nil {
284332
continue
285333
}
286-
287334
for _, path := range rule.HTTP.Paths {
288335
if path.Backend.Service == nil {
289336
continue
290337
}
291-
292338
service := path.Backend.Service
293339
if err := r.processBackendService(ctx, tctx, ingress.Namespace, service); err != nil {
294340
terr = err
295341
}
296342
}
297343
}
298-
299344
return terr
300345
}
301346

@@ -356,6 +401,11 @@ func (r *IngressReconciler) processBackendService(ctx context.Context, tctx *pro
356401
Name: backendService.Name,
357402
}] = endpointSliceList.Items
358403

404+
tctx.Services[client.ObjectKey{
405+
Namespace: namespace,
406+
Name: backendService.Name,
407+
}] = &service
408+
359409
return nil
360410
}
361411

@@ -383,6 +433,7 @@ func (r *IngressReconciler) updateStatus(ctx context.Context, ingress *networkin
383433
if err != nil {
384434
return fmt.Errorf("invalid ingress-publish-service format: %s, expected format: namespace/name", publishService)
385435
}
436+
// if the namespace is not specified, use the ingress namespace
386437
if namespace == "" {
387438
namespace = ingress.Namespace
388439
}

internal/provider/adc/adc.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,9 @@ func (d *adcClient) Delete(ctx context.Context, obj client.Object) error {
101101
labels = label.GenLabel(obj)
102102
case *gatewayv1.Gateway:
103103
// delete all resources
104+
case *networkingv1.Ingress:
105+
resourceTypes = append(resourceTypes, "service", "ssl")
106+
labels = label.GenLabel(obj)
104107
case *v1alpha1.Consumer:
105108
resourceTypes = append(resourceTypes, "consumer")
106109
labels = label.GenLabel(obj)

0 commit comments

Comments
 (0)