Skip to content

Commit b87e04c

Browse files
authored
feat: sync once when startup ingress (#233)
Signed-off-by: Ashing Zheng <[email protected]>
1 parent 840b137 commit b87e04c

File tree

8 files changed

+121
-10
lines changed

8 files changed

+121
-10
lines changed

internal/adc/client/client.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ import (
3939
)
4040

4141
type Client struct {
42-
syncMu sync.Mutex
42+
syncMu sync.RWMutex
4343
mu sync.Mutex
4444
*cache.Store
4545

@@ -97,6 +97,9 @@ func (d *Client) Update(ctx context.Context, args Task) error {
9797
}
9898
d.mu.Unlock()
9999

100+
d.syncMu.RLock()
101+
defer d.syncMu.RUnlock()
102+
100103
if len(deleteConfigs) > 0 {
101104
err := d.sync(ctx, Task{
102105
Name: args.Name,
@@ -108,6 +111,7 @@ func (d *Client) Update(ctx context.Context, args Task) error {
108111
log.Warnw("failed to sync deleted configs", zap.Error(err))
109112
}
110113
}
114+
111115
return d.sync(ctx, args)
112116
}
113117

@@ -154,6 +158,9 @@ func (d *Client) Delete(ctx context.Context, args Task) error {
154158
}
155159
d.mu.Unlock()
156160

161+
d.syncMu.RLock()
162+
defer d.syncMu.RUnlock()
163+
157164
return d.sync(ctx, Task{
158165
Labels: args.Labels,
159166
ResourceTypes: args.ResourceTypes,

internal/provider/api7ee/provider.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package api7ee
1919

2020
import (
2121
"context"
22+
"sync/atomic"
2223
"time"
2324

2425
"github.com/api7/gopkg/pkg/log"
@@ -56,6 +57,8 @@ type api7eeProvider struct {
5657

5758
syncCh chan struct{}
5859

60+
startUpSync atomic.Bool
61+
5962
client *adcclient.Client
6063
}
6164

@@ -159,6 +162,11 @@ func (d *api7eeProvider) Update(ctx context.Context, tctx *provider.TranslateCon
159162
},
160163
}
161164

165+
if !d.startUpSync.Load() {
166+
log.Debugw("startup synchronization not completed, skip sync", zap.Any("object", obj))
167+
return d.client.UpdateConfig(ctx, task)
168+
}
169+
162170
return d.client.Update(ctx, task)
163171
}
164172

@@ -204,6 +212,12 @@ func (d *api7eeProvider) Delete(ctx context.Context, obj client.Object) error {
204212
func (d *api7eeProvider) Start(ctx context.Context) error {
205213
d.readier.WaitReady(ctx, 5*time.Minute)
206214

215+
d.startUpSync.Store(true)
216+
log.Info("Performing startup synchronization")
217+
if err := d.sync(ctx); err != nil {
218+
log.Warnw("failed to sync for startup", zap.Error(err))
219+
}
220+
207221
initalSyncDelay := d.InitSyncDelay
208222
if initalSyncDelay > 0 {
209223
time.AfterFunc(initalSyncDelay, func() {

test/e2e/crds/v2/route.go

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,86 @@ spec:
460460
})
461461
})
462462

463+
Context("Ingress Scale and Route Management", func() {
464+
It("should handle ApisixRoute management during ingress scaling", func() {
465+
const apisixRouteSpec1 = `
466+
apiVersion: apisix.apache.org/v2
467+
kind: ApisixRoute
468+
metadata:
469+
name: route1
470+
spec:
471+
ingressClassName: apisix
472+
http:
473+
- name: rule1
474+
match:
475+
hosts:
476+
- httpbin
477+
paths:
478+
- /get
479+
backends:
480+
- serviceName: httpbin-service-e2e-test
481+
servicePort: 80
482+
`
483+
484+
const apisixRouteSpec2 = `
485+
apiVersion: apisix.apache.org/v2
486+
kind: ApisixRoute
487+
metadata:
488+
name: route2
489+
spec:
490+
ingressClassName: apisix
491+
http:
492+
- name: rule2
493+
match:
494+
hosts:
495+
- httpbin
496+
paths:
497+
- /anything
498+
backends:
499+
- serviceName: httpbin-service-e2e-test
500+
servicePort: 80
501+
`
502+
503+
request := func(path string) int {
504+
return s.NewAPISIXClient().GET(path).WithHost("httpbin").Expect().Raw().StatusCode
505+
}
506+
507+
By("apply first ApisixRoute")
508+
var apisixRoute1 apiv2.ApisixRoute
509+
applier.MustApplyAPIv2(types.NamespacedName{Namespace: s.Namespace(), Name: "route1"}, &apisixRoute1, apisixRouteSpec1)
510+
511+
By("apply second ApisixRoute")
512+
var apisixRoute2 apiv2.ApisixRoute
513+
applier.MustApplyAPIv2(types.NamespacedName{Namespace: s.Namespace(), Name: "route2"}, &apisixRoute2, apisixRouteSpec2)
514+
515+
By("verify both ApisixRoutes work")
516+
Eventually(request).WithArguments("/get").WithTimeout(8 * time.Second).ProbeEvery(time.Second).Should(Equal(http.StatusOK))
517+
Eventually(request).WithArguments("/anything").WithTimeout(8 * time.Second).ProbeEvery(time.Second).Should(Equal(http.StatusOK))
518+
519+
By("scale ingress to 0")
520+
s.Deployer.ScaleIngress(0)
521+
522+
By("delete first ApisixRoute")
523+
err := s.DeleteResource("ApisixRoute", "route1")
524+
Expect(err).ShouldNot(HaveOccurred(), "deleting ApisixRoute route1")
525+
526+
By("verify both routes still accessible during scale-down")
527+
Eventually(request).WithArguments("/get").WithTimeout(8 * time.Second).ProbeEvery(time.Second).Should(Equal(http.StatusOK))
528+
Eventually(request).WithArguments("/anything").WithTimeout(8 * time.Second).ProbeEvery(time.Second).Should(Equal(http.StatusOK))
529+
530+
By("scale ingress back to 1")
531+
s.Deployer.ScaleIngress(1)
532+
533+
By("verify first route is gone and second route still accessible after scale-up")
534+
Eventually(request).WithArguments("/get").WithTimeout(30 * time.Second).ProbeEvery(time.Second).Should(Equal(http.StatusNotFound))
535+
Eventually(request).WithArguments("/anything").WithTimeout(30 * time.Second).ProbeEvery(time.Second).Should(Equal(http.StatusOK))
536+
537+
routes, err := s.DefaultDataplaneResource().Route().List(context.Background())
538+
Expect(err).NotTo(HaveOccurred(), "list routes error")
539+
Expect(routes).To(HaveLen(1), "routes number not expect")
540+
})
541+
})
542+
463543
Context("Test ApisixRoute reference ApisixUpstream", func() {
464544
It("Test reference ApisixUpstream", func() {
465545
const apisixRouteSpec = `

test/e2e/framework/ingress.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ type IngressDeployOpts struct {
4949
ProviderSyncPeriod time.Duration
5050
Namespace string
5151
StatusAddress string
52-
Replicas int
52+
Replicas *int
5353
InitSyncDelay time.Duration
5454
}
5555

test/e2e/framework/manifests/ingress.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,15 @@ data:
334334
log_level: "debug"
335335
controller_name: {{ .ControllerName | default "apisix.apache.org/apisix-ingress-controller" }}
336336
leader_election_id: "apisix-ingress-controller-leader"
337+
leader_election:
338+
lease_duration: 10s # lease_duration is the duration that non-leader candidates will wait
339+
# after observing a leadership renewal until attempting to acquire leadership of a
340+
# leader election.
341+
renew_deadline: 5s # renew_deadline is the time in seconds that the acting controller
342+
# will retry refreshing leadership before giving up.
343+
retry_period: 2s # retry_period is the time in seconds that the acting controller
344+
# will wait between tries of actions with the controller.
345+
disable: false # Whether to disable leader election.
337346
exec_adc_timeout: 5s
338347
provider:
339348
type: {{ .ProviderType | default "apisix-standalone" }}

test/e2e/gatewayapi/httproute.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -609,10 +609,11 @@ spec:
609609
})
610610

611611
s.RequestAssert(&scaffold.RequestAssert{
612-
Method: "GET",
613-
Path: "/get",
614-
Host: "httpbin2.example",
615-
Check: scaffold.WithExpectedStatus(http.StatusNotFound),
612+
Method: "GET",
613+
Path: "/get",
614+
Host: "httpbin2.example",
615+
Timeout: 1 * time.Minute,
616+
Check: scaffold.WithExpectedStatus(http.StatusNotFound),
616617
})
617618
})
618619
})

test/e2e/scaffold/api7_deployer.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ func (s *API7Deployer) DeployIngress() {
207207
ProviderType: "api7ee",
208208
ControllerName: s.opts.ControllerName,
209209
Namespace: s.namespace,
210-
Replicas: 1,
210+
Replicas: ptr.To(1),
211211
})
212212
}
213213

@@ -216,7 +216,7 @@ func (s *API7Deployer) ScaleIngress(replicas int) {
216216
ProviderType: "api7ee",
217217
ControllerName: s.opts.ControllerName,
218218
Namespace: s.namespace,
219-
Replicas: replicas,
219+
Replicas: ptr.To(replicas),
220220
})
221221
}
222222

test/e2e/scaffold/apisix_deployer.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ func (s *APISIXDeployer) DeployIngress() {
265265
ProviderType: framework.ProviderType,
266266
ProviderSyncPeriod: syncPeriod,
267267
Namespace: s.namespace,
268-
Replicas: 1,
268+
Replicas: ptr.To(1),
269269
})
270270
}
271271

@@ -279,7 +279,7 @@ func (s *APISIXDeployer) ScaleIngress(replicas int) {
279279
ProviderType: framework.ProviderType,
280280
ProviderSyncPeriod: syncPeriod,
281281
Namespace: s.namespace,
282-
Replicas: replicas,
282+
Replicas: &replicas,
283283
})
284284
}
285285

0 commit comments

Comments
 (0)