Skip to content

Commit

Permalink
MID-8842 ninja, upgrade objects action impl started, work in progress
Browse files Browse the repository at this point in the history
  • Loading branch information
1azyman committed Jun 22, 2023
1 parent 96413e2 commit 79d8845
Show file tree
Hide file tree
Showing 9 changed files with 197 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType;

public interface UpgradeObjectProcessor<T extends ObjectType> {
public interface UpgradeObjectHandler<T extends ObjectType> {

String getIdentifier();

Expand Down
Original file line number Diff line number Diff line change
@@ -1,46 +1,103 @@
package com.evolveum.midpoint.ninja.action.upgrade;

import java.lang.reflect.Modifier;
import java.util.Set;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.BlockingQueue;
import java.util.stream.Collectors;

import com.evolveum.midpoint.ninja.Main;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;
import org.apache.commons.lang3.StringUtils;

import com.evolveum.midpoint.ninja.action.AbstractRepositorySearchAction;
import com.evolveum.midpoint.ninja.action.verify.VerificationReporter;
import com.evolveum.midpoint.ninja.util.OperationStatus;
import com.evolveum.midpoint.util.ClassPathUtil;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType;

public abstract class UpgradeObjectsAction extends AbstractRepositorySearchAction<UpgradeObjectsOptions> {
public class UpgradeObjectsAction extends AbstractRepositorySearchAction<UpgradeObjectsOptions> {

private Set<UUID> skipUpgradeForUUIDs;

@Override
public Void execute() throws Exception {
// final VerifyResult verifyResult = context.getResult(VerifyResult.class);
//
// final File output = verifyResult.getOutput();
skipUpgradeForUUIDs = loadVerificationFile();

// todo load CSV, only OIDs + state (whether to update)
// go through all oids that need to be updated
// if csv not available go through all
log.info("Upgrade will skip {} objects", skipUpgradeForUUIDs.size());

Set<Class<?>> classes = ClassPathUtil.listClasses(Main.class.getPackageName());
Set<Class<?>> processors = classes.stream()
.filter(UpgradeObjectProcessor.class::isAssignableFrom)
.filter(c -> !Modifier.isAbstract(c.getModifiers()))
.collect(Collectors.toUnmodifiableSet());

context.out.println("Found " + processors.size() + " upgrade rules");

return null;
return super.execute();
//
//
//// final VerifyResult verifyResult = context.getResult(VerifyResult.class);
////
//// final File output = verifyResult.getOutput();
//
// // todo load CSV, only OIDs + state (whether to update)
// // go through all oids that need to be updated
// // if csv not available go through all
//
// Set<Class<?>> classes = ClassPathUtil.listClasses(Main.class.getPackageName());
// Set<Class<?>> processors = classes.stream()
// .filter(UpgradeObjectProcessor.class::isAssignableFrom)
// .filter(c -> !Modifier.isAbstract(c.getModifiers()))
// .collect(Collectors.toUnmodifiableSet());
//
// context.out.println("Found " + processors.size() + " upgrade rules");
//
// return null;
}

@Override
protected String getOperationShortName() {
return "upgrade";
}

private Set<UUID> loadVerificationFile() throws IOException {
File verification = options.getVerification();
if (verification == null || !verification.exists() || !verification.isFile()) {
return Collections.emptySet();
}

log.info("Loading verification file");

Set<UUID> set = new HashSet<>();

CSVFormat format = VerificationReporter.CSV_FORMAT;
try (CSVParser parser = format.parse(new FileReader(verification, context.getCharset()))) {
Iterator<CSVRecord> iterator = parser.iterator();
while (iterator.hasNext()) {
CSVRecord record = iterator.next();
if (record.getRecordNumber() == 1 || isRecordEmpty(record)) {
// csv header or empty record
continue;
}

if (VerificationReporter.skipUpgradeForRecord(record)) {
UUID uuid = VerificationReporter.getUuidFromRecord(record);
if (uuid != null) {
set.add(uuid);
}
}
}
}

return Collections.unmodifiableSet(set);
}

private boolean isRecordEmpty(CSVRecord record) {
for (int i = 0; i < record.size(); i++) {
String value = record.get(i);
if (StringUtils.isNotBlank(value)) {
return false;
}
}

return true;
}

@Override
protected Runnable createConsumer(BlockingQueue<ObjectType> queue, OperationStatus operation) {
return new UpgradeObjectsConsumerWorker(context, options, queue, operation);
return new UpgradeObjectsConsumerWorker(skipUpgradeForUUIDs, context, options, queue, operation);
}
}
Original file line number Diff line number Diff line change
@@ -1,23 +1,88 @@
package com.evolveum.midpoint.ninja.action.upgrade;

import java.util.Set;
import java.util.UUID;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;

import com.evolveum.midpoint.ninja.action.worker.BaseWorker;
import com.evolveum.midpoint.ninja.impl.Log;
import com.evolveum.midpoint.ninja.impl.NinjaContext;
import com.evolveum.midpoint.ninja.util.OperationStatus;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.prism.delta.ObjectDelta;
import com.evolveum.midpoint.repo.api.RepoModifyOptions;
import com.evolveum.midpoint.repo.api.RepositoryService;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.util.exception.ObjectAlreadyExistsException;
import com.evolveum.midpoint.util.exception.ObjectNotFoundException;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType;

public class UpgradeObjectsConsumerWorker extends BaseWorker<UpgradeObjectsOptions, ObjectType> {
public class UpgradeObjectsConsumerWorker<T extends ObjectType> extends BaseWorker<UpgradeObjectsOptions, T> {

private final Set<UUID> skipUpgradeForUUIDs;

private final Log log;

public UpgradeObjectsConsumerWorker(
NinjaContext context, UpgradeObjectsOptions options,
BlockingQueue<ObjectType> queue, OperationStatus operation) {
Set<UUID> skipUpgradeForUUIDs, NinjaContext context, UpgradeObjectsOptions options,
BlockingQueue<T> queue, OperationStatus operation) {

super(context, options, queue, operation);

this.skipUpgradeForUUIDs = skipUpgradeForUUIDs;
this.log = context.getLog();
}

@Override
public void run() {
RepositoryService repository = context.getRepository();
// todo implement

try {
while (!shouldConsumerStop()) {
T object = null;
try {
object = queue.poll(CONSUMER_POLL_TIMEOUT, TimeUnit.SECONDS);
if (object == null) {
continue;
}

processObject(repository, object);

operation.incrementTotal();
} catch (Exception ex) {
log.error("Couldn't store object {}, reason: {}", ex, object, ex.getMessage());
operation.incrementError();
}
}
} catch (Exception ex) {
log.error(ex.getMessage(), ex);
} finally {
markDone();

if (isWorkersDone()) {
operation.finish();
}
}
}

private void processObject(RepositoryService repository, T object)
throws SchemaException, ObjectNotFoundException, ObjectAlreadyExistsException {

PrismObject<? extends ObjectType> prismObject = object.asPrismObject();

if (skipUpgradeForUUIDs.contains(object.getOid())) {
log.info("Skipping object {} with oid {}", prismObject.getBusinessDisplayName(), object.getOid());
return;
}

ObjectDelta<T> delta = new UpgradeObjectsHelper().upgradeObject(prismObject);

if (delta != null && !delta.isEmpty()) {
OperationResult result = new OperationResult("aaaa"); // todo fix operation result name and handling!
repository.modifyObject(object.getClass(), object.getOid(), delta.getModifications(), result);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.evolveum.midpoint.ninja.action.upgrade;

import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.prism.delta.ObjectDelta;

public class UpgradeObjectsHelper {

public ObjectDelta upgradeObject(PrismObject<?> object) {
return null;
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
package com.evolveum.midpoint.ninja.action.upgrade.handler;

import com.evolveum.midpoint.ninja.action.upgrade.UpgradeObjectProcessor;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType;

public abstract class RemovedElementProcessor<T extends ObjectType> {//implements UpgradeObjectProcessor<T> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import java.util.List;

import com.evolveum.midpoint.ninja.action.upgrade.UpgradeObjectProcessor;
import com.evolveum.midpoint.ninja.action.upgrade.UpgradeObjectHandler;
import com.evolveum.midpoint.ninja.action.upgrade.UpgradePhase;
import com.evolveum.midpoint.ninja.action.upgrade.UpgradePriority;
import com.evolveum.midpoint.ninja.action.upgrade.UpgradeType;
Expand All @@ -11,7 +11,7 @@
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.xml.ns._public.common.common_3.*;

public class UserDashboardHandler implements UpgradeObjectProcessor<ObjectType> {
public class UserDashboardHandler implements UpgradeObjectHandler<ObjectType> {

@Override
public String getIdentifier() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,19 @@
import java.io.StringWriter;
import java.io.Writer;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.*;
import java.util.stream.Collectors;

import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVPrinter;
import org.apache.commons.csv.CSVRecord;
import org.apache.commons.csv.QuoteMode;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;

import com.evolveum.midpoint.ninja.Main;
import com.evolveum.midpoint.ninja.action.VerifyOptions;
import com.evolveum.midpoint.ninja.action.upgrade.UpgradeObjectProcessor;
import com.evolveum.midpoint.ninja.action.upgrade.UpgradeObjectHandler;
import com.evolveum.midpoint.ninja.action.upgrade.UpgradePhase;
import com.evolveum.midpoint.ninja.action.upgrade.UpgradePriority;
import com.evolveum.midpoint.ninja.action.upgrade.UpgradeType;
Expand All @@ -31,7 +30,7 @@

public class VerificationReporter {

private static final List<String> REPORT_HEADER = List.of(
public static final List<String> REPORT_HEADER = List.of(
"Oid",
"Type",
"Name",
Expand All @@ -42,7 +41,7 @@ public class VerificationReporter {
"Phase",
"Priority",
"Type",
"Perform upgrade [yes/no]"
"Skip upgrade [yes/no]"
);

private final VerifyOptions options;
Expand All @@ -51,7 +50,7 @@ public class VerificationReporter {

private ObjectValidator validator;

private static final CSVFormat CSV_FORMAT;
public static final CSVFormat CSV_FORMAT;

static {
CSV_FORMAT = createCsvFormat();
Expand Down Expand Up @@ -137,17 +136,39 @@ public void verify(Writer writer, PrismObject<?> object) throws IOException {
}
}

public static UUID getUuidFromRecord(CSVRecord record) {
if (record == null || record.size() != REPORT_HEADER.size()) {
return null;
}

String uuid = record.get(0);
return StringUtils.isNotEmpty(uuid) ? UUID.fromString(uuid) : null;
}

public static boolean skipUpgradeForRecord(CSVRecord record) {
if (record == null || record.size() != REPORT_HEADER.size()) {
return true;
}

String value = record.get(REPORT_HEADER.size() - 1);

return value.equalsIgnoreCase("true")
|| value.equalsIgnoreCase("yes")
|| value.equalsIgnoreCase("t")
|| value.equalsIgnoreCase("y");
}

private void enhanceValidationResult(PrismObject<?> object, ValidationResult result) {
Set<Class<?>> processors = ClassPathUtil.listClasses(Main.class.getPackageName())
.stream()
.filter(UpgradeObjectProcessor.class::isAssignableFrom)
.filter(UpgradeObjectHandler.class::isAssignableFrom)
.filter(c -> !Modifier.isAbstract(c.getModifiers()))
.collect(Collectors.toUnmodifiableSet());

Set<UpgradeObjectProcessor<?>> instances = processors.stream()
Set<UpgradeObjectHandler<?>> instances = processors.stream()
.map(c -> {
try {
return (UpgradeObjectProcessor<?>) c.getConstructor().newInstance();
return (UpgradeObjectHandler<?>) c.getConstructor().newInstance();
} catch (Exception ex) {
// todo
ex.printStackTrace();
Expand All @@ -159,7 +180,7 @@ private void enhanceValidationResult(PrismObject<?> object, ValidationResult res
.collect(Collectors.toUnmodifiableSet());

for (ValidationItem validationItem : result.getItems()) {
for (UpgradeObjectProcessor<?> processor : instances) {
for (UpgradeObjectHandler<?> processor : instances) {
if (processor.isApplicable(object, validationItem.getItemPath())) {
// todo finish
}
Expand Down Expand Up @@ -200,7 +221,7 @@ private List<String> createReportRecord(ValidationItem item, PrismObject<?> obje
phase != null ? phase.name() : null,
priority != null ? priority.name() : null,
type != null ? type.name() : null,
null
null // todo last column should have YES (skip upgrade for all non-auto changes by default)
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ public enum Command {

UPGRADE_OBJECTS("upgrade-objects", UpgradeObjectsOptions.class, UpgradeObjectsAction.class),

// todo merge with verify, if there's -f option, then don't start whole context and search repository, just go to file system. same for upgrade-files
VERIFY_FILES("verify-files", VerifyFilesOptions.class, VerifyFilesAction.class);

private final String commandName;
Expand Down
1 change: 1 addition & 0 deletions tools/ninja/src/main/resources/messages.properties
Original file line number Diff line number Diff line change
Expand Up @@ -121,3 +121,4 @@ upgradeObjects=Upgrade objects
upgradeObjects.verification=Verification results file
output.output=Output file path. If file is not defined data will be printed out to SYSOUT.
output.overwrite=Overwrite output file if it exists.
upgradeFiles=Upgrade files

0 comments on commit 79d8845

Please sign in to comment.