Skip to content

Commit 8617e75

Browse files
ivanmatmatioktalz
authored andcommitted
MINOR: check GW API crd version
1 parent 530b75a commit 8617e75

File tree

6 files changed

+86
-19
lines changed

6 files changed

+86
-19
lines changed

go.mod

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ require (
1616
github.com/valyala/fasthttp v1.47.0
1717
go.uber.org/automaxprocs v1.5.2
1818
k8s.io/api v0.27.2
19+
k8s.io/apiextensions-apiserver v0.27.2
1920
k8s.io/apimachinery v0.27.2
2021
k8s.io/client-go v0.27.2
2122
sigs.k8s.io/controller-runtime v0.15.0

go.sum

+1
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,7 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
542542
k8s.io/api v0.27.2 h1:+H17AJpUMvl+clT+BPnKf0E3ksMAzoBBg7CntpSuADo=
543543
k8s.io/api v0.27.2/go.mod h1:ENmbocXfBT2ADujUXcBhHV55RIT31IIEvkntP6vZKS4=
544544
k8s.io/apiextensions-apiserver v0.27.2 h1:iwhyoeS4xj9Y7v8YExhUwbVuBhMr3Q4bd/laClBV6Bo=
545+
k8s.io/apiextensions-apiserver v0.27.2/go.mod h1:Oz9UdvGguL3ULgRdY9QMUzL2RZImotgxvGjdWRq6ZXQ=
545546
k8s.io/apimachinery v0.27.2 h1:vBjGaKKieaIreI+oQwELalVG4d8f3YAMNpWLzDXkxeg=
546547
k8s.io/apimachinery v0.27.2/go.mod h1:XNfZ6xklnMCOGGFNqXG7bUrQCoR04dh/E7FprV6pb+E=
547548
k8s.io/client-go v0.27.2 h1:vDLSeuYvCHKeoQRhCXjxXO45nHVv2Ip4Fe0MfioMrhE=

main.go

+5-2
Original file line numberDiff line numberDiff line change
@@ -119,9 +119,12 @@ func main() {
119119
WithRestClientSet(k.GetRestClientset()).
120120
WithArgs(osArgs).Build()
121121

122-
go k.MonitorChanges(eventChan, stop, osArgs)
123-
go c.Start()
122+
isGatewayAPIInstalled := k.IsGatewayAPIInstalled(osArgs.GatewayControllerName)
123+
124+
c.SetGatewayAPIInstalled(isGatewayAPIInstalled)
124125

126+
go k.MonitorChanges(eventChan, stop, osArgs, isGatewayAPIInstalled)
127+
go c.Start()
125128
// Catch QUIT signals
126129
signalC := make(chan os.Signal, 1)
127130
signal.Notify(signalC, os.Interrupt, syscall.SIGTERM, syscall.SIGUSR1)

pkg/controller/controller.go

+4
Original file line numberDiff line numberDiff line change
@@ -298,3 +298,7 @@ func (c *HAProxyController) clean(failedSync bool) {
298298
c.reload = false
299299
c.restart = false
300300
}
301+
302+
func (c *HAProxyController) SetGatewayAPIInstalled(gatewayAPIInstalled bool) {
303+
c.gatewayManager.SetGatewayAPIInstalled(gatewayAPIInstalled)
304+
}

pkg/gateways/gateways.go

+19-10
Original file line numberDiff line numberDiff line change
@@ -47,14 +47,15 @@ const (
4747
//nolint:golint
4848
type GatewayManager interface {
4949
ManageGateway() bool
50+
SetGatewayAPIInstalled(bool)
5051
}
5152

5253
func New(k8sStore store.K8s,
5354
haproxyClient api.HAProxyClient,
5455
osArgs utils.OSArgs,
5556
k8sRestClient client.Client,
5657
) GatewayManager {
57-
return GatewayManagerImpl{
58+
return &GatewayManagerImpl{
5859
k8sStore: k8sStore,
5960
haproxyClient: haproxyClient,
6061
osArgs: osArgs,
@@ -69,18 +70,22 @@ func New(k8sStore store.K8s,
6970

7071
//nolint:golint
7172
type GatewayManagerImpl struct {
72-
haproxyClient api.HAProxyClient
73-
statusManager StatusManager
74-
frontends map[string]struct{}
75-
gateways map[string]struct{}
76-
listenersByRoute map[string][]store.Listener
77-
backends map[string]struct{}
78-
serversByBackend map[string][]string
79-
k8sStore store.K8s
80-
osArgs utils.OSArgs
73+
haproxyClient api.HAProxyClient
74+
statusManager StatusManager
75+
frontends map[string]struct{}
76+
gateways map[string]struct{}
77+
listenersByRoute map[string][]store.Listener
78+
backends map[string]struct{}
79+
serversByBackend map[string][]string
80+
k8sStore store.K8s
81+
osArgs utils.OSArgs
82+
gatewayAPIInstalled bool
8183
}
8284

8385
func (gm GatewayManagerImpl) ManageGateway() bool {
86+
if gm.osArgs.GatewayControllerName == "" || !gm.gatewayAPIInstalled {
87+
return false
88+
}
8489
gm.clean()
8590
gm.manageGatewayClass()
8691

@@ -669,3 +674,7 @@ func (gm *GatewayManagerImpl) resetStatuses() {
669674
}
670675
}
671676
}
677+
678+
func (gm *GatewayManagerImpl) SetGatewayAPIInstalled(gatewayAPIInstalled bool) {
679+
gm.gatewayAPIInstalled = gatewayAPIInstalled
680+
}

pkg/k8s/main.go

+56-7
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
package k8s
1616

1717
import (
18+
"context"
1819
"errors"
1920
"os"
2021
"path/filepath"
@@ -31,6 +32,9 @@ import (
3132
crinformers "github.com/haproxytech/kubernetes-ingress/crs/generated/informers/externalversions"
3233
"github.com/haproxytech/kubernetes-ingress/pkg/ingress"
3334
"github.com/haproxytech/kubernetes-ingress/pkg/utils"
35+
crdclientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
36+
errGw "k8s.io/apimachinery/pkg/api/errors"
37+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3438
"sigs.k8s.io/controller-runtime/pkg/client"
3539
gatewayclientset "sigs.k8s.io/gateway-api/pkg/client/clientset/versioned"
3640
scheme "sigs.k8s.io/gateway-api/pkg/client/clientset/versioned/scheme"
@@ -44,15 +48,17 @@ const (
4448
TRACE_API = false //nolint:golint,stylecheck
4549
CRSGroupVersionV1alpha1 = "core.haproxy.org/v1alpha1"
4650
CRSGroupVersionV1alpha2 = "core.haproxy.org/v1alpha2"
51+
GATEWAY_API_VERSION = "v0.5.1" //nolint:golint,stylecheck
4752
)
4853

4954
var ErrIgnored = errors.New("ignored resource")
5055

5156
type K8s interface {
5257
GetRestClientset() client.Client
5358
GetClientset() *k8sclientset.Clientset
54-
MonitorChanges(eventChan chan SyncDataEvent, stop chan struct{}, osArgs utils.OSArgs)
59+
MonitorChanges(eventChan chan SyncDataEvent, stop chan struct{}, osArgs utils.OSArgs, gatewayAPIInstalled bool)
5560
UpdatePublishService(ingresses []*ingress.Ingress, publishServiceAddresses []string)
61+
IsGatewayAPIInstalled(gatewayControllerName string) bool
5662
}
5763

5864
// A Custom Resource interface
@@ -77,6 +83,8 @@ type k8s struct {
7783
syncPeriod time.Duration
7884
cacheResyncPeriod time.Duration
7985
disableSvcExternalName bool // CVE-2021-25740
86+
crdClient *crdclientset.Clientset
87+
gatewayAPIInstalled bool
8088
}
8189

8290
func New(osArgs utils.OSArgs, whitelist map[string]struct{}, publishSvc *utils.NamespaceValue) K8s { //nolint:ireturn
@@ -104,6 +112,11 @@ func New(osArgs utils.OSArgs, whitelist map[string]struct{}, publishSvc *utils.N
104112
logger.Print("Gateway API not present")
105113
}
106114

115+
crdClient, err := crdclientset.NewForConfig(restconfig)
116+
if err != nil {
117+
logger.Error("CRD API client not present")
118+
}
119+
107120
prefix, _ := utils.GetPodPrefix(os.Getenv("POD_NAME"))
108121
k := k8s{
109122
builtInClient: builtInClient,
@@ -118,6 +131,7 @@ func New(osArgs utils.OSArgs, whitelist map[string]struct{}, publishSvc *utils.N
118131
disableSvcExternalName: osArgs.DisableServiceExternalName,
119132
gatewayClient: gatewayClient,
120133
gatewayRestClient: gatewayRestClient,
134+
crdClient: crdClient,
121135
}
122136
// alpha1 is deprecated
123137
k.registerCoreCR(NewGlobalCRV1Alpha1(), CRSGroupVersionV1alpha1)
@@ -145,14 +159,13 @@ func (k k8s) UpdatePublishService(ingresses []*ingress.Ingress, publishServiceAd
145159
}
146160
}
147161

148-
func (k k8s) MonitorChanges(eventChan chan SyncDataEvent, stop chan struct{}, osArgs utils.OSArgs) {
162+
func (k k8s) MonitorChanges(eventChan chan SyncDataEvent, stop chan struct{}, osArgs utils.OSArgs, gatewayAPIInstalled bool) {
149163
informersSynced := &[]cache.InformerSynced{}
150-
needGatewayAPIInformers := k.isGatewayAPIInstalled() && osArgs.GatewayControllerName != ""
151164
k.runPodInformer(eventChan, stop, informersSynced)
152165
for _, namespace := range k.whiteListedNS {
153166
k.runInformers(eventChan, stop, namespace, informersSynced)
154167
k.runCRInformers(eventChan, stop, namespace, informersSynced)
155-
if needGatewayAPIInformers {
168+
if gatewayAPIInstalled {
156169
k.runInformersGwAPI(eventChan, stop, namespace, informersSynced)
157170
}
158171
}
@@ -320,7 +333,43 @@ func getWhitelistedNS(whitelist map[string]struct{}, cfgMapNS string) []string {
320333
return namespaces
321334
}
322335

323-
func (k k8s) isGatewayAPIInstalled() bool {
324-
_, err := k.crClient.DiscoveryClient.ServerResourcesForGroupVersion("gateway.networking.k8s.io/v1beta1")
325-
return err == nil
336+
func (k k8s) IsGatewayAPIInstalled(gatewayControllerName string) (installed bool) {
337+
installed = true
338+
defer func() {
339+
k.gatewayAPIInstalled = installed
340+
}()
341+
gatewayCrd, err := k.crdClient.ApiextensionsV1().CustomResourceDefinitions().Get(context.Background(), "gateways.gateway.networking.k8s.io", metav1.GetOptions{})
342+
if err != nil {
343+
var errStatus *errGw.StatusError
344+
if !errors.As(err, &errStatus) || errStatus.ErrStatus.Code != 404 {
345+
logger.Error(err)
346+
return false
347+
}
348+
}
349+
350+
if gatewayCrd.Name == "" {
351+
if gatewayControllerName != "" {
352+
logger.Errorf("No gateway api is installed, please install experimental yaml version %s", GATEWAY_API_VERSION)
353+
}
354+
return false
355+
}
356+
357+
log := logger.Warningf
358+
if gatewayControllerName != "" {
359+
log = logger.Errorf
360+
}
361+
362+
version := gatewayCrd.Annotations["gateway.networking.k8s.io/bundle-version"]
363+
if version != GATEWAY_API_VERSION {
364+
log("Unsupported version '%s' of gateway api is installed, please install experimental yaml version %s", version, GATEWAY_API_VERSION)
365+
installed = false
366+
}
367+
368+
// gatewayCrd is not nil so gateway API is present
369+
tcprouteCrd, err := k.crdClient.ApiextensionsV1().CustomResourceDefinitions().Get(context.Background(), "tcproutes.gateway.networking.k8s.io", metav1.GetOptions{})
370+
if tcprouteCrd == nil || err != nil {
371+
log("No tcproute crd is installed, please install experimental yaml version %s", GATEWAY_API_VERSION)
372+
installed = false
373+
}
374+
return
326375
}

0 commit comments

Comments
 (0)