diff --git a/examples/app/templates/myapp-ipfamily-service.yaml b/examples/app/templates/myapp-ipfamily-service.yaml new file mode 100644 index 00000000..fbfc76c6 --- /dev/null +++ b/examples/app/templates/myapp-ipfamily-service.yaml @@ -0,0 +1,21 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "app.fullname" . }}-myapp-ipfamily-service + labels: + app: myapp + {{- include "app.labels" . | nindent 4 }} +spec: + type: {{ .Values.myappIpfamilyService.type }} + selector: + app: myapp + {{- include "app.selectorLabels" . | nindent 4 }} + {{- if .Values.myappIpfamilyService.ipFamilyPolicy }} + ipFamilyPolicy: {{ .Values.myappIpfamilyService.ipFamilyPolicy }} + {{- end }} + {{- if .Values.myappIpfamilyService.ipFamilies }} + ipFamilies: + {{- .Values.myappIpfamilyService.ipFamilies | toYaml | nindent 2 }} + {{- end }} + ports: + {{- .Values.myappIpfamilyService.ports | toYaml | nindent 2 }} diff --git a/examples/app/values.yaml b/examples/app/values.yaml index 0023b067..54f03b4b 100644 --- a/examples/app/values.yaml +++ b/examples/app/values.yaml @@ -103,6 +103,15 @@ myapp: revisionHistoryLimit: 5 tolerations: [] topologySpreadConstraints: [] +myappIpfamilyService: + ipFamilies: + - IPv4 + ipFamilyPolicy: SingleStack + ports: + - name: https + port: 8443 + targetPort: https + type: ClusterIP myappLbService: loadBalancerSourceRanges: - 10.0.0.0/8 diff --git a/pkg/processor/service/service.go b/pkg/processor/service/service.go index 89ad6404..0cc77354 100644 --- a/pkg/processor/service/service.go +++ b/pkg/processor/service/service.go @@ -25,7 +25,7 @@ spec: type: {{ .Values.%[1]s.type }} selector: %[2]s - {{- include "%[3]s.selectorLabels" . | nindent 4 }} + {{- include "%[3]s.selectorLabels" . | nindent 4 }}%[4]s ports: {{- .Values.%[1]s.ports | toYaml | nindent 2 }}` ) @@ -36,6 +36,17 @@ const ( {{- .Values.%[1]s.loadBalancerSourceRanges | toYaml | nindent 2 }}` ) +const ( + ipFamilyTempSpec = ` + {{- if .Values.%[1]s.ipFamilyPolicy }} + ipFamilyPolicy: {{ .Values.%[1]s.ipFamilyPolicy }} + {{- end }} + {{- if .Values.%[1]s.ipFamilies }} + ipFamilies: + {{- .Values.%[1]s.ipFamilies | toYaml | nindent 2 }} + {{- end }}` +) + var svcGVC = schema.GroupVersionKind{ Group: "", Version: "v1", @@ -102,7 +113,9 @@ func (r svc) Process(appMeta helmify.AppMetadata, obj *unstructured.Unstructured } _ = unstructured.SetNestedSlice(values, ports, shortNameCamel, "ports") - res := meta + fmt.Sprintf(svcTempSpec, shortNameCamel, selector, appMeta.ChartName()) + + ipFamilySpec := parseIPFamily(values, service, shortNameCamel) + res := meta + fmt.Sprintf(svcTempSpec, shortNameCamel, selector, appMeta.ChartName(), ipFamilySpec) res += parseLoadBalancerSourceRanges(values, service, shortNameCamel) @@ -116,6 +129,29 @@ func (r svc) Process(appMeta helmify.AppMetadata, obj *unstructured.Unstructured }, nil } +func parseIPFamily(values helmify.Values, service corev1.Service, shortNameCamel string) string { + hasIPFamilyPolicy := service.Spec.IPFamilyPolicy != nil + hasIPFamilies := len(service.Spec.IPFamilies) > 0 + + if !hasIPFamilyPolicy && !hasIPFamilies { + return "" + } + + if hasIPFamilyPolicy { + _ = unstructured.SetNestedField(values, string(*service.Spec.IPFamilyPolicy), shortNameCamel, "ipFamilyPolicy") + } + + if hasIPFamilies { + ipFamilies := make([]interface{}, len(service.Spec.IPFamilies)) + for i, fam := range service.Spec.IPFamilies { + ipFamilies[i] = string(fam) + } + _ = unstructured.SetNestedSlice(values, ipFamilies, shortNameCamel, "ipFamilies") + } + + return fmt.Sprintf(ipFamilyTempSpec, shortNameCamel) +} + func parseLoadBalancerSourceRanges(values helmify.Values, service corev1.Service, shortNameCamel string) string { if len(service.Spec.LoadBalancerSourceRanges) < 1 { return "" diff --git a/pkg/processor/service/service_test.go b/pkg/processor/service/service_test.go index fd310f4f..134e6c91 100644 --- a/pkg/processor/service/service_test.go +++ b/pkg/processor/service/service_test.go @@ -3,10 +3,10 @@ package service import ( "testing" - "github.com/arttor/helmify/pkg/metadata" - "github.com/arttor/helmify/internal" + "github.com/arttor/helmify/pkg/metadata" "github.com/stretchr/testify/assert" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" ) const svcYaml = `apiVersion: v1 @@ -24,6 +24,25 @@ spec: selector: control-plane: controller-manager` +const svcWithIPFamilyYaml = `apiVersion: v1 +kind: Service +metadata: + labels: + control-plane: controller-manager + name: my-operator-controller-manager-metrics-service + namespace: my-operator-system +spec: + ipFamilyPolicy: PreferDualStack + ipFamilies: + - IPv4 + - IPv6 + ports: + - name: https + port: 8443 + targetPort: https + selector: + control-plane: controller-manager` + func Test_svc_Process(t *testing.T) { var testInstance svc @@ -39,4 +58,23 @@ func Test_svc_Process(t *testing.T) { assert.NoError(t, err) assert.Equal(t, false, processed) }) + + t.Run("processed with IP family", func(t *testing.T) { + obj := internal.GenerateObj(svcWithIPFamilyYaml) + processed, template, err := testInstance.Process(&metadata.Service{}, obj) + assert.NoError(t, err) + assert.Equal(t, true, processed) + assert.NotNil(t, template) + + values := template.Values() + ipFamilyPolicy, found, err := unstructured.NestedString(values, "myOperatorControllerManagerMetricsService", "ipFamilyPolicy") + assert.NoError(t, err) + assert.True(t, found) + assert.Equal(t, "PreferDualStack", ipFamilyPolicy) + + ipFamilies, found, err := unstructured.NestedSlice(values, "myOperatorControllerManagerMetricsService", "ipFamilies") + assert.NoError(t, err) + assert.True(t, found) + assert.Len(t, ipFamilies, 2) + }) } diff --git a/test_data/sample-app.yaml b/test_data/sample-app.yaml index 4e754939..e3e13197 100644 --- a/test_data/sample-app.yaml +++ b/test_data/sample-app.yaml @@ -156,6 +156,24 @@ spec: loadBalancerSourceRanges: - 10.0.0.0/8 --- +apiVersion: v1 +kind: Service +metadata: + labels: + app: myapp + name: myapp-ipfamily-service + namespace: my-ns +spec: + ipFamilyPolicy: SingleStack + ipFamilies: + - IPv4 + ports: + - name: https + port: 8443 + targetPort: https + selector: + app: myapp +--- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: