Skip to content

Commit

Permalink
Fix: Don't destroy credentials when re-creating organization folders
Browse files Browse the repository at this point in the history
Similar to 8d8ea63, we should be able
to support organization folders not losing their credentials.

This requires we bump our dependency of `credentials` to pick up the
`branch-api` dependency.

We need to handle the various bits of metadata available in the
`OrganizationFolder`s, so our tests are slightly more complex than we
usually have.

Co-authored-by: Jean-François Roche <jfroche@affinitic.be>

Closes JENKINS-44681.
  • Loading branch information
jamietanna committed Jul 1, 2022
1 parent 9cf8a38 commit 0390db7
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 6 deletions.
3 changes: 2 additions & 1 deletion job-dsl-plugin/build.gradle
Expand Up @@ -109,6 +109,7 @@ dependencies {
compile(project(':job-dsl-core')) {
exclude group: 'org.jvnet.hudson', module:'xstream'
}
implementation 'org.jenkins-ci.plugins:branch-api:2.4.0'
implementation 'org.jenkins-ci.plugins:cloudbees-folder:5.14'
implementation 'org.jenkins-ci.plugins:structs:1.19'
implementation 'org.jenkins-ci.plugins:script-security:1.54'
Expand All @@ -123,5 +124,5 @@ dependencies {
testImplementation 'io.jenkins:configuration-as-code:1.15:tests'
testImplementation 'org.jenkins-ci.plugins:matrix-auth:1.3'
testImplementation 'org.jenkins-ci.plugins:nested-view:1.14'
testImplementation 'org.jenkins-ci.plugins:credentials:2.1.10'
testImplementation 'org.jenkins-ci.plugins:credentials:2.1.11'
}
Expand Up @@ -39,6 +39,7 @@
import javaposse.jobdsl.dsl.NameNotProvidedException;
import javaposse.jobdsl.dsl.UserContent;
import javaposse.jobdsl.plugin.ExtensionPointHelper.DslExtension;
import jenkins.branch.OrganizationFolder;
import jenkins.model.DirectlyModifiableTopLevelItemGroup;
import jenkins.model.Jenkins;
import jenkins.model.ModifiableTopLevelItemGroup;
Expand Down Expand Up @@ -587,17 +588,25 @@ private void renameJob(Job from, String to) throws IOException {
}

private void mergeCredentials(AbstractItem item, javaposse.jobdsl.dsl.Item dslItem) {
Optional<AbstractFolderProperty<?>> maybeProperty = Optional.empty();
if (item instanceof Folder) {
Folder folder = (Folder) item;
Optional<AbstractFolderProperty<?>> maybeProperty =
maybeProperty =
folder.getProperties().stream()
.filter(p -> p instanceof FolderCredentialsProperty)
.findFirst();

if (maybeProperty.isPresent()) {
LOGGER.log(Level.FINE, format("Merging credentials for %s", item.getName()));
DslItemConfigurer.mergeCredentials(maybeProperty.get(), dslItem);
}
}
if (item instanceof OrganizationFolder) {
OrganizationFolder folder = (OrganizationFolder) item;
maybeProperty =
folder.getProperties().stream()
.filter(p -> p instanceof FolderCredentialsProperty)
.findFirst();
}
if (maybeProperty.isPresent()) {
LOGGER.log(Level.FINE, format("Merging credentials for %s", item.getName()));
DslItemConfigurer.mergeCredentials(maybeProperty.get(), dslItem);
}
}

Expand Down
@@ -1,5 +1,6 @@
package javaposse.jobdsl.plugin

import jenkins.branch.OrganizationFolder
import com.cloudbees.hudson.plugins.folder.AbstractFolder
import com.cloudbees.hudson.plugins.folder.AbstractFolderProperty
import com.cloudbees.hudson.plugins.folder.AbstractFolderPropertyDescriptor
Expand Down Expand Up @@ -667,6 +668,43 @@ class JenkinsJobManagementSpec extends Specification {
actual.properties.size() == 0
}
def 'createOrUpdateConfig should preserve credentials if they exist on an OrganizationFolder'() {
setup:
OrganizationFolder folder = jenkinsRule.createProject(OrganizationFolder, 'org')
// `OrganizationFolder`s include a lot of existing metadata that is appended, regardless of how few we already
// set, so we should calculate expected as the default computed properties
int defaultProperties = folder.properties.size()
def property = createCredentialProperty()
folder.addProperty(property)
when:
jobManagement.createOrUpdateConfig(createItem('org', '/organizationfolder.xml'), false)
then:
def actualItem = jenkinsRule.jenkins.getItem('org')
def actual = (AbstractFolder<?>) actualItem
actual.properties.size() == defaultProperties + 1
}
def 'createOrUpdateConfig should ignore other properties on the OrganizationFolder'() {
setup:
OrganizationFolder folder = jenkinsRule.createProject(OrganizationFolder, 'org')
// `OrganizationFolder`s include a lot of existing metadata that is appended, regardless of how few we already
// set, so we should calculate expected as the default computed properties
int defaultProperties = folder.properties.size()
folder.addProperty(new FakeProperty())
when:
jobManagement.createOrUpdateConfig(createItem('org', '/organizationfolder.xml'), false)
folder.writeConfigDotXml(System.out)
then:
def actual = jenkinsRule.jenkins.getItem('org')
actual.properties.size() == defaultProperties
}
def 'createOrUpdateView should work if view type changes'() {
setup:
jenkinsRule.jenkins.addView(new AllView('foo'))
Expand Down
9 changes: 9 additions & 0 deletions job-dsl-plugin/src/test/resources/organizationfolder.xml
@@ -0,0 +1,9 @@
<?xml version='1.1' encoding='UTF-8'?>
<jenkins.branch.OrganizationFolder>
<properties>
</properties>
<disabled>false</disabled>
<navigators/>
<projectFactories/>
<buildStrategies/>
</jenkins.branch.OrganizationFolder>

0 comments on commit 0390db7

Please sign in to comment.