fkorotkov / k8s-kotlin-dsl

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

Issue generating deployment template #27

Closed brizzbuzz closed 4 years ago

brizzbuzz commented 4 years ago

Hi,

I'm having issues generating a valid deployment, hopefully this is just an easy error in my DSL. In trying to follow the kubernetes docs for deployments, I thought it would be a good "hello world" to try to recreate this deployment with Kotlin

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

My attempt thus far has lead me to the following DSL

class SimpleDeployment : Deployment() {
  init {
    metadata {
      name = "nginx-deployment"
      labels = mapOf("app" to "nginx")
    }
    spec {
      replicas = 3
      selector {
        matchLabels = mapOf(
          "app" to "nginx"
        )
      }
      template {
        metadata {
          labels = mapOf("app" to "nginx")
        }
        spec {
          newContainer {
            name = "nginx"
            image = "nginx:1.14.2"
            ports = listOf(newContainerPort { containerPort = 80 })
          }
        }
      }
    }
  }
}

Unfortunately, this code block seems to sorta fizzle out at the template block, because the resulting YAML is

apiVersion: "apps/v1"
kind: "Deployment"
metadata:
  labels:
    app: "nginx"
  name: "nginx-deployment"
spec:
  replicas: 3
  selector:
    matchLabels:
      app: "nginx"
  template: {}

I'm pretty new to Kotlin and in all honest am kind of struggling to debug it 😕

Currently I am using the following versions

  val kFabric8Version = "2.8"
  val fabric8Version = "4.10.3"
  ... 
  implementation("com.fkorotkov:kubernetes-dsl:$kFabric8Version")
  implementation("io.fabric8:kubernetes-client:$fabric8Version")

Any tips/advice would be amazing!

fkorotkov commented 4 years ago

I think you are missing to assign your container to `containers field:

containers = listOf(
  newContainer {
    name = "nginx"
    image = "nginx:1.14.2"
    ports = listOf(newContainerPort { containerPort = 80 })
  }
)
brizzbuzz commented 4 years ago

Ahhh fantastic... it was a bit more involved but that change pointed out several issues. Though now I could use some kotlin knowledge 😅 it seems as though

...
spec {
  containers = ...
}

is invalid, with no val containers expected.. However..

spec = newPodSpec {
  containers = ...
}

Did the trick... Similarly for template metadata, simply doing the following was insufficient

template {
  metadata {
     ...
  }
}

But this worked

template {
  metadata = newObjectMeta {
    ...
  }
}

This kinda led me down the rabbit hole... looking at newObjectMeta for example

newObjectMeta(block : model_ObjectMeta.() -> Unit = {}): model_ObjectMeta { ... }

The return type is model_ObjectMeta

Now, looking at

metadata { .. }

This corresponds to

fun  apps_Deployment.`metadata`(block: model_ObjectMeta.() -> Unit = {}) {
  if(this.`metadata` == null) {
    this.`metadata` = model_ObjectMeta()
  }

  this.`metadata`.block()
}

which to my understanding, should take a model_ObjectMeta internal block, and set it to the metadata directly.

So I guess super long story made short, I don't understand why one way works and the other doesn't 😄

fkorotkov commented 4 years ago

It might depend on what kind of imports you have. There is. a working example here: https://github.com/fkorotkov/k8s-kotlin-dsl/blob/master/example/src/main/kotlin/BaseDeployment.kt