Skip to content

Commit 130bc80

Browse files
authored
feat: support retry for full synchronization (#367)
1 parent 133ed58 commit 130bc80

File tree

4 files changed

+167
-18
lines changed

4 files changed

+167
-18
lines changed

internal/provider/api7ee/provider.go

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,18 @@ import (
3939
"github.com/apache/apisix-ingress-controller/internal/controller/status"
4040
"github.com/apache/apisix-ingress-controller/internal/manager/readiness"
4141
"github.com/apache/apisix-ingress-controller/internal/provider"
42+
"github.com/apache/apisix-ingress-controller/internal/provider/common"
4243
"github.com/apache/apisix-ingress-controller/internal/types"
4344
"github.com/apache/apisix-ingress-controller/internal/utils"
4445
pkgutils "github.com/apache/apisix-ingress-controller/pkg/utils"
4546
)
4647

47-
const ProviderTypeAPI7EE = "api7ee"
48+
const (
49+
ProviderTypeAPI7EE = "api7ee"
50+
51+
RetryBaseDelay = 1 * time.Second
52+
RetryMaxDelay = 1000 * time.Second
53+
)
4854

4955
type api7eeProvider struct {
5056
translator *translator.Translator
@@ -252,20 +258,23 @@ func (d *api7eeProvider) Start(ctx context.Context) error {
252258
}
253259
ticker := time.NewTicker(d.SyncPeriod)
254260
defer ticker.Stop()
261+
262+
retrier := common.NewRetrier(common.NewExponentialBackoff(RetryBaseDelay, RetryMaxDelay))
263+
255264
for {
256-
synced := false
257265
select {
258266
case <-d.syncCh:
259-
synced = true
267+
case <-retrier.C():
260268
case <-ticker.C:
261-
synced = true
262269
case <-ctx.Done():
263270
return nil
264271
}
265-
if synced {
266-
if err := d.sync(ctx); err != nil {
267-
d.log.Error(err, "failed to sync for startup")
268-
}
272+
273+
if err := d.sync(ctx); err != nil {
274+
d.log.Error(err, "failed to sync")
275+
retrier.Next()
276+
} else {
277+
retrier.Reset()
269278
}
270279
}
271280
}

test/e2e/api7/gatewayproxy.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
// specific language governing permissions and limitations
1616
// under the License.
1717

18-
package gatewayapi
18+
package api7
1919

2020
import (
2121
"fmt"

test/e2e/api7/route.go

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
package api7
19+
20+
import (
21+
"fmt"
22+
"time"
23+
24+
. "github.com/onsi/ginkgo/v2"
25+
. "github.com/onsi/gomega"
26+
27+
"github.com/apache/apisix-ingress-controller/test/e2e/scaffold"
28+
)
29+
30+
var _ = Describe("Test apisix.apache.org/v2 Status", Label("apisix.apache.org", "v2", "apisixroute"), func() {
31+
s := scaffold.NewDefaultScaffold()
32+
33+
Context("Test ApisixRoute Sync Status", func() {
34+
const (
35+
serviceSpec = `
36+
apiVersion: v1
37+
kind: Service
38+
metadata:
39+
name: api7ee3-dashboard
40+
spec:
41+
type: ExternalName
42+
externalName: %s
43+
`
44+
gatewayProxyYaml = `
45+
apiVersion: apisix.apache.org/v1alpha1
46+
kind: GatewayProxy
47+
metadata:
48+
name: apisix-proxy-config
49+
spec:
50+
provider:
51+
type: ControlPlane
52+
controlPlane:
53+
endpoints:
54+
- https://api7ee3-dashboard:7443
55+
auth:
56+
type: AdminKey
57+
adminKey:
58+
value: "%s"
59+
`
60+
ar = `
61+
apiVersion: apisix.apache.org/v2
62+
kind: ApisixRoute
63+
metadata:
64+
name: default
65+
namespace: %s
66+
spec:
67+
ingressClassName: %s
68+
http:
69+
- name: rule0
70+
match:
71+
hosts:
72+
- httpbin
73+
paths:
74+
- /*
75+
backends:
76+
- serviceName: httpbin-service-e2e-test
77+
servicePort: 80
78+
`
79+
)
80+
81+
It("dataplane unavailable", func() {
82+
s.Deployer.ScaleIngress(0)
83+
By("create GatewayProxy")
84+
err := s.CreateResourceFromString(fmt.Sprintf(gatewayProxyYaml, s.AdminKey()))
85+
Expect(err).NotTo(HaveOccurred(), "creating GatewayProxy")
86+
87+
By("create IngressClass")
88+
err = s.CreateResourceFromStringWithNamespace(s.GetIngressClassYaml(), "")
89+
Expect(err).NotTo(HaveOccurred(), "creating IngressClass")
90+
91+
By("create Service with invalid host")
92+
err = s.CreateResourceFromString(fmt.Sprintf(serviceSpec, "invalid.host"))
93+
Expect(err).NotTo(HaveOccurred(), "creating Service")
94+
95+
By("apply ApisixRoute")
96+
err = s.CreateResourceFromString(fmt.Sprintf(ar, s.Namespace(), s.Namespace()))
97+
Expect(err).NotTo(HaveOccurred(), "creating ApisixRoute")
98+
99+
s.Deployer.ScaleIngress(1)
100+
101+
By("check ApisixRoute status")
102+
s.RetryAssertion(func() string {
103+
output, _ := s.GetOutputFromString("ar", "default", "-o", "yaml", "-n", s.Namespace())
104+
return output
105+
}).WithTimeout(5 * time.Minute).
106+
Should(
107+
And(
108+
ContainSubstring(`status: "False"`),
109+
ContainSubstring(`reason: SyncFailed`),
110+
),
111+
)
112+
113+
By("update service to dashboard")
114+
err = s.CreateResourceFromString(fmt.Sprintf(serviceSpec, "api7ee3-dashboard.api7-ee-e2e.svc.cluster.local"))
115+
Expect(err).NotTo(HaveOccurred(), "updating Service")
116+
117+
By("check ApisixRoute status after scaling up")
118+
s.RetryAssertion(func() string {
119+
output, _ := s.GetOutputFromString("ar", "default", "-o", "yaml", "-n", s.Namespace())
120+
return output
121+
}).WithTimeout(60 * time.Second).
122+
Should(
123+
And(
124+
ContainSubstring(`status: "True"`),
125+
ContainSubstring(`reason: Accepted`),
126+
),
127+
)
128+
129+
By("check route in APISIX")
130+
s.RequestAssert(&scaffold.RequestAssert{
131+
Method: "GET",
132+
Path: "/get",
133+
Host: "httpbin",
134+
Check: scaffold.WithExpectedStatus(200),
135+
})
136+
})
137+
})
138+
})

test/e2e/scaffold/api7_deployer.go

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -193,20 +193,22 @@ func (s *API7Deployer) DeployIngress() {
193193
}
194194

195195
s.Framework.DeployIngress(framework.IngressDeployOpts{
196-
ProviderType: "api7ee",
197-
ControllerName: s.runtimeOpts.ControllerName,
198-
Namespace: s.namespace,
199-
Replicas: ptr.To(1),
200-
WebhookEnable: s.runtimeOpts.EnableWebhook,
196+
ProviderType: "api7ee",
197+
ControllerName: s.runtimeOpts.ControllerName,
198+
ProviderSyncPeriod: 1 * time.Hour,
199+
Namespace: s.namespace,
200+
Replicas: ptr.To(1),
201+
WebhookEnable: s.runtimeOpts.EnableWebhook,
201202
})
202203
}
203204

204205
func (s *API7Deployer) ScaleIngress(replicas int) {
205206
s.Framework.DeployIngress(framework.IngressDeployOpts{
206-
ProviderType: "api7ee",
207-
ControllerName: s.runtimeOpts.ControllerName,
208-
Namespace: s.namespace,
209-
Replicas: ptr.To(replicas),
207+
ProviderType: "api7ee",
208+
ControllerName: s.runtimeOpts.ControllerName,
209+
ProviderSyncPeriod: 1 * time.Hour,
210+
Namespace: s.namespace,
211+
Replicas: ptr.To(replicas),
210212
})
211213
}
212214

0 commit comments

Comments
 (0)