Skip to content
13 changes: 7 additions & 6 deletions gateway/internal/features/feature/circuit_breaker.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import (
"context"
"fmt"

"github.com/go-logr/logr"
"github.com/pkg/errors"
"github.com/telekom/controlplane/common/pkg/util/contextutil"
Expand Down Expand Up @@ -101,7 +102,7 @@

func isDeleteScenario(route *gatewayv1.Route) bool {
// completely removed or turned to false
if (route.Spec.Traffic.CircuitBreaker != nil && route.Spec.Traffic.CircuitBreaker.Enabled == false) && route.GetUpstreamId() != "" {

Check failure on line 105 in gateway/internal/features/feature/circuit_breaker.go

View workflow job for this annotation

GitHub Actions / Gateway / Static Checks for gateway

S1002: should omit comparison to bool constant, can be simplified to !route.Spec.Traffic.CircuitBreaker.Enabled (staticcheck)
return true
} else {
return false
Expand Down Expand Up @@ -171,7 +172,7 @@
targetsName := routeName
targetsTarget := DefaultTargetsTarget
targetsWeight := 100
targetsBody := kong.CreateTargetForUpstreamJSONRequestBody{
targetsBody := kong.UpsertTargetForUpstreamJSONRequestBody{
Tags: &[]string{
client.BuildTag("env", contextutil.EnvFromContextOrDie(ctx)),
client.BuildTag("targets", targetsName),
Expand All @@ -181,13 +182,13 @@
Weight: &targetsWeight,
}

// this is a special case with the kong admin API - this endpoint /upstreams/:upstreamName/targets actually accepts multiple POST requests, so this is not a mistake
targetsResponse, err := kongAdminApi.CreateTargetForUpstreamWithResponse(ctx, upstreamName, targetsBody)
// Use upsert (PUT) instead of create (POST) to handle re-reconciliation gracefully
targetsResponse, err := kongAdminApi.UpsertTargetForUpstreamWithResponse(ctx, upstreamName, targetsTarget, targetsBody)
if err != nil {
return errors.Wrap(err, "failed to create targets for upstream")
return errors.Wrap(err, "failed to upsert targets for upstream")
}
if err := client.CheckStatusCode(targetsResponse, 200, 201); err != nil {
return errors.Wrap(fmt.Errorf("error body from kong admin api: %s", string(targetsResponse.Body)), "failed to create targets for upstream")
if err := client.CheckStatusCode(targetsResponse, 200); err != nil {
return errors.Wrap(fmt.Errorf("error body from kong admin api: %s", string(targetsResponse.Body)), "failed to upsert targets for upstream")
}
route.SetTargetsId(*targetsResponse.JSON200.Id)

Expand Down
30 changes: 17 additions & 13 deletions gateway/internal/features/feature/circuit_breaker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@ package feature_test

import (
"context"
"net/http"

"github.com/telekom/controlplane/common/pkg/util/contextutil"
"github.com/telekom/controlplane/gateway/internal/features/feature/config"
kong "github.com/telekom/controlplane/gateway/pkg/kong/api"
"github.com/telekom/controlplane/gateway/pkg/kong/client/mock"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"net/http"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
Expand Down Expand Up @@ -155,25 +156,27 @@ var _ = Describe("CircuitBreakerFeature", func() {
}
mockKongAdminApi.EXPECT().UpsertUpstreamWithResponse(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(upsertUpstreamWithResponse_func).Times(1)

// mock CreateTargetForUpstreamWithResponse
var createTargetForUpstreamWithResponse_upstreamNameArg string
var createTargetForUpstreamWithResponse_targetBodyArg kong.CreateTargetForUpstreamJSONRequestBody
// mock UpsertTargetForUpstreamWithResponse
var upsertTargetForUpstreamWithResponse_upstreamNameArg string
var upsertTargetForUpstreamWithResponse_targetIdArg string
var upsertTargetForUpstreamWithResponse_targetBodyArg kong.UpsertTargetForUpstreamJSONRequestBody

createTargetForUpstreamWithResponse_func := func(_ context.Context, upstreamName string, targetsBody kong.CreateTargetForUpstreamJSONRequestBody, _ ...kong.RequestEditorFn) (*kong.CreateTargetForUpstreamResponse, error) {
createTargetForUpstreamWithResponse_upstreamNameArg = upstreamName
createTargetForUpstreamWithResponse_targetBodyArg = targetsBody
upsertTargetForUpstreamWithResponse_func := func(_ context.Context, upstreamName string, targetIdOrTarget string, targetsBody kong.UpsertTargetForUpstreamJSONRequestBody, _ ...kong.RequestEditorFn) (*kong.UpsertTargetForUpstreamResponse, error) {
upsertTargetForUpstreamWithResponse_upstreamNameArg = upstreamName
upsertTargetForUpstreamWithResponse_targetIdArg = targetIdOrTarget
upsertTargetForUpstreamWithResponse_targetBodyArg = targetsBody

createTargetForUpstreamResponseId := "kong_target_response_id"
return &kong.CreateTargetForUpstreamResponse{
upsertTargetForUpstreamResponseId := "kong_target_response_id"
return &kong.UpsertTargetForUpstreamResponse{
HTTPResponse: &http.Response{
StatusCode: 200,
},
JSON200: &kong.Target{
Id: &createTargetForUpstreamResponseId,
Id: &upsertTargetForUpstreamResponseId,
},
}, nil
}
mockKongAdminApi.EXPECT().CreateTargetForUpstreamWithResponse(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(createTargetForUpstreamWithResponse_func).Times(1)
mockKongAdminApi.EXPECT().UpsertTargetForUpstreamWithResponse(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(upsertTargetForUpstreamWithResponse_func).Times(1)
Comment thread
stefan-ctrl marked this conversation as resolved.
Outdated

// Execute
err := feature.InstanceCircuitBreakerFeature.Apply(ctx, mockFeatureBuilder)
Expand All @@ -195,10 +198,11 @@ var _ = Describe("CircuitBreakerFeature", func() {
Expect(upsertUpstreamWithResponse_upstreamBodyArg).To(Equal(*expectedUpstreamBody))
Expect(route.GetUpstreamId()).To(Equal("kong_upstream_response_id"))

Expect(createTargetForUpstreamWithResponse_upstreamNameArg).To(Equal("test-route-name"))
Expect(upsertTargetForUpstreamWithResponse_upstreamNameArg).To(Equal("test-route-name"))
Expect(upsertTargetForUpstreamWithResponse_targetIdArg).To(Equal("localhost:8080"))
expectedTargetTarget := "localhost:8080"
expectedTargetWeight := 100
Expect(createTargetForUpstreamWithResponse_targetBodyArg).To(Equal(kong.CreateTargetForUpstreamJSONRequestBody{
Expect(upsertTargetForUpstreamWithResponse_targetBodyArg).To(Equal(kong.UpsertTargetForUpstreamJSONRequestBody{
Tags: &[]string{"env--test", "targets--test-route-name", "route--test-route-name"},
Target: &expectedTargetTarget,
Weight: &expectedTargetWeight,
Expand Down
1 change: 1 addition & 0 deletions gateway/pkg/kong/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@

UpsertUpstreamWithResponse(ctx context.Context, upstreamIdOrName string, body kong.UpsertUpstreamJSONRequestBody, reqEditors ...kong.RequestEditorFn) (*kong.UpsertUpstreamResponse, error)
CreateTargetForUpstreamWithResponse(ctx context.Context, upstreamIdOrName string, body kong.CreateTargetForUpstreamJSONRequestBody, reqEditors ...kong.RequestEditorFn) (*kong.CreateTargetForUpstreamResponse, error)
UpsertTargetForUpstreamWithResponse(ctx context.Context, upstreamIdOrName string, targetIdOrTarget string, body kong.UpsertTargetForUpstreamJSONRequestBody, reqEditors ...kong.RequestEditorFn) (*kong.UpsertTargetForUpstreamResponse, error)
DeleteUpstreamWithResponse(ctx context.Context, upstreamIdOrName string, reqEditors ...kong.RequestEditorFn) (*kong.DeleteUpstreamResponse, error)
DeleteUpstreamTargetWithResponse(ctx context.Context, upstreamIdOrName string, targetIdOrTarget string, reqEditors ...kong.RequestEditorFn) (*kong.DeleteUpstreamTargetResponse, error)

Expand All @@ -71,7 +72,7 @@
var _ KongClient = &kongClient{}

type kongClient struct {
//client kong.ClientWithResponsesInterface

Check failure on line 75 in gateway/pkg/kong/client/client.go

View workflow job for this annotation

GitHub Actions / Gateway / Static Checks for gateway

comment-spacings: no space between comment delimiter and comment text (revive)
client KongAdminApi
commonTags []string
}
Expand Down
20 changes: 20 additions & 0 deletions gateway/pkg/kong/client/mock/client.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading