Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
package com.dtsx.astra.sdk.db;

import com.dtsx.astra.sdk.AbstractApiClient;
import com.dtsx.astra.sdk.db.domain.Database;
import com.dtsx.astra.sdk.db.domain.DatabaseCloneStatus;
import com.dtsx.astra.sdk.utils.ApiLocator;
import com.dtsx.astra.sdk.utils.ApiResponseHttp;
import com.dtsx.astra.sdk.utils.Assert;
import com.dtsx.astra.sdk.utils.AstraEnvironment;
import com.dtsx.astra.sdk.utils.JsonUtils;

import java.net.HttpURLConnection;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.stream.Stream;

/**
* Delegate operation on DB cloning
*/
public class DbCloneClient extends AbstractApiClient {

/** Clone path component, part I. */
public static final String PATH_CLONE_1 = "/databases/";

/** Clone path component, part II. */
public static final String PATH_CLONE_2 = "/cloneFrom/";

/** Get-clone-status path component, part I. */
public static final String PATH_GETSTATUS_1 = "/databases/";

/** Get-clone-status path component, part II. */
public static final String PATH_GETSTATUS_2 = "/cloneStatus/";

/**
* unique db identifier.
*/
private final Database db;

/**
* As immutable object use builder to initiate the object.
*
* @param token
* authenticated token
* @param databaseId
* database identifier
*/
public DbCloneClient(String token, String databaseId) {
this(token, AstraEnvironment.PROD, databaseId);
}

/**
* As immutable object use builder to initiate the object.
*
* @param env
* define target environment to be used
* @param token
* authenticated token
* @param databaseId
* database identifier
*/
public DbCloneClient(String token, AstraEnvironment env, String databaseId) {
super(token, env);
Assert.hasLength(databaseId, "databaseId");
this.db = new DbOpsClient(token, env, databaseId).get();
}

/** {@inheritDoc} */
@Override
public String getServiceName() {
return "db.clone";
}

/**
* Clone database from a source database using a snapshot.
*
* @param sourceDbId
* ID of the source database
* @param databaseSnapshotId
* ID of the snapshot to clone from
* @return clone status
*/
public DatabaseCloneStatus cloneFrom(String sourceDbId, String databaseSnapshotId) {
return cloneFrom(sourceDbId, databaseSnapshotId, null);
}

/**
* Clone database from a source database using a snapshot.
*
* @param sourceDbId
* ID of the source database
* @param databaseSnapshotId
* ID of the snapshot to clone from
* @param sourceRegion
* Source region (optional)
* @return clone status
*/
public DatabaseCloneStatus cloneFrom(String sourceDbId, String databaseSnapshotId, String sourceRegion) {
Assert.hasLength(sourceDbId, "sourceDbId");
Assert.hasLength(databaseSnapshotId, "databaseSnapshotId");

// Build URL with query parameters
String url = getEndpointCloneFrom(sourceDbId) +
"?snapshotID=" + URLEncoder.encode(databaseSnapshotId, StandardCharsets.UTF_8);

if (sourceRegion != null && !sourceRegion.isEmpty()) {
url += "&sourceRegion=" + URLEncoder.encode(sourceRegion, StandardCharsets.UTF_8);
}

// Fire POST request
ApiResponseHttp res = POST(url, getOperationName("cloneFrom"));

// Parse and return response
return JsonUtils.unmarshallBean(res.getBody(), DatabaseCloneStatus.class);
}

/**
* Get the status of a clone operation.
*
* @param operationId
* ID of the clone operation
* @return clone status
*/
public DatabaseCloneStatus getCloneStatus(String operationId) {
Assert.hasLength(operationId, "operationId");

// Build URL
String url = getEndpointGetCloneStatus(operationId);

// Fire GET request
ApiResponseHttp res = GET(url, getOperationName("getCloneStatus"));

// Parse and return response
return JsonUtils.unmarshallBean(res.getBody(), DatabaseCloneStatus.class);
}

/**
* Endpoint to initiate DB clone
*
* @param sourceDbId
* ID of the source database
* @return request endpoint
*/
private String getEndpointCloneFrom(String sourceDbId) {
return ApiLocator.getApiDevopsEndpoint(environment) + PATH_CLONE_1 + db.getId() + PATH_CLONE_2 + sourceDbId;
}

/**
* Endpoint to retrieve a DB-clone status (by operation ID)
*
* @param operationId
* ID of the clone operation (as obtained e.g. with a cloneFrom previous invocation)
* @return request endpoint
*/
private String getEndpointGetCloneStatus(String operationId) {
return ApiLocator.getApiDevopsEndpoint(environment) + PATH_GETSTATUS_1 + db.getId() + PATH_GETSTATUS_2 + operationId;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,32 @@ public DbPrivateLinksClient privateLink() {
return new DbPrivateLinksClient(token, environment, databaseId);
}

// ---------------------------------
// ---- Clone ----
// ---------------------------------

/**
* Delegate clone operation in a dedicated class
*
* @return clone client
*/
public DbCloneClient clone() {
return new DbCloneClient(token, environment, databaseId);
}

// ---------------------------------
// ---- Snapshots ----
// ---------------------------------

/**
* Delegate snapshots operation in a dedicated class
*
* @return snapshots client
*/
public DbSnapshotsClient snapshots() {
return new DbSnapshotsClient(token, environment, databaseId);
}

// ---------------------------------
// ---- Utilities ----
// ---------------------------------
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
package com.dtsx.astra.sdk.db;

import com.dtsx.astra.sdk.AbstractApiClient;
import com.dtsx.astra.sdk.db.domain.Database;
import com.dtsx.astra.sdk.db.domain.DatabaseSnapshot;
import com.dtsx.astra.sdk.db.domain.DatabaseSnapshotsResponse;
import com.dtsx.astra.sdk.utils.ApiLocator;
import com.dtsx.astra.sdk.utils.ApiResponseHttp;
import com.dtsx.astra.sdk.utils.Assert;
import com.dtsx.astra.sdk.utils.AstraEnvironment;
import com.dtsx.astra.sdk.utils.JsonUtils;

import java.net.HttpURLConnection;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.stream.Stream;

/**
* Delegate operation on snapshots
*/
public class DbSnapshotsClient extends AbstractApiClient {

/** Path for listing snapshots, part I. */
public static final String PATH_SNAPSHOTS_1 = "/databases/";

/** Path for listing snapshots, part II. */
public static final String PATH_SNAPSHOTS_2 = "/snapshots";

/**
* unique db identifier.
*/
private final Database db;

/**
* As immutable object use builder to initiate the object.
*
* @param token
* authenticated token
* @param databaseId
* database identifier
*/
public DbSnapshotsClient(String token, String databaseId) {
this(token, AstraEnvironment.PROD, databaseId);
}

/**
* As immutable object use builder to initiate the object.
*
* @param env
* define target environment to be used
* @param token
* authenticated token
* @param databaseId
* database identifier
*/
public DbSnapshotsClient(String token, AstraEnvironment env, String databaseId) {
super(token, env);
Assert.hasLength(databaseId, "databaseId");
this.db = new DbOpsClient(token, env, databaseId).get();
}

/** {@inheritDoc} */
@Override
public String getServiceName() {
return "db.snapshots";
}

/**
* Get snapshots with filters.
*
* @param from
* start time (ISO 8601 format)
* @param to
* end time (ISO 8601 format)
* @param region
* region name
* @return list of snapshots.
*/
public Stream<DatabaseSnapshot> find(String from, String to, String region) {
// Build URL with query parameters
StringBuilder url = new StringBuilder(getEndpointSnapshots());
boolean hasParams = false;

if (region != null) {
url.append("?sourceRegion=").append(URLEncoder.encode(region, StandardCharsets.UTF_8));
hasParams = true;
}

if (from != null) {
url.append(hasParams ? "&" : "?").append("from=").append(URLEncoder.encode(from, StandardCharsets.UTF_8));
hasParams = true;
}

if (to != null) {
url.append(hasParams ? "&" : "?").append("to=").append(URLEncoder.encode(to, StandardCharsets.UTF_8));
}

// Invoke endpoint
ApiResponseHttp res = GET(url.toString(), getOperationName("find"));

// Handle response
if (HttpURLConnection.HTTP_NOT_FOUND == res.getCode()) {
return Stream.of();
} else {
DatabaseSnapshotsResponse response = JsonUtils.unmarshallBean(res.getBody(), DatabaseSnapshotsResponse.class);
return response.getSnapshots() != null ? response.getSnapshots().stream() : Stream.of();
}
}

/**
* Get all snapshots.
*
* @return list of snapshots.
*/
public Stream<DatabaseSnapshot> findAll() {
return find(null, null, null);
}

// TODO: add other overloads here

/**
* Endpoint to access snapshots of a db
*
* @return database endpoint
*/
private String getEndpointSnapshots() {
return ApiLocator.getApiDevopsEndpoint(environment) + PATH_SNAPSHOTS_1 + db.getId() + PATH_SNAPSHOTS_2;
}

}
Loading