Skip to content

Commit

Permalink
JENKINS-15681: Support for Cloudbees Folders
Browse files Browse the repository at this point in the history
  • Loading branch information
tofuatgit committed Dec 8, 2012
1 parent 5f80b49 commit 85a3c94
Show file tree
Hide file tree
Showing 6 changed files with 197 additions and 54 deletions.
1 change: 1 addition & 0 deletions .gitignore
@@ -0,0 +1 @@
/target
20 changes: 19 additions & 1 deletion pom.xml
Expand Up @@ -86,12 +86,30 @@
<artifactId>mockito-core</artifactId>
<version>1.9.5</version>
<scope>test</scope>
<exclusions>
<exclusion>
<artifactId>hamcrest-core</artifactId>
<groupId>org.hamcrest</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<artifactId>junit-dep</artifactId>
<version>4.10</version>
<scope>test</scope>
<exclusions>
<exclusion>
<artifactId>hamcrest-core</artifactId>
<groupId>org.hamcrest</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-library</artifactId>
<version>1.3</version>
<scope>test</scope>
</dependency>
</dependencies>
<distributionManagement>
Expand Down
Expand Up @@ -16,6 +16,7 @@
*/
package org.jvnet.hudson.plugins.thinbackup.backup;

import groovy.swing.factory.HBoxFactory;
import hudson.PluginWrapper;
import hudson.model.Hudson;

Expand Down Expand Up @@ -46,6 +47,7 @@
import org.jvnet.hudson.plugins.thinbackup.utils.Utils;

public class HudsonBackup {

private static final Logger LOGGER = Logger.getLogger("hudson.plugins.thinbackup");

public static final String BUILDS_DIR_NAME = "builds";
Expand All @@ -55,6 +57,7 @@ public class HudsonBackup {
public static final String ARCHIVE_DIR_NAME = "archive";
public static final String USERSCONTENTS_DIR_NAME = "userContent";
public static final String NEXT_BUILD_NUMBER_FILE_NAME = "nextBuildNumber";
public static final String CONFIG_XML = "config.xml";
public static final String XML_FILE_EXTENSION = ".xml";
public static final String ZIP_FILE_EXTENSION = ".zip";
public static final String INSTALLED_PLUGINS_XML = "installedPlugins" + XML_FILE_EXTENSION;
Expand Down Expand Up @@ -163,39 +166,48 @@ private void backupJobs() throws IOException {
final File jobsDirectory = new File(hudsonHome.getAbsolutePath(), JOBS_DIR_NAME);
final File jobsBackupDirectory = new File(backupDirectory.getAbsolutePath(), JOBS_DIR_NAME);

Collection<String> jobNames;
final Hudson hudson = Hudson.getInstance();
if (hudson != null) {
jobNames = hudson.getJobNames();
} else {
jobNames = Arrays.asList(jobsDirectory.list());
}
backupJobsDirectory(jobsDirectory, jobsBackupDirectory);
LOGGER.fine("DONE backing up job specific configuration files.");
}

private void backupJobsDirectory(final File jobsDirectory, final File jobsBackupDirectory) throws IOException {
Collection<String> jobNames = Arrays.asList(jobsDirectory.list());
LOGGER.info(String.format("Found %d jobs to back up.", jobNames.size()));
LOGGER.fine(String.format("\t%s", jobNames));
LOGGER.fine(String.format("\t%s", jobNames));

for (final String jobName : jobNames) {
final File jobDirectory = new File(jobsDirectory, jobName);
if (jobDirectory.exists()) { // sub jobs e.g. maven modules need not be copied
if (jobDirectory.canRead()) {
final File jobBackupDirectory = new File(jobsBackupDirectory, jobName);
backupJobConfigFor(jobDirectory, jobBackupDirectory);
backupBuildsFor(jobDirectory, jobBackupDirectory);
if (isMatrixJob(jobDirectory)) {
List<File> configurations = findAllConfigurations(new File(jobDirectory, HudsonBackup.CONFIGURATIONS_DIR_NAME));
for (File configurationDirectory : configurations) {
File configurationBackupDirectory = createConfigurationBackupDirectory(jobBackupDirectory, jobDirectory, configurationDirectory);
backupJobConfigFor(configurationDirectory, configurationBackupDirectory);
backupBuildsFor(configurationDirectory, configurationBackupDirectory);
}
}

File childJobsFolder = new File(jobDirectory, HudsonBackup.JOBS_DIR_NAME);
if (childJobsFolder.exists()) { // found CloudBeesFolder
File folderBackupDirectory = new File(jobsBackupDirectory, jobName);
File folderJobsBackupDirectory = new File(folderBackupDirectory, JOBS_DIR_NAME);
folderJobsBackupDirectory.mkdirs();
FileUtils.copyFile(new File(jobDirectory, CONFIG_XML), new File(folderBackupDirectory, CONFIG_XML));
backupJobsDirectory(childJobsFolder, folderJobsBackupDirectory);
} else
backupJob(jobDirectory, jobsBackupDirectory, jobName);
} else {
final String msg = String.format("Read access denied on directory '%s', cannot back up the job '%s'.", jobDirectory.getAbsolutePath(), jobName);
LOGGER.severe(msg);
}
}
}
LOGGER.fine("DONE backing up job specific configuration files.");
}

private void backupJob(final File jobDirectory, final File jobsBackupDirectory, final String jobName) throws IOException {
final File jobBackupDirectory = new File(jobsBackupDirectory, jobName);
backupJobConfigFor(jobDirectory, jobBackupDirectory);
backupBuildsFor(jobDirectory, jobBackupDirectory);
if (isMatrixJob(jobDirectory)) {
List<File> configurations = findAllConfigurations(new File(jobDirectory, HudsonBackup.CONFIGURATIONS_DIR_NAME));
for (File configurationDirectory : configurations) {
File configurationBackupDirectory = createConfigurationBackupDirectory(jobBackupDirectory, jobDirectory, configurationDirectory);
backupJobConfigFor(configurationDirectory, configurationBackupDirectory);
backupBuildsFor(configurationDirectory, configurationBackupDirectory);
}
}
}

private File createConfigurationBackupDirectory(File jobBackupdirectory, File jobDirectory, File configurationDirectory) {
Expand All @@ -207,7 +219,7 @@ private File createConfigurationBackupDirectory(File jobBackupdirectory, File jo

private List<File> findAllConfigurations(File dir) {
@SuppressWarnings("unchecked")
Collection<File> listFiles = FileUtils.listFiles(dir, FileFilterUtils.nameFileFilter("config.xml"), TrueFileFilter.INSTANCE);
Collection<File> listFiles = FileUtils.listFiles(dir, FileFilterUtils.nameFileFilter(CONFIG_XML), TrueFileFilter.INSTANCE);

List<File> confs = new ArrayList<File>();
for (File file : listFiles) {
Expand Down
49 changes: 44 additions & 5 deletions src/test/java/org/jvnet/hudson/plugins/thinbackup/TestHelper.java
@@ -1,7 +1,11 @@
package org.jvnet.hudson.plugins.thinbackup;

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
Expand Down Expand Up @@ -40,15 +44,21 @@ public static File createBackupFolder(File base) {
return backupDir;
}

public static File createJob(File jenkinsHome, String jobName) throws IOException {
final File jobsDir = new File(jenkinsHome, HudsonBackup.JOBS_DIR_NAME);
final File testJob = new File(jobsDir , jobName);
testJob.mkdir();
final File config = new File(testJob, "config.xml");
public static File createCloudBeesFolder(File jenkinsHome, String folderName) throws FileNotFoundException, IOException {
final File folderDir = new File(new File(jenkinsHome, HudsonBackup.JOBS_DIR_NAME), folderName);
folderDir.mkdirs();

final File config = new File(folderDir, "config.xml");
config.createNewFile();
final BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(config));
out.write(new ByteArrayBuffer(CONFIG_XML_CONTENTS).array());
out.close();

return folderDir;
}

public static File createJob(File jenkinsHome, String jobName) throws IOException {
final File testJob = createJobsFolderWithConfiguration(jenkinsHome, jobName);
final File nextBuildNumberFile = new File(testJob, HudsonBackup.NEXT_BUILD_NUMBER_FILE_NAME);
nextBuildNumberFile.createNewFile();
addBuildNumber(nextBuildNumberFile);
Expand All @@ -58,6 +68,17 @@ public static File createJob(File jenkinsHome, String jobName) throws IOExceptio

return testJob;
}

private static File createJobsFolderWithConfiguration(File jenkinsHome, String jobName) throws IOException, FileNotFoundException {
final File testJob = new File(new File(jenkinsHome, HudsonBackup.JOBS_DIR_NAME), jobName);
testJob.mkdirs();
final File config = new File(testJob, "config.xml");
config.createNewFile();
final BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(config));
out.write(new ByteArrayBuffer(CONFIG_XML_CONTENTS).array());
out.close();
return testJob;
}

public static File addNewBuildToJob(File job) throws IOException {
final File builds = new File(job, HudsonBackup.BUILDS_DIR_NAME);
Expand Down Expand Up @@ -138,4 +159,22 @@ private static void addBuildNumber(final File nextBuildNumberFile) {
}
}
}

public static ThinBackupPluginImpl createMockPlugin(File jenkinsHome, File backupDir) {
final ThinBackupPluginImpl mockPlugin = mock(ThinBackupPluginImpl.class);

when(mockPlugin.getHudsonHome()).thenReturn(jenkinsHome);
when(mockPlugin.getFullBackupSchedule()).thenReturn("");
when(mockPlugin.getDiffBackupSchedule()).thenReturn("");
when(mockPlugin.getExpandedBackupPath()).thenReturn(backupDir.getAbsolutePath());
when(mockPlugin.getNrMaxStoredFull()).thenReturn(-1);
when(mockPlugin.isCleanupDiff()).thenReturn(false);
when(mockPlugin.isMoveOldBackupsToZipFile()).thenReturn(false);
when(mockPlugin.isBackupBuildResults()).thenReturn(true);
when(mockPlugin.isBackupBuildArchive()).thenReturn(false);
when(mockPlugin.isBackupNextBuildNumber()).thenReturn(false);
when(mockPlugin.getExcludedFilesRegex()).thenReturn("");

return mockPlugin;
}
}
@@ -0,0 +1,92 @@
package org.jvnet.hudson.plugins.thinbackup.backup;

import static org.junit.Assert.*;

import java.io.File;
import java.io.IOException;
import java.util.Calendar;
import java.util.Collection;

import org.apache.commons.io.FileUtils;
import org.hamcrest.Matchers;
import org.junit.Assert;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.jvnet.hudson.plugins.thinbackup.TestHelper;
import org.jvnet.hudson.plugins.thinbackup.ThinBackupPeriodicWork.BackupType;
import org.jvnet.hudson.plugins.thinbackup.utils.Utils;
import org.jvnet.hudson.plugins.thinbackup.ThinBackupPluginImpl;

public class TestBackupWithCloudBeesFolder {
private static final String TEST_FOLDER = "testFolder";
private File backupDir;
private File jenkinsHome;
private File cloudBeesFolder;

@Before
public void setup() throws IOException {
File base = new File(System.getProperty("java.io.tmpdir"));
backupDir = TestHelper.createBackupFolder(base);

jenkinsHome = TestHelper.createBasicFolderStructure(base);
cloudBeesFolder = TestHelper.createCloudBeesFolder(jenkinsHome, TEST_FOLDER);
File jobDir = TestHelper.createJob(cloudBeesFolder, TestHelper.TEST_JOB_NAME);
TestHelper.addNewBuildToJob(jobDir);

}

@After
public void tearDown() throws Exception {
FileUtils.deleteDirectory(jenkinsHome);
FileUtils.deleteDirectory(backupDir);
FileUtils.deleteDirectory(new File(Utils.THINBACKUP_TMP_DIR));
}

@Test
public void testCloudBeesFolderBackup() throws Exception {
final Calendar cal = Calendar.getInstance();
cal.set(Calendar.MINUTE, cal.get(Calendar.MINUTE - 10));

final ThinBackupPluginImpl mockPlugin = TestHelper.createMockPlugin(jenkinsHome, backupDir);
new HudsonBackup(mockPlugin, BackupType.FULL, cal.getTime()).backup();

final File backup = new File(backupDir, backupDir.list()[0]);
File rootJobsFolder = new File(backup, HudsonBackup.JOBS_DIR_NAME);
String[] list = rootJobsFolder.list();
Assert.assertThat(list, Matchers.arrayContainingInAnyOrder(TEST_FOLDER));

File cloudBeesFolder = new File(rootJobsFolder, list[0]);
list = cloudBeesFolder.list();
Assert.assertThat(list, Matchers.arrayContainingInAnyOrder(HudsonBackup.JOBS_DIR_NAME, HudsonBackup.CONFIG_XML));

File childJobsFolder = new File(cloudBeesFolder, HudsonBackup.JOBS_DIR_NAME);
list = childJobsFolder.list();
Assert.assertThat(list, Matchers.arrayContainingInAnyOrder(TestHelper.TEST_JOB_NAME));

File jobFolder = new File(childJobsFolder, TestHelper.TEST_JOB_NAME);
list = jobFolder.list();
Assert.assertThat(list, Matchers.arrayContainingInAnyOrder(HudsonBackup.BUILDS_DIR_NAME, HudsonBackup.CONFIG_XML));
}

@Test
public void testRecursiveFolderBackup() throws Exception {
File subFolderDirectory = TestHelper.createCloudBeesFolder(cloudBeesFolder, "subFolder");
TestHelper.createJob(subFolderDirectory, "folderJob");

final Calendar cal = Calendar.getInstance();
cal.set(Calendar.MINUTE, cal.get(Calendar.MINUTE - 10));

final ThinBackupPluginImpl mockPlugin = TestHelper.createMockPlugin(jenkinsHome, backupDir);
new HudsonBackup(mockPlugin, BackupType.FULL, cal.getTime()).backup();

File subFolderJobsBackupDirectory = new File(backupDir, backupDir.list()[0]+"/jobs/"+TEST_FOLDER+"/jobs/subFolder/jobs");
String[] list = subFolderJobsBackupDirectory.list();
Assert.assertThat(list , Matchers.arrayContainingInAnyOrder("folderJob"));

File jobFolder = new File(subFolderJobsBackupDirectory, "folderJob");
list = jobFolder.list();
Assert.assertThat(list, Matchers.arrayContainingInAnyOrder(HudsonBackup.CONFIG_XML));
}

}

1 comment on commit 85a3c94

@jglick
Copy link
Member

@jglick jglick commented on 85a3c94 Jan 3, 2013

Choose a reason for hiding this comment

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

BTW probably irrelevant for these tests (since you seem to be working at the File level), but MockFolder in newer cores can be used to test behavior against folder-like Items.

Please sign in to comment.