Skip to content

Commit

Permalink
MID-8842 ninja - upgrade installation now preserve file permissions f…
Browse files Browse the repository at this point in the history
…or existing files being replaced. Also better validation of midpoint installation directory
  • Loading branch information
1azyman committed Jul 6, 2023
1 parent 2607e3d commit 0660617
Show file tree
Hide file tree
Showing 5 changed files with 116 additions and 63 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

public class UpgradeObjectsHandler {

private static final List<UpgradeObjectProcessor<?>> PROCESSORS;
public static final List<UpgradeObjectProcessor<?>> PROCESSORS;

static {
PROCESSORS = initProcessors();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
package com.evolveum.midpoint.schema.validator.processor;

import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;

import org.assertj.core.api.Assertions;
Expand All @@ -19,6 +21,7 @@
import com.evolveum.midpoint.prism.util.PrismTestUtil;
import com.evolveum.midpoint.schema.AbstractSchemaTest;
import com.evolveum.midpoint.schema.validator.ObjectUpgradeValidator;
import com.evolveum.midpoint.schema.validator.UpgradeObjectsHandler;
import com.evolveum.midpoint.schema.validator.UpgradeValidationItem;
import com.evolveum.midpoint.schema.validator.UpgradeValidationResult;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType;
Expand Down Expand Up @@ -52,6 +55,21 @@ private <O extends ObjectType> void testUpgradeValidator(String fileName, Consum
resultConsumer.accept(result);
}

@Test
public void test00CheckIdentifierUniqueness() {
Map<String, Class<?>> identifiers = new HashMap<>();
UpgradeObjectsHandler.PROCESSORS.forEach(p -> {
String identifier = p.getIdentifier();
Class<?> existing = identifiers.get(identifier);
if (existing != null) {
Assertions.fail("Processor (" + p.getClass().getName() + ") identifier (" + identifier
+ ") is not unique, collides with class " + existing.getName());
} else {
identifiers.put(identifier, p.getClass());
}
});
}

@Test
public void test10TestResource() throws Exception {
testUpgradeValidator("resource.xml", result -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ public R execute() throws Exception {

List<SearchProducerWorker> producers = createProducers(queue, operation);

log.info("Starting " + getOperationName());
operation.start();

// execute as many producers as there are threads for them
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,21 @@

import java.io.File;
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.PosixFilePermission;
import java.util.Set;

import org.apache.commons.io.FileUtils;

import com.evolveum.midpoint.ninja.action.Action;
import com.evolveum.midpoint.ninja.impl.NinjaException;
import com.evolveum.midpoint.ninja.util.NinjaUtils;

public class UpgradeInstallationAction extends Action<UpgradeInstallationOptions, Void> {

private static final String VAR_DIRECTORY = "var";
private static final boolean IS_POSIX = FileSystems.getDefault().supportedFileAttributeViews().contains("posix");

@Override
public String getOperationName() {
Expand All @@ -24,6 +30,9 @@ public Void execute() throws Exception {
final boolean backupFiles = options.isBackup();

File midpointInstallation = NinjaUtils.computeInstallationDirectory(options.getInstallationDirectory(), context);
if (midpointInstallation == null) {
throw new NinjaException("Undefined midpoint installation directory");
}

File backupDirectory = null;
if (backupFiles) {
Expand All @@ -34,74 +43,61 @@ public Void execute() throws Exception {
}

for (File file : emptyIfNull(distributionDirectory.listFiles())) {
String fileName = file.getName();

if (backupFiles) {
File newFile = new File(midpointInstallation, fileName);

if (!VAR_DIRECTORY.equals(fileName)) {
if (newFile.exists()) {
FileUtils.moveToDirectory(newFile, backupDirectory, false);
}
} else {
// don't back up var directory, upgrade shouldn't touch it, back up only content if needed
FileUtils.forceMkdir(new File(backupDirectory, fileName));
backupAndCopyFiles(file, new File(midpointInstallation, file.getName()), backupFiles, backupDirectory);
}

return null;
}

private void backupAndCopyFiles(File from, File to, boolean doBackup, File backupDirectory) throws IOException {
if (from.isFile()) {
Set<PosixFilePermission> permissions = null;
if (to.exists()) {
permissions = IS_POSIX ? Files.getPosixFilePermissions(to.toPath()) : null;

if (doBackup) {
FileUtils.copyFile(to, new File(backupDirectory, to.getName()), StandardCopyOption.COPY_ATTRIBUTES, StandardCopyOption.REPLACE_EXISTING);
}
}

if (VAR_DIRECTORY.equals(fileName)) {
copyFiles(file, new File(midpointInstallation, fileName), new File(backupDirectory, fileName), backupFiles);
} else {
File targetFile = new File(midpointInstallation, fileName);
deleteExisting(targetFile);

FileUtils.moveToDirectory(file, midpointInstallation, false);
FileUtils.copyFile(from, to, StandardCopyOption.COPY_ATTRIBUTES, StandardCopyOption.REPLACE_EXISTING);
if (permissions != null) {
Files.setPosixFilePermissions(to.toPath(), permissions);
}

return;
}

log.info("");
// handling directory
Set<PosixFilePermission> permissions = null;
if (to.exists()) {
permissions = IS_POSIX ? Files.getPosixFilePermissions(to.toPath()) : null;

return null;
}
if (doBackup) {
File backedUp = new File(backupDirectory, to.getName());
backedUp.mkdir();

private File[] emptyIfNull(File[] files) {
if (files == null) {
return new File[0];
if (permissions != null) {
Files.setPosixFilePermissions(backedUp.toPath(), permissions);
}
}
}

return files;
}

private void deleteExisting(File targetFile) throws IOException {
if (!targetFile.exists()) {
return;
to.mkdir();
if (permissions != null) {
Files.setPosixFilePermissions(to.toPath(), permissions);
}

if (targetFile.isDirectory()) {
FileUtils.deleteDirectory(targetFile);
} else {
targetFile.delete();
for (File file : emptyIfNull(from.listFiles())) {
backupAndCopyFiles(file, new File(to, file.getName()), doBackup, new File(backupDirectory, from.getName()));
}
}

private void copyFiles(File srcDir, File dstDir, File backupDir, boolean backup) throws IOException {
File[] files = srcDir.listFiles();
private File[] emptyIfNull(File[] files) {
if (files == null) {
return;
return new File[0];
}

for (File file : files) {
String fileName = file.getName();

if (backup) {
File newFile = new File(dstDir, fileName);
if (newFile.exists()) {
FileUtils.moveToDirectory(newFile, backupDir, false);
}
}

deleteExisting(new File(dstDir, fileName));
FileUtils.moveToDirectory(file, dstDir, false);
}
return files;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,7 @@
import java.lang.reflect.Modifier;
import java.nio.charset.Charset;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.*;
import java.util.function.Function;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
Expand Down Expand Up @@ -218,19 +215,62 @@ public static List<ObjectTypes> getTypes(Set<ObjectTypes> selected) {
return types;
}

public static File computeInstallationDirectory(File installationDirectory, NinjaContext context) {
public static File computeInstallationDirectory(File installationDirectory, NinjaContext context) throws NinjaException {
final ConnectionOptions connectionOptions = context.getOptions(ConnectionOptions.class);
File midpointHomeDirectory = new File(connectionOptions.getMidpointHome());
String mpHome = connectionOptions.getMidpointHome();
File midpointHomeDirectory = mpHome != null ? new File(connectionOptions.getMidpointHome()) : null;

return computeInstallationDirectory(installationDirectory, midpointHomeDirectory);
}

public static File computeInstallationDirectory(File installationDirectory, File midpointHomeDirectory) {
public static File computeInstallationDirectory(File installationDirectory, File midpointHomeDirectory) throws NinjaException {
File installation;
if (installationDirectory != null) {
return installationDirectory;
installation = installationDirectory;
} else {
if (midpointHomeDirectory != null) {
installation = midpointHomeDirectory.getParentFile();
} else {
throw new NinjaException("Neither installation directory nor midpoint.home is specified");
}
}

File bin = new File(installation, "bin");
if (!validateDirectory(bin, "midpoint\\.(sh|bat)", "start\\.(sh|bat)", "stop\\.(sh|bat)")) {
throw new NinjaException("Installation directory " + installation.getPath() + " doesn't contain bin/ with midpoint, "
+ "start, and stop scripts. Probably wrong installation path, or customized installation.");
}

File lib = new File(installation, "lib");
if (!validateDirectory(lib, "midpoint\\.(war|jar)")) {
throw new NinjaException("Installation directory " + installation.getPath() + " doesn't contain lib/ with midpoint "
+ "(jar/war). Probably wrong installation path, or customized installation.");
}

return installation;
}

private static boolean validateDirectory(File dir, String... expectedFileNames) {
if (!dir.exists() || !dir.isDirectory()) {
return false;
}

String[] fileNames = dir.list();
for (String fileName : expectedFileNames) {
if (!containsFileNames(fileNames, fileName)) {
return false;
}
}

return true;
}

private static boolean containsFileNames(String[] names, String filenameRegex) {
if (names == null) {
return false;
}

return midpointHomeDirectory.getParentFile();
return Arrays.stream(names).anyMatch(s -> s.matches(filenameRegex));
}

public static void readInput(Function<String, Boolean> responseHandler) throws IOException {
Expand Down

0 comments on commit 0660617

Please sign in to comment.