com.centurylink.mdw.dataaccess.DataAccess Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of mdw-common Show documentation
Show all versions of mdw-common Show documentation
MDW is a workflow framework specializing in microservice orchestration
/*
* Copyright (C) 2017 CenturyLink, Inc.
*
* 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.
*/
package com.centurylink.mdw.dataaccess;
import java.io.File;
import java.io.IOException;
import java.sql.SQLException;
import com.centurylink.mdw.app.ApplicationContext;
import com.centurylink.mdw.cli.Checkpoint;
import com.centurylink.mdw.cli.Import;
import com.centurylink.mdw.config.PropertyManager;
import com.centurylink.mdw.constant.PropertyNames;
import com.centurylink.mdw.dataaccess.file.GitDiffs;
import com.centurylink.mdw.dataaccess.file.LoaderPersisterVcs;
import com.centurylink.mdw.dataaccess.file.MdwBaselineData;
import com.centurylink.mdw.dataaccess.file.RuntimeDataAccessVcs;
import com.centurylink.mdw.dataaccess.file.VersionControlGit;
import com.centurylink.mdw.dataaccess.file.WrappedBaselineData;
import com.centurylink.mdw.spring.SpringAppContext;
import com.centurylink.mdw.util.DesignatedHostSslVerifier;
import com.centurylink.mdw.util.log.LoggerUtil;
import com.centurylink.mdw.util.log.StandardLogger;
public class DataAccess {
public final static int schemaVersion60 = 6000;
public final static int schemaVersion61 = 6001;
public final static int currentSchemaVersion = schemaVersion61;
public static int supportedSchemaVersion = currentSchemaVersion;
public static boolean isPackageLevelAuthorization = true;
public static ProcessPersister getProcessPersister() throws DataAccessException {
return getProcessPersister(currentSchemaVersion, supportedSchemaVersion, new DatabaseAccess(null));
}
public static ProcessPersister getProcessPersister(int version, int supportedVersion, DatabaseAccess db)
throws DataAccessException {
File assetRoot = ApplicationContext.getAssetRoot();
if (assetRoot == null)
throw new IllegalStateException("Asset root not known");
return (ProcessPersister) getVcsProcessLoader(assetRoot);
}
public static ProcessLoader getProcessLoader(int version, int supportedVersion, DatabaseAccess db)
throws DataAccessException {
File assetRoot = ApplicationContext.getAssetRoot();
if (assetRoot == null)
throw new IllegalStateException("Asset root not known");
return getVcsProcessLoader(assetRoot);
}
public static ProcessLoader getProcessLoader(DatabaseAccess db) throws DataAccessException {
return getProcessLoader(currentSchemaVersion, supportedSchemaVersion, db);
}
public static ProcessLoader getProcessLoader() throws DataAccessException {
return getProcessLoader(currentSchemaVersion, supportedSchemaVersion, new DatabaseAccess(null));
}
public static RuntimeDataAccess getRuntimeDataAccess(DatabaseAccess db) throws DataAccessException {
File assetRoot = ApplicationContext.getAssetRoot();
if (assetRoot == null)
throw new IllegalStateException("Asset root not known");
return getVcsRuntimeDataAccess(db, assetRoot);
}
private static volatile ProcessLoader loaderPersisterVcs;
private static final Object loaderPersisterLock = new Object();
protected static ProcessLoader getVcsProcessLoader(File rootDir) throws DataAccessException {
ProcessLoader myLoaderPersisterVcs = loaderPersisterVcs;
if (myLoaderPersisterVcs == null) { // needs to be always the same version
synchronized(loaderPersisterLock) {
myLoaderPersisterVcs = loaderPersisterVcs;
if (myLoaderPersisterVcs == null) {
if (!rootDir.exists() || rootDir.list().length == 0) { // initial environment startup scenario
String message;
if (rootDir.isDirectory())
message = "Asset location " + rootDir + " is empty.";
else
message = "Asset location " + rootDir + " does not exist.";
String warning = "\n****************************************\n" +
"** WARNING: " + message + "\n" +
"** Please import the MDW base and hub packages\n" +
"******************************************\n";
LoggerUtil.getStandardLogger().severe(warning);
}
VersionControl vc = getAssetVersionControl(rootDir);
loaderPersisterVcs = myLoaderPersisterVcs = new LoaderPersisterVcs("mdw", rootDir, vc, getBaselineData());
}
}
}
return myLoaderPersisterVcs;
}
protected static RuntimeDataAccess getVcsRuntimeDataAccess(DatabaseAccess db, File rootDir) throws DataAccessException {
return new RuntimeDataAccessVcs(db, getBaselineData());
}
private static VersionControl assetVersionControl;
public synchronized static VersionControl getAssetVersionControl(File rootDir) throws DataAccessException {
if (assetVersionControl == null) {
assetVersionControl = new VersionControlGit();
String gitLocalPath = PropertyManager.getProperty(PropertyNames.MDW_GIT_LOCAL_PATH);
if (gitLocalPath == null) // use the asset dir as placeholder
gitLocalPath = rootDir.getAbsolutePath();
try {
assetVersionControl.connect(null, "mdw", null, new File(gitLocalPath));
// check up-to-date
StandardLogger logger = LoggerUtil.getStandardLogger();
try {
String url = PropertyManager.getProperty(PropertyNames.MDW_GIT_REMOTE_URL);
String branch = PropertyManager.getProperty(PropertyNames.MDW_GIT_BRANCH);
String tag = branch == null ? PropertyManager.getProperty(PropertyNames.MDW_GIT_TAG) : null;
if (url != null && (branch != null || tag != null)) {
String user = PropertyManager.getProperty(PropertyNames.MDW_GIT_USER);
String password = PropertyManager.getProperty(PropertyNames.MDW_GIT_PASSWORD);
if (user != null) {
VersionControlGit vcGit = (VersionControlGit) assetVersionControl;
File gitLocal = new File(gitLocalPath);
vcGit.connect(url, user, password, gitLocal);
String gitTrustedHost = PropertyManager.getProperty(PropertyNames.MDW_GIT_TRUSTED_HOST);
if (gitTrustedHost != null)
DesignatedHostSslVerifier.setupSslVerification(gitTrustedHost);
String assetPath = vcGit.getRelativePath(rootDir);
logger.info("Loading assets from path: " + assetPath);
if (!gitLocal.isDirectory()) {
if (!gitLocal.mkdirs())
throw new DataAccessException("Git loc " + gitLocalPath + " does not exist and cannot be created.");
}
if (!vcGit.localRepoExists()) {
logger.severe("**** WARNING: Git location " + gitLocalPath + " does not contain a repository. Cloning: " + url);
vcGit.cloneNoCheckout();
if (PropertyManager.getBooleanProperty(PropertyNames.MDW_GIT_AUTO_CHECKOUT, true)) {
if (branch != null) {
logger.info("Performing branch checkout...");
vcGit.hardCheckout(branch);
}
else { // tag != null
logger.info("Performing tag checkout...");
vcGit.hardTagCheckout(tag);
}
}
else
logger.warn("Git Auto Checkout is set to false! No assets will be pulled from Git...");
}
// sanity checks
if (branch != null) {
String gitBranch = vcGit.getBranch();
if (!branch.equals(gitBranch)) {
String warning = "\n****************************************\n" +
"** WARNING: Git branch: " + gitBranch + " does not match " + PropertyNames.MDW_GIT_BRANCH + ": " + branch + "\n" +
"** Please perform an Import to sync with branch " + branch + "\n" +
"******************************************\n";
LoggerUtil.getStandardLogger().severe(warning);
} else {
String localCommit = vcGit.getCommit();
if (localCommit != null) {
String remoteCommit = vcGit.getRemoteCommit(branch);
if (!localCommit.equals(remoteCommit))
LoggerUtil.getStandardLogger().severe("**** WARNING: Git commit: " + localCommit + " does not match remote HEAD commit: " + remoteCommit);
}
// log actual diffs at debug level
GitDiffs diffs = vcGit.getDiffs(branch, assetPath);
if (!diffs.isEmpty()) {
logger.warn("**** WARNING: Local Git repository is out-of-sync with respect to remote branch: " + branch
+ "\n(" + gitLocal.getAbsolutePath() + ")");
logger.info("Differences:\n============\n" + diffs);
}
}
}
else { // Tag != null
String localCommit = vcGit.getCommit();
String tagCommit = vcGit.getCommitForTag(tag);
if (localCommit != null && tagCommit != null && !localCommit.equals(tagCommit)) {
logger.info("Current commit " + localCommit + " does not match commit for tag " + tag + ". Performing tag checkout...");
vcGit.hardTagCheckout(tag);
}
else if (localCommit == null)
logger.warn("Could not find local commit!");
else if (tagCommit == null) {
logger.warn("Git Tag named " + tag + " was NOT found!");
}
}
}
else {
logger.severe("**** WARNING: Not verifying Git asset sync due to missing property " + PropertyNames.MDW_GIT_USER + " (use anonymous for public repos)");
}
}
}
catch (Exception ex) {
logger.severeException("Error during Git up-to-date check.", ex);
}
// allow initial startup with no asset root
if (!rootDir.exists()) {
if (!rootDir.mkdirs())
throw new DataAccessException("Asset root: " + rootDir + " does not exist and cannot be created.");
}
}
catch (IOException ex) {
throw new DataAccessException(ex.getMessage(), ex);
}
}
return assetVersionControl;
}
public static void updateAssetRefs() throws DataAccessException {
StandardLogger logger = LoggerUtil.getStandardLogger();
// asset ref autopopulation disabled by default for dev envs
boolean autopop = PropertyManager.getBooleanProperty(PropertyNames.MDW_ASSET_REF_AUTOPOP, !ApplicationContext.isDevelopment());
if (autopop && assetVersionControl != null && !PropertyManager.getBooleanProperty(PropertyNames.MDW_GIT_AUTO_PULL, false)) {
// Automatically update ASSET_REF DB table in case application doesn't do an Import - safety measure
File assetLoc = ApplicationContext.getAssetRoot();
VersionControlGit vcGit = (VersionControlGit) assetVersionControl;
try (DbAccess dbAccess = new DbAccess()) {
String ref = vcGit.getCommit();
if (ref != null) { // avoid attempting update for local-only resources
logger.info("Auto-populating ASSET_REF table...");
Checkpoint cp = new Checkpoint(assetLoc, vcGit, vcGit.getCommit(), dbAccess.getConnection());
cp.updateRefs();
}
else
logger.info("ASSET_REF table not auto-populated during startup due to: null Git commit");
}
catch (SQLException e) {
throw new DataAccessException(e.getErrorCode(), e.getMessage(), e);
}
catch (IOException e) {
throw new DataAccessException(e.getMessage(), e);
}
}
else {
String message = "";
if (assetVersionControl == null) message = " (AssetVersionControl is null)";
if ("true".equals(PropertyManager.getProperty(PropertyNames.MDW_GIT_AUTO_PULL))) message = message.length() == 0 ? " (mdw.git.auto.pull=true)" : ", (mdw.git.auto.pull=true";
logger.info("ASSET_REF table not auto-populated during startup. " + message);
}
}
public static BaselineData getBaselineData() throws DataAccessException {
try {
return new WrappedBaselineData(new MdwBaselineData()) {
protected BaselineData getOverrideBaselineData() {
return SpringAppContext.getInstance().getBaselineData();
}
};
}
catch (Exception ex) {
throw new DataAccessException(ex.getMessage(), ex);
}
}
/**
* TODO differentiate version 6
*/
public static int[] getDatabaseSchemaVersion(DatabaseAccess db) throws DataAccessException {
return new int[] {schemaVersion60, schemaVersion61};
}
}