pkg/brownfield/pathmaps.go (149 lines of code) (raw):

// ------------------------------------------------------------------------------------------- // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. // -------------------------------------------------------------------------------------------- package brownfield import ( "strings" n "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2021-03-01/network" "k8s.io/klog/v2" ) type urlPathMapName string type pathRuleName string type pathmapToTargets map[urlPathMapName][]Target type pathMapsByName map[urlPathMapName]n.ApplicationGatewayURLPathMap type pathRulesByName map[pathRuleName]n.ApplicationGatewayPathRule // GetBlacklistedPathMaps filters the given list of routing pathMaps to the list pathMaps that AGIC is allowed to manage. func (er ExistingResources) GetBlacklistedPathMaps() ([]n.ApplicationGatewayURLPathMap, []n.ApplicationGatewayURLPathMap) { blacklist := GetTargetBlacklist(er.ProhibitedTargets) if blacklist == nil { return nil, er.URLPathMaps } _, pathMapToTargets := er.getRuleToTargets() klog.V(3).Infof("[brownfield] PathMap to Targets map: %+v", pathMapToTargets) // Figure out if the given BackendAddressPathMap is blacklisted. It will be if it has a host/path that // has been referenced in a AzureIngressProhibitedTarget CRD (even if it has some other paths that are not) isBlacklisted := func(pathMap n.ApplicationGatewayURLPathMap) bool { targetsForPathMap := pathMapToTargets[urlPathMapName(*pathMap.Name)] for _, target := range targetsForPathMap { if target.IsBlacklisted(blacklist) { klog.V(3).Infof("[brownfield] Routing PathMap %s is blacklisted", *pathMap.Name) return true } } klog.V(3).Infof("[brownfield] Routing PathMap %s is NOT blacklisted", *pathMap.Name) return false } var blacklistedPathMaps []n.ApplicationGatewayURLPathMap var nonBlacklistedPathMaps []n.ApplicationGatewayURLPathMap for _, pathMap := range er.URLPathMaps { if isBlacklisted(pathMap) { blacklistedPathMaps = append(blacklistedPathMaps, pathMap) continue } nonBlacklistedPathMaps = append(nonBlacklistedPathMaps, pathMap) } return blacklistedPathMaps, nonBlacklistedPathMaps } // MergePathMaps merges list of lists of pathMaps into a single list, maintaining uniqueness. func MergePathMaps(pathMapBuckets ...[]n.ApplicationGatewayURLPathMap) []n.ApplicationGatewayURLPathMap { uniq := make(pathMapsByName) for _, bucket := range pathMapBuckets { for _, pathMap := range bucket { if existingPathMap, exists := uniq[urlPathMapName(*pathMap.Name)]; exists { klog.V(3).Infof("[brownfield] Merging urlpath %s in existing blacklist and AGIC list", *existingPathMap.Name) uniq[urlPathMapName(*pathMap.Name)].PathRules = mergePathRules(existingPathMap.PathRules, pathMap.PathRules) } else { klog.V(3).Infof("[brownfield] Adding urlpath %s to the uniq map", *pathMap.Name) uniq[urlPathMapName(*pathMap.Name)] = pathMap } } } var merged []n.ApplicationGatewayURLPathMap for _, pathMap := range uniq { merged = append(merged, pathMap) } return merged } // LogPathMaps emits a few log lines detailing what pathMaps are created, blacklisted, and removed from ARM. func LogPathMaps(existingBlacklisted []n.ApplicationGatewayURLPathMap, existingNonBlacklisted []n.ApplicationGatewayURLPathMap, managedPathMaps []n.ApplicationGatewayURLPathMap) { var garbage []n.ApplicationGatewayURLPathMap blacklistedSet := indexPathMapsByName(existingBlacklisted) managedSet := indexPathMapsByName(managedPathMaps) for pathMapName, pathMap := range indexPathMapsByName(existingNonBlacklisted) { _, existsInBlacklist := blacklistedSet[pathMapName] _, existsInNewPathMaps := managedSet[pathMapName] if !existsInBlacklist && !existsInNewPathMaps { garbage = append(garbage, pathMap) } } klog.V(3).Info("[brownfield] PathMaps AGIC created: ", getPathMapNames(managedPathMaps)) klog.V(3).Info("[brownfield] Existing Blacklisted PathMaps AGIC will retain: ", getPathMapNames(existingBlacklisted)) klog.V(3).Info("[brownfield] Existing PathMaps AGIC will remove: ", getPathMapNames(garbage)) } // mergePathMapsWithBasicRule merges a Url pathmap with a basic routing rule func mergePathMapsWithBasicRule(pathMap *n.ApplicationGatewayURLPathMap, rule *n.ApplicationGatewayRequestRoutingRule) *n.ApplicationGatewayURLPathMap { // Replace the default values in the path map with values from the routing rule pathMap.DefaultBackendAddressPool = rule.BackendAddressPool pathMap.DefaultBackendHTTPSettings = rule.BackendHTTPSettings pathMap.DefaultRedirectConfiguration = rule.RedirectConfiguration pathMap.DefaultRewriteRuleSet = rule.RewriteRuleSet return pathMap } // mergePathRules merges list of lists of pathMaps into a single list, maintaining uniqueness. func mergePathRules(pathRulesBucket ...*[]n.ApplicationGatewayPathRule) *[]n.ApplicationGatewayPathRule { uniq := make(pathRulesByName) for _, bucket := range pathRulesBucket { if bucket == nil { continue } for _, pathRule := range *bucket { uniq[pathRuleName(*pathRule.Name)] = pathRule } } var merged []n.ApplicationGatewayPathRule for _, pathRule := range uniq { klog.V(3).Infof("[brownfield] Appending %s with paths %v", *pathRule.Name, pathRule.Paths) merged = append(merged, pathRule) } return &merged } // lookupPathMap using resourceID in the list of path map func lookupPathMap(pathMaps *[]n.ApplicationGatewayURLPathMap, resourceID *string) *n.ApplicationGatewayURLPathMap { for idx, pathMap := range *pathMaps { if *pathMap.ID == *resourceID { return &(*pathMaps)[idx] } } return nil } // deletePathMap deletes a path map from the list of path maps and return the new list func deletePathMap(pathMapsPtr *[]n.ApplicationGatewayURLPathMap, resourceID *string) *[]n.ApplicationGatewayURLPathMap { pathMaps := *pathMapsPtr deleteIdx := -1 for idx, pathMap := range pathMaps { if *pathMap.ID == *resourceID { klog.V(3).Infof("[brownfield] Deleting %s", *resourceID) deleteIdx = idx } } if deleteIdx != -1 { pathMaps[deleteIdx] = pathMaps[len(pathMaps)-1] *pathMapsPtr = pathMaps[:len(pathMaps)-1] } return pathMapsPtr } func getPathMapNames(pathMaps []n.ApplicationGatewayURLPathMap) string { var names []string for _, pathMap := range pathMaps { names = append(names, *pathMap.Name) } if len(names) == 0 { return "n/a" } return strings.Join(names, ", ") } func indexPathMapsByName(pathMaps []n.ApplicationGatewayURLPathMap) pathMapsByName { indexed := make(pathMapsByName) for _, pathMap := range pathMaps { indexed[urlPathMapName(*pathMap.Name)] = pathMap } return indexed } func (er ExistingResources) getURLPathMapsByName() pathMapsByName { if er.urlPathMapsByName != nil { return er.urlPathMapsByName } // Index URLPathMaps by the path map name urlpathMapsByName := make(pathMapsByName) for _, pm := range er.URLPathMaps { urlpathMapsByName[urlPathMapName(*pm.Name)] = pm } er.urlPathMapsByName = urlpathMapsByName return urlpathMapsByName }