From 4dc358a1c77c78d468ab15bc22de2a909388d250 Mon Sep 17 00:00:00 2001 From: Spencer Hance Date: Thu, 8 Aug 2019 21:16:26 -0700 Subject: [PATCH] Update e2e framework for ILB --- cmd/e2e-test/ilb_test.go | 123 +++++++++++++ pkg/fuzz/feature.go | 5 + pkg/fuzz/features/features.go | 1 + pkg/fuzz/features/ilb.go | 69 ++++++++ pkg/fuzz/features/neg.go | 44 +++++ pkg/fuzz/gcp.go | 316 +++++++++++++++++++++++++--------- pkg/fuzz/helpers.go | 9 + 7 files changed, 485 insertions(+), 82 deletions(-) create mode 100644 cmd/e2e-test/ilb_test.go create mode 100644 pkg/fuzz/features/ilb.go diff --git a/cmd/e2e-test/ilb_test.go b/cmd/e2e-test/ilb_test.go new file mode 100644 index 0000000000..d8489788bc --- /dev/null +++ b/cmd/e2e-test/ilb_test.go @@ -0,0 +1,123 @@ +/* +Copyright 2019 The Kubernetes Authors. + +Licensed 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 main + +import ( + "context" + "k8s.io/api/networking/v1beta1" + "k8s.io/apimachinery/pkg/util/intstr" + "k8s.io/ingress-gce/pkg/annotations" + "k8s.io/ingress-gce/pkg/e2e" + "k8s.io/ingress-gce/pkg/fuzz" + "k8s.io/ingress-gce/pkg/fuzz/features" + "testing" +) + +func TestILBBasic(t *testing.T) { + t.Parallel() + + port80 := intstr.FromInt(80) + + for _, tc := range []struct { + desc string + ing *v1beta1.Ingress + + numForwardingRules int + numBackendServices int + }{ + { + desc: "http ILB default backend", + ing: fuzz.NewIngressBuilder("", "ingress-1", ""). + DefaultBackend("service-1", port80). + ConfigureForILB(). + Build(), + numForwardingRules: 1, + numBackendServices: 1, + }, + { + desc: "http ILB one path", + ing: fuzz.NewIngressBuilder("", "ingress-1", ""). + AddPath("test.com", "/", "service-1", port80). + ConfigureForILB(). + Build(), + numForwardingRules: 1, + numBackendServices: 2, + }, + { + desc: "http ILB multiple paths", + ing: fuzz.NewIngressBuilder("", "ingress-1", ""). + AddPath("test.com", "/foo", "service-1", port80). + AddPath("test.com", "/bar", "service-1", port80). + ConfigureForILB(). + Build(), + numForwardingRules: 1, + numBackendServices: 2, + }, + } { + tc := tc // Capture tc as we are running this in parallel. + Framework.RunWithSandbox(tc.desc, t, func(t *testing.T, s *e2e.Sandbox) { + t.Parallel() + + ctx := context.Background() + + t.Logf("Ingress = %s", tc.ing.String()) + + negAnnotation := annotations.NegAnnotation{Ingress: true} + annotation := map[string]string{annotations.NEGAnnotationKey: negAnnotation.String()} + + _, err := e2e.CreateEchoService(s, "service-1", annotation) + if err != nil { + t.Fatalf("error creating echo service: %v", err) + } + t.Logf("Echo service created (%s/%s)", s.Namespace, "service-1") + + if _, err := Framework.Clientset.NetworkingV1beta1().Ingresses(s.Namespace).Create(tc.ing); err != nil { + t.Fatalf("error creating Ingress spec: %v", err) + } + t.Logf("Ingress created (%s/%s)", s.Namespace, tc.ing.Name) + + ing, err := e2e.WaitForIngress(s, tc.ing, nil) + if err != nil { + t.Fatalf("error waiting for Ingress to stabilize: %v", err) + } + t.Logf("GCLB resources createdd (%s/%s)", s.Namespace, tc.ing.Name) + + // Perform whitebox testing. + if len(ing.Status.LoadBalancer.Ingress) < 1 { + t.Fatalf("Ingress does not have an IP: %+v", ing.Status) + } + + vip := ing.Status.LoadBalancer.Ingress[0].IP + t.Logf("Ingress %s/%s VIP = %s", s.Namespace, tc.ing.Name, vip) + gclb, err := fuzz.GCLBForVIP(context.Background(), Framework.Cloud, vip, fuzz.FeatureValidators(features.All)) + if err != nil { + t.Fatalf("Error getting GCP resources for LB with IP = %q: %v", vip, err) + } + + if err = e2e.CheckGCLB(gclb, tc.numForwardingRules, tc.numBackendServices); err != nil { + t.Error(err) + } + + deleteOptions := &fuzz.GCLBDeleteOptions{ + SkipDefaultBackend: true, + } + if err := e2e.WaitForIngressDeletion(ctx, gclb, s, ing, deleteOptions); err != nil { + t.Errorf("e2e.WaitForIngressDeletion(..., %q, nil) = %v, want nil", ing.Name, err) + } + }) + } +} diff --git a/pkg/fuzz/feature.go b/pkg/fuzz/feature.go index 3c7bd37eac..8c867ea528 100644 --- a/pkg/fuzz/feature.go +++ b/pkg/fuzz/feature.go @@ -70,6 +70,7 @@ type FeatureValidator interface { CheckResponse(host, path string, resp *http.Response, body []byte) (CheckResponseAction, error) HasAlphaResource(resourceType string) bool + HasAlphaRegionResource(resourceType string) bool HasBetaResource(resourceType string) bool } @@ -97,6 +98,10 @@ func (*NullValidator) HasAlphaResource(resourceType string) bool { return false } +func (*NullValidator) HasAlphaRegionResource(resourceType string) bool { + return false +} + // HasBetaResource implements Feature. func (*NullValidator) HasBetaResource(resourceType string) bool { return false diff --git a/pkg/fuzz/features/features.go b/pkg/fuzz/features/features.go index cdb9410d40..9299ff0c86 100644 --- a/pkg/fuzz/features/features.go +++ b/pkg/fuzz/features/features.go @@ -31,4 +31,5 @@ var All = []fuzz.Feature{ Affinity, NEG, AppProtocol, + ILB, } diff --git a/pkg/fuzz/features/ilb.go b/pkg/fuzz/features/ilb.go new file mode 100644 index 0000000000..b5af39d3c7 --- /dev/null +++ b/pkg/fuzz/features/ilb.go @@ -0,0 +1,69 @@ +/* +Copyright 2019 The Kubernetes Authors. + +Licensed 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 features + +import ( + "k8s.io/api/networking/v1beta1" + "k8s.io/ingress-gce/pkg/fuzz" + "net/http" +) + +// ILB is an internal load balancer +var ILB = &ILBFeature{} + +// ILBFeature implements the associated feature +type ILBFeature struct{} + +// NewValidator implements fuzz.Feature. +func (*ILBFeature) NewValidator() fuzz.FeatureValidator { + return &ILBValidator{} +} + +// Name implements fuzz.Feature. +func (*ILBFeature) Name() string { + return "ILB" +} + +// ILBValidator is an example validator. +type ILBValidator struct { + fuzz.NullValidator + + ing *v1beta1.Ingress + env fuzz.ValidatorEnv +} + +// Name implements fuzz.FeatureValidator. +func (*ILBValidator) Name() string { + return "ILB" +} + +// ConfigureAttributes implements fuzz.FeatureValidator. +func (v *ILBValidator) ConfigureAttributes(env fuzz.ValidatorEnv, ing *v1beta1.Ingress, a *fuzz.IngressValidatorAttributes) error { + // Capture the env for use later in CheckResponse. + v.ing = ing + v.env = env + return nil +} + +// CheckResponse implements fuzz.FeatureValidator. +func (v *ILBValidator) CheckResponse(host, path string, resp *http.Response, body []byte) (fuzz.CheckResponseAction, error) { + return fuzz.CheckResponseContinue, nil +} + +func (v *ILBValidator) HasAlphaRegionResource(resourceType string) bool { + return true +} diff --git a/pkg/fuzz/features/neg.go b/pkg/fuzz/features/neg.go index 651e938897..a49b4478fa 100644 --- a/pkg/fuzz/features/neg.go +++ b/pkg/fuzz/features/neg.go @@ -23,6 +23,7 @@ package features import ( "context" "fmt" + "k8s.io/klog" "net/http" "strconv" "strings" @@ -92,6 +93,9 @@ func (v *negValidator) CheckResponse(host, path string, resp *http.Response, bod urlMapName := v.env.Namer().UrlMap(v.env.Namer().LoadBalancer(key)) if negEnabled { + if utils.IsGCEL7ILBIngress(v.ing) { + return fuzz.CheckResponseContinue, verifyNegRegionBackend(v.env, negName, negName, urlMapName) + } return fuzz.CheckResponseContinue, verifyNegBackend(v.env, negName, urlMapName) } else { return fuzz.CheckResponseContinue, verifyIgBackend(v.env, v.env.Namer().IGBackend(int64(svcPort.NodePort)), urlMapName) @@ -143,6 +147,7 @@ func verifyIgBackend(env fuzz.ValidatorEnv, bsName string, urlMapName string) er // verifyBackend verifies the backend service and check if the corresponding backend group has the keyword func verifyBackend(env fuzz.ValidatorEnv, bsName string, backendKeyword string, urlMapName string) error { + klog.V(3).Info("Verifying NEG Global Backend") ctx := context.Background() beService, err := env.Cloud().BackendServices().Get(ctx, &meta.Key{Name: bsName}) if err != nil { @@ -178,3 +183,42 @@ func verifyBackend(env fuzz.ValidatorEnv, bsName string, backendKeyword string, return fmt.Errorf("backend service %q is not used by UrlMap %q", bsName, urlMapName) } + +// verifyBackend verifies the backend service and check if the corresponding backend group has the keyword +func verifyNegRegionBackend(env fuzz.ValidatorEnv, bsName string, backendKeyword string, urlMapName string) error { + klog.V(3).Info("Verifying NEG Regional Backend") + ctx := context.Background() + beService, err := env.Cloud().AlphaRegionBackendServices().Get(ctx, &meta.Key{Name: bsName, Region: "us-central1"}) + if err != nil { + return err + } + + if beService == nil { + return fmt.Errorf("no backend service returned for name %s", bsName) + } + + for _, be := range beService.Backends { + if !strings.Contains(be.Group, backendKeyword) { + return fmt.Errorf("backend group %q of backend service %q does not contain keyword %q", be.Group, bsName, backendKeyword) + } + } + + // Examine if ingress url map is targeting the backend service + urlMap, err := env.Cloud().AlphaRegionUrlMaps().Get(ctx, &meta.Key{Name: urlMapName, Region: "us-central1"}) + if err != nil { + return err + } + + if strings.Contains(urlMap.DefaultService, beService.Name) { + return nil + } + for _, pathMatcher := range urlMap.PathMatchers { + for _, rule := range pathMatcher.PathRules { + if strings.Contains(rule.Service, beService.Name) { + return nil + } + } + } + + return fmt.Errorf("backend service %q is not used by UrlMap %q", bsName, urlMapName) +} diff --git a/pkg/fuzz/gcp.go b/pkg/fuzz/gcp.go index 3d2b22bfb6..f29c034f44 100644 --- a/pkg/fuzz/gcp.go +++ b/pkg/fuzz/gcp.go @@ -20,27 +20,30 @@ import ( "context" "errors" "fmt" + "k8s.io/ingress-gce/pkg/composite" + "k8s.io/ingress-gce/pkg/utils" "net/http" "strings" computealpha "google.golang.org/api/compute/v0.alpha" computebeta "google.golang.org/api/compute/v0.beta" - compute "google.golang.org/api/compute/v1" + "google.golang.org/api/compute/v1" "google.golang.org/api/googleapi" "k8s.io/klog" "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud" "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/filter" "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta" - - "k8s.io/ingress-gce/pkg/utils" ) const ( NegResourceType = "networkEndpointGroup" + defaultRegion = "us-central1" // TODO(shance): plumb this from GCE IgResourceType = "instanceGroup" ) +// TODO(shance): convert below to composite types and resourceVersions + // ForwardingRule is a union of the API version types. type ForwardingRule struct { GA *compute.ForwardingRule @@ -132,13 +135,13 @@ type GCLBDeleteOptions struct { // all of the associated resources no longer exist. func (g *GCLB) CheckResourceDeletion(ctx context.Context, c cloud.Cloud, options *GCLBDeleteOptions) error { var resources []meta.Key + var err error for k := range g.ForwardingRule { - var err error - if k.Region != "" { - _, err = c.ForwardingRules().Get(ctx, &k) + if k.Type() == meta.Regional { + _, err = c.AlphaForwardingRules().Get(ctx, &k) } else { - _, err = c.GlobalForwardingRules().Get(ctx, &k) + _, err = c.ForwardingRules().Get(ctx, &k) } if err != nil { if err.(*googleapi.Error) == nil || err.(*googleapi.Error).Code != http.StatusNotFound { @@ -149,7 +152,11 @@ func (g *GCLB) CheckResourceDeletion(ctx context.Context, c cloud.Cloud, options } } for k := range g.TargetHTTPProxy { - _, err := c.TargetHttpProxies().Get(ctx, &k) + if k.Type() == meta.Regional { + _, err = c.AlphaRegionTargetHttpProxies().Get(ctx, &k) + } else { + _, err = c.TargetHttpProxies().Get(ctx, &k) + } if err != nil { if err.(*googleapi.Error) == nil || err.(*googleapi.Error).Code != http.StatusNotFound { return fmt.Errorf("TargetHTTPProxy %s is not deleted/error to get: %s", k.Name, err) @@ -159,7 +166,11 @@ func (g *GCLB) CheckResourceDeletion(ctx context.Context, c cloud.Cloud, options } } for k := range g.TargetHTTPSProxy { - _, err := c.TargetHttpsProxies().Get(ctx, &k) + if k.Type() == meta.Regional { + _, err = c.AlphaRegionTargetHttpsProxies().Get(ctx, &k) + } else { + _, err = c.TargetHttpsProxies().Get(ctx, &k) + } if err != nil { if err.(*googleapi.Error) == nil || err.(*googleapi.Error).Code != http.StatusNotFound { return fmt.Errorf("TargetHTTPSProxy %s is not deleted/error to get: %s", k.Name, err) @@ -169,7 +180,11 @@ func (g *GCLB) CheckResourceDeletion(ctx context.Context, c cloud.Cloud, options } } for k := range g.URLMap { - _, err := c.UrlMaps().Get(ctx, &k) + if k.Type() == meta.Regional { + _, err = c.AlphaRegionUrlMaps().Get(ctx, &k) + } else { + _, err = c.UrlMaps().Get(ctx, &k) + } if err != nil { if err.(*googleapi.Error) == nil || err.(*googleapi.Error).Code != http.StatusNotFound { return fmt.Errorf("URLMap %s is not deleted/error to get: %s", k.Name, err) @@ -179,19 +194,36 @@ func (g *GCLB) CheckResourceDeletion(ctx context.Context, c cloud.Cloud, options } } for k := range g.BackendService { - bs, err := c.BackendServices().Get(ctx, &k) - if err != nil { - if err.(*googleapi.Error) == nil || err.(*googleapi.Error).Code != http.StatusNotFound { - return fmt.Errorf("BackendService %s is not deleted/error to get: %s", k.Name, err) + if k.Type() == meta.Regional { + bs, err := c.AlphaRegionBackendServices().Get(ctx, &k) + if err != nil { + if err.(*googleapi.Error) == nil || err.(*googleapi.Error).Code != http.StatusNotFound { + return err + } + } else { + if options != nil && options.SkipDefaultBackend { + desc := utils.DescriptionFromString(bs.Description) + if desc.ServiceName == "kube-system/default-http-backend" { + continue + } + } + resources = append(resources, k) } } else { - if options != nil && options.SkipDefaultBackend { - desc := utils.DescriptionFromString(bs.Description) - if desc.ServiceName == "kube-system/default-http-backend" { - continue + bs, err := c.BackendServices().Get(ctx, &k) + if err != nil { + if err.(*googleapi.Error) == nil || err.(*googleapi.Error).Code != http.StatusNotFound { + return err + } + } else { + if options != nil && options.SkipDefaultBackend { + desc := utils.DescriptionFromString(bs.Description) + if desc.ServiceName == "kube-system/default-http-backend" { + continue + } } + resources = append(resources, k) } - resources = append(resources, k) } } for k := range g.NetworkEndpointGroup { @@ -251,6 +283,15 @@ func hasAlphaResource(resourceType string, validators []FeatureValidator) bool { return false } +func hasAlphaRegionResource(resourceType string, validators []FeatureValidator) bool { + for _, val := range validators { + if val.HasAlphaRegionResource(resourceType) { + return true + } + } + return false +} + func hasBetaResource(resourceType string, validators []FeatureValidator) bool { for _, val := range validators { if val.HasBetaResource(resourceType) { @@ -271,19 +312,52 @@ func GCLBForVIP(ctx context.Context, c cloud.Cloud, vip string, validators []Fea return nil, err } - var gfrs []*compute.ForwardingRule + var forwardingRules []*composite.ForwardingRule for _, gfr := range allGFRs { if gfr.IPAddress == vip { - gfrs = append(gfrs, gfr) + compositeGfr, err := composite.ToForwardingRule(gfr) + if err != nil { + return nil, fmt.Errorf("Error converting forwarding rule to composite") + } + forwardingRules = append(forwardingRules, compositeGfr) + } + } + + if hasAlphaRegionResource("forwardingRule", validators) { + allRFRs, err := c.AlphaForwardingRules().List(ctx, defaultRegion, filter.None) + if err != nil { + klog.Warningf("Error listing forwarding rules: %v", err) + return nil, err + } + + for _, rfr := range allRFRs { + if rfr.IPAddress == vip { + compositeRfr, err := composite.ToForwardingRule(rfr) + if err != nil { + return nil, fmt.Errorf("Error converting forwarding rule to composite") + } + compositeRfr.Scope = meta.Regional + forwardingRules = append(forwardingRules, compositeRfr) + } } } var urlMapKey *meta.Key - for _, gfr := range gfrs { - frKey := meta.GlobalKey(gfr.Name) - gclb.ForwardingRule[*frKey] = &ForwardingRule{GA: gfr} + for _, fr := range forwardingRules { + frKey := meta.GlobalKey(fr.Name) + ga, err := fr.ToGA() + gclb.ForwardingRule[*frKey] = &ForwardingRule{GA: ga} if hasAlphaResource("forwardingRule", validators) { - fr, err := c.AlphaForwardingRules().Get(ctx, frKey) + fr, err := c.AlphaGlobalForwardingRules().Get(ctx, frKey) + if err != nil { + klog.Warningf("Error getting alpha forwarding rules: %v", err) + return nil, err + } + gclb.ForwardingRule[*frKey].Alpha = fr + } + if hasAlphaRegionResource("forwardingRule", validators) && fr.Scope == meta.Regional { + regionKey := meta.RegionalKey(fr.Name, defaultRegion) + fr, err := c.AlphaForwardingRules().Get(ctx, regionKey) if err != nil { klog.Warningf("Error getting alpha forwarding rules: %v", err) return nil, err @@ -295,27 +369,43 @@ func GCLBForVIP(ctx context.Context, c cloud.Cloud, vip string, validators []Fea } // ForwardingRule => TargetProxy - resID, err := cloud.ParseResourceURL(gfr.Target) + resID, err := cloud.ParseResourceURL(fr.Target) if err != nil { - klog.Warningf("Error parsing Target (%q): %v", gfr.Target, err) + klog.Warningf("Error parsing Target (%q): %v", fr.Target, err) return nil, err } + + var urlMapResID *cloud.ResourceID switch resID.Resource { case "targetHttpProxies": - p, err := c.TargetHttpProxies().Get(ctx, resID.Key) - if err != nil { - klog.Warningf("Error getting TargetHttpProxy %s: %v", resID.Key, err) - return nil, err - } - gclb.TargetHTTPProxy[*resID.Key] = &TargetHTTPProxy{GA: p} - if hasAlphaResource("targetHttpProxy", validators) || hasBetaResource("targetHttpProxy", validators) { + if hasAlphaRegionResource("targetHttpProxy", validators) && resID.Key.Type() == meta.Regional { + p, err := c.AlphaRegionTargetHttpProxies().Get(ctx, resID.Key) + if err != nil { + klog.Warningf("Error getting TargetHttpProxy %s: %v", resID.Key, err) + return nil, err + } + gclb.TargetHTTPProxy[*resID.Key] = &TargetHTTPProxy{Alpha: p} + + urlMapResID, err = cloud.ParseResourceURL(p.UrlMap) + if err != nil { + klog.Warningf("Error parsing urlmap URL (%q): %v", p.UrlMap, err) + return nil, err + } + } else if hasAlphaResource("targetHttpProxy", validators) || hasBetaResource("targetHttpProxy", validators) { return nil, errors.New("unsupported targetHttpProxy version") - } + } else { + p, err := c.TargetHttpProxies().Get(ctx, resID.Key) + if err != nil { + klog.Warningf("Error getting TargetHttpProxy %s: %v", resID.Key, err) + return nil, err + } + gclb.TargetHTTPProxy[*resID.Key] = &TargetHTTPProxy{GA: p} - urlMapResID, err := cloud.ParseResourceURL(p.UrlMap) - if err != nil { - klog.Warningf("Error parsing urlmap URL (%q): %v", p.UrlMap, err) - return nil, err + urlMapResID, err = cloud.ParseResourceURL(p.UrlMap) + if err != nil { + klog.Warningf("Error parsing urlmap URL (%q): %v", p.UrlMap, err) + return nil, err + } } if urlMapKey == nil { urlMapKey = urlMapResID.Key @@ -325,20 +415,33 @@ func GCLBForVIP(ctx context.Context, c cloud.Cloud, vip string, validators []Fea return nil, fmt.Errorf("targetHttpProxy references are not the same: %+v != %+v", *urlMapKey, *urlMapResID.Key) } case "targetHttpsProxies": - p, err := c.TargetHttpsProxies().Get(ctx, resID.Key) - if err != nil { - klog.Warningf("Error getting targetHttpsProxy (%s): %v", resID.Key, err) - return nil, err - } - gclb.TargetHTTPSProxy[*resID.Key] = &TargetHTTPSProxy{GA: p} - if hasAlphaResource("targetHttpsProxy", validators) || hasBetaResource("targetHttpsProxy", validators) { + if hasAlphaRegionResource("targetHttpsProxy", validators) && resID.Key.Type() == meta.Regional { + p, err := c.AlphaRegionTargetHttpsProxies().Get(ctx, resID.Key) + if err != nil { + klog.Warningf("Error getting targetHttpsProxy (%s): %v", resID.Key, err) + return nil, err + } + gclb.TargetHTTPSProxy[*resID.Key] = &TargetHTTPSProxy{Alpha: p} + urlMapResID, err = cloud.ParseResourceURL(p.UrlMap) + if err != nil { + klog.Warningf("Error parsing urlmap URL (%q): %v", p.UrlMap, err) + return nil, err + } + } else if hasAlphaResource("targetHttpsProxy", validators) || hasBetaResource("targetHttpsProxy", validators) { return nil, errors.New("unsupported targetHttpsProxy version") - } + } else { + p, err := c.TargetHttpsProxies().Get(ctx, resID.Key) + if err != nil { + klog.Warningf("Error getting targetHttpsProxy (%s): %v", resID.Key, err) + return nil, err + } + gclb.TargetHTTPSProxy[*resID.Key] = &TargetHTTPSProxy{GA: p} - urlMapResID, err := cloud.ParseResourceURL(p.UrlMap) - if err != nil { - klog.Warningf("Error parsing urlmap URL (%q): %v", p.UrlMap, err) - return nil, err + urlMapResID, err = cloud.ParseResourceURL(p.UrlMap) + if err != nil { + klog.Warningf("Error parsing urlmap URL (%q): %v", p.UrlMap, err) + return nil, err + } } if urlMapKey == nil { urlMapKey = urlMapResID.Key @@ -348,65 +451,102 @@ func GCLBForVIP(ctx context.Context, c cloud.Cloud, vip string, validators []Fea return nil, fmt.Errorf("targetHttpsProxy references are not the same: %+v != %+v", *urlMapKey, *urlMapResID.Key) } default: - klog.Errorf("Unhandled resource: %q, grf = %+v", resID.Resource, gfr) + klog.Errorf("Unhandled resource: %q, grf = %+v", resID.Resource, fr) return nil, fmt.Errorf("unhandled resource %q", resID.Resource) } } // TargetProxy => URLMap - urlMap, err := c.UrlMaps().Get(ctx, urlMapKey) - if err != nil { - return nil, err - } - gclb.URLMap[*urlMapKey] = &URLMap{GA: urlMap} + var bsKeys []*meta.Key if hasAlphaResource("urlMap", validators) || hasBetaResource("urlMap", validators) { return nil, errors.New("unsupported urlMap version") - } - - // URLMap => BackendService(s) - var bsKeys []*meta.Key - resID, err := cloud.ParseResourceURL(urlMap.DefaultService) - if err != nil { - return nil, err - } - bsKeys = append(bsKeys, resID.Key) - - for _, pm := range urlMap.PathMatchers { - resID, err := cloud.ParseResourceURL(pm.DefaultService) + } else if hasAlphaRegionResource("urlMap", validators) && urlMapKey.Type() == meta.Regional { + urlMap, err := c.AlphaRegionUrlMaps().Get(ctx, urlMapKey) + if err != nil { + klog.Warningf("Error getting alpha region Url Maps: %v", err) + return nil, err + } + gclb.URLMap[*urlMapKey] = &URLMap{Alpha: urlMap} + resID, err := cloud.ParseResourceURL(urlMap.DefaultService) if err != nil { + klog.Warningf("Error parsing resource URL: %v", err) return nil, err } bsKeys = append(bsKeys, resID.Key) - for _, pr := range pm.PathRules { - resID, err := cloud.ParseResourceURL(pr.Service) + // URLMap => BackendService(s) + for _, pm := range urlMap.PathMatchers { + resID, err := cloud.ParseResourceURL(pm.DefaultService) if err != nil { + klog.Warningf("Error parsing resource URL: %v", err) return nil, err } bsKeys = append(bsKeys, resID.Key) - } - } - for _, bsKey := range bsKeys { - bs, err := c.BackendServices().Get(ctx, bsKey) + for _, pr := range pm.PathRules { + resID, err := cloud.ParseResourceURL(pr.Service) + if err != nil { + klog.Warningf("Error parsing resource URL: %v", err) + return nil, err + } + bsKeys = append(bsKeys, resID.Key) + } + } + } else { + urlMap, err := c.UrlMaps().Get(ctx, urlMapKey) + if err != nil { + klog.Warningf("Error getting URL map: %v", err) + return nil, err + } + gclb.URLMap[*urlMapKey] = &URLMap{GA: urlMap} + resID, err := cloud.ParseResourceURL(urlMap.DefaultService) if err != nil { + klog.Warningf("Error parsing resource URL: %v", err) return nil, err } - gclb.BackendService[*bsKey] = &BackendService{GA: bs} + bsKeys = append(bsKeys, resID.Key) - if hasAlphaResource("backendService", validators) { - bs, err := c.AlphaBackendServices().Get(ctx, bsKey) + // URLMap => BackendService(s) + for _, pm := range urlMap.PathMatchers { + resID, err := cloud.ParseResourceURL(pm.DefaultService) if err != nil { + klog.Warningf("Error parsing resource URL: %v", err) return nil, err } - gclb.BackendService[*bsKey].Alpha = bs + bsKeys = append(bsKeys, resID.Key) + + for _, pr := range pm.PathRules { + resID, err := cloud.ParseResourceURL(pr.Service) + if err != nil { + klog.Warningf("Error parsing resource URL: %v", err) + return nil, err + } + bsKeys = append(bsKeys, resID.Key) + } } - if hasBetaResource("backendService", validators) { + } + + for _, bsKey := range bsKeys { + if hasAlphaRegionResource("backendService", validators) && bsKey.Type() == meta.Regional { + bs, err := c.AlphaRegionBackendServices().Get(ctx, bsKey) + if err != nil { + klog.Warningf("Error getting alpha region backend service: %v", err) + return nil, err + } + gclb.BackendService[*bsKey] = &BackendService{Alpha: bs} + } else if hasBetaResource("backendService", validators) { bs, err := c.BetaBackendServices().Get(ctx, bsKey) + if err != nil { + klog.Warningf("Error getting beta backend service: %v", err) + return nil, err + } + gclb.BackendService[*bsKey] = &BackendService{Beta: bs} + } else { + bs, err := c.BackendServices().Get(ctx, bsKey) if err != nil { return nil, err } - gclb.BackendService[*bsKey].Beta = bs + gclb.BackendService[*bsKey] = &BackendService{GA: bs} } } @@ -415,9 +555,19 @@ func GCLBForVIP(ctx context.Context, c cloud.Cloud, vip string, validators []Fea // Fetch NEG Backends for _, bsKey := range bsKeys { beGroups := []string{} - if hasAlphaResource("backendService", validators) { + if hasAlphaRegionResource("backendService", validators) && bsKey.Type() == meta.Regional { + bs, err := c.AlphaRegionBackendServices().Get(ctx, bsKey) + if err != nil { + klog.Warningf("Error getting alpha region backend service: %v", err) + return nil, err + } + for _, be := range bs.Backends { + beGroups = append(beGroups, be.Group) + } + } else if hasAlphaResource("backendService", validators) { bs, err := c.AlphaBackendServices().Get(ctx, bsKey) if err != nil { + klog.Warningf("Error getting alpha backend service: %v", err) return nil, err } for _, be := range bs.Backends { @@ -426,6 +576,7 @@ func GCLBForVIP(ctx context.Context, c cloud.Cloud, vip string, validators []Fea } else { bs, err := c.BetaBackendServices().Get(ctx, bsKey) if err != nil { + klog.Warningf("Error getting backend service: %v", err) return nil, err } for _, be := range bs.Backends { @@ -461,6 +612,7 @@ func GCLBForVIP(ctx context.Context, c cloud.Cloud, vip string, validators []Fea if hasAlphaResource(NegResourceType, validators) { neg, err := c.AlphaNetworkEndpointGroups().Get(ctx, negKey) if err != nil { + klog.Warningf("Error getting alpha network endpoint groups: %v", err) return nil, err } gclb.NetworkEndpointGroup[*negKey].Alpha = neg diff --git a/pkg/fuzz/helpers.go b/pkg/fuzz/helpers.go index 339d297bc8..b783307714 100644 --- a/pkg/fuzz/helpers.go +++ b/pkg/fuzz/helpers.go @@ -258,6 +258,15 @@ func (i *IngressBuilder) AddStaticIP(name string) *IngressBuilder { return i } +// Configure for ILB adds the ILB ingress class annotation +func (i *IngressBuilder) ConfigureForILB() *IngressBuilder { + if i.ing.Annotations == nil { + i.ing.Annotations = make(map[string]string) + } + i.ing.Annotations[annotations.IngressClassKey] = annotations.GceL7ILBIngressClass + return i +} + // BackendConfigBuilder is syntactic sugar for creating BackendConfig specs for testing // purposes. //