diff --git a/adapter/go.mod b/adapter/go.mod index a43b82e128..eeb7f4350b 100644 --- a/adapter/go.mod +++ b/adapter/go.mod @@ -15,7 +15,7 @@ require ( github.com/wso2/apk/common-go-libs v0.0.0-20231208100153-24bee7b4bd81 golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb google.golang.org/grpc v1.62.0 - google.golang.org/protobuf v1.33.0 + google.golang.org/protobuf v1.34.1 gopkg.in/yaml.v2 v2.4.0 k8s.io/api v0.29.2 k8s.io/apimachinery v0.29.2 diff --git a/adapter/go.sum b/adapter/go.sum index d92a48c78a..9bc0af125c 100644 --- a/adapter/go.sum +++ b/adapter/go.sum @@ -244,8 +244,8 @@ google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk= google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= +google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/adapter/internal/oasparser/envoyconf/routes_configs.go b/adapter/internal/oasparser/envoyconf/routes_configs.go index 585ab47bab..12b87c0a25 100644 --- a/adapter/internal/oasparser/envoyconf/routes_configs.go +++ b/adapter/internal/oasparser/envoyconf/routes_configs.go @@ -28,6 +28,7 @@ import ( routev3 "github.com/envoyproxy/go-control-plane/envoy/config/route/v3" extAuthService "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/ext_authz/v3" envoy_type_matcherv3 "github.com/envoyproxy/go-control-plane/envoy/type/matcher/v3" + metadatav3 "github.com/envoyproxy/go-control-plane/envoy/type/metadata/v3" "github.com/envoyproxy/go-control-plane/pkg/wellknown" "github.com/golang/protobuf/ptypes/any" logger "github.com/wso2/apk/adapter/internal/loggers" @@ -41,6 +42,21 @@ import ( gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" ) +// Constants for Rate Limiting +const ( + DescriptorKeyForSubscription = "subscription" + DescriptorKeyForPolicy = "policy" + DescriptorKeyForOrganization = "organization" + extAuthzFilterName = "envoy.filters.http.ext_authz" + + descriptorMetadataKeyForSubscription = "ratelimit:subscription" + descriptorMetadataKeyForUsagePolicy = "ratelimit:usage-policy" + descriptorMetadataKeyForOrganization = "ratelimit:organization" + descriptorMetadataKeyForBurstCtrlSubscription = "burstCtrl:subscription" + descriptorMetadataKeyForBurstCtrlUsagePolicy = "burstCtrl:usage-policy" + descriptorMetadataKeyForBurstCtrlOrganization = "burstCtrl:organization" +) + func generateRouteConfig(routeName string, match *routev3.RouteMatch, action *routev3.Route_Route, redirectAction *routev3.Route_Redirect, metadata *corev3.Metadata, decorator *routev3.Decorator, typedPerFilterConfig map[string]*anypb.Any, requestHeadersToAdd []*corev3.HeaderValueOption, requestHeadersToRemove []string, @@ -168,7 +184,6 @@ func mapStatusCodeToEnum(statusCode int) int { } func generateRateLimitPolicy(ratelimitCriteria *ratelimitCriteria) []*routev3.RateLimit { - environmentValue := ratelimitCriteria.environment if ratelimitCriteria.level != RateLimitPolicyAPILevel && ratelimitCriteria.envType == opConstants.Sandbox { environmentValue += "_sandbox" @@ -223,7 +238,10 @@ func generateRateLimitPolicy(ratelimitCriteria *ratelimitCriteria) []*routev3.Ra }, }) } - return []*routev3.RateLimit{&rateLimit} + + ratelimits := []*routev3.RateLimit{&rateLimit} + ratelimits = addSubscriptionRatelimitActions(ratelimits) + return ratelimits } func generateHTTPMethodMatcher(methodRegex string, sandClusterName string) []*routev3.HeaderMatcher { @@ -263,6 +281,139 @@ func generateHeaderMatcher(headerName, valueRegex string) *routev3.HeaderMatcher return headerMatcherArray } +func addSubscriptionRatelimitActions(actions []*routev3.RateLimit) []*routev3.RateLimit { + return append(actions, + &routev3.RateLimit{ + Actions: []*routev3.RateLimit_Action{ + { + ActionSpecifier: &routev3.RateLimit_Action_Metadata{ + Metadata: &routev3.RateLimit_Action_MetaData{ + DescriptorKey: DescriptorKeyForOrganization, + MetadataKey: &metadatav3.MetadataKey{ + Key: extAuthzFilterName, + Path: []*metadatav3.MetadataKey_PathSegment{ + { + Segment: &metadatav3.MetadataKey_PathSegment_Key{ + Key: descriptorMetadataKeyForOrganization, + }, + }, + }, + }, + Source: routev3.RateLimit_Action_MetaData_DYNAMIC, + SkipIfAbsent: true, + }, + }, + }, + { + ActionSpecifier: &routev3.RateLimit_Action_Metadata{ + Metadata: &routev3.RateLimit_Action_MetaData{ + DescriptorKey: DescriptorKeyForSubscription, + MetadataKey: &metadatav3.MetadataKey{ + Key: extAuthzFilterName, + Path: []*metadatav3.MetadataKey_PathSegment{ + { + Segment: &metadatav3.MetadataKey_PathSegment_Key{ + Key: descriptorMetadataKeyForSubscription, + }, + }, + }, + }, + Source: routev3.RateLimit_Action_MetaData_DYNAMIC, + SkipIfAbsent: true, + }, + }, + }, + { + ActionSpecifier: &routev3.RateLimit_Action_Metadata{ + Metadata: &routev3.RateLimit_Action_MetaData{ + DescriptorKey: DescriptorKeyForPolicy, + MetadataKey: &metadatav3.MetadataKey{ + Key: extAuthzFilterName, + Path: []*metadatav3.MetadataKey_PathSegment{ + { + Segment: &metadatav3.MetadataKey_PathSegment_Key{ + Key: descriptorMetadataKeyForUsagePolicy, + }, + }, + }, + }, + Source: routev3.RateLimit_Action_MetaData_DYNAMIC, + SkipIfAbsent: true, + }, + }, + }, + }, + }, &routev3.RateLimit{ + Actions: []*routev3.RateLimit_Action{ + { + ActionSpecifier: &routev3.RateLimit_Action_Metadata{ + Metadata: &routev3.RateLimit_Action_MetaData{ + DescriptorKey: DescriptorKeyForOrganization, + MetadataKey: &metadatav3.MetadataKey{ + Key: extAuthzFilterName, + Path: []*metadatav3.MetadataKey_PathSegment{ + { + Segment: &metadatav3.MetadataKey_PathSegment_Key{ + Key: descriptorMetadataKeyForOrganization, + }, + }, + }, + }, + Source: routev3.RateLimit_Action_MetaData_DYNAMIC, + SkipIfAbsent: true, + }, + }, + }, + { + ActionSpecifier: &routev3.RateLimit_Action_Metadata{ + Metadata: &routev3.RateLimit_Action_MetaData{ + DescriptorKey: DescriptorKeyForSubscription, + MetadataKey: &metadatav3.MetadataKey{ + Key: extAuthzFilterName, + Path: []*metadatav3.MetadataKey_PathSegment{ + { + Segment: &metadatav3.MetadataKey_PathSegment_Key{ + Key: descriptorMetadataKeyForSubscription, + }, + }, + }, + }, + Source: routev3.RateLimit_Action_MetaData_DYNAMIC, + SkipIfAbsent: true, + }, + }, + }, + { + ActionSpecifier: &routev3.RateLimit_Action_Metadata{ + Metadata: &routev3.RateLimit_Action_MetaData{ + DescriptorKey: DescriptorKeyForPolicy, + MetadataKey: &metadatav3.MetadataKey{ + Key: extAuthzFilterName, + Path: []*metadatav3.MetadataKey_PathSegment{ + { + Segment: &metadatav3.MetadataKey_PathSegment_Key{ + Key: descriptorMetadataKeyForUsagePolicy, + }, + }, + }, + }, + Source: routev3.RateLimit_Action_MetaData_DYNAMIC, + SkipIfAbsent: true, + }, + }, + }, + { + ActionSpecifier: &routev3.RateLimit_Action_GenericKey_{ + GenericKey: &routev3.RateLimit_Action_GenericKey{ + DescriptorKey: "burst", + DescriptorValue: "enabled", + }, + }, + }, + }, + }) +} + func generateRegexMatchAndSubstitute(routePath, endpointResourcePath string, pathMatchType gwapiv1.PathMatchType) *envoy_type_matcherv3.RegexMatchAndSubstitute { substitutionString := generateSubstitutionString(endpointResourcePath, pathMatchType) diff --git a/adapter/internal/oasparser/model/adapter_internal_api.go b/adapter/internal/oasparser/model/adapter_internal_api.go index 3d7e4b838d..061f6c27ee 100644 --- a/adapter/internal/oasparser/model/adapter_internal_api.go +++ b/adapter/internal/oasparser/model/adapter_internal_api.go @@ -33,6 +33,7 @@ import ( "github.com/wso2/apk/adapter/internal/operator/utils" dpv1alpha1 "github.com/wso2/apk/common-go-libs/apis/dp/v1alpha1" dpv1alpha2 "github.com/wso2/apk/common-go-libs/apis/dp/v1alpha2" + dpv1alpha3 "github.com/wso2/apk/common-go-libs/apis/dp/v1alpha3" "golang.org/x/exp/maps" "k8s.io/apimachinery/pkg/types" gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" @@ -463,7 +464,7 @@ func (adapterInternalAPI *AdapterInternalAPI) SetInfoHTTPRouteCR(httpRoute *gwap if outputAPIPolicy != nil { apiPolicy = *outputAPIPolicy } - var ratelimitPolicy *dpv1alpha1.RateLimitPolicy + var ratelimitPolicy *dpv1alpha3.RateLimitPolicy if outputRatelimitPolicy != nil { ratelimitPolicy = *outputRatelimitPolicy } @@ -946,7 +947,7 @@ func (adapterInternalAPI *AdapterInternalAPI) SetInfoGQLRouteCR(gqlRoute *dpv1al if outputAPIPolicy != nil { apiPolicy = *outputAPIPolicy } - var ratelimitPolicy *dpv1alpha1.RateLimitPolicy + var ratelimitPolicy *dpv1alpha3.RateLimitPolicy if outputRatelimitPolicy != nil { ratelimitPolicy = *outputRatelimitPolicy } diff --git a/adapter/internal/oasparser/model/custom_ratelimit_policy.go b/adapter/internal/oasparser/model/custom_ratelimit_policy.go index bd9b8b4b4d..43b2e47f95 100644 --- a/adapter/internal/oasparser/model/custom_ratelimit_policy.go +++ b/adapter/internal/oasparser/model/custom_ratelimit_policy.go @@ -17,7 +17,9 @@ package model -import dpv1alpha1 "github.com/wso2/apk/common-go-libs/apis/dp/v1alpha1" +import ( + dpv1alpha3 "github.com/wso2/apk/common-go-libs/apis/dp/v1alpha3" +) // RateLimit is the rate limit values for a policy type RateLimit struct { @@ -39,7 +41,7 @@ type CustomRateLimitPolicy struct { } // ParseCustomRateLimitPolicy parses the custom rate limit policy -func ParseCustomRateLimitPolicy(customRateLimitCR dpv1alpha1.RateLimitPolicy) *CustomRateLimitPolicy { +func ParseCustomRateLimitPolicy(customRateLimitCR dpv1alpha3.RateLimitPolicy) *CustomRateLimitPolicy { rlPolicy := concatRateLimitPolicies(&customRateLimitCR, nil) return &CustomRateLimitPolicy{ Key: rlPolicy.Spec.Override.Custom.Key, diff --git a/adapter/internal/oasparser/model/http_route.go b/adapter/internal/oasparser/model/http_route.go index 96c6293d82..71ad97b12a 100644 --- a/adapter/internal/oasparser/model/http_route.go +++ b/adapter/internal/oasparser/model/http_route.go @@ -24,6 +24,7 @@ import ( "github.com/wso2/apk/adapter/internal/operator/utils" dpv1alpha1 "github.com/wso2/apk/common-go-libs/apis/dp/v1alpha1" dpv1alpha2 "github.com/wso2/apk/common-go-libs/apis/dp/v1alpha2" + dpv1alpha3 "github.com/wso2/apk/common-go-libs/apis/dp/v1alpha3" "k8s.io/apimachinery/pkg/types" gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" ) @@ -38,8 +39,8 @@ type ResourceParams struct { BackendJWTMapping map[string]dpv1alpha1.BackendJWT BackendMapping map[string]*dpv1alpha2.ResolvedBackend ResourceScopes map[string]dpv1alpha1.Scope - RateLimitPolicies map[string]dpv1alpha1.RateLimitPolicy - ResourceRateLimitPolicies map[string]dpv1alpha1.RateLimitPolicy + RateLimitPolicies map[string]dpv1alpha3.RateLimitPolicy + ResourceRateLimitPolicies map[string]dpv1alpha3.RateLimitPolicy } func parseBackendJWTTokenToInternal(backendJWTToken dpv1alpha1.BackendJWTSpec) *BackendJWTTokenInfo { @@ -96,7 +97,7 @@ func getCorsConfigFromAPIPolicy(apiPolicy *dpv1alpha2.APIPolicy) *CorsConfig { return &corsConfig } -func parseRateLimitPolicyToInternal(ratelimitPolicy *dpv1alpha1.RateLimitPolicy) *RateLimitPolicy { +func parseRateLimitPolicyToInternal(ratelimitPolicy *dpv1alpha3.RateLimitPolicy) *RateLimitPolicy { var rateLimitPolicyInternal *RateLimitPolicy if ratelimitPolicy != nil && ratelimitPolicy.Spec.Override != nil { if ratelimitPolicy.Spec.Override.API.RequestsPerUnit > 0 { @@ -191,8 +192,8 @@ func GetBackendBasePath(backendName types.NamespacedName, backendMapping map[str return "" } -func concatRateLimitPolicies(schemeUp *dpv1alpha1.RateLimitPolicy, schemeDown *dpv1alpha1.RateLimitPolicy) *dpv1alpha1.RateLimitPolicy { - finalRateLimit := dpv1alpha1.RateLimitPolicy{} +func concatRateLimitPolicies(schemeUp *dpv1alpha3.RateLimitPolicy, schemeDown *dpv1alpha3.RateLimitPolicy) *dpv1alpha3.RateLimitPolicy { + finalRateLimit := dpv1alpha3.RateLimitPolicy{} if schemeUp != nil && schemeDown != nil { finalRateLimit.Spec.Override = utils.SelectPolicy(&schemeUp.Spec.Override, &schemeUp.Spec.Default, &schemeDown.Spec.Override, &schemeDown.Spec.Default) } else if schemeUp != nil { diff --git a/adapter/internal/oasparser/model/http_route_test.go b/adapter/internal/oasparser/model/http_route_test.go index 580ac9a48f..b17fd72c85 100644 --- a/adapter/internal/oasparser/model/http_route_test.go +++ b/adapter/internal/oasparser/model/http_route_test.go @@ -21,43 +21,43 @@ import ( "testing" "github.com/stretchr/testify/assert" - dpv1alpha1 "github.com/wso2/apk/common-go-libs/apis/dp/v1alpha1" dpv1alpha2 "github.com/wso2/apk/common-go-libs/apis/dp/v1alpha2" + dpv1alpha3 "github.com/wso2/apk/common-go-libs/apis/dp/v1alpha3" ) func TestConcatRateLimitPolicies(t *testing.T) { type testItem struct { - schemeUpSpec dpv1alpha1.RateLimitPolicySpec - schemeDownSpec dpv1alpha1.RateLimitPolicySpec - result dpv1alpha1.RateLimitPolicySpec + schemeUpSpec dpv1alpha3.RateLimitPolicySpec + schemeDownSpec dpv1alpha3.RateLimitPolicySpec + result dpv1alpha3.RateLimitPolicySpec message string } - schemeUp := &dpv1alpha1.RateLimitPolicy{} - schemeDown := &dpv1alpha1.RateLimitPolicy{} - resultScheme := &dpv1alpha1.RateLimitPolicy{} + schemeUp := &dpv1alpha3.RateLimitPolicy{} + schemeDown := &dpv1alpha3.RateLimitPolicy{} + resultScheme := &dpv1alpha3.RateLimitPolicy{} dataItems := []testItem{ { - schemeUpSpec: dpv1alpha1.RateLimitPolicySpec{ - Override: &dpv1alpha1.RateLimitAPIPolicy{ - API: &dpv1alpha1.APIRateLimitPolicy{ + schemeUpSpec: dpv1alpha3.RateLimitPolicySpec{ + Override: &dpv1alpha3.RateLimitAPIPolicy{ + API: &dpv1alpha3.APIRateLimitPolicy{ RequestsPerUnit: 10, Unit: "Minute", }, }, }, - schemeDownSpec: dpv1alpha1.RateLimitPolicySpec{ - Override: &dpv1alpha1.RateLimitAPIPolicy{ - API: &dpv1alpha1.APIRateLimitPolicy{ + schemeDownSpec: dpv1alpha3.RateLimitPolicySpec{ + Override: &dpv1alpha3.RateLimitAPIPolicy{ + API: &dpv1alpha3.APIRateLimitPolicy{ RequestsPerUnit: 20, Unit: "Day", }, }, }, - result: dpv1alpha1.RateLimitPolicySpec{ - Override: &dpv1alpha1.RateLimitAPIPolicy{ - API: &dpv1alpha1.APIRateLimitPolicy{ + result: dpv1alpha3.RateLimitPolicySpec{ + Override: &dpv1alpha3.RateLimitAPIPolicy{ + API: &dpv1alpha3.APIRateLimitPolicy{ RequestsPerUnit: 10, Unit: "Minute", }, @@ -66,25 +66,25 @@ func TestConcatRateLimitPolicies(t *testing.T) { message: "When API level override and Resource level override policies both provided", }, { - schemeUpSpec: dpv1alpha1.RateLimitPolicySpec{ - Override: &dpv1alpha1.RateLimitAPIPolicy{ - API: &dpv1alpha1.APIRateLimitPolicy{ + schemeUpSpec: dpv1alpha3.RateLimitPolicySpec{ + Override: &dpv1alpha3.RateLimitAPIPolicy{ + API: &dpv1alpha3.APIRateLimitPolicy{ RequestsPerUnit: 10, Unit: "Minute", }, }, }, - schemeDownSpec: dpv1alpha1.RateLimitPolicySpec{ - Default: &dpv1alpha1.RateLimitAPIPolicy{ - API: &dpv1alpha1.APIRateLimitPolicy{ + schemeDownSpec: dpv1alpha3.RateLimitPolicySpec{ + Default: &dpv1alpha3.RateLimitAPIPolicy{ + API: &dpv1alpha3.APIRateLimitPolicy{ RequestsPerUnit: 20, Unit: "Day", }, }, }, - result: dpv1alpha1.RateLimitPolicySpec{ - Override: &dpv1alpha1.RateLimitAPIPolicy{ - API: &dpv1alpha1.APIRateLimitPolicy{ + result: dpv1alpha3.RateLimitPolicySpec{ + Override: &dpv1alpha3.RateLimitAPIPolicy{ + API: &dpv1alpha3.APIRateLimitPolicy{ RequestsPerUnit: 10, Unit: "Minute", }, @@ -93,25 +93,25 @@ func TestConcatRateLimitPolicies(t *testing.T) { message: "When API level override and Resource level default policies both provided", }, { - schemeUpSpec: dpv1alpha1.RateLimitPolicySpec{ - Default: &dpv1alpha1.RateLimitAPIPolicy{ - API: &dpv1alpha1.APIRateLimitPolicy{ + schemeUpSpec: dpv1alpha3.RateLimitPolicySpec{ + Default: &dpv1alpha3.RateLimitAPIPolicy{ + API: &dpv1alpha3.APIRateLimitPolicy{ RequestsPerUnit: 10, Unit: "Minute", }, }, }, - schemeDownSpec: dpv1alpha1.RateLimitPolicySpec{ - Override: &dpv1alpha1.RateLimitAPIPolicy{ - API: &dpv1alpha1.APIRateLimitPolicy{ + schemeDownSpec: dpv1alpha3.RateLimitPolicySpec{ + Override: &dpv1alpha3.RateLimitAPIPolicy{ + API: &dpv1alpha3.APIRateLimitPolicy{ RequestsPerUnit: 20, Unit: "Day", }, }, }, - result: dpv1alpha1.RateLimitPolicySpec{ - Override: &dpv1alpha1.RateLimitAPIPolicy{ - API: &dpv1alpha1.APIRateLimitPolicy{ + result: dpv1alpha3.RateLimitPolicySpec{ + Override: &dpv1alpha3.RateLimitAPIPolicy{ + API: &dpv1alpha3.APIRateLimitPolicy{ RequestsPerUnit: 20, Unit: "Day", }, @@ -120,25 +120,25 @@ func TestConcatRateLimitPolicies(t *testing.T) { message: "When API level default and Resource level override policies both provided", }, { - schemeUpSpec: dpv1alpha1.RateLimitPolicySpec{ - Default: &dpv1alpha1.RateLimitAPIPolicy{ - API: &dpv1alpha1.APIRateLimitPolicy{ + schemeUpSpec: dpv1alpha3.RateLimitPolicySpec{ + Default: &dpv1alpha3.RateLimitAPIPolicy{ + API: &dpv1alpha3.APIRateLimitPolicy{ RequestsPerUnit: 10, Unit: "Minute", }, }, }, - schemeDownSpec: dpv1alpha1.RateLimitPolicySpec{ - Default: &dpv1alpha1.RateLimitAPIPolicy{ - API: &dpv1alpha1.APIRateLimitPolicy{ + schemeDownSpec: dpv1alpha3.RateLimitPolicySpec{ + Default: &dpv1alpha3.RateLimitAPIPolicy{ + API: &dpv1alpha3.APIRateLimitPolicy{ RequestsPerUnit: 20, Unit: "Day", }, }, }, - result: dpv1alpha1.RateLimitPolicySpec{ - Override: &dpv1alpha1.RateLimitAPIPolicy{ - API: &dpv1alpha1.APIRateLimitPolicy{ + result: dpv1alpha3.RateLimitPolicySpec{ + Override: &dpv1alpha3.RateLimitAPIPolicy{ + API: &dpv1alpha3.APIRateLimitPolicy{ RequestsPerUnit: 20, Unit: "Day", }, @@ -147,37 +147,37 @@ func TestConcatRateLimitPolicies(t *testing.T) { message: "When API level default and Resource level default policies both provided", }, { - schemeUpSpec: dpv1alpha1.RateLimitPolicySpec{ - Default: &dpv1alpha1.RateLimitAPIPolicy{ - API: &dpv1alpha1.APIRateLimitPolicy{ + schemeUpSpec: dpv1alpha3.RateLimitPolicySpec{ + Default: &dpv1alpha3.RateLimitAPIPolicy{ + API: &dpv1alpha3.APIRateLimitPolicy{ RequestsPerUnit: 10, Unit: "Minute", }, }, - Override: &dpv1alpha1.RateLimitAPIPolicy{ - API: &dpv1alpha1.APIRateLimitPolicy{ + Override: &dpv1alpha3.RateLimitAPIPolicy{ + API: &dpv1alpha3.APIRateLimitPolicy{ RequestsPerUnit: 20, Unit: "Second", }, }, }, - schemeDownSpec: dpv1alpha1.RateLimitPolicySpec{ - Default: &dpv1alpha1.RateLimitAPIPolicy{ - API: &dpv1alpha1.APIRateLimitPolicy{ + schemeDownSpec: dpv1alpha3.RateLimitPolicySpec{ + Default: &dpv1alpha3.RateLimitAPIPolicy{ + API: &dpv1alpha3.APIRateLimitPolicy{ RequestsPerUnit: 30, Unit: "Day", }, }, - Override: &dpv1alpha1.RateLimitAPIPolicy{ - API: &dpv1alpha1.APIRateLimitPolicy{ + Override: &dpv1alpha3.RateLimitAPIPolicy{ + API: &dpv1alpha3.APIRateLimitPolicy{ RequestsPerUnit: 40, Unit: "Hour", }, }, }, - result: dpv1alpha1.RateLimitPolicySpec{ - Override: &dpv1alpha1.RateLimitAPIPolicy{ - API: &dpv1alpha1.APIRateLimitPolicy{ + result: dpv1alpha3.RateLimitPolicySpec{ + Override: &dpv1alpha3.RateLimitAPIPolicy{ + API: &dpv1alpha3.APIRateLimitPolicy{ RequestsPerUnit: 20, Unit: "Second", }, diff --git a/adapter/internal/operator/controllers/dp/api_controller.go b/adapter/internal/operator/controllers/dp/api_controller.go index 9873e57541..b96e7aa310 100644 --- a/adapter/internal/operator/controllers/dp/api_controller.go +++ b/adapter/internal/operator/controllers/dp/api_controller.go @@ -61,6 +61,7 @@ import ( dpv1alpha1 "github.com/wso2/apk/common-go-libs/apis/dp/v1alpha1" "github.com/wso2/apk/common-go-libs/apis/dp/v1alpha2" dpv1alpha2 "github.com/wso2/apk/common-go-libs/apis/dp/v1alpha2" + dpv1alpha3 "github.com/wso2/apk/common-go-libs/apis/dp/v1alpha3" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -192,7 +193,7 @@ func NewAPIController(mgr manager.Manager, operatorDataStore *synchronizer.Opera return err } - if err := c.Watch(source.Kind(mgr.GetCache(), &dpv1alpha1.RateLimitPolicy{}), handler.EnqueueRequestsFromMapFunc(apiReconciler.populateAPIReconcileRequestsForRateLimitPolicy), + if err := c.Watch(source.Kind(mgr.GetCache(), &dpv1alpha3.RateLimitPolicy{}), handler.EnqueueRequestsFromMapFunc(apiReconciler.populateAPIReconcileRequestsForRateLimitPolicy), predicates...); err != nil { loggers.LoggerAPKOperator.ErrorC(logging.PrintError(logging.Error2639, logging.BLOCKER, "Error watching Ratelimit resources: %v", err)) return err @@ -607,10 +608,10 @@ func (apiReconciler *APIReconciler) getAuthenticationsForAPI(ctx context.Context } func (apiReconciler *APIReconciler) getRatelimitPoliciesForAPI(ctx context.Context, - api dpv1alpha2.API) (map[string]dpv1alpha1.RateLimitPolicy, error) { + api dpv1alpha2.API) (map[string]dpv1alpha3.RateLimitPolicy, error) { nameSpacedName := utils.NamespacedName(&api).String() - ratelimitPolicies := make(map[string]dpv1alpha1.RateLimitPolicy) - ratelimitPolicyList := &dpv1alpha1.RateLimitPolicyList{} + ratelimitPolicies := make(map[string]dpv1alpha3.RateLimitPolicy) + ratelimitPolicyList := &dpv1alpha3.RateLimitPolicyList{} if err := apiReconciler.client.List(ctx, ratelimitPolicyList, &k8client.ListOptions{ FieldSelector: fields.OneTermEqualSelector(apiRateLimitIndex, nameSpacedName), }); err != nil { @@ -683,10 +684,10 @@ func (apiReconciler *APIReconciler) getAuthenticationsForResources(ctx context.C } func (apiReconciler *APIReconciler) getRatelimitPoliciesForResources(ctx context.Context, - api dpv1alpha2.API) (map[string]dpv1alpha1.RateLimitPolicy, error) { + api dpv1alpha2.API) (map[string]dpv1alpha3.RateLimitPolicy, error) { nameSpacedName := utils.NamespacedName(&api).String() - ratelimitpolicies := make(map[string]dpv1alpha1.RateLimitPolicy) - ratelimitPolicyList := &dpv1alpha1.RateLimitPolicyList{} + ratelimitpolicies := make(map[string]dpv1alpha3.RateLimitPolicy) + ratelimitPolicyList := &dpv1alpha3.RateLimitPolicyList{} if err := apiReconciler.client.List(ctx, ratelimitPolicyList, &k8client.ListOptions{ FieldSelector: fields.OneTermEqualSelector(apiRateLimitResourceIndex, nameSpacedName), }); err != nil { @@ -1085,8 +1086,8 @@ func (apiReconciler *APIReconciler) retriveParentAPIsAndUpdateOwnerReferene(ctx } requests = apiReconciler.getAPIsForScope(ctx, &scope) apiReconciler.handleOwnerReference(ctx, &scope, &requests) - case *dpv1alpha1.RateLimitPolicy: - var rl dpv1alpha1.RateLimitPolicy + case *dpv1alpha3.RateLimitPolicy: + var rl dpv1alpha3.RateLimitPolicy namesapcedName := types.NamespacedName{ Name: string(obj.GetName()), Namespace: string(obj.GetNamespace()), @@ -1464,7 +1465,7 @@ func (apiReconciler *APIReconciler) getAPIsForBackendJWT(ctx context.Context, ob // from RateLimitPolicy objects. If the changes are done for an API stored in the Operator Data store, // a new reconcile event will be created and added to the reconcile event queue. func (apiReconciler *APIReconciler) getAPIsForRateLimitPolicy(ctx context.Context, obj k8client.Object) []reconcile.Request { - ratelimitPolicy, ok := obj.(*dpv1alpha1.RateLimitPolicy) + ratelimitPolicy, ok := obj.(*dpv1alpha3.RateLimitPolicy) requests := []reconcile.Request{} if !ok { loggers.LoggerAPKOperator.ErrorC(logging.PrintError(logging.Error2622, logging.TRIVIAL, "Unexpected object type, bypassing reconciliation: %v", ratelimitPolicy)) @@ -1994,9 +1995,9 @@ func addIndexes(ctx context.Context, mgr manager.Manager) error { } // ratelimit policy to API indexer - if err := mgr.GetFieldIndexer().IndexField(ctx, &dpv1alpha1.RateLimitPolicy{}, apiRateLimitIndex, + if err := mgr.GetFieldIndexer().IndexField(ctx, &dpv1alpha3.RateLimitPolicy{}, apiRateLimitIndex, func(rawObj k8client.Object) []string { - ratelimitPolicy := rawObj.(*dpv1alpha1.RateLimitPolicy) + ratelimitPolicy := rawObj.(*dpv1alpha3.RateLimitPolicy) var apis []string if ratelimitPolicy.Spec.TargetRef.Kind == constants.KindAPI { @@ -2023,9 +2024,9 @@ func addIndexes(ctx context.Context, mgr manager.Manager) error { // https://gateway-api.sigs.k8s.io/geps/gep-713/?h=multiple+targetrefs#apply-policies-to-sections-of-a-resource-future-extension // we will use a temporary kindName called Resource for policy attachments // TODO(amali) Fix after the official support is available - if err := mgr.GetFieldIndexer().IndexField(ctx, &dpv1alpha1.RateLimitPolicy{}, apiRateLimitResourceIndex, + if err := mgr.GetFieldIndexer().IndexField(ctx, &dpv1alpha3.RateLimitPolicy{}, apiRateLimitResourceIndex, func(rawObj k8client.Object) []string { - ratelimitPolicy := rawObj.(*dpv1alpha1.RateLimitPolicy) + ratelimitPolicy := rawObj.(*dpv1alpha3.RateLimitPolicy) var apis []string if ratelimitPolicy.Spec.TargetRef.Kind == constants.KindResource { diff --git a/adapter/internal/operator/controllers/dp/gateway_controller.go b/adapter/internal/operator/controllers/dp/gateway_controller.go index 51c32b6618..f8cf51aff8 100644 --- a/adapter/internal/operator/controllers/dp/gateway_controller.go +++ b/adapter/internal/operator/controllers/dp/gateway_controller.go @@ -39,6 +39,7 @@ import ( "github.com/wso2/apk/adapter/internal/operator/utils" dpv1alpha1 "github.com/wso2/apk/common-go-libs/apis/dp/v1alpha1" dpv1alpha2 "github.com/wso2/apk/common-go-libs/apis/dp/v1alpha2" + dpv1alpha3 "github.com/wso2/apk/common-go-libs/apis/dp/v1alpha3" ctrl "sigs.k8s.io/controller-runtime" k8client "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller" @@ -99,7 +100,7 @@ func NewGatewayController(mgr manager.Manager, operatorDataStore *synchronizer.O return err } - if err := c.Watch(source.Kind(mgr.GetCache(), &dpv1alpha1.RateLimitPolicy{}), + if err := c.Watch(source.Kind(mgr.GetCache(), &dpv1alpha3.RateLimitPolicy{}), handler.EnqueueRequestsFromMapFunc(r.handleCustomRateLimitPolicies), predicates...); err != nil { loggers.LoggerAPKOperator.ErrorC(logging.PrintError(logging.Error3121, logging.BLOCKER, "Error watching Ratelimit resources: %v", err)) return err @@ -494,7 +495,7 @@ func (gatewayReconciler *GatewayReconciler) handleGatewayStatus(gatewayKey types // handleCustomRateLimitPolicies returns the list of gateway reconcile requests func (gatewayReconciler *GatewayReconciler) handleCustomRateLimitPolicies(ctx context.Context, obj k8client.Object) []reconcile.Request { - ratelimitPolicy, ok := obj.(*dpv1alpha1.RateLimitPolicy) + ratelimitPolicy, ok := obj.(*dpv1alpha3.RateLimitPolicy) if !ok { loggers.LoggerAPKOperator.ErrorC(logging.PrintError(logging.Error3107, logging.TRIVIAL, "Unexpected object type, bypassing reconciliation: %v", ratelimitPolicy)) return []reconcile.Request{} @@ -521,10 +522,10 @@ func (gatewayReconciler *GatewayReconciler) handleCustomRateLimitPolicies(ctx co } // getCustomRateLimitPoliciesForGateway returns the list of custom rate limit policies for a gateway -func (gatewayReconciler *GatewayReconciler) getCustomRateLimitPoliciesForGateway(gatewayName types.NamespacedName) (map[string]*dpv1alpha1.RateLimitPolicy, error) { +func (gatewayReconciler *GatewayReconciler) getCustomRateLimitPoliciesForGateway(gatewayName types.NamespacedName) (map[string]*dpv1alpha3.RateLimitPolicy, error) { ctx := context.Background() - var ratelimitPolicyList dpv1alpha1.RateLimitPolicyList - rateLimitPolicies := make(map[string]*dpv1alpha1.RateLimitPolicy) + var ratelimitPolicyList dpv1alpha3.RateLimitPolicyList + rateLimitPolicies := make(map[string]*dpv1alpha3.RateLimitPolicy) if err := gatewayReconciler.client.List(ctx, &ratelimitPolicyList, &k8client.ListOptions{ FieldSelector: fields.OneTermEqualSelector(gatewayRateLimitPolicyIndex, gatewayName.String()), }); err != nil { @@ -569,9 +570,9 @@ func (gatewayReconciler *GatewayReconciler) getGatewaysForAPIPolicy(ctx context. // addGatewayIndexes adds indexers related to Gateways func addGatewayIndexes(ctx context.Context, mgr manager.Manager) error { // Gateway to RateLimitPolicy indexer - if err := mgr.GetFieldIndexer().IndexField(ctx, &dpv1alpha1.RateLimitPolicy{}, gatewayRateLimitPolicyIndex, + if err := mgr.GetFieldIndexer().IndexField(ctx, &dpv1alpha3.RateLimitPolicy{}, gatewayRateLimitPolicyIndex, func(rawObj k8client.Object) []string { - ratelimitPolicy := rawObj.(*dpv1alpha1.RateLimitPolicy) + ratelimitPolicy := rawObj.(*dpv1alpha3.RateLimitPolicy) var gateways []string if ratelimitPolicy.Spec.TargetRef.Kind == constants.KindGateway { diff --git a/adapter/internal/operator/operator.go b/adapter/internal/operator/operator.go index 87cf2bf916..8558432053 100644 --- a/adapter/internal/operator/operator.go +++ b/adapter/internal/operator/operator.go @@ -49,6 +49,7 @@ import ( dpv1alpha1 "github.com/wso2/apk/common-go-libs/apis/dp/v1alpha1" dpv1alpha2 "github.com/wso2/apk/common-go-libs/apis/dp/v1alpha2" + dpv1alpha3 "github.com/wso2/apk/common-go-libs/apis/dp/v1alpha3" //+kubebuilder:scaffold:imports ) @@ -66,6 +67,7 @@ func init() { utilruntime.Must(gwapiv1a2.AddToScheme(scheme)) utilruntime.Must(dpv1alpha2.AddToScheme(scheme)) + utilruntime.Must(dpv1alpha3.AddToScheme(scheme)) //+kubebuilder:scaffold:scheme } diff --git a/adapter/internal/operator/synchronizer/api_state.go b/adapter/internal/operator/synchronizer/api_state.go index 0b6654433e..e6ce50560b 100644 --- a/adapter/internal/operator/synchronizer/api_state.go +++ b/adapter/internal/operator/synchronizer/api_state.go @@ -20,6 +20,7 @@ package synchronizer import ( "github.com/wso2/apk/common-go-libs/apis/dp/v1alpha1" "github.com/wso2/apk/common-go-libs/apis/dp/v1alpha2" + "github.com/wso2/apk/common-go-libs/apis/dp/v1alpha3" gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" ) @@ -33,9 +34,9 @@ type APIState struct { ProdGQLRoute *GQLRouteState SandGQLRoute *GQLRouteState Authentications map[string]v1alpha2.Authentication - RateLimitPolicies map[string]v1alpha1.RateLimitPolicy + RateLimitPolicies map[string]v1alpha3.RateLimitPolicy ResourceAuthentications map[string]v1alpha2.Authentication - ResourceRateLimitPolicies map[string]v1alpha1.RateLimitPolicy + ResourceRateLimitPolicies map[string]v1alpha3.RateLimitPolicy ResourceAPIPolicies map[string]v1alpha2.APIPolicy APIPolicies map[string]v1alpha2.APIPolicy InterceptorServiceMapping map[string]v1alpha1.InterceptorService diff --git a/adapter/internal/operator/synchronizer/data_store.go b/adapter/internal/operator/synchronizer/data_store.go index b21e482227..0c861d315b 100644 --- a/adapter/internal/operator/synchronizer/data_store.go +++ b/adapter/internal/operator/synchronizer/data_store.go @@ -22,8 +22,8 @@ import ( "github.com/wso2/apk/adapter/internal/loggers" "github.com/wso2/apk/adapter/internal/operator/utils" - dpv1alpha1 "github.com/wso2/apk/common-go-libs/apis/dp/v1alpha1" dpv1alpha2 "github.com/wso2/apk/common-go-libs/apis/dp/v1alpha2" + dpv1alpha3 "github.com/wso2/apk/common-go-libs/apis/dp/v1alpha3" "k8s.io/apimachinery/pkg/types" gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" ) @@ -512,7 +512,7 @@ func (ods *OperatorDataStore) UpdateGatewayState(gatewayDef *gwapiv1.Gateway, // processGatewayState process and update the GatewayState on ref updates func (ods *OperatorDataStore) processGatewayState(gatewayDef *gwapiv1.Gateway, - customRateLimitPolicies map[string]*dpv1alpha1.RateLimitPolicy) (GatewayState, []string, bool) { + customRateLimitPolicies map[string]*dpv1alpha3.RateLimitPolicy) (GatewayState, []string, bool) { ods.mu.Lock() defer ods.mu.Unlock() var updated bool diff --git a/adapter/internal/operator/synchronizer/gateway_state.go b/adapter/internal/operator/synchronizer/gateway_state.go index 070466db84..3755163578 100644 --- a/adapter/internal/operator/synchronizer/gateway_state.go +++ b/adapter/internal/operator/synchronizer/gateway_state.go @@ -20,6 +20,7 @@ package synchronizer import ( "github.com/wso2/apk/common-go-libs/apis/dp/v1alpha1" "github.com/wso2/apk/common-go-libs/apis/dp/v1alpha2" + "github.com/wso2/apk/common-go-libs/apis/dp/v1alpha3" gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" ) @@ -38,5 +39,5 @@ type GatewayStateData struct { GatewayAPIPolicies map[string]v1alpha2.APIPolicy GatewayBackendMapping map[string]*v1alpha2.ResolvedBackend GatewayInterceptorServiceMapping map[string]v1alpha1.InterceptorService - GatewayCustomRateLimitPolicies map[string]*v1alpha1.RateLimitPolicy + GatewayCustomRateLimitPolicies map[string]*v1alpha3.RateLimitPolicy } diff --git a/adapter/internal/operator/synchronizer/gateway_synchronizer.go b/adapter/internal/operator/synchronizer/gateway_synchronizer.go index a43ceaac17..1f374a9f82 100644 --- a/adapter/internal/operator/synchronizer/gateway_synchronizer.go +++ b/adapter/internal/operator/synchronizer/gateway_synchronizer.go @@ -32,6 +32,7 @@ import ( "github.com/wso2/apk/adapter/pkg/logging" dpv1alpha1 "github.com/wso2/apk/common-go-libs/apis/dp/v1alpha1" dpv1alpha2 "github.com/wso2/apk/common-go-libs/apis/dp/v1alpha2" + dpv1alpha3 "github.com/wso2/apk/common-go-libs/apis/dp/v1alpha3" "golang.org/x/exp/maps" "k8s.io/apimachinery/pkg/types" gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" @@ -126,7 +127,7 @@ func DeleteGateway(gateway *gwapiv1.Gateway) (string, error) { } // getCustomRateLimitPolicies returns the custom rate limit policies. -func getCustomRateLimitPolicies(customRateLimitPoliciesDef map[string]*dpv1alpha1.RateLimitPolicy) []*model.CustomRateLimitPolicy { +func getCustomRateLimitPolicies(customRateLimitPoliciesDef map[string]*dpv1alpha3.RateLimitPolicy) []*model.CustomRateLimitPolicy { var customRateLimitPolicies []*model.CustomRateLimitPolicy for _, customRateLimitPolicy := range customRateLimitPoliciesDef { customRLPolicy := model.ParseCustomRateLimitPolicy(*customRateLimitPolicy) diff --git a/adapter/internal/operator/synchronizer/zz_generated.deepcopy.go b/adapter/internal/operator/synchronizer/zz_generated.deepcopy.go index ffe28ace55..0ce21cdd35 100644 --- a/adapter/internal/operator/synchronizer/zz_generated.deepcopy.go +++ b/adapter/internal/operator/synchronizer/zz_generated.deepcopy.go @@ -63,13 +63,6 @@ func (in *APIState) DeepCopyInto(out *APIState) { (*out)[key] = *val.DeepCopy() } } - if in.RateLimitPolicies != nil { - in, out := &in.RateLimitPolicies, &out.RateLimitPolicies - *out = make(map[string]v1alpha1.RateLimitPolicy, len(*in)) - for key, val := range *in { - (*out)[key] = *val.DeepCopy() - } - } if in.ResourceAuthentications != nil { in, out := &in.ResourceAuthentications, &out.ResourceAuthentications *out = make(map[string]v1alpha2.Authentication, len(*in)) @@ -77,13 +70,6 @@ func (in *APIState) DeepCopyInto(out *APIState) { (*out)[key] = *val.DeepCopy() } } - if in.ResourceRateLimitPolicies != nil { - in, out := &in.ResourceRateLimitPolicies, &out.ResourceRateLimitPolicies - *out = make(map[string]v1alpha1.RateLimitPolicy, len(*in)) - for key, val := range *in { - (*out)[key] = *val.DeepCopy() - } - } if in.ResourceAPIPolicies != nil { in, out := &in.ResourceAPIPolicies, &out.ResourceAPIPolicies *out = make(map[string]v1alpha2.APIPolicy, len(*in)) @@ -273,21 +259,6 @@ func (in *GatewayStateData) DeepCopyInto(out *GatewayStateData) { (*out)[key] = *val.DeepCopy() } } - if in.GatewayCustomRateLimitPolicies != nil { - in, out := &in.GatewayCustomRateLimitPolicies, &out.GatewayCustomRateLimitPolicies - *out = make(map[string]*v1alpha1.RateLimitPolicy, len(*in)) - for key, val := range *in { - var outVal *v1alpha1.RateLimitPolicy - if val == nil { - (*out)[key] = nil - } else { - in, out := &val, &outVal - *out = new(v1alpha1.RateLimitPolicy) - (*in).DeepCopyInto(*out) - } - (*out)[key] = outVal - } - } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayStateData. diff --git a/common-controller/go.mod b/common-controller/go.mod index 81aa12a6fb..5e0e92001e 100644 --- a/common-controller/go.mod +++ b/common-controller/go.mod @@ -117,7 +117,7 @@ require ( google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect - google.golang.org/protobuf v1.33.0 + google.golang.org/protobuf v1.34.1 gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/common-controller/go.sum b/common-controller/go.sum index c2d87b95fb..44ab8d7761 100644 --- a/common-controller/go.sum +++ b/common-controller/go.sum @@ -363,8 +363,8 @@ google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk= google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= +google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/common-controller/internal/cache/datastore.go b/common-controller/internal/cache/datastore.go index 3730bf7b39..d9b71480b1 100644 --- a/common-controller/internal/cache/datastore.go +++ b/common-controller/internal/cache/datastore.go @@ -22,25 +22,55 @@ import ( logger "github.com/sirupsen/logrus" dpv1alpha1 "github.com/wso2/apk/common-go-libs/apis/dp/v1alpha1" + dpv1alpha3 "github.com/wso2/apk/common-go-libs/apis/dp/v1alpha3" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" ) // RatelimitDataStore is a cache for rate limit policies. type RatelimitDataStore struct { - resolveRatelimitStore map[types.NamespacedName][]dpv1alpha1.ResolveRateLimitAPIPolicy - customRatelimitStore map[types.NamespacedName]*dpv1alpha1.CustomRateLimitPolicyDef - mu sync.Mutex + resolveRatelimitStore map[types.NamespacedName][]dpv1alpha1.ResolveRateLimitAPIPolicy + resolveSubscriptionRatelimitStore map[types.NamespacedName]dpv1alpha3.ResolveSubscriptionRatelimitPolicy + customRatelimitStore map[types.NamespacedName]*dpv1alpha1.CustomRateLimitPolicyDef + mu sync.Mutex } // CreateNewOperatorDataStore creates a new RatelimitDataStore. func CreateNewOperatorDataStore() *RatelimitDataStore { return &RatelimitDataStore{ - resolveRatelimitStore: map[types.NamespacedName][]dpv1alpha1.ResolveRateLimitAPIPolicy{}, - customRatelimitStore: map[types.NamespacedName]*dpv1alpha1.CustomRateLimitPolicyDef{}, + resolveRatelimitStore: map[types.NamespacedName][]dpv1alpha1.ResolveRateLimitAPIPolicy{}, + customRatelimitStore: map[types.NamespacedName]*dpv1alpha1.CustomRateLimitPolicyDef{}, + resolveSubscriptionRatelimitStore: map[types.NamespacedName]dpv1alpha3.ResolveSubscriptionRatelimitPolicy{}, } } +// AddorUpdateResolveSubscriptionRatelimitToStore adds a new ratelimit to the RatelimitDataStore. +func (ods *RatelimitDataStore) AddorUpdateResolveSubscriptionRatelimitToStore(rateLimit types.NamespacedName, + resolveSubscriptionRatelimit dpv1alpha3.ResolveSubscriptionRatelimitPolicy) { + ods.mu.Lock() + defer ods.mu.Unlock() + logger.Debug("Adding/Updating ratelimit to cache") + ods.resolveSubscriptionRatelimitStore[rateLimit] = resolveSubscriptionRatelimit +} + +// GetResolveSubscriptionRatelimitPolicy get cached ratelimit +func (ods *RatelimitDataStore) GetResolveSubscriptionRatelimitPolicy(rateLimit types.NamespacedName) (dpv1alpha3.ResolveSubscriptionRatelimitPolicy, bool) { + var rateLimitPolicy dpv1alpha3.ResolveSubscriptionRatelimitPolicy + if cachedRatelimit, found := ods.resolveSubscriptionRatelimitStore[rateLimit]; found { + logger.Debug("Found cached ratelimit") + return cachedRatelimit, true + } + return rateLimitPolicy, false +} + +// DeleteSubscriptionRatelimitPolicy delete from ratelimit cache +func (ods *RatelimitDataStore) DeleteSubscriptionRatelimitPolicy(rateLimit types.NamespacedName) { + ods.mu.Lock() + defer ods.mu.Unlock() + logger.Debug("Deleting ratelimit from cache") + delete(ods.resolveSubscriptionRatelimitStore, rateLimit) +} + // AddorUpdateResolveRatelimitToStore adds a new ratelimit to the RatelimitDataStore. func (ods *RatelimitDataStore) AddorUpdateResolveRatelimitToStore(rateLimit types.NamespacedName, resolveRatelimitPolicyList []dpv1alpha1.ResolveRateLimitAPIPolicy) { diff --git a/common-controller/internal/cache/subscriptionDataStore.go b/common-controller/internal/cache/subscriptionDataStore.go index 85d5cecd15..d253fbf699 100644 --- a/common-controller/internal/cache/subscriptionDataStore.go +++ b/common-controller/internal/cache/subscriptionDataStore.go @@ -22,13 +22,14 @@ import ( logger "github.com/sirupsen/logrus" cpv1alpha2 "github.com/wso2/apk/common-go-libs/apis/cp/v1alpha2" + cpv1alpha3 "github.com/wso2/apk/common-go-libs/apis/cp/v1alpha3" "k8s.io/apimachinery/pkg/types" ) // SubscriptionDataStore is a cache subscription data. type SubscriptionDataStore struct { applicationStore map[types.NamespacedName]*cpv1alpha2.ApplicationSpec - subscriptionStore map[types.NamespacedName]*cpv1alpha2.SubscriptionSpec + subscriptionStore map[types.NamespacedName]*cpv1alpha3.SubscriptionSpec applicationMappingStore map[types.NamespacedName]*cpv1alpha2.ApplicationMappingSpec mu sync.Mutex } @@ -37,7 +38,7 @@ type SubscriptionDataStore struct { func CreateNewSubscriptionDataStore() *SubscriptionDataStore { return &SubscriptionDataStore{ applicationStore: map[types.NamespacedName]*cpv1alpha2.ApplicationSpec{}, - subscriptionStore: map[types.NamespacedName]*cpv1alpha2.SubscriptionSpec{}, + subscriptionStore: map[types.NamespacedName]*cpv1alpha3.SubscriptionSpec{}, applicationMappingStore: map[types.NamespacedName]*cpv1alpha2.ApplicationMappingSpec{}, } } @@ -51,7 +52,7 @@ func (ods *SubscriptionDataStore) AddorUpdateApplicationToStore(name types.Names } // AddorUpdateSubscriptionToStore adds a new subscription to the DataStore. -func (ods *SubscriptionDataStore) AddorUpdateSubscriptionToStore(name types.NamespacedName, subscription cpv1alpha2.SubscriptionSpec) { +func (ods *SubscriptionDataStore) AddorUpdateSubscriptionToStore(name types.NamespacedName, subscription cpv1alpha3.SubscriptionSpec) { ods.mu.Lock() defer ods.mu.Unlock() logger.Debug("Adding/Updating subscription to cache") @@ -77,8 +78,8 @@ func (ods *SubscriptionDataStore) GetApplicationFromStore(name types.NamespacedN } // GetSubscriptionFromStore get cached subscription -func (ods *SubscriptionDataStore) GetSubscriptionFromStore(name types.NamespacedName) (cpv1alpha2.SubscriptionSpec, bool) { - var subscription cpv1alpha2.SubscriptionSpec +func (ods *SubscriptionDataStore) GetSubscriptionFromStore(name types.NamespacedName) (cpv1alpha3.SubscriptionSpec, bool) { + var subscription cpv1alpha3.SubscriptionSpec if cachedSubscription, found := ods.subscriptionStore[name]; found { logger.Debug("Found cached subscription") return *cachedSubscription, true diff --git a/common-controller/internal/controlplane/k8s_artifact_deployer.go b/common-controller/internal/controlplane/k8s_artifact_deployer.go index ed259e60a2..08841bf677 100644 --- a/common-controller/internal/controlplane/k8s_artifact_deployer.go +++ b/common-controller/internal/controlplane/k8s_artifact_deployer.go @@ -24,6 +24,7 @@ import ( "github.com/wso2/apk/common-controller/internal/loggers" "github.com/wso2/apk/common-controller/internal/server" cpv1alpha2 "github.com/wso2/apk/common-go-libs/apis/cp/v1alpha2" + cpv1alpha3 "github.com/wso2/apk/common-go-libs/apis/cp/v1alpha3" "github.com/wso2/apk/common-go-libs/constants" "github.com/wso2/apk/common-go-libs/utils" k8error "k8s.io/apimachinery/pkg/api/errors" @@ -104,8 +105,8 @@ func (k8sArtifactDeployer K8sArtifactDeployer) UpdateKeyMappings(keyMapping serv // DeploySubscription deploys a subscription func (k8sArtifactDeployer K8sArtifactDeployer) DeploySubscription(subscription server.Subscription) error { - crSubscription := cpv1alpha2.Subscription{ObjectMeta: v1.ObjectMeta{Name: subscription.UUID, Namespace: utils.GetOperatorPodNamespace()}, - Spec: cpv1alpha2.SubscriptionSpec{Organization: subscription.Organization, API: cpv1alpha2.API{Name: subscription.SubscribedAPI.Name, Version: subscription.SubscribedAPI.Version}, SubscriptionStatus: subscription.SubStatus}} + crSubscription := cpv1alpha3.Subscription{ObjectMeta: v1.ObjectMeta{Name: subscription.UUID, Namespace: utils.GetOperatorPodNamespace()}, + Spec: cpv1alpha3.SubscriptionSpec{Organization: subscription.Organization, API: cpv1alpha3.API{Name: subscription.SubscribedAPI.Name, Version: subscription.SubscribedAPI.Version}, SubscriptionStatus: subscription.SubStatus}} err := k8sArtifactDeployer.client.Create(context.Background(), &crSubscription) if err != nil { loggers.LoggerAPKOperator.ErrorC(logging.PrintError(logging.Error1101, logging.CRITICAL, "Failed to create subscription in k8s %v", err.Error())) @@ -116,7 +117,7 @@ func (k8sArtifactDeployer K8sArtifactDeployer) DeploySubscription(subscription s // UpdateSubscription updates a subscription func (k8sArtifactDeployer K8sArtifactDeployer) UpdateSubscription(subscription server.Subscription) error { - crSubscription := cpv1alpha2.Subscription{} + crSubscription := cpv1alpha3.Subscription{} err := k8sArtifactDeployer.client.Get(context.Background(), client.ObjectKey{Name: subscription.UUID, Namespace: utils.GetOperatorPodNamespace()}, &crSubscription) if err != nil { if !k8error.IsNotFound(err) { @@ -283,7 +284,7 @@ func (k8sArtifactDeployer K8sArtifactDeployer) DeleteKeyMappings(keyMapping serv // DeleteSubscription deletes a subscription func (k8sArtifactDeployer K8sArtifactDeployer) DeleteSubscription(subscriptionID string) error { - crSubscription := cpv1alpha2.Subscription{} + crSubscription := cpv1alpha3.Subscription{} err := k8sArtifactDeployer.client.Get(context.Background(), client.ObjectKey{Name: subscriptionID, Namespace: utils.GetOperatorPodNamespace()}, &crSubscription) if err != nil { if !k8error.IsNotFound(err) { @@ -416,7 +417,7 @@ func (k8sArtifactDeployer K8sArtifactDeployer) DeployAllSubscriptions(subscripti if err != nil { return err } - clonedSubscriptionsFromK8s := make([]cpv1alpha2.Subscription, len(subscriptionsFromK8s)) + clonedSubscriptionsFromK8s := make([]cpv1alpha3.Subscription, len(subscriptionsFromK8s)) copy(clonedSubscriptionsFromK8s, subscriptionsFromK8s) clonedSubscriptions := make([]server.Subscription, len(subscriptions.List)) copy(clonedSubscriptions, subscriptions.List) @@ -424,7 +425,7 @@ func (k8sArtifactDeployer K8sArtifactDeployer) DeployAllSubscriptions(subscripti sameSubscriptions := make([]server.Subscription, 0) for _, subscription := range clonedSubscriptions { found := false - unFilteredSubscriptionsInK8s := make([]cpv1alpha2.Subscription, 0) + unFilteredSubscriptionsInK8s := make([]cpv1alpha3.Subscription, 0) for _, subscriptionFromK8s := range clonedSubscriptionsFromK8s { if subscription.UUID == subscriptionFromK8s.Name { sameSubscriptions = append(sameSubscriptions, subscription) @@ -528,9 +529,9 @@ func (k8sArtifactDeployer K8sArtifactDeployer) retrieveAllApplicationsFromK8s(ne return resolvedApplicationList, applicationList.Continue, nil } -func (k8sArtifactDeployer K8sArtifactDeployer) retrieveAllSubscriptionsFromK8s(nextToken string) ([]cpv1alpha2.Subscription, string, error) { - subscriptionList := cpv1alpha2.SubscriptionList{} - resolvedSubscripitonList := make([]cpv1alpha2.Subscription, 0) +func (k8sArtifactDeployer K8sArtifactDeployer) retrieveAllSubscriptionsFromK8s(nextToken string) ([]cpv1alpha3.Subscription, string, error) { + subscriptionList := cpv1alpha3.SubscriptionList{} + resolvedSubscripitonList := make([]cpv1alpha3.Subscription, 0) var err error if nextToken == "" { err = k8sArtifactDeployer.client.List(context.Background(), &subscriptionList, &client.ListOptions{Namespace: utils.GetOperatorPodNamespace()}) diff --git a/common-controller/internal/operator/controllers/cp/applicationmapping_controller.go b/common-controller/internal/operator/controllers/cp/applicationmapping_controller.go index c2ff077cb9..d396db973b 100644 --- a/common-controller/internal/operator/controllers/cp/applicationmapping_controller.go +++ b/common-controller/internal/operator/controllers/cp/applicationmapping_controller.go @@ -41,6 +41,8 @@ import ( "github.com/wso2/apk/common-controller/internal/utils" cpv1alpha2 "github.com/wso2/apk/common-go-libs/apis/cp/v1alpha2" + cpv1alpha3 "github.com/wso2/apk/common-go-libs/apis/cp/v1alpha3" + "github.com/wso2/apk/common-go-libs/constants" ) @@ -87,7 +89,7 @@ func NewApplicationMappingController(mgr manager.Manager, subscriptionStore *cac return err } - if err := c.Watch(source.Kind(mgr.GetCache(), &cpv1alpha2.Subscription{}), handler.EnqueueRequestsFromMapFunc(r.getApplicationMappingsForSubscription), + if err := c.Watch(source.Kind(mgr.GetCache(), &cpv1alpha3.Subscription{}), handler.EnqueueRequestsFromMapFunc(r.getApplicationMappingsForSubscription), predicates...); err != nil { loggers.LoggerAPKOperator.ErrorC(logging.PrintError(logging.Error2613, logging.BLOCKER, "Error watching Subscription resources: %v", err)) return err @@ -135,7 +137,7 @@ func (r *ApplicationMappingReconciler) Reconcile(ctx context.Context, req ctrl.R loggers.LoggerAPKOperator.ErrorC(logging.PrintError(logging.Error2614, logging.CRITICAL, "Error getting Application: %v", err)) return ctrl.Result{}, nil } - var subscription cpv1alpha2.Subscription + var subscription cpv1alpha3.Subscription if err := r.client.Get(ctx, types.NamespacedName{Name: string(applicationMapping.Spec.SubscriptionRef), Namespace: applicationMapping.Namespace}, &subscription); err != nil { loggers.LoggerAPKOperator.ErrorC(logging.PrintError(logging.Error2615, logging.CRITICAL, "Error getting Subscription: %v", err)) return ctrl.Result{}, nil @@ -148,7 +150,7 @@ func (r *ApplicationMappingReconciler) Reconcile(ctx context.Context, req ctrl.R return ctrl.Result{}, nil } -func sendUpdates(applicationMapping *cpv1alpha2.ApplicationMapping, application cpv1alpha2.Application, subscription cpv1alpha2.Subscription) { +func sendUpdates(applicationMapping *cpv1alpha2.ApplicationMapping, application cpv1alpha2.Application, subscription cpv1alpha3.Subscription) { resolvedApplication := marshalApplication(application) appMapping := marshalApplicationMapping(applicationMapping, resolvedApplication) server.AddApplicationMapping(appMapping) @@ -233,7 +235,7 @@ func (r *ApplicationMappingReconciler) getApplicationMappingsForApplication(ctx // getApplicationMappingsForSubscription triggers the ApplicationMapping controller reconcile method based on the changes detected // from Subscription objects. If the changes are done for an API stored in the Operator Data store, func (r *ApplicationMappingReconciler) getApplicationMappingsForSubscription(ctx context.Context, obj k8client.Object) []reconcile.Request { - subscription, ok := obj.(*cpv1alpha2.Subscription) + subscription, ok := obj.(*cpv1alpha3.Subscription) if !ok { loggers.LoggerAPKOperator.ErrorC(logging.PrintError(logging.Error2622, logging.TRIVIAL, "Unexpected object type, bypassing reconciliation: %v", subscription)) return []reconcile.Request{} diff --git a/common-controller/internal/operator/controllers/cp/subscription_controller.go b/common-controller/internal/operator/controllers/cp/subscription_controller.go index cf84d6b7d4..5d8212474b 100644 --- a/common-controller/internal/operator/controllers/cp/subscription_controller.go +++ b/common-controller/internal/operator/controllers/cp/subscription_controller.go @@ -22,22 +22,28 @@ import ( "github.com/wso2/apk/adapter/pkg/logging" "github.com/wso2/apk/common-controller/internal/cache" + "github.com/wso2/apk/common-controller/internal/config" loggers "github.com/wso2/apk/common-controller/internal/loggers" "github.com/wso2/apk/common-controller/internal/server" "github.com/wso2/apk/common-controller/internal/utils" "github.com/wso2/apk/common-go-libs/constants" k8error "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/types" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" + k8client "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller" "sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/manager" "sigs.k8s.io/controller-runtime/pkg/predicate" + "sigs.k8s.io/controller-runtime/pkg/reconcile" "sigs.k8s.io/controller-runtime/pkg/source" - cpv1alpha2 "github.com/wso2/apk/common-go-libs/apis/cp/v1alpha2" + cpv1alpha3 "github.com/wso2/apk/common-go-libs/apis/cp/v1alpha3" + dpv1alpha3 "github.com/wso2/apk/common-go-libs/apis/dp/v1alpha3" ) // SubscriptionReconciler reconciles a Subscription object @@ -47,24 +53,41 @@ type SubscriptionReconciler struct { ods *cache.SubscriptionDataStore } +const ( + subscriptionRatelimitIndex = "subscriptionRatelimitIndex" +) + // NewSubscriptionController creates a new Subscription controller instance. func NewSubscriptionController(mgr manager.Manager, subscriptionStore *cache.SubscriptionDataStore) error { r := &SubscriptionReconciler{ client: mgr.GetClient(), ods: subscriptionStore, } + ctx := context.Background() + conf := config.ReadConfigs() + predicates := []predicate.Predicate{predicate.NewPredicateFuncs(utils.FilterByNamespaces(conf.CommonController.Operator.Namespaces))} + if err := addSubscriptionControllerIndexes(ctx, mgr); err != nil { + loggers.LoggerAPKOperator.ErrorC(logging.PrintError(logging.Error2658, logging.CRITICAL, "Error adding indexes: %v", err)) + return err + } c, err := controller.New(constants.SubscriptionController, mgr, controller.Options{Reconciler: r}) if err != nil { loggers.LoggerAPKOperator.ErrorC(logging.PrintError(logging.Error2608, logging.BLOCKER, "Error creating Subscription controller: %v", err.Error())) return err } - if err := c.Watch(source.Kind(mgr.GetCache(), &cpv1alpha2.Subscription{}), &handler.EnqueueRequestForObject{}, + if err := c.Watch(source.Kind(mgr.GetCache(), &cpv1alpha3.Subscription{}), &handler.EnqueueRequestForObject{}, predicate.NewPredicateFuncs(utils.FilterByNamespaces([]string{utils.GetOperatorPodNamespace()}))); err != nil { loggers.LoggerAPKOperator.ErrorC(logging.PrintError(logging.Error2609, logging.BLOCKER, "Error watching Subscription resources: %v", err.Error())) return err } + if err := c.Watch(source.Kind(mgr.GetCache(), &dpv1alpha3.RateLimitPolicy{}), handler.EnqueueRequestsFromMapFunc(r.getSubscriptionForRatelimit), + predicates...); err != nil { + loggers.LoggerAPKOperator.ErrorC(logging.PrintError(logging.Error2613, logging.BLOCKER, "Error watching Subscription resources: %v", err)) + return err + } + loggers.LoggerAPKOperator.Debug("Subscription Controller successfully started. Watching Subscription Objects...") return nil } @@ -88,14 +111,14 @@ func (subscriptionReconciler *SubscriptionReconciler) Reconcile(ctx context.Cont loggers.LoggerAPKOperator.Debugf("Reconciling subscription: %v", req.NamespacedName.String()) subscriptionKey := req.NamespacedName - var subscription cpv1alpha2.Subscription + var subscription cpv1alpha3.Subscription if err := subscriptionReconciler.client.Get(ctx, req.NamespacedName, &subscription); err != nil { if k8error.IsNotFound(err) { - subscriptionSpec, state := subscriptionReconciler.ods.GetSubscriptionFromStore(subscriptionKey) + _, state := subscriptionReconciler.ods.GetSubscriptionFromStore(subscriptionKey) if state { // Subscription in cache loggers.LoggerAPKOperator.Debugf("Subscription %s/%s not found. Ignoring since object must be deleted", subscriptionKey.Namespace, subscriptionKey.Name) - utils.SendDeleteSubscriptionEvent(subscriptionKey.Name, subscriptionSpec) + utils.SendDeleteSubscriptionEvent(subscriptionKey.Name, subscription) subscriptionReconciler.ods.DeleteSubscriptionFromStore(subscriptionKey) server.DeleteSubscription(subscriptionKey.Name) return ctrl.Result{}, nil @@ -109,18 +132,19 @@ func (subscriptionReconciler *SubscriptionReconciler) Reconcile(ctx context.Cont return ctrl.Result{}, nil } -func sendSubUpdates(subscription cpv1alpha2.Subscription) { +func sendSubUpdates(subscription cpv1alpha3.Subscription) { subList := marshalSubscription(subscription) server.AddSubscription(subList) } -func marshalSubscription(subscription cpv1alpha2.Subscription) server.Subscription { +func marshalSubscription(subscription cpv1alpha3.Subscription) server.Subscription { subscribedAPI := &server.SubscribedAPI{} sub := server.Subscription{ UUID: subscription.Name, SubStatus: subscription.Spec.SubscriptionStatus, Organization: subscription.Spec.Organization, } + sub.RatelimitTier = subscription.Spec.RatelimitRef.Name if subscription.Spec.API.Name != "" && subscription.Spec.API.Version != "" { subscribedAPI.Name = subscription.Spec.API.Name subscribedAPI.Version = subscription.Spec.API.Version @@ -128,3 +152,58 @@ func marshalSubscription(subscription cpv1alpha2.Subscription) server.Subscripti sub.SubscribedAPI = subscribedAPI return sub } + +// addSubscriptionControllerIndexes adds indexes to the Subscription controller +func addSubscriptionControllerIndexes(ctx context.Context, mgr manager.Manager) error { + if err := mgr.GetFieldIndexer().IndexField(ctx, &cpv1alpha3.Subscription{}, subscriptionRatelimitIndex, + func(rawObj k8client.Object) []string { + subscription := rawObj.(*cpv1alpha3.Subscription) + var subscriptionRatelimit []string + subscriptionRatelimit = append(subscriptionRatelimit, + types.NamespacedName{ + Name: string(subscription.Spec.RatelimitRef.Name), + Namespace: subscription.Namespace, + }.String()) + return subscriptionRatelimit + }); err != nil { + loggers.LoggerAPKOperator.ErrorC(logging.PrintError(logging.Error2610, logging.CRITICAL, "Error adding indexes: %v", err)) + return err + } + return nil +} + +// getApplicationMappingsForSubscription triggers the ApplicationMapping controller reconcile method based on the changes detected +// from Subscription objects. If the changes are done for an API stored in the Operator Data store, +func (subscriptionReconciler *SubscriptionReconciler) getSubscriptionForRatelimit(ctx context.Context, obj k8client.Object) []reconcile.Request { + ratelimit, ok := obj.(*dpv1alpha3.RateLimitPolicy) + if !ok { + loggers.LoggerAPKOperator.ErrorC(logging.PrintError(logging.Error2622, logging.TRIVIAL, "Unexpected object type, bypassing reconciliation: %v", ratelimit)) + return []reconcile.Request{} + } + + subList := &cpv1alpha3.SubscriptionList{} + if err := subscriptionReconciler.client.List(ctx, subList, &k8client.ListOptions{ + FieldSelector: fields.OneTermEqualSelector(subscriptionIndex, utils.NamespacedName(ratelimit).String()), + }); err != nil { + loggers.LoggerAPKOperator.ErrorC(logging.PrintError(logging.Error2623, logging.CRITICAL, "Unable to find associated Application mappings: %s", utils.NamespacedName(ratelimit).String())) + return []reconcile.Request{} + } + + if len(subList.Items) == 0 { + loggers.LoggerAPKOperator.Debugf("ApplicationMappings for Subscription %s/%s not found", ratelimit.Namespace, ratelimit.Name) + return []reconcile.Request{} + } + + requests := []reconcile.Request{} + for _, subscription := range subList.Items { + req := reconcile.Request{ + NamespacedName: types.NamespacedName{ + Name: subscription.Name, + Namespace: subscription.Namespace}, + } + requests = append(requests, req) + loggers.LoggerAPKOperator.Debugf("Adding reconcile request for ApplicationMapping: %s/%s with Subscription UUID: %v", subscription.Namespace, subscription.Name, + string(subscription.ObjectMeta.UID)) + } + return requests +} diff --git a/common-controller/internal/operator/controllers/dp/ratelimitpolicy_controller.go b/common-controller/internal/operator/controllers/dp/ratelimitpolicy_controller.go index 91ae9ee529..7db849b0ff 100644 --- a/common-controller/internal/operator/controllers/dp/ratelimitpolicy_controller.go +++ b/common-controller/internal/operator/controllers/dp/ratelimitpolicy_controller.go @@ -47,6 +47,7 @@ import ( xds "github.com/wso2/apk/common-controller/internal/xds" dpv1alpha1 "github.com/wso2/apk/common-go-libs/apis/dp/v1alpha1" dpv1alpha2 "github.com/wso2/apk/common-go-libs/apis/dp/v1alpha2" + dpv1alpha3 "github.com/wso2/apk/common-go-libs/apis/dp/v1alpha3" "github.com/wso2/apk/common-go-libs/constants" ) @@ -101,7 +102,7 @@ func NewratelimitController(mgr manager.Manager, ratelimitStore *cache.Ratelimit return err } - if err := c.Watch(source.Kind(mgr.GetCache(), &dpv1alpha1.RateLimitPolicy{}), &handler.EnqueueRequestForObject{}, predicates...); err != nil { + if err := c.Watch(source.Kind(mgr.GetCache(), &dpv1alpha3.RateLimitPolicy{}), &handler.EnqueueRequestForObject{}, predicates...); err != nil { loggers.LoggerAPKOperator.ErrorC(logging.PrintError(logging.Error2639, logging.BLOCKER, "Error watching Ratelimit resources: %v", err.Error())) return err @@ -130,7 +131,7 @@ func (ratelimitReconsiler *RateLimitPolicyReconciler) Reconcile(ctx context.Cont loggers.LoggerAPKOperator.Infof("Reconciling ratelimit...") conf := config.ReadConfigs() ratelimitKey := req.NamespacedName - var ratelimitPolicy dpv1alpha1.RateLimitPolicy + var ratelimitPolicy dpv1alpha3.RateLimitPolicy // Check k8s RatelimitPolicy Availbility if err := ratelimitReconsiler.client.Get(ctx, ratelimitKey, &ratelimitPolicy); err != nil { @@ -149,6 +150,14 @@ func (ratelimitReconsiler *RateLimitPolicyReconciler) Reconcile(ctx context.Cont xds.DeleteCustomRateLimitPolicies(resolveCustomRateLimitPolicy) xds.UpdateRateLimiterPolicies(conf.CommonController.Server.Label) } + resolveSubscriptionRatelimitPolicy, foundSubscription := ratelimitReconsiler.ods.GetResolveSubscriptionRatelimitPolicy(req.NamespacedName) + if foundSubscription && k8error.IsNotFound(err) { + ratelimitReconsiler.ods.DeleteSubscriptionRatelimitPolicy(req.NamespacedName) + logger.Debug("Deleting SubscriptionRateLimitPolicy : ", resolveSubscriptionRatelimitPolicy) + xds.DeleteSubscriptionRateLimitPolicies(resolveSubscriptionRatelimitPolicy) + xds.UpdateRateLimiterPolicies(conf.CommonController.Server.Label) + } + if k8error.IsNotFound(err) { return ctrl.Result{}, nil } @@ -162,8 +171,12 @@ func (ratelimitReconsiler *RateLimitPolicyReconciler) Reconcile(ctx context.Cont ratelimitReconsiler.ods.AddorUpdateCustomRatelimitToStore(ratelimitKey, customRateLimitPolicy) xds.UpdateRateLimitXDSCacheForCustomPolicies(customRateLimitPolicy) xds.UpdateRateLimiterPolicies(conf.CommonController.Server.Label) + } else if ratelimitPolicy.Spec.Override != nil && ratelimitPolicy.Spec.Override.Subscription != nil { + var resolveSubscriptionRatelimitPolicy = ratelimitReconsiler.marshelSubscriptionRateLimit(ratelimitPolicy) + ratelimitReconsiler.ods.AddorUpdateResolveSubscriptionRatelimitToStore(ratelimitKey, resolveSubscriptionRatelimitPolicy) + xds.UpdateRateLimitXDSCacheForSubscriptionPolicies(resolveSubscriptionRatelimitPolicy) + xds.UpdateRateLimiterPolicies(conf.CommonController.Server.Label) } else { - if resolveRatelimitPolicyList, err := ratelimitReconsiler.marshelRateLimit(ctx, ratelimitKey, ratelimitPolicy); err != nil { return ctrl.Result{}, err } else if len(resolveRatelimitPolicyList) > 0 { @@ -186,7 +199,7 @@ func (ratelimitReconsiler *RateLimitPolicyReconciler) getRatelimitForAPI(ctx con requests := []reconcile.Request{} - ratelimitPolicyList := &dpv1alpha1.RateLimitPolicyList{} + ratelimitPolicyList := &dpv1alpha3.RateLimitPolicyList{} if err := ratelimitReconsiler.client.List(ctx, ratelimitPolicyList, &k8client.ListOptions{ FieldSelector: fields.OneTermEqualSelector(apiRateLimitIndex, NamespacedName(api).String()), }); err != nil { @@ -203,7 +216,7 @@ func (ratelimitReconsiler *RateLimitPolicyReconciler) getRatelimitForAPI(ctx con // AddRatelimitRequest adds a request to reconcile for the given ratelimit policy func (ratelimitReconsiler *RateLimitPolicyReconciler) AddRatelimitRequest(obj k8client.Object) []reconcile.Request { - ratelimitPolicy, ok := obj.(*dpv1alpha1.RateLimitPolicy) + ratelimitPolicy, ok := obj.(*dpv1alpha3.RateLimitPolicy) if !ok { loggers.LoggerAPKOperator.ErrorC(logging.PrintError(logging.Error2622, logging.TRIVIAL, "Unexpected object type, bypassing reconciliation: %v", ratelimitPolicy)) @@ -228,7 +241,7 @@ func (ratelimitReconsiler *RateLimitPolicyReconciler) getRatelimitForHTTPRoute(c requests := []reconcile.Request{} - ratelimitPolicyList := &dpv1alpha1.RateLimitPolicyList{} + ratelimitPolicyList := &dpv1alpha3.RateLimitPolicyList{} if err := ratelimitReconsiler.client.List(ctx, ratelimitPolicyList, &k8client.ListOptions{ FieldSelector: fields.OneTermEqualSelector(httprouteRateLimitIndex, NamespacedName(httpRoute).String()), }); err != nil { @@ -242,8 +255,24 @@ func (ratelimitReconsiler *RateLimitPolicyReconciler) getRatelimitForHTTPRoute(c return requests } +func (ratelimitReconsiler *RateLimitPolicyReconciler) marshelSubscriptionRateLimit( + ratelimitPolicy dpv1alpha3.RateLimitPolicy) dpv1alpha3.ResolveSubscriptionRatelimitPolicy { + + var resolveSubscriptionRatelimit dpv1alpha3.ResolveSubscriptionRatelimitPolicy + resolveSubscriptionRatelimit.Name = ratelimitPolicy.Name + resolveSubscriptionRatelimit.RequestCount.RequestsPerUnit = ratelimitPolicy.Spec.Override.Subscription.RequestCount.RequestsPerUnit + resolveSubscriptionRatelimit.RequestCount.Unit = ratelimitPolicy.Spec.Override.Subscription.RequestCount.Unit + if ratelimitPolicy.Spec.Override.Subscription.BurstControl != nil { + resolveSubscriptionRatelimit.BurstControl.RequestsPerUnit = ratelimitPolicy.Spec.Override.Subscription.BurstControl.RequestsPerUnit + resolveSubscriptionRatelimit.BurstControl.Unit = ratelimitPolicy.Spec.Override.Subscription.BurstControl.Unit + } + resolveSubscriptionRatelimit.StopOnQuotaReach = ratelimitPolicy.Spec.Override.Subscription.StopOnQuotaReach + resolveSubscriptionRatelimit.Organization = ratelimitPolicy.Spec.Override.Subscription.Organization + return resolveSubscriptionRatelimit +} + func (ratelimitReconsiler *RateLimitPolicyReconciler) marshelRateLimit(ctx context.Context, ratelimitKey types.NamespacedName, - ratelimitPolicy dpv1alpha1.RateLimitPolicy) ([]dpv1alpha1.ResolveRateLimitAPIPolicy, error) { + ratelimitPolicy dpv1alpha3.RateLimitPolicy) ([]dpv1alpha1.ResolveRateLimitAPIPolicy, error) { policyList := []dpv1alpha1.ResolveRateLimitAPIPolicy{} var api dpv1alpha2.API @@ -317,7 +346,7 @@ func (ratelimitReconsiler *RateLimitPolicyReconciler) marshelRateLimit(ctx conte } func (ratelimitReconsiler *RateLimitPolicyReconciler) getHTTPRouteResourceList(ctx context.Context, ratelimitKey types.NamespacedName, - ratelimitPolicy dpv1alpha1.RateLimitPolicy, httpRefs []string) ([]dpv1alpha1.ResolveResource, error) { + ratelimitPolicy dpv1alpha3.RateLimitPolicy, httpRefs []string) ([]dpv1alpha1.ResolveResource, error) { var resolveResourceList []dpv1alpha1.ResolveResource var httpRoute gwapiv1.HTTPRoute @@ -363,7 +392,7 @@ func (ratelimitReconsiler *RateLimitPolicyReconciler) getHTTPRouteResourceList(c } func (ratelimitReconsiler *RateLimitPolicyReconciler) marshelCustomRateLimit(ctx context.Context, ratelimitKey types.NamespacedName, - ratelimitPolicy dpv1alpha1.RateLimitPolicy) dpv1alpha1.CustomRateLimitPolicyDef { + ratelimitPolicy dpv1alpha3.RateLimitPolicy) dpv1alpha1.CustomRateLimitPolicyDef { var customRateLimitPolicy dpv1alpha1.CustomRateLimitPolicyDef // Custom Rate limit policy if ratelimitPolicy.Spec.TargetRef.Kind == constants.KindGateway { @@ -374,7 +403,7 @@ func (ratelimitReconsiler *RateLimitPolicyReconciler) marshelCustomRateLimit(ctx } // getCustomRateLimitPolicy returns the custom rate limit policy. -func getCustomRateLimitPolicy(customRateLimitPolicy *dpv1alpha1.RateLimitPolicy) dpv1alpha1.CustomRateLimitPolicyDef { +func getCustomRateLimitPolicy(customRateLimitPolicy *dpv1alpha3.RateLimitPolicy) dpv1alpha1.CustomRateLimitPolicyDef { customRLPolicy := *dpv1alpha1.ParseCustomRateLimitPolicy(*customRateLimitPolicy) logger.Debug("customRLPolicy:", customRLPolicy) return customRLPolicy @@ -404,9 +433,9 @@ func addIndexes(ctx context.Context, mgr manager.Manager) error { } // ratelimite policy to API indexer - err := mgr.GetFieldIndexer().IndexField(ctx, &dpv1alpha1.RateLimitPolicy{}, apiRateLimitIndex, + err := mgr.GetFieldIndexer().IndexField(ctx, &dpv1alpha3.RateLimitPolicy{}, apiRateLimitIndex, func(rawObj k8client.Object) []string { - ratelimitPolicy := rawObj.(*dpv1alpha1.RateLimitPolicy) + ratelimitPolicy := rawObj.(*dpv1alpha3.RateLimitPolicy) var apis []string apis = append(apis, types.NamespacedName{ @@ -437,6 +466,6 @@ func GetNamespace(namespace *gwapiv1.Namespace, defaultNamespace string) string // SetupWithManager sets up the controller with the Manager. func (ratelimitReconsiler *RateLimitPolicyReconciler) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). - For(&dpv1alpha1.RateLimitPolicy{}). + For(&dpv1alpha3.RateLimitPolicy{}). Complete(ratelimitReconsiler) } diff --git a/common-controller/internal/operator/operator.go b/common-controller/internal/operator/operator.go index 473ca72d90..d28717211a 100644 --- a/common-controller/internal/operator/operator.go +++ b/common-controller/internal/operator/operator.go @@ -37,8 +37,10 @@ import ( dpcontrollers "github.com/wso2/apk/common-controller/internal/operator/controllers/dp" "github.com/wso2/apk/common-controller/pkg/metrics" cpv1alpha2 "github.com/wso2/apk/common-go-libs/apis/cp/v1alpha2" + cpv1alpha3 "github.com/wso2/apk/common-go-libs/apis/cp/v1alpha3" dpv1alpha1 "github.com/wso2/apk/common-go-libs/apis/dp/v1alpha1" dpv1alpha2 "github.com/wso2/apk/common-go-libs/apis/dp/v1alpha2" + dpv1alpha3 "github.com/wso2/apk/common-go-libs/apis/dp/v1alpha3" "k8s.io/apimachinery/pkg/runtime" utilruntime "k8s.io/apimachinery/pkg/util/runtime" clientgoscheme "k8s.io/client-go/kubernetes/scheme" @@ -63,6 +65,8 @@ func init() { utilruntime.Must(dpv1alpha2.AddToScheme(scheme)) utilruntime.Must(cpv1alpha2.AddToScheme(scheme)) utilruntime.Must(cpv1alpha2.AddToScheme(scheme)) + utilruntime.Must(cpv1alpha3.AddToScheme(scheme)) + utilruntime.Must(dpv1alpha3.AddToScheme(scheme)) //+kubebuilder:scaffold:scheme } diff --git a/common-controller/internal/server/subscription_types.go b/common-controller/internal/server/subscription_types.go index 43f601a18f..57c9f14d9a 100644 --- a/common-controller/internal/server/subscription_types.go +++ b/common-controller/internal/server/subscription_types.go @@ -22,6 +22,7 @@ type Subscription struct { SubStatus string `json:"subStatus,omitempty"` UUID string `json:"uuid,omitempty"` Organization string `json:"organization,omitempty"` + RatelimitTier string `json:"ratelimitTier,omitempty"` SubscribedAPI *SubscribedAPI `json:"subscribedApi,omitempty"` } diff --git a/common-controller/internal/utils/event_utils.go b/common-controller/internal/utils/event_utils.go index 3c88c24ed8..79bbf36e33 100644 --- a/common-controller/internal/utils/event_utils.go +++ b/common-controller/internal/utils/event_utils.go @@ -6,6 +6,7 @@ import ( "github.com/google/uuid" "github.com/wso2/apk/common-controller/internal/loggers" cpv1alpha2 "github.com/wso2/apk/common-go-libs/apis/cp/v1alpha2" + cpv1alpha3 "github.com/wso2/apk/common-go-libs/apis/cp/v1alpha3" "github.com/wso2/apk/common-go-libs/constants" "github.com/wso2/apk/common-go-libs/pkg/discovery/api/wso2/discovery/subscription" ) @@ -58,13 +59,13 @@ func SendAddApplicationEvent(application cpv1alpha2.Application) { } // SendAddSubscriptionEvent sends an subscription creation event to the enforcer -func SendAddSubscriptionEvent(sub cpv1alpha2.Subscription) { +func SendAddSubscriptionEvent(sub cpv1alpha3.Subscription) { SendSubscriptionEvent(constants.SubscriptionCreated, sub.ObjectMeta.Name, sub.Spec.SubscriptionStatus, - sub.Spec.Organization, sub.Spec.API.Name, sub.Spec.API.Version) + sub.Spec.Organization, sub.Spec.API.Name, sub.Spec.API.Version, sub.Spec.RatelimitRef.Name) } // SendSubscriptionEvent sends an subscription creation event to the enforcer -func SendSubscriptionEvent(eventType, subscriptionID, subscriptionStatus, organization, apiName, apiVersion string) { +func SendSubscriptionEvent(eventType, subscriptionID, subscriptionStatus, organization, apiName, apiVersion string, ratelimit string) { currentTime := time.Now() milliseconds := currentTime.UnixNano() / int64(time.Millisecond) event := subscription.Event{ @@ -79,19 +80,20 @@ func SendSubscriptionEvent(eventType, subscriptionID, subscriptionStatus, organi Name: apiName, Version: apiVersion, }, + RatelimitTier: ratelimit, }, } sendEvent(&event) } // SendDeleteSubscriptionEvent sends an subscription deletion event to the enforcer -func SendDeleteSubscriptionEvent(subscriptionUUID string, subscriptionSpec cpv1alpha2.SubscriptionSpec) { - SendSubscriptionEvent(constants.SubscriptionDeleted, subscriptionUUID, subscriptionSpec.SubscriptionStatus, - subscriptionSpec.Organization, subscriptionSpec.API.Name, subscriptionSpec.API.Version) +func SendDeleteSubscriptionEvent(subscriptionUUID string, sub cpv1alpha3.Subscription) { + SendSubscriptionEvent(constants.SubscriptionDeleted, subscriptionUUID, sub.Spec.SubscriptionStatus, + sub.Spec.Organization, sub.Spec.API.Name, sub.Spec.API.Version, sub.Spec.RatelimitRef.Name) } // SendCreateApplicationMappingEvent sends an application mapping event to the enforcer -func SendCreateApplicationMappingEvent(applicationMapping cpv1alpha2.ApplicationMapping, application cpv1alpha2.Application, subscriptionCr cpv1alpha2.Subscription) { +func SendCreateApplicationMappingEvent(applicationMapping cpv1alpha2.ApplicationMapping, application cpv1alpha2.Application, subscriptionCr cpv1alpha3.Subscription) { SendApplicationMappingEvent(constants.ApplicationMappingCreated, applicationMapping.ObjectMeta.Name, applicationMapping.Spec.ApplicationRef, applicationMapping.Spec.SubscriptionRef, application.Spec.Organization) } diff --git a/common-controller/internal/xds/ratelimiter_cache.go b/common-controller/internal/xds/ratelimiter_cache.go index 43b40f68a9..15a191a408 100644 --- a/common-controller/internal/xds/ratelimiter_cache.go +++ b/common-controller/internal/xds/ratelimiter_cache.go @@ -31,6 +31,7 @@ import ( "github.com/wso2/apk/adapter/pkg/logging" "github.com/wso2/apk/common-controller/internal/loggers" dpv1alpha1 "github.com/wso2/apk/common-go-libs/apis/dp/v1alpha1" + dpv1alpha3 "github.com/wso2/apk/common-go-libs/apis/dp/v1alpha3" "github.com/wso2/apk/common-go-libs/constants" ) @@ -48,6 +49,11 @@ const ( apiDefinitionClusterName = "api_definition_cluster" ) +const ( + subscriptionPolicyType = "subscription" + organization = "organization" +) + // Constants relevant to the rate limit service const ( RateLimiterDomain = "Default" @@ -68,11 +74,18 @@ type rateLimitPolicyCache struct { // org -> environment -> API-Identifier (i.e. Environment:API-UUID) -> Rate Limit Configs apiLevelRateLimitPolicies map[string]map[string]map[string]map[string]*rls_config.RateLimitDescriptor + // metadataBasedPolicies is used to store the rate limit policies which are based on dynamic metadata. + // metadata related rate limit configs: rate limit type (eg: subscription) -> organization -> policy name (eg: Gold, Silver) -> rate-limit config + metadataBasedPolicies map[string]map[string]map[string]*rls_config.RateLimitDescriptor + // org -> Custom Rate Limit Configs customRateLimitPolicies map[string]map[string]*rls_config.RateLimitDescriptor // mutex for API level apiLevelMu sync.RWMutex + + // mutex for metadata based policies + metadataBasedMu sync.RWMutex } // AddAPILevelRateLimitPolicies adds inline Rate Limit policies in APIs to be updated in the Rate Limiter service. @@ -202,6 +215,7 @@ func (r *rateLimitPolicyCache) DeleteCustomRateLimitPolicies(customRateLimitPoli func (r *rateLimitPolicyCache) generateRateLimitConfig() *rls_config.RateLimitConfig { var orgDescriptors []*rls_config.RateLimitDescriptor + var metadataDescriptors []*rls_config.RateLimitDescriptor r.apiLevelMu.RLock() defer r.apiLevelMu.RUnlock() @@ -246,6 +260,28 @@ func (r *rateLimitPolicyCache) generateRateLimitConfig() *rls_config.RateLimitCo customRateLimitDescriptors := r.generateCustomPolicyRateLimitConfig() orgDescriptors = append(orgDescriptors, customRateLimitDescriptors...) + if subscriptionPoliciesList, ok := r.metadataBasedPolicies[subscriptionPolicyType]; ok { + for orgUUID := range subscriptionPoliciesList { + var metadataDescriptor *rls_config.RateLimitDescriptor + var policyDescriptors []*rls_config.RateLimitDescriptor + metadataDescriptor = &rls_config.RateLimitDescriptor{ + Key: organization, + Value: orgUUID, + } + subscriptionIDDescriptor := &rls_config.RateLimitDescriptor{ + Key: subscriptionPolicyType, + } + for policyName := range subscriptionPoliciesList[orgUUID] { + policyDescriptors = append(policyDescriptors, subscriptionPoliciesList[orgUUID][policyName]) + } + subscriptionIDDescriptor.Descriptors = policyDescriptors + metadataDescriptor.Descriptors = append(metadataDescriptor.Descriptors, subscriptionIDDescriptor) + + metadataDescriptors = append(metadataDescriptors, metadataDescriptor) + } + } + orgDescriptors = append(orgDescriptors, metadataDescriptors...) + return &rls_config.RateLimitConfig{ Name: RateLimiterDomain, Domain: RateLimiterDomain, @@ -306,6 +342,101 @@ func (r *rateLimitPolicyCache) updateXdsCache(label string) bool { return true } +// AddSubscriptionLevelRateLimitPolicies adds a subscription level rate limit policies to the cache. +// func AddSubscriptionLevelRateLimitPolicies(policyList *types.SubscriptionPolicyList) error { +// // Check if rlsPolicyCache.metadataBasedPolicies[Subscription] exists and create a new map if not +// if _, ok := rlsPolicyCache.metadataBasedPolicies[subscriptionPolicyType]; !ok { +// rlsPolicyCache.metadataBasedPolicies[subscriptionPolicyType] = make(map[string]map[string]*rls_config.RateLimitDescriptor) +// } +// for _, policy := range policyList.List { +// // Needs to skip on async policies. +// if policy.DefaultLimit == nil || policy.DefaultLimit.QuotaType != "requestCount" || policy.DefaultLimit.RequestCount == nil { +// continue +// } + +// // Need not to add the Unauthenticated and Unlimited policies to the rate limiter service +// if (policy.Organization == "carbon.super" && policy.Name == "Unauthenticated") || policy.DefaultLimit.RequestCount.RequestCount <= 0 { +// continue +// } +// AddSubscriptionLevelRateLimitPolicy(policy) +// loggers.LoggerXds.Debugf("Rate-limiter cache map updated with subscription policy: %s belonging to the organization: %s", policy.Name, policy.Organization) +// } +// return nil +// } + +// RemoveSubscriptionRateLimitPolicy removes a subscription level rate limit policy from the rate-limit cache. +func (r *rateLimitPolicyCache) RemoveSubscriptionRateLimitPolicy(policy dpv1alpha3.ResolveSubscriptionRatelimitPolicy) { + rlsPolicyCache.metadataBasedMu.Lock() + defer rlsPolicyCache.metadataBasedMu.Unlock() + if policiesForOrg, ok := rlsPolicyCache.metadataBasedPolicies[subscriptionPolicyType][policy.Organization]; ok { + delete(policiesForOrg, policy.Name) + } +} + +// UpdateSubscriptionRateLimitPolicy updates a subscription level rate limit policy in the rate-limit cache. +// func (r *rateLimitPolicyCache) UpdateSubscriptionRateLimitPolicy(policy v1alpha1.ResolveSubscriptionRatelimitPolicy) { +// rlsPolicyCache.metadataBasedMu.Lock() +// defer rlsPolicyCache.metadataBasedMu.Unlock() +// if policiesForOrg, ok := rlsPolicyCache.metadataBasedPolicies[subscriptionPolicyType][policy.Organization]; ok { +// delete(policiesForOrg, policy.Name) +// } +// error := r.AddSubscriptionLevelRateLimitPolicy(policy) +// if error != nil { +// loggers.LoggerXds.Errorf("Error occurred while updating subscription policy: %s for the organization %s. Error: %v", +// policy.Name, policy.Organization, error) +// } +// } + +// AddSubscriptionLevelRateLimitPolicy adds a subscription level rate limit policy to the rate-limit cache. +func (r *rateLimitPolicyCache) AddSubscriptionLevelRateLimitPolicy(policy dpv1alpha3.ResolveSubscriptionRatelimitPolicy) error { + rateLimitUnit, err := parseRateLimitUnitFromSubscriptionPolicy(policy.RequestCount.Unit) + if err != nil { + loggers.LoggerXds.Error("Error while getting the rate limit unit: ", err) + return err + } + rlPolicyConfig := rls_config.RateLimitPolicy{ + Unit: rateLimitUnit, + RequestsPerUnit: uint32(policy.RequestCount.RequestsPerUnit), + } + descriptor := &rls_config.RateLimitDescriptor{ + Key: "policy", + Value: policy.Name, + RateLimit: &rlPolicyConfig, + ShadowMode: !policy.StopOnQuotaReach, + } + loggers.LoggerAPK.Info("Subscription policy: ", policy) + loggers.LoggerAPK.Info("Subscription policy descriptor: ", descriptor) + loggers.LoggerAPK.Info("Subscription policy type: ", subscriptionPolicyType) + loggers.LoggerAPK.Info("Subscription policy organization: ", policy.Organization) + if _, ok := rlsPolicyCache.metadataBasedPolicies[subscriptionPolicyType]; !ok { + rlsPolicyCache.metadataBasedPolicies[subscriptionPolicyType] = make(map[string]map[string]*rls_config.RateLimitDescriptor) + } + if _, ok := rlsPolicyCache.metadataBasedPolicies[subscriptionPolicyType][policy.Organization]; !ok { + loggers.LoggerAPK.Info("Subscription policy 1st create: ", policy) + rlsPolicyCache.metadataBasedPolicies[subscriptionPolicyType][policy.Organization] = make(map[string]*rls_config.RateLimitDescriptor) + } + + if policy.RequestCount.RequestsPerUnit > 0 && policy.RequestCount.Unit != "" { + burstCtrlUnit, err := parseRateLimitUnitFromSubscriptionPolicy(policy.RequestCount.Unit) + if err != nil { + loggers.LoggerXds.Error("Error while getting the burst control time unit", err) + return err + } + burstCtrlPolicyConfig := rls_config.RateLimitPolicy{ + Unit: burstCtrlUnit, + RequestsPerUnit: uint32(policy.RequestCount.RequestsPerUnit), + } + burstCtrlDescriptor := &rls_config.RateLimitDescriptor{ + Key: "burst", + Value: "enabled", + RateLimit: &burstCtrlPolicyConfig, + } + descriptor.Descriptors = append(descriptor.Descriptors, burstCtrlDescriptor) + } + rlsPolicyCache.metadataBasedPolicies[subscriptionPolicyType][policy.Organization][policy.Name] = descriptor + return nil +} + func parseRateLimitPolicyToXDS(policy dpv1alpha1.ResolveRateLimit) *rls_config.RateLimitPolicy { loggers.LoggerAPKOperator.Info("Rate count unit: ", policy.RequestsPerUnit) unit := getRateLimitUnit(policy.Unit) @@ -334,10 +465,27 @@ func getRateLimitUnit(name string) rls_config.RateLimitUnit { } } +func parseRateLimitUnitFromSubscriptionPolicy(name string) (rls_config.RateLimitUnit, error) { + loggers.LoggerAPKOperator.Info("Subscription Rate limit unit: ", name) + switch strings.ToUpper(name) { + case "SECOND": + return rls_config.RateLimitUnit_SECOND, nil + case "MINUTE": + return rls_config.RateLimitUnit_MINUTE, nil + case "HOUR": + return rls_config.RateLimitUnit_HOUR, nil + case "DAY": + return rls_config.RateLimitUnit_DAY, nil + default: + return rls_config.RateLimitUnit_UNKNOWN, fmt.Errorf("invalid rate limit unit %q", name) + } +} + func init() { rlsPolicyCache = &rateLimitPolicyCache{ xdsCache: gcp_cache.NewSnapshotCache(false, IDHash{}, nil), apiLevelRateLimitPolicies: make(map[string]map[string]map[string]map[string]*rls_config.RateLimitDescriptor), + metadataBasedPolicies: make(map[string]map[string]map[string]*rls_config.RateLimitDescriptor), customRateLimitPolicies: make(map[string]map[string]*rls_config.RateLimitDescriptor), } } diff --git a/common-controller/internal/xds/server.go b/common-controller/internal/xds/server.go index b65e5719c3..24be21d0ad 100644 --- a/common-controller/internal/xds/server.go +++ b/common-controller/internal/xds/server.go @@ -34,6 +34,7 @@ import ( wso2_cache "github.com/wso2/apk/adapter/pkg/discovery/protocol/cache/v3" eventhubTypes "github.com/wso2/apk/adapter/pkg/eventhub/types" dpv1alpha1 "github.com/wso2/apk/common-go-libs/apis/dp/v1alpha1" + dpv1alpha3 "github.com/wso2/apk/common-go-libs/apis/dp/v1alpha3" ) // EnvoyInternalAPI struct use to hold envoy resources and adapter internal resources @@ -190,6 +191,16 @@ func DeleteResourceLevelRateLimitPolicies(resolveRatelimitPolicyList []dpv1alpha } } +// DeleteSubscriptionRateLimitPolicies delete the ratelimit xds cache +func DeleteSubscriptionRateLimitPolicies(resolveSubscriptionRatelimit dpv1alpha3.ResolveSubscriptionRatelimitPolicy) { + rlsPolicyCache.RemoveSubscriptionRateLimitPolicy(resolveSubscriptionRatelimit) +} + +// UpdateRateLimitXDSCacheForSubscriptionPolicies updates the xDS cache of the RateLimiter for subscription policies. +func UpdateRateLimitXDSCacheForSubscriptionPolicies(resolveSubscriptionRatelimit dpv1alpha3.ResolveSubscriptionRatelimitPolicy) { + rlsPolicyCache.AddSubscriptionLevelRateLimitPolicy(resolveSubscriptionRatelimit) +} + // DeleteCustomRateLimitPolicies delete the ratelimit xds cache func DeleteCustomRateLimitPolicies(customRateLimitPolicy dpv1alpha1.CustomRateLimitPolicyDef) { rlsPolicyCache.DeleteCustomRateLimitPolicies(customRateLimitPolicy) diff --git a/common-controller/pkg/discovery/api/wso2/discovery/subscription/subscription.pb.go b/common-controller/pkg/discovery/api/wso2/discovery/subscription/subscription.pb.go index 078dbf67b1..406eebb63d 100644 --- a/common-controller/pkg/discovery/api/wso2/discovery/subscription/subscription.pb.go +++ b/common-controller/pkg/discovery/api/wso2/discovery/subscription/subscription.pb.go @@ -46,6 +46,7 @@ type Subscription struct { Uuid string `protobuf:"bytes,2,opt,name=uuid,proto3" json:"uuid,omitempty"` Organization string `protobuf:"bytes,3,opt,name=organization,proto3" json:"organization,omitempty"` SubscribedApi *SubscribedAPI `protobuf:"bytes,4,opt,name=subscribedApi,proto3" json:"subscribedApi,omitempty"` + RatelimitTier string `protobuf:"bytes,5,opt,name=ratelimitTier,proto3" json:"ratelimitTier,omitempty"` } func (x *Subscription) Reset() { @@ -108,6 +109,13 @@ func (x *Subscription) GetSubscribedApi() *SubscribedAPI { return nil } +func (x *Subscription) GetRatelimitTier() string { + if x != nil { + return x.RatelimitTier + } + return "" +} + type SubscribedAPI struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -170,7 +178,7 @@ var file_wso2_discovery_subscription_subscription_proto_rawDesc = []byte{ 0x2f, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1b, 0x77, 0x73, 0x6f, 0x32, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, - 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xb6, 0x01, + 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xdc, 0x01, 0x0a, 0x0c, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x75, 0x62, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x75, 0x62, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x12, 0x0a, 0x04, @@ -182,21 +190,23 @@ var file_wso2_discovery_subscription_subscription_proto_rawDesc = []byte{ 0x6f, 0x32, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x64, 0x41, 0x50, 0x49, 0x52, 0x0d, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, - 0x62, 0x65, 0x64, 0x41, 0x70, 0x69, 0x22, 0x3d, 0x0a, 0x0d, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, - 0x69, 0x62, 0x65, 0x64, 0x41, 0x50, 0x49, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x42, 0x95, 0x01, 0x0a, 0x2c, 0x6f, 0x72, 0x67, 0x2e, 0x77, 0x73, - 0x6f, 0x32, 0x2e, 0x61, 0x70, 0x6b, 0x2e, 0x65, 0x6e, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x72, 0x2e, - 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x11, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x50, 0x67, 0x69, 0x74, - 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x77, 0x73, 0x6f, 0x32, 0x2f, 0x61, 0x70, 0x6b, - 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2d, 0x67, 0x6f, 0x2d, 0x6c, 0x69, 0x62, 0x73, 0x2f, - 0x70, 0x6b, 0x67, 0x2f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x2f, 0x61, 0x70, - 0x69, 0x2f, 0x77, 0x73, 0x6f, 0x32, 0x2f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, - 0x2f, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x62, 0x06, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x62, 0x65, 0x64, 0x41, 0x70, 0x69, 0x12, 0x24, 0x0a, 0x0d, 0x72, 0x61, 0x74, 0x65, 0x6c, 0x69, + 0x6d, 0x69, 0x74, 0x54, 0x69, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x72, + 0x61, 0x74, 0x65, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x54, 0x69, 0x65, 0x72, 0x22, 0x3d, 0x0a, 0x0d, + 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x64, 0x41, 0x50, 0x49, 0x12, 0x12, 0x0a, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x42, 0x95, 0x01, 0x0a, 0x2c, + 0x6f, 0x72, 0x67, 0x2e, 0x77, 0x73, 0x6f, 0x32, 0x2e, 0x61, 0x70, 0x6b, 0x2e, 0x65, 0x6e, 0x66, + 0x6f, 0x72, 0x63, 0x65, 0x72, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x2e, + 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x11, 0x53, 0x75, + 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, + 0x01, 0x5a, 0x50, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x77, 0x73, + 0x6f, 0x32, 0x2f, 0x61, 0x70, 0x6b, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2d, 0x67, 0x6f, + 0x2d, 0x6c, 0x69, 0x62, 0x73, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, + 0x65, 0x72, 0x79, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x77, 0x73, 0x6f, 0x32, 0x2f, 0x64, 0x69, 0x73, + 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x2f, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/common-go-libs/apis/cp/v1alpha2/zz_generated.deepcopy.go b/common-go-libs/apis/cp/v1alpha2/zz_generated.deepcopy.go index 4d3fd79aa0..d893c19326 100644 --- a/common-go-libs/apis/cp/v1alpha2/zz_generated.deepcopy.go +++ b/common-go-libs/apis/cp/v1alpha2/zz_generated.deepcopy.go @@ -345,22 +345,6 @@ func (in *SubscriptionList) DeepCopyObject() runtime.Object { return nil } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SubscriptionSpec) DeepCopyInto(out *SubscriptionSpec) { - *out = *in - out.API = in.API -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SubscriptionSpec. -func (in *SubscriptionSpec) DeepCopy() *SubscriptionSpec { - if in == nil { - return nil - } - out := new(SubscriptionSpec) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SubscriptionStatus) DeepCopyInto(out *SubscriptionStatus) { *out = *in diff --git a/common-go-libs/apis/dp/v1alpha1/custom_ratelimit_policy.go b/common-go-libs/apis/dp/v1alpha1/custom_ratelimit_policy.go index 638c98d86b..f885d78b5a 100644 --- a/common-go-libs/apis/dp/v1alpha1/custom_ratelimit_policy.go +++ b/common-go-libs/apis/dp/v1alpha1/custom_ratelimit_policy.go @@ -17,6 +17,10 @@ package v1alpha1 +import ( + dpv1alpha3 "github.com/wso2/apk/common-go-libs/apis/dp/v1alpha3" +) + // CustomRateLimitPolicyDef defines the desired state of CustomPolicy type CustomRateLimitPolicyDef struct { Key string `json:"key,omitempty"` @@ -29,7 +33,7 @@ type CustomRateLimitPolicyDef struct { } // ParseCustomRateLimitPolicy parses the custom rate limit policy -func ParseCustomRateLimitPolicy(customRateLimitCR RateLimitPolicy) *CustomRateLimitPolicyDef { +func ParseCustomRateLimitPolicy(customRateLimitCR dpv1alpha3.RateLimitPolicy) *CustomRateLimitPolicyDef { return &CustomRateLimitPolicyDef{ Key: customRateLimitCR.Spec.Override.Custom.Key, Value: customRateLimitCR.Spec.Override.Custom.Value, diff --git a/common-go-libs/apis/dp/v1alpha1/ratelimitpolicy_webhook.go b/common-go-libs/apis/dp/v1alpha1/ratelimitpolicy_webhook.go index 89b7d30c5f..b7172ebf71 100644 --- a/common-go-libs/apis/dp/v1alpha1/ratelimitpolicy_webhook.go +++ b/common-go-libs/apis/dp/v1alpha1/ratelimitpolicy_webhook.go @@ -81,7 +81,7 @@ func (r *RateLimitPolicy) ValidatePolicies() error { "Name is required")) } if !(r.Spec.TargetRef.Kind == constants.KindAPI || r.Spec.TargetRef.Kind == constants.KindResource || - r.Spec.TargetRef.Kind == constants.KindGateway) { + r.Spec.TargetRef.Kind == constants.KindGateway || r.Spec.TargetRef.Kind == "Subscription") { allErrs = append(allErrs, field.Invalid(field.NewPath("spec").Child("targetRef").Child("kind"), r.Spec.TargetRef.Kind, "Invalid Kind is provided")) } diff --git a/common-go-libs/pkg/discovery/api/wso2/discovery/subscription/subscription.pb.go b/common-go-libs/pkg/discovery/api/wso2/discovery/subscription/subscription.pb.go index 078dbf67b1..406eebb63d 100644 --- a/common-go-libs/pkg/discovery/api/wso2/discovery/subscription/subscription.pb.go +++ b/common-go-libs/pkg/discovery/api/wso2/discovery/subscription/subscription.pb.go @@ -46,6 +46,7 @@ type Subscription struct { Uuid string `protobuf:"bytes,2,opt,name=uuid,proto3" json:"uuid,omitempty"` Organization string `protobuf:"bytes,3,opt,name=organization,proto3" json:"organization,omitempty"` SubscribedApi *SubscribedAPI `protobuf:"bytes,4,opt,name=subscribedApi,proto3" json:"subscribedApi,omitempty"` + RatelimitTier string `protobuf:"bytes,5,opt,name=ratelimitTier,proto3" json:"ratelimitTier,omitempty"` } func (x *Subscription) Reset() { @@ -108,6 +109,13 @@ func (x *Subscription) GetSubscribedApi() *SubscribedAPI { return nil } +func (x *Subscription) GetRatelimitTier() string { + if x != nil { + return x.RatelimitTier + } + return "" +} + type SubscribedAPI struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -170,7 +178,7 @@ var file_wso2_discovery_subscription_subscription_proto_rawDesc = []byte{ 0x2f, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1b, 0x77, 0x73, 0x6f, 0x32, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, - 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xb6, 0x01, + 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xdc, 0x01, 0x0a, 0x0c, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x75, 0x62, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x75, 0x62, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x12, 0x0a, 0x04, @@ -182,21 +190,23 @@ var file_wso2_discovery_subscription_subscription_proto_rawDesc = []byte{ 0x6f, 0x32, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x64, 0x41, 0x50, 0x49, 0x52, 0x0d, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, - 0x62, 0x65, 0x64, 0x41, 0x70, 0x69, 0x22, 0x3d, 0x0a, 0x0d, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, - 0x69, 0x62, 0x65, 0x64, 0x41, 0x50, 0x49, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x42, 0x95, 0x01, 0x0a, 0x2c, 0x6f, 0x72, 0x67, 0x2e, 0x77, 0x73, - 0x6f, 0x32, 0x2e, 0x61, 0x70, 0x6b, 0x2e, 0x65, 0x6e, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x72, 0x2e, - 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x11, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x50, 0x67, 0x69, 0x74, - 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x77, 0x73, 0x6f, 0x32, 0x2f, 0x61, 0x70, 0x6b, - 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2d, 0x67, 0x6f, 0x2d, 0x6c, 0x69, 0x62, 0x73, 0x2f, - 0x70, 0x6b, 0x67, 0x2f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x2f, 0x61, 0x70, - 0x69, 0x2f, 0x77, 0x73, 0x6f, 0x32, 0x2f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, - 0x2f, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x62, 0x06, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x62, 0x65, 0x64, 0x41, 0x70, 0x69, 0x12, 0x24, 0x0a, 0x0d, 0x72, 0x61, 0x74, 0x65, 0x6c, 0x69, + 0x6d, 0x69, 0x74, 0x54, 0x69, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x72, + 0x61, 0x74, 0x65, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x54, 0x69, 0x65, 0x72, 0x22, 0x3d, 0x0a, 0x0d, + 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x64, 0x41, 0x50, 0x49, 0x12, 0x12, 0x0a, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x42, 0x95, 0x01, 0x0a, 0x2c, + 0x6f, 0x72, 0x67, 0x2e, 0x77, 0x73, 0x6f, 0x32, 0x2e, 0x61, 0x70, 0x6b, 0x2e, 0x65, 0x6e, 0x66, + 0x6f, 0x72, 0x63, 0x65, 0x72, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x2e, + 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x11, 0x53, 0x75, + 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, + 0x01, 0x5a, 0x50, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x77, 0x73, + 0x6f, 0x32, 0x2f, 0x61, 0x70, 0x6b, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2d, 0x67, 0x6f, + 0x2d, 0x6c, 0x69, 0x62, 0x73, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, + 0x65, 0x72, 0x79, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x77, 0x73, 0x6f, 0x32, 0x2f, 0x64, 0x69, 0x73, + 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x2f, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/discovery/subscription/Subscription.java b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/discovery/subscription/Subscription.java index 8afbfaa967..177c99c0fb 100644 --- a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/discovery/subscription/Subscription.java +++ b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/discovery/subscription/Subscription.java @@ -23,6 +23,7 @@ private Subscription() { subStatus_ = ""; uuid_ = ""; organization_ = ""; + ratelimitTier_ = ""; } @java.lang.Override @@ -86,6 +87,12 @@ private Subscription( break; } + case 42: { + java.lang.String s = input.readStringRequireUtf8(); + + ratelimitTier_ = s; + break; + } default: { if (!parseUnknownField( input, unknownFields, extensionRegistry, tag)) { @@ -258,6 +265,44 @@ public org.wso2.apk.enforcer.discovery.subscription.SubscribedAPIOrBuilder getSu return getSubscribedApi(); } + public static final int RATELIMITTIER_FIELD_NUMBER = 5; + private volatile java.lang.Object ratelimitTier_; + /** + * string ratelimitTier = 5; + * @return The ratelimitTier. + */ + @java.lang.Override + public java.lang.String getRatelimitTier() { + java.lang.Object ref = ratelimitTier_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + ratelimitTier_ = s; + return s; + } + } + /** + * string ratelimitTier = 5; + * @return The bytes for ratelimitTier. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getRatelimitTierBytes() { + java.lang.Object ref = ratelimitTier_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + ratelimitTier_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + private byte memoizedIsInitialized = -1; @java.lang.Override public final boolean isInitialized() { @@ -284,6 +329,9 @@ public void writeTo(com.google.protobuf.CodedOutputStream output) if (subscribedApi_ != null) { output.writeMessage(4, getSubscribedApi()); } + if (!getRatelimitTierBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 5, ratelimitTier_); + } unknownFields.writeTo(output); } @@ -306,6 +354,9 @@ public int getSerializedSize() { size += com.google.protobuf.CodedOutputStream .computeMessageSize(4, getSubscribedApi()); } + if (!getRatelimitTierBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(5, ratelimitTier_); + } size += unknownFields.getSerializedSize(); memoizedSize = size; return size; @@ -332,6 +383,8 @@ public boolean equals(final java.lang.Object obj) { if (!getSubscribedApi() .equals(other.getSubscribedApi())) return false; } + if (!getRatelimitTier() + .equals(other.getRatelimitTier())) return false; if (!unknownFields.equals(other.unknownFields)) return false; return true; } @@ -353,6 +406,8 @@ public int hashCode() { hash = (37 * hash) + SUBSCRIBEDAPI_FIELD_NUMBER; hash = (53 * hash) + getSubscribedApi().hashCode(); } + hash = (37 * hash) + RATELIMITTIER_FIELD_NUMBER; + hash = (53 * hash) + getRatelimitTier().hashCode(); hash = (29 * hash) + unknownFields.hashCode(); memoizedHashCode = hash; return hash; @@ -502,6 +557,8 @@ public Builder clear() { subscribedApi_ = null; subscribedApiBuilder_ = null; } + ratelimitTier_ = ""; + return this; } @@ -536,6 +593,7 @@ public org.wso2.apk.enforcer.discovery.subscription.Subscription buildPartial() } else { result.subscribedApi_ = subscribedApiBuilder_.build(); } + result.ratelimitTier_ = ratelimitTier_; onBuilt(); return result; } @@ -599,6 +657,10 @@ public Builder mergeFrom(org.wso2.apk.enforcer.discovery.subscription.Subscripti if (other.hasSubscribedApi()) { mergeSubscribedApi(other.getSubscribedApi()); } + if (!other.getRatelimitTier().isEmpty()) { + ratelimitTier_ = other.ratelimitTier_; + onChanged(); + } this.mergeUnknownFields(other.unknownFields); onChanged(); return this; @@ -974,6 +1036,82 @@ public org.wso2.apk.enforcer.discovery.subscription.SubscribedAPIOrBuilder getSu } return subscribedApiBuilder_; } + + private java.lang.Object ratelimitTier_ = ""; + /** + * string ratelimitTier = 5; + * @return The ratelimitTier. + */ + public java.lang.String getRatelimitTier() { + java.lang.Object ref = ratelimitTier_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + ratelimitTier_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * string ratelimitTier = 5; + * @return The bytes for ratelimitTier. + */ + public com.google.protobuf.ByteString + getRatelimitTierBytes() { + java.lang.Object ref = ratelimitTier_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + ratelimitTier_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * string ratelimitTier = 5; + * @param value The ratelimitTier to set. + * @return This builder for chaining. + */ + public Builder setRatelimitTier( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + + ratelimitTier_ = value; + onChanged(); + return this; + } + /** + * string ratelimitTier = 5; + * @return This builder for chaining. + */ + public Builder clearRatelimitTier() { + + ratelimitTier_ = getDefaultInstance().getRatelimitTier(); + onChanged(); + return this; + } + /** + * string ratelimitTier = 5; + * @param value The bytes for ratelimitTier to set. + * @return This builder for chaining. + */ + public Builder setRatelimitTierBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + checkByteStringIsUtf8(value); + + ratelimitTier_ = value; + onChanged(); + return this; + } @java.lang.Override public final Builder setUnknownFields( final com.google.protobuf.UnknownFieldSet unknownFields) { diff --git a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/discovery/subscription/SubscriptionOrBuilder.java b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/discovery/subscription/SubscriptionOrBuilder.java index 514093ba90..77c25683fe 100644 --- a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/discovery/subscription/SubscriptionOrBuilder.java +++ b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/discovery/subscription/SubscriptionOrBuilder.java @@ -57,4 +57,16 @@ public interface SubscriptionOrBuilder extends * .wso2.discovery.subscription.SubscribedAPI subscribedApi = 4; */ org.wso2.apk.enforcer.discovery.subscription.SubscribedAPIOrBuilder getSubscribedApiOrBuilder(); + + /** + * string ratelimitTier = 5; + * @return The ratelimitTier. + */ + java.lang.String getRatelimitTier(); + /** + * string ratelimitTier = 5; + * @return The bytes for ratelimitTier. + */ + com.google.protobuf.ByteString + getRatelimitTierBytes(); } diff --git a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/discovery/subscription/SubscriptionProto.java b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/discovery/subscription/SubscriptionProto.java index 14e8baa70e..20d8c74130 100644 --- a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/discovery/subscription/SubscriptionProto.java +++ b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/discovery/subscription/SubscriptionProto.java @@ -34,16 +34,17 @@ public static void registerAllExtensions( static { java.lang.String[] descriptorData = { "\n.wso2/discovery/subscription/subscripti" + - "on.proto\022\033wso2.discovery.subscription\"\210\001" + + "on.proto\022\033wso2.discovery.subscription\"\237\001" + "\n\014Subscription\022\021\n\tsubStatus\030\001 \001(\t\022\014\n\004uui" + "d\030\002 \001(\t\022\024\n\014organization\030\003 \001(\t\022A\n\rsubscri" + "bedApi\030\004 \001(\0132*.wso2.discovery.subscripti" + - "on.SubscribedAPI\".\n\rSubscribedAPI\022\014\n\004nam" + - "e\030\001 \001(\t\022\017\n\007version\030\002 \001(\tB\225\001\n,org.wso2.ap" + - "k.enforcer.discovery.subscriptionB\021Subsc" + - "riptionProtoP\001ZPgithub.com/wso2/apk/comm" + - "on-go-libs/pkg/discovery/api/wso2/discov" + - "ery/subscriptionb\006proto3" + "on.SubscribedAPI\022\025\n\rratelimitTier\030\005 \001(\t\"" + + ".\n\rSubscribedAPI\022\014\n\004name\030\001 \001(\t\022\017\n\007versio" + + "n\030\002 \001(\tB\225\001\n,org.wso2.apk.enforcer.discov" + + "ery.subscriptionB\021SubscriptionProtoP\001ZPg" + + "ithub.com/wso2/apk/common-go-libs/pkg/di" + + "scovery/api/wso2/discovery/subscriptionb" + + "\006proto3" }; descriptor = com.google.protobuf.Descriptors.FileDescriptor .internalBuildGeneratedFileFrom(descriptorData, @@ -54,7 +55,7 @@ public static void registerAllExtensions( internal_static_wso2_discovery_subscription_Subscription_fieldAccessorTable = new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( internal_static_wso2_discovery_subscription_Subscription_descriptor, - new java.lang.String[] { "SubStatus", "Uuid", "Organization", "SubscribedApi", }); + new java.lang.String[] { "SubStatus", "Uuid", "Organization", "SubscribedApi", "RatelimitTier", }); internal_static_wso2_discovery_subscription_SubscribedAPI_descriptor = getDescriptor().getMessageTypes().get(1); internal_static_wso2_discovery_subscription_SubscribedAPI_fieldAccessorTable = new diff --git a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/grpc/ExtAuthService.java b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/grpc/ExtAuthService.java index 2a1e119d4d..eb2b59a978 100644 --- a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/grpc/ExtAuthService.java +++ b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/grpc/ExtAuthService.java @@ -146,7 +146,6 @@ private CheckResponse buildResponse(CheckRequest request, ResponseObject respons responseObject.getMetaDataMap().forEach((key, value) -> addMetadata(metadataStructBuilder, key, value)); } - addMetadata(metadataStructBuilder, "correlationID", responseObject.getCorrelationID()); addMetadata(metadataStructBuilder, MetadataConstants.APK_ENFORCER_REPLY, "Ok"); diff --git a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/models/Subscription.java b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/models/Subscription.java index 34fa8c73eb..f41457abf3 100644 --- a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/models/Subscription.java +++ b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/models/Subscription.java @@ -29,6 +29,7 @@ public class Subscription implements CacheableEntity { private String subscriptionStatus = null; private String organization = null; private SubscribedAPI subscribedApi = null; + private String ratelimitTier = null; private long timeStamp; public String getSubscriptionId() { @@ -87,6 +88,14 @@ public String getCacheKey() { return subscriptionId; } + public String getRatelimitTier() { + return ratelimitTier; + } + + public void setRatelimitTier(String ratelimitTier) { + this.ratelimitTier = ratelimitTier; + } + @Override public String toString() { diff --git a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/models/SubscriptionPolicy.java b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/models/SubscriptionPolicy.java deleted file mode 100644 index 3cac14ce0c..0000000000 --- a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/models/SubscriptionPolicy.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2020, WSO2 LLC. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 LLC. licenses this file to you 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 org.wso2.apk.enforcer.models; - -import org.wso2.apk.enforcer.subscription.SubscriptionDataStoreUtil; - -/** - * Entity to represent a Subscription Throttling Policy. - */ -public class SubscriptionPolicy extends Policy { - - private Integer rateLimitCount = null; - private String rateLimitTimeUnit = null; - private Boolean stopOnQuotaReach = null; - private Integer graphQLMaxComplexity = null; - private Integer graphQLMaxDepth = null; - - public int getRateLimitCount() { - - return rateLimitCount; - } - - public void setRateLimitCount(int rateLimitCount) { - - this.rateLimitCount = rateLimitCount; - } - - public String getRateLimitTimeUnit() { - - return rateLimitTimeUnit; - } - - public void setRateLimitTimeUnit(String rateLimitTimeUnit) { - - this.rateLimitTimeUnit = rateLimitTimeUnit; - } - - public boolean isStopOnQuotaReach() { - - return stopOnQuotaReach; - } - - public void setStopOnQuotaReach(boolean stopOnQuotaReach) { - - this.stopOnQuotaReach = stopOnQuotaReach; - } - - public int getGraphQLMaxComplexity() { - return graphQLMaxComplexity; - } - - public void setGraphQLMaxComplexity(int graphQLMaxComplexity) { - this.graphQLMaxComplexity = graphQLMaxComplexity; - } - - public int getGraphQLMaxDepth() { - return graphQLMaxDepth; - } - - public void setGraphQLMaxDepth(int graphQLMaxDepth) { - this.graphQLMaxDepth = graphQLMaxDepth; - } - @Override - public String getCacheKey() { - - return PolicyType.SUBSCRIPTION + SubscriptionDataStoreUtil.getPolicyCacheKey(getName()); - - } - - @Override - public String toString() { - return "SubscriptionPolicy [rateLimitCount=" + rateLimitCount + ", rateLimitTimeUnit=" + rateLimitTimeUnit - + ", stopOnQuotaReach=" + stopOnQuotaReach + ", getId()=" + getId() + ", getQuotaType()=" - + getQuotaType() + ", isContentAware()=" + isContentAware() + ", getTenantId()=" + getTenantId() - + ", getName()=" + getName() + "]"; - } -} - diff --git a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/models/SubscriptionPolicyList.java b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/models/SubscriptionPolicyList.java deleted file mode 100644 index 8f9b427c2c..0000000000 --- a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/models/SubscriptionPolicyList.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2020, WSO2 LLC. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 LLC. licenses this file to you 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 org.wso2.apk.enforcer.models; - -import java.util.ArrayList; -import java.util.List; - -/** - * Holds details about list of subscription policies. - */ -public class SubscriptionPolicyList { - - private Integer count = null; - private List list = new ArrayList<>(); - - public Integer getCount() { - - return count; - } - - public void setCount(Integer count) { - - this.count = count; - } - - public List getList() { - - return list; - } - - public void setList(List list) { - - this.list = list; - } -} diff --git a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/security/jwt/Oauth2Authenticator.java b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/security/jwt/Oauth2Authenticator.java index 586ca88144..9a29fbf451 100644 --- a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/security/jwt/Oauth2Authenticator.java +++ b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/security/jwt/Oauth2Authenticator.java @@ -41,6 +41,9 @@ import org.wso2.apk.enforcer.constants.APIConstants; import org.wso2.apk.enforcer.constants.APISecurityConstants; import org.wso2.apk.enforcer.dto.APIKeyValidationInfoDTO; +import org.wso2.apk.enforcer.models.ApplicationKeyMapping; +import org.wso2.apk.enforcer.models.ApplicationMapping; +import org.wso2.apk.enforcer.models.Subscription; import org.wso2.apk.enforcer.security.Authenticator; import org.wso2.apk.enforcer.security.KeyValidator; import org.wso2.apk.enforcer.security.TokenValidationContext; @@ -244,8 +247,31 @@ public AuthenticationContext authenticate(RequestContext requestContext) throws endUserToken); } - return FilterUtils.generateAuthenticationContext(requestContext, validationInfo.getIdentifier(), + AuthenticationContext authenticationContext = FilterUtils.generateAuthenticationContext(requestContext, validationInfo.getIdentifier(), validationInfo, apiKeyValidationInfoDTO, endUserToken, jwtToken, true); + + // For subscription rate limiting, it is required to populate dynamic metadata + SubscriptionDataStore datastore = SubscriptionDataHolder.getInstance(). + getSubscriptionDataStore(organization); + ApplicationKeyMapping keyMapping = datastore.getMatchingApplicationKeyMapping(validationInfo.getConsumerKey(), requestContext.getMatchedAPI().getEnvType(), APIConstants.API_SECURITY_OAUTH2, + requestContext.getMatchedAPI().getEnvironment()); + + if(keyMapping != null) { + String applicationId = keyMapping.getApplicationUUID(); + Set appMappings = datastore.getMatchingApplicationMappings(applicationId); + for (ApplicationMapping appMapping : appMappings) { + String subscriptionUUID = appMapping.getSubscriptionUUID(); + Subscription subscription = datastore.getMatchingSubscription(subscriptionUUID); + if (!"Unlimited".equals(subscription.getRatelimitTier())) { + String subscriptionId = subscription.getSubscribedApi().getName() + ":" + + applicationId; + requestContext.addMetadataToMap("ratelimit:subscription", subscriptionId); + requestContext.addMetadataToMap("ratelimit:usage-policy", subscription.getRatelimitTier()); + requestContext.addMetadataToMap("ratelimit:organization", subscription.getOrganization()); + } + } + } + return authenticationContext; } else { throw new APISecurityException(APIConstants.StatusCodes.UNAUTHENTICATED.getCode(), validationInfo.getValidationCode(), diff --git a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/server/swagger/SwaggerServerInitializer.java b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/server/swagger/SwaggerServerInitializer.java index b65f30156a..920641301c 100644 --- a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/server/swagger/SwaggerServerInitializer.java +++ b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/server/swagger/SwaggerServerInitializer.java @@ -12,7 +12,6 @@ public class SwaggerServerInitializer extends ChannelInitializer { private final SslContext sslCtx; public SwaggerServerInitializer(SslContext sslCtx) { - System.out.println("SwaggerServerInitializer constructor"); this.sslCtx = sslCtx; } diff --git a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/subscription/SubscriptionDataStoreImpl.java b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/subscription/SubscriptionDataStoreImpl.java index b18f3240c0..4859bac170 100644 --- a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/subscription/SubscriptionDataStoreImpl.java +++ b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/subscription/SubscriptionDataStoreImpl.java @@ -62,7 +62,6 @@ public class SubscriptionDataStoreImpl implements SubscriptionDataStore { private Map> applicationMappingMap = new ConcurrentHashMap<>(); private Map applicationMap = new ConcurrentHashMap<>(); private Map subscriptionMap = new ConcurrentHashMap<>(); - private Map jwtValidatorMap = new ConcurrentHashMap<>(); SubscriptionDataStoreImpl() { @@ -291,6 +290,7 @@ public void addSubscription(org.wso2.apk.enforcer.discovery.subscription.Subscri resolvedSubscription.setSubscriptionStatus(subscription.getSubStatus()); resolvedSubscription.setOrganization(subscription.getOrganization()); resolvedSubscription.setSubscribedApi(new SubscribedAPI(subscription.getSubscribedApi())); + resolvedSubscription.setRatelimitTier(subscription.getRatelimitTier()); if (subscriptionMap.containsKey(resolvedSubscription.getSubscriptionId())) { subscriptionMap.replace(resolvedSubscription.getSubscriptionId(), resolvedSubscription); } else { diff --git a/helm-charts/crds/cp.wso2.com_subscriptions.yaml b/helm-charts/crds/cp.wso2.com_subscriptions.yaml index 172cb762c9..77dd764eb0 100644 --- a/helm-charts/crds/cp.wso2.com_subscriptions.yaml +++ b/helm-charts/crds/cp.wso2.com_subscriptions.yaml @@ -47,11 +47,85 @@ spec: type: object organization: type: string + ratelimitRef: + description: RatelimitRef defines the ratelimit associated with the + subscription + properties: + level: + type: string + name: + type: string + required: + - level + - name + type: object + subscriptionStatus: + type: string + required: + - api + - organization + - ratelimitRef + - subscriptionStatus + type: object + status: + description: SubscriptionStatus defines the observed state of Subscription + type: object + type: object + served: true + storage: false + subresources: + status: {} + - name: v1alpha3 + schema: + openAPIV3Schema: + description: Subscription is the Schema for the subscriptions API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: SubscriptionSpec defines the desired state of Subscription + properties: + api: + description: API defines the API associated with the subscription + properties: + name: + type: string + version: + type: string + required: + - name + - version + type: object + organization: + type: string + ratelimitRef: + description: RatelimitRef defines the ratelimit associated with the + subscription + properties: + level: + type: string + name: + type: string + required: + - level + - name + type: object subscriptionStatus: type: string required: - api - organization + - ratelimitRef - subscriptionStatus type: object status: diff --git a/helm-charts/crds/dp.wso2.com_ratelimitpolicies.yaml b/helm-charts/crds/dp.wso2.com_ratelimitpolicies.yaml index 70851afd0f..c4d3ea8a9b 100644 --- a/helm-charts/crds/dp.wso2.com_ratelimitpolicies.yaml +++ b/helm-charts/crds/dp.wso2.com_ratelimitpolicies.yaml @@ -3,8 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.9.2 - creationTimestamp: null + controller-gen.kubebuilder.io/version: v0.12.0 name: ratelimitpolicies.dp.wso2.com spec: group: dp.wso2.com @@ -80,6 +79,258 @@ spec: description: Value is the value of the custom policy type: string type: object + subscription: + description: Subscription level ratelimit policy + properties: + burstControl: + description: BurstControl defines the rule for token count + quota. + properties: + requestsPerUnit: + format: int32 + type: integer + unit: + type: string + type: object + organization: + type: string + requestCount: + description: RequestCount defines the rule for request count + quota. + properties: + requestsPerUnit: + format: int32 + type: integer + unit: + type: string + type: object + stopOnQuotaReach: + type: boolean + required: + - organization + - stopOnQuotaReach + type: object + type: object + override: + description: RateLimitAPIPolicy defines the desired state of Policy + properties: + api: + description: API level ratelimit policy + properties: + requestsPerUnit: + description: RequestPerUnit is the number of requests allowed + per unit time + format: int32 + type: integer + unit: + description: Unit is the unit of the requestsPerUnit + enum: + - Minute + - Hour + - Day + type: string + type: object + custom: + description: Custom ratelimit policy + properties: + key: + description: Key is the key of the custom policy + minLength: 1 + type: string + organization: + description: Organization is the organization of the policy + type: string + requestsPerUnit: + description: RequestPerUnit is the number of requests allowed + per unit time + format: int32 + type: integer + unit: + description: Unit is the unit of the requestsPerUnit + enum: + - Minute + - Hour + - Day + type: string + value: + description: Value is the value of the custom policy + type: string + type: object + subscription: + description: Subscription level ratelimit policy + properties: + burstControl: + description: BurstControl defines the rule for token count + quota. + properties: + requestsPerUnit: + format: int32 + type: integer + unit: + type: string + type: object + organization: + type: string + requestCount: + description: RequestCount defines the rule for request count + quota. + properties: + requestsPerUnit: + format: int32 + type: integer + unit: + type: string + type: object + stopOnQuotaReach: + type: boolean + required: + - organization + - stopOnQuotaReach + type: object + type: object + targetRef: + description: PolicyTargetReference identifies an API object to apply + a direct or inherited policy to. This should be used as part of + Policy resources that can target Gateway API resources. For more + information on how this policy attachment model works, and a sample + Policy resource, refer to the policy attachment documentation for + Gateway API. + properties: + group: + description: Group is the group of the target resource. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the target resource. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the target resource. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: Namespace is the namespace of the referent. When + unspecified, the local namespace is inferred. Even when policy + targets a resource in a different namespace, it MUST only apply + to traffic originating from the same namespace as the policy. + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + required: + - group + - kind + - name + type: object + type: object + status: + description: RateLimitPolicyStatus defines the observed state of RateLimitPolicy + type: object + type: object + served: true + storage: false + subresources: + status: {} + - name: v1alpha3 + schema: + openAPIV3Schema: + description: RateLimitPolicy is the Schema for the ratelimitpolicies API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: RateLimitPolicySpec defines the desired state of RateLimitPolicy + properties: + default: + description: RateLimitAPIPolicy defines the desired state of Policy + properties: + api: + description: API level ratelimit policy + properties: + requestsPerUnit: + description: RequestPerUnit is the number of requests allowed + per unit time + format: int32 + type: integer + unit: + description: Unit is the unit of the requestsPerUnit + enum: + - Minute + - Hour + - Day + type: string + type: object + custom: + description: Custom ratelimit policy + properties: + key: + description: Key is the key of the custom policy + minLength: 1 + type: string + organization: + description: Organization is the organization of the policy + type: string + requestsPerUnit: + description: RequestPerUnit is the number of requests allowed + per unit time + format: int32 + type: integer + unit: + description: Unit is the unit of the requestsPerUnit + enum: + - Minute + - Hour + - Day + type: string + value: + description: Value is the value of the custom policy + type: string + type: object + subscription: + description: Subscription level ratelimit policy + properties: + burstControl: + description: BurstControl defines the rule for token count + quota. + properties: + requestsPerUnit: + format: int32 + type: integer + unit: + type: string + type: object + organization: + type: string + requestCount: + description: RequestCount defines the rule for request count + quota. + properties: + requestsPerUnit: + format: int32 + type: integer + unit: + type: string + type: object + stopOnQuotaReach: + type: boolean + required: + - organization + - stopOnQuotaReach + type: object type: object override: description: RateLimitAPIPolicy defines the desired state of Policy @@ -126,13 +377,45 @@ spec: description: Value is the value of the custom policy type: string type: object + subscription: + description: Subscription level ratelimit policy + properties: + burstControl: + description: BurstControl defines the rule for token count + quota. + properties: + requestsPerUnit: + format: int32 + type: integer + unit: + type: string + type: object + organization: + type: string + requestCount: + description: RequestCount defines the rule for request count + quota. + properties: + requestsPerUnit: + format: int32 + type: integer + unit: + type: string + type: object + stopOnQuotaReach: + type: boolean + required: + - organization + - stopOnQuotaReach + type: object type: object targetRef: description: PolicyTargetReference identifies an API object to apply - policy to. This should be used as part of Policy resources that - can target Gateway API resources. For more information on how this - policy attachment model works, and a sample Policy resource, refer - to the policy attachment documentation for Gateway API. + a direct or inherited policy to. This should be used as part of + Policy resources that can target Gateway API resources. For more + information on how this policy attachment model works, and a sample + Policy resource, refer to the policy attachment documentation for + Gateway API. properties: group: description: Group is the group of the target resource. diff --git a/helm-charts/values.yaml b/helm-charts/values.yaml index 79d83dd5c8..9cedea8cff 100644 --- a/helm-charts/values.yaml +++ b/helm-charts/values.yaml @@ -48,9 +48,9 @@ wso2: # secretName: "wso2apk-idp-signing" # fileName: "idp.crt" # cp: - # enableApiPropagation: false - # enabledSubscription: false - # host: "apim-apk-agent-service.apk.svc.cluster.local" + # enabledSubscription: true + # host: "apim-apk-agent-service.apk.svc.cluster.local" + # skipSSLVerification: true # skipSSLVerification: false # persistence: # type: "K8s" @@ -241,20 +241,20 @@ wso2: periodSeconds: 20 failureThreshold: 5 strategy: RollingUpdate - imagePullPolicy: Always - image: wso2/apk-enforcer:1.1.0 + imagePullPolicy: IfNotPresent + image: apk-enforcer:1.1.0-SNAPSHOT security: sslHostname: "enforcer" # logging: # level: DEBUG -# configs: + configs: # tls: # secretName: "router-cert" # certKeyFilename: "" # certFilename: "" -# JWKSClient: -# skipSSLVerification: false -# hostnameVerifier: "AllowAll" + # JWKSClient: + # skipSSLVerification: false + # hostnameVerifier: "AllowAll" metrics: enabled: false diff --git a/protos/wso2/discovery/subscription/subscription.proto b/protos/wso2/discovery/subscription/subscription.proto index 77c3a2481d..1597773d17 100644 --- a/protos/wso2/discovery/subscription/subscription.proto +++ b/protos/wso2/discovery/subscription/subscription.proto @@ -31,9 +31,11 @@ message Subscription { string uuid = 2; string organization = 3; SubscribedAPI subscribedApi = 4; + string ratelimitTier = 5; } message SubscribedAPI { string name = 1; string version = 2; } + diff --git a/test/apim-apk-agent-test/cucumber-tests/CRs/artifacts.yaml b/test/apim-apk-agent-test/cucumber-tests/CRs/artifacts.yaml index aa3cac1cdf..ff9675fa70 100644 --- a/test/apim-apk-agent-test/cucumber-tests/CRs/artifacts.yaml +++ b/test/apim-apk-agent-test/cucumber-tests/CRs/artifacts.yaml @@ -307,7 +307,7 @@ spec: - response_headers - invocation_context --- -apiVersion: dp.wso2.com/v1alpha1 +apiVersion: dp.wso2.com/v1alpha3 kind: RateLimitPolicy metadata: name: gw-ratelimit-user @@ -325,7 +325,7 @@ spec: name: wso2-apk-default group: gateway.networking.k8s.io --- -apiVersion: dp.wso2.com/v1alpha1 +apiVersion: dp.wso2.com/v1alpha3 kind: RateLimitPolicy metadata: name: gw-ratelimit-org diff --git a/test/cucumber-tests/CRs/agent-artifacts.yaml b/test/cucumber-tests/CRs/agent-artifacts.yaml index d758aa9f8b..eec0e66f11 100644 --- a/test/cucumber-tests/CRs/agent-artifacts.yaml +++ b/test/cucumber-tests/CRs/agent-artifacts.yaml @@ -304,7 +304,7 @@ spec: - response_headers - invocation_context --- -apiVersion: dp.wso2.com/v1alpha1 +apiVersion: dp.wso2.com/v1alpha3 kind: RateLimitPolicy metadata: name: gw-ratelimit-user @@ -322,7 +322,7 @@ spec: name: wso2-apk-default group: gateway.networking.k8s.io --- -apiVersion: dp.wso2.com/v1alpha1 +apiVersion: dp.wso2.com/v1alpha3 kind: RateLimitPolicy metadata: name: gw-ratelimit-org diff --git a/test/cucumber-tests/CRs/artifacts.yaml b/test/cucumber-tests/CRs/artifacts.yaml index a1731fb900..bd3b218a0a 100644 --- a/test/cucumber-tests/CRs/artifacts.yaml +++ b/test/cucumber-tests/CRs/artifacts.yaml @@ -304,7 +304,7 @@ spec: - response_headers - invocation_context --- -apiVersion: dp.wso2.com/v1alpha1 +apiVersion: dp.wso2.com/v1alpha3 kind: RateLimitPolicy metadata: name: gw-ratelimit-user @@ -322,7 +322,7 @@ spec: name: wso2-apk-default group: gateway.networking.k8s.io --- -apiVersion: dp.wso2.com/v1alpha1 +apiVersion: dp.wso2.com/v1alpha3 kind: RateLimitPolicy metadata: name: gw-ratelimit-org @@ -767,6 +767,32 @@ spec: api: name: "subscription-api" version: "1.0.0" + ratelimitRef: + name : api-subscription-ratelimit + level: application + + +--- +apiVersion: "dp.wso2.com/v1alpha1" +kind: "RateLimitPolicy" +metadata: + name: "api-subscription-ratelimit" +spec: + override: + subscription: + stopOnQuotaReach: true + organization: "default" + requestCount: + requestsPerUnit: 4 + unit: "Minute" + burstControl: + requestsPerUnit: 4 + unit: "Minute" + targetRef: + kind: Subscription + name: "7416c241a121b844392d447f00ff6709cb9c932b" + group: gateway.networking.k8s.io + --- apiVersion: cp.wso2.com/v1alpha2 @@ -885,6 +911,10 @@ spec: api: name: "Semantic Versioning API" version: "v\\d+(\\.\\d+)?" + ratelimitRef: + name: api-subscription-ratelimit + level: application + --- apiVersion: cp.wso2.com/v1alpha2 kind: ApplicationMapping diff --git a/test/integration/integration/tests/resources/tests/custom-policy-ratelimiting.yaml b/test/integration/integration/tests/resources/tests/custom-policy-ratelimiting.yaml index 8a18d9d328..94b0060d27 100644 --- a/test/integration/integration/tests/resources/tests/custom-policy-ratelimiting.yaml +++ b/test/integration/integration/tests/resources/tests/custom-policy-ratelimiting.yaml @@ -13,7 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # ----------------------------------------------------------------------- -apiVersion: dp.wso2.com/v1alpha1 +apiVersion: dp.wso2.com/v1alpha3 kind: RateLimitPolicy metadata: name: http-bin-ratelimit-usergroup diff --git a/test/integration/integration/tests/resources/tests/default-api-version-ratelimit-resource-level.yaml b/test/integration/integration/tests/resources/tests/default-api-version-ratelimit-resource-level.yaml index 07eb23cdfb..2c0aa6d1fc 100644 --- a/test/integration/integration/tests/resources/tests/default-api-version-ratelimit-resource-level.yaml +++ b/test/integration/integration/tests/resources/tests/default-api-version-ratelimit-resource-level.yaml @@ -79,7 +79,7 @@ spec: - host: infra-backend-v1.gateway-integration-test-infra port: 8080 --- -apiVersion: dp.wso2.com/v1alpha1 +apiVersion: dp.wso2.com/v1alpha3 kind: RateLimitPolicy metadata: name: ratelimitter-r1 diff --git a/test/integration/integration/tests/resources/tests/default-api-version-ratelimit.yaml b/test/integration/integration/tests/resources/tests/default-api-version-ratelimit.yaml index 341ea66650..e6d2e40704 100644 --- a/test/integration/integration/tests/resources/tests/default-api-version-ratelimit.yaml +++ b/test/integration/integration/tests/resources/tests/default-api-version-ratelimit.yaml @@ -55,7 +55,7 @@ spec: kind: Backend name: infra-backend-v1 --- -apiVersion: dp.wso2.com/v1alpha1 +apiVersion: dp.wso2.com/v1alpha3 kind: RateLimitPolicy metadata: name: ratelimitter diff --git a/test/integration/integration/tests/resources/tests/ratelimit-priority.yaml b/test/integration/integration/tests/resources/tests/ratelimit-priority.yaml index 5c7617608d..30dab71549 100644 --- a/test/integration/integration/tests/resources/tests/ratelimit-priority.yaml +++ b/test/integration/integration/tests/resources/tests/ratelimit-priority.yaml @@ -79,7 +79,7 @@ spec: - host: infra-backend-v1.gateway-integration-test-infra port: 8080 --- -apiVersion: dp.wso2.com/v1alpha1 +apiVersion: dp.wso2.com/v1alpha3 kind: RateLimitPolicy metadata: name: ratelimitter-r1 @@ -94,7 +94,7 @@ spec: name: ratelimit-priority group: gateway.networking.k8s.io --- -apiVersion: dp.wso2.com/v1alpha1 +apiVersion: dp.wso2.com/v1alpha3 kind: RateLimitPolicy metadata: name: ratelimitter diff --git a/test/integration/integration/tests/update-owner-references.go b/test/integration/integration/tests/update-owner-references.go index 0a104f920c..74f4834b60 100644 --- a/test/integration/integration/tests/update-owner-references.go +++ b/test/integration/integration/tests/update-owner-references.go @@ -22,11 +22,10 @@ import ( "testing" "time" + dpv1alpha1 "github.com/wso2/apk/common-go-libs/apis/dp/v1alpha1" "github.com/wso2/apk/test/integration/integration/utils/suite" "k8s.io/apimachinery/pkg/types" gwapiv1b1 "sigs.k8s.io/gateway-api/apis/v1beta1" - dpv1alpha1 "github.com/wso2/apk/common-go-libs/apis/dp/v1alpha1" - ) func init() { @@ -164,7 +163,7 @@ var UpdateOwnerReferences = suite.IntegrationTest{ } // Wait 5 seconds time.Sleep(5 * time.Second) - + // Verify hr2 has only one parent in the ownerReferences if err := suite.Client.Get(context.TODO(), hr2Key, &hr2); err != nil { t.Fatalf("Unable to load http route with key %+v error: %+v", hr2Key, err) diff --git a/test/k8s-resources/gw-interceptor.yaml b/test/k8s-resources/gw-interceptor.yaml index 42d47c02e5..106e0a4d5b 100644 --- a/test/k8s-resources/gw-interceptor.yaml +++ b/test/k8s-resources/gw-interceptor.yaml @@ -64,7 +64,7 @@ spec: - request_headers - invocation_context --- -apiVersion: dp.wso2.com/v1alpha1 +apiVersion: dp.wso2.com/v1alpha3 kind: RateLimitPolicy metadata: name: gw-ratelimit-user @@ -82,7 +82,7 @@ spec: name: wso2-apk-default group: gateway.networking.k8s.io --- -apiVersion: dp.wso2.com/v1alpha1 +apiVersion: dp.wso2.com/v1alpha3 kind: RateLimitPolicy metadata: name: gw-ratelimit-org