Skip to content

Commit

Permalink
Merge pull request #1251 from jenkinsci/defect/org-folder-secrets
Browse files Browse the repository at this point in the history
Fix: Don't destroy credentials when re-creating organization folders
  • Loading branch information
jamietanna authored Jul 1, 2022
2 parents 4639256 + 4b940e8 commit 610fc71
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 8 deletions.
2 changes: 2 additions & 0 deletions docs/Home.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ scripts, including [[tests for DSL scripts|Testing DSL Scripts]] and [[IDE Suppo
Browse the Jenkins issue tracker to see any [open issues](https://issues.jenkins-ci.org/issues/?filter=15140).

## Release Notes
* 1.80.0 (July 1 2022)
* Don't destroy credentials when re-creating organization folders ([GH-1251](https://github.com/jenkinsci/job-dsl-plugin/pull/1251) [JENKINS-44681](https://issues.jenkins.io/browse/JENKINS-44681))
* 1.79.0 (April 14 2022)
* Allow using classes not supported by `structs` for `DescribableContext` ([GH-1202](https://github.com/jenkinsci/job-dsl-plugin/pull/1202) [JENKINS-57435](https://issues.jenkins-ci.org/browse/JENKINS-57435))
** Note that this has the potential to be unsafe and can lead to source-controlled secrets. Please be **very cautious** when embedding secrets into source control!
Expand Down
3 changes: 2 additions & 1 deletion job-dsl-plugin/build.gradle
Original file line number Diff line number Diff line change
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'
}
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
@@ -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 @@ -641,7 +642,7 @@ class JenkinsJobManagementSpec extends Specification {
e.message == 'Type of item "my-job" does not match existing type, item type can not be changed'
}
def 'createOrUpdateConfig should preserve credentials if they exist on a folder'() {
def 'createOrUpdateConfig should preserve credentials if they exist on a Folder'() {
setup:
Folder folder = jenkinsRule.createProject(Folder, 'folder')
folder.addProperty(createCredentialProperty())
Expand All @@ -654,7 +655,7 @@ class JenkinsJobManagementSpec extends Specification {
actual.properties.size() == 1
}
def 'createOrUpdateConfig should ignore other properties on the folder'() {
def 'createOrUpdateConfig should ignore other properties on the Folder'() {
setup:
Folder folder = jenkinsRule.createProject(Folder, 'folder')
folder.addProperty(new FakeProperty())
Expand All @@ -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
Original file line number Diff line number Diff line change
@@ -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 610fc71

Please sign in to comment.