Skip to content

Commit 1e4361f

Browse files
authored
Experimental support for IPv6 (cherry pick of PR #1700) (#1706)
1 parent 07448af commit 1e4361f

File tree

15 files changed

+352
-13
lines changed

15 files changed

+352
-13
lines changed

api/v1alpha2/experimental.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@ package v1alpha2
22

33
type Experimental struct {
44
PilotFeatures `json:"pilot"`
5+
6+
// Enables the Dual Stack support
7+
// +kubebuilder:validation:Optional
8+
EnableDualStack *bool `json:"enableDualStack,omitempty"`
59
}
610

711
type PilotFeatures struct {

api/v1alpha2/istio_merge.go

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package v1alpha2
33
import (
44
"encoding/json"
55
"github.com/golang/protobuf/ptypes/duration"
6-
76
"istio.io/istio/operator/pkg/values"
87
"istio.io/istio/pkg/util/protomarshal"
98
appsv1 "k8s.io/api/apps/v1"
@@ -77,6 +76,17 @@ func (m *meshConfigBuilder) BuildPrometheusMergeConfig(prometheusMerge bool) *me
7776
return m
7877
}
7978

79+
func (m *meshConfigBuilder) BuildDualStackConfig(enableDualStack bool) *meshConfigBuilder {
80+
if enableDualStack {
81+
err := m.c.SetPath("defaultConfig.proxyMetadata.ISTIO_DUAL_STACK", "true")
82+
if err != nil {
83+
return nil
84+
}
85+
}
86+
87+
return m
88+
}
89+
8090
func (m *meshConfigBuilder) AddProxyMetadata(key, value string) (*meshConfigBuilder, error) {
8191
err := m.c.SetPath("defaultConfig.proxyMetadata."+key, value)
8292
if err != nil {
@@ -183,15 +193,23 @@ func (i *Istio) mergeConfig(op iopv1alpha1.IstioOperator) (iopv1alpha1.IstioOper
183193
return op, err
184194
}
185195

196+
dualStackEnabled := i.Spec.Experimental != nil && i.Spec.Experimental.EnableDualStack != nil && *i.Spec.Experimental.EnableDualStack
197+
186198
newMeshConfig := mcb.
187199
BuildNumTrustedProxies(i.Spec.Config.NumTrustedProxies).
188200
BuildExternalAuthorizerConfiguration(i.Spec.Config.Authorizers).
189201
BuildPrometheusMergeConfig(i.Spec.Config.Telemetry.Metrics.PrometheusMerge).
202+
BuildDualStackConfig(dualStackEnabled).
190203
Build()
191204

192205
op.Spec.MeshConfig = newMeshConfig
193206

194207
op = applyGatewayExternalTrafficPolicy(op, i)
208+
209+
op, err = applyDualStack(op, i)
210+
if err != nil {
211+
return op, err
212+
}
195213

196214
return op, nil
197215
}
@@ -228,6 +246,48 @@ func applyGatewayExternalTrafficPolicy(op iopv1alpha1.IstioOperator, i *Istio) i
228246
return op
229247
}
230248

249+
func applyDualStack(op iopv1alpha1.IstioOperator, i *Istio) (iopv1alpha1.IstioOperator, error) {
250+
if i.Spec.Experimental != nil && i.Spec.Experimental.EnableDualStack != nil && *i.Spec.Experimental.EnableDualStack {
251+
return enableDualStack(op, i)
252+
}
253+
return op, nil
254+
}
255+
256+
func enableDualStack(op iopv1alpha1.IstioOperator, i *Istio) (iopv1alpha1.IstioOperator, error) {
257+
valuesMap, err := values.MapFromObject(op.Spec.Values)
258+
if err != nil {
259+
return op, err
260+
}
261+
262+
if valuesMap == nil {
263+
valuesMap = make(values.Map)
264+
}
265+
266+
err = valuesMap.SetPath("pilot.env.ISTIO_DUAL_STACK", "true")
267+
if err != nil {
268+
return iopv1alpha1.IstioOperator{}, err
269+
}
270+
err = valuesMap.SetPath("pilot.ipFamilyPolicy", "RequireDualStack")
271+
if err != nil {
272+
return iopv1alpha1.IstioOperator{}, err
273+
}
274+
err = valuesMap.SetPath("gateways.istio-ingressgateway.ipFamilyPolicy", "RequireDualStack")
275+
if err != nil {
276+
return iopv1alpha1.IstioOperator{}, err
277+
}
278+
err = valuesMap.SetPath("gateways.istio-egressgateway.ipFamilyPolicy", "RequireDualStack")
279+
if err != nil {
280+
return iopv1alpha1.IstioOperator{}, err
281+
}
282+
283+
op.Spec.Values, err = values.ConvertMap[json.RawMessage](valuesMap)
284+
if err != nil {
285+
return op, err
286+
}
287+
288+
return op, nil
289+
}
290+
231291
//nolint:gocognit,gocyclo,cyclop,funlen // cognitive complexity 189 of func `(*Istio).mergeResources` is high (> 20), cyclomatic complexity 70 of func `(*Istio).mergeResources` is high (> 30), Function 'mergeResources' has too many statements (129 > 50) TODO: refactor this function
232292
func (i *Istio) mergeResources(op iopv1alpha1.IstioOperator) (iopv1alpha1.IstioOperator, error) {
233293
if i.Spec.Components == nil {

api/v1alpha2/merge_test.go

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -664,6 +664,76 @@ var _ = Describe("Merge", func() {
664664

665665
})
666666

667+
It("should set ipFamilyPolicy to RequireDualStack if dualStack is enabled in the Istio CR", func() {
668+
// given
669+
enableDualStack := true
670+
iop := iopv1alpha1.IstioOperator{
671+
Spec: iopv1alpha1.IstioOperatorSpec{},
672+
}
673+
istioCR := istiov1alpha2.Istio{Spec: istiov1alpha2.IstioSpec{
674+
Config: istiov1alpha2.Config{},
675+
Experimental: &istiov1alpha2.Experimental{
676+
EnableDualStack: &enableDualStack,
677+
},
678+
}}
679+
680+
// when
681+
out, err := istioCR.MergeInto(iop)
682+
683+
valuesMap, err := values.MapFromObject(out.Spec.Values)
684+
Expect(err).ShouldNot(HaveOccurred())
685+
686+
Expect(values.TryGetPathAs[string](valuesMap, "pilot.ipFamilyPolicy")).To(Equal("RequireDualStack"))
687+
Expect(values.TryGetPathAs[string](valuesMap, "gateways.istio-ingressgateway.ipFamilyPolicy")).To(Equal("RequireDualStack"))
688+
Expect(values.TryGetPathAs[string](valuesMap, "gateways.istio-egressgateway.ipFamilyPolicy")).To(Equal("RequireDualStack"))
689+
})
690+
691+
It("should set dual stack env for Istio pilot if dualStack is enabled in the Istio CR", func() {
692+
// given
693+
enableDualStack := true
694+
iop := iopv1alpha1.IstioOperator{
695+
Spec: iopv1alpha1.IstioOperatorSpec{},
696+
}
697+
istioCR := istiov1alpha2.Istio{Spec: istiov1alpha2.IstioSpec{
698+
Config: istiov1alpha2.Config{},
699+
Experimental: &istiov1alpha2.Experimental{
700+
EnableDualStack: &enableDualStack,
701+
},
702+
}}
703+
704+
// when
705+
out, err := istioCR.MergeInto(iop)
706+
707+
valuesMap, err := values.MapFromObject(out.Spec.Values)
708+
Expect(err).ShouldNot(HaveOccurred())
709+
710+
Expect(values.TryGetPathAs[string](valuesMap, "pilot.env.ISTIO_DUAL_STACK")).To(Equal("true"))
711+
})
712+
713+
It("should set dual stack in the mesh Config if dualStack is enabled in the Istio CR", func() {
714+
// given
715+
enableDualStack := true
716+
iop := iopv1alpha1.IstioOperator{
717+
Spec: iopv1alpha1.IstioOperatorSpec{},
718+
}
719+
istioCR := istiov1alpha2.Istio{Spec: istiov1alpha2.IstioSpec{
720+
Config: istiov1alpha2.Config{},
721+
Experimental: &istiov1alpha2.Experimental{
722+
EnableDualStack: &enableDualStack,
723+
},
724+
}}
725+
726+
// when
727+
out, err := istioCR.MergeInto(iop)
728+
729+
meshConfig, err := values.MapFromObject(out.Spec.MeshConfig)
730+
Expect(err).ShouldNot(HaveOccurred())
731+
732+
dualStack, exists := meshConfig.GetPath("defaultConfig.proxyMetadata.ISTIO_DUAL_STACK")
733+
Expect(exists).To(BeTrue())
734+
Expect(dualStack).To(Equal("true"))
735+
})
736+
667737
Context("Pilot", func() {
668738
Context("When Istio CR has 500m configured for CPU limits", func() {
669739
It("should set CPU limits to 500m in IOP", func() {

api/v1alpha2/zz_generated.deepcopy.go

Lines changed: 6 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/crd/bases/operator.kyma-project.io_istios.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1434,6 +1434,9 @@ spec:
14341434
experimental:
14351435
description: Defines experimental configuration options.
14361436
properties:
1437+
enableDualStack:
1438+
description: Enables the Dual Stack support
1439+
type: boolean
14371440
pilot:
14381441
properties:
14391442
enableAlphaGatewayAPI:

controllers/istio_controller.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,10 @@ func (r *IstioReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl
106106

107107
r.statusHandler.SetCondition(&istioCR, operatorv1alpha2.NewReasonWithMessage(operatorv1alpha2.ConditionReasonReconcileUnknown))
108108

109+
if err := r.validate(&istioCR); err != nil {
110+
return ctrl.Result{}, r.statusHandler.UpdateToError(ctx, &istioCR, err)
111+
}
112+
109113
istioImages, imgErr := images.GetImages()
110114
if imgErr != nil {
111115
return r.terminateReconciliation(ctx, &istioCR, describederrors.NewDescribedError(imgErr, "Unable to get Istio images environments"),
@@ -299,9 +303,6 @@ func (r *IstioReconciler) finishReconcile(ctx context.Context, istioCR *operator
299303

300304
r.statusHandler.SetCondition(istioCR, operatorv1alpha2.NewReasonWithMessage(operatorv1alpha2.ConditionReasonReconcileSucceeded))
301305
r.statusHandler.SetCondition(istioCR, operatorv1alpha2.NewReasonWithMessage(operatorv1alpha2.ConditionReasonIngressTargetingUserResourceNotFound))
302-
if err := r.validate(istioCR); err != nil {
303-
return ctrl.Result{}, r.statusHandler.UpdateToError(ctx, istioCR, err)
304-
}
305306

306307
if err := r.statusHandler.UpdateToReady(ctx, istioCR); err != nil {
307308
r.log.Error(err, "Error during updating status to ready")

controllers/validate.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ func (r *IstioReconciler) validate(istioCR *operatorv1alpha2.Istio) describederr
1313
if istioCR.Spec.Experimental != nil {
1414
// user has experimental field applied in their CR
1515
// return error with description
16-
r.log.Info("Experimental features are not supported in this image flavour")
17-
return describederrors.NewDescribedError(errors.New("istio CR contains experimental feature"), "Experimental features are not supported in this image flavour").
18-
SetWarning().
16+
err := errors.New("istio CR contains experimental feature")
17+
r.log.Error(err, "Experimental features are not supported in this image flavour")
18+
return describederrors.NewDescribedError(err, "Experimental features are not supported in this image flavour").
1919
SetCondition(false)
2020
}
2121
return nil

controllers/validate_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import (
1919
)
2020

2121
var _ = Describe("Istio Controller", func() {
22-
It("should set CR status to warning if experimental fields have been defined", func() {
22+
It("should set CR status to error if experimental fields have been defined", func() {
2323
// given
2424
istioCR := &operatorv1alpha2.Istio{
2525
ObjectMeta: metav1.ObjectMeta{
@@ -70,7 +70,7 @@ var _ = Describe("Istio Controller", func() {
7070
err = fakeClient.Get(context.Background(), client.ObjectKeyFromObject(istioCR), &updatedIstioCR)
7171
Expect(err).To(Not(HaveOccurred()))
7272

73-
Expect(updatedIstioCR.Status.State).Should(Equal(operatorv1alpha2.Warning))
73+
Expect(updatedIstioCR.Status.State).Should(Equal(operatorv1alpha2.Error))
7474
Expect(updatedIstioCR.Status.Description).To(ContainSubstring("Experimental features are not supported in this image flavour"))
7575
})
7676
})
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ spec:
1919
#[...]
2020
```
2121

22-
The experimental features should be only available to be used with a separately built controller image. Using the experimental features with production image should result in setting the Istio rustom resource to the `Warning` state.
22+
The experimental features should be only available to be used with a separately built controller image. Using the experimental features with production image should result in setting the Istio custom resource to the `Error` state and break the reconciliation to avoid unintended changes.
2323

2424
### SAP BTP, Kyma Runtime
2525
In context of SAP BTP, Kyma runtime, experimental features should only be available in the experimental release channel.

docs/release-notes/1.23.1.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
## New Features
2+
3+
- We've added dual-stack experimental support.
4+
See [#1700](https://github.com/kyma-project/istio/pull/1700).
5+
6+
## Fixed Bugs

0 commit comments

Comments
 (0)