Skip to content

Commit

Permalink
fix vhost maps and semantic version maps
Browse files Browse the repository at this point in the history
  • Loading branch information
AmaliMatharaarachchi committed Mar 5, 2024
1 parent a6fa97f commit 19a03d1
Show file tree
Hide file tree
Showing 27 changed files with 584 additions and 749 deletions.
2 changes: 0 additions & 2 deletions adapter/internal/discovery/xds/marshaller.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,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 {
Expand Down
214 changes: 37 additions & 177 deletions adapter/internal/discovery/xds/semantic_versioning.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import (
"github.com/wso2/apk/adapter/config"
logger "github.com/wso2/apk/adapter/internal/loggers"
logging "github.com/wso2/apk/adapter/internal/logging"
"github.com/wso2/apk/adapter/internal/oasparser/model"
semantic_version "github.com/wso2/apk/adapter/pkg/semanticversion"
)

Expand Down Expand Up @@ -68,8 +67,7 @@ func GetMinorVersionRange(semVersion semantic_version.SemVersion) string {
}

func updateRoutingRulesOnAPIUpdate(organizationID, apiIdentifier, apiName, apiVersion, vHost string) {

apiSemVersion, err := semantic_version.ValidateAndGetVersionComponents(apiVersion, apiName)
apiSemVersion, err := semantic_version.ValidateAndGetVersionComponents(apiVersion)
// If the version validation is not success, we just proceed without intelligent version
// Valid version pattern: vx.y.z or vx.y where x, y and z are non-negative integers and v is a prefix
if err != nil && apiSemVersion == nil {
Expand All @@ -90,9 +88,9 @@ func updateRoutingRulesOnAPIUpdate(organizationID, apiIdentifier, apiName, apiVe
// Remove the existing regexes from the path specifier when latest major and/or minor version is available
if (isMajorRangeRegexAvailable || isMinorRangeRegexAvailable) && (isLatestMajorVersion || isLatestMinorVersion) {
// Organization's all apis
for _, envoyInternalAPI := range orgAPIMap[organizationID] {
for vuuid, envoyInternalAPI := range orgAPIMap[organizationID] {
// API's all versions in the same vHost
if envoyInternalAPI.adapterInternalAPI.GetTitle() == apiName && isVHostMatched(organizationID, vHost) {
if envoyInternalAPI.adapterInternalAPI.GetTitle() == apiName && strings.HasPrefix(vuuid+":", vHost) {

if (isMajorRangeRegexAvailable && envoyInternalAPI.adapterInternalAPI.GetVersion() == existingMajorRangeLatestSemVersion.Version) ||
(isMinorRangeRegexAvailable && envoyInternalAPI.adapterInternalAPI.GetVersion() == existingMinorRangeLatestSemVersion.Version) {
Expand Down Expand Up @@ -167,192 +165,54 @@ func updateRoutingRulesOnAPIUpdate(organizationID, apiIdentifier, apiName, apiVe
}

route.Match.PathSpecifier = pathSpecifier
action := &routev3.Route_Route{}
action = route.Action.(*routev3.Route_Route)
action := route.Action.(*routev3.Route_Route)
action.Route.RegexRewrite.Pattern.Regex = regexRewritePattern
route.Action = action
}

}
}

func updateRoutingRulesOnAPIDelete(organizationID, apiIdentifier string, api model.AdapterInternalAPI) {
// Update the intelligent routing if the deleting API is the latest version of the API range
// and the API range has other versions
vhost, err := ExtractVhostFromAPIIdentifier(apiIdentifier)
if err != nil {
logger.LoggerXds.ErrorC(logging.PrintError(logging.Error1411, logging.MAJOR,
"Error extracting vhost from API identifier: %v for Organization %v. Ignore deploying the API, error: %v",
apiIdentifier, organizationID, err))
}
apiRangeIdentifier := generateIdentifierForAPIWithoutVersion(vhost, api.GetTitle())

latestAPIVersionMap, latestAPIVersionMapExists := orgIDLatestAPIVersionMap[organizationID][apiRangeIdentifier]
if !latestAPIVersionMapExists {
return
}
deletingAPISemVersion, _ := semantic_version.ValidateAndGetVersionComponents(api.GetVersion(), api.GetTitle())
if deletingAPISemVersion == nil {
return
}
majorVersionRange := GetMajorVersionRange(*deletingAPISemVersion)
newLatestMajorRangeAPIIdentifier := ""

if deletingAPIsMajorRangeLatestAPISemVersion, ok := latestAPIVersionMap[majorVersionRange]; ok {
if deletingAPIsMajorRangeLatestAPISemVersion.Version == api.GetVersion() {
newLatestMajorRangeAPI := &semantic_version.SemVersion{
Version: "",
Major: deletingAPISemVersion.Major,
Minor: 0,
Patch: nil,
}
for currentAPIIdentifier, envoyInternalAPI := range orgAPIMap[organizationID] {
// Iterate all the API versions other than the deleting API itself
if envoyInternalAPI.adapterInternalAPI.GetTitle() == api.GetTitle() && currentAPIIdentifier != apiIdentifier {
currentAPISemVersion, _ := semantic_version.ValidateAndGetVersionComponents(envoyInternalAPI.adapterInternalAPI.GetVersion(), envoyInternalAPI.adapterInternalAPI.GetTitle())
if currentAPISemVersion != nil {
if currentAPISemVersion.Major == deletingAPISemVersion.Major {
if newLatestMajorRangeAPI.Compare(*currentAPISemVersion) {
newLatestMajorRangeAPI = currentAPISemVersion
newLatestMajorRangeAPIIdentifier = currentAPIIdentifier
}
}
}
}
}
if newLatestMajorRangeAPIIdentifier != "" {
orgIDLatestAPIVersionMap[organizationID][apiRangeIdentifier][majorVersionRange] = *newLatestMajorRangeAPI
apiRoutes := getRoutesForAPIIdentifier(organizationID, newLatestMajorRangeAPIIdentifier)
for _, route := range apiRoutes {
regex := route.GetMatch().GetSafeRegex().GetRegex()
regexRewritePattern := route.GetRoute().GetRegexRewrite().GetPattern().GetRegex()
newLatestMajorRangeAPIVersionRegex := GetVersionMatchRegex(newLatestMajorRangeAPI.Version)
// Remove any available minor version range regexes and apply the minor range regex
regex = strings.Replace(
regex,
GetMinorVersionRangeRegex(*newLatestMajorRangeAPI),
newLatestMajorRangeAPIVersionRegex,
1,
)
regexRewritePattern = strings.Replace(
regexRewritePattern,
GetMinorVersionRangeRegex(*newLatestMajorRangeAPI),
newLatestMajorRangeAPIVersionRegex,
1,
)
regex = strings.Replace(
regex,
newLatestMajorRangeAPIVersionRegex,
GetMajorMinorVersionRangeRegex(*newLatestMajorRangeAPI),
1,
)
regexRewritePattern = strings.Replace(
regexRewritePattern,
newLatestMajorRangeAPIVersionRegex,
GetMajorMinorVersionRangeRegex(*newLatestMajorRangeAPI),
1,
)
pathSpecifier := &routev3.RouteMatch_SafeRegex{
SafeRegex: &envoy_type_matcherv3.RegexMatcher{
Regex: regex,
},
}

route.Match.PathSpecifier = pathSpecifier
action := &routev3.Route_Route{}
action = route.Action.(*routev3.Route_Route)
action.Route.RegexRewrite.Pattern.Regex = regexRewritePattern
route.Action = action
}
} else {
delete(orgIDLatestAPIVersionMap[organizationID][apiRangeIdentifier], majorVersionRange)
}
func updateSemanticVersioning(org string, apiRangeIdentifiers map[string]struct{}) {
// Iterate all the APIs in the API range
for vuuid, api := range orgAPIMap[org] {
// get vhost from the api identifier
vhost, _ := ExtractVhostFromAPIIdentifier(vuuid)
apiName := api.adapterInternalAPI.GetTitle()
apiRangeIdentifier := generateIdentifierForAPIWithoutVersion(vhost, apiName)
if _, ok := apiRangeIdentifiers[apiRangeIdentifier]; !ok {
continue
}
}
minorVersionRange := GetMinorVersionRange(*deletingAPISemVersion)

if deletingAPIsMinorRangeLatestAPI, ok := latestAPIVersionMap[minorVersionRange]; ok {
if deletingAPIsMinorRangeLatestAPI.Version == api.GetVersion() {
newLatestMinorRangeAPI := &semantic_version.SemVersion{
Version: "",
Major: deletingAPISemVersion.Major,
Minor: deletingAPISemVersion.Minor,
Patch: nil,
}
newLatestMinorRangeAPIIdentifier := ""
for currentAPIIdentifier, envoyInternalAPI := range orgAPIMap[organizationID] {
// Iterate all the API versions other than the deleting API itself
if envoyInternalAPI.adapterInternalAPI.GetTitle() == api.GetTitle() && currentAPIIdentifier != apiIdentifier {
currentAPISemVersion, _ := semantic_version.ValidateAndGetVersionComponents(envoyInternalAPI.adapterInternalAPI.GetVersion(), envoyInternalAPI.adapterInternalAPI.GetTitle())
if currentAPISemVersion != nil {
if currentAPISemVersion.Major == deletingAPISemVersion.Major &&
currentAPISemVersion.Minor == deletingAPISemVersion.Minor {
if newLatestMinorRangeAPI.Compare(*currentAPISemVersion) {
newLatestMinorRangeAPI = currentAPISemVersion
newLatestMinorRangeAPIIdentifier = currentAPIIdentifier
}
}
}
// get sem version from the api in orgmap
semVersion, err := semantic_version.ValidateAndGetVersionComponents(api.adapterInternalAPI.GetVersion())
if err != nil {
logger.LoggerXds.ErrorC(logging.PrintError(logging.Error1410, logging.MAJOR,
"Error validating the version of the API: %v for Organization: %v. Ignore deploying the API, error: %v",
vuuid, org, err))
continue
}
if currentAPISemVersion, exist := orgIDLatestAPIVersionMap[org][apiRangeIdentifier]; !exist {
orgIDLatestAPIVersionMap[org][apiRangeIdentifier] = make(map[string]semantic_version.SemVersion)
orgIDLatestAPIVersionMap[org][apiRangeIdentifier][GetMajorVersionRange(*semVersion)] = *semVersion
orgIDLatestAPIVersionMap[org][apiRangeIdentifier][GetMinorVersionRange(*semVersion)] = *semVersion

} else {
if _, ok := currentAPISemVersion[GetMajorVersionRange(*semVersion)]; !ok {
currentAPISemVersion[GetMajorVersionRange(*semVersion)] = *semVersion
} else {
if currentAPISemVersion[GetMajorVersionRange(*semVersion)].Compare(*semVersion) {
currentAPISemVersion[GetMajorVersionRange(*semVersion)] = *semVersion
}
}
if newLatestMinorRangeAPIIdentifier != "" && newLatestMinorRangeAPIIdentifier != newLatestMajorRangeAPIIdentifier {
orgIDLatestAPIVersionMap[organizationID][apiRangeIdentifier][minorVersionRange] = *newLatestMinorRangeAPI
apiRoutes := getRoutesForAPIIdentifier(organizationID, newLatestMinorRangeAPIIdentifier)
for _, route := range apiRoutes {
regex := route.GetMatch().GetSafeRegex().GetRegex()
newLatestMinorRangeAPIVersionRegex := GetVersionMatchRegex(newLatestMinorRangeAPI.Version)
regex = strings.Replace(
regex,
newLatestMinorRangeAPIVersionRegex,
GetMinorVersionRangeRegex(*newLatestMinorRangeAPI),
1,
)
pathSpecifier := &routev3.RouteMatch_SafeRegex{
SafeRegex: &envoy_type_matcherv3.RegexMatcher{
Regex: regex,
},
}
regexRewritePattern := route.GetRoute().GetRegexRewrite().GetPattern().GetRegex()
regexRewritePattern = strings.Replace(
regexRewritePattern,
newLatestMinorRangeAPIVersionRegex,
GetMinorVersionRangeRegex(*newLatestMinorRangeAPI),
1,
)
route.Match.PathSpecifier = pathSpecifier
action := &routev3.Route_Route{}
action = route.Action.(*routev3.Route_Route)
action.Route.RegexRewrite.Pattern.Regex = regexRewritePattern
route.Action = action
}
if _, ok := currentAPISemVersion[GetMinorVersionRange(*semVersion)]; !ok {
currentAPISemVersion[GetMinorVersionRange(*semVersion)] = *semVersion
} else {
delete(orgIDLatestAPIVersionMap[organizationID][apiRangeIdentifier], minorVersionRange)
}
}
}

if orgAPIMap, apiAvailable := orgIDLatestAPIVersionMap[organizationID][apiRangeIdentifier]; apiAvailable && len(orgAPIMap) == 0 {
delete(orgIDLatestAPIVersionMap[organizationID], apiRangeIdentifier)
if orgMap := orgIDLatestAPIVersionMap[organizationID]; len(orgMap) == 0 {
delete(orgIDLatestAPIVersionMap, organizationID)
}
}

}

func isVHostMatched(organizationID, vHost string) bool {

if apis, ok := orgIDAPIvHostsMap[organizationID]; ok {

for _, vHosts := range apis {
for _, vHostEntry := range vHosts {
if vHostEntry == vHost {
return true
if currentAPISemVersion[GetMinorVersionRange(*semVersion)].Compare(*semVersion) {
currentAPISemVersion[GetMinorVersionRange(*semVersion)] = *semVersion
}
}
}
}
return false
}

func getRoutesForAPIIdentifier(organizationID, apiIdentifier string) []*routev3.Route {
Expand All @@ -374,7 +234,7 @@ func isSemanticVersioningEnabled(apiName, apiVersion string) bool {
return false
}

apiSemVersion, err := semantic_version.ValidateAndGetVersionComponents(apiVersion, apiName)
apiSemVersion, err := semantic_version.ValidateAndGetVersionComponents(apiVersion)
if err != nil && apiSemVersion == nil {
return false
}
Expand Down
Loading

0 comments on commit 19a03d1

Please sign in to comment.