Repository: hashgraph/hedera-mirror-node
Issue: DB migration error 

**Detailed Description**
ERROR [main ] o.f.c.i.c.DbMigrate Migration of schema "public" to version 1.8 - MigrateConfig failed! Changes successfully rolled back.

The issue affects any attempt to migrate the database (which running any of the services does) when:
- The database had not already migrated v1.8 of the DB, **_and_**
- `./config/config.json` is not located relative to the working directory of the running service/app.

This would include anyone trying to install out of the CI-deliverable, using the instructions for installing that, against a fresh/empty database (as ./config/config.json is no longer located at that place relative to the running service's working directory).

**Workaround**
Ensure that "config.json" is found in the "./config/" directory relative to the working directory of the running processes (any of the downloaders or parsers).

If the working directory of the processes is /usr/lib/mirror-node and the config.json is in /usr/etc/mirror-node, then:

- `sudo ln -s /usr/etc/mirror-node /usr/lib/mirror-node/config`
- restart all downloader and parser processes

**Actual Behavior**

**Expected Behavior**

**Environment:**

**Additional Context**

Fix will be to remove the v1.8 migration code as it's not needed for a fresh DB, is causing this issue, and was only in place to upgrade from pre-v0.1.0 systems.


Changed files:
src/main/java/db/migration/V1_8__MigrateConfig.java, src/main/java/com/hedera/databaseUtilities/DatabaseUtilities.java

diff --git a/src/main/java/com/hedera/databaseUtilities/DatabaseUtilities.java b/src/main/java/com/hedera/databaseUtilities/DatabaseUtilities.java
index ce51629af..7cc839716 100644
--- a/src/main/java/com/hedera/databaseUtilities/DatabaseUtilities.java
+++ b/src/main/java/com/hedera/databaseUtilities/DatabaseUtilities.java
@@ -53,6 +53,16 @@ public class DatabaseUtilities {
                     .dataSource(dataSource)
                     .baselineOnMigrate(true)
                     .baselineVersion(MigrationVersion.fromVersion("0"))
+
+                    // Allow missing migrations without failing the overall migration.
+                    // This would allow the database to have a "V1.23" migration in it (before the product is 1.0-ready),
+                    // that gets removed by developers at a future point.
+                    // When the software is updated and no longer has V1.23 in it (bad migration file removed by dev),
+                    // but flyway sees a database that had V1.23 in it - ignore this issue and continue flyway migrations.
+                    // This allows development to more easily "fix" some bad initial migration files without resorting
+                    // to `flyway repair`.
+                    .ignoreMissingMigrations(true)
+
                     .placeholders(ImmutableMap.of(
                             "api-user", ConfigLoader.getApiUsername(),
                             "api-password", ConfigLoader.getApiPassword(),
diff --git a/src/main/java/db/migration/V1_8__MigrateConfig.java b/src/main/java/db/migration/V1_8__MigrateConfig.java
deleted file mode 100644
index d57fe3292..000000000
--- a/src/main/java/db/migration/V1_8__MigrateConfig.java
+++ /dev/null
@@ -1,203 +0,0 @@
-package db.migration;
-
-/*-
- * ‌
- * Hedera Mirror Node
- * ​
- * Copyright (C) 2019 Hedera Hashgraph, LLC
- * ​
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- *      http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ‍
- */
-
-import org.flywaydb.core.api.migration.BaseJavaMigration;
-import org.flywaydb.core.api.migration.Context;
-
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import com.google.gson.JsonIOException;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonParser;
-import com.google.gson.JsonSyntaxException;
-import com.hedera.databaseUtilities.ApplicationStatus;
-
-import lombok.extern.log4j.Log4j2;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileReader;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.sql.PreparedStatement;
-
-@Log4j2
-public class V1_8__MigrateConfig extends BaseJavaMigration {
-    public void migrate(Context context) throws Exception {
-    	
-    	String configSavePath = "./config/config.json";
-    	String balanceSavePath = "./config/balance.json";
-    	String recordsSavePath = "./config/records.json";
-    	String eventsSavePath = "./config/events.json";
-    	String loggerSavePath = "./config/loggerStatus.json";
-    	
-    	JsonObject configJsonObject;
-    	JsonObject balanceJsonObject;
-    	JsonObject recordsJsonObject;
-    	JsonObject eventsJsonObject;
-    	JsonObject loggerJsonObject;
-    	
-    	String stopLoggingIfRecordHashMismatchAfter = "";
-    	String stopLoggingIfEventHashMismatchAfter = "";
-    	String lastValidBalanceFileName = "";
-    	String lastValidRcdFileName = "";
-    	String lastValidRcdFileHash = "";
-    	String lastValidEventFileName = "";
-    	String lastValidEventFileHash = "";
-    	String lastProcessedRcdHash = "";
-    	String lastProcessedEventHash = "";
-    	
-		configJsonObject = getJsonObject(configSavePath);
-
-		if (configJsonObject.has("stopLoggingIfRecordHashMismatch")) {
-			stopLoggingIfRecordHashMismatchAfter = configJsonObject.get("stopLoggingIfRecordHashMismatch").getAsString();
-		}
-		
-		if (configJsonObject.has("stopLoggingIfEventHashMismatch")) {
-			stopLoggingIfEventHashMismatchAfter = configJsonObject.get("stopLoggingIfEventHashMismatch").getAsString();
-		}
-		File balanceFile = new File(balanceSavePath);
-		if (balanceFile.exists()) {
-			balanceJsonObject = getJsonObject(balanceSavePath);
-			if (balanceJsonObject.has("lastValidBalanceFileName")) {
-				lastValidBalanceFileName = balanceJsonObject.get("lastValidBalanceFileName").getAsString();
-			}
-		} else if (configJsonObject.has("lastValidBalanceFileName")) {
-			lastValidBalanceFileName = configJsonObject.get("lastValidBalanceFileName").getAsString();
-		}
-
-		File recordFile = new File(recordsSavePath);
-		if (recordFile.exists()) {
-			recordsJsonObject = getJsonObject(recordsSavePath);
-			if (recordsJsonObject.has("lastValidRcdFileName")) {
-				lastValidRcdFileName = recordsJsonObject.get("lastValidRcdFileName").getAsString();
-			}
-			if (recordsJsonObject.has("lastValidRcdFileHash")) {
-				lastValidRcdFileHash = recordsJsonObject.get("lastValidRcdFileHash").getAsString();
-			}
-		} else if ((configJsonObject.has("lastValidRcdFileName")) || (configJsonObject.has("lastValidRcdFileHash"))) {
-			if (configJsonObject.has("lastValidRcdFileName")) {
-				lastValidRcdFileName = configJsonObject.get("lastValidRcdFileName").getAsString();
-			}
-			if (configJsonObject.has("lastValidRcdFileHash")) {
-				lastValidRcdFileHash = configJsonObject.get("lastValidRcdFileHash").getAsString();
-			}
-		}
-
-		File eventFile = new File(eventsSavePath);
-		if (eventFile.exists()) {
-			eventsJsonObject = getJsonObject(eventsSavePath);
-			if (eventsJsonObject.has("lastValidEventFileName")) {
-				lastValidEventFileName = eventsJsonObject.get("lastValidEventFileName").getAsString();
-			}
-			if (eventsJsonObject.has("lastValidEventFileHash")) {
-			    lastValidEventFileHash = eventsJsonObject.get("lastValidEventFileHash").getAsString();
-			}
-		}
-		
-		File loggerFile = new File (loggerSavePath);
-		
-		if (loggerFile.exists()) {
-			loggerJsonObject = getJsonObject(loggerSavePath);
-			
-			if (loggerJsonObject.has("lastProcessedRcdHash")) {
-				lastProcessedRcdHash = loggerJsonObject.get("lastProcessedRcdHash").getAsString();
-			}
-			if (loggerJsonObject.has("lastProcessedEventHash")) {
-				lastProcessedEventHash = loggerJsonObject.get("lastProcessedEventHash").getAsString();
-			}
-		}
-
-		try (PreparedStatement updateValue = context.getConnection().prepareStatement(
-				"UPDATE t_application_status SET "
-				+ " status_value = ? "
-				+ " WHERE status_code = ?")) {
-			updateValue.setString(1, stopLoggingIfEventHashMismatchAfter);
-			updateValue.setString(2, ApplicationStatus.ApplicationStatusCode.EVENT_HASH_MISMATCH_BYPASS_UNTIL_AFTER.name());
-			updateValue.execute();
-			updateValue.setString(1, stopLoggingIfRecordHashMismatchAfter);
-			updateValue.setString(2, ApplicationStatus.ApplicationStatusCode.RECORD_HASH_MISMATCH_BYPASS_UNTIL_AFTER.name());
-			updateValue.execute();
-			updateValue.setString(1, lastValidBalanceFileName);
-			updateValue.setString(2, ApplicationStatus.ApplicationStatusCode.LAST_VALID_DOWNLOADED_BALANCE_FILE.name());
-			updateValue.execute();
-			updateValue.setString(1, lastValidRcdFileName);
-			updateValue.setString(2, ApplicationStatus.ApplicationStatusCode.LAST_VALID_DOWNLOADED_RECORD_FILE.name());
-			updateValue.execute();
-			updateValue.setString(1, lastValidRcdFileHash);
-			updateValue.setString(2, ApplicationStatus.ApplicationStatusCode.LAST_VALID_DOWNLOADED_RECORD_FILE_HASH.name());
-			updateValue.execute();
-			updateValue.setString(1, lastValidEventFileName);
-			updateValue.setString(2, ApplicationStatus.ApplicationStatusCode.LAST_VALID_DOWNLOADED_EVENT_FILE.name());
-			updateValue.execute();
-			updateValue.setString(1, lastValidEventFileHash);
-			updateValue.setString(2, ApplicationStatus.ApplicationStatusCode.LAST_VALID_DOWNLOADED_EVENT_FILE_HASH.name());
-			updateValue.execute();
-			updateValue.setString(1, lastProcessedRcdHash);
-			updateValue.setString(2, ApplicationStatus.ApplicationStatusCode.LAST_PROCESSED_RECORD_HASH.name());
-			updateValue.execute();
-			updateValue.setString(1, lastProcessedEventHash);
-			updateValue.setString(2, ApplicationStatus.ApplicationStatusCode.LAST_PROCESSED_EVENT_HASH.name());
-			updateValue.execute();
-		}
-		
-		// remove from config file
-		configJsonObject.remove("lastValidRcdFileName");
-		configJsonObject.remove("lastValidRcdFileHash");
-		configJsonObject.remove("stopLoggingIfRecordHashMismatch");
-		configJsonObject.remove("stopLoggingIfEventHashMismatch");
-		configJsonObject.remove("lastValidBalanceFileName");
-
-		try (FileWriter configFile = new FileWriter(configSavePath)) {
-			Gson gson = new GsonBuilder().setPrettyPrinting().create();
-			gson.toJson(configJsonObject, configFile);
-			log.debug("Successfully wrote update to {}", configSavePath);
-		} catch (IOException ex) {
-			log.error("Fail to write update to {}", configSavePath, ex);
-			throw ex;
-		}
-
-		if (balanceFile.exists()) {
-			balanceFile.delete();
-		}
-		if (recordFile.exists()) {
-			recordFile.delete();
-		}
-		if (eventFile.exists()) {
-			eventFile.delete();
-		}
-		if (loggerFile.exists()) {
-			loggerFile.delete();
-		}
-    }
-    
-	private JsonObject getJsonObject(
-			final String location) throws JsonIOException, JsonSyntaxException, FileNotFoundException {
-
-		final JsonParser parser = new JsonParser();
-
-		// Read file into object
-		final FileReader file = new FileReader(location);
-		return (JsonObject) parser.parse(file);
-	}    
-	
-}