15
15
package k8s
16
16
17
17
import (
18
+ "context"
18
19
"errors"
19
20
"os"
20
21
"path/filepath"
@@ -31,6 +32,9 @@ import (
31
32
crinformers "github.com/haproxytech/kubernetes-ingress/crs/generated/informers/externalversions"
32
33
"github.com/haproxytech/kubernetes-ingress/pkg/ingress"
33
34
"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"
34
38
"sigs.k8s.io/controller-runtime/pkg/client"
35
39
gatewayclientset "sigs.k8s.io/gateway-api/pkg/client/clientset/versioned"
36
40
scheme "sigs.k8s.io/gateway-api/pkg/client/clientset/versioned/scheme"
@@ -44,15 +48,17 @@ const (
44
48
TRACE_API = false //nolint:golint,stylecheck
45
49
CRSGroupVersionV1alpha1 = "core.haproxy.org/v1alpha1"
46
50
CRSGroupVersionV1alpha2 = "core.haproxy.org/v1alpha2"
51
+ GATEWAY_API_VERSION = "v0.5.1" //nolint:golint,stylecheck
47
52
)
48
53
49
54
var ErrIgnored = errors .New ("ignored resource" )
50
55
51
56
type K8s interface {
52
57
GetRestClientset () client.Client
53
58
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 )
55
60
UpdatePublishService (ingresses []* ingress.Ingress , publishServiceAddresses []string )
61
+ IsGatewayAPIInstalled (gatewayControllerName string ) bool
56
62
}
57
63
58
64
// A Custom Resource interface
@@ -77,6 +83,8 @@ type k8s struct {
77
83
syncPeriod time.Duration
78
84
cacheResyncPeriod time.Duration
79
85
disableSvcExternalName bool // CVE-2021-25740
86
+ crdClient * crdclientset.Clientset
87
+ gatewayAPIInstalled bool
80
88
}
81
89
82
90
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
104
112
logger .Print ("Gateway API not present" )
105
113
}
106
114
115
+ crdClient , err := crdclientset .NewForConfig (restconfig )
116
+ if err != nil {
117
+ logger .Error ("CRD API client not present" )
118
+ }
119
+
107
120
prefix , _ := utils .GetPodPrefix (os .Getenv ("POD_NAME" ))
108
121
k := k8s {
109
122
builtInClient : builtInClient ,
@@ -118,6 +131,7 @@ func New(osArgs utils.OSArgs, whitelist map[string]struct{}, publishSvc *utils.N
118
131
disableSvcExternalName : osArgs .DisableServiceExternalName ,
119
132
gatewayClient : gatewayClient ,
120
133
gatewayRestClient : gatewayRestClient ,
134
+ crdClient : crdClient ,
121
135
}
122
136
// alpha1 is deprecated
123
137
k .registerCoreCR (NewGlobalCRV1Alpha1 (), CRSGroupVersionV1alpha1 )
@@ -145,14 +159,13 @@ func (k k8s) UpdatePublishService(ingresses []*ingress.Ingress, publishServiceAd
145
159
}
146
160
}
147
161
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 ) {
149
163
informersSynced := & []cache.InformerSynced {}
150
- needGatewayAPIInformers := k .isGatewayAPIInstalled () && osArgs .GatewayControllerName != ""
151
164
k .runPodInformer (eventChan , stop , informersSynced )
152
165
for _ , namespace := range k .whiteListedNS {
153
166
k .runInformers (eventChan , stop , namespace , informersSynced )
154
167
k .runCRInformers (eventChan , stop , namespace , informersSynced )
155
- if needGatewayAPIInformers {
168
+ if gatewayAPIInstalled {
156
169
k .runInformersGwAPI (eventChan , stop , namespace , informersSynced )
157
170
}
158
171
}
@@ -320,7 +333,43 @@ func getWhitelistedNS(whitelist map[string]struct{}, cfgMapNS string) []string {
320
333
return namespaces
321
334
}
322
335
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
326
375
}
0 commit comments