Skip to content

Commit

Permalink
MID-8842 ninja - upgrade command, code cleanup, wip
Browse files Browse the repository at this point in the history
(cherry picked from commit 08af9da)
  • Loading branch information
1azyman committed Sep 4, 2023
1 parent 59c81bf commit 5eb6fba
Show file tree
Hide file tree
Showing 10 changed files with 175 additions and 76 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,13 @@ public abstract class AbstractRepositorySearchAction<O extends ExportOptions, R>
private static final int QUEUE_CAPACITY_PER_THREAD = 100;
private static final long CONSUMERS_WAIT_FOR_START = 2000L;

public AbstractRepositorySearchAction() {
}

public AbstractRepositorySearchAction(boolean partial) {
super(partial);
}

protected abstract Callable<R> createConsumer(BlockingQueue<ObjectType> queue, OperationStatus operation);

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@

import org.jetbrains.annotations.NotNull;

import com.evolveum.midpoint.ninja.impl.Log;
import com.evolveum.midpoint.ninja.impl.LogTarget;
import com.evolveum.midpoint.ninja.impl.NinjaApplicationContextLevel;
import com.evolveum.midpoint.ninja.impl.NinjaContext;
import com.evolveum.midpoint.ninja.impl.Log;
import com.evolveum.midpoint.ninja.util.NinjaUtils;
import com.evolveum.midpoint.ninja.util.OperationStatus;
import com.evolveum.midpoint.schema.result.OperationResult;
Expand All @@ -25,12 +25,26 @@
*/
public abstract class Action<O, R> {

/**
* Flag, whether action is part of more complex action.
* This is most often used to determine whether and how to print information to user (or skip some, e.g. next steps messages).
*/
protected final boolean partial;

protected Log log;

protected NinjaContext context;

protected O options;

public Action() {
this(false);
}

public Action(boolean partial) {
this.partial = partial;
}

public void init(NinjaContext context, O options) {
this.context = context;
this.options = options;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,10 @@
*/
public abstract class RepositoryAction<O, R> extends Action<O, R> {

public RepositoryAction() {
}

public RepositoryAction(boolean partial) {
super(partial);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@
*/
public class VerifyAction extends AbstractRepositorySearchAction<VerifyOptions, VerifyResult> {

public VerifyAction() {
}

public VerifyAction(boolean partial) {
super(partial);
}

@Override
public String getOperationName() {
return "verify";
Expand Down Expand Up @@ -92,7 +99,7 @@ public VerifyResult execute() throws Exception {
// todo this should not show when action is a part of complex action and next step is prepared automatically
// FIXME: ADD links (do not display in batch mode)
// FIXME: Could We could try to infer script name?
if (context.isUserMode()) {
if (context.isUserMode() && !partial) {
log.info("Please see documentation for use of verification report in upgrade process and modify it accordingly.");
log.info("After you reviewed verification report and marked changes to skip you can continue upgrade process "
+ "with running 'ninja.sh upgrade-objects --verification-file \"{}\"'", options.getOutput().getPath());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package com.evolveum.midpoint.ninja.action;

import java.io.File;
import java.util.HashMap;
import java.util.Map;

import com.evolveum.midpoint.schema.validator.UpgradePriority;

public class VerifyResult {

private File verificationFile;

private Map<UpgradePriority, Long> priorities = new HashMap<>();

private Long unknown = 0L;
Expand Down Expand Up @@ -69,4 +72,12 @@ public long getOptionalCount() {
public long getUnknownCount() {
return unknown;
}

public File getVerificationFile() {
return verificationFile;
}

public void setVerificationFile(File verificationFile) {
this.verificationFile = verificationFile;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,13 @@

public class PreUpgradeCheckAction extends Action<PreUpgradeCheckOptions, ActionResult<Boolean>> {

public PreUpgradeCheckAction() {
}

public PreUpgradeCheckAction(boolean partial) {
super(partial);
}

@Override
public String getOperationName() {
return "pre-upgrade checks";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import org.apache.commons.lang3.StringUtils;

import com.evolveum.midpoint.ninja.action.*;
import com.evolveum.midpoint.ninja.action.upgrade.UpgradeObjectsItemsSummary;
import com.evolveum.midpoint.ninja.util.NinjaUtils;
import com.evolveum.midpoint.ninja.util.ThrowableSupplier;

Expand Down Expand Up @@ -46,89 +47,87 @@ private ActionResult<Void> createCanceledResult() {
public ActionResult<Void> execute() throws Exception {
File tempDirectory = createTmpDirectory(null);

// objects verification
log.info("Do you want to run objects verification before upgrade? yes/skip/cancel (y/s/C) [y] ");
String verifyResp = checkInputOrDefault(
() -> NinjaUtils.readInput(log, input -> StringUtils.isEmpty(input) || input.matches("[ysC]")),
"y"
);

if ("C".equals(verifyResp)) {
return createCanceledResult();
}
// verify
final PartialActionResult<VerifyResult> partialVerifyResult = startAction(
"Do you want to run verification before upgrade?",
"Skipping objects verification",
() -> {
File verificationFile = new File(tempDirectory, VERIFY_OUTPUT_FILE);

File verificationFile = null;
VerifyOptions verifyOptions = new VerifyOptions();
verifyOptions.setOutput(verificationFile);
verifyOptions.setOverwrite(true);
verifyOptions.setReportStyle(VerifyOptions.ReportStyle.CSV);

if (StringUtils.isEmpty(verifyResp) || "y".equalsIgnoreCase(verifyResp)) {
verificationFile = new File(tempDirectory, VERIFY_OUTPUT_FILE);
return executeAction(new VerifyAction(true), verifyOptions);
});

VerifyOptions verifyOptions = new VerifyOptions();
verifyOptions.setOutput(verificationFile);
verifyOptions.setOverwrite(true);
verifyOptions.setReportStyle(VerifyOptions.ReportStyle.CSV);

executeAction(new VerifyAction(), verifyOptions);
if (partialVerifyResult.canceled) {
return createCanceledResult();
}

// objects upgrade
if ("s".equalsIgnoreCase(verifyResp)) {
log.warn("Skipping objects verification");
}
final File verificationFile = partialVerifyResult.result != null ? partialVerifyResult.result.getVerificationFile() : null;

log.info("");
log.info("Do you want to update objects before upgrade? yes/skip/cancel (y/s/C) [y] ");
String upgradeObjectsResp = checkInputOrDefault(
() -> NinjaUtils.readInput(log, input -> StringUtils.isEmpty(input) || input.matches("[ysC]")),
"y"
);

if ("C".equals(upgradeObjectsResp)) {
// objects upgrade
final PartialActionResult<ActionResult<UpgradeObjectsItemsSummary>> partialUpgradeObjectsResult = startAction(
"Do you want to update objects before upgrade?",
"Skipping objects upgrade",
() -> {
File finalVerifiactionFile = verificationFile;

if (finalVerifiactionFile == null) {
log.info("Do you want to provide a file with verification issues? yes/no (y/n) [n] ");
String verifyFileResp = checkInputOrDefault(
() -> NinjaUtils.readInput(log, input -> StringUtils.isEmpty(input) || input.matches("[yn]")),
"n"
);

if ("y".equals(verifyFileResp)) {
// todo maybe more interactive validation? check file existence etc...
String filePath = NinjaUtils.readInput(log, input -> StringUtils.isNotEmpty(input));
finalVerifiactionFile = new File(filePath);
}
} else {
checkVerificationReviewed();
}

if (finalVerifiactionFile == null) {
// todo how to report them?
// * we should report separately if there are CRITICAL issues with phase=AFTER - cause they would be updated
// after installation is upgraded before midpoint is started (via ninja)
// * we should report separately if there are CRITICAL issues with type=MANUAL - cause they would not be updated by ninja
// * we should report separately if there are CRITICAL issues with type=PREVIEW - cause they probably should not be
log.info(
"Verification file was not created, nor provided. "
+ "Ninja will try to update all objects that contain verification issues."
+ "Verification issues that were skipped will be reported");
}

UpgradeObjectsOptions upgradeObjectsOptions = new UpgradeObjectsOptions();
upgradeObjectsOptions.setVerification(finalVerifiactionFile);

return executeAction(new UpgradeObjectsAction(true), upgradeObjectsOptions);
});

if (partialUpgradeObjectsResult.canceled) {
return createCanceledResult();
}

if ("s".equals(upgradeObjectsResp)) {
log.warn("Skipping objects upgrade");
}
// pre-upgrade checks
PartialActionResult<ActionResult<Boolean>> preUpgradeResult = startAction(
"Do you want to run pre-upgrade checks?",
"Skipping pre-upgrade checks",
() -> {

PreUpgradeCheckOptions preUpgradeCheckOptions = new PreUpgradeCheckOptions();
// todo options
return executeAction(new PreUpgradeCheckAction(true), preUpgradeCheckOptions);
});

if (StringUtils.isEmpty(upgradeObjectsResp) || "y".equals(upgradeObjectsResp)) {
if (verificationFile == null) {
log.info("Do you want to provide a file with verification issues? yes/no (y/n) [n] ");
String verifyFileResp = checkInputOrDefault(
() -> NinjaUtils.readInput(log, input -> StringUtils.isEmpty(input) || input.matches("[yn]")),
"n"
);

if ("y".equals(verifyFileResp)) {
// todo maybe more interactive validation? check file existence etc...
String filePath = NinjaUtils.readInput(log, input -> StringUtils.isNotEmpty(input));
verificationFile = new File(filePath);
}
} else {
checkVerificationReviewed();
}

if (verificationFile == null) {
// todo how to report them?
// * we should report separately if there are CRITICAL issues with phase=AFTER - cause they would be updated
// after installation is upgraded before midpoint is started (via ninja)
// * we should report separately if there are CRITICAL issues with type=MANUAL - cause they would not be updated by ninja
// * we should report separately if there are CRITICAL issues with type=PREVIEW - cause they probably should not be
log.info(
"Verification file was not created, nor provided. "
+ "Ninja will try to update all objects that contain verification issues."
+ "Verification issues that were skipped will be reported");
}

UpgradeObjectsOptions upgradeObjectsOptions = new UpgradeObjectsOptions();
upgradeObjectsOptions.setVerification(verificationFile);

// executeAction(new UpgradeObjectsAction(), upgradeObjectsOptions);
if (preUpgradeResult.canceled) {
return createCanceledResult();
}

// PreUpgradeCheckOptions preUpgradeCheckOptions = new PreUpgradeCheckOptions();
// // todo options
// executeAction(new PreUpgradeCheckAction(), preUpgradeCheckOptions);
//
// DownloadDistributionOptions downloadDistributionOptions = new DownloadDistributionOptions();
// // todo options
// executeAction(new DownloadDistributionAction(), downloadDistributionOptions);
Expand All @@ -141,6 +140,26 @@ public ActionResult<Void> execute() throws Exception {
return null;
}

private <T> PartialActionResult<T> startAction(String confirmMessage, String skipMessage, ThrowableSupplier<T> supplier) throws Exception {
log.info("");
log.info(confirmMessage + " yes/skip/cancel (y/s/C) [y] ");
String response = checkInputOrDefault(
() -> NinjaUtils.readInput(log, input -> StringUtils.isEmpty(input) || input.matches("[ysC]")),
"y"
);

if ("C".equals(response)) {
return new PartialActionResult(true, response);
}

if ("s".equals(response)) {
log.warn(skipMessage);
return new PartialActionResult<>(false, response);
}

return new PartialActionResult<>(false, response, supplier.get());
}

private boolean checkVerificationReviewed() throws Exception {
log.info("Have you reviewed verification issues? yes/no (y/n) [y] ");
String reviewedVerificationResp = checkInputOrDefault(
Expand All @@ -154,4 +173,23 @@ private boolean checkVerificationReviewed() throws Exception {

return true;
}

private static final class PartialActionResult<T> {

final boolean canceled;

final String confirmationChoice;

final T result;

PartialActionResult(boolean canceled, String confirmationChoice) {
this(canceled, confirmationChoice, null);
}

PartialActionResult(boolean canceled, String confirmationChoice, T result) {
this.canceled = canceled;
this.confirmationChoice = confirmationChoice;
this.result = result;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public ActionResult<Void> execute() throws Exception {
verifyOptions.setMultiThread(options.getVerificationThreads());
verifyOptions.setStopOnCriticalError(options.isStopOnCriticalError());

VerifyResult verifyResult = executeAction(new VerifyAction(), verifyOptions);
VerifyResult verifyResult = executeAction(new VerifyAction(true), verifyOptions);
if (!verifyResult.hasCriticalItems()) {
log.info(Ansi.ansi().fgGreen().a("Pre-upgrade verification succeeded.").reset().toString());
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@

public class UpgradeObjectsAction extends AbstractRepositorySearchAction<UpgradeObjectsOptions, ActionResult<UpgradeObjectsItemsSummary>> {

public UpgradeObjectsAction() {
}

public UpgradeObjectsAction(boolean partial) {
super(partial);
}

private Map<UUID, Set<SkipUpgradeItem>> skipUpgradeItems;

@Override
Expand Down Expand Up @@ -144,7 +151,7 @@ private Map<UUID, Set<SkipUpgradeItem>> loadVerificationFile() throws IOExceptio
if (verification == null || !verification.exists() || !verification.isFile()) {
// FIXME: Add log explanation, what is happening
if (context.isUserMode()) {
log.warn("Upgrade objects started without verification report, all neccessary non-manual changes will be accepted.");
log.warn("Upgrade objects started without verification report, all necessary non-manual changes will be accepted.");
}
return Collections.emptyMap();
}
Expand Down Expand Up @@ -214,7 +221,7 @@ protected void handleResultOnFinish(ActionResult<UpgradeObjectsItemsSummary> con
logSummary(consumerResult.result(), UpgradeObjectsItemsSummary.ItemStatus.SKIPPED);

OperationResult result = operation.getResult();
if (result.isAcceptable() && context.isUserMode()) {
if (result.isAcceptable() && context.isUserMode() && !partial) {
log.info("");
log.info("If you want to continue to continue with upgrade, please run: ninja.sh upgrade-distribution.");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ public void destroy() {
}

public void init() {
result.setVerificationFile(options.getOutput());

if (createDeltaFile) {
initDeltaXmlFile();
}
Expand Down

0 comments on commit 5eb6fba

Please sign in to comment.