12

I am trying to use the Jenkins API with curl to create a new job, on Ubuntu 17.10. I'm following the example on this thread. Creating the crumb works well. However, the call to create the job fails with a stack trace with root cause:

[edited to add the rest of the stack trace]

org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1; Premature end of file.
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1239)
    at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transformIdentity(TransformerImpl.java:668)
    at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:737)
    at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:351)
    at jenkins.util.xml.XMLUtils._transform(XMLUtils.java:212)
    at jenkins.util.xml.XMLUtils.safeTransform(XMLUtils.java:84)
    at hudson.model.ItemGroupMixIn.createProjectFromXML(ItemGroupMixIn.java:272)
    at hudson.model.ItemGroupMixIn.createTopLevelItem(ItemGroupMixIn.java:189)
    at jenkins.model.Jenkins.doCreateItem(Jenkins.java:3816)
    at java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:627)
    at org.kohsuke.stapler.Function$MethodFunction.invoke(Function.java:343)
    at org.kohsuke.stapler.interceptor.RequirePOST$Processor.invoke(RequirePOST.java:77)
    at org.kohsuke.stapler.PreInvokeInterceptedFunction.invoke(PreInvokeInterceptedFunction.java:26)
    at org.kohsuke.stapler.Function.bindAndInvoke(Function.java:184)
    at org.kohsuke.stapler.Function.bindAndInvokeAndServeResponse(Function.java:117)
    at org.kohsuke.stapler.MetaClass$1.doDispatch(MetaClass.java:129)
    at org.kohsuke.stapler.NameBasedDispatcher.dispatch(NameBasedDispatcher.java:58)
    at org.kohsuke.stapler.Stapler.tryInvoke(Stapler.java:715)
    at org.kohsuke.stapler.Stapler.invoke(Stapler.java:845)
    at org.kohsuke.stapler.Stapler.invoke(Stapler.java:649)
    at org.kohsuke.stapler.Stapler.service(Stapler.java:238)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
    at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:841)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1650)
    at hudson.util.PluginServletFilter$1.doFilter(PluginServletFilter.java:154)
    at hudson.util.PluginServletFilter.doFilter(PluginServletFilter.java:157)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1637)
    at jenkins.security.ApiCrumbExclusion.process(ApiCrumbExclusion.java:48)
    at hudson.security.csrf.CrumbFilter.doFilter(CrumbFilter.java:73)
    ...
Caused: java.io.IOException: Failed to persist config.xml
    at hudson.model.ItemGroupMixIn.createProjectFromXML(ItemGroupMixIn.java:292)
    at hudson.model.ItemGroupMixIn.createTopLevelItem(ItemGroupMixIn.java:189)
    at jenkins.model.Jenkins.doCreateItem(Jenkins.java:3816)
    at java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:627)
    at org.kohsuke.stapler.Function$MethodFunction.invoke(Function.java:343)
    at org.kohsuke.stapler.interceptor.RequirePOST$Processor.invoke(RequirePOST.java:77)
    at org.kohsuke.stapler.PreInvokeInterceptedFunction.invoke(PreInvokeInterceptedFunction.java:26)
    at org.kohsuke.stapler.Function.bindAndInvoke(Function.java:184)
    at org.kohsuke.stapler.Function.bindAndInvokeAndServeResponse(Function.java:117)
    at org.kohsuke.stapler.MetaClass$1.doDispatch(MetaClass.java:129)
    at org.kohsuke.stapler.NameBasedDispatcher.dispatch(NameBasedDispatcher.java:58)
    at org.kohsuke.stapler.Stapler.tryInvoke(Stapler.java:715)
    at org.kohsuke.stapler.Stapler.invoke(Stapler.java:845)
    at org.kohsuke.stapler.Stapler.invoke(Stapler.java:649)
    at org.kohsuke.stapler.Stapler.service(Stapler.java:238)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
    at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:841)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1650)
    at hudson.util.PluginServletFilter$1.doFilter(PluginServletFilter.java:154)
    at hudson.util.PluginServletFilter.doFilter(PluginServletFilter.java:157)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1637)
    at jenkins.security.ApiCrumbExclusion.process(ApiCrumbExclusion.java:48)
    at hudson.security.csrf.CrumbFilter.doFilter(CrumbFilter.java:73)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1637)
    at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:84)
    at hudson.security.UnwrapSecurityExceptionFilter.doFilter(UnwrapSecurityExceptionFilter.java:51)
    at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
    at jenkins.security.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:117)
    at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
    at org.acegisecurity.providers.anonymous.AnonymousProcessingFilter.doFilter(AnonymousProcessingFilter.java:125)
    at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
    ...

The script file is:

CRUMB=$(curl -s 'http://<redacted>@localhost:8080/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,":",//crumb)')

echo ${CRUMB}

curl -X POST -H "$CRUMB" -H "content-type:application/xml" "http://<redacted>@localhost:8080/createItem?name=NewJob2"

[edit]

also tried with this variations, attempting to pass a basic config.xml file:

curl -X POST -H "$CRUMB" -H "content-type:application/xml" --data "@config.xml" "http://helo478:5ccf2750debe105962b1bf3a8483cfd8@localhost:8080/createItem?name=Test" --trace-ascii /dev/stdout
Don Subert
  • 2,636
  • 4
  • 27
  • 37
  • Has the jenkins write access to the folder? – S.Spieker Apr 04 '18 at 07:51
  • It must, right? I can use the GUI to do the same thing with no problems. – Don Subert Apr 07 '18 at 01:37
  • and also yes, it does. `drwxr-xr-x 15 jenkins jenkins 4096 Apr 3 17:33 jenkins` `-rw-r--r-- 1 jenkins jenkins 1825 Apr 3 17:33 config.xml` – Don Subert Apr 07 '18 at 02:10
  • I've also tried adding the user for which the crumb is created to the jenkins group. Still the same error – Don Subert Apr 07 '18 at 02:18
  • Looks like you haven't posted the entire stacktrace, the first like says `caused...`, which indicates that there were something else causing this. If possible, it would also help if we could se the config that you are trying to upload. – Jon S Apr 07 '18 at 06:52
  • The job "NewJob2" does not already exist? – S.Spieker Apr 07 '18 at 07:48
  • Try to remove `?name=NewJob2` – Ori Marko Apr 09 '18 at 12:48
  • @Jon S, excellent observation. I thought that said "caused by," rather than "caused." It appears in the opposite order that I usually see stack traces. I've added more of the error to the question. (I had to redact some lines, though, because system enforces a ratio of code/non-code in a question. If I had to guess, I think I'm supposed to be passing a config.xml. I had assumed that it would just create a basic one for me automatically. – Don Subert Apr 10 '18 at 03:25
  • @user7294900, I'm afraid that "Query parameter 'name' is required" – Don Subert Apr 10 '18 at 03:44
  • Hi, could you undelete this [post](https://stackoverflow.com/questions/64213590/azure-flask-app-services-resource-not-passing-environment-variables)? I want to add an answer, then it can help others. – Joy Wang Oct 09 '20 at 01:09

2 Answers2

3

Just posting an answer with what I noted as a comment. Looked like the entire stack trace was missing, the first line read caused... which indicates that there is more to the exception.

Additionally, I had a look at the source for the first stack trace frame, hudson.model.ItemGroupMixIn.createProjectFromXML line 292, from there it pretty obvious that there is something wrong with the uploaded XML file, which apparently weren't uploaded at all.

From the Jenkins API documentation, available at <jenkins instance root>/api/:

To create a new job, post config.xml to this URL with query parameter name=JOBNAME. You need to send a Content-Type: application/xml header. You will get a 200 status code if the creation is successful, or 4xx/5xx code if it fails. config.xml is the format Jenkins uses to store the project in the file system, so you can see examples of them in the Jenkins home directory, or by retrieving the XML configuration of existing jobs from /job/JOBNAME/config.xml.

Jon S
  • 15,846
  • 4
  • 44
  • 45
2

The API requires that a config.xml file be passed in the post data. I had assumed that, like the GUI, it would create a basic one, automatically. This is not the case

curl -X POST -H "$CRUMB" -H "content-type:application/xml" --data "@/home/helo478/Documents/config.xml" "http://helo478:5ccf2750debe105962b1bf3a8483cfd8@localhost:8080/createItem?name=Test5" --trace-ascii /dev/stdout

config.xml:

<?xml version='1.1' encoding='UTF-8'?>
<org.jenkinsci.plugins.workflow.multibranch.WorkflowMultiBranchProject plugin="workflow-multibranch@2.17">
  <actions/>
  <description></description>
  <displayName>Test5</displayName>
  <properties>
    <org.jenkinsci.plugins.pipeline.modeldefinition.config.FolderConfig plugin="pipeline-model-definition@1.2.7">
      <dockerLabel></dockerLabel>
      <registry plugin="docker-commons@1.11"/>
    </org.jenkinsci.plugins.pipeline.modeldefinition.config.FolderConfig>
  </properties>
  <folderViews class="jenkins.branch.MultiBranchProjectViewHolder" plugin="branch-api@2.0.18">
    <owner class="org.jenkinsci.plugins.workflow.multibranch.WorkflowMultiBranchProject" reference="../.."/>
  </folderViews>
  <healthMetrics>
    <com.cloudbees.hudson.plugins.folder.health.WorstChildHealthMetric plugin="cloudbees-folder@6.4">
      <nonRecursive>false</nonRecursive>
    </com.cloudbees.hudson.plugins.folder.health.WorstChildHealthMetric>
  </healthMetrics>
  <icon class="jenkins.branch.MetadataActionFolderIcon" plugin="branch-api@2.0.18">
    <owner class="org.jenkinsci.plugins.workflow.multibranch.WorkflowMultiBranchProject" reference="../.."/>
  </icon>
  <orphanedItemStrategy class="com.cloudbees.hudson.plugins.folder.computed.DefaultOrphanedItemStrategy" plugin="cloudbees-folder@6.4">
    <pruneDeadBranches>true</pruneDeadBranches>
    <daysToKeep>-1</daysToKeep>
    <numToKeep>-1</numToKeep>
  </orphanedItemStrategy>
  <triggers/>
  <disabled>false</disabled>
  <sources class="jenkins.branch.MultiBranchProject$BranchSourceList" plugin="branch-api@2.0.18">
    <data>
      <jenkins.branch.BranchSource>
        <source class="org.jenkinsci.plugins.github_branch_source.GitHubSCMSource" plugin="github-branch-source@2.3.3">
          <id>e514c038-dfd3-4748-99f1-8eb807276814</id>
          <credentialsId>54956458-e73d-45db-8ed1-04cb42a3612e</credentialsId>
          <repoOwner>helo478</repoOwner>
          <repository>agartha-web</repository>
          <traits>
            <org.jenkinsci.plugins.github__branch__source.BranchDiscoveryTrait>
              <strategyId>1</strategyId>
            </org.jenkinsci.plugins.github__branch__source.BranchDiscoveryTrait>
            <org.jenkinsci.plugins.github__branch__source.OriginPullRequestDiscoveryTrait>
              <strategyId>1</strategyId>
            </org.jenkinsci.plugins.github__branch__source.OriginPullRequestDiscoveryTrait>
            <org.jenkinsci.plugins.github__branch__source.ForkPullRequestDiscoveryTrait>
              <strategyId>1</strategyId>
              <trust class="org.jenkinsci.plugins.github_branch_source.ForkPullRequestDiscoveryTrait$TrustPermission"/>
            </org.jenkinsci.plugins.github__branch__source.ForkPullRequestDiscoveryTrait>
          </traits>
        </source>
        <strategy class="jenkins.branch.DefaultBranchPropertyStrategy">
          <properties class="empty-list"/>
        </strategy>
      </jenkins.branch.BranchSource>
    </data>
    <owner class="org.jenkinsci.plugins.workflow.multibranch.WorkflowMultiBranchProject" reference="../.."/>
  </sources>
  <factory class="org.jenkinsci.plugins.workflow.multibranch.WorkflowBranchProjectFactory">
    <owner class="org.jenkinsci.plugins.workflow.multibranch.WorkflowMultiBranchProject" reference="../.."/>
    <scriptPath>Jenkinsfile</scriptPath>
  </factory>
</org.jenkinsci.plugins.workflow.multibranch.WorkflowMultiBranchProject>
Don Subert
  • 2,636
  • 4
  • 27
  • 37