Skip to content

Commit 979adee

Browse files
authored
fix: use upstream id instead of inline upstream in traffic-split plugin (#2546) (#264)
Signed-off-by: Ashing Zheng <[email protected]>
1 parent 1b22891 commit 979adee

File tree

5 files changed

+121
-6
lines changed

5 files changed

+121
-6
lines changed

.github/workflows/apisix-e2e-test.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ concurrency:
2929
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
3030
cancel-in-progress: true
3131

32+
env:
33+
ADC_VERSION: dev
34+
3235
jobs:
3336
e2e-test:
3437
strategy:

api/adc/types.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ type Service struct {
168168
StreamRoutes []*StreamRoute `json:"stream_routes,omitempty" yaml:"stream_routes,omitempty"`
169169
StripPathPrefix *bool `json:"strip_path_prefix,omitempty" yaml:"strip_path_prefix,omitempty"`
170170
Upstream *Upstream `json:"upstream,omitempty" yaml:"upstream,omitempty"`
171+
Upstreams []*Upstream `json:"upstreams,omitempty" yaml:"upstreams,omitempty"`
171172
}
172173

173174
// +k8s:deepcopy-gen=true
@@ -807,3 +808,59 @@ func (c Config) MarshalJSON() ([]byte, error) {
807808
TlsVerify: c.TlsVerify,
808809
})
809810
}
811+
812+
var (
813+
ResolveGranularity = struct {
814+
Endpoint string
815+
Service string
816+
}{
817+
Endpoint: "endpoint",
818+
Service: "service",
819+
}
820+
)
821+
822+
// ComposeUpstreamName uses namespace, name, subset (optional), port, resolveGranularity info to compose
823+
// the upstream name.
824+
// the resolveGranularity is not composited in the upstream name when it is endpoint.
825+
// ref: https://github.com/apache/apisix-ingress-controller/blob/10059afe3e84b693cc61e6df7a0040890a9d16eb/pkg/types/apisix/v1/types.go#L595-L598
826+
func ComposeUpstreamName(namespace, name, subset string, port int32, resolveGranularity string) string {
827+
pstr := strconv.Itoa(int(port))
828+
// FIXME Use sync.Pool to reuse this buffer if the upstream
829+
// name composing code path is hot.
830+
var p []byte
831+
plen := len(namespace) + len(name) + len(pstr) + 2
832+
if subset != "" {
833+
plen = plen + len(subset) + 1
834+
}
835+
if resolveGranularity == ResolveGranularity.Service {
836+
plen = plen + len(resolveGranularity) + 1
837+
}
838+
839+
p = make([]byte, 0, plen)
840+
buf := bytes.NewBuffer(p)
841+
buf.WriteString(namespace)
842+
buf.WriteByte('_')
843+
buf.WriteString(name)
844+
buf.WriteByte('_')
845+
if subset != "" {
846+
buf.WriteString(subset)
847+
buf.WriteByte('_')
848+
}
849+
buf.WriteString(pstr)
850+
if resolveGranularity == ResolveGranularity.Service {
851+
buf.WriteByte('_')
852+
buf.WriteString(resolveGranularity)
853+
}
854+
855+
return buf.String()
856+
}
857+
858+
// ComposeExternalUpstreamName uses ApisixUpstream namespace, name to compose the upstream name.
859+
func ComposeExternalUpstreamName(namespace, name string) string {
860+
return namespace + "_" + name
861+
}
862+
863+
// ComposeUpstreamNameForBackendRef composes upstream name using kind, namespace, name and port.
864+
func ComposeUpstreamNameForBackendRef(kind, namespace, name string, port int32) string {
865+
return fmt.Sprintf("%s_%s_%s_%d", kind, namespace, name, port)
866+
}

api/adc/zz_generated.deepcopy.go

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/adc/translator/apisixroute.go

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,10 @@ func (t *Translator) buildUpstream(tctx *provider.TranslateContext, service *adc
235235
if backend.Weight != nil {
236236
upstream.Labels["meta_weight"] = strconv.FormatInt(int64(*backend.Weight), 10)
237237
}
238+
239+
upstreamName := adc.ComposeUpstreamName(ar.Namespace, backend.ServiceName, backend.Subset, int32(backend.ServicePort.IntValue()), backend.ResolveGranularity)
240+
upstream.Name = upstreamName
241+
upstream.ID = id.GenID(upstreamName)
238242
upstreams = append(upstreams, upstream)
239243
}
240244

@@ -257,6 +261,9 @@ func (t *Translator) buildUpstream(tctx *provider.TranslateContext, service *adc
257261
upstream.Labels["meta_weight"] = strconv.FormatInt(int64(*upstreamRef.Weight), 10)
258262
}
259263

264+
upstreamName := adc.ComposeExternalUpstreamName(upsNN.Namespace, upsNN.Name)
265+
upstream.Name = upstreamName
266+
upstream.ID = id.GenID(upstreamName)
260267
upstreams = append(upstreams, upstream)
261268
}
262269

@@ -268,8 +275,16 @@ func (t *Translator) buildUpstream(tctx *provider.TranslateContext, service *adc
268275
// the first valid upstream is used as service.upstream;
269276
// the others are configured in the traffic-split plugin
270277
service.Upstream = upstreams[0]
278+
// remove the id and name of the service.upstream, adc schema does not need id and name for it
279+
service.Upstream.ID = ""
280+
service.Upstream.Name = ""
281+
271282
upstreams = upstreams[1:]
272283

284+
if len(upstreams) > 0 {
285+
service.Upstreams = upstreams
286+
}
287+
273288
// set weight in traffic-split for the default upstream
274289
if len(upstreams) > 0 {
275290
weight, err := strconv.Atoi(service.Upstream.Labels["meta_weight"])
@@ -281,15 +296,15 @@ func (t *Translator) buildUpstream(tctx *provider.TranslateContext, service *adc
281296
})
282297
}
283298

284-
// set others upstreams in traffic-split
299+
// set others upstreams in traffic-split using upstream_id
285300
for _, item := range upstreams {
286301
weight, err := strconv.Atoi(item.Labels["meta_weight"])
287302
if err != nil {
288303
weight = apiv2.DefaultWeight
289304
}
290305
weightedUpstreams = append(weightedUpstreams, adc.TrafficSplitConfigRuleWeightedUpstream{
291-
Upstream: item,
292-
Weight: weight,
306+
UpstreamID: item.ID,
307+
Weight: weight,
293308
})
294309
}
295310

internal/adc/translator/httproute.go

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,24 @@ func (t *Translator) TranslateHTTPRoute(tctx *provider.TranslateContext, httpRou
543543

544544
t.AttachBackendTrafficPolicyToUpstream(backend.BackendRef, tctx.BackendTrafficPolicies, upstream)
545545
upstream.Nodes = upNodes
546+
547+
var (
548+
kind string
549+
port int32
550+
)
551+
if backend.Kind == nil {
552+
kind = "Service"
553+
} else {
554+
kind = string(*backend.Kind)
555+
}
556+
if backend.Port != nil {
557+
port = int32(*backend.Port)
558+
}
559+
namespace := string(*backend.Namespace)
560+
name := string(backend.Name)
561+
upstreamName := adctypes.ComposeUpstreamNameForBackendRef(kind, namespace, name, port)
562+
upstream.Name = upstreamName
563+
upstream.ID = id.GenID(upstreamName)
546564
upstreams = append(upstreams, upstream)
547565
}
548566

@@ -554,11 +572,22 @@ func (t *Translator) TranslateHTTPRoute(tctx *provider.TranslateContext, httpRou
554572
} else if len(upstreams) == 1 {
555573
// Single backend - use directly as service upstream
556574
service.Upstream = upstreams[0]
575+
// remove the id and name of the service.upstream, adc schema does not need id and name for it
576+
service.Upstream.ID = ""
577+
service.Upstream.Name = ""
557578
} else {
558579
// Multiple backends - use traffic-split plugin
559580
service.Upstream = upstreams[0]
581+
// remove the id and name of the service.upstream, adc schema does not need id and name for it
582+
service.Upstream.ID = ""
583+
service.Upstream.Name = ""
584+
560585
upstreams = upstreams[1:]
561586

587+
if len(upstreams) > 0 {
588+
service.Upstreams = upstreams
589+
}
590+
562591
// Set weight in traffic-split for the default upstream
563592
weight := apiv2.DefaultWeight
564593
if rule.BackendRefs[0].Weight != nil {
@@ -568,16 +597,16 @@ func (t *Translator) TranslateHTTPRoute(tctx *provider.TranslateContext, httpRou
568597
Weight: weight,
569598
})
570599

571-
// Set other upstreams in traffic-split
600+
// Set other upstreams in traffic-split using upstream_id
572601
for i, upstream := range upstreams {
573602
weight := apiv2.DefaultWeight
574603
// get weight from the backend refs starting from the second backend
575604
if i+1 < len(rule.BackendRefs) && rule.BackendRefs[i+1].Weight != nil {
576605
weight = int(*rule.BackendRefs[i+1].Weight)
577606
}
578607
weightedUpstreams = append(weightedUpstreams, adctypes.TrafficSplitConfigRuleWeightedUpstream{
579-
Upstream: upstream,
580-
Weight: weight,
608+
UpstreamID: upstream.ID,
609+
Weight: weight,
581610
})
582611
}
583612

0 commit comments

Comments
 (0)