pkg/appgw/rewrites.go (118 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 appgw
import (
"fmt"
"strings"
"github.com/Azure/application-gateway-kubernetes-ingress/pkg/annotations"
"github.com/Azure/application-gateway-kubernetes-ingress/pkg/apis/azureapplicationgatewayrewrite/v1beta1"
n "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2021-03-01/network"
"github.com/Azure/go-autorest/autorest/to"
"k8s.io/klog/v2"
)
// RewriteRuleSets builds the RewriteRuleSets part of the configBuilder
func (c *appGwConfigBuilder) RewriteRuleSets(cbCtx *ConfigBuilderContext) error {
if c.appGw.RewriteRuleSets == nil {
c.appGw.RewriteRuleSets = &[]n.ApplicationGatewayRewriteRuleSet{}
}
rewriteRuleSets := removeAGICGeneratedRewriteRuleSets(c.appGw.RewriteRuleSets)
rewriteRuleSets = append(rewriteRuleSets, c.getAGICRewriteRuleSets(cbCtx)...)
c.appGw.RewriteRuleSets = &rewriteRuleSets
return nil
}
// removeAGICGeneratedRewriteRuleSets removes the rewrite rule sets that were generated by AGIC
func removeAGICGeneratedRewriteRuleSets(currentRewriteRuleSets *[]n.ApplicationGatewayRewriteRuleSet) []n.ApplicationGatewayRewriteRuleSet {
if len(*currentRewriteRuleSets) == 0 {
return *currentRewriteRuleSets
}
var appGwRewriteRuleSets []n.ApplicationGatewayRewriteRuleSet
for _, rrs := range *currentRewriteRuleSets {
if rewriteRuleSetName := *(rrs.Name); !(strings.HasPrefix(rewriteRuleSetName, "crd-")) {
appGwRewriteRuleSets = append(appGwRewriteRuleSets, rrs)
}
}
return appGwRewriteRuleSets
}
// getAGICRewriteRuleSets returns all the rewrite rule sets that are referenced in atleast one of the ingress manifests
func (c appGwConfigBuilder) getAGICRewriteRuleSets(cbCtx *ConfigBuilderContext) []n.ApplicationGatewayRewriteRuleSet {
type rewriteCRDInfo struct {
ingressNamespace string
crdName string
}
uniqueRewriteRuleSetCR := map[string]rewriteCRDInfo{}
// insert all referenced rewrite rule sets into a map to avoid duplicates
for _, ingress := range cbCtx.IngressList {
klog.V(9).Infof("Looking for %s annotation in %s/%s", annotations.RewriteRuleSetCustomResourceKey, ingress.Namespace, ingress.Name)
rewriteRuleSetCRName, err := annotations.RewriteRuleSetCustomResource(ingress)
// if there is error fetching CR or if the value is "", move onto the next ingress
if err != nil || rewriteRuleSetCRName == "" {
continue
}
uniqueRewriteRuleSetCR[ingress.Namespace+"/"+rewriteRuleSetCRName] = rewriteCRDInfo{
ingressNamespace: ingress.Namespace,
crdName: rewriteRuleSetCRName,
}
}
var appGwRewriteRuleSet []n.ApplicationGatewayRewriteRuleSet
// get details of all the unique rewrite rule sets referenced in various ingress manifest
for _, rewriteRuleSetCRInfo := range uniqueRewriteRuleSetCR {
rewrite, err := c.k8sContext.GetRewriteRuleSetCustomResource(rewriteRuleSetCRInfo.ingressNamespace, rewriteRuleSetCRInfo.crdName)
if err != nil {
klog.Errorf("Error occured while fetching rewrite rule set custom resource named %s.", rewriteRuleSetCRInfo.crdName)
continue
}
appGwRewriteRuleSet = append(appGwRewriteRuleSet, c.makeRewrite(rewriteRuleSetCRInfo.ingressNamespace, rewriteRuleSetCRInfo.crdName, rewrite))
}
return appGwRewriteRuleSet
}
// c.makeRewrite converts *v1beta1.AzureApplicationGatewayRewrite to n.ApplicationGatewayRewriteRuleSet
func (c appGwConfigBuilder) makeRewrite(namespace string, rewriteRuleSetCRName string, rewrite *v1beta1.AzureApplicationGatewayRewrite) n.ApplicationGatewayRewriteRuleSet {
// prefix AGIC built rewriteRuleSets by crd- to help differentiate from user created rewrite rule sets
rewriteRuleSetCRName = fmt.Sprintf("crd-%s-%s", namespace, rewriteRuleSetCRName)
appGwRewriteRules := []n.ApplicationGatewayRewriteRule{}
for _, rr := range rewrite.Spec.RewriteRules {
appGwNewRewriteRule := n.ApplicationGatewayRewriteRule{
Name: to.StringPtr(rr.Name),
RuleSequence: to.Int32Ptr(int32(rr.RuleSequence)),
Conditions: makeConditions(rr.Conditions),
ActionSet: makeActionSet(rr.Actions),
}
appGwRewriteRules = append(appGwRewriteRules, appGwNewRewriteRule)
}
return n.ApplicationGatewayRewriteRuleSet{
Name: to.StringPtr(rewriteRuleSetCRName),
ID: to.StringPtr(c.appGwIdentifier.rewriteRuleSetID(rewriteRuleSetCRName)),
ApplicationGatewayRewriteRuleSetPropertiesFormat: &n.ApplicationGatewayRewriteRuleSetPropertiesFormat{
RewriteRules: &appGwRewriteRules,
},
}
}
// makeConditions converts []v1beta.Condition to *[]n.ApplicationGatewayRewriteRuleCondition
func makeConditions(apiConditions []v1beta1.Condition) *[]n.ApplicationGatewayRewriteRuleCondition {
appGwConditions := []n.ApplicationGatewayRewriteRuleCondition{}
for _, c := range apiConditions {
appGwConditions = append(appGwConditions, n.ApplicationGatewayRewriteRuleCondition{
IgnoreCase: to.BoolPtr(c.IgnoreCase),
Negate: to.BoolPtr(c.Negate),
Variable: to.StringPtr(c.Variable),
Pattern: to.StringPtr(c.Pattern),
})
}
return &appGwConditions
}
// makeActionSet converts v1beta1.Actions to *n.ApplicationGatewayRewriteRuleActionSet
func makeActionSet(apiActions v1beta1.Actions) *n.ApplicationGatewayRewriteRuleActionSet {
return &n.ApplicationGatewayRewriteRuleActionSet{
RequestHeaderConfigurations: makeHeaderConfigs(apiActions.RequestHeaderConfigurations),
ResponseHeaderConfigurations: makeHeaderConfigs(apiActions.ResponseHeaderConfigurations),
URLConfiguration: makeURLConfig(apiActions.UrlConfiguration),
}
}
// makeHeaderConfigs converts []v1beta1.HeaderConfiguration to *[]n.ApplicationGatewayHeaderConfiguration
func makeHeaderConfigs(apiHeaderConfigs []v1beta1.HeaderConfiguration) *[]n.ApplicationGatewayHeaderConfiguration {
appGwHeaderConfig := []n.ApplicationGatewayHeaderConfiguration{}
for _, hc := range apiHeaderConfigs {
appGwHeaderConfig = append(appGwHeaderConfig, n.ApplicationGatewayHeaderConfiguration{
HeaderName: to.StringPtr(hc.HeaderName),
HeaderValue: to.StringPtr(hc.HeaderValue),
})
}
return &appGwHeaderConfig
}
// makeURLConfig converts v1beta1.UrlConfiguration to *n.ApplicationGatewayURLConfiguration
func makeURLConfig(apiURLConfig *v1beta1.UrlConfiguration) *n.ApplicationGatewayURLConfiguration {
if apiURLConfig == nil {
return nil
}
return &n.ApplicationGatewayURLConfiguration{
ModifiedPath: to.StringPtr(apiURLConfig.ModifiedPath),
ModifiedQueryString: to.StringPtr(apiURLConfig.ModifiedQueryString),
Reroute: to.BoolPtr(apiURLConfig.Reroute),
}
}