Skip to content

Commit 0a97f82

Browse files
authored
chore: use adc dump instead of apisixCli (#162)
1 parent 9a9af12 commit 0a97f82

10 files changed

Lines changed: 305 additions & 70 deletions

File tree

.github/workflows/e2e-test.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,18 @@ jobs:
7070
echo "building images..."
7171
make build-image
7272
73+
- name: Build Dockerfile.dev and extract adc binary
74+
run: |
75+
echo "Building Dockerfile.dev..."
76+
docker build -f Dockerfile.dev -t adc-builder:latest .
77+
echo "Extracting adc binary..."
78+
docker run --name adc-temp --entrypoint="" adc-builder:latest /bin/true
79+
docker cp adc-temp:/bin/adc ./bin/adc
80+
docker rm adc-temp
81+
chmod +x ./bin/adc
82+
mv ./bin/adc /usr/local/bin/adc
83+
echo "ADC binary extracted to /usr/local/bin/adc"
84+
7385
- name: Launch Kind Cluster
7486
run: |
7587
make kind-up

Dockerfile.dev

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ ARG ENABLE_PROXY=false
33
FROM node:22 AS node_builder
44

55
ARG TARGETARCH
6-
ARG ADC_COMMIT=78484e87a0168e0f86d130bfae8f808d0d1a1e41
6+
ARG ADC_COMMIT=e948079ed0576dbac29320ebfa01c9b7a298924c
77

88
WORKDIR /app
99

@@ -22,10 +22,13 @@ RUN apt update \
2222
&& rm -rf /app
2323

2424
FROM debian:bullseye-slim
25+
26+
ARG TARGETARCH
27+
2528
WORKDIR /app
2629

2730
COPY --from=node_builder /bin/adc /bin/adc
28-
COPY ./bin/apisix-ingress-controller .
31+
COPY ./bin/apisix-ingress-controller_${TARGETARCH} ./apisix-ingress-controller
2932
COPY ./config/samples/config.yaml ./conf/config.yaml
3033

3134
ENTRYPOINT ["/app/apisix-ingress-controller"]

test/e2e/framework/manifests/apisix-standalone.yaml

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,20 @@ metadata:
44
name: apisix-conf
55
data:
66
config.yaml: |
7-
apisix:
8-
enable_admin: true
9-
admin_key:
10-
- name: admin
11-
key: {{ .AdminKey }}
12-
role: admin
13-
ssl:
14-
enabled: true
15-
nginx_config:
16-
worker_processes: 2
17-
error_log_level: info
187
deployment:
198
role: traditional
209
role_traditional:
2110
config_provider: yaml
11+
admin:
12+
allow_admin:
13+
- 0.0.0.0/0
14+
admin_key:
15+
- key: {{ .AdminKey }}
16+
name: admin
17+
role: admin
18+
nginx_config:
19+
worker_processes: 2
20+
error_log_level: info
2221
---
2322
apiVersion: apps/v1
2423
kind: Deployment

test/e2e/gatewayapi/gateway.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,8 @@ spec:
204204
tls, err := s.DefaultDataplaneResource().SSL().List(context.Background())
205205
assert.Nil(GinkgoT(), err, "list tls error")
206206
assert.Len(GinkgoT(), tls, 1, "tls number not expect")
207-
assert.Equal(GinkgoT(), Cert, tls[0].Cert, "tls cert not expect")
207+
assert.Len(GinkgoT(), tls[0].Certificates, 1, "length of certificates not expect")
208+
assert.Equal(GinkgoT(), Cert, tls[0].Certificates[0].Certificate, "tls cert not expect")
208209
assert.ElementsMatch(GinkgoT(), []string{host, "*.api6.com"}, tls[0].Snis)
209210
})
210211

@@ -277,7 +278,8 @@ spec:
277278
tls, err := s.DefaultDataplaneResource().SSL().List(context.Background())
278279
assert.Nil(GinkgoT(), err, "list tls error")
279280
assert.Len(GinkgoT(), tls, 1, "tls number not expect")
280-
assert.Equal(GinkgoT(), Cert, tls[0].Cert, "tls cert not expect")
281+
assert.Len(GinkgoT(), tls[0].Certificates, 1, "length of certificates not expect")
282+
assert.Equal(GinkgoT(), Cert, tls[0].Certificates[0].Certificate, "tls cert not expect")
281283
assert.Equal(GinkgoT(), tls[0].Labels["k8s/controller-name"], "apisix.apache.org/apisix-ingress-controller")
282284

283285
By("update secret")
@@ -289,7 +291,10 @@ spec:
289291
if len(tls) < 1 {
290292
return ""
291293
}
292-
return tls[0].Cert
294+
if len(tls[0].Certificates) < 1 {
295+
return ""
296+
}
297+
return tls[0].Certificates[0].Certificate
293298
}).WithTimeout(8 * time.Second).ProbeEvery(time.Second).Should(Equal(framework.TestCert))
294299
})
295300
})

test/e2e/ingress/ingress.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,8 @@ spec:
131131
tls, err := s.DefaultDataplaneResource().SSL().List(context.Background())
132132
assert.Nil(GinkgoT(), err, "list tls error")
133133
assert.Len(GinkgoT(), tls, 1, "tls number not expect")
134-
assert.Equal(GinkgoT(), Cert, tls[0].Cert, "tls cert not expect")
134+
assert.Len(GinkgoT(), tls[0].Certificates, 1, "length of certificates not expect")
135+
assert.Equal(GinkgoT(), Cert, tls[0].Certificates[0].Certificate, "tls cert not expect")
135136
assert.ElementsMatch(GinkgoT(), []string{host}, tls[0].Snis)
136137
})
137138
})

test/e2e/scaffold/adc.go

Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
1+
// Licensed under the Apache License, Version 2.0 (the "License");
2+
// you may not use this file except in compliance with the License.
3+
// You may obtain a copy of the License at
4+
//
5+
// http://www.apache.org/licenses/LICENSE-2.0
6+
//
7+
// Unless required by applicable law or agreed to in writing, software
8+
// distributed under the License is distributed on an "AS IS" BASIS,
9+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+
// See the License for the specific language governing permissions and
11+
// limitations under the License.
12+
13+
package scaffold
14+
15+
import (
16+
"bytes"
17+
"context"
18+
"errors"
19+
"os"
20+
"os/exec"
21+
"time"
22+
23+
"github.com/api7/gopkg/pkg/log"
24+
"go.uber.org/zap"
25+
"gopkg.in/yaml.v3"
26+
27+
adctypes "github.com/apache/apisix-ingress-controller/api/adc"
28+
"github.com/apache/apisix-ingress-controller/internal/provider/adc/translator"
29+
)
30+
31+
// DataplaneResource defines the interface for accessing dataplane resources
32+
type DataplaneResource interface {
33+
Route() RouteResource
34+
Service() ServiceResource
35+
SSL() SSLResource
36+
Consumer() ConsumerResource
37+
}
38+
39+
// RouteResource defines the interface for route resources
40+
type RouteResource interface {
41+
List(ctx context.Context) ([]*adctypes.Route, error)
42+
}
43+
44+
// ServiceResource defines the interface for service resources
45+
type ServiceResource interface {
46+
List(ctx context.Context) ([]*adctypes.Service, error)
47+
}
48+
49+
// SSLResource defines the interface for SSL resources
50+
type SSLResource interface {
51+
List(ctx context.Context) ([]*adctypes.SSL, error)
52+
}
53+
54+
// ConsumerResource defines the interface for consumer resources
55+
type ConsumerResource interface {
56+
List(ctx context.Context) ([]*adctypes.Consumer, error)
57+
}
58+
59+
// adcDataplaneResource implements DataplaneResource using ADC command
60+
type adcDataplaneResource struct {
61+
backend string
62+
serverAddr string
63+
token string
64+
tlsVerify bool
65+
syncTimeout time.Duration
66+
}
67+
68+
// newADCDataplaneResource creates a new ADC-based dataplane resource
69+
func newADCDataplaneResource(backend, serverAddr, token string, tlsVerify bool) DataplaneResource {
70+
return &adcDataplaneResource{
71+
backend: backend,
72+
serverAddr: serverAddr,
73+
token: token,
74+
tlsVerify: tlsVerify,
75+
syncTimeout: 30 * time.Second,
76+
}
77+
}
78+
79+
func (a *adcDataplaneResource) Route() RouteResource {
80+
return &adcRouteResource{a}
81+
}
82+
83+
func (a *adcDataplaneResource) Service() ServiceResource {
84+
return &adcServiceResource{a}
85+
}
86+
87+
func (a *adcDataplaneResource) SSL() SSLResource {
88+
return &adcSSLResource{a}
89+
}
90+
91+
func (a *adcDataplaneResource) Consumer() ConsumerResource {
92+
return &adcConsumerResource{a}
93+
}
94+
95+
func init() {
96+
// dashboard sdk log
97+
l, err := log.NewLogger(
98+
log.WithOutputFile("stderr"),
99+
log.WithLogLevel("debug"),
100+
log.WithSkipFrames(3),
101+
)
102+
if err != nil {
103+
panic(err)
104+
}
105+
log.DefaultLogger = l
106+
}
107+
108+
// dumpResources executes adc dump command and returns the resources
109+
func (a *adcDataplaneResource) dumpResources(ctx context.Context) (*translator.TranslateResult, error) {
110+
ctxWithTimeout, cancel := context.WithTimeout(ctx, a.syncTimeout)
111+
defer cancel()
112+
113+
// Create a temporary file for the adc dump
114+
tempFile, err := os.CreateTemp("", "adc-dump-*.yaml")
115+
if err != nil {
116+
return nil, err
117+
}
118+
defer func() {
119+
_ = tempFile.Close()
120+
_ = os.Remove(tempFile.Name())
121+
}()
122+
123+
args := []string{"dump", "-o", tempFile.Name()}
124+
if !a.tlsVerify {
125+
args = append(args, "--tls-skip-verify")
126+
}
127+
128+
adcEnv := []string{
129+
"ADC_RUNNING_MODE=", // need to set empty
130+
"ADC_BACKEND=" + a.backend,
131+
"ADC_SERVER=" + a.serverAddr,
132+
"ADC_TOKEN=" + a.token,
133+
}
134+
135+
var stdout, stderr bytes.Buffer
136+
cmd := exec.CommandContext(ctxWithTimeout, "adc", args...)
137+
cmd.Stdout = &stdout
138+
cmd.Stderr = &stderr
139+
cmd.Env = append(cmd.Env, os.Environ()...)
140+
cmd.Env = append(cmd.Env, adcEnv...)
141+
142+
log.Debug("running adc command", zap.String("command", cmd.String()), zap.Strings("env", adcEnv))
143+
144+
if err := cmd.Run(); err != nil {
145+
stderrStr := stderr.String()
146+
stdoutStr := stdout.String()
147+
errMsg := stderrStr
148+
if errMsg == "" {
149+
errMsg = stdoutStr
150+
}
151+
log.Errorw("failed to run adc",
152+
zap.Error(err),
153+
zap.String("output", stdoutStr),
154+
zap.String("stderr", stderrStr),
155+
)
156+
return nil, errors.New("failed to dump resources: " + errMsg + ", exit err: " + err.Error())
157+
}
158+
159+
// Read the YAML file that was created by adc dump
160+
yamlData, err := os.ReadFile(tempFile.Name())
161+
if err != nil {
162+
return nil, err
163+
}
164+
165+
var resources adctypes.Resources
166+
if err := yaml.Unmarshal(yamlData, &resources); err != nil {
167+
return nil, err
168+
}
169+
170+
// Extract routes from services
171+
var routes []*adctypes.Route
172+
for _, service := range resources.Services {
173+
routes = append(routes, service.Routes...)
174+
}
175+
176+
return &translator.TranslateResult{
177+
Routes: routes,
178+
Services: resources.Services,
179+
SSL: resources.SSLs,
180+
GlobalRules: resources.GlobalRules,
181+
PluginMetadata: resources.PluginMetadata,
182+
Consumers: resources.Consumers,
183+
}, nil
184+
}
185+
186+
// adcRouteResource implements RouteResource
187+
type adcRouteResource struct {
188+
*adcDataplaneResource
189+
}
190+
191+
func (r *adcRouteResource) List(ctx context.Context) ([]*adctypes.Route, error) {
192+
result, err := r.dumpResources(ctx)
193+
if err != nil {
194+
return nil, err
195+
}
196+
return result.Routes, nil
197+
}
198+
199+
// adcServiceResource implements ServiceResource
200+
type adcServiceResource struct {
201+
*adcDataplaneResource
202+
}
203+
204+
func (s *adcServiceResource) List(ctx context.Context) ([]*adctypes.Service, error) {
205+
result, err := s.dumpResources(ctx)
206+
if err != nil {
207+
return nil, err
208+
}
209+
return result.Services, nil
210+
}
211+
212+
// adcSSLResource implements SSLResource
213+
type adcSSLResource struct {
214+
*adcDataplaneResource
215+
}
216+
217+
func (s *adcSSLResource) List(ctx context.Context) ([]*adctypes.SSL, error) {
218+
result, err := s.dumpResources(ctx)
219+
if err != nil {
220+
return nil, err
221+
}
222+
return result.SSL, nil
223+
}
224+
225+
// adcConsumerResource implements ConsumerResource
226+
type adcConsumerResource struct {
227+
*adcDataplaneResource
228+
}
229+
230+
func (c *adcConsumerResource) List(ctx context.Context) ([]*adctypes.Consumer, error) {
231+
result, err := c.dumpResources(ctx)
232+
if err != nil {
233+
return nil, err
234+
}
235+
return result.Consumers, nil
236+
}

0 commit comments

Comments
 (0)