jenkinsci / docker-plugin

Jenkins cloud plugin that uses Docker
https://plugins.jenkins.io/docker-plugin/
MIT License
486 stars 322 forks source link

Unexpected change in volumes/mounts syntax breaks existing CasC configuration #852

Closed Crosse closed 2 years ago

Crosse commented 2 years ago

Version report

Jenkins and plugins versions report:

Jenkins: 2.289.2
OS: Linux - 5.13.12-200.fc34.x86_64
---
docker-commons:1.17
docker-java-api:3.1.5.2
docker-plugin:1.2.3
docker-workflow:1.26
(Click here for full plugins list)
ace-editor:1.1
analysis-model-api:10.3.0
ansicolor:1.0.0
ant:1.11
antisamy-markup-formatter:2.1
apache-httpcomponents-client-4-api:4.5.13-1.0
artifactory:3.13.1
authentication-tokens:1.4
authorize-project:1.4.0
blueocean:1.24.8
blueocean-autofavorite:1.2.4
blueocean-bitbucket-pipeline:1.24.8
blueocean-commons:1.24.8
blueocean-config:1.24.8
blueocean-core-js:1.24.8
blueocean-dashboard:1.24.8
blueocean-display-url:2.4.1
blueocean-events:1.24.8
blueocean-git-pipeline:1.24.8
blueocean-github-pipeline:1.24.8
blueocean-i18n:1.24.8
blueocean-jira:1.24.8
blueocean-jwt:1.24.8
blueocean-personalization:1.24.8
blueocean-pipeline-api-impl:1.24.8
blueocean-pipeline-editor:1.24.8
blueocean-pipeline-scm-api:1.24.8
blueocean-rest:1.24.8
blueocean-rest-impl:1.24.8
blueocean-web:1.24.8
bootstrap4-api:4.6.0-3
bootstrap5-api:5.1.0-3
bouncycastle-api:2.24
branch-api:2.6.5
build-name-setter:2.2.0
build-timestamp:1.0.3
built-on-column:1.1
caffeine-api:2.9.2-29.v717aac953ff3
checks-api:1.7.2
cloudbees-bitbucket-branch-source:2.9.11
cloudbees-folder:6.16
cloudbees-jenkins-advisor:3.3.1
command-launcher:1.6
conditional-buildstep:1.4.1
config-file-provider:3.8.1
configuration-as-code:1.52
credentials:2.5
credentials-binding:1.27
custom-folder-icon:1.7
dashboard-view:2.17
data-tables-api:1.10.25-3
display-url-api:2.3.5
docker-commons:1.17
docker-java-api:3.1.5.2
docker-plugin:1.2.3
docker-workflow:1.26
durable-task:1.39
echarts-api:5.1.2-11
email-ext:2.83
emailext-template:1.2
embeddable-build-status:2.0.3
envinject:2.4.0
envinject-api:1.7
extended-choice-parameter:0.82
external-monitor-job:1.7
favorite:2.3.3
font-awesome-api:5.15.4-1
forensics-api:1.3.0
generic-webhook-trigger:1.76
git:4.8.2
git-client:3.9.0
git-forensics:1.2.0
git-parameter:0.9.13
git-server:1.10
github:1.34.1
github-api:1.123
github-branch-source:2.11.2
github-checks:1.0.13
github-oauth:0.33
gradle:1.37.1
greenballs:1.15.1
handlebars:3.0.8
handy-uri-templates-2-api:2.1.8-1.0
htmlpublisher:1.25
http_request:1.11
ivy:2.1
jackson2-api:2.12.4
javadoc:1.6
jaxb:2.3.0.1
jdk-tool:1.5
jenkins-design-language:1.24.8
jenkins-multijob-plugin:1.36
jira:3.5
jjwt-api:0.11.2-9.c8b45b8bb173
job-dsl:1.77
job-import-plugin:3.5-SNAPSHOT (private-564c44fa-seth.wright)
jquery:1.12.4-1
jquery-detached:1.2.1
jquery3-api:3.6.0-2
jsch:0.1.55.2
junit:1.53
kubernetes:1.30.1
kubernetes-client-api:5.4.1
kubernetes-credentials:0.9.0
ldap:2.7
leastload:3.0.0
mailer:1.34
matrix-auth:2.6.8
matrix-project:1.19
maven-plugin:3.12
mercurial:2.15
metrics:4.0.2.8
momentjs:1.1.1
okhttp-api:3.14.9
pam-auth:1.6
parameterized-trigger:2.41
pipeline-build-step:2.15
pipeline-graph-analysis:1.11
pipeline-input-step:2.12
pipeline-milestone-step:1.3.2
pipeline-model-api:1.9.1
pipeline-model-definition:1.9.1
pipeline-model-extensions:1.9.1
pipeline-rest-api:2.19
pipeline-stage-step:2.5
pipeline-stage-tags-metadata:1.9.1
pipeline-stage-view:2.19
pipeline-utility-steps:2.10.0
plain-credentials:1.7
plugin-util-api:2.4.0
popper-api:1.16.1-2
popper2-api:2.9.3-1
pubsub-light:1.16
rebuild:1.32
resource-disposer:0.16
robot:3.0.1
run-condition:1.5
scm-api:2.6.5
script-security:1.78
simple-theme-plugin:0.7
skip-notifications-trait:1.0.5
snakeyaml-api:1.29.1
sse-gateway:1.24
ssh:2.6.1
ssh-agent:1.23
ssh-credentials:1.19
ssh-slaves:1.33.0
sshd:3.1.0
structs:1.23
support-core:2.75
throttle-concurrents:2.4
timestamper:1.13
token-macro:266.v44a80cf277fd
trilead-api:1.0.13
uno-choice:2.5.6
variant:1.4
warnings-ng:9.5.0
windows-slaves:1.8
workflow-api:2.46
workflow-basic-steps:2.24
workflow-cps:2.93
workflow-cps-global-lib:2.21
workflow-durable-task-step:2.39
workflow-job:2.41
workflow-multibranch:2.26
workflow-scm-step:2.13
workflow-step-api:2.24
workflow-support:3.8
ws-cleanup:0.39

Controller and agents are running under Linux (specifically Fedora CoreOS 34)

Reproduction steps

Prior to v1.2.3, the following CasC snippet worked (ref):

x-jenkins-docker-volumes: &jenkins_docker_volumes_anchor
  volumes:
    - "rust-registry:/home/jenkins/.cargo/registry:rw"
    - "gradle-cache:/home/jenkins/.gradle:rw"
    - "go-cache:/home/jenkins/.cache/go:rw"
    - "jenkins-workdir:/home/jenkins/agent:rw"
    - "jenkins-workspace:/home/jenkins/workspace:rw"

Due to #826 (I think), this syntax stopped working with v1.2.3 of this plugin. I had to change all of my volumes and volumesString references to mounts and mountsString, respectively.

Results

Expected result:

Jenkins to restart and CasC to process my configuration successfully.

Actual result:

I didn't see a change log or other indication that I needed to change my Configuration as Code syntax for this release, so the stack trace Jenkins threw at me on restart was unexpected. 😄

io.jenkins.plugins.casc.ConfiguratorException: Invalid configuration elements for type class com.nirima.jenkins.plugins.docker.DockerTemplateBase : volumesString,volumes.
Available attributes : bindAllPorts, bindPorts, capabilitiesToAdd, capabilitiesToAddString, capabilitiesToDrop, capabilitiesToDropString, cpuPeriod, cpuQuota, cpuShares, devices, devicesString, dnsHosts, dnsString, dockerCommand, environment, environmentsString, extraDockerLabelsString, extraGroups, extraGroupsString, extraHosts, extraHostsString, hostname, image, macAddress, memoryLimit, memorySwap, mounts, mountsString, network, privileged, pullCredentialsId, securityOpts, securityOptsString, shmSize, tty, user, volumesFrom2, volumesFromString
    at io.jenkins.plugins.casc.BaseConfigurator.handleUnknown(BaseConfigurator.java:376)
    at io.jenkins.plugins.casc.BaseConfigurator.configure(BaseConfigurator.java:365)
    at io.jenkins.plugins.casc.BaseConfigurator.configure(BaseConfigurator.java:276)
    at io.jenkins.plugins.casc.impl.configurators.DataBoundConfigurator.configure(DataBoundConfigurator.java:82)
    at io.jenkins.plugins.casc.impl.configurators.DataBoundConfigurator.tryConstructor(DataBoundConfigurator.java:159)
    at io.jenkins.plugins.casc.impl.configurators.DataBoundConfigurator.instance(DataBoundConfigurator.java:76)
    at io.jenkins.plugins.casc.BaseConfigurator.configure(BaseConfigurator.java:267)
    at io.jenkins.plugins.casc.impl.configurators.DataBoundConfigurator.configure(DataBoundConfigurator.java:82)
    at io.jenkins.plugins.casc.impl.configurators.DataBoundConfigurator.tryConstructor(DataBoundConfigurator.java:151)
    at io.jenkins.plugins.casc.impl.configurators.DataBoundConfigurator.instance(DataBoundConfigurator.java:76)
    at io.jenkins.plugins.casc.BaseConfigurator.configure(BaseConfigurator.java:267)
    at io.jenkins.plugins.casc.impl.configurators.DataBoundConfigurator.configure(DataBoundConfigurator.java:82)
    at io.jenkins.plugins.casc.impl.configurators.HeteroDescribableConfigurator.lambda$doConfigure$16668e2$1(HeteroDescribableConfigurator.java:277)
    at io.vavr.CheckedFunction0.lambda$unchecked$52349c75$1(CheckedFunction0.java:247)
    at io.jenkins.plugins.casc.impl.configurators.HeteroDescribableConfigurator.doConfigure(HeteroDescribableConfigurator.java:277)
    at io.jenkins.plugins.casc.impl.configurators.HeteroDescribableConfigurator.lambda$configure$2(HeteroDescribableConfigurator.java:86)
    at io.vavr.control.Option.map(Option.java:392)
    at io.jenkins.plugins.casc.impl.configurators.HeteroDescribableConfigurator.lambda$configure$3(HeteroDescribableConfigurator.java:86)
    at io.vavr.Tuple2.apply(Tuple2.java:238)
    at io.jenkins.plugins.casc.impl.configurators.HeteroDescribableConfigurator.configure(HeteroDescribableConfigurator.java:83)
    at io.jenkins.plugins.casc.impl.configurators.HeteroDescribableConfigurator.check(HeteroDescribableConfigurator.java:92)
    at io.jenkins.plugins.casc.impl.configurators.HeteroDescribableConfigurator.check(HeteroDescribableConfigurator.java:55)
    at io.jenkins.plugins.casc.BaseConfigurator.configure(BaseConfigurator.java:344)
    at io.jenkins.plugins.casc.BaseConfigurator.check(BaseConfigurator.java:287)
    at io.jenkins.plugins.casc.ConfigurationAsCode.lambda$checkWith$8(ConfigurationAsCode.java:777)
    at io.jenkins.plugins.casc.ConfigurationAsCode.invokeWith(ConfigurationAsCode.java:713)
Caused: io.jenkins.plugins.casc.ConfiguratorException: jenkins: error configuring 'jenkins' with class io.jenkins.plugins.casc.core.JenkinsConfigurator configurator
    at io.jenkins.plugins.casc.ConfigurationAsCode.invokeWith(ConfigurationAsCode.java:719)
    at io.jenkins.plugins.casc.ConfigurationAsCode.checkWith(ConfigurationAsCode.java:777)
    at io.jenkins.plugins.casc.ConfigurationAsCode.configureWith(ConfigurationAsCode.java:762)
    at io.jenkins.plugins.casc.ConfigurationAsCode.configureWith(ConfigurationAsCode.java:638)
    at io.jenkins.plugins.casc.ConfigurationAsCode.configure(ConfigurationAsCode.java:307)
    at io.jenkins.plugins.casc.ConfigurationAsCode.init(ConfigurationAsCode.java:299)
Caused: java.lang.reflect.InvocationTargetException
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at hudson.init.TaskMethodFinder.invoke(TaskMethodFinder.java:104)
Caused: java.lang.Error
    at hudson.init.TaskMethodFinder.invoke(TaskMethodFinder.java:110)
    at hudson.init.TaskMethodFinder$TaskImpl.run(TaskMethodFinder.java:175)
    at org.jvnet.hudson.reactor.Reactor.runTask(Reactor.java:296)
    at jenkins.model.Jenkins$5.runTask(Jenkins.java:1129)
    at org.jvnet.hudson.reactor.Reactor$2.run(Reactor.java:214)
    at org.jvnet.hudson.reactor.Reactor$Node.run(Reactor.java:117)
    at jenkins.security.ImpersonatingExecutorService$1.run(ImpersonatingExecutorService.java:68)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
    at java.base/java.lang.Thread.run(Thread.java:829)
2021-09-08 14:26:06.570+0000 [id=23]    SEVERE  hudson.util.BootFailure#publish: Failed to initialize Jenkins

At a minimum it might be a good idea to get the CasC example updated. I can put a PR in for that if necessary.

bguerin commented 2 years ago

At a minimum it might be a good idea to get the CasC example updated

done : https://github.com/jenkinsci/configuration-as-code-plugin/pull/1960

pjdarton commented 2 years ago

It sounds like this was an undesired consequence of #826

In hindsight, maybe we shouldn't have removed support for volumes and simply added support for mounts so that both are supported - they're very similar in function, but mounts are not quite a like-for-like replacement. e.g. I personally discovered (albeit too late, when parts of my build environment stopped working) that mounts require things to exist whereas volumes are more fault-tolerant. Lesson learned - never ever remove functionality...

So, if anyone wants to make a PR that re-adds support for volumes (ideally adding a warning in the UI that folks should use probably use mounts instead, maybe even using the existing migration code to tell the user exactly how to do that), that could make all these issues go away.

Crosse commented 2 years ago

While I no longer use Jenkins, I'm sure this will be a welcome fix for other users. Thank you!