diff --git a/adapter/config/default_config.go b/adapter/config/default_config.go index b40c05a784..9b22d5ef7d 100644 --- a/adapter/config/default_config.go +++ b/adapter/config/default_config.go @@ -143,18 +143,18 @@ var defaultConfig = &Config{ { Organizations: "*", CircuitBreakerName: "BasicCircuitBreaker", - MaxConnections: 3, - MaxRequests: 3, + MaxConnections: 1, + MaxRequests: 1, MaxPendingRequests: 1, - MaxRetries: 3, + MaxConnectionPools: 1, }, { Organizations: "*", CircuitBreakerName: "EnhancedCircuitBreaker", - MaxConnections: 50, - MaxRequests: 50, + MaxConnections: 25, + MaxRequests: 25, MaxPendingRequests: 1, - MaxRetries: 50, + MaxConnectionPools: 2, }, }, }, diff --git a/adapter/internal/api/apis_impl.go b/adapter/internal/api/apis_impl.go index 585702ab43..deeec450a7 100644 --- a/adapter/internal/api/apis_impl.go +++ b/adapter/internal/api/apis_impl.go @@ -223,7 +223,7 @@ func validateAndUpdateXds(apiProject mgw.ProjectAPI, override *bool) (err error) // TODO: (renuka) optimize to update cache only once when all internal memory maps are updated for vhost, environments := range vhostToEnvsMap { - _, err = xds.UpdateAPI(vhost, apiProject, environments, common.XdsOptions{}) + _, err = xds.UpdateAPI(vhost, apiProject, environments, common.XdsOptions{}, synchronizer.ChoreoComponentInfo{}) if err != nil { return } @@ -238,6 +238,7 @@ func ApplyAPIProjectFromAPIM( vhostToEnvsMap map[string][]*synchronizer.GatewayLabel, apiEnvs map[string]map[string]synchronizer.APIEnvProps, xdsOptions common.XdsOptions, + choreoComponentInfo synchronizer.ChoreoComponentInfo, ) (deployedRevisionList []*notifier.DeployedAPIRevision, err error) { apiProject, err := extractAPIProject(payload) if err != nil { @@ -283,7 +284,7 @@ func ApplyAPIProjectFromAPIM( loggers.LoggerAPI.Debugf("Update all environments (%v) of API %v %v:%v with UUID \"%v\".", environments, vhost, apiYaml.Name, apiYaml.Version, apiYaml.ID) // first update the API for vhost - deployedRevision, err := xds.UpdateAPI(vhost, apiProject, environments, xdsOptions) + deployedRevision, err := xds.UpdateAPI(vhost, apiProject, environments, xdsOptions, choreoComponentInfo) if err != nil { return deployedRevisionList, fmt.Errorf("%v:%v with UUID \"%v\"", apiYaml.Name, apiYaml.Version, apiYaml.ID) } diff --git a/adapter/internal/discovery/xds/server.go b/adapter/internal/discovery/xds/server.go index f48de56534..b5b1a8fe22 100644 --- a/adapter/internal/discovery/xds/server.go +++ b/adapter/internal/discovery/xds/server.go @@ -273,7 +273,7 @@ func DeployReadinessAPI(envs []string) { // UpdateAPI updates the Xds Cache when OpenAPI Json content is provided func UpdateAPI(vHost string, apiProject mgw.ProjectAPI, deployedEnvironments []*synchronizer.GatewayLabel, - xdsOptions common.XdsOptions) (*notifier.DeployedAPIRevision, error) { + xdsOptions common.XdsOptions, apiChoreoComponentInfo synchronizer.ChoreoComponentInfo) (*notifier.DeployedAPIRevision, error) { var mgwSwagger mgw.MgwSwagger var deployedRevision *notifier.DeployedAPIRevision @@ -372,14 +372,14 @@ func UpdateAPI(vHost string, apiProject mgw.ProjectAPI, deployedEnvironments []* apiHashValue := generateHashValue(apiYaml.Name, apiYaml.Version) if mgwSwagger.GetProdEndpoints() != nil { - mgwSwagger.GetProdEndpoints().SetEndpointsConfig(apiYaml.EndpointConfig.ProductionEndpoints, apiYaml.EndpointConfig.EndpointType, apiYaml.OrganizationID) + mgwSwagger.GetProdEndpoints().SetEndpointsConfig(apiYaml.EndpointConfig.ProductionEndpoints, apiYaml.EndpointConfig.EndpointType, apiYaml.OrganizationID, apiChoreoComponentInfo.IsChoreoOrgPaid) if !mgwSwagger.GetProdEndpoints().SecurityConfig.Enabled && apiYaml.EndpointConfig.APIEndpointSecurity.Production.Enabled { mgwSwagger.GetProdEndpoints().SecurityConfig = apiYaml.EndpointConfig.APIEndpointSecurity.Production } } if mgwSwagger.GetSandEndpoints() != nil { - mgwSwagger.GetSandEndpoints().SetEndpointsConfig(apiYaml.EndpointConfig.SandBoxEndpoints, apiYaml.EndpointConfig.EndpointType, apiYaml.OrganizationID) + mgwSwagger.GetSandEndpoints().SetEndpointsConfig(apiYaml.EndpointConfig.SandBoxEndpoints, apiYaml.EndpointConfig.EndpointType, apiYaml.OrganizationID, apiChoreoComponentInfo.IsChoreoOrgPaid) if !mgwSwagger.GetSandEndpoints().SecurityConfig.Enabled && apiYaml.EndpointConfig.APIEndpointSecurity.Sandbox.Enabled { mgwSwagger.GetSandEndpoints().SecurityConfig = apiYaml.EndpointConfig.APIEndpointSecurity.Sandbox } diff --git a/adapter/internal/oasparser/model/mgw_swagger.go b/adapter/internal/oasparser/model/mgw_swagger.go index 8841258058..69030b2e17 100644 --- a/adapter/internal/oasparser/model/mgw_swagger.go +++ b/adapter/internal/oasparser/model/mgw_swagger.go @@ -180,6 +180,7 @@ const prototypedAPI = "prototyped" // BasicCircuitBreaker is the name for free tier cluster level circuit breaker const BasicCircuitBreaker = "BasicCircuitBreaker" +const EnhancedCircuitBreaker = "EnhancedCircuitBreaker" // GetCorsConfig returns the CorsConfiguration Object. func (swagger *MgwSwagger) GetCorsConfig() *CorsConfig { @@ -643,7 +644,7 @@ func (swagger *MgwSwagger) setXWso2Endpoints() error { } // SetEndpointsConfig set configs for Endpoints sent by api.yaml -func (endpointCluster *EndpointCluster) SetEndpointsConfig(endpointInfos []EndpointInfo, apiType string, orgID string) error { +func (endpointCluster *EndpointCluster) SetEndpointsConfig(endpointInfos []EndpointInfo, apiType string, orgID string, isChoreoOrgPaid bool) error { if endpointInfos == nil || len(endpointInfos) == 0 { return nil } @@ -685,7 +686,16 @@ func (endpointCluster *EndpointCluster) SetEndpointsConfig(endpointInfos []Endpo var selectedCircuitBreaker *CircuitBreakers for _, circuitBreaker := range conf.Envoy.Upstream.CircuitBreakers { - if utills.GetIsOrganizationInList(orgID, circuitBreaker.Organizations) { + if isChoreoOrgPaid && circuitBreaker.CircuitBreakerName == EnhancedCircuitBreaker { + selectedCircuitBreaker = createCircuitBreaker( + circuitBreaker.MaxConnections, + circuitBreaker.MaxPendingRequests, + circuitBreaker.MaxRequests, + circuitBreaker.MaxRetries, + circuitBreaker.MaxConnectionPools, + ) + break + } else if !isChoreoOrgPaid && circuitBreaker.CircuitBreakerName == BasicCircuitBreaker { selectedCircuitBreaker = createCircuitBreaker( circuitBreaker.MaxConnections, circuitBreaker.MaxPendingRequests, @@ -694,22 +704,6 @@ func (endpointCluster *EndpointCluster) SetEndpointsConfig(endpointInfos []Endpo circuitBreaker.MaxConnectionPools, ) break - } - } - if selectedCircuitBreaker == nil { - for _, circuitBreaker := range conf.Envoy.Upstream.CircuitBreakers { - // breaks from the first iteration - if circuitBreaker.CircuitBreakerName == BasicCircuitBreaker { - selectedCircuitBreaker = createCircuitBreaker( - circuitBreaker.MaxConnections, - circuitBreaker.MaxPendingRequests, - circuitBreaker.MaxRequests, - circuitBreaker.MaxRetries, - circuitBreaker.MaxConnectionPools, - ) - break - } - } } endpointCluster.Config.CircuitBreakers = selectedCircuitBreaker diff --git a/adapter/internal/oasparser/model/types.go b/adapter/internal/oasparser/model/types.go index 5e504a6e80..ee03dd4331 100644 --- a/adapter/internal/oasparser/model/types.go +++ b/adapter/internal/oasparser/model/types.go @@ -152,10 +152,11 @@ type apiData struct { } type choreoComponentInfo struct { - OrganizationID string `json:"organizationId,omitempty"` - ProjectID string `json:"projectId,omitempty"` - ComponentID string `json:"componentId,omitempty"` - VersionID string `json:"versionId,omitempty"` + OrganizationID string `json:"organizationId,omitempty"` + ProjectID string `json:"projectId,omitempty"` + ComponentID string `json:"componentId,omitempty"` + VersionID string `json:"versionId,omitempty"` + IsChoreoOrgPaid bool `json:"isChoreoOrgPaid,omitempty"` } type backendJWTConfiguration struct { diff --git a/adapter/internal/synchronizer/apis_fetcher.go b/adapter/internal/synchronizer/apis_fetcher.go index c79235b59d..095eb9f6aa 100644 --- a/adapter/internal/synchronizer/apis_fetcher.go +++ b/adapter/internal/synchronizer/apis_fetcher.go @@ -113,7 +113,7 @@ func PushAPIProjects(payload []byte, environments []string, xdsOptions common.Xd // Pass the byte slice for the XDS APIs to push it to the enforcer and router // TODO: (renuka) optimize applying API project, update maps one by one and apply xds once var deployedRevisionList []*notifier.DeployedAPIRevision - deployedRevisionList, err = apiServer.ApplyAPIProjectFromAPIM(apiFileData, vhostToEnvsMap, envProps, xdsOptions) + deployedRevisionList, err = apiServer.ApplyAPIProjectFromAPIM(apiFileData, vhostToEnvsMap, envProps, xdsOptions, deployment.ChoreoComponentInfo) if err != nil { logger.LoggerSync.Errorf("Error occurred while applying project %v", err) } else if deployedRevisionList != nil { @@ -123,7 +123,7 @@ func PushAPIProjects(payload []byte, environments []string, xdsOptions common.Xd // TODO: (renuka) notify the revision deployment to the control plane once all chunks are deployed. // This is not fixed as notify the control plane chunk by chunk (even though the chunk is not really applied to the Enforcer and Router) is not a drastic issue. - // This path is only happening when Adapter is restarting and at that time the deployed time is already updated in the control plane. + // This path is only happening when Adapter is restarting and at that time the deployed time is already updated in the control plane. notifier.SendRevisionUpdate(deploymentList) logger.LoggerSync.Infof("Successfully deployed %d API/s", len(deploymentList)) // Error nil for successful execution diff --git a/adapter/pkg/synchronizer/types.go b/adapter/pkg/synchronizer/types.go index 535e200d9a..de946eec6d 100644 --- a/adapter/pkg/synchronizer/types.go +++ b/adapter/pkg/synchronizer/types.go @@ -53,9 +53,10 @@ type APIDeployment struct { APIFile string `json:"apiFile"` Environments []GatewayLabel `json:"environments"` // These properties are used by global Adapter - OrganizationID string `json:"organizationId"` - APIContext string `json:"apiContext"` - Version string `json:"version"` + OrganizationID string `json:"organizationId"` + ChoreoComponentInfo ChoreoComponentInfo `json:"choreoComponentInfo"` + APIContext string `json:"apiContext"` + Version string `json:"version"` } // GatewayLabel represents gateway environment name, vhost and deployedTimeStamp of an API project. @@ -68,6 +69,14 @@ type GatewayLabel struct { DeploymentType string `json:"deploymentType"` } +type ChoreoComponentInfo struct { + OrganizationID string `json:"organizationId"` + ProjectID string `json:"projectId"` + ComponentID string `json:"componentId"` + VersionID string `json:"versionId"` + IsChoreoOrgPaid bool `json:"isChoreoOrgPaid"` // isPaidOrg +} + // APIConfigs represents env properties belongs to the API type APIConfigs struct { ProductionEndpoint string `mapstructure:"productionEndpoint,omitempty"` diff --git a/resources/conf/config.toml.template b/resources/conf/config.toml.template index d9da67afd0..34549687e2 100644 --- a/resources/conf/config.toml.template +++ b/resources/conf/config.toml.template @@ -206,18 +206,18 @@ retainKeys = ["self_validate_jwt", "issuer", "claim_mappings", "consumer_key_cla [[router.upstream.circuitBreakers]] organizations = "*" circuitBreakerName = "BasicCircuitBreaker" -maxConnections = 3 -maxRequests = 3 -maxPendingRequests = 0 -maxConnectionPools = 3 +maxConnections = 1 +maxRequests = 1 +maxPendingRequests = 1 +maxConnectionPools = 1 [[router.upstream.circuitBreakers]] -organizations = "e0682456-2ba6-4c5f-8f36-3c5b6dc46913,4b9afefb-4bcc-4e63-85d3-ddd593841012,d3a7dfea-fb10-4371-b21d-85d1bc28667b" +organizations = "e0682456-2ba6-4c5f-8f36-3c5b6dc46913,4b9afefb-4bcc-4e63-85d3-ddd593841012" circuitBreakerName = "EnhancedCircuitBreaker" -maxConnections = 50 -maxRequests = 50 -maxPendingRequests = 0 -maxConnectionPools = 50 +maxConnections = 25 +maxRequests = 25 +maxPendingRequests = 1 +maxConnectionPools = 2 # Configs relevant to the envoy rate-limit service [router.ratelimit]