Skip to content

Commit

Permalink
feat(k8s): add support for GA ingress apiVersion in helm chart and op…
Browse files Browse the repository at this point in the history
…erator (#287)

* feat: add support for GA ingress apiVersion in helm chart

* remove support for k8s <1.19

* feat: BREAKING CHANGE: remove support for non-GA ingress in operator

* docs: do not edit the historical changelog

* revert gitignore change
  • Loading branch information
nasonfish authored Mar 23, 2023
1 parent afabd81 commit 8424836
Show file tree
Hide file tree
Showing 10 changed files with 91 additions and 125 deletions.
1 change: 0 additions & 1 deletion deploy/operator/cluster/role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ rules:
- '*'
- apiGroups:
- networking.k8s.io
- extensions
resources:
- ingresses
verbs:
Expand Down
2 changes: 1 addition & 1 deletion deploy/operator/helm/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ apiVersion: v1
appVersion: 0.1.0
description: Provides easy installation of Spinnaker
name: spinnaker-operator
version: 0.1.0
version: 0.1.1
sources:
- https://github.com/armory/spinnaker-operator
maintainers:
Expand Down
29 changes: 19 additions & 10 deletions deploy/operator/helm/templates/ingress.yaml
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
{{- if .Values.ingress.enabled -}}
{{- $fullName := include "spinnaker-operator.fullname" . -}}
apiVersion: extensions/v1beta1
{{- $svcPort := .Values.service.port -}}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ $fullName }}
labels:
{{ include "spinnaker-operator.labels" . | indent 4 }}
{{- include "spinnaker-operator.labels" . | indent 4 }}
{{- with .Values.ingress.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- if .Values.ingress.tls }}
{{- if .Values.ingress.className }}
ingressClassName: {{ .Values.ingress.className }}
{{- end }}
{{- if .Values.ingress.tls }}
tls:
{{- range .Values.ingress.tls }}
- hosts:
Expand All @@ -22,15 +26,20 @@ spec:
{{- end }}
{{- end }}
rules:
{{- range .Values.ingress.hosts }}
{{- range .Values.ingress.hosts }}
- host: {{ .host | quote }}
http:
paths:
{{- range .paths }}
- path: {{ . }}
{{- range .paths }}
- path: {{ .path }}
{{- if .pathType }}
pathType: {{ .pathType }}
{{- end }}
backend:
serviceName: {{ $fullName }}
servicePort: http
{{- end }}
{{- end }}
service:
name: {{ $fullName }}
port:
number: {{ $svcPort }}
{{- end }}
{{- end }}
{{- end }}
1 change: 1 addition & 0 deletions deploy/operator/helm/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ service:

ingress:
enabled: false
className: ""
annotations: {}
# kubernetes.io/ingress.class: nginx
# kubernetes.io/tls-acme: "true"
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ require (
github.com/stretchr/testify v1.7.0
gomodules.xyz/jsonpatch/v2 v2.2.0
gopkg.in/yaml.v2 v2.4.0
k8s.io/api v0.23.5
k8s.io/api v0.26.2
k8s.io/apimachinery v0.23.5
k8s.io/client-go v12.0.0+incompatible
k8s.io/code-generator v0.23.5
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ rules:
- '*'
- apiGroups:
- networking.k8s.io
- extensions
resources:
- ingresses
verbs:
Expand Down
88 changes: 13 additions & 75 deletions pkg/deploy/spindeploy/expose_ingress/ingress.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ import (
"github.com/armory/spinnaker-operator/pkg/apis/spinnaker/interfaces"
"github.com/armory/spinnaker-operator/pkg/util"
"github.com/go-logr/logr"
"k8s.io/api/extensions/v1beta1"
v1beta12 "k8s.io/api/networking/v1beta1"
"k8s.io/api/networking/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/wait"
"net/url"
Expand All @@ -18,36 +17,27 @@ type ingressExplorer struct {
log logr.Logger
client client.Client
scheme *runtime.Scheme
networkingIngresses []v1beta12.Ingress
extensionIngresses []v1beta1.Ingress
networkingIngresses []v1.Ingress
}

func (i *ingressExplorer) loadIngresses(ctx context.Context, ns string) error {
// Already loaded
if i.networkingIngresses != nil || i.extensionIngresses != nil {
if i.networkingIngresses != nil {
return nil
}
var errNet, errExt error
g := wait.Group{}
networkingIngresses := &v1beta12.IngressList{}
extensionIngresses := &v1beta1.IngressList{}
networkingIngresses := &v1.IngressList{}

if i.scheme.Recognizes(v1beta12.SchemeGroupVersion.WithKind("Ingress")) {
if i.scheme.Recognizes(v1.SchemeGroupVersion.WithKind("Ingress")) {
g.StartWithContext(ctx, func(ctx context.Context) {
errNet = i.client.List(ctx, networkingIngresses, client.InNamespace(ns))
})
}

if i.scheme.Recognizes(v1beta1.SchemeGroupVersion.WithKind("Ingress")) {
g.StartWithContext(ctx, func(ctx context.Context) {
errExt = i.client.List(ctx, extensionIngresses, client.InNamespace(ns))
})
}

g.Wait()

i.networkingIngresses = networkingIngresses.Items
i.extensionIngresses = extensionIngresses.Items

// Return either error
if errExt != nil {
Expand All @@ -57,62 +47,18 @@ func (i *ingressExplorer) loadIngresses(ctx context.Context, ns string) error {
}

func (i *ingressExplorer) getIngressUrl(serviceName string, servicePort int32) *url.URL {
if url := i.getExtensionIngressUrl(serviceName, servicePort); url != nil {
return url
}
return i.getNetworkingIngressUrl(serviceName, servicePort)
}

func (i *ingressExplorer) getExtensionIngressUrl(serviceName string, servicePort int32) *url.URL {
// Find the service name
for _, ing := range i.extensionIngresses {
for _, rule := range ing.Spec.Rules {
if rule.HTTP != nil {
for _, path := range rule.HTTP.Paths {
if path.Backend.ServiceName == serviceName {
// Are we referencing the service name?
if path.Backend.ServicePort.StrVal == "http" || path.Backend.ServicePort.IntVal == servicePort {
host := i.getActualExtensionHost(rule.Host, ing)
if host == "" {
return nil
}
return &url.URL{
Scheme: i.getSchemeFromExtensionIngress(ing, host),
Host: host,
Path: path.Path,
}
}
}
}
}
}
}
return nil
}

func (i *ingressExplorer) getActualExtensionHost(host string, ingress v1beta1.Ingress) string {
if host != "" {
return host
}
if len(ingress.Status.LoadBalancer.Ingress) == 0 {
return ""
}
// Take first host defined for the ingress
if ingress.Status.LoadBalancer.Ingress[0].Hostname != "" {
return ingress.Status.LoadBalancer.Ingress[0].Hostname
}
return ingress.Status.LoadBalancer.Ingress[0].IP
}

func (i *ingressExplorer) getNetworkingIngressUrl(serviceName string, servicePort int32) *url.URL {
// Find the service name
for _, ing := range i.networkingIngresses {
for _, rule := range ing.Spec.Rules {
if rule.HTTP != nil {
for _, path := range rule.HTTP.Paths {
if path.Backend.ServiceName == serviceName {
if path.Backend.Service.Name == serviceName {
// Are we referencing the service name?
if path.Backend.ServicePort.StrVal == "http" || path.Backend.ServicePort.IntVal == servicePort {
if path.Backend.Service.Port.Name == "http" || path.Backend.Service.Port.Number == servicePort {
host := i.getActualNetworkingHost(rule.Host, ing)
if host == "" {
return nil
Expand All @@ -131,14 +77,17 @@ func (i *ingressExplorer) getNetworkingIngressUrl(serviceName string, servicePor
return nil
}

func (i *ingressExplorer) getActualNetworkingHost(host string, ingress v1beta12.Ingress) string {
func (i *ingressExplorer) getActualNetworkingHost(host string, ingress v1.Ingress) string {
if host != "" {
return host
}
if len(ingress.Status.LoadBalancer.Ingress) == 0 {
return ""
}
return ingress.Status.LoadBalancer.Ingress[0].Hostname
if ingress.Status.LoadBalancer.Ingress[0].Hostname != "" {
return ingress.Status.LoadBalancer.Ingress[0].Hostname
}
return ingress.Status.LoadBalancer.Ingress[0].IP
}

func guessGatePort(ctx context.Context, svc interfaces.SpinnakerService) int32 {
Expand All @@ -150,18 +99,7 @@ func guessGatePort(ctx context.Context, svc interfaces.SpinnakerService) int32 {
return util.GateDefaultPort
}

func (i *ingressExplorer) getSchemeFromExtensionIngress(ingress v1beta1.Ingress, host string) string {
for _, tls := range ingress.Spec.TLS {
for _, h := range tls.Hosts {
if h == host {
return "https"
}
}
}
return "http"
}

func (i *ingressExplorer) getSchemeFromNetworkingIngress(ingress v1beta12.Ingress, host string) string {
func (i *ingressExplorer) getSchemeFromNetworkingIngress(ingress v1.Ingress, host string) string {
for _, tls := range ingress.Spec.TLS {
for _, h := range tls.Hosts {
if h == host {
Expand Down
Loading

0 comments on commit 8424836

Please sign in to comment.