diff --git a/adapter/internal/discovery/xds/marshaller.go b/adapter/internal/discovery/xds/marshaller.go index df6841c434..f9b6b15896 100644 --- a/adapter/internal/discovery/xds/marshaller.go +++ b/adapter/internal/discovery/xds/marshaller.go @@ -3,7 +3,6 @@ package xds import ( "encoding/json" "fmt" - "strconv" "github.com/wso2/product-microgateway/adapter/config" logger "github.com/wso2/product-microgateway/adapter/internal/loggers" @@ -14,8 +13,8 @@ import ( ) var ( - // APIListMap has the following mapping label -> apiUUID -> API (Metadata) - APIListMap map[string]map[string]*subscription.APIs + // APIMetadataMap has the following mapping apiUUID -> API (Metadata) + APIMetadataMap map[string]*subscription.APIs // SubscriptionMap contains the subscriptions recieved from API Manager Control Plane SubscriptionMap map[int32]*subscription.Subscription // ApplicationMap contains the applications recieved from API Manager Control Plane @@ -40,8 +39,6 @@ const ( DeleteEvent ) -const blockedStatus string = "BLOCKED" - // MarshalConfig will marshal a Config struct - read from the config toml - to // enfocer's CDS resource representation. func MarshalConfig(config *config.Config) *enforcer.Config { @@ -480,20 +477,15 @@ func MarshalSubscriptionPolicyEventAndReturnList(policy *types.SubscriptionPolic return marshalSubscriptionPolicyMapToList(SubscriptionPolicyMap) } -// MarshalAPIMetataAndReturnList updates the internal APIListMap and returns the XDS compatible APIList. -// apiList is the internal APIList object (For single API, this would contain a List with just one API) +// UpdateAPIMetataMapWithMultipleAPIs updates the internal APIMetadataMap and it needs to be called during the startup. +// The purpose here is to store default versioned APIs and blocked APIs. // initialAPIUUIDListMap is assigned during startup when global adapter is associated. This would be empty otherwise. -// gatewayLabel is the environment. -func MarshalAPIMetataAndReturnList(apiList *types.APIList, initialAPIUUIDListMap map[string]int, gatewayLabel string) *subscription.APIList { +func UpdateAPIMetataMapWithMultipleAPIs(apiList *types.APIList, initialAPIUUIDListMap map[string]int) { - if APIListMap == nil { - APIListMap = make(map[string]map[string]*subscription.APIs) - } - // var resourceMapForLabel map[string]*subscription.APIs - if _, ok := APIListMap[gatewayLabel]; !ok { - APIListMap[gatewayLabel] = make(map[string]*subscription.APIs) + if APIMetadataMap == nil { + APIMetadataMap = make(map[string]*subscription.APIs) } - resourceMapForLabel := APIListMap[gatewayLabel] + for _, api := range apiList.List { // initialAPIUUIDListMap is not null if the adapter is running with global adapter enabled, and it is // the first method invocation. @@ -503,44 +495,44 @@ func MarshalAPIMetataAndReturnList(apiList *types.APIList, initialAPIUUIDListMap } } newAPI := marshalAPIMetadata(&api) - resourceMapForLabel[api.UUID] = newAPI - } - return marshalAPIListMapToList(resourceMapForLabel) -} - -// DeleteAPIAndReturnList removes the API from internal maps and returns the marshalled API List. -// If the apiUUID is not found in the internal map under the provided environment, then it would return a -// nil value. Hence it is required to check if the return value is nil, prior to updating the XDS cache. -func DeleteAPIAndReturnList(apiUUID, organizationUUID string, gatewayLabel string) *subscription.APIList { - if _, ok := APIListMap[gatewayLabel]; !ok { - logger.LoggerXds.Debugf("No API Metadata is available under gateway Environment : %s", gatewayLabel) - return nil + APIMetadataMap[api.UUID] = newAPI } - delete(APIListMap[gatewayLabel], apiUUID) - return marshalAPIListMapToList(APIListMap[gatewayLabel]) } -// MarshalAPIForLifeCycleChangeEventAndReturnList updates the internal map's API instances lifecycle state only if -// stored API Instance's or input status event is a blocked event. -// If no change is applied, it would return nil. Hence the XDS cache should not be updated. -func MarshalAPIForLifeCycleChangeEventAndReturnList(apiUUID, status, gatewayLabel string) *subscription.APIList { - if _, ok := APIListMap[gatewayLabel]; !ok { - logger.LoggerXds.Debugf("No API Metadata is available under gateway Environment : %s", gatewayLabel) - return nil - } - if _, ok := APIListMap[gatewayLabel][apiUUID]; !ok { - logger.LoggerXds.Debugf("No API Metadata for API ID: %s is available under gateway Environment : %s", - apiUUID, gatewayLabel) - return nil - } - storedAPILCState := APIListMap[gatewayLabel][apiUUID].LcState - - // Because the adapter only required to update the XDS if it is related to blocked state. - if !(storedAPILCState == blockedStatus || status == blockedStatus) { - return nil - } - APIListMap[gatewayLabel][apiUUID].LcState = status - return marshalAPIListMapToList(APIListMap[gatewayLabel]) +// UpdateAPIMetataMapWithAPILCEvent updates the internal map's API instances lifecycle state only if +// stored API Instance's or input status event is a blocked event. If the API's state is changed to un-BLOCKED state, +// the record will be removed. +func UpdateAPIMetataMapWithAPILCEvent(apiUUID, status string) { + + apiEntry, apiFound := APIMetadataMap[apiUUID] + if !apiFound { + // IF API is not stored within the metadata Map and the lifecycle state is something else other BLOCKED state, those are discarded. + if status != blockedStatus { + logger.LoggerXds.Debugf("API life cycle state change event is discarded for the API : %s", apiUUID) + return + } + // IF API is not available and state is BLOCKED, needs to create a new instance and store within the Map. + logger.LoggerXds.Debugf("No API Metadata for API ID: %s is available. Hence a new record is added.", apiUUID) + APIMetadataMap[apiUUID] = &subscription.APIs{ + Uuid: apiUUID, + LcState: status, + } + logger.LoggerXds.Infof("API life cycle state change event with state %q is updated for the API : %s", + status, apiUUID) + return + } + // If the API is available in the metadata map it should be either a BLOCKED API and/or default versioned API. + // If the update for existing API entry is not "BLOCKED" then the API can be removed from the list. + // when the API is unavailable in the api metadata list received in the enforcer, it would be treated as + // an unblocked API. + // But if the API is not the default version, those records won't be stored. + if status != blockedStatus && !apiEntry.IsDefaultVersion { + delete(APIMetadataMap, apiUUID) + return + } + APIMetadataMap[apiUUID].LcState = status + logger.LoggerXds.Infof("API life cycle state change event with state %q is updated for the API : %s", + status, apiUUID) } func marshalSubscription(subscriptionInternal *types.Subscription) *subscription.Subscription { @@ -599,13 +591,6 @@ func marshalKeyMapping(keyMappingInternal *types.ApplicationKeyMapping) *subscri func marshalAPIMetadata(api *types.API) *subscription.APIs { return &subscription.APIs{ - ApiId: strconv.Itoa(api.APIID), - Name: api.Name, - Provider: api.Provider, - Version: api.Version, - Context: api.Context, - Policy: api.Policy, - ApiType: api.APIType, Uuid: api.UUID, IsDefaultVersion: api.IsDefaultVersion, LcState: api.APIStatus, @@ -642,14 +627,3 @@ func marshalSubscriptionPolicy(policy *types.SubscriptionPolicy) *subscription.S func GetApplicationKeyMappingReference(keyMapping *types.ApplicationKeyMapping) string { return keyMapping.ConsumerKey + ":" + keyMapping.KeyManager } - -// CheckIfAPIMetadataIsAlreadyAvailable returns true only if the API Metadata for the given API UUID -// is already available -func CheckIfAPIMetadataIsAlreadyAvailable(apiUUID, label string) bool { - if _, labelAvailable := APIListMap[label]; labelAvailable { - if _, apiAvailale := APIListMap[label][apiUUID]; apiAvailale { - return true - } - } - return false -} diff --git a/adapter/internal/discovery/xds/server.go b/adapter/internal/discovery/xds/server.go index 432a174263..dbb58dfa24 100644 --- a/adapter/internal/discovery/xds/server.go +++ b/adapter/internal/discovery/xds/server.go @@ -45,6 +45,7 @@ import ( "github.com/wso2/product-microgateway/adapter/internal/oasparser/model" mgw "github.com/wso2/product-microgateway/adapter/internal/oasparser/model" "github.com/wso2/product-microgateway/adapter/internal/svcdiscovery" + "github.com/wso2/product-microgateway/adapter/pkg/discovery/api/wso2/discovery/api" subscription "github.com/wso2/product-microgateway/adapter/pkg/discovery/api/wso2/discovery/subscription" throttle "github.com/wso2/product-microgateway/adapter/pkg/discovery/api/wso2/discovery/throttle" wso2_cache "github.com/wso2/product-microgateway/adapter/pkg/discovery/protocol/cache/v3" @@ -83,7 +84,7 @@ var ( orgIDOpenAPIRoutesMap map[string]map[string][]*routev3.Route // organizationID -> Vhost:API_UUID -> Envoy Routes map orgIDOpenAPIClustersMap map[string]map[string][]*clusterv3.Cluster // organizationID -> Vhost:API_UUID -> Envoy Clusters map orgIDOpenAPIEndpointsMap map[string]map[string][]*corev3.Address // organizationID -> Vhost:API_UUID -> Envoy Endpoints map - orgIDOpenAPIEnforcerApisMap map[string]map[string]types.Resource // organizationID -> Vhost:API_UUID -> API Resource map + orgIDOpenAPIEnforcerApisMap map[string]map[string]*api.Api // organizationID -> Vhost:API_UUID -> API Resource map orgIDvHostBasepathMap map[string]map[string]string // organizationID -> Vhost:basepath -> Vhost:API_UUID reverseAPINameVersionMap map[string]string @@ -119,6 +120,8 @@ const ( maxRandomInt int = 999999999 prototypedAPI string = "PROTOTYPED" apiKeyFieldSeparator string = ":" + blockedStatus string = "BLOCKED" + nonBlockedStatus string = "CREATED/PUBLISHED" ) // IDHash uses ID field as the node hash. @@ -161,7 +164,7 @@ func init() { orgIDOpenAPIRoutesMap = make(map[string]map[string][]*routev3.Route) // organizationID -> Vhost:API_UUID -> Envoy Routes map orgIDOpenAPIClustersMap = make(map[string]map[string][]*clusterv3.Cluster) // organizationID -> Vhost:API_UUID -> Envoy Clusters map orgIDOpenAPIEndpointsMap = make(map[string]map[string][]*corev3.Address) // organizationID -> Vhost:API_UUID -> Envoy Endpoints map - orgIDOpenAPIEnforcerApisMap = make(map[string]map[string]types.Resource) // organizationID -> Vhost:API_UUID -> API Resource map + orgIDOpenAPIEnforcerApisMap = make(map[string]map[string]*api.Api) // organizationID -> Vhost:API_UUID -> API Resource map orgIDvHostBasepathMap = make(map[string]map[string]string) reverseAPINameVersionMap = make(map[string]string) @@ -334,6 +337,8 @@ func UpdateAPI(vHost string, apiProject mgw.ProjectAPI, environments []string) ( apiYaml.Name, apiYaml.Version, organizationID) return nil, validationErr } + // Update the LifecycleStatus of the API. + updateLCStateOfMgwSwagger(&mgwSwagger) // -------- Finished updating mgwSwagger struct @@ -434,12 +439,10 @@ func UpdateAPI(vHost string, apiProject mgw.ProjectAPI, environments []string) ( } if _, ok := orgIDOpenAPIEnforcerApisMap[organizationID]; ok { - orgIDOpenAPIEnforcerApisMap[organizationID][apiIdentifier] = oasParser.GetEnforcerAPI(mgwSwagger, - apiProject.APILifeCycleStatus, vHost) + orgIDOpenAPIEnforcerApisMap[organizationID][apiIdentifier] = oasParser.GetEnforcerAPI(mgwSwagger, vHost) } else { - enforcerAPIMap := make(map[string]types.Resource) - enforcerAPIMap[apiIdentifier] = oasParser.GetEnforcerAPI(mgwSwagger, apiProject.APILifeCycleStatus, - vHost) + enforcerAPIMap := make(map[string]*api.Api) + enforcerAPIMap[apiIdentifier] = oasParser.GetEnforcerAPI(mgwSwagger, vHost) orgIDOpenAPIEnforcerApisMap[organizationID] = enforcerAPIMap } @@ -447,8 +450,7 @@ func UpdateAPI(vHost string, apiProject mgw.ProjectAPI, environments []string) ( revisionStatus := updateXdsCacheOnAPIAdd(oldLabels, newLabels) if revisionStatus { // send updated revision to control plane - deployedRevision = notifier.UpdateDeployedRevisions(apiYaml.ID, apiYaml.RevisionID, environments, - vHost) + deployedRevision = notifier.UpdateDeployedRevisions(apiYaml.ID, apiYaml.RevisionID, environments, vHost) } if svcdiscovery.IsServiceDiscoveryEnabled { startConsulServiceDiscovery(organizationID) //consul service discovery starting point @@ -456,6 +458,41 @@ func UpdateAPI(vHost string, apiProject mgw.ProjectAPI, environments []string) ( return deployedRevision, nil } +// UpdateAPIInEnforcerForBlockedAPIUpdate updates the state of APIMetadataMap under apiID with the lifecycle state and then +// XDS cache for enforcerAPIs is updated. +func UpdateAPIInEnforcerForBlockedAPIUpdate(apiID, organizationID, state string) { + mutexForInternalMapUpdate.Lock() + defer mutexForInternalMapUpdate.Unlock() + // First needs to update the API Metadata Map + UpdateAPIMetataMapWithAPILCEvent(apiID, state) + var apiReferenceArray []string + // Iterate through the enforcerAPIsMap and update the lifecycle status for the map. This is the map representing + // runtime-artifact for each API + if openAPIEnforcerAPIsMap, orgFound := orgIDOpenAPIEnforcerApisMap[organizationID]; orgFound { + // The reference is vhost:apiUUID. Hence it is required to iterate through all API entries as there could be multiple deployments of the same API + // under different vhosts. + for apiReference, enforcerAPI := range openAPIEnforcerAPIsMap { + if strings.HasSuffix(apiReference, ":"+apiID) && (state == blockedStatus || enforcerAPI.ApiLifeCycleState == blockedStatus) { + logger.LoggerXds.Infof("API Lifecycle status is updated for the API %s to %s state", apiReference, state) + enforcerAPI.ApiLifeCycleState = state + apiReferenceArray = append(apiReferenceArray, apiReference) + } + } + } else { + logger.LoggerXds.Infof("API Life Cycle event is not applied due to irrelevant tenant domain : %s.", organizationID) + return + } + + // For all the gateway labels containing the API, the enforcer XDS cache needs to be updated. + if openAPIEnvoyLabelMap, ok := orgIDOpenAPIEnvoyMap[organizationID]; ok { + for _, apiReference := range apiReferenceArray { + if labels, labelsFound := openAPIEnvoyLabelMap[apiReference]; labelsFound { + updateXdsCacheForEnforcerAPIsOnly(labels) + } + } + } +} + // GetAllEnvironments returns all the environments merging new environments with already deployed environments // of the given vhost of the API func GetAllEnvironments(apiUUID, vhost string, newEnvironments []string) []string { @@ -782,6 +819,12 @@ func updateXdsCacheOnAPIAdd(oldLabels []string, newLabels []string) bool { return revisionStatus } +func updateXdsCacheForEnforcerAPIsOnly(labels []string) { + for _, label := range labels { + UpdateEnforcerApis(label, generateEnforcerAPIsForLabel(label), "") + } +} + // GenerateEnvoyResoucesForLabel generates envoy resources for a given label // This method will list out all APIs mapped to the label. and generate envoy resources for all of these APIs. func GenerateEnvoyResoucesForLabel(label string) ([]types.Resource, []types.Resource, []types.Resource, @@ -850,6 +893,24 @@ func GenerateEnvoyResoucesForLabel(label string) ([]types.Resource, []types.Reso return endpoints, clusters, listeners, routeConfigs, apis } +// generateEnforcerAPIsForLabel generates ebforcerAPIs resource array for a given label. +// This is used when the envoy resources are not required to have changes but the enforcer APIs are required to (Blocked State APIs) +func generateEnforcerAPIsForLabel(label string) []types.Resource { + var apis []types.Resource + + for organizationID, entityMap := range orgIDOpenAPIEnvoyMap { + for apiKey, labels := range entityMap { + if arrayContains(labels, label) { + enforcerAPI, ok := orgIDOpenAPIEnforcerApisMap[organizationID][apiKey] + if ok { + apis = append(apis, enforcerAPI) + } + } + } + } + return apis +} + // GenerateGlobalClusters generates the globally available clusters and endpoints. func GenerateGlobalClusters(label string) { clusters, endpoints := oasParser.GetGlobalClusters() @@ -1239,3 +1300,13 @@ func UpdateEnforcerThrottleData(throttleData *throttle.ThrottleData) { enforcerThrottleData = t logger.LoggerXds.Infof("New Throttle Data cache update for the label: " + label + " version: " + fmt.Sprint(version)) } + +func updateLCStateOfMgwSwagger(mgwSwagger *model.MgwSwagger) { + // If there are any metadata stored under the APIMetadataMap and Life Cycle state is blocked, update the mgwSwagger + apiEntry, apiFound := APIMetadataMap[mgwSwagger.GetID()] + if apiFound && apiEntry.LcState == blockedStatus { + mgwSwagger.LifeCycleState = blockedStatus + return + } + mgwSwagger.LifeCycleState = nonBlockedStatus +} diff --git a/adapter/internal/eventhub/subscription.go b/adapter/internal/eventhub/subscription.go index 6811a9627a..86e517befc 100644 --- a/adapter/internal/eventhub/subscription.go +++ b/adapter/internal/eventhub/subscription.go @@ -48,6 +48,8 @@ const ( VersionParam string = "version" // GatewayLabelParam is trequired to call /apis endpoint GatewayLabelParam string = "gatewayLabel" + // ExpandParam is a specific query parameter to pull blocked APIs and default apis (for that the value should be false). + ExpandParam string = "expand" // APIUUIDParam is required to call /apis endpoint APIUUIDParam string = "apiId" // ApisEndpoint is the resource path of /apis endpoint @@ -146,49 +148,45 @@ func LoadSubscriptionData(configFile *config.Config, initialAPIUUIDListMap map[s } } - // TODO: (VirajSalaka) Calling /apis endpoint is temporarily removed. - // Take the configured labels from the adapter - // configuredEnvs := conf.ControlPlane.EnvironmentLabels + configuredEnvs := conf.ControlPlane.EnvironmentLabels // If no environments are configured, default gateway label value is assigned. - // if len(configuredEnvs) == 0 { - // configuredEnvs = append(configuredEnvs, config.DefaultGatewayName) - // } - // for _, configuredEnv := range configuredEnvs { - // queryParamMap := make(map[string]string, 1) - // queryParamMap[GatewayLabelParam] = configuredEnv - // go InvokeService(ApisEndpoint, apiList, queryParamMap, APIListChannel, 0) - // for { - // data := <-APIListChannel - // logger.LoggerSync.Debug("Receiving API information for an environment") - // if data.Payload != nil { - // logger.LoggerSync.Info("Payload data with API information recieved") - // retrieveAPIList(data, initialAPIUUIDListMap) - // break - // } else if data.ErrorCode >= 400 && data.ErrorCode < 500 { - // logger.LoggerSync.Errorf("Error occurred when retrieving Subscription information from the control plane: %v", data.Error) - // health.SetControlPlaneRestAPIStatus(false) - // } else { - // // Keep the iteration going on until a response is recieved. - // logger.LoggerSync.Errorf("Error occurred while fetching data from control plane: %v", data.Error) - // go func(d response) { - // // Retry fetching from control plane after a configured time interval - // if conf.ControlPlane.RetryInterval == 0 { - // // Assign default retry interval - // conf.ControlPlane.RetryInterval = 5 - // } - // logger.LoggerSync.Debugf("Time Duration for retrying: %v", conf.ControlPlane.RetryInterval*time.Second) - // time.Sleep(conf.ControlPlane.RetryInterval * time.Second) - // logger.LoggerSync.Infof("Retrying to fetch APIs from control plane. Time Duration for the next retry: %v", conf.ControlPlane.RetryInterval*time.Second) - // go InvokeService(ApisEndpoint, apiList, queryParamMap, APIListChannel, 0) - // }(data) - // } - // } - // } - // TODO: (VirajSalaka) APIList (/apis response) processing is temporarily blocked. - // // InitialAPIUUIDList is already processed (if available). Then onwards, that list is not required. - // go retrieveAPIListFromChannel(APIListChannel, nil) + if len(configuredEnvs) == 0 { + configuredEnvs = append(configuredEnvs, config.DefaultGatewayName) + } + for _, configuredEnv := range configuredEnvs { + queryParamMap := make(map[string]string, 1) + queryParamMap[GatewayLabelParam] = configuredEnv + queryParamMap[ExpandParam] = "false" + go InvokeService(ApisEndpoint, apiList, queryParamMap, APIListChannel, 0) + for { + data := <-APIListChannel + logger.LoggerSync.Debug("Receiving API information for an environment") + if data.Payload != nil { + logger.LoggerSync.Info("Payload data with API information recieved") + retrieveAPIList(data, initialAPIUUIDListMap) + break + } else if data.ErrorCode >= 400 && data.ErrorCode < 500 { + logger.LoggerSync.Errorf("Error occurred when retrieving Subscription information from the control plane: %v", data.Error) + health.SetControlPlaneRestAPIStatus(false) + } else { + // Keep the iteration going on until a response is recieved. + logger.LoggerSync.Errorf("Error occurred while fetching data from control plane: %v", data.Error) + go func(d response) { + // Retry fetching from control plane after a configured time interval + if conf.ControlPlane.RetryInterval == 0 { + // Assign default retry interval + conf.ControlPlane.RetryInterval = 5 + } + logger.LoggerSync.Debugf("Time Duration for retrying: %v", conf.ControlPlane.RetryInterval*time.Second) + time.Sleep(conf.ControlPlane.RetryInterval * time.Second) + logger.LoggerSync.Infof("Retrying to fetch APIs from control plane. Time Duration for the next retry: %v", conf.ControlPlane.RetryInterval*time.Second) + InvokeService(ApisEndpoint, apiList, queryParamMap, APIListChannel, 0) + }(data) + } + } + } } // InvokeService invokes the internal data resource @@ -279,9 +277,7 @@ func retrieveAPIList(response response, initialAPIUUIDListMap map[string]int) { logger.LoggerSubscription.Debugf("Received API List information for API : %s", api.UUID) } } - - xds.UpdateEnforcerAPIList(response.GatewayLabel, - xds.MarshalAPIMetataAndReturnList(apiListResponse, initialAPIUUIDListMap, response.GatewayLabel)) + xds.UpdateAPIMetataMapWithMultipleAPIs(apiListResponse, initialAPIUUIDListMap) default: logger.LoggerSubscription.Warnf("APIList Type DTO is not recieved. Unknown type %T", t) } diff --git a/adapter/internal/ga/api_event_listener.go b/adapter/internal/ga/api_event_listener.go index 2759fb8afd..f4e42eda77 100644 --- a/adapter/internal/ga/api_event_listener.go +++ b/adapter/internal/ga/api_event_listener.go @@ -35,29 +35,9 @@ func handleAPIEventsFromGA(channel chan APIEvent) { } if !event.IsDeployEvent { xds.DeleteAPIWithAPIMEvent(event.APIUUID, event.OrganizationUUID, configuredEnvs, event.RevisionUUID) - // TODO: (VirajSalaka) Temporarily removed. - // for _, env := range configuredEnvs { - // xds.DeleteAPIAndReturnList(event.APIUUID, event.OrganizationUUID, env) - // } continue } go synchronizer.FetchAPIsFromControlPlane(event.APIUUID, configuredEnvs) - - // TODO: (VirajSalaka) temporarily removed. - // for _, env := range configuredEnvs { - // if xds.CheckIfAPIMetadataIsAlreadyAvailable(event.APIUUID, env) { - // logger.LoggerGA.Debugf("APIList for API UUID: %s is not updated as it already "+ - // "exists", event.APIUUID) - // continue - // } - // queryParamMap := make(map[string]string, 2) - // queryParamMap[eh.GatewayLabelParam] = env - // queryParamMap[eh.APIUUIDParam] = event.APIUUID - // logger.LoggerGA.Infof("Invoking the apis service endpoint") - // var apiList *types.APIList - // go eh.InvokeService(eh.ApisEndpoint, apiList, queryParamMap, - // eh.APIListChannel, 0) - // } } } diff --git a/adapter/internal/messaging/notification_listener.go b/adapter/internal/messaging/notification_listener.go index a874b502a1..a98411bd76 100644 --- a/adapter/internal/messaging/notification_listener.go +++ b/adapter/internal/messaging/notification_listener.go @@ -171,42 +171,13 @@ func handleAPIEvents(data []byte, eventType string) { // to delete. Hence we could simply delete after checking against just one iteration. if strings.EqualFold(removeAPIFromGateway, apiEvent.Event.Type) { xds.DeleteAPIWithAPIMEvent(apiEvent.UUID, apiEvent.TenantDomain, apiEvent.GatewayLabels, "") - // TODO: (VirajSalaka) Temporarily Removed. - // for _, env := range apiEvent.GatewayLabels { - // xdsAPIList := xds.DeleteAPIAndReturnList(apiEvent.UUID, apiEvent.TenantDomain, env) - // if xdsAPIList != nil { - // xds.UpdateEnforcerAPIList(env, xdsAPIList) - // } - // } return } - // TODO: (VirajSalaka) Temporarily removed. - // if strings.EqualFold(deployAPIToGateway, apiEvent.Event.Type) { - // conf, _ := config.ReadConfigs() - // configuredEnvs := conf.ControlPlane.EnvironmentLabels - // if len(configuredEnvs) == 0 { - // configuredEnvs = append(configuredEnvs, config.DefaultGatewayName) - // } - // for _, configuredEnv := range configuredEnvs { - // if configuredEnv == env { - // if xds.CheckIfAPIMetadataIsAlreadyAvailable(apiEvent.UUID, env) { - // logger.LoggerInternalMsg.Debugf("API Metadata for api Id: %s is not updated as it already exists", apiEvent.UUID) - // continue - // } - // queryParamMap := make(map[string]string, 3) - // queryParamMap[eh.GatewayLabelParam] = configuredEnv - // queryParamMap[eh.ContextParam] = apiEvent.Context - // queryParamMap[eh.VersionParam] = apiEvent.Version - // var apiList *types.APIList - // go eh.InvokeService(eh.ApisEndpoint, apiList, queryParamMap, - // eh.APIListChannel, 0) - // } - // } - // } } } func handleLifeCycleEvents(data []byte) { + // TODO: (VirajSalaka) IsLaterEvent var apiEvent msg.APIEvent apiLCEventErr := json.Unmarshal([]byte(string(data)), &apiEvent) if apiLCEventErr != nil { @@ -218,20 +189,8 @@ func handleLifeCycleEvents(data []byte) { apiEvent.APIName, apiEvent.APIVersion, apiEvent.TenantDomain) return } - // conf, _ := config.ReadConfigs() - // configuredEnvs := conf.ControlPlane.EnvironmentLabels - logger.LoggerInternalMsg.Debugf("%s : %s API life cycle state change event is discarded", apiEvent.APIName, apiEvent.APIVersion) - - // TODO: (VirajSalaka) Temporarily removed as API Blocked LC state change is ignored atm. - // if len(configuredEnvs) == 0 { - // configuredEnvs = append(configuredEnvs, config.DefaultGatewayName) - // } - // for _, configuredEnv := range configuredEnvs { - // xdsAPIList := xds.MarshalAPIForLifeCycleChangeEventAndReturnList(apiEvent.UUID, apiEvent.APIStatus, configuredEnv) - // if xdsAPIList != nil { - // xds.UpdateEnforcerAPIList(configuredEnv, xdsAPIList) - // } - // } + // TODO: (VirajSalaka) Unnecessary Tenants' API Metadata are also stored. + xds.UpdateAPIInEnforcerForBlockedAPIUpdate(apiEvent.UUID, apiEvent.TenantDomain, apiEvent.APIStatus) } // handleApplicationEvents to process application related events diff --git a/adapter/internal/oasparser/config_generator.go b/adapter/internal/oasparser/config_generator.go index be6d176209..a633740ba6 100644 --- a/adapter/internal/oasparser/config_generator.go +++ b/adapter/internal/oasparser/config_generator.go @@ -116,7 +116,7 @@ func UpdateRoutesConfig(routeConfig *routev3.RouteConfiguration, vhostToRouteArr // GetEnforcerAPI retrieves the ApiDS object model for a given swagger definition // along with the vhost to deploy the API. -func GetEnforcerAPI(mgwSwagger model.MgwSwagger, lifeCycleState string, vhost string) *api.Api { +func GetEnforcerAPI(mgwSwagger model.MgwSwagger, vhost string) *api.Api { resources := []*api.Resource{} securitySchemes := []*api.SecurityScheme{} securityList := []*api.SecurityList{} @@ -196,7 +196,7 @@ func GetEnforcerAPI(mgwSwagger model.MgwSwagger, lifeCycleState string, vhost st ProductionEndpoints: generateRPCEndpointCluster(mgwSwagger.GetProdEndpoints()), SandboxEndpoints: generateRPCEndpointCluster(mgwSwagger.GetSandEndpoints()), Resources: resources, - ApiLifeCycleState: lifeCycleState, + ApiLifeCycleState: mgwSwagger.LifeCycleState, Tier: mgwSwagger.GetXWso2ThrottlingTier(), SecurityScheme: securitySchemes, Security: securityList, diff --git a/adapter/internal/oasparser/model/mgw_swagger.go b/adapter/internal/oasparser/model/mgw_swagger.go index ae0fc36367..4ac5aba73e 100644 --- a/adapter/internal/oasparser/model/mgw_swagger.go +++ b/adapter/internal/oasparser/model/mgw_swagger.go @@ -63,7 +63,8 @@ type MgwSwagger struct { OrganizationID string IsProtoTyped bool // APIProvider is required for analytics purposes as /apis call is avoided temporarily. - APIProvider string + APIProvider string + LifeCycleState string } // EndpointCluster represent an upstream cluster diff --git a/adapter/pkg/eventhub/types/types.go b/adapter/pkg/eventhub/types/types.go index eddc4317a3..47c97bbbb0 100644 --- a/adapter/pkg/eventhub/types/types.go +++ b/adapter/pkg/eventhub/types/types.go @@ -76,18 +76,9 @@ type ApplicationKeyMappingList struct { // API for struct Api type API struct { - APIID int `json:"apiId"` UUID string `json:"uuid"` - Provider string `json:"provider" json:"apiProvider"` - Name string `json:"name" json:"apiName"` - Version string `json:"version" json:"apiVersion"` - Context string `json:"context" json:"apiContext"` - Policy string `json:"policy"` - APIType string `json:"apiType"` IsDefaultVersion bool `json:"isDefaultVersion"` APIStatus string `json:"status"` - TenantID int32 `json:"tenanId,omitempty"` - TenantDomain string `json:"tenanDomain,omitempty"` TimeStamp int64 `json:"timeStamp,omitempty"` } diff --git a/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/admin/AdminUtils.java b/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/admin/AdminUtils.java index dd127257d9..d861d4fc14 100644 --- a/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/admin/AdminUtils.java +++ b/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/admin/AdminUtils.java @@ -20,11 +20,8 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import io.grpc.netty.shaded.io.netty.handler.codec.http.HttpResponseStatus; -import org.wso2.choreo.connect.enforcer.models.API; -import org.wso2.choreo.connect.enforcer.models.APIInfo; +import org.wso2.choreo.connect.enforcer.api.API; import org.wso2.choreo.connect.enforcer.models.Application; -import org.wso2.choreo.connect.enforcer.models.ApplicationInfo; -import org.wso2.choreo.connect.enforcer.models.ApplicationInfoList; import org.wso2.choreo.connect.enforcer.models.ApplicationKeyMapping; import org.wso2.choreo.connect.enforcer.models.ApplicationPolicy; import org.wso2.choreo.connect.enforcer.models.ApplicationPolicyList; @@ -32,10 +29,14 @@ import org.wso2.choreo.connect.enforcer.models.RevokedToken; import org.wso2.choreo.connect.enforcer.models.RevokedTokenList; import org.wso2.choreo.connect.enforcer.models.Subscription; -import org.wso2.choreo.connect.enforcer.models.SubscriptionInfo; import org.wso2.choreo.connect.enforcer.models.SubscriptionList; import org.wso2.choreo.connect.enforcer.models.SubscriptionPolicy; import org.wso2.choreo.connect.enforcer.models.SubscriptionPolicyList; +import org.wso2.choreo.connect.enforcer.models.admin.APIInfo; +import org.wso2.choreo.connect.enforcer.models.admin.ApplicationInfo; +import org.wso2.choreo.connect.enforcer.models.admin.ApplicationInfoList; +import org.wso2.choreo.connect.enforcer.models.admin.BasicAPIInfo; +import org.wso2.choreo.connect.enforcer.models.admin.SubscriptionInfo; import java.util.List; @@ -47,14 +48,28 @@ public class AdminUtils { public static APIInfo toAPIInfo(API api, List subscriptionInfoList) { APIInfo apiInfo = new APIInfo(); apiInfo.setSubscriptions(subscriptionInfoList); - apiInfo.setApiId(api.getApiId()); - apiInfo.setApiUUID(api.getApiUUID()); - apiInfo.setContext(api.getContext()); - apiInfo.setName(api.getApiName()); - apiInfo.setLcState(api.getLcState()); - apiInfo.setTier(api.getApiTier()); - apiInfo.setVersion(api.getApiVersion()); - apiInfo.setProvider(api.getApiProvider()); + apiInfo.setApiUUID(api.getAPIConfig().getUuid()); + apiInfo.setContext(api.getAPIConfig().getBasePath()); + apiInfo.setName(api.getAPIConfig().getName()); + apiInfo.setLcState(api.getAPIConfig().getApiLifeCycleState()); + apiInfo.setTier(api.getAPIConfig().getTier()); + apiInfo.setVersion(api.getAPIConfig().getVersion()); + apiInfo.setProvider(api.getAPIConfig().getApiProvider()); + apiInfo.setApiType(api.getAPIConfig().getApiType()); + return apiInfo; + } + + public static BasicAPIInfo toBasicAPIInfo(API api, boolean isDefaultVersion) { + BasicAPIInfo apiInfo = new BasicAPIInfo(); + apiInfo.setApiUUID(api.getAPIConfig().getUuid()); + apiInfo.setContext(api.getAPIConfig().getBasePath()); + apiInfo.setName(api.getAPIConfig().getName()); + apiInfo.setLcState(api.getAPIConfig().getApiLifeCycleState()); + apiInfo.setDefaultVersion(isDefaultVersion); + apiInfo.setApiType(api.getAPIConfig().getApiType()); + apiInfo.setVersion(api.getAPIConfig().getVersion()); + apiInfo.setProvider(api.getAPIConfig().getApiProvider()); + apiInfo.setPolicy(api.getAPIConfig().getTier()); return apiInfo; } diff --git a/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/admin/handlers/APIRequestHandler.java b/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/admin/handlers/APIRequestHandler.java index 66a09e9532..8a23616c7d 100644 --- a/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/admin/handlers/APIRequestHandler.java +++ b/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/admin/handlers/APIRequestHandler.java @@ -20,16 +20,18 @@ import com.fasterxml.jackson.core.JsonProcessingException; import io.grpc.netty.shaded.io.netty.handler.codec.http.HttpResponseStatus; import org.wso2.choreo.connect.enforcer.admin.AdminUtils; +import org.wso2.choreo.connect.enforcer.api.API; +import org.wso2.choreo.connect.enforcer.api.APIFactory; import org.wso2.choreo.connect.enforcer.constants.AdminConstants; -import org.wso2.choreo.connect.enforcer.models.API; -import org.wso2.choreo.connect.enforcer.models.APIInfo; -import org.wso2.choreo.connect.enforcer.models.APIList; import org.wso2.choreo.connect.enforcer.models.Application; -import org.wso2.choreo.connect.enforcer.models.ApplicationInfo; import org.wso2.choreo.connect.enforcer.models.ApplicationKeyMapping; import org.wso2.choreo.connect.enforcer.models.ResponsePayload; import org.wso2.choreo.connect.enforcer.models.Subscription; -import org.wso2.choreo.connect.enforcer.models.SubscriptionInfo; +import org.wso2.choreo.connect.enforcer.models.admin.APIInfo; +import org.wso2.choreo.connect.enforcer.models.admin.APIList; +import org.wso2.choreo.connect.enforcer.models.admin.ApplicationInfo; +import org.wso2.choreo.connect.enforcer.models.admin.BasicAPIInfo; +import org.wso2.choreo.connect.enforcer.models.admin.SubscriptionInfo; import java.util.ArrayList; import java.util.List; @@ -44,9 +46,8 @@ public ResponsePayload handleRequest(String[] params, String requestType) throws if (AdminConstants.API_TYPE.equals(requestType)) { return getAPIs(params); - } else { - return getAPIInfo(params); } + return getAPIInfo(params); } /** @@ -54,7 +55,7 @@ public ResponsePayload handleRequest(String[] params, String requestType) throws * * @param params Array of parameters * @return ResponsePayload with APIs as APIList object. - * */ + */ private ResponsePayload getAPIs(String[] params) throws JsonProcessingException { List apis; String name = null; @@ -82,10 +83,15 @@ private ResponsePayload getAPIs(String[] params) throws JsonProcessingException } } } - apis = super.dataStore.getMatchingAPIs(name, context, version, uuid); + apis = APIFactory.getInstance().getMatchingAPIs(name, context, version, uuid); APIList apiList = new APIList(); apiList.setCount(apis.size()); - apiList.setList(apis); + List modelAPIs = new ArrayList<>(apis.size()); + for (API api : apis) { + // TODO: (VirajSalaka) fix + modelAPIs.add(AdminUtils.toBasicAPIInfo(api, false)); + } + apiList.setList(modelAPIs); return AdminUtils.buildResponsePayload(apiList, HttpResponseStatus.OK, false); } @@ -96,7 +102,7 @@ private ResponsePayload getAPIs(String[] params) throws JsonProcessingException * * @param params API Context and API version * @return APIInfo in as a ResponsePayload object. - * @throws JsonProcessingException + * @throws JsonProcessingException If the object cannot be converted into a JSON */ private ResponsePayload getAPIInfo(String[] params) throws JsonProcessingException { APIInfo apiInfo; @@ -117,10 +123,12 @@ private ResponsePayload getAPIInfo(String[] params) throws JsonProcessingExcepti version = param.split("=")[1]; } } - API matchingAPI = super.dataStore.getMatchingAPI(context, version); - if (matchingAPI != null) { + List apis = APIFactory.getInstance().getMatchingAPIs(null, context, version, null); + String apiUUID; + if (apis.size() > 0) { + apiUUID = apis.get(0).getAPIConfig().getUuid(); List matchingSubscriptions = dataStore. - getMatchingSubscriptions(null, matchingAPI.getApiUUID(), null); + getMatchingSubscriptions(null, apiUUID, null); List subscriptionInfoList = new ArrayList<>(); // For each subscription, build the Subscription info with application and key mapping. for (Subscription subscription : matchingSubscriptions) { @@ -138,7 +146,8 @@ private ResponsePayload getAPIInfo(String[] params) throws JsonProcessingExcepti SubscriptionInfo subscriptionInfo = AdminUtils.toSubscriptionInfo(subscription, applicationInfo); subscriptionInfoList.add(subscriptionInfo); } - apiInfo = AdminUtils.toAPIInfo(matchingAPI, subscriptionInfoList); + + apiInfo = AdminUtils.toAPIInfo(apis.get(0), subscriptionInfoList); return AdminUtils.buildResponsePayload(apiInfo, HttpResponseStatus.OK, false); } else { // No api found for the provided search parameters... diff --git a/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/admin/handlers/ApplicationRequestHandler.java b/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/admin/handlers/ApplicationRequestHandler.java index 88e7502b46..87e38ac308 100644 --- a/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/admin/handlers/ApplicationRequestHandler.java +++ b/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/admin/handlers/ApplicationRequestHandler.java @@ -22,10 +22,10 @@ import org.wso2.choreo.connect.enforcer.admin.AdminUtils; import org.wso2.choreo.connect.enforcer.constants.AdminConstants; import org.wso2.choreo.connect.enforcer.models.Application; -import org.wso2.choreo.connect.enforcer.models.ApplicationInfo; -import org.wso2.choreo.connect.enforcer.models.ApplicationInfoList; import org.wso2.choreo.connect.enforcer.models.ApplicationKeyMapping; import org.wso2.choreo.connect.enforcer.models.ResponsePayload; +import org.wso2.choreo.connect.enforcer.models.admin.ApplicationInfo; +import org.wso2.choreo.connect.enforcer.models.admin.ApplicationInfoList; import java.util.ArrayList; import java.util.List; diff --git a/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/api/APIFactory.java b/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/api/APIFactory.java index b762eba204..91dc0bfd97 100644 --- a/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/api/APIFactory.java +++ b/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/api/APIFactory.java @@ -18,6 +18,7 @@ package org.wso2.choreo.connect.enforcer.api; import io.envoyproxy.envoy.service.auth.v3.CheckRequest; +import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.wso2.choreo.connect.discovery.api.Api; @@ -27,6 +28,7 @@ import org.wso2.choreo.connect.enforcer.constants.APIConstants; import org.wso2.choreo.connect.enforcer.discovery.ApiDiscoveryClient; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -143,4 +145,30 @@ private String getApiKey(API api) { private String getApiKey(String vhost, String basePath, String version) { return String.format("%s:%s:%s", vhost, basePath, version); } + + public List getMatchingAPIs (String name, String context, String version, String uuid) { + List apiList = new ArrayList<>(); + for (API api : apis.values()) { + boolean isNameMatching = true; + boolean isContextMatching = true; + boolean isVersionMatching = true; + boolean isUUIDMatching = true; + if (StringUtils.isNotEmpty(name)) { + isNameMatching = api.getAPIConfig().getName().contains(name); + } + if (StringUtils.isNotEmpty(context)) { + isContextMatching = api.getAPIConfig().getBasePath().equals(context); + } + if (StringUtils.isNotEmpty(version)) { + isVersionMatching = api.getAPIConfig().getVersion().equals(version); + } + if (StringUtils.isNotEmpty(uuid)) { + isUUIDMatching = api.getAPIConfig().getUuid().equals(uuid); + } + if (isNameMatching && isContextMatching && isVersionMatching && isUUIDMatching) { + apiList.add(api); + } + } + return apiList; + } } diff --git a/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/models/API.java b/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/models/API.java index 2c6a098e7d..cad7b0e937 100644 --- a/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/models/API.java +++ b/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/models/API.java @@ -20,117 +20,20 @@ import org.wso2.choreo.connect.enforcer.common.CacheableEntity; -import java.util.ArrayList; -import java.util.List; - /** * Entity for keeping API related information. */ public class API implements CacheableEntity { - private Integer apiId = null; - private String provider = null; - private String name = null; - private String version = null; - private String context = null; - private String policy = null; - private String apiType = null; private boolean isDefaultVersion = false; private String apiUUID = null; private String lcState = null; - private List urlMappings = new ArrayList<>(); - - - public void addResource(URLMapping resource) { - - urlMappings.add(resource); - } - - public List getResources() { - - return urlMappings; - } - - public void removeResource(URLMapping resource) { - urlMappings.remove(resource); - } - - public String getContext() { - - return context; - } - - public void setContext(String context) { - - this.context = context; - } - - public String getApiTier() { - - return policy; - } - - public void setApiTier(String apiTier) { - - this.policy = apiTier; - } - - public int getApiId() { - - return apiId; - } - - public void setApiId(int apiId) { - - this.apiId = apiId; - } - - public String getApiProvider() { - - return provider; - } - - public void setApiProvider(String apiProvider) { - - this.provider = apiProvider; - } - - public String getApiName() { - - return name; - } - - public void setApiName(String apiName) { - - this.name = apiName; - } - - public String getApiVersion() { - - return version; - } - - public void setApiVersion(String apiVersion) { - - this.version = apiVersion; - } - public String getCacheKey() { return apiUUID; } - public String getApiType() { - - return apiType; - } - - public void setApiType(String apiType) { - - this.apiType = apiType; - } - public String getLcState() { return lcState; } @@ -139,12 +42,12 @@ public void setLcState(String lcState) { this.lcState = lcState; } - @Override - public String toString() { - return "API [apiId=" + apiId + ", provider=" + provider + ", name=" + name + ", version=" + version - + ", context=" + context + ", policy=" + policy + ", apiType=" + apiType + ", urlMappings=" - + urlMappings + "]"; - } + // TODO: (VirajSalaka) +// @Override +// public String toString() { +// return "API [apiId=" + apiId + ", provider=" + provider + ", name=" + name + ", version=" + version +// + ", context=" + context + ", policy=" + policy + ", apiType=" + apiType + "]"; +// } public boolean isDefaultVersion() { return isDefaultVersion; diff --git a/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/models/URLMapping.java b/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/models/URLMapping.java deleted file mode 100644 index 3736110e0d..0000000000 --- a/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/models/URLMapping.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (c) 2020, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. 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.choreo.connect.enforcer.models; - -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; - -/** - * Holds details about url mapping of API resources. - */ -public class URLMapping { - - private String throttlingPolicy; - private String authScheme; - private String httpMethod; - private String urlPattern; - private List scopes = new ArrayList<>(); - - - public String getHttpMethod() { - - return httpMethod; - } - - public void setHttpMethod(String httpMethod) { - - this.httpMethod = httpMethod; - } - - public String getThrottlingPolicy() { - - return throttlingPolicy; - } - - public void setThrottlingPolicy(String throttlingPolicy) { - - this.throttlingPolicy = throttlingPolicy; - } - - public String getAuthScheme() { - - return authScheme; - } - - public void setAuthScheme(String authScheme) { - - this.authScheme = authScheme; - } - - public String getUrlPattern() { - - return urlPattern; - } - - public void setUrlPattern(String urlPattern) { - - this.urlPattern = urlPattern; - } - - public void addScope(String scope) { - scopes.add(scope); - } - - public List getScopes() { - return scopes; - } - - @Override - public boolean equals(Object o) { - - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - URLMapping that = (URLMapping) o; - return Objects.equals(throttlingPolicy, that.throttlingPolicy) && - Objects.equals(authScheme, that.authScheme) && - Objects.equals(httpMethod, that.httpMethod) && - Objects.equals(urlPattern, that.urlPattern); - } - - @Override - public int hashCode() { - - return Objects.hash(throttlingPolicy, authScheme, httpMethod, urlPattern); - } - - @Override - public String toString() { - - return "URLMapping {" + - ", throttlingPolicy ='" + throttlingPolicy + '\'' + - ", authScheme ='" + authScheme + '\'' + - ", httpMethod ='" + httpMethod + '\'' + - ", urlPattern ='" + urlPattern + '\'' + - '}'; - } -} diff --git a/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/models/APIInfo.java b/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/models/admin/APIInfo.java similarity index 92% rename from enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/models/APIInfo.java rename to enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/models/admin/APIInfo.java index 7824b15e43..c92de2ce7e 100644 --- a/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/models/APIInfo.java +++ b/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/models/admin/APIInfo.java @@ -15,7 +15,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.wso2.choreo.connect.enforcer.models; +package org.wso2.choreo.connect.enforcer.models.admin; import java.util.List; @@ -23,7 +23,6 @@ * Model class for API Information */ public class APIInfo { - private Integer apiId = null; private String provider = null; private String name = null; private String version = null; @@ -35,14 +34,6 @@ public class APIInfo { private String lcState = null; private List subscriptions = null; - public Integer getApiId() { - return apiId; - } - - public void setApiId(Integer apiId) { - this.apiId = apiId; - } - public String getProvider() { return provider; } diff --git a/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/models/APIList.java b/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/models/admin/APIList.java similarity index 83% rename from enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/models/APIList.java rename to enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/models/admin/APIList.java index 368474ab28..8f930b80e8 100644 --- a/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/models/APIList.java +++ b/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/models/admin/APIList.java @@ -16,7 +16,7 @@ * under the License. */ -package org.wso2.choreo.connect.enforcer.models; +package org.wso2.choreo.connect.enforcer.models.admin; import java.util.ArrayList; import java.util.List; @@ -27,7 +27,7 @@ public class APIList { private Integer count = null; - private List list = new ArrayList<>(); + private List list = new ArrayList<>(); public Integer getCount() { @@ -39,12 +39,12 @@ public void setCount(Integer count) { this.count = count; } - public List getList() { + public List getList() { return list; } - public void setList(List list) { + public void setList(List list) { this.list = list; } diff --git a/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/models/ApplicationInfo.java b/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/models/admin/ApplicationInfo.java similarity index 97% rename from enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/models/ApplicationInfo.java rename to enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/models/admin/ApplicationInfo.java index 4178d2e0eb..40ef3e4b2e 100644 --- a/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/models/ApplicationInfo.java +++ b/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/models/admin/ApplicationInfo.java @@ -15,7 +15,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.wso2.choreo.connect.enforcer.models; +package org.wso2.choreo.connect.enforcer.models.admin; import java.util.ArrayList; import java.util.List; diff --git a/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/models/ApplicationInfoList.java b/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/models/admin/ApplicationInfoList.java similarity index 95% rename from enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/models/ApplicationInfoList.java rename to enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/models/admin/ApplicationInfoList.java index 380ff69f44..f45a07d767 100644 --- a/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/models/ApplicationInfoList.java +++ b/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/models/admin/ApplicationInfoList.java @@ -15,7 +15,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.wso2.choreo.connect.enforcer.models; +package org.wso2.choreo.connect.enforcer.models.admin; import java.util.ArrayList; import java.util.List; diff --git a/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/models/admin/BasicAPIInfo.java b/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/models/admin/BasicAPIInfo.java new file mode 100644 index 0000000000..1f8834d145 --- /dev/null +++ b/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/models/admin/BasicAPIInfo.java @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. 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.choreo.connect.enforcer.models.admin; + +/** + * Entity for representing API related information for Admin REST API within enforcer. + */ +public class BasicAPIInfo { + + private String provider = null; + private String name = null; + private String version = null; + private String context = null; + private String policy = null; + private String apiType = null; + private boolean isDefaultVersion = false; + private String apiUUID = null; + private String lcState = null; + + public String getProvider() { + return provider; + } + + public void setProvider(String provider) { + this.provider = provider; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public String getContext() { + return context; + } + + public void setContext(String context) { + this.context = context; + } + + public String getPolicy() { + return policy; + } + + public void setPolicy(String policy) { + this.policy = policy; + } + + public String getApiType() { + return apiType; + } + + public void setApiType(String apiType) { + this.apiType = apiType; + } + + public boolean isDefaultVersion() { + return isDefaultVersion; + } + + public void setDefaultVersion(boolean defaultVersion) { + isDefaultVersion = defaultVersion; + } + + public String getApiUUID() { + return apiUUID; + } + + public void setApiUUID(String apiUUID) { + this.apiUUID = apiUUID; + } + + public String getLcState() { + return lcState; + } + + public void setLcState(String lcState) { + this.lcState = lcState; + } +} diff --git a/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/models/SubscriptionInfo.java b/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/models/admin/SubscriptionInfo.java similarity index 97% rename from enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/models/SubscriptionInfo.java rename to enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/models/admin/SubscriptionInfo.java index e7931a5e1e..8b163174c7 100644 --- a/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/models/SubscriptionInfo.java +++ b/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/models/admin/SubscriptionInfo.java @@ -15,7 +15,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.wso2.choreo.connect.enforcer.models; +package org.wso2.choreo.connect.enforcer.models.admin; import java.io.Serializable; diff --git a/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/security/KeyValidator.java b/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/security/KeyValidator.java index 0d0493cd2e..9af3723256 100644 --- a/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/security/KeyValidator.java +++ b/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/security/KeyValidator.java @@ -25,6 +25,7 @@ import org.wso2.choreo.connect.enforcer.commons.model.APIConfig; import org.wso2.choreo.connect.enforcer.commons.model.ResourceConfig; import org.wso2.choreo.connect.enforcer.constants.APIConstants; +import org.wso2.choreo.connect.enforcer.constants.GeneralErrorCodeConstants; import org.wso2.choreo.connect.enforcer.dto.APIKeyValidationInfoDTO; import org.wso2.choreo.connect.enforcer.exception.EnforcerException; import org.wso2.choreo.connect.enforcer.models.ApiPolicy; @@ -33,7 +34,6 @@ import org.wso2.choreo.connect.enforcer.models.ApplicationPolicy; import org.wso2.choreo.connect.enforcer.models.Subscription; import org.wso2.choreo.connect.enforcer.models.SubscriptionPolicy; -import org.wso2.choreo.connect.enforcer.models.URLMapping; import org.wso2.choreo.connect.enforcer.subscription.SubscriptionDataHolder; import org.wso2.choreo.connect.enforcer.subscription.SubscriptionDataStore; import org.wso2.choreo.connect.enforcer.util.FilterUtils; @@ -263,12 +263,11 @@ private static void validate(APIKeyValidationInfoDTO infoDTO, SubscriptionDataSt infoDTO.setAuthorized(false); return; } - // TODO: (VirajSalaka) checking for blocked APIs implementation is temporarily removed. -// else if (APIConstants.LifecycleStatus.BLOCKED.equals(api.getLcState())) { -// infoDTO.setValidationStatus(GeneralErrorCodeConstants.API_BLOCKED_CODE); -// infoDTO.setAuthorized(false); -// return; -// } + if (APIConstants.LifecycleStatus.BLOCKED.equals(apiConfig.getApiLifeCycleState())) { + infoDTO.setValidationStatus(GeneralErrorCodeConstants.API_BLOCKED_CODE); + infoDTO.setAuthorized(false); + return; + } infoDTO.setTier(sub.getPolicyId()); infoDTO.setSubscriber(app.getSubName()); infoDTO.setApplicationId(app.getId()); @@ -331,23 +330,4 @@ private static void validate(APIKeyValidationInfoDTO infoDTO, SubscriptionDataSt infoDTO.setThrottlingDataList(list); infoDTO.setAuthorized(true); } - - private boolean isResourcePathMatching(String resourceString, URLMapping urlMapping) { - - String resource = resourceString.trim(); - String urlPattern = urlMapping.getUrlPattern().trim(); - - if (resource.equalsIgnoreCase(urlPattern)) { - return true; - } - - // If the urlPattern is only one character longer than the resource and the urlPattern ends with a '/' - if (resource.length() + 1 == urlPattern.length() && urlPattern.endsWith("/")) { - // Check if resource is equal to urlPattern if the trailing '/' of the urlPattern is ignored - String urlPatternWithoutSlash = urlPattern.substring(0, urlPattern.length() - 1); - return resource.equalsIgnoreCase(urlPatternWithoutSlash); - } - - return false; - } } diff --git a/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/subscription/SubscriptionDataStore.java b/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/subscription/SubscriptionDataStore.java index abf638a48a..edcd22a01a 100644 --- a/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/subscription/SubscriptionDataStore.java +++ b/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/subscription/SubscriptionDataStore.java @@ -139,25 +139,6 @@ void addApplicationKeyMappings( API getDefaultApiByContext(String context); - /** - * Filter the API map according to the provided parameters - * @param name API Name - * @param context API Context - * @param version API Version - * @param uuid API UUID - * @return Matching list of apis. - */ - List getMatchingAPIs(String name, String context, String version, String uuid); - - /** - * Filter the API map according to the provided parameters - * - * @param context API Context - * @param version API Version - * @return Matching list of apis. - */ - API getMatchingAPI(String context, String version); - /** * Filter the applications map based on the criteria. * @param name Application Name diff --git a/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/subscription/SubscriptionDataStoreImpl.java b/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/subscription/SubscriptionDataStoreImpl.java index 6218e29bcc..613ddd47a1 100644 --- a/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/subscription/SubscriptionDataStoreImpl.java +++ b/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/subscription/SubscriptionDataStoreImpl.java @@ -41,9 +41,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.concurrent.ConcurrentHashMap; -import java.util.stream.Collectors; /** * Implementation of the subscription data store. @@ -198,13 +196,6 @@ public void addApis(List apisList) { for (APIs api : apisList) { API newApi = new API(); - newApi.setApiId(Integer.parseInt(api.getApiId())); - newApi.setApiName(api.getName()); - newApi.setApiProvider(api.getProvider()); - newApi.setApiType(api.getApiType()); - newApi.setApiVersion(api.getVersion()); - newApi.setContext(api.getContext()); - newApi.setApiTier(api.getPolicy()); newApi.setApiUUID(api.getUuid()); newApi.setLcState(api.getLcState()); newApiMap.put(newApi.getCacheKey(), newApi); @@ -376,55 +367,16 @@ public void removeApiPolicy(ApiPolicy apiPolicy) { @Override public API getDefaultApiByContext(String context) { - Set set = apiMap.keySet() - .stream() - .filter(s -> s.startsWith(context)) - .collect(Collectors.toSet()); - for (String key : set) { - API api = apiMap.get(key); - if (api.isDefaultVersion() && (api.getContext().replace("/" + api.getApiVersion(), "")).equals(context)) { - return api; - } - } - return null; - } - - @Override - public List getMatchingAPIs(String name, String context, String version, String uuid) { - List apiList = new ArrayList<>(); - for (API api : apiMap.values()) { - boolean isNameMatching = true; - boolean isContextMatching = true; - boolean isVersionMatching = true; - boolean isUUIDMatching = true; - if (StringUtils.isNotEmpty(name)) { - isNameMatching = api.getApiName().contains(name); - } - if (StringUtils.isNotEmpty(context)) { - isContextMatching = api.getContext().equals(context); - } - if (StringUtils.isNotEmpty(version)) { - isVersionMatching = api.getApiVersion().equals(version); - } - if (StringUtils.isNotEmpty(uuid)) { - isUUIDMatching = api.getApiUUID().equals(uuid); - } - if (isNameMatching && isContextMatching && isVersionMatching && isUUIDMatching) { - apiList.add(api); - } - } - return apiList; - } - - @Override - public API getMatchingAPI(String context, String version) { - for (API api : apiMap.values()) { - if (StringUtils.isNotEmpty(context) && StringUtils.isNotEmpty(version)) { - if (api.getContext().equals(context) && api.getApiVersion().equals(version)) { - return api; - } - } - } +// Set set = apiMap.keySet() +// .stream() +// .filter(s -> s.startsWith(context)) +// .collect(Collectors.toSet()); +// for (String key : set) { +// API api = apiMap.get(key); +// if (api.isDefaultVersion() && (api.getContext().replace("/" + api.getApiVersion(), "")).equals(context)) { +// return api; +// } +// } return null; } diff --git a/integration/test-integration/src/test/java/org/wso2/choreo/connect/tests/testcases/withapim/EnforcerAPITestCase.java b/integration/test-integration/src/test/java/org/wso2/choreo/connect/tests/testcases/withapim/EnforcerAPITestCase.java index 302f3efa33..a60bee5664 100644 --- a/integration/test-integration/src/test/java/org/wso2/choreo/connect/tests/testcases/withapim/EnforcerAPITestCase.java +++ b/integration/test-integration/src/test/java/org/wso2/choreo/connect/tests/testcases/withapim/EnforcerAPITestCase.java @@ -42,51 +42,51 @@ void setup() throws Exception { super.initWithSuperTenant(); } -// @Test -// public void testGetAPIInfo() throws IOException { -// String requestUrl = "https://localhost:9001/api/info?context=" + API_CONTEXT + "&version=" + API_VERSION; -// Map headers = new HashMap<>(); -// headers.put("Authorization", "Basic " + ADMIN_CREDENTIALS); -// HttpResponse httpResponse = HttpClientRequest.doGet(requestUrl, headers); -// Assert.assertNotNull(httpResponse.getData()); -// Assert.assertTrue(httpResponse.getData().contains(API_NAME)); -// Assert.assertTrue(httpResponse.getData().contains(API_CONTEXT)); -// Assert.assertTrue(httpResponse.getData().contains(API_VERSION)); -// Assert.assertTrue(httpResponse.getData().contains(APPLICATION_NAME)); -// } + @Test + public void testGetAPIInfo() throws IOException { + String requestUrl = "https://localhost:9001/api/info?context=" + API_CONTEXT + "&version=" + API_VERSION; + Map headers = new HashMap<>(); + headers.put("Authorization", "Basic " + ADMIN_CREDENTIALS); + HttpResponse httpResponse = HttpClientRequest.doGet(requestUrl, headers); + Assert.assertNotNull(httpResponse.getData()); + Assert.assertTrue(httpResponse.getData().contains(API_NAME)); + Assert.assertTrue(httpResponse.getData().contains(API_CONTEXT)); + Assert.assertTrue(httpResponse.getData().contains(API_VERSION)); + Assert.assertTrue(httpResponse.getData().contains(APPLICATION_NAME)); + } -// @Test -// public void testGetNonExistingAPIInfo() throws IOException { -// String requestUrl = "https://localhost:9001/api/info?context=" + NON_EXISTING_CONTEXT + "&version=" + API_VERSION; -// Map headers = new HashMap<>(); -// headers.put("Authorization", "Basic " + ADMIN_CREDENTIALS); -// HttpResponse httpResponse = HttpClientRequest.doGet(requestUrl, headers); -// Assert.assertNotNull(httpResponse.getData()); -// Assert.assertTrue(httpResponse.getData().contains("No API information found for context " + -// NON_EXISTING_CONTEXT + " and version " + API_VERSION)); -// } + @Test + public void testGetNonExistingAPIInfo() throws IOException { + String requestUrl = "https://localhost:9001/api/info?context=" + NON_EXISTING_CONTEXT + "&version=" + API_VERSION; + Map headers = new HashMap<>(); + headers.put("Authorization", "Basic " + ADMIN_CREDENTIALS); + HttpResponse httpResponse = HttpClientRequest.doGet(requestUrl, headers); + Assert.assertNotNull(httpResponse.getData()); + Assert.assertTrue(httpResponse.getData().contains("No API information found for context " + + NON_EXISTING_CONTEXT + " and version " + API_VERSION)); + } -// @Test -// public void testGetAllAPIs() throws IOException { -// String requestUrl = "https://localhost:9001/apis"; -// Map headers = new HashMap<>(); -// headers.put("Authorization", "Basic " + ADMIN_CREDENTIALS); -// HttpResponse httpResponse = HttpClientRequest.doGet(requestUrl, headers); -// Assert.assertNotNull(httpResponse.getData()); -// Assert.assertTrue(httpResponse.getData().contains("count")); -// } + @Test + public void testGetAllAPIs() throws IOException { + String requestUrl = "https://localhost:9001/apis"; + Map headers = new HashMap<>(); + headers.put("Authorization", "Basic " + ADMIN_CREDENTIALS); + HttpResponse httpResponse = HttpClientRequest.doGet(requestUrl, headers); + Assert.assertNotNull(httpResponse.getData()); + Assert.assertTrue(httpResponse.getData().contains("count")); + } -// @Test -// public void testQueryAPIs() throws IOException { -// String requestUrl = "https://localhost:9001/apis?context=" + API_CONTEXT; -// Map headers = new HashMap<>(); -// headers.put("Authorization", "Basic " + ADMIN_CREDENTIALS); -// HttpResponse httpResponse = HttpClientRequest.doGet(requestUrl, headers); -// Assert.assertNotNull(httpResponse.getData()); -// Assert.assertTrue(httpResponse.getData().contains("\"count\":1")); -// Assert.assertTrue(httpResponse.getData().contains(API_CONTEXT)); -// Assert.assertTrue(httpResponse.getData().contains(API_NAME)); -// } + @Test + public void testQueryAPIs() throws IOException { + String requestUrl = "https://localhost:9001/apis?context=" + API_CONTEXT; + Map headers = new HashMap<>(); + headers.put("Authorization", "Basic " + ADMIN_CREDENTIALS); + HttpResponse httpResponse = HttpClientRequest.doGet(requestUrl, headers); + Assert.assertNotNull(httpResponse.getData()); + Assert.assertTrue(httpResponse.getData().contains("\"count\":1")); + Assert.assertTrue(httpResponse.getData().contains(API_CONTEXT)); + Assert.assertTrue(httpResponse.getData().contains(API_NAME)); + } @Test public void testGetApplications() throws IOException { diff --git a/integration/test-integration/src/test/java/org/wso2/choreo/connect/tests/testcases/withapim/PrototypedAPITestCase.java b/integration/test-integration/src/test/java/org/wso2/choreo/connect/tests/testcases/withapim/PrototypedAPITestCase.java deleted file mode 100644 index 89571ad087..0000000000 --- a/integration/test-integration/src/test/java/org/wso2/choreo/connect/tests/testcases/withapim/PrototypedAPITestCase.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org). - * - * WSO2 Inc. 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.choreo.connect.tests.testcases.withapim; - -import com.github.dockerjava.zerodep.shaded.org.apache.hc.core5.http.HttpStatus; -import com.google.gson.Gson; -import net.minidev.json.JSONObject; -import net.minidev.json.parser.JSONParser; -import org.testng.Assert; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import org.wso2.am.integration.clients.publisher.api.v1.dto.APIDTO; -import org.wso2.am.integration.clients.publisher.api.v1.dto.WorkflowResponseDTO; -import org.wso2.am.integration.test.utils.bean.APILifeCycleAction; -import org.wso2.am.integration.test.utils.bean.APIRequest; -import org.wso2.carbon.automation.test.utils.http.client.HttpResponse; -import org.wso2.choreo.connect.tests.apim.ApimBaseTest; -import org.wso2.choreo.connect.tests.apim.utils.PublisherUtils; -import org.wso2.choreo.connect.tests.util.HttpsClientRequest; -import org.wso2.choreo.connect.tests.util.TestConstant; -import org.wso2.choreo.connect.tests.util.Utils; - -import java.net.URL; -import java.util.HashMap; -import java.util.Map; - -public class PrototypedAPITestCase extends ApimBaseTest { - private static final String SAMPLE_API_NAME = "APIMPrototypedEndpointAPI1"; - private static final String SAMPLE_API_CONTEXT = "petstore-prototype"; - private static final String SAMPLE_API_VERSION = "1.0.0"; - private String apiId; - - @BeforeClass(description = "Initialise the setup for API key tests") - void start() throws Exception { - super.initWithSuperTenant(); - String apiEndPointUrl = Utils.getDockerMockServiceURLHttp(TestConstant.MOCK_BACKEND_BASEPATH);; - String apiProvider = "admin"; - - APIRequest apiRequest = new APIRequest(SAMPLE_API_NAME, SAMPLE_API_CONTEXT, new URL(apiEndPointUrl)); - apiRequest.setVersion(SAMPLE_API_VERSION); - apiRequest.setVisibility(APIDTO.VisibilityEnum.PUBLIC.getValue()); - apiRequest.setProvider(apiProvider); - - apiId = PublisherUtils.createAPI(apiRequest, publisherRestClient); - - WorkflowResponseDTO lcChangeResponse = publisherRestClient.changeAPILifeCycleStatus( - apiId, APILifeCycleAction.DEPLOY_AS_PROTOTYPE.getAction()); - - HttpResponse response = publisherRestClient.getAPI(apiId); - Gson g = new Gson(); - APIDTO apiDto = g.fromJson(response.getData(), APIDTO.class); - String endPointString = "{\"implementation_status\":\"prototyped\",\"endpoint_type\":\"http\"," + - "\"production_endpoints\":{\"config\":null," + - "\"url\":\"" + apiEndPointUrl + "\"}," + - "\"sandbox_endpoints\":{\"config\":null,\"url\":\"" + "http://localhost" + "\"}}"; - - JSONParser parser = new JSONParser(); - JSONObject endpoint = (JSONObject) parser.parse(endPointString); - apiDto.setEndpointConfig(endpoint); - publisherRestClient.updateAPI(apiDto); - - Assert.assertTrue(lcChangeResponse.getLifecycleState().getState().equals("Prototyped"), - SAMPLE_API_NAME + " status not updated as Prototyped"); - - PublisherUtils.createAPIRevisionAndDeploy(apiId, publisherRestClient); - Utils.delay(TestConstant.DEPLOYMENT_WAIT_TIME, "Could not wait till initial setup completion."); - } - - @Test(description = "Test to check the PrototypedAPI is working") - public void invokePrototypeAPISuccessTest() throws Exception { - // Set header - Map headers = new HashMap<>(); - org.wso2.choreo.connect.tests.util.HttpResponse response = - HttpsClientRequest.doGet( - Utils.getServiceURLHttps("/petstore-prototype/1.0.0/pet/findByStatus"), headers); - - Assert.assertNotNull(response); - Assert.assertEquals(response.getResponseCode(), HttpStatus.SC_OK,"Response code mismatched"); - } -} diff --git a/integration/test-integration/src/test/resources/testng-cc-with-apim.xml b/integration/test-integration/src/test/resources/testng-cc-with-apim.xml index f27aa3b250..1845958364 100644 --- a/integration/test-integration/src/test/resources/testng-cc-with-apim.xml +++ b/integration/test-integration/src/test/resources/testng-cc-with-apim.xml @@ -41,9 +41,9 @@ - - - + + + @@ -60,7 +60,7 @@ - + @@ -77,7 +77,7 @@ - + @@ -89,7 +89,6 @@ - diff --git a/router/src/main/resources/Dockerfile b/router/src/main/resources/Dockerfile index 23976bf7dd..1b09b291fd 100644 --- a/router/src/main/resources/Dockerfile +++ b/router/src/main/resources/Dockerfile @@ -69,4 +69,5 @@ COPY maven/wasm /home/wso2/wasm COPY maven/security/truststore/ca-certificates.crt /etc/ssl/certs COPY maven/interceptor /home/wso2/interceptor COPY maven/envoy.yaml /etc/envoy/envoy.yaml + CMD /usr/local/bin/envoy -c /etc/envoy/envoy.yaml --config-yaml "{admin: {address: {socket_address: {address: '${ROUTER_ADMIN_HOST}', port_value: '${ROUTER_ADMIN_PORT}'}}}, dynamic_resources: {ads_config: {api_type: GRPC, transport_api_version: V3, grpc_services: [{envoy_grpc: {cluster_name: xds_cluster}}]}, cds_config: {ads: {}, resource_api_version: V3}, lds_config: {ads: {}, resource_api_version: V3}}, node: {cluster: '${ROUTER_CLUSTER}', id: '${ROUTER_LABEL}', metadata: {instanceIdentifier : ${HOSTNAME}}}, static_resources: {clusters: [{name: xds_cluster, type: STRICT_DNS, connect_timeout: 1s, upstream_connection_options: {tcp_keepalive: {keepalive_probes: 3, keepalive_time: 300, keepalive_interval: 30}}, load_assignment: {cluster_name: xds_cluster, endpoints: [{lb_endpoints: [{endpoint: {address: {socket_address: {address: '${ADAPTER_HOST}', port_value: '${ADAPTER_PORT}'}}}}]}]}, typed_extension_protocol_options: {envoy.extensions.upstreams.http.v3.HttpProtocolOptions: {'@type': 'type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions', explicit_http_config: {http2_protocol_options: {}}}}, transport_socket: {name: envoy.transport_sockets.tls, typed_config: {'@type': type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext, common_tls_context: {tls_params: {tls_minimum_protocol_version: TLSv1_2, tls_maximum_protocol_version: TLSv1_2}, tls_certificates: {private_key: {filename: '${ROUTER_PRIVATE_KEY_PATH}'}, certificate_chain: {filename: '${ROUTER_PUBLIC_CERT_PATH}'}}, validation_context: {trusted_ca: {filename: '${ADAPTER_CA_CERT_PATH}'}}}}}}, {name: ext-authz, type: STRICT_DNS, connect_timeout: 20s, typed_extension_protocol_options: {envoy.extensions.upstreams.http.v3.HttpProtocolOptions: {'@type': 'type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions', explicit_http_config: {http2_protocol_options: {}}}}, transport_socket: {name: envoy.transport_sockets.tls, typed_config: {'@type': type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext, common_tls_context: {tls_params: {tls_minimum_protocol_version: TLSv1_2, tls_maximum_protocol_version: TLSv1_2}, tls_certificates: {private_key: {filename: '${ROUTER_PRIVATE_KEY_PATH}'}, certificate_chain: {filename: '${ROUTER_PUBLIC_CERT_PATH}'}}, validation_context: {trusted_ca: {filename: '${ENFORCER_CA_CERT_PATH}'}}}}}, load_assignment: {cluster_name: ext-authz, endpoints: [{lb_endpoints: [{endpoint: {address: {socket_address: {address: '${ENFORCER_HOST}', port_value: '${ENFORCER_PORT}'}}}}]}]}}, {name: access-logger, type: STRICT_DNS, connect_timeout: 200s, typed_extension_protocol_options: {envoy.extensions.upstreams.http.v3.HttpProtocolOptions: {'@type': 'type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions', explicit_http_config: {http2_protocol_options: {}}}}, transport_socket: {name: envoy.transport_sockets.tls, typed_config: {'@type': type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext, common_tls_context: {tls_params: {tls_minimum_protocol_version: TLSv1_2, tls_maximum_protocol_version: TLSv1_2}, tls_certificates: {private_key: {filename: '${ROUTER_PRIVATE_KEY_PATH}'}, certificate_chain: {filename: '${ROUTER_PUBLIC_CERT_PATH}'}}, validation_context: {trusted_ca: {filename: '${ENFORCER_CA_CERT_PATH}'}}}}}, load_assignment: {cluster_name: access-logger, endpoints: [{lb_endpoints: [{endpoint: {address: {socket_address: {address: '${ENFORCER_ANALYTICS_HOST}', port_value: '${ENFORCER_ANALYTICS_RECEIVER_PORT}'}}}}]}]}}, {name: token_cluster, type: STRICT_DNS, connect_timeout: 20s, transport_socket: {name: envoy.transport_sockets.tls, typed_config: {'@type': type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext, common_tls_context: {tls_params: {tls_minimum_protocol_version: TLSv1_2, tls_maximum_protocol_version: TLSv1_2}, tls_certificates: {private_key: {filename: '${ROUTER_PRIVATE_KEY_PATH}'}, certificate_chain: {filename: '${ROUTER_PUBLIC_CERT_PATH}'}}, validation_context: {trusted_ca: {filename: '${ENFORCER_CA_CERT_PATH}'}}}}}, load_assignment: {cluster_name: token_cluster, endpoints: [{lb_endpoints: [{endpoint: {address: {socket_address: {address: '${ENFORCER_HOST}', port_value: 8082}}}}]}]}}]}, layeredRuntime: {layers: [{name: deprecation, staticLayer: {re2.max_program_size.error_level: 1000}}]} }" --concurrency "${CONCURRENCY}" $TRAILING_ARGS diff --git a/router/src/main/resources/Dockerfile.ubuntu b/router/src/main/resources/Dockerfile.ubuntu index cf2d7062ca..37d56580a8 100644 --- a/router/src/main/resources/Dockerfile.ubuntu +++ b/router/src/main/resources/Dockerfile.ubuntu @@ -69,4 +69,5 @@ COPY maven/wasm /home/wso2/wasm COPY maven/security/truststore/ca-certificates.crt /etc/ssl/certs COPY maven/interceptor /home/wso2/interceptor COPY maven/envoy.yaml /etc/envoy/envoy.yaml + CMD /usr/local/bin/envoy -c /etc/envoy/envoy.yaml --config-yaml "{admin: {address: {socket_address: {address: '${ROUTER_ADMIN_HOST}', port_value: '${ROUTER_ADMIN_PORT}'}}}, dynamic_resources: {ads_config: {api_type: GRPC, transport_api_version: V3, grpc_services: [{envoy_grpc: {cluster_name: xds_cluster}}]}, cds_config: {ads: {}, resource_api_version: V3}, lds_config: {ads: {}, resource_api_version: V3}}, node: {cluster: '${ROUTER_CLUSTER}', id: '${ROUTER_LABEL}', metadata: {instanceIdentifier : ${HOSTNAME}}}, static_resources: {clusters: [{name: xds_cluster, type: STRICT_DNS, connect_timeout: 1s, upstream_connection_options: {tcp_keepalive: {keepalive_probes: 3, keepalive_time: 300, keepalive_interval: 30}}, load_assignment: {cluster_name: xds_cluster, endpoints: [{lb_endpoints: [{endpoint: {address: {socket_address: {address: '${ADAPTER_HOST}', port_value: '${ADAPTER_PORT}'}}}}]}]}, typed_extension_protocol_options: {envoy.extensions.upstreams.http.v3.HttpProtocolOptions: {'@type': 'type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions', explicit_http_config: {http2_protocol_options: {}}}}, transport_socket: {name: envoy.transport_sockets.tls, typed_config: {'@type': type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext, common_tls_context: {tls_params: {tls_minimum_protocol_version: TLSv1_2, tls_maximum_protocol_version: TLSv1_2}, tls_certificates: {private_key: {filename: '${ROUTER_PRIVATE_KEY_PATH}'}, certificate_chain: {filename: '${ROUTER_PUBLIC_CERT_PATH}'}}, validation_context: {trusted_ca: {filename: '${ADAPTER_CA_CERT_PATH}'}}}}}}, {name: ext-authz, type: STRICT_DNS, connect_timeout: 20s, typed_extension_protocol_options: {envoy.extensions.upstreams.http.v3.HttpProtocolOptions: {'@type': 'type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions', explicit_http_config: {http2_protocol_options: {}}}}, transport_socket: {name: envoy.transport_sockets.tls, typed_config: {'@type': type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext, common_tls_context: {tls_params: {tls_minimum_protocol_version: TLSv1_2, tls_maximum_protocol_version: TLSv1_2}, tls_certificates: {private_key: {filename: '${ROUTER_PRIVATE_KEY_PATH}'}, certificate_chain: {filename: '${ROUTER_PUBLIC_CERT_PATH}'}}, validation_context: {trusted_ca: {filename: '${ENFORCER_CA_CERT_PATH}'}}}}}, load_assignment: {cluster_name: ext-authz, endpoints: [{lb_endpoints: [{endpoint: {address: {socket_address: {address: '${ENFORCER_HOST}', port_value: '${ENFORCER_PORT}'}}}}]}]}}, {name: access-logger, type: STRICT_DNS, connect_timeout: 200s, typed_extension_protocol_options: {envoy.extensions.upstreams.http.v3.HttpProtocolOptions: {'@type': 'type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions', explicit_http_config: {http2_protocol_options: {}}}}, transport_socket: {name: envoy.transport_sockets.tls, typed_config: {'@type': type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext, common_tls_context: {tls_params: {tls_minimum_protocol_version: TLSv1_2, tls_maximum_protocol_version: TLSv1_2}, tls_certificates: {private_key: {filename: '${ROUTER_PRIVATE_KEY_PATH}'}, certificate_chain: {filename: '${ROUTER_PUBLIC_CERT_PATH}'}}, validation_context: {trusted_ca: {filename: '${ENFORCER_CA_CERT_PATH}'}}}}}, load_assignment: {cluster_name: access-logger, endpoints: [{lb_endpoints: [{endpoint: {address: {socket_address: {address: '${ENFORCER_ANALYTICS_HOST}', port_value: '${ENFORCER_ANALYTICS_RECEIVER_PORT}'}}}}]}]}}, {name: token_cluster, type: STRICT_DNS, connect_timeout: 20s, transport_socket: {name: envoy.transport_sockets.tls, typed_config: {'@type': type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext, common_tls_context: {tls_params: {tls_minimum_protocol_version: TLSv1_2, tls_maximum_protocol_version: TLSv1_2}, tls_certificates: {private_key: {filename: '${ROUTER_PRIVATE_KEY_PATH}'}, certificate_chain: {filename: '${ROUTER_PUBLIC_CERT_PATH}'}}, validation_context: {trusted_ca: {filename: '${ENFORCER_CA_CERT_PATH}'}}}}}, load_assignment: {cluster_name: token_cluster, endpoints: [{lb_endpoints: [{endpoint: {address: {socket_address: {address: '${ENFORCER_HOST}', port_value: 8082}}}}]}]}}]}, layeredRuntime: {layers: [{name: deprecation, staticLayer: {re2.max_program_size.error_level: 1000}}]} }" --concurrency "${CONCURRENCY}" $TRAILING_ARGS