use of liquibase.hub.LiquibaseHubException in project liquibase by liquibase.
the class HttpClient method doRequest.
protected <T> T doRequest(String method, String url, Object requestBodyObject, Class<T> returnType, Class contentReturnType) throws LiquibaseHubException {
try {
HttpURLConnection connection = (HttpURLConnection) openConnection(url);
if (requestBodyObject != null) {
connection.setDoOutput(true);
}
connection.setRequestMethod(method);
String requestBodyDescription = "";
if (requestBodyObject != null) {
String requestBody = yaml.dumpAs(requestBodyObject, Tag.MAP, DumperOptions.FlowStyle.FLOW);
// strip out problematic text
requestBody = requestBody.replaceAll("(?m)^(\\s*)!![a-zA-Z0-9.]+", "$1").replaceAll("!!int \"(\\d+)\"", "$1").replaceAll("!!java.util.UUID ", "").replaceAll("!!null \"null\"", "null").replaceAll("!!liquibase.hub.model.hubChange ", "").replaceAll("!!timestamp '(.+?)'", "\"$1\"");
try (OutputStream output = connection.getOutputStream()) {
output.write(requestBody.getBytes(StandardCharsets.UTF_8));
}
requestBodyDescription = " with a " + requestBody.length() + " char " + requestBodyObject.getClass().getName() + " request body";
}
Scope.getCurrentScope().getLog(getClass()).fine(method.toUpperCase() + " " + url + requestBodyDescription);
try (InputStream response = connection.getInputStream()) {
// TODO: figure out how to populate ListResponse.content with objects rather than maps
// if (contentReturnType != null) {
// final TypeDescription peopleDescription = new TypeDescription(contentReturnType);
// peopleDescription.addPropertyParameters("content", List.class, contentReturnType);
// yaml.addTypeDescription(peopleDescription);
// }
int responseCode = connection.getResponseCode();
if (responseCode != HttpURLConnection.HTTP_OK) {
if (responseCode == HttpURLConnection.HTTP_MOVED_TEMP || responseCode == HttpURLConnection.HTTP_MOVED_PERM || responseCode == HttpURLConnection.HTTP_SEE_OTHER) {
//
// Get redirect url from "location" header field
//
String newHubUrl = connection.getHeaderField("Location");
newHubUrl = newHubUrl.replaceAll(url, "");
Scope.getCurrentScope().getLog(getClass()).info("Redirecting to URL: " + newHubUrl);
DeprecatedConfigurationValueProvider.setData(HubConfiguration.LIQUIBASE_HUB_URL, newHubUrl);
throw new LiquibaseHubRedirectException();
}
}
String contentType = connection.getContentType();
if (!contentType.equals("application/json")) {
throw new LiquibaseHubException("\nUnexpected content type '" + contentType + "' returned from Hub. Response code is " + responseCode);
}
return (T) yaml.loadAs(response, returnType);
} catch (IOException e) {
if (connection.getResponseCode() == 401) {
throw new LiquibaseHubSecurityException("Authentication failure for " + connection.getRequestMethod() + " " + connection.getURL().toExternalForm() + "\n" + "Check your Liquibase Hub API Key or other permissions. Learn more https://hub.liquibase.com.");
}
try {
try (InputStream error = connection.getErrorStream()) {
if (error != null) {
Object loadedObject = yaml.load(error);
if (loadedObject instanceof Map) {
final Map errorDetails = (Map) loadedObject;
LiquibaseHubException returnException = new LiquibaseHubException((String) errorDetails.get("message"), e);
if (connection.getResponseCode() == 404) {
returnException = new LiquibaseHubObjectNotFoundException(returnException.getMessage(), returnException.getCause());
}
returnException.setTimestamp((String) errorDetails.get("timestamp"));
returnException.setDetails((String) errorDetails.get("details"));
throw returnException;
} else {
String errorMessage = "Unable to parse '" + loadedObject.toString() + "': " + e.getMessage();
throw new LiquibaseHubException(errorMessage, e.getCause());
}
}
}
} catch (IOException ioException) {
Scope.getCurrentScope().getLog(getClass()).info("Cannot read request error stream", e);
}
throw new LiquibaseHubException(e);
}
} catch (IOException e) {
throw new LiquibaseHubException(e);
}
}
use of liquibase.hub.LiquibaseHubException in project liquibase by liquibase.
the class HubChangeExecListener method updateHubForRollback.
//
// Send an update message to Hub for this change set rollback
//
private void updateHubForRollback(ChangeSet changeSet, DatabaseChangeLog databaseChangeLog, Database database, String operationStatusType, String statusMessage) {
if (operation == null) {
String apiKey = StringUtil.trimToNull(HubConfiguration.LIQUIBASE_HUB_API_KEY.getCurrentValue());
boolean hubOn = HubConfiguration.LIQUIBASE_HUB_MODE.getCurrentValue() != HubConfiguration.HubMode.OFF;
if (apiKey != null && hubOn) {
String message = "Hub communication failure.\n" + "The data for operation on changeset '" + changeSet.getId() + "' by author '" + changeSet.getAuthor() + "'\n" + "was not successfully recorded in your Liquibase Hub project";
Scope.getCurrentScope().getUI().sendMessage(message);
logger.info(message);
}
return;
}
HubChangeLog hubChangeLog;
final HubService hubService = Scope.getCurrentScope().getSingleton(HubServiceFactory.class).getService();
try {
hubChangeLog = hubService.getHubChangeLog(UUID.fromString(databaseChangeLog.getChangeLogId()));
if (hubChangeLog == null) {
logger.warning("The changelog '" + databaseChangeLog.getPhysicalFilePath() + "' has not been registered with Hub");
return;
}
} catch (LiquibaseHubException lhe) {
logger.warning("The changelog '" + databaseChangeLog.getPhysicalFilePath() + "' has not been registered with Hub");
return;
}
Date dateExecuted = new Date();
//
// POST /organizations/{id}/projects/{id}/operations/{id}/change-events
//
OperationChangeEvent operationChangeEvent = new OperationChangeEvent();
operationChangeEvent.setEventType("ROLLBACK");
operationChangeEvent.setStartDate(startDateMap.get(changeSet));
operationChangeEvent.setEndDate(dateExecuted);
operationChangeEvent.setDateExecuted(dateExecuted);
operationChangeEvent.setChangesetId(changeSet.getId());
operationChangeEvent.setChangesetFilename(changeSet.getFilePath());
operationChangeEvent.setChangesetAuthor(changeSet.getAuthor());
List<String> sqlList = new ArrayList<>();
try {
if (rollbackScriptContents != null) {
sqlList.add(rollbackScriptContents);
} else if (changeSet.hasCustomRollbackChanges()) {
List<Change> changes = changeSet.getRollback().getChanges();
for (Change change : changes) {
SqlStatement[] statements = change.generateStatements(database);
for (SqlStatement statement : statements) {
for (Sql sql : SqlGeneratorFactory.getInstance().generateSql(statement, database)) {
sqlList.add(sql.toSql());
}
}
}
} else {
List<Change> changes = changeSet.getChanges();
for (Change change : changes) {
SqlStatement[] statements = change.generateRollbackStatements(database);
for (SqlStatement statement : statements) {
for (Sql sql : SqlGeneratorFactory.getInstance().generateSql(statement, database)) {
sqlList.add(sql.toSql());
}
}
}
}
} catch (LiquibaseException lbe) {
logger.warning(lbe.getMessage());
}
String[] sqlArray = new String[sqlList.size()];
sqlArray = sqlList.toArray(sqlArray);
operationChangeEvent.setGeneratedSql(sqlArray);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ChangeLogSerializer serializer = ChangeLogSerializerFactory.getInstance().getSerializer(".json");
try {
serializer.write(Collections.singletonList(changeSet), baos);
operationChangeEvent.setChangesetBody(baos.toString("UTF-8"));
} catch (IOException ioe) {
//
// Consume
//
}
operationChangeEvent.setOperationStatusType(operationStatusType);
operationChangeEvent.setStatusMessage(statusMessage);
if ("FAIL".equals(operationStatusType)) {
operationChangeEvent.setLogs(statusMessage);
} else {
String logs = getCurrentLog();
if (!StringUtil.isEmpty(logs)) {
operationChangeEvent.setLogs(logs);
} else {
operationChangeEvent.setLogs(statusMessage);
}
}
operationChangeEvent.setLogsTimestamp(new Date());
operationChangeEvent.setProject(hubChangeLog.getProject());
operationChangeEvent.setOperation(operation);
try {
hubService.sendOperationChangeEvent(operationChangeEvent);
postCount++;
} catch (LiquibaseException lbe) {
logger.warning(lbe.getMessage(), lbe);
logger.warning("Unable to send Operation Change Event for operation '" + operation.getId().toString() + " change set '" + changeSet.toString(false));
}
}
use of liquibase.hub.LiquibaseHubException in project liquibase by liquibase.
the class HubChangeExecListener method updateHub.
//
// Send an update message to Hub for this change set
//
private void updateHub(ChangeSet changeSet, DatabaseChangeLog databaseChangeLog, Database database, String eventType, String operationStatusType, String statusMessage) {
//
if (operation == null) {
String apiKey = StringUtil.trimToNull(HubConfiguration.LIQUIBASE_HUB_API_KEY.getCurrentValueObfuscated());
boolean hubOn = HubConfiguration.LIQUIBASE_HUB_MODE.getCurrentValue() != HubConfiguration.HubMode.OFF;
if (apiKey != null && hubOn) {
String message;
if (databaseChangeLog.getChangeLogId() == null) {
message = "The changelog '" + databaseChangeLog.getPhysicalFilePath() + "' has not been registered with Liquibase Hub.\n" + "To register the changelog with your Hub Project run 'liquibase registerChangeLog'.\n" + "Learn more at https://hub.liquibase.com.";
} else {
message = "The changelog file specified is not registered with any Liquibase Hub project, so the results will not be recorded in Liquibase Hub.\n" + "To register the changelog with your Hub Project run 'liquibase registerChangeLog'.\n" + "Learn more at https://hub.liquibase.com.";
}
Scope.getCurrentScope().getUI().sendMessage(message);
logger.info(message);
}
return;
}
HubChangeLog hubChangeLog;
final HubService hubService = Scope.getCurrentScope().getSingleton(HubServiceFactory.class).getService();
try {
hubChangeLog = hubService.getHubChangeLog(UUID.fromString(databaseChangeLog.getChangeLogId()));
if (hubChangeLog == null) {
logger.warning("The changelog '" + databaseChangeLog.getPhysicalFilePath() + "' has not been registered with Hub");
return;
}
} catch (LiquibaseHubException lhe) {
logger.warning("The changelog '" + databaseChangeLog.getPhysicalFilePath() + "' has not been registered with Hub");
return;
}
//
// POST /organizations/{id}/projects/{id}/operations/{id}/change-events
// Do not send generated SQL or changeset body for changeLogSync operation
//
OperationChangeEvent operationChangeEvent = new OperationChangeEvent();
List<String> sqlList = new ArrayList<>();
if (!eventType.equals("SYNC")) {
List<Change> changes = changeSet.getChanges();
for (Change change : changes) {
try {
Sql[] sqls = SqlGeneratorFactory.getInstance().generateSql(change, database);
for (Sql sql : sqls) {
sqlList.add(sql.toSql());
}
} catch (Exception e) {
logger.warning("Unable to generate SQL for Hub failure message: " + e.getMessage());
}
}
String[] sqlArray = new String[sqlList.size()];
sqlArray = sqlList.toArray(sqlArray);
operationChangeEvent.setGeneratedSql(sqlArray);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ChangeLogSerializer serializer = ChangeLogSerializerFactory.getInstance().getSerializer(".json");
try {
serializer.write(Collections.singletonList(changeSet), baos);
operationChangeEvent.setChangesetBody(baos.toString("UTF-8"));
} catch (IOException ioe) {
//
// Just log message
//
logger.warning("Unable to serialize change set '" + changeSet.toString(false) + "' for Hub.");
}
}
Date dateExecuted = new Date();
String[] sqlArray = new String[sqlList.size()];
sqlArray = sqlList.toArray(sqlArray);
operationChangeEvent.setEventType(eventType);
operationChangeEvent.setStartDate(startDateMap.get(changeSet));
operationChangeEvent.setEndDate(dateExecuted);
operationChangeEvent.setDateExecuted(dateExecuted);
operationChangeEvent.setChangesetId(changeSet.getId());
operationChangeEvent.setChangesetFilename(changeSet.getFilePath());
operationChangeEvent.setChangesetAuthor(changeSet.getAuthor());
operationChangeEvent.setOperationStatusType(operationStatusType);
operationChangeEvent.setStatusMessage(statusMessage);
operationChangeEvent.setGeneratedSql(sqlArray);
operationChangeEvent.setOperation(operation);
operationChangeEvent.setLogsTimestamp(new Date());
if ("FAIL".equals(operationStatusType)) {
operationChangeEvent.setLogs(statusMessage);
} else {
String logs = getCurrentLog();
if (!StringUtil.isEmpty(logs)) {
operationChangeEvent.setLogs(logs);
} else {
operationChangeEvent.setLogs(statusMessage);
}
}
operationChangeEvent.setProject(hubChangeLog.getProject());
operationChangeEvent.setOperation(operation);
try {
hubService.sendOperationChangeEvent(operationChangeEvent);
postCount++;
} catch (LiquibaseException lbe) {
logger.warning(lbe.getMessage(), lbe);
logger.warning("Unable to send Operation Change Event for operation '" + operation.getId().toString() + " change set '" + changeSet.toString(false));
failedToPostCount++;
}
}
use of liquibase.hub.LiquibaseHubException in project liquibase by liquibase.
the class HttpClient method openConnection.
private URLConnection openConnection(String url) throws LiquibaseHubException {
String apiKey = HubConfiguration.LIQUIBASE_HUB_API_KEY.getCurrentValue();
try {
final URLConnection connection = new URL(getHubUrl() + url).openConnection();
connection.setRequestProperty("User-Agent", "Liquibase " + LiquibaseUtil.getBuildVersion());
if (StringUtil.isNotEmpty(apiKey)) {
connection.setRequestProperty("Authorization", "Bearer " + apiKey);
}
connection.setRequestProperty("Accept", "application/json");
connection.setRequestProperty("Content-Type", "application/json");
return connection;
} catch (IOException e) {
throw new LiquibaseHubException(e);
}
}
use of liquibase.hub.LiquibaseHubException in project liquibase by liquibase.
the class InternalSyncHubCommandStep method run.
@Override
public void run(CommandResultsBuilder resultsBuilder) throws Exception {
CommandScope commandScope = resultsBuilder.getCommandScope();
final HubServiceFactory hubServiceFactory = Scope.getCurrentScope().getSingleton(HubServiceFactory.class);
if (!hubServiceFactory.isOnline()) {
if (commandScope.getArgumentValue(FAIL_IF_OFFLINE_ARG)) {
throw new CommandExecutionException("The command syncHub requires access to Liquibase Hub: " + hubServiceFactory.getOfflineReason() + ". Learn more at https://hub.liquibase.com");
} else {
Scope.getCurrentScope().getUI().sendMessage("Sync skipped, offline");
return;
}
}
//
// Check for both connection and project specified
// unless we have said to favor the connectionID
//
final Boolean favorConnectionId = commandScope.getArgumentValue(CONTINUE_IF_CONNECTION_AND_PROJECT_ID_BOTH_SET_ARG);
final UUID hubConnectionId = commandScope.getArgumentValue(HUB_CONNECTION_ID_ARG);
if (!favorConnectionId && hubConnectionId != null && commandScope.getArgumentValue(HUB_PROJECT_ID_ARG) != null) {
String message = "The syncHub command requires only one valid hubConnectionId or hubProjectId or unique URL. Please remove extra values.";
Scope.getCurrentScope().getLog(getClass()).severe(message);
throw new CommandExecutionException(message);
}
HubChangeLog hubChangeLog = null;
final HubService hubService = Scope.getCurrentScope().getSingleton(HubServiceFactory.class).getService();
Connection connectionToSync;
if (hubConnectionId == null) {
Project project = null;
if (StringUtil.isNotEmpty(commandScope.getArgumentValue(CHANGELOG_FILE_ARG))) {
final ResourceAccessor resourceAccessor = Scope.getCurrentScope().getResourceAccessor();
final String changelogFile = commandScope.getArgumentValue(CHANGELOG_FILE_ARG);
final DatabaseChangeLog databaseChangeLog = ChangeLogParserFactory.getInstance().getParser(changelogFile, resourceAccessor).parse(changelogFile, new ChangeLogParameters(), resourceAccessor);
final String changeLogId = databaseChangeLog.getChangeLogId();
if (changeLogId == null) {
Scope.getCurrentScope().getLog(getClass()).info("Changelog " + changelogFile + " has not been registered with Liquibase Hub. Cannot use it to help determine project.");
} else {
hubChangeLog = hubService.getHubChangeLog(UUID.fromString(changeLogId), "*");
if (hubChangeLog == null) {
throw new CommandExecutionException("Changelog " + changelogFile + " has an unrecognized changeLogId.");
}
if (hubChangeLog.isDeleted()) {
//
// Complain and stop the operation
//
String message = "\n" + "The operation did not complete and will not be reported to Hub because the\n" + "" + "registered changelog has been deleted by someone in your organization.\n" + "Learn more at http://hub.liquibase.com";
throw new LiquibaseHubException(message);
}
project = hubChangeLog.getProject();
}
} else if (commandScope.getArgumentValue(HUB_PROJECT_ID_ARG) != null) {
project = hubService.getProject(commandScope.getArgumentValue(HUB_PROJECT_ID_ARG));
if (project == null) {
throw new CommandExecutionException("Project Id '" + commandScope.getArgumentValue(HUB_PROJECT_ID_ARG) + "' does not exist or you do not have access to it");
}
} else {
Scope.getCurrentScope().getLog(getClass()).info("No project, connection, or changeLogFile specified. Searching for jdbcUrl across the entire organization.");
}
final String url = commandScope.getArgumentValue(URL_ARG);
final Connection searchConnection = new Connection().setJdbcUrl(url).setProject(project);
final List<Connection> connections = hubService.getConnections(searchConnection);
if (connections.size() == 0) {
if (project == null) {
throw new CommandExecutionException("The url " + url + " does not match any defined connections. To auto-create a connection, please specify a 'changeLogFile=<changeLogFileName>' in liquibase.properties or the command line which contains a registered changeLogId.");
}
Connection inputConnection = new Connection();
inputConnection.setJdbcUrl(url);
inputConnection.setProject(project);
connectionToSync = hubService.createConnection(inputConnection);
} else if (connections.size() == 1) {
connectionToSync = connections.get(0);
} else {
throw new CommandExecutionException("The url " + url + " is used by more than one connection. Please specify 'hubConnectionId=<hubConnectionId>' or 'changeLogFile=<changeLogFileName>' in liquibase.properties or the command line.");
}
} else {
final List<Connection> connections = hubService.getConnections(new Connection().setId(hubConnectionId));
if (connections.size() == 0) {
throw new CommandExecutionException("Hub connection Id " + hubConnectionId + " was either not found, or you do not have access");
} else {
connectionToSync = connections.get(0);
}
}
final Database database = commandScope.getArgumentValue(DATABASE_ARG);
Scope.child(Scope.Attr.database, database, () -> {
final ChangeLogHistoryService historyService = ChangeLogHistoryServiceFactory.getInstance().getChangeLogService(database);
final List<RanChangeSet> ranChangeSets = historyService.getRanChangeSets();
hubService.setRanChangeSets(connectionToSync, ranChangeSets);
});
//
if (hubChangeLog != null && hubChangeLog.isInactive()) {
String message = "\n" + "The command completed and reported to Hub, but the changelog has been deactivated by someone in your organization.\n" + "To synchronize your changelog, checkout the latest from source control or run \"deactivatechangelog\".\n" + "After that, commands run against this changelog will not be reported to Hub until \"registerchangelog\" is run again.\n" + "Learn more at http://hub.liquibase.com";
Scope.getCurrentScope().getLog(HubUpdater.class).warning(message);
Scope.getCurrentScope().getUI().sendMessage("WARNING: " + message);
}
}
Aggregations