diff --git a/hawkbit-repository/hawkbit-repository-jpa-init/src/main/java/org/eclipse/hawkbit/repository/jpa/init/HawkbitFlywayDbInit.java b/hawkbit-repository/hawkbit-repository-jpa-init/src/main/java/org/eclipse/hawkbit/repository/jpa/init/HawkbitFlywayDbInit.java index 3e363d8f6..5c225bef5 100644 --- a/hawkbit-repository/hawkbit-repository-jpa-init/src/main/java/org/eclipse/hawkbit/repository/jpa/init/HawkbitFlywayDbInit.java +++ b/hawkbit-repository/hawkbit-repository-jpa-init/src/main/java/org/eclipse/hawkbit/repository/jpa/init/HawkbitFlywayDbInit.java @@ -14,6 +14,10 @@ import java.util.regex.Pattern; import lombok.extern.slf4j.Slf4j; import org.flywaydb.core.Flyway; +import org.flywaydb.core.api.CoreErrorCode; +import org.flywaydb.core.api.ErrorCode; +import org.flywaydb.core.api.FlywayException; +import org.flywaydb.core.api.exception.FlywayValidateException; /** * hawkBit Flyway db init configuration. Could be configured with "hawkbit.db.*" or "spring.database.*" environment or system properties, @@ -35,24 +39,41 @@ import org.flywaydb.core.Flyway; * There are two modes: * * Note: could also be configured using default flyway env properties + *

+ * Exit codes: + *

+ * Note: {@link HawkbitFlywayDbInit#EXIT_CODE_VALIDATE_FAILED} doesn't really mean it is an error, it in general is most likely that the state of the db schema - it doesn't match the target versions. */ @Slf4j public class HawkbitFlywayDbInit { + public static final int EXIT_CODE_SUCCESS = 0; + public static final int EXIT_CODE_FAILED = 1; // default exit code when error happens + public static final int EXIT_CODE_VALIDATE_FAILED = 2; + public static final String MIGRATE = "migrate"; + public static final String VALIDATE = "validate"; - public static final String MODE = prop("mode", "validate"); + private static final String MODE = prop("mode", VALIDATE); - public static final String URL = prop("url", "jdbc:h2:mem:hawkbit;MODE=LEGACY;"); - public static final String USER = prop("username", "sa"); - public static final String PASSWORD = prop("password", ""); - protected static final String TABLE = prop("table", "schema_version"); + private static final String URL = prop("url", "jdbc:h2:mem:hawkbit;MODE=LEGACY;"); + private static final String USER = prop("username", "sa"); + private static final String PASSWORD = prop("password", ""); + private static final String TABLE = prop("table", "schema_version"); - public static final String[] LOCATIONS = prop("locations", "db/migration").split(","); - public static final String SQL_MIGRATION_SUFFIXES = prop("sql-migration-suffixes", suffix(URL)) + ".sql"; + private static final String[] LOCATIONS = prop("locations", "db/migration").split(","); + private static final String SQL_MIGRATION_SUFFIXES = prop("sql-migration-suffixes", suffix(URL)) + ".sql"; + + private static final String EXCEPTION_MESSAGE = "Exception message: {}"; public static void main(final String[] args) { final Flyway flyway = Flyway.configure() @@ -69,10 +90,40 @@ public class HawkbitFlywayDbInit { MODE, USER, URL, TABLE, LOCATIONS, SQL_MIGRATION_SUFFIXES); if (MODE.equals(MIGRATE)) { - flyway.migrate(); + try { + flyway.migrate(); + } catch (final FlywayException e) { + final ErrorCode errorCode = e.getErrorCode(); + final int errorCodeOrdinal = errorCode instanceof CoreErrorCode coreErrorCode ? coreErrorCode.ordinal() : -1; + log.error("Flyway migrate failed: error code = {}, error code ordinal = {}", errorCode, errorCodeOrdinal); + log.debug(EXCEPTION_MESSAGE, e.getMessage()); + System.exit(EXIT_CODE_FAILED); // migration failed + } catch (final Throwable e) { + log.error("Flyway validate failed (undeclared exception): ", e); + System.exit(EXIT_CODE_FAILED); // migration failed with undeclared exception + } } else { - flyway.validate(); + try { + flyway.validate(); + } catch (final FlywayValidateException e) { + final ErrorCode errorCode = e.getErrorCode(); + final int errorCodeOrdinal = errorCode instanceof CoreErrorCode coreErrorCode ? coreErrorCode.ordinal() : -1; + log.error("Flyway validate failed (FlywayValidateException): error code = {}, error code ordinal = {}", errorCode, errorCodeOrdinal); + log.info(EXCEPTION_MESSAGE, e.getMessage()); + System.exit(EXIT_CODE_VALIDATE_FAILED); // validation failed, not real error but tables are not valid + } catch (final FlywayException e) { + final ErrorCode errorCode = e.getErrorCode(); + final int errorCodeOrdinal = errorCode instanceof CoreErrorCode coreErrorCode ? coreErrorCode.ordinal() : -1; + log.error("Flyway validate failed: error code = {}, error code ordinal = {}", errorCode, errorCodeOrdinal); + log.info(EXCEPTION_MESSAGE, e.getMessage()); + System.exit(EXIT_CODE_FAILED); // validation failed + } catch (final Throwable e) { + log.error("Flyway validate failed (undeclared exception): ", e); + System.exit(EXIT_CODE_FAILED); // validation failed with undeclared exception + } } + + System.exit(EXIT_CODE_SUCCESS); } private static String prop(final String key, final String defaultValue) {