diff --git a/cmd/e2e/README.md b/cmd/e2e/README.md index 428b2ad1..057b748e 100644 --- a/cmd/e2e/README.md +++ b/cmd/e2e/README.md @@ -33,9 +33,9 @@ kubectl delete namespace foo; kubectl create namespace foo make ./build/stackset-controller --apiserver=http://127.0.0.1:8001 \ --enable-configmap-support --enable-secret-support --enable-routegroup-support \ ---enable-traffic-segments --annotated-traffic-segments \ +--enable-traffic-segments --controller-id=foo \ --sync-ingress-annotation=example.org/i-haz-synchronize \ ---sync-ingress-annotation=teapot.org/the-best --controller-id=foo \ +--sync-ingress-annotation=teapot.org/the-best \ --cluster-domain=${CLUSTER_DOMAIN} --cluster-domain=${CLUSTER_DOMAIN_INTERNAL} ``` 4. rebuild e2e test and run e2e tests in `foo` namespace diff --git a/cmd/e2e/annotations_sync_test.go b/cmd/e2e/annotations_sync_test.go index b16b39f1..7104aa6f 100644 --- a/cmd/e2e/annotations_sync_test.go +++ b/cmd/e2e/annotations_sync_test.go @@ -134,16 +134,10 @@ func TestSyncAnnotationsPropagateToSegments(t *testing.T) { } require.NoError(t, err) - _, err = waitForIngress( - t, - stacksetName+"-"+version+"-traffic-segment", - ) + _, err = waitForIngressSegment(t, stacksetName, version) require.NoError(t, err) - _, err = waitForRouteGroup( - t, - stacksetName+"-"+version+"-traffic-segment", - ) + _, err = waitForRouteGroupSegment(t, stacksetName, version) require.NoError(t, err) } @@ -152,10 +146,7 @@ func TestSyncAnnotationsPropagateToSegments(t *testing.T) { for i := 0; i < len(tc.annotationsIng); i++ { version := fmt.Sprintf("v%d", i) - ingress, err := waitForIngress( - t, - stacksetName+"-"+version+"-traffic-segment", - ) + ingress, err := waitForIngressSegment(t, stacksetName, version) require.NoError(t, err) delete( @@ -176,9 +167,10 @@ func TestSyncAnnotationsPropagateToSegments(t *testing.T) { ) } - routeGroup, err := waitForRouteGroup( + routeGroup, err := waitForRouteGroupSegment( t, - stacksetName+"-"+version+"-traffic-segment", + stacksetName, + version, ) require.NoError(t, err) diff --git a/cmd/e2e/basic_test.go b/cmd/e2e/basic_test.go index 079f334f..98c4a9ad 100644 --- a/cmd/e2e/basic_test.go +++ b/cmd/e2e/basic_test.go @@ -4,7 +4,6 @@ import ( "fmt" "slices" "sort" - "strings" "testing" "github.com/stretchr/testify/assert" @@ -419,7 +418,11 @@ func verifyStackSegments( resourceName := stack.Name + core.SegmentSuffix if stack.Spec.Ingress != nil { - segmentIngress, err := waitForIngress(t, resourceName) + segmentIngress, err := waitForIngressSegment( + t, + stacksetName, + currentVersion, + ) require.NoError(t, err) require.Contains( t, @@ -553,124 +556,6 @@ func verifyStacksetExternalIngress(t *testing.T, stacksetName string, stacksetSp require.NoError(t, err) } -func verifyStacksetIngress(t *testing.T, stacksetName string, stacksetSpec zv1.StackSetSpec, stackWeights map[string]float64, annotations map[string]string) { - stacksetResourceLabels := map[string]string{stacksetHeritageLabelKey: stacksetName} - - expectedWeights := make(map[string]float64) - - var expectedPaths []v1.HTTPIngressPath - for stack, weight := range stackWeights { - serviceName := fmt.Sprintf("%s-%s", stacksetName, stack) - expectedWeights[serviceName] = weight - - if weight == 0.0 { - continue - } - - expectedPaths = append(expectedPaths, v1.HTTPIngressPath{ - PathType: &pathType, - Backend: v1.IngressBackend{ - Service: &v1.IngressServiceBackend{ - Name: serviceName, - Port: v1.ServiceBackendPort{ - Number: 80, - }, - }, - }, - }) - sort.Slice(expectedPaths, func(i, j int) bool { - return strings.Compare(expectedPaths[i].Backend.Service.Name, expectedPaths[j].Backend.Service.Name) < 0 - }) - } - - globalIngress, err := waitForIngress(t, stacksetName) - require.NoError(t, err) - require.EqualValues(t, stacksetResourceLabels, globalIngress.Labels) - for k, v := range annotations { - require.Contains(t, globalIngress.Annotations, k) - require.Equal(t, v, globalIngress.Annotations[k]) - } - globalIngressRules := make([]v1.IngressRule, 0, len(stacksetSpec.Ingress.Hosts)) - for _, host := range stacksetSpec.Ingress.Hosts { - globalIngressRules = append(globalIngressRules, v1.IngressRule{ - Host: host, - IngressRuleValue: v1.IngressRuleValue{ - HTTP: &v1.HTTPIngressRuleValue{ - Paths: expectedPaths, - }, - }, - }) - } - // sort rules by hostname for a stable order - sort.Slice(globalIngressRules, func(i, j int) bool { - return globalIngressRules[i].Host < globalIngressRules[j].Host - }) - require.EqualValues(t, globalIngressRules, globalIngress.Spec.Rules) - - err = trafficWeightsUpdatedStackset(t, stacksetName, weightKindDesired, expectedWeights, nil).await() - require.NoError(t, err) - err = trafficWeightsUpdatedStackset(t, stacksetName, weightKindActual, expectedWeights, nil).await() - require.NoError(t, err) -} - -func verifyStacksetRouteGroup(t *testing.T, stacksetName string, stacksetSpec zv1.StackSetSpec, stackWeights map[string]float64, annotations map[string]string) { - stacksetResourceLabels := map[string]string{stacksetHeritageLabelKey: stacksetName} - - expectedWeights := make(map[string]float64) - - var expectedDefaultBackends []rgv1.RouteGroupBackendReference - var expectedBackends []rgv1.RouteGroupBackend - for stack, weight := range stackWeights { - serviceName := fmt.Sprintf("%s-%s", stacksetName, stack) - expectedWeights[serviceName] = weight - - expectedBackends = append(expectedBackends, rgv1.RouteGroupBackend{ - Name: serviceName, - Type: rgv1.ServiceRouteGroupBackend, - ServiceName: serviceName, - ServicePort: 80, - }) - - if weight == 0.0 { - continue - } - - expectedDefaultBackends = append(expectedDefaultBackends, rgv1.RouteGroupBackendReference{ - BackendName: serviceName, - Weight: int(weight), - }) - } - - sort.Slice(expectedDefaultBackends, func(i, j int) bool { - return strings.Compare(expectedDefaultBackends[i].BackendName, expectedDefaultBackends[j].BackendName) < 0 - }) - sort.Slice(expectedBackends, func(i, j int) bool { - return strings.Compare(expectedBackends[i].Name, expectedBackends[j].Name) < 0 - }) - - globalRouteGroup, err := waitForRouteGroup(t, stacksetName) - require.NoError(t, err) - require.EqualValues(t, stacksetResourceLabels, globalRouteGroup.Labels) - for k, v := range annotations { - require.Contains(t, globalRouteGroup.Annotations, k) - require.Equal(t, v, globalRouteGroup.Annotations[k]) - } - - sort.Slice(globalRouteGroup.Spec.DefaultBackends, func(i, j int) bool { - return strings.Compare(globalRouteGroup.Spec.DefaultBackends[i].BackendName, globalRouteGroup.Spec.DefaultBackends[j].BackendName) < 0 - }) - sort.Slice(globalRouteGroup.Spec.Backends, func(i, j int) bool { - return strings.Compare(globalRouteGroup.Spec.Backends[i].Name, globalRouteGroup.Spec.Backends[j].Name) < 0 - }) - require.EqualValues(t, expectedDefaultBackends, globalRouteGroup.Spec.DefaultBackends) - require.EqualValues(t, expectedBackends, globalRouteGroup.Spec.Backends) - - err = trafficWeightsUpdatedStackset(t, stacksetName, weightKindDesired, expectedWeights, nil).await() - require.NoError(t, err) - err = trafficWeightsUpdatedStackset(t, stacksetName, weightKindActual, expectedWeights, nil).await() - require.NoError(t, err) -} - func testStacksetCreate( t *testing.T, testName string, @@ -685,106 +570,76 @@ func testStacksetCreate( ) { t.Parallel() - for _, ingType := range []string{"central", "segment"} { - stacksetName := fmt.Sprintf("stackset-create-%s-%s", ingType, testName) - stackVersion := "v1" - stacksetSpecFactory := NewTestStacksetSpecFactory(stacksetName) - if configmapRef { - configMapName := fmt.Sprintf("%s-%s-configmap", stacksetName, stackVersion) - createConfigMap(t, configMapName) - stacksetSpecFactory.AddReferencedConfigMap(configMapName) - } - if secretRef { - secretName := fmt.Sprintf("%s-%s-secret", stacksetName, stackVersion) - createSecret(t, secretName) - stacksetSpecFactory.AddReferencedSecret(secretName) - } - if hpa { - stacksetSpecFactory.Autoscaler( - 1, - 3, - []zv1.AutoscalerMetrics{makeCPUAutoscalerMetrics(50)}, - ) - } - if ingress { - stacksetSpecFactory.Ingress() - } - if routegroup { - stacksetSpecFactory.RouteGroup() - } - if externalIngress { - stacksetSpecFactory.ExternalIngress() - } - if updateStrategy { - stacksetSpecFactory.UpdateMaxSurge(10).UpdateMaxUnavailable(100) - } - if len(subResourceAnnotations) > 0 { - stacksetSpecFactory.SubResourceAnnotations(subResourceAnnotations) - } - stacksetSpec := stacksetSpecFactory.Create(t, stackVersion) - - var err error - switch ingType { - case "segment": - err = createStackSetWithAnnotations( - stacksetName, - 0, - stacksetSpec, - map[string]string{ - controller.TrafficSegmentsAnnotationKey: "true", - }, - ) - default: - err = createStackSet(stacksetName, 0, stacksetSpec) - } - require.NoError(t, err) + stacksetName := fmt.Sprintf("stackset-create-%s", testName) + stackVersion := "v1" + stacksetSpecFactory := NewTestStacksetSpecFactory(stacksetName) + if configmapRef { + configMapName := fmt.Sprintf("%s-%s-configmap", stacksetName, stackVersion) + createConfigMap(t, configMapName) + stacksetSpecFactory.AddReferencedConfigMap(configMapName) + } + if secretRef { + secretName := fmt.Sprintf("%s-%s-secret", stacksetName, stackVersion) + createSecret(t, secretName) + stacksetSpecFactory.AddReferencedSecret(secretName) + } + if hpa { + stacksetSpecFactory.Autoscaler( + 1, + 3, + []zv1.AutoscalerMetrics{makeCPUAutoscalerMetrics(50)}, + ) + } + if ingress { + stacksetSpecFactory.Ingress() + } + if routegroup { + stacksetSpecFactory.RouteGroup() + } + if externalIngress { + stacksetSpecFactory.ExternalIngress() + } + if updateStrategy { + stacksetSpecFactory.UpdateMaxSurge(10).UpdateMaxUnavailable(100) + } + if len(subResourceAnnotations) > 0 { + stacksetSpecFactory.SubResourceAnnotations(subResourceAnnotations) + } + stacksetSpec := stacksetSpecFactory.Create(t, stackVersion) + + err := createStackSetWithAnnotations( + stacksetName, + 0, + stacksetSpec, + map[string]string{ + controller.TrafficSegmentsAnnotationKey: "true", + }, + ) + require.NoError(t, err) + + verifyStack( + t, + stacksetName, + stackVersion, + stacksetSpec, + subResourceAnnotations, + ) + + verifyStackSegments( + t, + stacksetName, + stackVersion, + "TrafficSegment(0.00, 1.00)", + subResourceAnnotations, + ) - verifyStack( + if externalIngress { + verifyStacksetExternalIngress( t, stacksetName, - stackVersion, stacksetSpec, - subResourceAnnotations, + map[string]float64{stackVersion: 100}, ) - - switch ingType { - case "segment": - verifyStackSegments( - t, - stacksetName, - stackVersion, - "TrafficSegment(0.00, 1.00)", - subResourceAnnotations, - ) - default: - if ingress { - verifyStacksetIngress( - t, - stacksetName, - stacksetSpec, - map[string]float64{stackVersion: 100}, - subResourceAnnotations, - ) - } - if routegroup { - verifyStacksetRouteGroup( - t, - stacksetName, - stacksetSpec, - map[string]float64{stackVersion: 100}, - subResourceAnnotations, - ) - } - } - - if externalIngress { - verifyStacksetExternalIngress( - t, - stacksetName, - stacksetSpec, - map[string]float64{stackVersion: 100}, - ) - } } } @@ -804,249 +659,157 @@ func testStacksetUpdate( ) { t.Parallel() - for _, ingType := range []string{"central", "segment"} { - var actualTraffic []*zv1.ActualTraffic + var actualTraffic []*zv1.ActualTraffic - stacksetName := fmt.Sprintf("stackset-update-%s-%s", ingType, testName) - initialVersion := "v1" - stacksetSpecFactory := NewTestStacksetSpecFactory(stacksetName) - if oldHpa { - stacksetSpecFactory.Autoscaler(1, 3, []zv1.AutoscalerMetrics{ - makeCPUAutoscalerMetrics(50), - }) - } - if oldIngress { - stacksetSpecFactory.Ingress() - } - if oldRouteGroup { - stacksetSpecFactory.RouteGroup() - } - if oldExternalIngress { - stacksetSpecFactory.ExternalIngress() - } + stacksetName := fmt.Sprintf("stackset-update-%s", testName) + initialVersion := "v1" + stacksetSpecFactory := NewTestStacksetSpecFactory(stacksetName) + if oldHpa { + stacksetSpecFactory.Autoscaler(1, 3, []zv1.AutoscalerMetrics{ + makeCPUAutoscalerMetrics(50), + }) + } + if oldIngress { + stacksetSpecFactory.Ingress() + } + if oldRouteGroup { + stacksetSpecFactory.RouteGroup() + } + if oldExternalIngress { + stacksetSpecFactory.ExternalIngress() + } - if oldIngress || oldRouteGroup || oldExternalIngress { - actualTraffic = []*zv1.ActualTraffic{ - { - StackName: stacksetName + "-" + initialVersion, - ServiceName: stacksetName + "-" + initialVersion, - ServicePort: intstr.FromInt(80), - Weight: 100.0, - }, - } - } - if len(oldSubResourceAnnotations) > 0 { - stacksetSpecFactory.SubResourceAnnotations( - oldSubResourceAnnotations, - ) - } - stacksetSpec := stacksetSpecFactory.Create(t, initialVersion) - - var err error - switch ingType { - case "segment": - err = createStackSetWithAnnotations( - stacksetName, - 0, - stacksetSpec, - map[string]string{ - controller.TrafficSegmentsAnnotationKey: "true", - }, - ) - default: - err = createStackSet(stacksetName, 0, stacksetSpec) + if oldIngress || oldRouteGroup || oldExternalIngress { + actualTraffic = []*zv1.ActualTraffic{ + { + StackName: stacksetName + "-" + initialVersion, + ServiceName: stacksetName + "-" + initialVersion, + ServicePort: intstr.FromInt(80), + Weight: 100.0, + }, } - require.NoError(t, err) + } + if len(oldSubResourceAnnotations) > 0 { + stacksetSpecFactory.SubResourceAnnotations( + oldSubResourceAnnotations, + ) + } + stacksetSpec := stacksetSpecFactory.Create(t, initialVersion) + + err := createStackSetWithAnnotations( + stacksetName, + 0, + stacksetSpec, + map[string]string{ + controller.TrafficSegmentsAnnotationKey: "true", + }, + ) + require.NoError(t, err) + + verifyStack( + t, + stacksetName, + initialVersion, + stacksetSpec, + oldSubResourceAnnotations, + ) + + verifyStackSegments( + t, + stacksetName, + initialVersion, + "TrafficSegment(0.00, 1.00)", + oldSubResourceAnnotations, + ) - verifyStack( + if oldExternalIngress { + verifyStacksetExternalIngress( t, stacksetName, - initialVersion, stacksetSpec, - oldSubResourceAnnotations, + map[string]float64{initialVersion: 100}, ) + } - switch ingType { - case "segment": - verifyStackSegments( - t, - stacksetName, - initialVersion, - "TrafficSegment(0.00, 1.00)", - oldSubResourceAnnotations, - ) - default: - if oldIngress { - verifyStacksetIngress( - t, - stacksetName, - stacksetSpec, - map[string]float64{initialVersion: 100}, - oldSubResourceAnnotations, - ) - } - if oldRouteGroup { - verifyStacksetRouteGroup( - t, - stacksetName, - stacksetSpec, - map[string]float64{initialVersion: 100}, - oldSubResourceAnnotations, - ) - } - } - - if oldExternalIngress { - verifyStacksetExternalIngress( - t, - stacksetName, - stacksetSpec, - map[string]float64{initialVersion: 100}, - ) - } + verifyStackSetStatus(t, stacksetName, expectedStackSetStatus{ + observedStackVersion: initialVersion, + actualTraffic: actualTraffic, + }) - verifyStackSetStatus(t, stacksetName, expectedStackSetStatus{ - observedStackVersion: initialVersion, - actualTraffic: actualTraffic, + stacksetSpecFactory = NewTestStacksetSpecFactory(stacksetName) + updatedVersion := "v2" + if newHpa { + stacksetSpecFactory.Autoscaler(1, 3, []zv1.AutoscalerMetrics{ + makeCPUAutoscalerMetrics(50), }) + } + if newIngress { + stacksetSpecFactory.Ingress() + } else if newRouteGroup { + stacksetSpecFactory.RouteGroup() + } else if newExternalIngress { + stacksetSpecFactory.ExternalIngress() + } else if oldIngress || oldRouteGroup || oldExternalIngress { + actualTraffic = nil + } - stacksetSpecFactory = NewTestStacksetSpecFactory(stacksetName) - updatedVersion := "v2" - if newHpa { - stacksetSpecFactory.Autoscaler(1, 3, []zv1.AutoscalerMetrics{ - makeCPUAutoscalerMetrics(50), - }) - } - if newIngress { - stacksetSpecFactory.Ingress() - } else if newRouteGroup { - stacksetSpecFactory.RouteGroup() - } else if newExternalIngress { - stacksetSpecFactory.ExternalIngress() - } else if oldIngress || oldRouteGroup || oldExternalIngress { - actualTraffic = nil + if newIngress || newRouteGroup || newExternalIngress { + actualTraffic = []*zv1.ActualTraffic{ + { + StackName: stacksetName + "-" + initialVersion, + ServiceName: stacksetName + "-" + initialVersion, + ServicePort: intstr.FromInt(80), + Weight: 100.0, + }, + { + StackName: stacksetName + "-" + updatedVersion, + ServiceName: stacksetName + "-" + updatedVersion, + ServicePort: intstr.FromInt(80), + Weight: 0.0, + }, } + } - if newIngress || newRouteGroup || newExternalIngress { - actualTraffic = []*zv1.ActualTraffic{ - { - StackName: stacksetName + "-" + initialVersion, - ServiceName: stacksetName + "-" + initialVersion, - ServicePort: intstr.FromInt(80), - Weight: 100.0, - }, - { - StackName: stacksetName + "-" + updatedVersion, - ServiceName: stacksetName + "-" + updatedVersion, - ServicePort: intstr.FromInt(80), - Weight: 0.0, - }, - } - } + if len(newSubResourceAnnotations) > 0 { + stacksetSpecFactory.SubResourceAnnotations( + newSubResourceAnnotations, + ) + } - if len(newSubResourceAnnotations) > 0 { - stacksetSpecFactory.SubResourceAnnotations( - newSubResourceAnnotations, - ) - } + updatedSpec := stacksetSpecFactory.Create(t, updatedVersion) + err = updateStackset(stacksetName, updatedSpec) + require.NoError(t, err) - updatedSpec := stacksetSpecFactory.Create(t, updatedVersion) - err = updateStackset(stacksetName, updatedSpec) - require.NoError(t, err) + verifyStack( + t, + stacksetName, + updatedVersion, + updatedSpec, + newSubResourceAnnotations, + ) + verifyStackSetStatus(t, stacksetName, expectedStackSetStatus{ + observedStackVersion: updatedVersion, + actualTraffic: actualTraffic, + }) - verifyStack( - t, - stacksetName, - updatedVersion, - updatedSpec, - newSubResourceAnnotations, - ) + verifyStackSegments( + t, + stacksetName, + updatedVersion, + "TrafficSegment(0.00, 0.00)", + newSubResourceAnnotations, + ) + + if newExternalIngress { verifyStackSetStatus(t, stacksetName, expectedStackSetStatus{ observedStackVersion: updatedVersion, actualTraffic: actualTraffic, }) - - switch ingType { - case "segment": - verifyStackSegments( - t, - stacksetName, - updatedVersion, - "TrafficSegment(0.00, 0.00)", - newSubResourceAnnotations, - ) - default: - if newIngress { - verifyStacksetIngress( - t, - stacksetName, - updatedSpec, - map[string]float64{initialVersion: 100, updatedVersion: 0}, - newSubResourceAnnotations, - ) - // no traffic switch here - verifyStackSetStatus(t, stacksetName, expectedStackSetStatus{ - observedStackVersion: updatedVersion, - actualTraffic: actualTraffic, - }) - } else if oldIngress { - err = resourceDeleted( - t, - "ingress", - stacksetName, - ingressInterface(), - ).await() - require.NoError(t, err) - verifyStackSetStatus( - t, - stacksetName, - expectedStackSetStatus{ - observedStackVersion: updatedVersion, - actualTraffic: nil, - }, - ) - } else if newRouteGroup { - verifyStacksetRouteGroup( - t, - stacksetName, - updatedSpec, - map[string]float64{ - initialVersion: 100, - updatedVersion: 0, - }, - newSubResourceAnnotations, - ) - // no traffic switch here - verifyStackSetStatus(t, stacksetName, expectedStackSetStatus{ - observedStackVersion: updatedVersion, - actualTraffic: actualTraffic, - }) - } else if oldRouteGroup { - err = resourceDeleted( - t, - "routegroup", - stacksetName, - routegroupInterface(), - ).await() - require.NoError(t, err) - verifyStackSetStatus(t, stacksetName, expectedStackSetStatus{ - observedStackVersion: updatedVersion, - actualTraffic: nil, - }) - } - } - - if newExternalIngress { - verifyStackSetStatus(t, stacksetName, expectedStackSetStatus{ - observedStackVersion: updatedVersion, - actualTraffic: actualTraffic, - }) - } else if oldExternalIngress { - verifyStackSetStatus(t, stacksetName, expectedStackSetStatus{ - observedStackVersion: updatedVersion, - actualTraffic: nil, - }) - } + } else if oldExternalIngress { + verifyStackSetStatus(t, stacksetName, expectedStackSetStatus{ + observedStackVersion: updatedVersion, + actualTraffic: nil, + }) } } diff --git a/cmd/e2e/broken_stack_test.go b/cmd/e2e/broken_stack_test.go index 94652a68..b8e2a6e5 100644 --- a/cmd/e2e/broken_stack_test.go +++ b/cmd/e2e/broken_stack_test.go @@ -23,6 +23,8 @@ func TestBrokenStacks(t *testing.T) { require.NoError(t, err) _, err = waitForStack(t, stacksetName, firstVersion) require.NoError(t, err) + _, err = waitForIngressSegment(t, stacksetName, firstVersion) + require.NoError(t, err) unhealthyVersion := "v2" unhealthyStack := fmt.Sprintf("%s-%s", stacksetName, unhealthyVersion) @@ -37,8 +39,7 @@ func TestBrokenStacks(t *testing.T) { require.NoError(t, err) _, err = waitForStack(t, stacksetName, unhealthyVersion) require.NoError(t, err) - - _, err = waitForIngress(t, stacksetName) + _, err = waitForIngressSegment(t, stacksetName, unhealthyVersion) require.NoError(t, err) initialWeights := map[string]float64{firstStack: 100} @@ -107,6 +108,8 @@ func TestBrokenStackWithConfigMaps(t *testing.T) { require.NoError(t, err) _, err = waitForStack(t, stacksetName, firstVersion) require.NoError(t, err) + _, err = waitForIngressSegment(t, stacksetName, firstVersion) + require.NoError(t, err) unhealthyVersion := "v2" unhealthyStack := fmt.Sprintf("%s-%s", stacksetName, unhealthyVersion) @@ -119,8 +122,7 @@ func TestBrokenStackWithConfigMaps(t *testing.T) { require.NoError(t, err) _, err = waitForStack(t, stacksetName, unhealthyVersion) require.NoError(t, err) - - _, err = waitForIngress(t, stacksetName) + _, err = waitForIngressSegment(t, stacksetName, unhealthyVersion) require.NoError(t, err) initialWeights := map[string]float64{firstStack: 100} @@ -198,6 +200,8 @@ func TestBrokenStackWithSecrets(t *testing.T) { require.NoError(t, err) _, err = waitForStack(t, stacksetName, firstVersion) require.NoError(t, err) + _, err = waitForIngressSegment(t, stacksetName, firstVersion) + require.NoError(t, err) unhealthyVersion := "v2" @@ -210,8 +214,7 @@ func TestBrokenStackWithSecrets(t *testing.T) { require.NoError(t, err) _, err = waitForStack(t, stacksetName, unhealthyVersion) require.NoError(t, err) - - _, err = waitForIngress(t, stacksetName) + _, err = waitForIngressSegment(t, stacksetName, unhealthyVersion) require.NoError(t, err) initialWeights := map[string]float64{firstStack: 100} diff --git a/cmd/e2e/ingress_source_switch_test.go b/cmd/e2e/ingress_source_switch_test.go deleted file mode 100644 index b4431f87..00000000 --- a/cmd/e2e/ingress_source_switch_test.go +++ /dev/null @@ -1,233 +0,0 @@ -package main - -import ( - "testing" - "time" - - "github.com/stretchr/testify/require" - v1 "github.com/szuecs/routegroup-client/apis/zalando.org/v1" - "github.com/zalando-incubator/stackset-controller/controller" - "github.com/zalando-incubator/stackset-controller/pkg/core" -) - -const ( - // The e2e env IngressSourceSwitchTTL - IngressSourceSwitchTTL = time.Minute -) - -func TestIngressSourceSwitch(t *testing.T) { - t.Parallel() - - stacksetName := "ingress-source-switch-stackset" - firstVersion := "v1" - - // create stackset with ingress - factory := NewTestStacksetSpecFactory(stacksetName).Ingress() - spec := factory.Create(t, firstVersion) - err := createStackSet(stacksetName, 0, spec) - require.NoError(t, err) - ingress, err := waitForIngress(t, stacksetName) - require.NoError(t, err) - require.Contains(t, ingress.Annotations, controller.ControllerLastUpdatedAnnotationKey) - require.NotEqual(t, "", ingress.Annotations[controller.ControllerLastUpdatedAnnotationKey]) - - // update stackset adding a routegroup - updatedVersion := "v2" - spec = factory.RouteGroup().Create(t, updatedVersion) - err = updateStackset(stacksetName, spec) - require.NoError(t, err) - rg, err := waitForRouteGroup(t, stacksetName) - require.NoError(t, err) - firstRgUpdatedTimestamp := ingress.Annotations[controller.ControllerLastUpdatedAnnotationKey] - require.Contains(t, rg.Annotations, controller.ControllerLastUpdatedAnnotationKey) - require.NotEqual(t, "", firstRgUpdatedTimestamp) - secondIngress, err := waitForIngress(t, stacksetName) - require.Equal(t, secondIngress.Annotations[controller.ControllerLastUpdatedAnnotationKey], ingress.Annotations[controller.ControllerLastUpdatedAnnotationKey]) - require.NoError(t, err) - - // update the routegroup and delete the ingress - lastVersion := "v3" - lastSpec := spec - lastSpec.StackTemplate.Spec.Version = lastVersion - lastSpec.RouteGroup.AdditionalBackends = []v1.RouteGroupBackend{{Name: "shunt", Type: v1.ShuntRouteGroupBackend}} - lastSpec.Ingress = nil - err = updateStackset(stacksetName, lastSpec) - require.NoError(t, err) - lastRg, err := waitForUpdatedRouteGroup(t, rg.Name, rg.Annotations[controller.ControllerLastUpdatedAnnotationKey]) - require.NoError(t, err) - require.NotEqual(t, lastRg.Annotations[controller.ControllerLastUpdatedAnnotationKey], firstRgUpdatedTimestamp) - // If the ingress is not deleted right away, then, it respects the - // TTL. - err = resourceDeleted(t, "ingress", stacksetName, ingressInterface()).await() - require.Error(t, err) - - // make sure the ingress is finally deleted after twice the TTL - a := resourceDeleted(t, "ingress", stacksetName, ingressInterface()) - a.timeout += IngressSourceSwitchTTL * 2 - err = a.await() - require.NoError(t, err) -} - -func TestIngressToRouteGroupSwitch(t *testing.T) { - t.Parallel() - - stacksetName := "ingress-to-routegroup-switch" - firstVersion := "v1" - - // create stackset with ingress and routegroup - factory := NewTestStacksetSpecFactory(stacksetName).Ingress().RouteGroup() - spec := factory.Create(t, firstVersion) - err := createStackSet(stacksetName, 0, spec) - require.NoError(t, err) - rg, err := waitForRouteGroup(t, stacksetName) - require.NoError(t, err) - - // Wait the IngressSourceSwitchTTL to make sure the ingress is - // created a time long enough ago. - time.Sleep(IngressSourceSwitchTTL) - - // update the routegroup and delete the ingress - lastVersion := "v2" - lastSpec := spec - lastSpec.StackTemplate.Spec.Version = lastVersion - lastSpec.RouteGroup.AdditionalBackends = []v1.RouteGroupBackend{{Name: "shunt", Type: v1.ShuntRouteGroupBackend}} - lastSpec.Ingress = nil - err = updateStackset(stacksetName, lastSpec) - require.NoError(t, err) - _, err = waitForUpdatedRouteGroup(t, rg.Name, rg.Annotations[controller.ControllerLastUpdatedAnnotationKey]) - require.NoError(t, err) - - // make sure ingress is not deleted before IngressSourceSwitchTTL - err = resourceDeleted(t, "ingress", stacksetName, ingressInterface()).await() - require.Error(t, err) -} - -func TestRouteGroupToIngressSwitch(t *testing.T) { - t.Parallel() - - stacksetName := "routegroup-to-ingress-switch" - firstVersion := "v1" - - // create stackset with ingress and routegroup - factory := NewTestStacksetSpecFactory(stacksetName).Ingress().RouteGroup() - spec := factory.Create(t, firstVersion) - err := createStackSet(stacksetName, 0, spec) - require.NoError(t, err) - ing, err := waitForIngress(t, stacksetName) - require.NoError(t, err) - - // Wait the IngressSourceSwitchTTL to make sure the RouteGroup is - // created a time long enough ago. - time.Sleep(IngressSourceSwitchTTL) - - // update the Ingress and delete the RouteGroup - lastVersion := "v2" - lastSpec := spec - lastSpec.StackTemplate.Spec.Version = lastVersion - lastSpec.Ingress.Annotations["a-random-annotation"] = "a-random-annotation-value" - lastSpec.RouteGroup = nil - err = updateStackset(stacksetName, lastSpec) - require.NoError(t, err) - _, err = waitForUpdatedIngress(t, ing.Name, ing.Annotations[controller.ControllerLastUpdatedAnnotationKey]) - require.NoError(t, err) - - // make sure ingress is not deleted before IngressSourceSwitchTTL - err = resourceDeleted(t, "routegroup", stacksetName, routegroupInterface()).await() - require.Error(t, err) -} - -func TestStackTTLConvertToSegmentIngress(t *testing.T) { - t.Parallel() - stacksetName := "stackset-ttl-convert-segment" - specFactory := NewTestStacksetSpecFactory(stacksetName).Ingress() - - // create stackset with central ingress - spec := specFactory.Create(t, "v1") - err := createStackSet(stacksetName, 0, spec) - require.NoError(t, err) - _, err = waitForIngress(t, stacksetName) - require.NoError(t, err) - - time.Sleep(IngressSourceSwitchTTL) - - // Add the annotation to convert to segment ingresses - spec.StackTemplate.Spec.Version = "v2" - err = updateStackSetWithAnnotations( - stacksetName, - spec, - map[string]string{controller.TrafficSegmentsAnnotationKey: "true"}, - ) - require.NoError(t, err) - - // make sure controller does not delete ingress IngressSourceSwitchTTL - err = resourceDeleted( - t, - "ingress", - stacksetName, - ingressInterface(), - ).await() - require.Error(t, err) - - // make sure controller creates ingress segments - _, err = waitForIngress(t, stacksetName+"-v1"+core.SegmentSuffix) - require.NoError(t, err) - _, err = waitForIngress(t, stacksetName+"-v2"+core.SegmentSuffix) - require.NoError(t, err) - - // make sure controller deletes ingress is after IngressSourceSwitchTTL - err = resourceDeleted( - t, - "ingress", - stacksetName, - ingressInterface(), - ).await() - require.NoError(t, err) -} - -func TestShallowStackSetConvertToSegmentIngress(t *testing.T) { - t.Parallel() - stacksetName := "stackset-shallow-convert-segment" - stackVersion := "v1" - specFactory := NewTestStacksetSpecFactory(stacksetName).Ingress() - - // create stackset with central ingress - spec := specFactory.Create(t, stackVersion) - err := createStackSet(stacksetName, 0, spec) - require.NoError(t, err) - - _, err = waitForIngress(t, stacksetName) - require.NoError(t, err) - stack, err := waitForStack(t, stacksetName, stackVersion) - require.NoError(t, err) - - err = deleteStack(stack.Name) - require.NoError(t, err) - - err = resourceDeleted( - t, - "stack", - stack.Name, - stackInterface(), - ).withTimeout(time.Second * 60).await() - require.NoError(t, err) - - // Add the annotation to convert to segment ingresses but DON'T increase the - // StackSet version. - err = updateStackSetWithAnnotations( - stacksetName, - spec, - map[string]string{controller.TrafficSegmentsAnnotationKey: "true"}, - ) - require.NoError(t, err) - - time.Sleep(time.Second * 20) - - // make sure controller DOES delete the ingress - err = resourceDeleted( - t, - "ingress", - stacksetName, - ingressInterface(), - ).await() - require.NoError(t, err) -} diff --git a/cmd/e2e/prescaling_test.go b/cmd/e2e/prescaling_test.go index bb6216d8..825795ff 100644 --- a/cmd/e2e/prescaling_test.go +++ b/cmd/e2e/prescaling_test.go @@ -21,6 +21,8 @@ func TestPrescalingWithoutHPA(t *testing.T) { require.NoError(t, err) _, err = waitForStack(t, stacksetName, firstStack) require.NoError(t, err) + _, err = waitForIngressSegment(t, stacksetName, firstStack) + require.NoError(t, err) // create second stack with 3 replicas secondStack := "v2" @@ -29,12 +31,12 @@ func TestPrescalingWithoutHPA(t *testing.T) { require.NoError(t, err) _, err = waitForStack(t, stacksetName, secondStack) require.NoError(t, err) + _, err = waitForIngressSegment(t, stacksetName, secondStack) + require.NoError(t, err) // switch traffic so that both stacks are receiving equal traffic and verify traffic has actually switched fullFirstStack := fmt.Sprintf("%s-%s", stacksetName, firstStack) fullSecondStack := fmt.Sprintf("%s-%s", stacksetName, secondStack) - _, err = waitForIngress(t, stacksetName) - require.NoError(t, err) desiredTraffic := map[string]float64{ fullFirstStack: 50, fullSecondStack: 50, @@ -92,6 +94,8 @@ func TestPrescalingWithHPA(t *testing.T) { require.NoError(t, err) _, err = waitForStack(t, stacksetName, firstStack) require.NoError(t, err) + _, err = waitForIngressSegment(t, stacksetName, firstStack) + require.NoError(t, err) // create second stack with 3 replicas secondStack := "v2" @@ -100,12 +104,12 @@ func TestPrescalingWithHPA(t *testing.T) { require.NoError(t, err) _, err = waitForStack(t, stacksetName, secondStack) require.NoError(t, err) + _, err = waitForIngressSegment(t, stacksetName, secondStack) + require.NoError(t, err) // switch traffic so that both stacks are receiving equal traffic fullFirstStack := fmt.Sprintf("%s-%s", stacksetName, firstStack) fullSecondStack := fmt.Sprintf("%s-%s", stacksetName, secondStack) - _, err = waitForIngress(t, stacksetName) - require.NoError(t, err) desiredTraffic := map[string]float64{ fullFirstStack: 50, fullSecondStack: 50, @@ -244,6 +248,8 @@ func TestPrescalingWaitsForBackends(t *testing.T) { require.NoError(t, err) _, err = waitForStack(t, stacksetName, firstStack) require.NoError(t, err) + _, err = waitForIngressSegment(t, stacksetName, firstStack) + require.NoError(t, err) // create second stack with 3 replicas secondStack := "v2" @@ -252,6 +258,8 @@ func TestPrescalingWaitsForBackends(t *testing.T) { require.NoError(t, err) _, err = waitForStack(t, stacksetName, secondStack) require.NoError(t, err) + _, err = waitForIngressSegment(t, stacksetName, secondStack) + require.NoError(t, err) // create third stack with 3 replicas thirdStack := "v3" @@ -260,8 +268,7 @@ func TestPrescalingWaitsForBackends(t *testing.T) { require.NoError(t, err) _, err = waitForStack(t, stacksetName, thirdStack) require.NoError(t, err) - - _, err = waitForIngress(t, stacksetName) + _, err = waitForIngressSegment(t, stacksetName, thirdStack) require.NoError(t, err) // switch traffic so that all three stacks are receiving 0%, 50% & 50% traffic and verify traffic has actually switched diff --git a/cmd/e2e/test_utils.go b/cmd/e2e/test_utils.go index b7bf3dbe..532d286f 100644 --- a/cmd/e2e/test_utils.go +++ b/cmd/e2e/test_utils.go @@ -2,10 +2,8 @@ package main import ( "context" - "encoding/json" "fmt" "reflect" - "strconv" "testing" "time" @@ -14,6 +12,7 @@ import ( rgv1 "github.com/szuecs/routegroup-client/apis/zalando.org/v1" "github.com/zalando-incubator/stackset-controller/controller" zv1 "github.com/zalando-incubator/stackset-controller/pkg/apis/zalando.org/v1" + "github.com/zalando-incubator/stackset-controller/pkg/core" appsv1 "k8s.io/api/apps/v1" autoscalingv2 "k8s.io/api/autoscaling/v2" corev1 "k8s.io/api/core/v1" @@ -178,19 +177,32 @@ func removeZeroWeights(weights map[string]float64) { // will never be retried type trafficAsserter func(map[string]float64) error -func trafficWeightsUpdatedIngress(t *testing.T, ingressName string, kind weightKind, expectedWeights map[string]float64, asserter trafficAsserter) *awaiter { +func trafficWeightsUpdatedIngress(t *testing.T, ingressName string, expectedWeights map[string]float64, asserter trafficAsserter) *awaiter { removeZeroWeights(expectedWeights) - timeout := waitTimeout - if kind == weightKindActual { - timeout = trafficSwitchWaitTimeout - } return newAwaiter(t, fmt.Sprintf("update of traffic weights in ingress %s", ingressName)).withPoll(func() (retry bool, err error) { - ingress, err := ingressInterface().Get(context.Background(), ingressName, metav1.GetOptions{}) - if err != nil { - return false, err + predicates := map[string]string{} + for stack := range expectedWeights { + ingSeg, err := ingressInterface().Get( + context.Background(), + fmt.Sprintf("%s-traffic-segment", stack), + metav1.GetOptions{}, + ) + + if err != nil { + return true, err + } + + predicates[stack] = ingSeg.Annotations[core.IngressPredicateKey] } - actualWeights := getIngressTrafficWeights(ingress, kind) + actualWeights := map[string]float64{} + for version, predicate := range predicates { + lower, upper, err := core.GetSegmentLimits(predicate) + if err != nil { + return false, err + } + actualWeights[version] = (upper - lower) * 100 + } if asserter != nil { err = asserter(actualWeights) @@ -205,31 +217,7 @@ func trafficWeightsUpdatedIngress(t *testing.T, ingressName string, kind weightK return true, fmt.Errorf("%s: weights %v != expected %v", ingressName, actualWeights, expectedWeights) } return false, nil - }).withTimeout(timeout) -} - -func ingressTrafficAuthoritative(t *testing.T, ingressName string, expectedAuthoritative bool) *awaiter { - return newAwaiter(t, fmt.Sprintf("update of traffic authoritative annotation in ingress %s", ingressName)).withPoll(func() (retry bool, err error) { - ingress, err := ingressInterface().Get(context.Background(), ingressName, metav1.GetOptions{}) - if err != nil { - return false, err - } - - authoritativeStr, ok := ingress.Annotations["zalando.org/traffic-authoritative"] - if !ok { - return true, fmt.Errorf("missing traffic authoritative annotation in ingress %s", ingressName) - } - authoritative, err := strconv.ParseBool(authoritativeStr) - if !ok { - return false, fmt.Errorf("invalid value for authoritative annotation in ingress %s: %v", ingressName, err) - } - - if authoritative != expectedAuthoritative { - return true, fmt.Errorf("%s: authoritative %v != expected %v", ingressName, authoritative, expectedAuthoritative) - } - - return false, nil - }).withTimeout(waitTimeout) + }).withTimeout(trafficSwitchWaitTimeout) } func trafficWeightsUpdatedStackset(t *testing.T, stacksetName string, kind weightKind, expectedWeights map[string]float64, asserter trafficAsserter) *awaiter { @@ -391,14 +379,6 @@ func deleteStackset(stacksetName string) error { ) } -func deleteStack(stackName string) error { - return stackInterface().Delete( - context.Background(), - stackName, - metav1.DeleteOptions{}, - ) -} - func stacksetExists(stacksetName string) bool { _, err := stacksetInterface().Get(context.Background(), stacksetName, metav1.GetOptions{}) return err == nil @@ -493,6 +473,20 @@ func waitForIngress(t *testing.T, name string) (*networkingv1.Ingress, error) { return ingressInterface().Get(context.Background(), name, metav1.GetOptions{}) } +func waitForIngressSegment(t *testing.T, name, version string) ( + *networkingv1.Ingress, + error, +) { + return waitForIngress( + t, + fmt.Sprintf( + "%s-%s-traffic-segment", + name, + version, + ), + ) +} + func waitForRouteGroup(t *testing.T, name string) (*rgv1.RouteGroup, error) { err := resourceCreated(t, "routegroup", name, routegroupInterface()).await() if err != nil { @@ -501,6 +495,20 @@ func waitForRouteGroup(t *testing.T, name string) (*rgv1.RouteGroup, error) { return routegroupInterface().Get(context.Background(), name, metav1.GetOptions{}) } +func waitForRouteGroupSegment(t *testing.T, name, version string) ( + *rgv1.RouteGroup, + error, +) { + return waitForRouteGroup( + t, + fmt.Sprintf( + "%s-%s-traffic-segment", + name, + version, + ), + ) +} + func waitForConfigMap(t *testing.T, configMapName string) (*corev1.ConfigMap, error) { err := resourceCreated(t, "configmap", configMapName, configMapInterface()).await() if err != nil { @@ -517,48 +525,6 @@ func waitForSecret(t *testing.T, secretName string) (*corev1.Secret, error) { return secretInterface().Get(context.Background(), secretName, metav1.GetOptions{}) } -func waitForUpdatedRouteGroup(t *testing.T, name string, oldTimestamp string) (*rgv1.RouteGroup, error) { - err := newAwaiter(t, fmt.Sprintf("updated RouteGroup %s", name)).withPoll(func() (bool, error) { - rg, err := routegroupInterface().Get(context.Background(), name, metav1.GetOptions{}) - if err != nil { - return apiErrors.IsNotFound(err), err - } - return rg.Annotations[controller.ControllerLastUpdatedAnnotationKey] != oldTimestamp, nil - }).await() - if err != nil { - return nil, err - } - return routegroupInterface().Get(context.Background(), name, metav1.GetOptions{}) -} - -func waitForUpdatedIngress(t *testing.T, name string, oldTimestamp string) (*networkingv1.Ingress, error) { - err := newAwaiter(t, fmt.Sprintf("updated Ingress %s", name)).withPoll(func() (bool, error) { - ing, err := ingressInterface().Get(context.Background(), name, metav1.GetOptions{}) - if err != nil { - return apiErrors.IsNotFound(err), err - } - return ing.Annotations[controller.ControllerLastUpdatedAnnotationKey] != oldTimestamp, nil - }).await() - if err != nil { - return nil, err - } - return ingressInterface().Get(context.Background(), name, metav1.GetOptions{}) -} - -func getIngressTrafficWeights(ingress *networkingv1.Ingress, kind weightKind) map[string]float64 { - weights := ingress.Annotations[string(kind)] - if weights == "" { - return nil - } - - var result map[string]float64 - err := json.Unmarshal([]byte(weights), &result) - if err != nil { - return nil - } - return result -} - func getStacksetTrafficWeights(stackset *zv1.StackSet, kind weightKind) map[string]float64 { result := make(map[string]float64) diff --git a/cmd/e2e/traffic_switch_test.go b/cmd/e2e/traffic_switch_test.go index 0f6ba6e1..5e6a55ed 100644 --- a/cmd/e2e/traffic_switch_test.go +++ b/cmd/e2e/traffic_switch_test.go @@ -10,7 +10,7 @@ import ( // expectActualTrafficWeights waits until that both stackset.status and the ingress have the expected actual traffic weight, // and all stacks have their weights populated correctly func expectActualTrafficWeights(t *testing.T, stacksetName string, weights map[string]float64) { - err := trafficWeightsUpdatedIngress(t, stacksetName, weightKindActual, weights, nil).await() + err := trafficWeightsUpdatedIngress(t, stacksetName, weights, nil).await() require.NoError(t, err) err = trafficWeightsUpdatedStackset(t, stacksetName, weightKindActual, weights, nil).await() require.NoError(t, err) @@ -39,20 +39,21 @@ func TestTrafficSwitchStackset(t *testing.T) { require.NoError(t, err) _, err = waitForStack(t, stacksetName, firstVersion) require.NoError(t, err) + _, err = waitForIngressSegment(t, stacksetName, firstVersion) + require.NoError(t, err) + spec = factory.Create(t, updatedVersion) err = updateStackset(stacksetName, spec) require.NoError(t, err) _, err = waitForStack(t, stacksetName, updatedVersion) require.NoError(t, err) - - _, err = waitForIngress(t, stacksetName) + _, err = waitForIngressSegment(t, stacksetName, updatedVersion) require.NoError(t, err) initialWeights := map[string]float64{firstStack: 100} expectActualTrafficWeights(t, stacksetName, initialWeights) err = trafficWeightsUpdatedStackset(t, stacksetName, weightKindDesired, initialWeights, nil).await() require.NoError(t, err) - err = ingressTrafficAuthoritative(t, stacksetName, false).await() require.NoError(t, err) expectStackTrafficWeights(t, firstStack, 100, 100) @@ -63,7 +64,6 @@ func TestTrafficSwitchStackset(t *testing.T) { err = setDesiredTrafficWeightsStackset(stacksetName, desiredWeights) require.NoError(t, err) expectActualTrafficWeights(t, stacksetName, desiredWeights) - err = ingressTrafficAuthoritative(t, stacksetName, false).await() require.NoError(t, err) expectStackTrafficWeights(t, firstStack, 50, 50) @@ -74,7 +74,6 @@ func TestTrafficSwitchStackset(t *testing.T) { err = setDesiredTrafficWeightsStackset(stacksetName, newDesiredWeights) require.NoError(t, err) expectActualTrafficWeights(t, stacksetName, newDesiredWeights) - err = ingressTrafficAuthoritative(t, stacksetName, false).await() require.NoError(t, err) expectStackTrafficWeights(t, firstStack, 0, 0) diff --git a/docs/stack_crd.yaml b/docs/stack_crd.yaml index 5139f4fb..5af997b7 100644 --- a/docs/stack_crd.yaml +++ b/docs/stack_crd.yaml @@ -652,9 +652,6 @@ spec: resources, in this case pods. properties: matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. items: properties: key: @@ -708,14 +705,6 @@ spec: matchLabels: additionalProperties: type: string - description: matchLabels is a map of - {key,value} pairs. A single {key,value} - in the matchLabels map is equivalent - to an element of matchExpressions, - whose key field is "key", the operator - is "In", and the values array contains - only "value". The requirements are - ANDed. type: object type: object x-kubernetes-map-type: atomic @@ -918,9 +907,6 @@ spec: resources, in this case pods. properties: matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. items: properties: key: @@ -953,9 +939,6 @@ spec: empty selector ({}) matches all namespaces. properties: matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. items: properties: key: @@ -2021,6 +2004,28 @@ spec: exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object + restartPolicy: + description: 'RestartPolicy defines the restart behavior + of individual containers in a pod. This field may + only be set for init containers, and the only allowed + value is "Always". For non-init containers or when + this field is not specified, the restart behavior + is defined by the Pod''s restart policy and the container + type. Setting the RestartPolicy as "Always" for the + init container will have the following effect: this + init container will be continually restarted on exit + until all regular containers have terminated. Once + all regular containers have completed, all init containers + with restartPolicy "Always" will be shut down. This + lifecycle differs from normal init containers and + is often referred to as a "sidecar" container. Although + this init container still starts in the init container + sequence, it does not wait for the container to complete + before proceeding to the next init container. Instead, + the next init container starts immediately after this + init container is started, or after any startupProbe + has successfully completed.' + type: string securityContext: description: 'SecurityContext defines the security options the container should be run with. If set, the fields @@ -2150,7 +2155,8 @@ spec: The profile must be preconfigured on the node to work. Must be a descending path, relative to the kubelet's configured seccomp profile - location. Must only be set if type is "Localhost". + location. Must be set if type is "Localhost". + Must NOT be set for any other type. type: string type: description: "type indicates which kind of seccomp @@ -2186,14 +2192,10 @@ spec: hostProcess: description: HostProcess determines if a container should be run as a 'Host Process' container. - This field is alpha-level and will only be - honored by components that enable the WindowsHostProcessContainers - feature flag. Setting this field without the - feature flag will result in errors when validating - the Pod. All of a Pod's containers must have - the same effective HostProcess value (it is - not allowed to have a mix of HostProcess containers - and non-HostProcess containers). In addition, + All of a Pod's containers must have the same + effective HostProcess value (it is not allowed + to have a mix of HostProcess containers and + non-HostProcess containers). In addition, if HostProcess is true then HostNetwork must also be set to true. type: boolean @@ -3417,6 +3419,12 @@ spec: exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object + restartPolicy: + description: Restart policy for the container to manage + the restart behavior of each container within a pod. + This may only be set for init containers. You cannot + set this field on ephemeral containers. + type: string securityContext: description: 'Optional: SecurityContext defines the security options the ephemeral container should be @@ -3546,7 +3554,8 @@ spec: The profile must be preconfigured on the node to work. Must be a descending path, relative to the kubelet's configured seccomp profile - location. Must only be set if type is "Localhost". + location. Must be set if type is "Localhost". + Must NOT be set for any other type. type: string type: description: "type indicates which kind of seccomp @@ -3582,14 +3591,10 @@ spec: hostProcess: description: HostProcess determines if a container should be run as a 'Host Process' container. - This field is alpha-level and will only be - honored by components that enable the WindowsHostProcessContainers - feature flag. Setting this field without the - feature flag will result in errors when validating - the Pod. All of a Pod's containers must have - the same effective HostProcess value (it is - not allowed to have a mix of HostProcess containers - and non-HostProcess containers). In addition, + All of a Pod's containers must have the same + effective HostProcess value (it is not allowed + to have a mix of HostProcess containers and + non-HostProcess containers). In addition, if HostProcess is true then HostNetwork must also be set to true. type: boolean @@ -4846,6 +4851,28 @@ spec: exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object + restartPolicy: + description: 'RestartPolicy defines the restart behavior + of individual containers in a pod. This field may + only be set for init containers, and the only allowed + value is "Always". For non-init containers or when + this field is not specified, the restart behavior + is defined by the Pod''s restart policy and the container + type. Setting the RestartPolicy as "Always" for the + init container will have the following effect: this + init container will be continually restarted on exit + until all regular containers have terminated. Once + all regular containers have completed, all init containers + with restartPolicy "Always" will be shut down. This + lifecycle differs from normal init containers and + is often referred to as a "sidecar" container. Although + this init container still starts in the init container + sequence, it does not wait for the container to complete + before proceeding to the next init container. Instead, + the next init container starts immediately after this + init container is started, or after any startupProbe + has successfully completed.' + type: string securityContext: description: 'SecurityContext defines the security options the container should be run with. If set, the fields @@ -4975,7 +5002,8 @@ spec: The profile must be preconfigured on the node to work. Must be a descending path, relative to the kubelet's configured seccomp profile - location. Must only be set if type is "Localhost". + location. Must be set if type is "Localhost". + Must NOT be set for any other type. type: string type: description: "type indicates which kind of seccomp @@ -5011,14 +5039,10 @@ spec: hostProcess: description: HostProcess determines if a container should be run as a 'Host Process' container. - This field is alpha-level and will only be - honored by components that enable the WindowsHostProcessContainers - feature flag. Setting this field without the - feature flag will result in errors when validating - the Pod. All of a Pod's containers must have - the same effective HostProcess value (it is - not allowed to have a mix of HostProcess containers - and non-HostProcess containers). In addition, + All of a Pod's containers must have the same + effective HostProcess value (it is not allowed + to have a mix of HostProcess containers and + non-HostProcess containers). In addition, if HostProcess is true then HostNetwork must also be set to true. type: boolean @@ -5454,19 +5478,14 @@ spec: namespace as this pod. \n The template will be used to create a new ResourceClaim, which will be bound to this pod. When this pod is deleted, - the ResourceClaim will also be deleted. The name - of the ResourceClaim will be -, where is the PodResourceClaim.Name. - Pod validation will reject the pod if the concatenated - name is not valid for a ResourceClaim (e.g. too - long). \n An existing ResourceClaim with that - name that is not owned by the pod will not be - used for the pod to avoid using an unrelated resource - by mistake. Scheduling and pod startup are then - blocked until the unrelated ResourceClaim is removed. - \n This field is immutable and no changes will - be made to the corresponding ResourceClaim by - the control plane after creating the ResourceClaim." + the ResourceClaim will also be deleted. The pod + name and resource name, along with a generated + component, will be used to form a unique name + for the ResourceClaim, which will be recorded + in pod.status.resourceClaimStatuses. \n This field + is immutable and no changes will be made to the + corresponding ResourceClaim by the control plane + after creating the ResourceClaim." type: string type: object required: @@ -5613,8 +5632,9 @@ spec: defined in a file on the node should be used. The profile must be preconfigured on the node to work. Must be a descending path, relative to the kubelet's - configured seccomp profile location. Must only be - set if type is "Localhost". + configured seccomp profile location. Must be set + if type is "Localhost". Must NOT be set for any + other type. type: string type: description: "type indicates which kind of seccomp @@ -5682,15 +5702,11 @@ spec: type: string hostProcess: description: HostProcess determines if a container - should be run as a 'Host Process' container. This - field is alpha-level and will only be honored by - components that enable the WindowsHostProcessContainers - feature flag. Setting this field without the feature - flag will result in errors when validating the Pod. - All of a Pod's containers must have the same effective + should be run as a 'Host Process' container. All + of a Pod's containers must have the same effective HostProcess value (it is not allowed to have a mix - of HostProcess containers and non-HostProcess containers). In - addition, if HostProcess is true then HostNetwork + of HostProcess containers and non-HostProcess containers). + In addition, if HostProcess is true then HostNetwork must also be set to true. type: boolean runAsUserName: @@ -6495,12 +6511,6 @@ spec: will not be copied to dataSource.' properties: apiGroup: - description: APIGroup is the group for - the resource being referenced. If - APIGroup is not specified, the specified - Kind must be in the core API group. - For any other third-party types, APIGroup - is required. type: string kind: description: Kind is the type of resource @@ -6554,12 +6564,6 @@ spec: gate to be enabled.' properties: apiGroup: - description: APIGroup is the group for - the resource being referenced. If - APIGroup is not specified, the specified - Kind must be in the core API group. - For any other third-party types, APIGroup - is required. type: string kind: description: Kind is the type of resource @@ -6586,13 +6590,6 @@ spec: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' properties: claims: - description: "Claims lists the names - of resources, defined in spec.resourceClaims, - that are used by this container. \n - This is an alpha field and requires - enabling the DynamicResourceAllocation - feature gate. \n This field is immutable. - It can only be set for containers." items: properties: name: @@ -6611,9 +6608,6 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: 'Limits describes the maximum - amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object requests: additionalProperties: @@ -6629,9 +6623,6 @@ spec: volumes to consider for binding. properties: matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. items: properties: key: @@ -6650,14 +6641,6 @@ spec: matchLabels: additionalProperties: type: string - description: matchLabels is a map of - {key,value} pairs. A single {key,value} - in the matchLabels map is equivalent - to an element of matchExpressions, - whose key field is "key", the operator - is "In", and the values array contains - only "value". The requirements are - ANDed. type: object type: object x-kubernetes-map-type: atomic @@ -7121,9 +7104,6 @@ spec: description: Items is a list of DownwardAPIVolume file items: - description: DownwardAPIVolumeFile represents - information to create the file containing - the pod field properties: fieldRef: properties: @@ -7768,12 +7748,19 @@ spec: description: ServicePort contains information on service's port. properties: appProtocol: - description: The application protocol for this port. This - field follows standard Kubernetes label syntax. Un-prefixed - names are reserved for IANA standard service names (as - per RFC-6335 and https://www.iana.org/assignments/service-names). - Non-standard protocols should use prefixed names such - as mycompany.com/my-custom-protocol. + description: "The application protocol for this port. This + is used as a hint for implementations to offer richer + behavior for protocols that they understand. This field + follows standard Kubernetes label syntax. Valid values + are either: \n * Un-prefixed protocol names - reserved + for IANA standard service names (as per RFC-6335 and https://www.iana.org/assignments/service-names). + \n * Kubernetes-defined prefixed names: * 'kubernetes.io/h2c' + - HTTP/2 over cleartext as described in https://www.rfc-editor.org/rfc/rfc7540 + * 'kubernetes.io/ws' - WebSocket over cleartext as described + in https://www.rfc-editor.org/rfc/rfc6455 * 'kubernetes.io/wss' + - WebSocket over TLS as described in https://www.rfc-editor.org/rfc/rfc6455 + \n * Other protocols should use implementation-defined + prefixed names such as mycompany.com/my-custom-protocol." type: string name: description: The name of this port within the service. This diff --git a/docs/stackset_crd.yaml b/docs/stackset_crd.yaml index b04c73bb..cb33c793 100644 --- a/docs/stackset_crd.yaml +++ b/docs/stackset_crd.yaml @@ -891,10 +891,6 @@ spec: pods. properties: matchExpressions: - description: matchExpressions - is a list of label selector - requirements. The requirements - are ANDed. items: properties: key: @@ -929,10 +925,6 @@ spec: selector ({}) matches all namespaces. properties: matchExpressions: - description: matchExpressions - is a list of label selector - requirements. The requirements - are ANDed. items: properties: key: @@ -1177,10 +1169,6 @@ spec: pods. properties: matchExpressions: - description: matchExpressions - is a list of label selector - requirements. The requirements - are ANDed. items: properties: key: @@ -1215,10 +1203,6 @@ spec: selector ({}) matches all namespaces. properties: matchExpressions: - description: matchExpressions - is a list of label selector - requirements. The requirements - are ANDed. items: properties: key: @@ -2389,6 +2373,31 @@ spec: More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object + restartPolicy: + description: 'RestartPolicy defines the restart + behavior of individual containers in a pod. + This field may only be set for init containers, + and the only allowed value is "Always". For + non-init containers or when this field is + not specified, the restart behavior is defined + by the Pod''s restart policy and the container + type. Setting the RestartPolicy as "Always" + for the init container will have the following + effect: this init container will be continually + restarted on exit until all regular containers + have terminated. Once all regular containers + have completed, all init containers with restartPolicy + "Always" will be shut down. This lifecycle + differs from normal init containers and is + often referred to as a "sidecar" container. + Although this init container still starts + in the init container sequence, it does not + wait for the container to complete before + proceeding to the next init container. Instead, + the next init container starts immediately + after this init container is started, or after + any startupProbe has successfully completed.' + type: string securityContext: description: 'SecurityContext defines the security options the container should be run with. @@ -2531,8 +2540,9 @@ spec: be preconfigured on the node to work. Must be a descending path, relative to the kubelet's configured seccomp - profile location. Must only be set - if type is "Localhost". + profile location. Must be set if type + is "Localhost". Must NOT be set for + any other type. type: string type: description: "type indicates which kind @@ -2572,18 +2582,14 @@ spec: hostProcess: description: HostProcess determines if a container should be run as a - 'Host Process' container. This field - is alpha-level and will only be honored - by components that enable the WindowsHostProcessContainers - feature flag. Setting this field without - the feature flag will result in errors - when validating the Pod. All of a + 'Host Process' container. All of a Pod's containers must have the same effective HostProcess value (it is not allowed to have a mix of HostProcess - containers and non-HostProcess containers). In - addition, if HostProcess is true then - HostNetwork must also be set to true. + containers and non-HostProcess containers). + In addition, if HostProcess is true + then HostNetwork must also be set + to true. type: boolean runAsUserName: description: The UserName in Windows @@ -3918,6 +3924,13 @@ spec: More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object + restartPolicy: + description: Restart policy for the container + to manage the restart behavior of each container + within a pod. This may only be set for init + containers. You cannot set this field on ephemeral + containers. + type: string securityContext: description: 'Optional: SecurityContext defines the security options the ephemeral container @@ -4060,8 +4073,9 @@ spec: be preconfigured on the node to work. Must be a descending path, relative to the kubelet's configured seccomp - profile location. Must only be set - if type is "Localhost". + profile location. Must be set if type + is "Localhost". Must NOT be set for + any other type. type: string type: description: "type indicates which kind @@ -4101,18 +4115,14 @@ spec: hostProcess: description: HostProcess determines if a container should be run as a - 'Host Process' container. This field - is alpha-level and will only be honored - by components that enable the WindowsHostProcessContainers - feature flag. Setting this field without - the feature flag will result in errors - when validating the Pod. All of a + 'Host Process' container. All of a Pod's containers must have the same effective HostProcess value (it is not allowed to have a mix of HostProcess - containers and non-HostProcess containers). In - addition, if HostProcess is true then - HostNetwork must also be set to true. + containers and non-HostProcess containers). + In addition, if HostProcess is true + then HostNetwork must also be set + to true. type: boolean runAsUserName: description: The UserName in Windows @@ -5488,6 +5498,31 @@ spec: More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object + restartPolicy: + description: 'RestartPolicy defines the restart + behavior of individual containers in a pod. + This field may only be set for init containers, + and the only allowed value is "Always". For + non-init containers or when this field is + not specified, the restart behavior is defined + by the Pod''s restart policy and the container + type. Setting the RestartPolicy as "Always" + for the init container will have the following + effect: this init container will be continually + restarted on exit until all regular containers + have terminated. Once all regular containers + have completed, all init containers with restartPolicy + "Always" will be shut down. This lifecycle + differs from normal init containers and is + often referred to as a "sidecar" container. + Although this init container still starts + in the init container sequence, it does not + wait for the container to complete before + proceeding to the next init container. Instead, + the next init container starts immediately + after this init container is started, or after + any startupProbe has successfully completed.' + type: string securityContext: description: 'SecurityContext defines the security options the container should be run with. @@ -5630,8 +5665,9 @@ spec: be preconfigured on the node to work. Must be a descending path, relative to the kubelet's configured seccomp - profile location. Must only be set - if type is "Localhost". + profile location. Must be set if type + is "Localhost". Must NOT be set for + any other type. type: string type: description: "type indicates which kind @@ -5671,18 +5707,14 @@ spec: hostProcess: description: HostProcess determines if a container should be run as a - 'Host Process' container. This field - is alpha-level and will only be honored - by components that enable the WindowsHostProcessContainers - feature flag. Setting this field without - the feature flag will result in errors - when validating the Pod. All of a + 'Host Process' container. All of a Pod's containers must have the same effective HostProcess value (it is not allowed to have a mix of HostProcess - containers and non-HostProcess containers). In - addition, if HostProcess is true then - HostNetwork must also be set to true. + containers and non-HostProcess containers). + In addition, if HostProcess is true + then HostNetwork must also be set + to true. type: boolean runAsUserName: description: The UserName in Windows @@ -6158,17 +6190,10 @@ spec: a new ResourceClaim, which will be bound to this pod. When this pod is deleted, the ResourceClaim will also be deleted. - The name of the ResourceClaim will be - -, where is the PodResourceClaim.Name. Pod - validation will reject the pod if the - concatenated name is not valid for a ResourceClaim - (e.g. too long). \n An existing ResourceClaim - with that name that is not owned by the - pod will not be used for the pod to avoid - using an unrelated resource by mistake. - Scheduling and pod startup are then blocked - until the unrelated ResourceClaim is removed. + The pod name and resource name, along + with a generated component, will be used + to form a unique name for the ResourceClaim, + which will be recorded in pod.status.resourceClaimStatuses. \n This field is immutable and no changes will be made to the corresponding ResourceClaim by the control plane after creating the @@ -6330,8 +6355,9 @@ spec: be used. The profile must be preconfigured on the node to work. Must be a descending path, relative to the kubelet's configured - seccomp profile location. Must only be set - if type is "Localhost". + seccomp profile location. Must be set if + type is "Localhost". Must NOT be set for + any other type. type: string type: description: "type indicates which kind of @@ -6406,17 +6432,12 @@ spec: hostProcess: description: HostProcess determines if a container should be run as a 'Host Process' container. - This field is alpha-level and will only - be honored by components that enable the - WindowsHostProcessContainers feature flag. - Setting this field without the feature flag - will result in errors when validating the - Pod. All of a Pod's containers must have - the same effective HostProcess value (it - is not allowed to have a mix of HostProcess - containers and non-HostProcess containers). In - addition, if HostProcess is true then HostNetwork - must also be set to true. + All of a Pod's containers must have the + same effective HostProcess value (it is + not allowed to have a mix of HostProcess + containers and non-HostProcess containers). + In addition, if HostProcess is true then + HostNetwork must also be set to true. type: boolean runAsUserName: description: The UserName in Windows to run @@ -7315,12 +7336,8 @@ spec: apiGroup: type: string kind: - description: Kind is the type - of resource being referenced type: string name: - description: Name is the name - of resource being referenced type: string required: - kind @@ -7376,12 +7393,8 @@ spec: apiGroup: type: string kind: - description: Kind is the type - of resource being referenced type: string name: - description: Name is the name - of resource being referenced type: string namespace: type: string @@ -7436,10 +7449,6 @@ spec: for binding. properties: matchExpressions: - description: matchExpressions - is a list of label selector - requirements. The requirements - are ANDed. items: properties: key: @@ -7908,26 +7917,7 @@ spec: about the configMap data to project properties: items: - description: items if unspecified, - each key-value pair in the Data - field of the referenced ConfigMap - will be projected into the volume - as a file whose name is the - key and content is the value. - If specified, the listed keys - will be projected into the specified - paths, and unlisted keys will - not be present. If a key is - specified which is not present - in the ConfigMap, the volume - setup will error unless it is - marked optional. Paths must - be relative and may not contain - the '..' path or start with - '..'. items: - description: Maps a string key - to a path within a volume. properties: key: type: string @@ -7962,10 +7952,6 @@ spec: description: Items is a list of DownwardAPIVolume file items: - description: DownwardAPIVolumeFile - represents information to - create the file containing - the pod field properties: fieldRef: properties: @@ -8008,25 +7994,7 @@ spec: the secret data to project properties: items: - description: items if unspecified, - each key-value pair in the Data - field of the referenced Secret - will be projected into the volume - as a file whose name is the - key and content is the value. - If specified, the listed keys - will be projected into the specified - paths, and unlisted keys will - not be present. If a key is - specified which is not present - in the Secret, the volume setup - will error unless it is marked - optional. Paths must be relative - and may not contain the '..' - path or start with '..'. items: - description: Maps a string key - to a path within a volume. properties: key: type: string @@ -8069,20 +8037,6 @@ spec: to the identifier of the apiserver. type: string expirationSeconds: - description: expirationSeconds - is the requested duration of - validity of the service account - token. As the token approaches - expiration, the kubelet volume - plugin will proactively rotate - the service account token. The - kubelet will start trying to - rotate the token if the token - is older than 80 percent of - its time to live or if the token - is older than 24 hours.Defaults - to 1 hour and must be at least - 10 minutes. format: int64 type: integer path: @@ -8467,12 +8421,21 @@ spec: port. properties: appProtocol: - description: The application protocol for this port. - This field follows standard Kubernetes label syntax. - Un-prefixed names are reserved for IANA standard - service names (as per RFC-6335 and https://www.iana.org/assignments/service-names). - Non-standard protocols should use prefixed names - such as mycompany.com/my-custom-protocol. + description: "The application protocol for this + port. This is used as a hint for implementations + to offer richer behavior for protocols that they + understand. This field follows standard Kubernetes + label syntax. Valid values are either: \n * Un-prefixed + protocol names - reserved for IANA standard service + names (as per RFC-6335 and https://www.iana.org/assignments/service-names). + \n * Kubernetes-defined prefixed names: * 'kubernetes.io/h2c' + - HTTP/2 over cleartext as described in https://www.rfc-editor.org/rfc/rfc7540 + * 'kubernetes.io/ws' - WebSocket over cleartext + as described in https://www.rfc-editor.org/rfc/rfc6455 + * 'kubernetes.io/wss' - WebSocket over TLS as + described in https://www.rfc-editor.org/rfc/rfc6455 + \n * Other protocols should use implementation-defined + prefixed names such as mycompany.com/my-custom-protocol." type: string name: description: The name of this port within the service. diff --git a/e2e/apply/deployment.yaml b/e2e/apply/deployment.yaml index 50c69522..1d473c74 100644 --- a/e2e/apply/deployment.yaml +++ b/e2e/apply/deployment.yaml @@ -30,7 +30,7 @@ spec: - "--enable-configmap-support" - "--enable-secret-support" - "--enable-routegroup-support" - - "--annotated-traffic-segments" + - "--enable-traffic-segments" - "--sync-ingress-annotation=example.org/i-haz-synchronize" - "--sync-ingress-annotation=teapot.org/the-best" - "--ingress-source-switch-ttl=1m" diff --git a/e2e/apply/sample-segment.yaml b/e2e/apply/sample-segment.yaml deleted file mode 100644 index 26bb6dd4..00000000 --- a/e2e/apply/sample-segment.yaml +++ /dev/null @@ -1,92 +0,0 @@ -apiVersion: zalando.org/v1 -kind: StackSet -metadata: - name: e2e-deploy-sample-segment - labels: - application: "e2e-deploy-sample-segment" - annotations: - "stackset-controller.zalando.org/controller": "{{{CONTROLLER_ID}}}" - "stackset-controller.zalando.org/use-traffic-segments": "true" -spec: - ingress: - hosts: - - "e2e-deploy-sample-segment.{{{CLUSTER_DOMAIN}}}" - backendPort: 80 - stackLifecycle: - scaledownTTLSeconds: 300 - limit: 3 - stackTemplate: - spec: - version: "{{{CDP_BUILD_VERSION}}}" - replicas: 2 - configurationResources: - - configMapRef: - name: e2e-deploy-sample-segment-{{{CDP_BUILD_VERSION}}}-my-reference-config - - secretRef: - name: e2e-deploy-sample-segment-{{{CDP_BUILD_VERSION}}}-my-reference-secret - autoscaler: - minReplicas: 2 - maxReplicas: 2 - metrics: - - type: CPU - averageUtilization: 50 - - type: Ingress - average: 20000m - podTemplate: - metadata: - labels: - application: "e2e-deploy-sample-segment" - spec: - containers: - - name: skipper - image: ghcr.io/zalando/skipper:v0.15.33 - args: - - skipper - - -inline-routes - - '* -> inlineContent("OK") -> ' - - -address=:80 - ports: - - containerPort: 80 - resources: - requests: - cpu: 1m - memory: 100Mi - limits: - cpu: 1m - memory: 100Mi - volumeMounts: - - name: my-reference-config - mountPath: /etc/my-reference-config - readOnly: true - - name: my-reference-secret - mountPath: /etc/my-reference-secret - readOnly: true - volumes: - - name: my-reference-config - configMap: - name: e2e-deploy-sample-segment-{{{CDP_BUILD_VERSION}}}-my-reference-config - - name: my-reference-secret - secret: - secretName: e2e-deploy-sample-segment-{{{CDP_BUILD_VERSION}}}-my-reference-secret - ---- - -apiVersion: v1 -kind: ConfigMap -metadata: - name: e2e-deploy-sample-segment-{{{CDP_BUILD_VERSION}}}-my-reference-config - labels: - application: "e2e-deploy-sample-segment" -data: - something_is: configured_by_reference - ---- - -apiVersion: v1 -kind: Secret -metadata: - name: e2e-deploy-sample-segment-{{{CDP_BUILD_VERSION}}}-my-reference-secret - labels: - application: "e2e-deploy-sample-segment" -data: - something_is: c2VjcmV0bHlfY29uZmlndXJlZF9ieV9yZWZlcmVuY2U= diff --git a/e2e/run_e2e.sh b/e2e/run_e2e.sh index d808dd33..583adced 100755 --- a/e2e/run_e2e.sh +++ b/e2e/run_e2e.sh @@ -52,7 +52,6 @@ sscPath=$(find build/ -name "stackset-controller" | head -n 1) command $sscPath --apiserver=http://127.0.0.1:8001 \ --ingress-source-switch-ttl="1m" \ --enable-traffic-segments \ - --annotated-traffic-segments \ --sync-ingress-annotation=example.org/i-haz-synchronize \ --sync-ingress-annotation=teapot.org/the-best \ --enable-configmap-support \ diff --git a/pkg/client/informers/externalversions/factory.go b/pkg/client/informers/externalversions/factory.go index f4d5a0f2..c38d053a 100644 --- a/pkg/client/informers/externalversions/factory.go +++ b/pkg/client/informers/externalversions/factory.go @@ -166,7 +166,7 @@ func (f *sharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[ref return res } -// InternalInformerFor returns the SharedIndexInformer for obj using an internal +// InformerFor returns the SharedIndexInformer for obj using an internal // client. func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer { f.lock.Lock() @@ -239,7 +239,7 @@ type SharedInformerFactory interface { // ForResource gives generic access to a shared informer of the matching type. ForResource(resource schema.GroupVersionResource) (GenericInformer, error) - // InternalInformerFor returns the SharedIndexInformer for obj using an internal + // InformerFor returns the SharedIndexInformer for obj using an internal // client. InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer diff --git a/pkg/core/traffic.go b/pkg/core/traffic.go index 426f1d0c..6a53d06f 100644 --- a/pkg/core/traffic.go +++ b/pkg/core/traffic.go @@ -57,7 +57,7 @@ func newTrafficSegment(id types.UID, sc *StackContainer) ( if sc.ingressSpec != nil { if sc.Resources.IngressSegment != nil { predicates := sc.Resources.IngressSegment.Annotations[IngressPredicateKey] - lowerLimit, upperLimit, err := getSegmentLimits(predicates) + lowerLimit, upperLimit, err := GetSegmentLimits(predicates) if err != nil { return nil, err } @@ -67,7 +67,7 @@ func newTrafficSegment(id types.UID, sc *StackContainer) ( if sc.routeGroupSpec != nil { if sc.Resources.RouteGroupSegment != nil { - lowerLimit, upperLimit, err := getSegmentLimits( + lowerLimit, upperLimit, err := GetSegmentLimits( sc.Resources.RouteGroupSegment.Spec.Routes[0].Predicates..., ) if err != nil { @@ -147,11 +147,11 @@ func (l segmentList) Swap(i, j int) { l[i], l[j] = l[j], l[i] } -// getSegmentLimits returns the lower and upper limit of the TrafficSegment +// GetSegmentLimits returns the lower and upper limit of the TrafficSegment // predicate. // // Returns an error if it fails to parse. -func getSegmentLimits(predicates ...string) (float64, float64, error) { +func GetSegmentLimits(predicates ...string) (float64, float64, error) { for _, p := range predicates { segmentParams := segmentRe.FindStringSubmatch(p) if len(segmentParams) != 3 {