Skip to content

Commit 139e9de

Browse files
feat: Add setHeader functionality for httpRoutes (#31)
* feat: Add setHeader functionality for httpRoutes Signed-off-by: Philipp Plotnikov <[email protected]> * refactor: fix lint Signed-off-by: Philipp Plotnikov <[email protected]> * refactor: seperate logic setHTTPHeaderRoute to the different functions Signed-off-by: Philipp Plotnikov <[email protected]> * refactor: move error messages into seperate file Signed-off-by: Philipp Plotnikov <[email protected]> * refactor: rename mu field to the mutex field Signed-off-by: Philipp Plotnikov <[email protected]> * test: add tests for setHeaderRoute functionality Signed-off-by: Philipp Plotnikov <[email protected]> * feat: store data about httpManagedRoutes in configMap Signed-off-by: Philipp Plotnikov <[email protected]> * fix: fix getBackendRef function and add getRouteRule function Signed-off-by: Philipp Plotnikov <[email protected]> * refactor: add getGatewayAPITracfficRoutingConfig function Signed-off-by: Philipp Plotnikov <[email protected]> * fix: fix multiple managed route removement from map Signed-off-by: Philipp Plotnikov <[email protected]> * chore: up go version from 1.19 to 1.20 in github workflows Signed-off-by: Philipp Plotnikov <[email protected]> --------- Signed-off-by: Philipp Plotnikov <[email protected]>
1 parent b9fb854 commit 139e9de

File tree

14 files changed

+731
-176
lines changed

14 files changed

+731
-176
lines changed

.github/workflows/ci.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ on:
77
branches:
88
- "main"
99
env:
10-
GOLANG_VERSION: '1.19'
10+
GOLANG_VERSION: '1.20'
1111

1212
jobs:
1313
unit-tests:

.github/workflows/release.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ on:
66
- "release-v[0-9]+.[0-9]+.[0-9]+-rc[0-9]+"
77

88
env:
9-
GOLANG_VERSION: "1.19"
9+
GOLANG_VERSION: "1.20"
1010

1111
jobs:
1212
release-creation:

internal/defaults/defaults.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package defaults
2+
3+
const ConfigMap = "argo-gatewayapi-configmap"

internal/utils/common.go

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
package utils
2+
3+
import (
4+
"encoding/json"
5+
"strings"
6+
7+
pluginTypes "github.com/argoproj/argo-rollouts/utils/plugin/types"
8+
log "github.com/sirupsen/logrus"
9+
v1 "k8s.io/api/core/v1"
10+
kubeErrors "k8s.io/apimachinery/pkg/api/errors"
11+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
12+
"k8s.io/client-go/rest"
13+
"k8s.io/client-go/tools/clientcmd"
14+
)
15+
16+
func GetKubeConfig() (*rest.Config, error) {
17+
loadingRules := clientcmd.NewDefaultClientConfigLoadingRules()
18+
// if you want to change the loading rules (which files in which order), you can do so here
19+
configOverrides := &clientcmd.ConfigOverrides{}
20+
// if you want to change override values or bind them to flags, there are methods to help you
21+
kubeConfig := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingRules, configOverrides)
22+
config, err := kubeConfig.ClientConfig()
23+
if err != nil {
24+
return nil, pluginTypes.RpcError{ErrorString: err.Error()}
25+
}
26+
return config, nil
27+
}
28+
29+
func SetLogLevel(logLevel string) {
30+
level, err := log.ParseLevel(logLevel)
31+
if err != nil {
32+
log.Fatal(err)
33+
}
34+
log.SetLevel(level)
35+
}
36+
37+
func CreateFormatter(logFormat string) log.Formatter {
38+
var formatType log.Formatter
39+
switch strings.ToLower(logFormat) {
40+
case "json":
41+
formatType = &log.JSONFormatter{}
42+
case "text":
43+
formatType = &log.TextFormatter{
44+
FullTimestamp: true,
45+
}
46+
default:
47+
log.Infof("Unknown format: %s. Using text logformat", logFormat)
48+
formatType = &log.TextFormatter{
49+
FullTimestamp: true,
50+
}
51+
}
52+
return formatType
53+
}
54+
55+
func CreateConfigMap(name string, options CreateConfigMapOptions) (*v1.ConfigMap, error) {
56+
clientset := options.Clientset
57+
ctx := options.Ctx
58+
configMap, err := clientset.Get(ctx, name, metav1.GetOptions{})
59+
if err != nil && !kubeErrors.IsNotFound(err) {
60+
return nil, err
61+
}
62+
if err == nil {
63+
return configMap, err
64+
}
65+
configMap.Name = name
66+
configMap, err = clientset.Create(ctx, configMap, metav1.CreateOptions{})
67+
if err != nil {
68+
return nil, err
69+
}
70+
return configMap, err
71+
}
72+
73+
func GetConfigMapData(configMap *v1.ConfigMap, configMapKey string, destination any) error {
74+
if configMap.Data != nil && configMap.Data[configMapKey] != "" {
75+
err := json.Unmarshal([]byte(configMap.Data[configMapKey]), &destination)
76+
if err != nil {
77+
return err
78+
}
79+
}
80+
return nil
81+
}
82+
83+
func UpdateConfigMapData(configMap *v1.ConfigMap, configMapData any, options UpdateConfigMapOptions) error {
84+
clientset := options.Clientset
85+
rawConfigMapData, err := json.Marshal(configMapData)
86+
if err != nil {
87+
return err
88+
}
89+
if configMap.Data == nil {
90+
configMap.Data = make(map[string]string)
91+
}
92+
configMap.Data[options.ConfigMapKey] = string(rawConfigMapData)
93+
_, err = clientset.Update(options.Ctx, configMap, metav1.UpdateOptions{})
94+
return err
95+
}
96+
97+
func RemoveIndex[T any](original []T, index int) []T {
98+
result := original[:index]
99+
return append(result, original[index+1:]...)
100+
}
101+
102+
func DoTransaction(logCtx *log.Entry, taskList ...Task) error {
103+
var err, reverseErr error
104+
for index, task := range taskList {
105+
err = task.Action()
106+
if err == nil {
107+
continue
108+
}
109+
logCtx.Error(err.Error())
110+
for i := index - 1; i > -1; i-- {
111+
reverseErr = taskList[i].ReverseAction()
112+
if err != nil {
113+
return reverseErr
114+
}
115+
}
116+
return err
117+
}
118+
return nil
119+
}

internal/utils/types.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package utils
2+
3+
import (
4+
"context"
5+
6+
v1 "k8s.io/client-go/kubernetes/typed/core/v1"
7+
)
8+
9+
type CreateConfigMapOptions struct {
10+
Clientset v1.ConfigMapInterface
11+
Ctx context.Context
12+
}
13+
14+
type UpdateConfigMapOptions struct {
15+
Clientset v1.ConfigMapInterface
16+
ConfigMapKey string
17+
Ctx context.Context
18+
}
19+
20+
type Task struct {
21+
Action func() error
22+
ReverseAction func() error
23+
}

main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
package main
22

33
import (
4+
"github.com/argoproj-labs/rollouts-plugin-trafficrouter-gatewayapi/internal/utils"
45
"github.com/argoproj-labs/rollouts-plugin-trafficrouter-gatewayapi/pkg/plugin"
5-
"github.com/argoproj-labs/rollouts-plugin-trafficrouter-gatewayapi/utils"
66

77
rolloutsPlugin "github.com/argoproj/argo-rollouts/rollout/trafficrouting/plugin/rpc"
88
goPlugin "github.com/hashicorp/go-plugin"

pkg/mocks/plugin.go

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package mocks
22

33
import (
4+
v1 "k8s.io/api/core/v1"
45
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
56

67
"sigs.k8s.io/gateway-api/apis/v1alpha2"
@@ -9,18 +10,26 @@ import (
910
)
1011

1112
const (
12-
HTTPRoute = "HTTPRoute"
13-
TCPRoute = "TCPRoute"
14-
StableServiceName = "argo-rollouts-stable-service"
15-
CanaryServiceName = "argo-rollouts-canary-service"
16-
HTTPRouteName = "argo-rollouts-http-route"
17-
TCPRouteName = "argo-rollouts-tcp-route"
18-
Namespace = "default"
13+
HTTPRoute = "HTTPRoute"
14+
TCPRoute = "TCPRoute"
15+
StableServiceName = "argo-rollouts-stable-service"
16+
CanaryServiceName = "argo-rollouts-canary-service"
17+
HTTPRouteName = "argo-rollouts-http-route"
18+
TCPRouteName = "argo-rollouts-tcp-route"
19+
Namespace = "default"
20+
ConfigMapName = "test-config"
21+
HTTPManagedRouteName = "test-http-header-route"
1922
)
2023

2124
var (
22-
port = v1beta1.PortNumber(80)
23-
weight int32 = 0
25+
port = v1beta1.PortNumber(80)
26+
weight int32 = 0
27+
httpPathMatchType = v1beta1.PathMatchPathPrefix
28+
httpPathMatchValue = "/"
29+
httpPathMatch = v1beta1.HTTPPathMatch{
30+
Type: &httpPathMatchType,
31+
Value: &httpPathMatchValue,
32+
}
2433
)
2534

2635
var HTTPRouteObj = v1beta1.HTTPRoute{
@@ -58,6 +67,11 @@ var HTTPRouteObj = v1beta1.HTTPRoute{
5867
},
5968
},
6069
},
70+
Matches: []v1beta1.HTTPRouteMatch{
71+
{
72+
Path: &httpPathMatch,
73+
},
74+
},
6175
},
6276
},
6377
},
@@ -98,3 +112,10 @@ var TCPPRouteObj = v1alpha2.TCPRoute{
98112
},
99113
},
100114
}
115+
116+
var ConfigMapObj = v1.ConfigMap{
117+
ObjectMeta: metav1.ObjectMeta{
118+
Name: ConfigMapName,
119+
Namespace: Namespace,
120+
},
121+
}

pkg/plugin/errors.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package plugin
2+
3+
const (
4+
GatewayAPIUpdateError = "error updating Gateway API %q: %s"
5+
GatewayAPIManifestError = "httpRoute and tcpRoute fields are empty. tcpRoute or httpRoute should be set"
6+
HTTPRouteFieldIsEmptyError = "httpRoute field is empty. It has to be set to remove managed routes"
7+
InvalidHeaderMatchTypeError = "invalid header match type"
8+
BackendRefWasNotFoundInHTTPRouteError = "backendRef was not found in httpRoute"
9+
BackendRefWasNotFoundInTCPRouteError = "backendRef was not found in tcpRoute"
10+
BackendRefListWasNotFoundInTCPRouteError = "backendRef list was not found in tcpRoute"
11+
ManagedRouteMapEntryDeleteError = "can't delete key %q from managedRouteMap. The key %q is not in the managedRouteMap"
12+
)

0 commit comments

Comments
 (0)