Skip to content

Commit 5f79569

Browse files
authored
Add Cilium to ingress2gateway (#199)
* Cilium basic structure * Add base for Cilium * Add Cilium to IR * Add force-https annotation test * Add README for Cilium Add Cilium to main README * Added missing boilerplate * Fix comments gofmt
1 parent e9621a1 commit 5f79569

13 files changed

+738
-0
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ API.
2020
## Supported providers
2121

2222
* [apisix](pkg/i2gw/providers/apisix/README.md)
23+
* [cilium](pkg./i2gw/providers/cilium/README.md)
2324
* [ingress-nginx](pkg/i2gw/providers/ingressnginx/README.md)
2425
* [istio](pkg/i2gw/providers/istio/README.md)
2526
* [gce](pkg/i2gw/providers/gce/README.md)

cmd/print.go

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import (
3333

3434
// Call init function for the providers
3535
_ "github.com/kubernetes-sigs/ingress2gateway/pkg/i2gw/providers/apisix"
36+
_ "github.com/kubernetes-sigs/ingress2gateway/pkg/i2gw/providers/cilium"
3637
_ "github.com/kubernetes-sigs/ingress2gateway/pkg/i2gw/providers/gce"
3738
_ "github.com/kubernetes-sigs/ingress2gateway/pkg/i2gw/providers/ingressnginx"
3839
_ "github.com/kubernetes-sigs/ingress2gateway/pkg/i2gw/providers/istio"

pkg/i2gw/intermediate/intermediate_representation.go

+3
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ type GatewayContext struct {
5252

5353
type ProviderSpecificGatewayIR struct {
5454
Apisix *ApisixGatewayIR
55+
Cilium *CiliumGatewayIR
5556
Gce *GceGatewayIR
5657
IngressNginx *IngressNginxGatewayIR
5758
Istio *IstioGatewayIR
@@ -71,6 +72,7 @@ type HTTPRouteContext struct {
7172

7273
type ProviderSpecificHTTPRouteIR struct {
7374
Apisix *ApisixHTTPRouteIR
75+
Cilium *CiliumHTTPRouteIR
7476
Gce *GceHTTPRouteIR
7577
IngressNginx *IngressNginxHTTPRouteIR
7678
Istio *IstioHTTPRouteIR
@@ -82,6 +84,7 @@ type ProviderSpecificHTTPRouteIR struct {
8284
// extension features on Service.
8385
type ProviderSpecificServiceIR struct {
8486
Apisix *ApisixServiceIR
87+
Cilium *CiliumServiceIR
8588
Gce *GceServiceIR
8689
IngressNginx *IngressNginxServiceIR
8790
Istio *IstioServiceIR
+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*
2+
Copyright 2024 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package intermediate
18+
19+
type CiliumGatewayIR struct{}
20+
type CiliumHTTPRouteIR struct{}
21+
type CiliumServiceIR struct{}

pkg/i2gw/providers/cilium/README.md

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Cilium Provider
2+
3+
The project supports translating [Cilium](https://github.com/cilium/cilium) specific annotations.
4+
5+
## Supported Annotations
6+
7+
- `ingress.cilium.io/force-https:`: This annotation redirects HTTP requests to HTTPS with a `301` status code.
8+
+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
Copyright 2024 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package cilium
18+
19+
import "fmt"
20+
21+
const (
22+
annotationPrefix = "ingress.cilium.io"
23+
)
24+
25+
func ciliumAnnotation(suffix string) string {
26+
return fmt.Sprintf("%s/%s", annotationPrefix, suffix)
27+
}

pkg/i2gw/providers/cilium/cilium.go

+81
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/*
2+
Copyright 2023 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package cilium
18+
19+
import (
20+
"context"
21+
"fmt"
22+
23+
"github.com/kubernetes-sigs/ingress2gateway/pkg/i2gw"
24+
"github.com/kubernetes-sigs/ingress2gateway/pkg/i2gw/intermediate"
25+
"github.com/kubernetes-sigs/ingress2gateway/pkg/i2gw/providers/common"
26+
"k8s.io/apimachinery/pkg/util/validation/field"
27+
)
28+
29+
// The Name of the provider.
30+
const Name = "cilium"
31+
const CiliumIngressClass = "cilium"
32+
33+
func init() {
34+
i2gw.ProviderConstructorByName[Name] = NewProvider
35+
}
36+
37+
// Provider implements the i2gw.Provider interface.
38+
type Provider struct {
39+
storage *storage
40+
resourceReader *resourceReader
41+
resourcesToIRConverter *resourcesToIRConverter
42+
}
43+
44+
// NewProvider constructs and returns the cilium implementation of i2gw.Provider.
45+
func NewProvider(conf *i2gw.ProviderConf) i2gw.Provider {
46+
return &Provider{
47+
storage: newResourcesStorage(),
48+
resourceReader: newResourceReader(conf),
49+
resourcesToIRConverter: newResourcesToIRConverter(),
50+
}
51+
}
52+
53+
// ToIR converts stored Cilium API entities to intermediate.IR
54+
// including the cilium specific features.
55+
func (p *Provider) ToIR() (intermediate.IR, field.ErrorList) {
56+
return p.resourcesToIRConverter.convertToIR(p.storage)
57+
}
58+
59+
func (p *Provider) ToGatewayResources(ir intermediate.IR) (i2gw.GatewayResources, field.ErrorList) {
60+
return common.ToGatewayResources(ir)
61+
}
62+
63+
func (p *Provider) ReadResourcesFromCluster(ctx context.Context) error {
64+
storage, err := p.resourceReader.readResourcesFromCluster(ctx)
65+
if err != nil {
66+
return fmt.Errorf("failed to read resources from cluster: %w", err)
67+
}
68+
69+
p.storage = storage
70+
return nil
71+
}
72+
73+
func (p *Provider) ReadResourcesFromFile(_ context.Context, filename string) error {
74+
storage, err := p.resourceReader.readResourcesFromFile(filename)
75+
if err != nil {
76+
return fmt.Errorf("failed to read resources from file: %w", err)
77+
}
78+
79+
p.storage = storage
80+
return nil
81+
}
+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
Copyright 2023 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package cilium
18+
19+
import (
20+
"github.com/kubernetes-sigs/ingress2gateway/pkg/i2gw"
21+
"github.com/kubernetes-sigs/ingress2gateway/pkg/i2gw/intermediate"
22+
"github.com/kubernetes-sigs/ingress2gateway/pkg/i2gw/providers/common"
23+
networkingv1 "k8s.io/api/networking/v1"
24+
"k8s.io/apimachinery/pkg/util/validation/field"
25+
)
26+
27+
// resourcesToIRConverter implements the ToIR function of i2gw.ResourcesToIRConverter interface.
28+
type resourcesToIRConverter struct {
29+
featureParsers []i2gw.FeatureParser
30+
implementationSpecificOptions i2gw.ProviderImplementationSpecificOptions
31+
}
32+
33+
// newResourcesToIRConverter returns a cilium resourcesToIRConverter instance.
34+
func newResourcesToIRConverter() *resourcesToIRConverter {
35+
return &resourcesToIRConverter{
36+
featureParsers: []i2gw.FeatureParser{
37+
forceHTTPSFeature,
38+
},
39+
implementationSpecificOptions: i2gw.ProviderImplementationSpecificOptions{
40+
// The list of the implementationSpecific ingress fields options comes here.
41+
},
42+
}
43+
}
44+
45+
func (c *resourcesToIRConverter) convertToIR(storage *storage) (intermediate.IR, field.ErrorList) {
46+
ingressList := []networkingv1.Ingress{}
47+
for _, ing := range storage.Ingresses {
48+
ingressList = append(ingressList, *ing)
49+
}
50+
// Convert plain ingress resources to gateway resources, ignoring all
51+
// provider-specific features.
52+
ir, errs := common.ToIR(ingressList, c.implementationSpecificOptions)
53+
if len(errs) > 0 {
54+
return intermediate.IR{}, errs
55+
}
56+
57+
for _, parseFeatureFunc := range c.featureParsers {
58+
// Apply the feature parsing function to the gateway resources, one by one.
59+
parseErrs := parseFeatureFunc(ingressList, &ir)
60+
// Append the parsing errors to the error list.
61+
errs = append(errs, parseErrs...)
62+
}
63+
64+
return ir, errs
65+
}
+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
Copyright 2024 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package cilium
18+
19+
import (
20+
"fmt"
21+
22+
"github.com/kubernetes-sigs/ingress2gateway/pkg/i2gw/intermediate"
23+
"github.com/kubernetes-sigs/ingress2gateway/pkg/i2gw/notifications"
24+
"github.com/kubernetes-sigs/ingress2gateway/pkg/i2gw/providers/common"
25+
networkingv1 "k8s.io/api/networking/v1"
26+
"k8s.io/apimachinery/pkg/types"
27+
"k8s.io/apimachinery/pkg/util/validation/field"
28+
"k8s.io/utils/ptr"
29+
gatewayv1 "sigs.k8s.io/gateway-api/apis/v1"
30+
)
31+
32+
func forceHTTPSFeature(ingresses []networkingv1.Ingress, ir *intermediate.IR) field.ErrorList {
33+
var errs field.ErrorList
34+
forceHTTPSAnnotation := ciliumAnnotation("force-https")
35+
ruleGroups := common.GetRuleGroups(ingresses)
36+
for _, rg := range ruleGroups {
37+
38+
for _, rule := range rg.Rules {
39+
if val, annotationFound := rule.Ingress.Annotations[forceHTTPSAnnotation]; val == "enabled" || val == "true" {
40+
if rule.Ingress.Spec.Rules == nil {
41+
continue
42+
}
43+
key := types.NamespacedName{Namespace: rule.Ingress.Namespace, Name: common.RouteName(rg.Name, rg.Host)}
44+
45+
httpRoute, ok := ir.HTTPRoutes[key]
46+
if !ok {
47+
errs = append(errs, field.NotFound(field.NewPath("HTTPRoute"), key))
48+
}
49+
50+
for i, rule := range httpRoute.Spec.Rules {
51+
rule.Filters = append(rule.Filters, gatewayv1.HTTPRouteFilter{
52+
Type: gatewayv1.HTTPRouteFilterRequestRedirect,
53+
RequestRedirect: &gatewayv1.HTTPRequestRedirectFilter{
54+
Scheme: ptr.To("https"),
55+
StatusCode: ptr.To(int(301)),
56+
},
57+
})
58+
rule.BackendRefs = nil
59+
60+
httpRoute.Spec.Rules[i] = rule
61+
62+
}
63+
if annotationFound && ok {
64+
notify(notifications.InfoNotification, fmt.Sprintf("parsed \"%v\" annotation of ingress and patched %v fields", forceHTTPSAnnotation, field.NewPath("httproute", "spec", "rules").Key("").Child("filters")), &httpRoute)
65+
}
66+
}
67+
}
68+
}
69+
return errs
70+
}

0 commit comments

Comments
 (0)