Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sotw: rlp workflow #893

Merged
merged 60 commits into from
Oct 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
e7d4a67
sotw: effective ratelimitpolicy
guicassolato Sep 27, 2024
9e21c61
removed unused function to apply rlp overrides
guicassolato Oct 8, 2024
688be2c
istio extension (WasmPlugin) reconciler
guicassolato Oct 8, 2024
1cbf4c9
fixup: unique limit definitions per scope
guicassolato Oct 8, 2024
7d0b7e9
fixup: log error only when indeed there's an error to be logged
guicassolato Oct 8, 2024
e60aed0
do not fail when missing kuadrant object
guicassolato Oct 8, 2024
962510d
fixup: equality between wasmplugins and avoid rebuilding wasm config …
guicassolato Oct 8, 2024
77158b3
fixup: error comparison
guicassolato Oct 8, 2024
d9256ab
cleanup istio extension objects when it cannot calculate effective po…
guicassolato Oct 8, 2024
8d4414a
refactor: removal of SortablePolicy for sorting policies objects by c…
guicassolato Oct 9, 2024
78c2175
remove no longer relevant integration test case
guicassolato Oct 9, 2024
fe28e06
fixup: avoid updating invalid rate limit policies to 'accepted' on ev…
guicassolato Oct 9, 2024
42846b9
fixup: continue istio extension workflow when it fails for a given ga…
guicassolato Oct 10, 2024
0b30d5b
Remove unnused event recorder from base reconciler
guicassolato Oct 10, 2024
a3b646e
Istio rate limit cluster reconciler
guicassolato Oct 10, 2024
6db892f
enable Istio-related rate limit tasks only when Istio is installed
guicassolato Oct 10, 2024
1e57ef4
ensure at least one hostname per wasm config policy
guicassolato Oct 10, 2024
063390e
bump istio to 1.22
guicassolato Oct 11, 2024
30b13cd
Use targetRefs to attach to gateways in the Istio EnvoyFilter and Was…
guicassolato Oct 11, 2024
ebbdf9f
refactor: debug log messages for when Limitador, EnvoyFilter and Wasm…
guicassolato Oct 12, 2024
6b8fff4
sort wasm 'policies' within the wasm plugin config by hostname from m…
guicassolato Oct 12, 2024
fae64cd
go fmt: refactor: debug log messages for when Limitador, EnvoyFilter …
guicassolato Oct 12, 2024
8ce2f58
sort wasm 'policies' within the wasm plugin config by hostname and ht…
guicassolato Oct 12, 2024
6f7a812
code style: remove unused parameter ctx
guicassolato Oct 12, 2024
9a50401
fix: unit test: sort wasm 'policies' within the wasm plugin config by…
guicassolato Oct 12, 2024
4ed7b3e
Refactor WasmPlugin reconciliation to reduce repetition with EnvoyExt…
guicassolato Oct 14, 2024
0a99570
envoy gateway rate limit cluster reconciler
guicassolato Oct 14, 2024
3ef09d3
fix: wrong default GroupKind assumed on Istio policies TargetRefs
guicassolato Oct 15, 2024
ca820d1
minor fixes to code comments and log messages
guicassolato Oct 15, 2024
9d4aad1
envoy gateway extension reconciler
guicassolato Oct 15, 2024
384b230
code style: ratelimit.RateLimitIndex -> Index
guicassolato Oct 15, 2024
4e5c7c5
code style: wasm.WasmExtensionName -> ExtensionName
guicassolato Oct 15, 2024
f071fbd
code style: wasm.WasmRuleBuilderFunc -> RuleBuilderFunc
guicassolato Oct 15, 2024
b676b86
code style: fix grouping of go imports
guicassolato Oct 15, 2024
341f7ab
new structure of the wasm config based on https://github.com/Kuadrant…
guicassolato Oct 15, 2024
7683ef2
fix: envoy_gateway_extension_reconciler.go file name
guicassolato Oct 16, 2024
1ba85f6
fix: log messages of envoy patch policy reconciliation
guicassolato Oct 16, 2024
a6673ba
rlp enforced condition and consistency in the message when target not…
guicassolato Oct 16, 2024
de8d2c7
tests: gateway extension reconciler tests resource comparison
guicassolato Oct 16, 2024
8c67cc5
more descriptive wasm actionset names
guicassolato Oct 17, 2024
9c99f61
tests: fix integration tests - order of wasm action sets
guicassolato Oct 17, 2024
e29420d
fixup: should not increment twice on the index of http route match wh…
guicassolato Oct 17, 2024
c17818d
tests: fix integration tests - order of wasm action sets (again!)
guicassolato Oct 17, 2024
6321b35
back to opaque wasm action set names
guicassolato Oct 17, 2024
a4516d5
remove duplicate GetKuadrantFromTopology func
guicassolato Oct 17, 2024
e142372
do not isolate policy-machinery imports in a separate group
guicassolato Oct 17, 2024
c19a78b
helper function to extract network objects in a request path
guicassolato Oct 17, 2024
fe75a17
set owner reference directly when building the desired objects
guicassolato Oct 17, 2024
7fe21ee
only validate policies on create and update events
guicassolato Oct 18, 2024
3388d57
update policy status on all kinds of policy-releated event (deleting …
guicassolato Oct 18, 2024
baeb961
use labels on the internal resources created to watch and select them…
guicassolato Oct 18, 2024
4f66c9a
policy not enforced due to 'not in the path to any existing routes' (…
guicassolato Oct 18, 2024
4c9996d
tests: fix integration tests - Istio EnvoyFilter only created if RLP …
guicassolato Oct 18, 2024
fe85021
lint: removed unnused func arg in the tests
guicassolato Oct 18, 2024
2245a38
tests: fix integration tests - Istio WasmPlugin config with correct l…
guicassolato Oct 18, 2024
1e66d6f
check state of the targeted resources to define the policy's enforced…
guicassolato Oct 18, 2024
144f340
re-enable RateLimitPolicy discoverability (PolicyAffected status cond…
guicassolato Oct 18, 2024
7d83a8c
tests: fix integration tests - common ratelimit workflow tests
guicassolato Oct 18, 2024
fa62eb0
refactor: common.NamespacedNameFromLocator func
guicassolato Oct 18, 2024
b2d57ea
hack to isolate test namespaces sharing the same limitador cr
guicassolato Oct 18, 2024
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
200 changes: 200 additions & 0 deletions api/v1/merge_strategies.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
/*
Copyright 2024.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package v1

import (
"sort"
"strings"

"github.com/kuadrant/policy-machinery/controller"
"github.com/kuadrant/policy-machinery/machinery"
"github.com/samber/lo"
"k8s.io/apimachinery/pkg/runtime"
k8stypes "k8s.io/apimachinery/pkg/types"
)

const (
AtomicMergeStrategy = "atomic"
PolicyRuleMergeStrategy = "merge"
)

type MergeableRule struct {
Spec any
Source string
}

// +kubebuilder:object:generate=false
type MergeablePolicy interface {
machinery.Policy

Rules() map[string]MergeableRule
SetRules(map[string]MergeableRule)
Empty() bool

DeepCopyObject() runtime.Object
}

// AtomicDefaultsMergeStrategy implements a merge strategy that returns the target Policy if it exists,
// otherwise it returns the source Policy.
func AtomicDefaultsMergeStrategy(source, target machinery.Policy) machinery.Policy {
if source == nil {
return target
}

Check warning on line 56 in api/v1/merge_strategies.go

View check run for this annotation

Codecov / codecov/patch

api/v1/merge_strategies.go#L55-L56

Added lines #L55 - L56 were not covered by tests
if target == nil {
return source
}

Check warning on line 59 in api/v1/merge_strategies.go

View check run for this annotation

Codecov / codecov/patch

api/v1/merge_strategies.go#L58-L59

Added lines #L58 - L59 were not covered by tests

mergeableTargetPolicy := target.(MergeablePolicy)

if !mergeableTargetPolicy.Empty() {
return mergeableTargetPolicy.DeepCopyObject().(machinery.Policy)
}

return source.(MergeablePolicy).DeepCopyObject().(machinery.Policy)

Check warning on line 67 in api/v1/merge_strategies.go

View check run for this annotation

Codecov / codecov/patch

api/v1/merge_strategies.go#L67

Added line #L67 was not covered by tests
}

var _ machinery.MergeStrategy = AtomicDefaultsMergeStrategy

// AtomicOverridesMergeStrategy implements a merge strategy that overrides a target Policy with
// a source one.
func AtomicOverridesMergeStrategy(source, _ machinery.Policy) machinery.Policy {
if source == nil {
return nil
}

Check warning on line 77 in api/v1/merge_strategies.go

View check run for this annotation

Codecov / codecov/patch

api/v1/merge_strategies.go#L76-L77

Added lines #L76 - L77 were not covered by tests
return source.(MergeablePolicy).DeepCopyObject().(machinery.Policy)
}

var _ machinery.MergeStrategy = AtomicOverridesMergeStrategy

// PolicyRuleDefaultsMergeStrategy implements a merge strategy that merges a source Policy into a target one
// by keeping the policy rules from the target and adding the ones from the source that do not exist in the target.
func PolicyRuleDefaultsMergeStrategy(source, target machinery.Policy) machinery.Policy {
if source == nil {
return target
}
if target == nil {
return source
}

Check warning on line 91 in api/v1/merge_strategies.go

View check run for this annotation

Codecov / codecov/patch

api/v1/merge_strategies.go#L85-L91

Added lines #L85 - L91 were not covered by tests

sourceMergeablePolicy := source.(MergeablePolicy)
targetMergeablePolicy := target.(MergeablePolicy)

// copy rules from the target
rules := targetMergeablePolicy.Rules()

// add extra rules from the source
for ruleID, rule := range sourceMergeablePolicy.Rules() {
if _, ok := targetMergeablePolicy.Rules()[ruleID]; !ok {
rules[ruleID] = MergeableRule{
Spec: rule.Spec,
Source: source.GetLocator(),
}
}

Check warning on line 106 in api/v1/merge_strategies.go

View check run for this annotation

Codecov / codecov/patch

api/v1/merge_strategies.go#L93-L106

Added lines #L93 - L106 were not covered by tests
}

mergedPolicy := targetMergeablePolicy.DeepCopyObject().(MergeablePolicy)
mergedPolicy.SetRules(rules)
return mergedPolicy

Check warning on line 111 in api/v1/merge_strategies.go

View check run for this annotation

Codecov / codecov/patch

api/v1/merge_strategies.go#L109-L111

Added lines #L109 - L111 were not covered by tests
}

var _ machinery.MergeStrategy = PolicyRuleDefaultsMergeStrategy

// PolicyRuleOverridesMergeStrategy implements a merge strategy that merges a source Policy into a target one
// by using the policy rules from the source and keeping from the target only the policy rules that do not exist in
// the source.
func PolicyRuleOverridesMergeStrategy(source, target machinery.Policy) machinery.Policy {
sourceMergeablePolicy := source.(MergeablePolicy)
targetMergeablePolicy := target.(MergeablePolicy)

// copy rules from the source
rules := sourceMergeablePolicy.Rules()

// add extra rules from the target
for ruleID, rule := range targetMergeablePolicy.Rules() {
if _, ok := sourceMergeablePolicy.Rules()[ruleID]; !ok {
rules[ruleID] = rule
}

Check warning on line 130 in api/v1/merge_strategies.go

View check run for this annotation

Codecov / codecov/patch

api/v1/merge_strategies.go#L119-L130

Added lines #L119 - L130 were not covered by tests
}

mergedPolicy := targetMergeablePolicy.DeepCopyObject().(MergeablePolicy)
mergedPolicy.SetRules(rules)
return mergedPolicy

Check warning on line 135 in api/v1/merge_strategies.go

View check run for this annotation

Codecov / codecov/patch

api/v1/merge_strategies.go#L133-L135

Added lines #L133 - L135 were not covered by tests
}

var _ machinery.MergeStrategy = PolicyRuleOverridesMergeStrategy

func DefaultsMergeStrategy(strategy string) machinery.MergeStrategy {
switch strategy {
case AtomicMergeStrategy:
return AtomicDefaultsMergeStrategy
case PolicyRuleMergeStrategy:
return PolicyRuleDefaultsMergeStrategy
default:
return AtomicDefaultsMergeStrategy

Check warning on line 147 in api/v1/merge_strategies.go

View check run for this annotation

Codecov / codecov/patch

api/v1/merge_strategies.go#L144-L147

Added lines #L144 - L147 were not covered by tests
}
}

func OverridesMergeStrategy(strategy string) machinery.MergeStrategy {
switch strategy {
case AtomicMergeStrategy:
return AtomicOverridesMergeStrategy
case PolicyRuleMergeStrategy:
return PolicyRuleOverridesMergeStrategy
default:
return AtomicOverridesMergeStrategy

Check warning on line 158 in api/v1/merge_strategies.go

View check run for this annotation

Codecov / codecov/patch

api/v1/merge_strategies.go#L155-L158

Added lines #L155 - L158 were not covered by tests
}
}

// EffectivePolicyForPath returns the effective policy for a given path, merging all policies in the path.
// The policies in the path are sorted from the least specific to the most specific.
// Only policies whose predicate returns true are considered.
func EffectivePolicyForPath[T machinery.Policy](path []machinery.Targetable, predicate func(machinery.Policy) bool) *T {
policies := PoliciesInPath(path, predicate)
if len(policies) == 0 {
return nil
}

// map reduces the policies from most specific to least specific, merging them into one effective policy
effectivePolicy := lo.ReduceRight(policies, func(effectivePolicy machinery.Policy, policy machinery.Policy, _ int) machinery.Policy {
return effectivePolicy.Merge(policy)
}, policies[len(policies)-1])

concreteEffectivePolicy, _ := effectivePolicy.(T)
return &concreteEffectivePolicy
}

// OrderedPoliciesForPath gathers all policies in a path sorted from the least specific to the most specific.
// Only policies whose predicate returns true are considered.
func PoliciesInPath(path []machinery.Targetable, predicate func(machinery.Policy) bool) []machinery.Policy {
return lo.FlatMap(path, func(targetable machinery.Targetable, _ int) []machinery.Policy {
policies := lo.FilterMap(targetable.Policies(), func(policy machinery.Policy, _ int) (controller.Object, bool) {
o, object := policy.(controller.Object)
return o, object && predicate(policy)
})
sort.Sort(controller.ObjectsByCreationTimestamp(policies))
return lo.Map(policies, func(policy controller.Object, _ int) machinery.Policy {
p, _ := policy.(machinery.Policy)
return p
})
})
}

func PathID(path []machinery.Targetable) string {
return strings.Join(lo.Map(path, func(t machinery.Targetable, _ int) string {
return strings.TrimPrefix(k8stypes.NamespacedName{Namespace: t.GetNamespace(), Name: t.GetName()}.String(), string(k8stypes.Separator))
}), "|")
}
32 changes: 21 additions & 11 deletions api/v1beta3/groupversion_info.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright 2021.
Copyright 2024.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand All @@ -14,23 +14,33 @@
limitations under the License.
*/

// Package v1beta3 contains API Schema definitions for the kuadrant v1beta3 API group
// API schema definitions for the Kuadrant v1beta3 API group
// +kubebuilder:object:generate=true
// +groupName=kuadrant.io
package v1beta3

import (
"k8s.io/apimachinery/pkg/runtime/schema"
"sigs.k8s.io/controller-runtime/pkg/scheme"
ctrl "sigs.k8s.io/controller-runtime/pkg/scheme"
)

var (
// GroupVersion is group version used to register these objects
GroupVersion = schema.GroupVersion{Group: "kuadrant.io", Version: "v1beta3"}
// GroupName specifies the group name used to register the objects.
const GroupName = "kuadrant.io"

// SchemeBuilder is used to add go types to the GroupVersionKind scheme
SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion}
// GroupVersion specifies the group and the version used to register the objects.
var GroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1beta3"}

// AddToScheme adds the types in this group-version to the given scheme.
AddToScheme = SchemeBuilder.AddToScheme
)
// SchemeGroupVersion is group version used to register these objects
// Deprecated: use GroupVersion instead.
var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1beta3"}

// SchemeBuilder is used to add go types to the GroupVersionKind scheme
var SchemeBuilder = &ctrl.Builder{GroupVersion: GroupVersion}

// AddToScheme adds the types in this group-version to the given scheme.
var AddToScheme = SchemeBuilder.AddToScheme

// Resource takes an unqualified resource and returns a Group qualified GroupResource
func Resource(resource string) schema.GroupResource {
return SchemeGroupVersion.WithResource(resource).GroupResource()

Check warning on line 45 in api/v1beta3/groupversion_info.go

View check run for this annotation

Codecov / codecov/patch

api/v1beta3/groupversion_info.go#L44-L45

Added lines #L44 - L45 were not covered by tests
}
Loading
Loading