Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[JENKINS-50282] Allow creating Pod templates from yaml #275

Merged
merged 9 commits into from
Apr 1, 2018
Merged

Conversation

carlossg
Copy link
Contributor

To avoid having to manually add fields for all possible options current and future, just pass the yaml to be used as base.

Yaml is merged with other fields (if set) as it if were a parent Podtemplate

@carlossg carlossg changed the title Allow creating Pod templates from yaml [WiP] Allow creating Pod templates from yaml Jan 21, 2018
@chancez
Copy link
Contributor

chancez commented Jan 23, 2018

This is awesome. I am a huge supporter of this being a feature. 👍 This would mean I don't need to add explicit support for using taints/tolerations and other things, making many things easier!

Will the JNLP container be merged into the resulting pod template automatically with this?

@carlossg
Copy link
Contributor Author

Yes, if yaml doesn't include a jnlp container it will be added

@azweb76
Copy link

azweb76 commented Jan 24, 2018

So we use a jnlp container. Correct me if Im wrong, if the container is a jnlp container, it will not be merged?

@hoshsadiq
Copy link
Contributor

Big. Would also be nice to be able to load it from a file rather than as a string.

@chancez
Copy link
Contributor

chancez commented Feb 16, 2018

ALso, what does this mean for the declarative step? If it supported the yaml form, it would fix most of my issues with the declarative steps, assuming you could also use container() steps within.

@carlossg carlossg changed the title [WiP] Allow creating Pod templates from yaml [WiP][JENKINS-50282] Allow creating Pod templates from yaml Mar 20, 2018
@carlossg carlossg changed the title [WiP][JENKINS-50282] Allow creating Pod templates from yaml [JENKINS-50282] Allow creating Pod templates from yaml Mar 30, 2018
@carlossg
Copy link
Contributor Author

The rules from combination parent/yaml Pod and child Pod are set in

public static Pod combine(Pod parent, Pod template) {

Containers are also merged if present in both parent and child with the same name

To read from file instead of inline just use readFile

return this;
}

@Deprecated
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is a new deprecated method being added?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this one is not new, the new one is public Pod build()

@carlossg carlossg merged commit bbf9a20 into master Apr 1, 2018
@carlossg carlossg deleted the yaml branch April 1, 2018 18:47
@bbzg
Copy link

bbzg commented Apr 1, 2018

This is a great addition, but adding a yaml template for 5+ Jenkinsfiles quickly becomes a chore... It would have been so nice if it was possible to set the template from the global Jenkins configuration (since all our jobs share the same settings). Maybe it already is, but I can not seem to find it.

Maybe I am speaking out of line, if I am I apologize.

Thanks for all your great work!

@carlossg
Copy link
Contributor Author

carlossg commented Apr 1, 2018

That just needs the jelly UI code, PRs welcome

@siwyd
Copy link

siwyd commented Apr 2, 2018

@bbzg You can use a Jenkins shared library to define a function that keeps all that logic in a single place?

@bbzg
Copy link

bbzg commented Apr 2, 2018

@siwyd Hmm, that's a good idea actually since we already have that for other stuff. Thanks!

@bbzg
Copy link

bbzg commented Apr 2, 2018

def kubernetesNode(Closure closureForPod) {
    String template = """
apiVersion: v1
kind: Pod
metadata:
  labels:
    test: something
spec:
  tolerations:
  - key: "jenkins"
    operator: "Equal"
    value: "builder"
    effect: "NoSchedule"
"""
    GString label = "default-${UUID.randomUUID().toString()}"
    podTemplate(label: label, yaml: template, inheritFrom: "default") {
        node {
            closureForPod.call()
        }
    }
}

This schedules a pod but it does not get any of the attributes from the YAML

I also tried without "inheritFrom" and used name: "default", but with the same result.

(I am using scripted pipeline btw)

Any pointers would be greatly appreciated.

Edit:
For clarification I have a "Cloud" called "kubernetes" and a "Kubernetes pod template" called "default" with a bunch of settings that I want to (re-)use.

@bbzg
Copy link

bbzg commented Apr 2, 2018

I finally got it working with these settings

def kubernetesNode(Closure closureForPod) {
    String template = """
apiVersion: v1
kind: Pod
metadata:
  labels:
    test: something
spec:
  tolerations:
  - key: "jenkins"
    operator: "Equal"
    value: "builder"
    effect: "NoSchedule"
"""
    GString label = "default-${UUID.randomUUID().toString()}"
    podTemplate(label: label, yaml: template) {
        node(label) {
            closureForPod.call()
        }
    }
}

And in the global configuration for the Kubernetes plugin I set Defaults Provider Template Name to default

@rlees85
Copy link

rlees85 commented Apr 3, 2018

I think this change has broken something. I am not using this new feature, but a plugin upgrade from 1.4.1 to 1.5 and a pod with an emptyDir and valid mountpath now just throws this error:

WARNING: Error in provisioning; agent=KubernetesSlave name: packer-slave-xz2bp, template=PodTemplate{inheritFrom='', name='packer-slave', namespace='devops-testing', instanceCap=25, idleMinutes=5, label='packer', nodeSelector='', nodeUsageMode=EXCLUSIVE, workspaceVolume=org.csanchez.jenkins.plugins.kubernetes.volumes.workspace.EmptyDirWorkspaceVolume@48b9a7ee, volumes=[org.csanchez.jenkins.plugins.kubernetes.volumes.EmptyDirVolume@14e5dc74], containers=[ContainerTemplate{name='jnlp', image='removed.dkr.ecr.eu-west-1.amazonaws.com/jenkins-slave-packer:latest', alwaysPullImage=true, workingDir='/home/jenkins', command='', args='${computer.jnlpmac} ${computer.name}', ttyEnabled=true, resourceRequestCpu='', resourceRequestMemory='512Mi', resourceLimitCpu='', resourceLimitMemory='512Mi', envVars=[KeyValueEnvVar [getValue()=-Xmx256M -Xms256M, getKey()=JAVA_OPTS], KeyValueEnvVar [getValue()=tcp://localhost:2375 , getKey()=DOCKER_HOST]], livenessProbe=org.csanchez.jenkins.plugins.kubernetes.ContainerLivenessProbe@8e44d37}, ContainerTemplate{name='docker', image='docker:stable-dind', privileged=true, alwaysPullImage=true, workingDir='', command='', args='', resourceRequestCpu='', resourceRequestMemory='512Mi', resourceLimitCpu='', resourceLimitMemory='512Mi', livenessProbe=org.csanchez.jenkins.plugins.kubernetes.ContainerLivenessProbe@53a14519}], annotations=[org.csanchez.jenkins.plugins.kubernetes.PodAnnotation@6bd82452]}
io.fabric8.kubernetes.client.KubernetesClientException: Failure executing: POST at: https://api.removed/api/v1/namespaces/devops-testing/pods. Message: Pod "packer-slave-xz2bp" is invalid: spec.containers[1].volumeMounts[1].mountPath: Required value. Received status: Status(apiVersion=v1, code=422, details=StatusDetails(causes=[StatusCause(field=spec.containers[1].volumeMounts[1].mountPath, message=Required value, reason=FieldValueRequired, additionalProperties={})], group=null, kind=Pod, name=packer-slave-xz2bp, retryAfterSeconds=null, uid=null, additionalProperties={}), kind=Status, message=Pod "packer-slave-xz2bp" is invalid: spec.containers[1].volumeMounts[1].mountPath: Required value, metadata=ListMeta(resourceVersion=null, selfLink=null, additionalProperties={}), reason=Invalid, status=Failure, additionalProperties={}).
	at io.fabric8.kubernetes.client.dsl.base.OperationSupport.requestFailure(OperationSupport.java:472)
	at io.fabric8.kubernetes.client.dsl.base.OperationSupport.assertResponseCode(OperationSupport.java:411)
	at io.fabric8.kubernetes.client.dsl.base.OperationSupport.handleResponse(OperationSupport.java:381)
	at io.fabric8.kubernetes.client.dsl.base.OperationSupport.handleResponse(OperationSupport.java:344)
	at io.fabric8.kubernetes.client.dsl.base.OperationSupport.handleCreate(OperationSupport.java:227)
	at io.fabric8.kubernetes.client.dsl.base.BaseOperation.handleCreate(BaseOperation.java:756)
	at io.fabric8.kubernetes.client.dsl.base.BaseOperation.create(BaseOperation.java:334)
	at org.csanchez.jenkins.plugins.kubernetes.KubernetesLauncher.launch(KubernetesLauncher.java:105)
	at hudson.slaves.SlaveComputer$1.call(SlaveComputer.java:288)
	at jenkins.util.ContextResettingExecutorService$2.call(ContextResettingExecutorService.java:46)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)

Jenkins LTS latest

@carlossg
Copy link
Contributor Author

carlossg commented Apr 3, 2018

@bparees
Copy link
Contributor

bparees commented Apr 10, 2018

@carlossg any thoughts about exposing this in the config.xml (so you can paste a pod template yaml into the k8s cloud plugin config ui, instead of having to define it in your pipeline)? Or is this already possible and i'm missing it?

/cc @gabemontero

@carlossg
Copy link
Contributor Author

it's just a matter of adding a new yaml field to https://github.com/jenkinsci/kubernetes-plugin/blob/master/src/main/resources/org/csanchez/jenkins/plugins/kubernetes/PodTemplate/config.jelly and associated help file.
Lack of time on my side, PRs welcome

@bparees
Copy link
Contributor

bparees commented Apr 10, 2018

@carlossg we might be able to carve some cycles from @gabemontero to do it in the next few weeks.

@shdowofdeath
Copy link

i cannot use it like this :

containerTemplate(name: 'basic',
                            image: slaveImage,
                            ttyEnabled: true,
                            shell: 'sh',
                            envVars: [ valueFrom(key: 'parentHost', fieldRef:  "status.hostIP")
                            ],
                            privileged: true,
                            workingDir: '/data/',
                            alwaysPullImage: false,

?? it;s not woking for me

@jasminen
Copy link

@shdowofdeath It works if you use the 'yaml' attribute

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants