Skip to content

Commit b47ed04

Browse files
authored
feat: add unified API server with debugging capabilities (#2550)
1 parent 7fee6bd commit b47ed04

File tree

10 files changed

+445
-7
lines changed

10 files changed

+445
-7
lines changed

config/samples/config.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ leader_election:
1818

1919
metrics_addr: ":8080" # The address the metrics endpoint binds to.
2020
# The default value is ":8080".
21+
enable_server: false # The debug API is behind this server which is disabled by default for security reasons.
22+
server_addr: "127.0.0.1:9092" # Available endpoints: /debug can be used to debug in-memory state of translated adc configs to be synced with data plane.
2123

2224
enable_http2: false # Whether to enable HTTP/2 for the server.
2325
# The default value is false.

internal/adc/client/client.go

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,21 +45,24 @@ type Client struct {
4545
executor ADCExecutor
4646
BackendMode string
4747

48-
ConfigManager *common.ConfigManager[types.NamespacedNameKind, adctypes.Config]
48+
ConfigManager *common.ConfigManager[types.NamespacedNameKind, adctypes.Config]
49+
ADCDebugProvider *common.ADCDebugProvider
4950
}
5051

5152
func New(mode string, timeout time.Duration) (*Client, error) {
5253
serverURL := os.Getenv("ADC_SERVER_URL")
5354
if serverURL == "" {
5455
serverURL = defaultHTTPADCExecutorAddr
5556
}
56-
57+
store := cache.NewStore()
58+
configManager := common.NewConfigManager[types.NamespacedNameKind, adctypes.Config]()
5759
log.Infow("using HTTP ADC Executor", zap.String("server_url", serverURL))
5860
return &Client{
59-
Store: cache.NewStore(),
60-
executor: NewHTTPADCExecutor(serverURL, timeout),
61-
BackendMode: mode,
62-
ConfigManager: common.NewConfigManager[types.NamespacedNameKind, adctypes.Config](),
61+
Store: store,
62+
executor: NewHTTPADCExecutor(serverURL, timeout),
63+
BackendMode: mode,
64+
ConfigManager: configManager,
65+
ADCDebugProvider: common.NewADCDebugProvider(store, configManager),
6366
}, nil
6467
}
6568

internal/controller/config/config.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ func NewDefaultConfig() *Config {
4848
LeaderElectionID: DefaultLeaderElectionID,
4949
ProbeAddr: DefaultProbeAddr,
5050
MetricsAddr: DefaultMetricsAddr,
51+
ServerAddr: DefaultServerAddr,
5152
LeaderElection: NewLeaderElection(),
5253
ExecADCTimeout: types.TimeDuration{Duration: 15 * time.Second},
5354
ProviderConfig: ProviderConfig{

internal/controller/config/types.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ const (
4343

4444
DefaultMetricsAddr = ":8080"
4545
DefaultProbeAddr = ":8081"
46+
DefaultServerAddr = ":9092"
4647
)
4748

4849
// Config contains all config items which are necessary for
@@ -52,6 +53,8 @@ type Config struct {
5253
ControllerName string `json:"controller_name" yaml:"controller_name"`
5354
LeaderElectionID string `json:"leader_election_id" yaml:"leader_election_id"`
5455
MetricsAddr string `json:"metrics_addr" yaml:"metrics_addr"`
56+
ServerAddr string `json:"server_addr" yaml:"server_addr"`
57+
EnableServer bool `json:"enable_server" yaml:"enable_server"`
5558
EnableHTTP2 bool `json:"enable_http2" yaml:"enable_http2"`
5659
ProbeAddr string `json:"probe_addr" yaml:"probe_addr"`
5760
SecureMetrics bool `json:"secure_metrics" yaml:"secure_metrics"`

internal/manager/run.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ import (
4242
"github.com/apache/apisix-ingress-controller/internal/controller/config"
4343
"github.com/apache/apisix-ingress-controller/internal/controller/status"
4444
"github.com/apache/apisix-ingress-controller/internal/manager/readiness"
45+
"github.com/apache/apisix-ingress-controller/internal/manager/server"
4546
"github.com/apache/apisix-ingress-controller/internal/provider"
4647
_ "github.com/apache/apisix-ingress-controller/internal/provider/init"
4748
_ "github.com/apache/apisix-ingress-controller/pkg/metrics"
@@ -178,6 +179,14 @@ func Run(ctx context.Context, logger logr.Logger) error {
178179
return err
179180
}
180181

182+
if cfg.EnableServer {
183+
srv := server.NewServer(config.ControllerConfig.ServerAddr)
184+
srv.Register("/debug", provider)
185+
if err := mgr.Add(srv); err != nil {
186+
setupLog.Error(err, "unable to add debug server to manager")
187+
return err
188+
}
189+
}
181190
if err := mgr.Add(provider); err != nil {
182191
setupLog.Error(err, "unable to add provider to manager")
183192
return err

internal/manager/server/server.go

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
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 server
19+
20+
import (
21+
"context"
22+
"net/http"
23+
"time"
24+
25+
"github.com/apache/apisix-ingress-controller/internal/provider"
26+
)
27+
28+
type Server struct {
29+
server *http.Server
30+
mux *http.ServeMux
31+
}
32+
33+
func (s *Server) Start(ctx context.Context) error {
34+
stop := make(chan error, 1)
35+
go func() {
36+
if err := s.server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
37+
stop <- err
38+
}
39+
close(stop)
40+
}()
41+
select {
42+
case <-ctx.Done():
43+
shutdownCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
44+
defer cancel()
45+
return s.server.Shutdown(shutdownCtx)
46+
case err := <-stop:
47+
return err
48+
}
49+
}
50+
51+
func (s *Server) Register(pathPrefix string, registrant provider.RegisterHandler) {
52+
subMux := http.NewServeMux()
53+
registrant.Register(pathPrefix, subMux)
54+
s.mux.Handle(pathPrefix+"/", http.StripPrefix(pathPrefix, subMux))
55+
s.mux.HandleFunc(pathPrefix, func(w http.ResponseWriter, r *http.Request) {
56+
http.Redirect(w, r, pathPrefix+"/", http.StatusPermanentRedirect)
57+
})
58+
}
59+
60+
func NewServer(addr string) *Server {
61+
mux := http.NewServeMux()
62+
return &Server{
63+
server: &http.Server{
64+
Addr: addr,
65+
Handler: mux,
66+
},
67+
mux: mux,
68+
}
69+
}

internal/provider/apisix/provider.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package apisix
1919

2020
import (
2121
"context"
22+
"net/http"
2223
"sync"
2324
"time"
2425

@@ -89,6 +90,10 @@ func New(updater status.Updater, readier readiness.ReadinessManager, opts ...pro
8990
}, nil
9091
}
9192

93+
func (d *apisixProvider) Register(pathPrefix string, mux *http.ServeMux) {
94+
d.client.ADCDebugProvider.SetupHandler(pathPrefix, mux)
95+
}
96+
9297
func (d *apisixProvider) Update(ctx context.Context, tctx *provider.TranslateContext, obj client.Object) error {
9398
log.Debugw("updating object", zap.Any("object", obj))
9499
var (
@@ -231,7 +236,6 @@ func (d *apisixProvider) buildConfig(tctx *provider.TranslateContext, nnk types.
231236

232237
func (d *apisixProvider) Start(ctx context.Context) error {
233238
d.readier.WaitReady(ctx, 5*time.Minute)
234-
235239
initalSyncDelay := d.InitSyncDelay
236240
if initalSyncDelay > 0 {
237241
time.AfterFunc(initalSyncDelay, d.syncNotify)

0 commit comments

Comments
 (0)