Skip to content

Commit

Permalink
Configmap configuration (#43)
Browse files Browse the repository at this point in the history
* Configmap configuration

* Add config helper and usage in validation and generation of resources

* Fix tests

* Validate test config

* Reindex some internal comments
  • Loading branch information
videlov authored Oct 6, 2022
1 parent 064be15 commit 202a16c
Show file tree
Hide file tree
Showing 17 changed files with 236 additions and 70 deletions.
7 changes: 7 additions & 0 deletions config/configmap/configmap.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: config
data:
api-gateway-config.yaml: >
jwtHandler: "ory"
2 changes: 2 additions & 0 deletions config/configmap/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
resources:
- configmap.yaml
2 changes: 1 addition & 1 deletion config/crd/bases/gateway.kyma-project.io_apirules.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -386,4 +386,4 @@ spec:
served: true
storage: true
subresources:
status: {}
status: {}
1 change: 1 addition & 0 deletions config/default/kustomization.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ bases:
- ../webhook
# [CERTIFICATES] To enable certificate injection in CRD and manager uncomment ../certificates
- ../certificates
- ../configmap

patchesStrategicMerge:
- manager_args_patch.yaml
Expand Down
8 changes: 8 additions & 0 deletions config/manager/manager.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,13 @@ spec:
requests:
cpu: 100m
memory: 20Mi
volumeMounts:
- name: api-gateway-config
mountPath: /api-gateway-config.yaml
subPath: api-gateway-config.yaml
volumes:
- name: api-gateway-config
configMap:
name: api-gateway-config
serviceAccountName: controller-manager
terminationGracePeriodSeconds: 10
4 changes: 4 additions & 0 deletions controllers/api_controller_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"time"

"github.com/kyma-incubator/api-gateway/internal/builders"
"github.com/kyma-incubator/api-gateway/internal/helpers"
"github.com/kyma-incubator/api-gateway/internal/processing"

"encoding/json"
Expand Down Expand Up @@ -61,6 +62,9 @@ var _ = Describe("APIRule Controller", func() {
AllowMethods(TestAllowMethods...).
AllowOrigins(TestAllowOrigins...)

fakeFileReader := FakeFileReader{FileContent: fmt.Sprintf("jwtHandler: %s", helpers.JWT_HANDLER_ORY)}
helpers.ReadFileHandle = fakeFileReader.ReadFile

Context("when updating the APIRule with multiple paths", func() {

It("should create, update and delete rules depending on patch match", func() {
Expand Down
15 changes: 15 additions & 0 deletions controllers/api_controller_test.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
package controllers_test

import (
"bytes"
"context"
"fmt"
"io/ioutil"
"net/http"

"sigs.k8s.io/controller-runtime/pkg/config/v1alpha1"

"github.com/go-logr/logr"
"sigs.k8s.io/controller-runtime/pkg/healthz"

"github.com/kyma-incubator/api-gateway/internal/helpers"
"github.com/kyma-incubator/api-gateway/internal/processing"

gatewayv1beta1 "github.com/kyma-incubator/api-gateway/api/v1beta1"
Expand Down Expand Up @@ -40,6 +44,14 @@ var (
isExernal bool
)

type FakeFileReader struct {
FileContent string
}

func (f FakeFileReader) ReadFile(filename string) ([]byte, error) {
return ioutil.ReadAll(bytes.NewBufferString(f.FileContent))
}

var _ = Describe("Controller", func() {
Describe("Reconcile", func() {
Context("APIRule", func() {
Expand All @@ -50,6 +62,9 @@ var _ = Describe("Controller", func() {
reconciler := getAPIReconciler(ts.mgr)
ctx := context.Background()

fakeFileReader := FakeFileReader{FileContent: fmt.Sprintf("jwtHandler: %s", helpers.JWT_HANDLER_ORY)}
helpers.ReadFileHandle = fakeFileReader.ReadFile

result, err := reconciler.Reconcile(ctx, reconcile.Request{NamespacedName: types.NamespacedName{Name: testAPI.Name}})
Expect(err).ToNot(HaveOccurred())
Expect(result.Requeue).To(BeFalse())
Expand Down
17 changes: 13 additions & 4 deletions controllers/apirule_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (

gatewayv1beta1 "github.com/kyma-incubator/api-gateway/api/v1beta1"

"github.com/kyma-incubator/api-gateway/internal/helpers"
"github.com/kyma-incubator/api-gateway/internal/processing"
"github.com/kyma-incubator/api-gateway/internal/validation"

Expand Down Expand Up @@ -80,21 +81,29 @@ func (r *APIRuleReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct
//Prevent reconciliation after status update. It should be solved by controller-runtime implementation but still isn't.
if api.Generation != api.Status.ObservedGeneration {

//1.1) Get the list of existing Virtual Services to validate host
//1.1) Get the configuration
config, err := helpers.LoadConfig()
if err != nil {
//If configuration is not available not been able to continue.
r.Log.Info(fmt.Sprintf(`Configuration loading failed {"controller": "Api", "request": "%s/%s", "file": %s}`, api.Namespace, api.Name, helpers.CONFIG_FILE))
return r.setStatusForError(ctx, api, err, gatewayv1beta1.StatusError)
}

//1.2) Get the list of existing Virtual Services to validate host
var vsList networkingv1beta1.VirtualServiceList
if err := r.Client.List(ctx, &vsList); err != nil {
//Nothing is yet processed: StatusSkipped
return r.setStatusForError(ctx, api, err, gatewayv1beta1.StatusSkipped)
}

//1.2) Validate input including host
//1.3) Validate input including host
validator := validation.APIRule{
ServiceBlockList: r.ServiceBlockList,
DomainAllowList: r.DomainAllowList,
HostBlockList: r.HostBlockList,
DefaultDomainName: r.DefaultDomainName,
}
validationFailures := validator.Validate(api, vsList)
validationFailures := validator.Validate(api, vsList, config)
if len(validationFailures) > 0 {
failuresJson, _ := json.Marshal(validationFailures)
r.Log.Info(fmt.Sprintf(`Validation failure {"controller": "Api", "request": "%s/%s", "failures": %s}`, api.Namespace, api.Name, string(failuresJson)))
Expand All @@ -103,7 +112,7 @@ func (r *APIRuleReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct

//2) Compute list of required objects (the set of objects required to satisfy our contract on apiRule.Spec, not yet applied)
factory := processing.NewFactory(r.Client, r.Log, r.OathkeeperSvc, r.OathkeeperSvcPort, r.CorsConfig, r.GeneratedObjectsLabels, r.DefaultDomainName)
requiredObjects := factory.CalculateRequiredState(api)
requiredObjects := factory.CalculateRequiredState(api, config)

//3.1 Fetch all existing objects related to _this_ apiRule from the cluster (VS, Rules)
actualObjects, err := factory.GetActualState(ctx, api)
Expand Down
33 changes: 33 additions & 0 deletions internal/helpers/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package helpers

import (
"io/ioutil"

"gopkg.in/yaml.v2"
)

const JWT_HANDLER_ORY = "ory"
const JWT_HANDLER_ISTIO = "istio"

const CONFIG_FILE = "/api-gateway-config.yaml"

var ReadFileHandle = ioutil.ReadFile

type Config struct {
JWTHandler string `yaml:"jwtHandler"`
}

func LoadConfig() (*Config, error) {
configData, err := ReadFileHandle(CONFIG_FILE)
if err != nil {
return nil, err
}

config := &Config{}
err = yaml.Unmarshal(configData, config)
if err != nil {
return nil, err
}

return config, err
}
17 changes: 14 additions & 3 deletions internal/processing/processing.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/go-logr/logr"
gatewayv1alpha1 "github.com/kyma-incubator/api-gateway/api/v1alpha1"
gatewayv1beta1 "github.com/kyma-incubator/api-gateway/api/v1beta1"
"github.com/kyma-incubator/api-gateway/internal/helpers"
rulev1alpha1 "github.com/ory/oathkeeper-maester/api/v1alpha1"
networkingv1beta1 "istio.io/client-go/pkg/apis/networking/v1beta1"
)
Expand Down Expand Up @@ -54,19 +55,29 @@ type CorsConfig struct {
}

// CalculateRequiredState returns required state of all objects related to given api
func (f *Factory) CalculateRequiredState(api *gatewayv1beta1.APIRule) *State {
func (f *Factory) CalculateRequiredState(api *gatewayv1beta1.APIRule, config *helpers.Config) *State {
var res State
pathDuplicates := hasPathDuplicates(api.Spec.Rules)
res.accessRules = make(map[string]*rulev1alpha1.Rule)
for _, rule := range api.Spec.Rules {
if isSecured(rule) {
ar := generateAccessRule(api, rule, rule.AccessStrategies, f.additionalLabels, f.defaultDomainName)
var ar *rulev1alpha1.Rule
if config.JWTHandler == helpers.JWT_HANDLER_ORY {
ar = generateAccessRule(api, rule, rule.AccessStrategies, f.additionalLabels, f.defaultDomainName)
} else if config.JWTHandler == helpers.JWT_HANDLER_ISTIO {
//TODO generate based on config.JWTHandler="istio"
}
res.accessRules[setAccessRuleKey(pathDuplicates, *ar)] = ar
}
}

//Only one vs
vs := f.generateVirtualService(api)
var vs *networkingv1beta1.VirtualService
if config.JWTHandler == helpers.JWT_HANDLER_ORY {
vs = f.generateVirtualService(api)
} else if config.JWTHandler == helpers.JWT_HANDLER_ISTIO {
//TODO generate based on config.JWTHandler="istio"
}
res.virtualService = vs

return &res
Expand Down
31 changes: 18 additions & 13 deletions internal/processing/processing_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"k8s.io/apimachinery/pkg/types"

gatewayv1beta1 "github.com/kyma-incubator/api-gateway/api/v1beta1"
"github.com/kyma-incubator/api-gateway/internal/helpers"
rulev1alpha1 "github.com/ory/oathkeeper-maester/api/v1alpha1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
ctrl "sigs.k8s.io/controller-runtime"
Expand All @@ -38,6 +39,10 @@ const (
)

var (
config = helpers.Config{JWTHandler: helpers.JWT_HANDLER_ORY}

//TODO should include tests for other JWT handler

apiMethods = []string{"GET"}
apiScopes = []string{"write", "read"}
servicePort uint32 = 8080
Expand Down Expand Up @@ -88,7 +93,7 @@ var _ = Describe("Factory", func() {

f := NewFactory(nil, ctrl.Log.WithName("test"), oathkeeperSvc, oathkeeperSvcPort, testCors, testAdditionalLabels, defaultDomain)

desiredState := f.CalculateRequiredState(apiRule)
desiredState := f.CalculateRequiredState(apiRule, &config)
vs := desiredState.virtualService
accessRules := desiredState.accessRules

Expand Down Expand Up @@ -150,7 +155,7 @@ var _ = Describe("Factory", func() {

f := NewFactory(nil, ctrl.Log.WithName("test"), oathkeeperSvc, oathkeeperSvcPort, testCors, testAdditionalLabels, defaultDomain)

desiredState := f.CalculateRequiredState(apiRule)
desiredState := f.CalculateRequiredState(apiRule, &config)
vs := desiredState.virtualService
accessRules := desiredState.accessRules

Expand Down Expand Up @@ -186,7 +191,7 @@ var _ = Describe("Factory", func() {

f := NewFactory(nil, ctrl.Log.WithName("test"), oathkeeperSvc, oathkeeperSvcPort, testCors, testAdditionalLabels, defaultDomain)

desiredState := f.CalculateRequiredState(apiRule)
desiredState := f.CalculateRequiredState(apiRule, &config)
vs := desiredState.virtualService
accessRules := desiredState.accessRules

Expand Down Expand Up @@ -228,7 +233,7 @@ var _ = Describe("Factory", func() {

f := NewFactory(nil, ctrl.Log.WithName("test"), oathkeeperSvc, oathkeeperSvcPort, testCors, testAdditionalLabels, defaultDomain)

desiredState := f.CalculateRequiredState(apiRule)
desiredState := f.CalculateRequiredState(apiRule, &config)
vs := desiredState.virtualService
accessRules := desiredState.accessRules

Expand Down Expand Up @@ -268,7 +273,7 @@ var _ = Describe("Factory", func() {

f := NewFactory(nil, ctrl.Log.WithName("test"), oathkeeperSvc, oathkeeperSvcPort, testCors, testAdditionalLabels, defaultDomain)

desiredState := f.CalculateRequiredState(apiRule)
desiredState := f.CalculateRequiredState(apiRule, &config)
vs := desiredState.virtualService
accessRules := desiredState.accessRules

Expand Down Expand Up @@ -306,7 +311,7 @@ var _ = Describe("Factory", func() {

f := NewFactory(nil, ctrl.Log.WithName("test"), oathkeeperSvc, oathkeeperSvcPort, testCors, testAdditionalLabels, defaultDomain)

desiredState := f.CalculateRequiredState(apiRule)
desiredState := f.CalculateRequiredState(apiRule, &config)
vs := desiredState.virtualService
accessRules := desiredState.accessRules

Expand Down Expand Up @@ -370,7 +375,7 @@ var _ = Describe("Factory", func() {

f := NewFactory(nil, ctrl.Log.WithName("test"), oathkeeperSvc, oathkeeperSvcPort, testCors, testAdditionalLabels, defaultDomain)

desiredState := f.CalculateRequiredState(apiRule)
desiredState := f.CalculateRequiredState(apiRule, &config)
vs := desiredState.virtualService
accessRules := desiredState.accessRules

Expand Down Expand Up @@ -530,7 +535,7 @@ var _ = Describe("Factory", func() {

f := NewFactory(nil, ctrl.Log.WithName("test"), oathkeeperSvc, oathkeeperSvcPort, testCors, testAdditionalLabels, defaultDomain)

desiredState := f.CalculateRequiredState(apiRule)
desiredState := f.CalculateRequiredState(apiRule, &config)
vs := desiredState.virtualService
accessRules := desiredState.accessRules

Expand Down Expand Up @@ -683,7 +688,7 @@ var _ = Describe("Factory", func() {

f := NewFactory(nil, ctrl.Log.WithName("test"), oathkeeperSvc, oathkeeperSvcPort, testCors, testAdditionalLabels, defaultDomain)

desiredState := f.CalculateRequiredState(apiRule)
desiredState := f.CalculateRequiredState(apiRule, &config)
vs := desiredState.virtualService
accessRules := desiredState.accessRules

Expand Down Expand Up @@ -851,7 +856,7 @@ var _ = Describe("Factory", func() {

f := NewFactory(nil, ctrl.Log.WithName("test"), oathkeeperSvc, oathkeeperSvcPort, testCors, testAdditionalLabels, defaultDomain)

desiredState := f.CalculateRequiredState(apiRule)
desiredState := f.CalculateRequiredState(apiRule, &config)
vs := desiredState.virtualService
accessRules := desiredState.accessRules

Expand Down Expand Up @@ -971,7 +976,7 @@ var _ = Describe("Factory", func() {

f := NewFactory(nil, ctrl.Log.WithName("test"), oathkeeperSvc, oathkeeperSvcPort, testCors, testAdditionalLabels, defaultDomain)

desiredState := f.CalculateRequiredState(apiRule)
desiredState := f.CalculateRequiredState(apiRule, &config)
vs := desiredState.virtualService
accessRules := desiredState.accessRules

Expand Down Expand Up @@ -1063,7 +1068,7 @@ var _ = Describe("Factory", func() {

f := NewFactory(nil, ctrl.Log.WithName("test"), oathkeeperSvc, oathkeeperSvcPort, testCors, testAdditionalLabels, defaultDomain)

desiredState := f.CalculateRequiredState(apiRule)
desiredState := f.CalculateRequiredState(apiRule, &config)
actualState := &State{}

patch := f.CalculateDiff(desiredState, actualState)
Expand Down Expand Up @@ -1110,7 +1115,7 @@ var _ = Describe("Factory", func() {

f := NewFactory(nil, ctrl.Log.WithName("test"), oathkeeperSvc, oathkeeperSvcPort, testCors, testAdditionalLabels, defaultDomain)

desiredState := f.CalculateRequiredState(apiRule)
desiredState := f.CalculateRequiredState(apiRule, &config)
oauthNoopRuleMatchURL := fmt.Sprintf("<http|https>://%s<%s>", serviceHost, oauthAPIPath)
expectedNoopRuleMatchURL := fmt.Sprintf("<http|https>://%s<%s>", serviceHost, headersAPIPath)
notDesiredRuleMatchURL := fmt.Sprintf("<http|https>://%s<%s>", serviceHost, "/delete")
Expand Down
7 changes: 5 additions & 2 deletions internal/validation/dummy.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package validation

import gatewayv1beta1 "github.com/kyma-incubator/api-gateway/api/v1beta1"
import (
gatewayv1beta1 "github.com/kyma-incubator/api-gateway/api/v1beta1"
"github.com/kyma-incubator/api-gateway/internal/helpers"
)

// dummy is an accessStrategy validator that does nothing
type dummyAccStrValidator struct{}

func (dummy *dummyAccStrValidator) Validate(attrPath string, handler *gatewayv1beta1.Handler) []Failure {
func (dummy *dummyAccStrValidator) Validate(attrPath string, handler *gatewayv1beta1.Handler, config *helpers.Config) []Failure {
return nil
}
Loading

0 comments on commit 202a16c

Please sign in to comment.