fkorotkov / k8s-kotlin-dsl

Kotlin DSL for Kubernetes configs
MIT License
342 stars 19 forks source link

Defining ingress backend with port instead of servicePort #35

Closed rrva closed 2 years ago

rrva commented 2 years ago

If I have a desired yaml definition of an ingress like this

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: myapp-reader-feature-internal
  namespace: myteam
  annotations:
    nginx.ingress.kubernetes.io/configuration-snippet: |
      proxy_set_header l5d-dst-override $service_name.$namespace.svc.$clusterDomain:$service_port;
      grpc_set_header l5d-dst-override $service_name.$namespace.svc.$clusterDomain:$service_port;
  labels:
    app: myapp-reader-feature

spec:
  tls:
  - hosts:
    - myteam-myapp-feature.dev.example.com
  rules:
  - host: myteam-myapp-feature.dev.example.com
    http:
      paths:
      - backend:
          service:
            name: myapp-reader-feature
            port:
              number: 8080
        pathType: ImplementationSpecific

I have not found a way to model the spec.rules.http.paths.backend correctly. What I am doing is this

fun myingress(): HasMetadata {
    return newIngress {
        apiVersion = "networking.k8s.io/v1"
        metadata {
            name = "myapp-feature-internal"
            namespace = "myteam"
            annotations = mapOf(
                "nginx.ingress.kubernetes.io/configuration-snippet" to
                        """
                           proxy_set_header l5d-dst-override ${"$"}service_name.${"$"}namespace.svc.${"$"}clusterDomain:${"$"}service_port;
                           grpc_set_header l5d-dst-override ${"$"}service_name.${"$"}namespace.svc.${"$"}clusterDomain:${"$"}service_port;""".trimIndent()
            )
            labels = mapOf("app" to "myapp-feature")
        }
        spec {
            newIngressTLS {
                hosts = listOf("myteam-myapp-feature.example.com")
            }
            rules = listOf(newIngressRule {
                host = "myteam-myapp-feature.example.com"
                http = newHTTPIngressRuleValue {
                    paths = listOf(newHTTPIngressPath {
                        backend {
                            serviceName = "myapp-feature"
                            servicePort = IntOrString(8080)
                        }
                        pathType = "ImplementationSpecific"
                    })
                }
            })
        }
    }
}

Which gives me

---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/configuration-snippet: |-
      proxy_set_header l5d-dst-override $service_name.$namespace.svc.$clusterDomain:$service_port;
      grpc_set_header l5d-dst-override $service_name.$namespace.svc.$clusterDomain:$service_port;
  labels:
    app: myapp-feature
  name: myapp-feature-internal
  namespace: myteam
spec:
  rules:
  - host: myteam-myapp-feature.example.com
    http:
      paths:
      - backend:
          serviceName: myapp-feature
          servicePort: 8080
        pathType: ImplementationSpecific

There seems to be no way to express this part:

      - backend:
          service:
            name: myapp-feature
            port:
              number: 8080

The resulting yaml from the above kotlin code is even flagged as invalid kubernetes yaml when linting it.

Using these versions:

    implementation("com.github.fkorotkov:k8s-kotlin-dsl:3.1.1")
    implementation("io.fabric8:kubernetes-client:5.11.1")
rrva commented 2 years ago

Wrong apiVersion defined. Should have been apiVersion = "networking.k8s.io/v1beta1". Works now.