Skip to content
This repository has been archived by the owner on Jul 11, 2023. It is now read-only.

ingress: don't error if candidate group version is not available #4007

Merged
merged 1 commit into from
Aug 18, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 6 additions & 14 deletions pkg/errcode/errcode.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,10 +113,6 @@ const (

// ErrUnmarshallingKubernetesResource indicates that a Kubernetes resource could not be unmarshalled
ErrUnmarshallingKubernetesResource

// ErrGettingSupportedIngressVersions indicates the mapping of Ingress API versions to the corresponding values indicating
// if they are supported could not be configured
ErrGettingSupportedIngressVersions
)

// Range 4000-4100 reserved for errors related to certificate providers
Expand Down Expand Up @@ -549,10 +545,6 @@ A Kubernetes resource could not be marshalled.

ErrUnmarshallingKubernetesResource: `
A Kubernetes resource could not be unmarshalled.
`,

ErrGettingSupportedIngressVersions: `
The Ingress API versions supported by the k8s API server could not be obtained.
`,

//
Expand Down Expand Up @@ -728,7 +720,7 @@ The proxy was not allowed to be a part of the mesh.
`,

ErrGRPCStreamClosedByProxy: `
The gRPC stream was closed by the proxy and no DiscoveryRequests can be received.
The gRPC stream was closed by the proxy and no DiscoveryRequests can be received.
The Stream Agreggated Resource server was terminated for the specified proxy.
`,

Expand Down Expand Up @@ -809,7 +801,7 @@ The corresponding certificate resource was ignored by the system.
`,

ErrGettingServiceCertSecret: `
An XDS secret containing a TLS certificate could not be retrieved.
An XDS secret containing a TLS certificate could not be retrieved.
The corresponding secret request was ignored by the system.
`,

Expand All @@ -835,7 +827,7 @@ A protobuf ProtoMessage could not be converted into YAML.
`,

ErrParsingMutatingWebhookCert: `
The mutating webhook certificate could not be parsed.
The mutating webhook certificate could not be parsed.
The mutating webhook HTTP server was not started.
`,

Expand All @@ -852,8 +844,8 @@ The timeout from an AdmissionRequest could not be parsed.
`,

ErrInvalidAdmissionReqHeader: `
The AdmissionRequest's header was invalid. The content type obtained from the
header is not supported.
The AdmissionRequest's header was invalid. The content type obtained from the
header is not supported.
`,

ErrWritingAdmissionResp: `
Expand Down Expand Up @@ -907,7 +899,7 @@ The ValidatingWebhookConfiguration could not be patched with the CA Bundle.
`,

ErrParsingValidatingWebhookCert: `
The validating webhook certificate could not be parsed.
The validating webhook certificate could not be parsed.
The validating webhook HTTP server was not started.
`,
}
27 changes: 10 additions & 17 deletions pkg/ingress/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,6 @@ var candidateVersions = []string{networkingV1.SchemeGroupVersion.String(), netwo

// NewIngressClient implements ingress.Monitor and creates the Kubernetes client to monitor Ingress resources.
func NewIngressClient(kubeClient kubernetes.Interface, kubeController k8s.Controller, stop chan struct{}, cfg configurator.Configurator, certProvider certificate.Manager) (Monitor, error) {
supportedIngressVersions, err := getSupportedIngressVersions(kubeClient.Discovery())
if err != nil {
// TODO(#3962): metric might not be scraped before process restart resulting from this error
log.Error().Err(err).Str(errcode.Kind, errcode.GetErrCodeWithMetric(errcode.ErrGettingSupportedIngressVersions)).
Msgf("Error retrieving ingress API versions supported by k8s API server")
return nil, err
}

// Ignore ingresses that have the ignore label
ignoreLabel, _ := labels.NewRequirement(constants.IgnoreLabel, selection.DoesNotExist, nil)
option := informers.WithTweakListOptions(func(opt *metav1.ListOptions) {
Expand Down Expand Up @@ -67,6 +59,8 @@ func NewIngressClient(kubeClient kubernetes.Interface, kubeController k8s.Contro
certProvider: certProvider,
}

supportedIngressVersions := getSupportedIngressVersions(kubeClient.Discovery())

if v1Supported, ok := supportedIngressVersions[networkingV1.SchemeGroupVersion.String()]; ok && v1Supported {
c.informerV1 = informerFactory.Networking().V1().Ingresses().Informer()
c.cacheV1 = c.informerV1.GetStore()
Expand Down Expand Up @@ -215,14 +209,12 @@ func (c client) GetIngressNetworkingV1(meshService service.MeshService) ([]*netw
}

// getSupportedIngressVersions returns a map comprising of keys matching candidate ingress API versions
// and corresponding values indidicating if they are supported by the k8s API server or not. An error
// is returned in case this cannot be determined.
// and corresponding values indidicating if they are supported by the k8s API server or not.
// Example return values:
// - only networking.k8s.io/v1 is supported: {'networking.k8s.io/v1': true, 'networking.k8s.io/v1beta1': false}, nil
// - only networking.k8s.io/v1beta1 is supported: {'networking.k8s.io/v1': false, 'networking.k8s.io/v1beta1': true}, nil
// - both networking.k8s.io/v1 and networking.k8s.io/v1beta1 are supported: {'networking.k8s.io/v1': true, 'networking.k8s.io/v1beta1': true}, nil
// - on error: nil, error
func getSupportedIngressVersions(client discovery.ServerResourcesInterface) (map[string]bool, error) {
// - only networking.k8s.io/v1 is supported: {'networking.k8s.io/v1': true, 'networking.k8s.io/v1beta1': false}
// - only networking.k8s.io/v1beta1 is supported: {'networking.k8s.io/v1': false, 'networking.k8s.io/v1beta1': true}
// - both networking.k8s.io/v1 and networking.k8s.io/v1beta1 are supported: {'networking.k8s.io/v1': true, 'networking.k8s.io/v1beta1': true}
func getSupportedIngressVersions(client discovery.ServerResourcesInterface) map[string]bool {
versions := make(map[string]bool)

for _, groupVersion := range candidateVersions {
Expand All @@ -231,7 +223,8 @@ func getSupportedIngressVersions(client discovery.ServerResourcesInterface) (map

list, err := client.ServerResourcesForGroupVersion(groupVersion)
if err != nil {
return nil, err
// The 'groupVersion' is not supported by the API server
continue
}

for _, elem := range list.APIResources {
Expand All @@ -242,5 +235,5 @@ func getSupportedIngressVersions(client discovery.ServerResourcesInterface) (map
}
}

return versions, nil
return versions
}
29 changes: 20 additions & 9 deletions pkg/ingress/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ func TestGetSupportedIngressVersions(t *testing.T) {
name string
discoveryClient discovery.ServerResourcesInterface
expectedVersions map[string]bool
exepectError bool
}

testCases := []testCase{
Expand All @@ -53,7 +52,6 @@ func TestGetSupportedIngressVersions(t *testing.T) {
"networking.k8s.io/v1": true,
"networking.k8s.io/v1beta1": true,
},
exepectError: false,
},
{
name: "k8s API server supports only ingress v1beta1",
Expand All @@ -72,7 +70,6 @@ func TestGetSupportedIngressVersions(t *testing.T) {
"networking.k8s.io/v1": false,
"networking.k8s.io/v1beta1": true,
},
exepectError: false,
},
{
name: "k8s API server supports only ingress v1",
Expand All @@ -91,26 +88,40 @@ func TestGetSupportedIngressVersions(t *testing.T) {
"networking.k8s.io/v1": true,
"networking.k8s.io/v1beta1": false,
},
exepectError: false,
},
{
name: "k8s API server returns an error",
discoveryClient: &k8s.FakeDiscoveryClient{
Resources: map[string]metav1.APIResourceList{},
Err: errors.New("fake error"),
},
expectedVersions: nil,
exepectError: true,
expectedVersions: map[string]bool{
"networking.k8s.io/v1": false,
"networking.k8s.io/v1beta1": false,
},
},
{
name: "k8s API server does not support the networking.k8s.io/v1beta1 group version",
discoveryClient: &k8s.FakeDiscoveryClient{
Resources: map[string]metav1.APIResourceList{
"networking.k8s.io/v1beta1": {APIResources: []metav1.APIResource{
{Kind: "Ingress"},
}},
},
Err: errors.New("fake"),
},
expectedVersions: map[string]bool{
"networking.k8s.io/v1": false,
"networking.k8s.io/v1beta1": false,
},
},
}

for i, tc := range testCases {
t.Run(fmt.Sprintf("Running test case %d: %s", i, tc.name), func(t *testing.T) {
assert := tassert.New(t)

versions, err := getSupportedIngressVersions(tc.discoveryClient)

assert.Equal(tc.exepectError, err != nil)
versions := getSupportedIngressVersions(tc.discoveryClient)
assert.Equal(tc.expectedVersions, versions)
})
}
Expand Down