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
14 changes: 14 additions & 0 deletions astra-db-java/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,20 @@
</systemPropertyVariables>
</configuration>
</plugin>

<!-- Build test-jar for other modules to use test utilities -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,15 @@
*/

import com.datastax.astra.client.admin.commands.AstraAvailableRegionInfo;
import com.datastax.astra.client.admin.definition.DatabaseDefinition;
import com.datastax.astra.client.admin.definition.PCUGroupDefinition;
import com.datastax.astra.client.admin.options.AdminOptions;
import com.datastax.astra.client.admin.options.AstraFindAvailableRegionsOptions;
import com.datastax.astra.client.admin.options.CreateDatabaseOptions;
import com.datastax.astra.client.core.options.DataAPIClientOptions;
import com.datastax.astra.client.databases.definition.DatabaseInfo;
import com.datastax.astra.client.databases.DatabaseOptions;
import com.datastax.astra.client.exceptions.AstraDevOpsAPIException;
import com.datastax.astra.internal.api.AstraApiEndpoint;
import com.datastax.astra.internal.command.LoggingCommandObserver;
import com.datastax.astra.internal.utils.Assert;
Expand All @@ -38,6 +42,8 @@
import com.dtsx.astra.sdk.db.domain.FilterByOrgType;
import com.dtsx.astra.sdk.db.domain.RegionType;
import com.dtsx.astra.sdk.db.exception.DatabaseNotFoundException;
import com.dtsx.astra.sdk.pcu.PCUGroupsOpsClient;
import com.dtsx.astra.sdk.pcu.domain.PCUGroup;
import com.dtsx.astra.sdk.utils.AstraRc;
import com.dtsx.astra.sdk.utils.observability.ApiRequestObserver;
import com.dtsx.astra.sdk.utils.observability.LoggingRequestObserver;
Expand All @@ -46,7 +52,6 @@

import java.net.http.HttpClient;
import java.time.Duration;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -77,6 +82,9 @@ public class AstraDBAdmin {
/** Client for Astra Devops Api. */
final AstraDBOpsClient devopsDbClient;

/** Client for Astra Devops Api PCU. */
final PCUGroupsOpsClient devopsPcuClient;

/** Options to personalized http client other client options. */
final AdminOptions adminOptions;

Expand Down Expand Up @@ -110,14 +118,17 @@ public AstraDBAdmin(AdminOptions options) {
if (dataAPIClientOptions.getObservers() != null) {
Map<String, ApiRequestObserver> devopsObservers = new HashMap<>();
if (dataAPIClientOptions.getObservers().containsKey(LoggingCommandObserver.class.getSimpleName())) {
System.out.println("Logging enabled for AstraDBAdmin operations.");
devopsObservers.put("logging", new LoggingRequestObserver(AstraDBAdmin.class));
}
this.devopsDbClient = new AstraDBOpsClient(options.getToken(),
dataAPIClientOptions.getAstraEnvironment(), devopsObservers);
this.devopsPcuClient = new PCUGroupsOpsClient(options.getToken(),
dataAPIClientOptions.getAstraEnvironment(), devopsObservers);
} else {
this.devopsDbClient = new AstraDBOpsClient(options.getToken(),
dataAPIClientOptions.getAstraEnvironment());
this.devopsPcuClient = new PCUGroupsOpsClient(options.getToken(),
dataAPIClientOptions.getAstraEnvironment());
}

// Local Agent for Resume
Expand Down Expand Up @@ -158,6 +169,85 @@ public List<AstraAvailableRegionInfo> findAvailableRegions(AstraFindAvailableReg
.toList();
}

// --------------------
// -- PCU Support ---
// --------------------

/**
* Lists PCU (Processing Capacity Units) groups filtered by cloudProvider provider and region.
* PCU groups manage compute resources for databases across cloudProvider providers and regions.
*
* @param cloudProvider
* cloudProvider provider to filter by (AWS, GCP, AZURE), or null for all providers
* @param region
* cloudProvider region to filter by (e.g., "us-east-1"), or null for all regions
* @return
* list of PCU groups matching the specified filters
*/
public List<PCUGroupDefinition> listPCUGroups(CloudProviderType cloudProvider, String region) {
List<PCUGroup> pcus = devopsPcuClient.findAll().toList();
// Filter by cloudProvider provider if specified
if (cloudProvider != null) {
pcus = pcus.stream()
.filter(pcu -> cloudProvider.equals(pcu.getCloudProvider()))
.collect(Collectors.toList());
}

// Filter by region if specified
if (region != null && !region.isBlank()) {
pcus = pcus.stream()
.filter(pcu -> region.equals(pcu.getRegion()))
.collect(Collectors.toList());
}
return pcus
.stream()
.map(PCUGroupDefinition::new)
.collect(Collectors.toList());
}

/**
* Lists all PCU (Processing Capacity Units) groups in the organization.
* This is a convenience method that returns all PCU groups without filtering.
*
* @return
* list of all PCU groups
*/
public List<PCUGroupDefinition> listPCUGroups() {
return listPCUGroups(null, null);
}

/**
* Checks if a PCU group exists by its identifier.
* This is a convenience method that checks existence without filtering by cloud or region.
*
* @param PCUGroupId
* PCU group UUID to check
* @return
* true if the PCU group exists, false otherwise
*/
public boolean PCUGroupExists(UUID PCUGroupId) {
return PCUGroupExists(PCUGroupId, null, null);
}

/**
* Checks if a PCU group exists by its identifier, optionally filtered by cloudProvider provider and region.
*
* @param PCUGroupId
* PCU group UUID to check
* @param cloudProvider
* cloudProvider provider to filter by (AWS, GCP, AZURE), or null for all providers
* @param region
* cloudProvider region to filter by (e.g., "us-east-1"), or null for all regions
* @return
* true if the PCU group exists and matches the filters, false otherwise
*/
public boolean PCUGroupExists(UUID PCUGroupId, CloudProviderType cloudProvider, String region) {
Assert.notNull(PCUGroupId, "PCUGroupId");
return listPCUGroups(cloudProvider, region)
.stream()
.anyMatch(pcuGroup -> PCUGroupId.equals(pcuGroup.getId()));
}

// --------------------
// -- Databases ---
// --------------------
Expand Down Expand Up @@ -298,6 +388,32 @@ public DatabaseAdmin createDatabase(String name, CloudProviderType cloud, String
return createDatabase(name, cloud, cloudRegion, true);
}

/**
* Create new database with a name on free tier. The database name should not exist in the tenant.
*
* @param name
* unique name for the database
* @param definition
* definition of the database
* @return
* database admin object
*/
public DatabaseAdmin createDatabase(String name, DatabaseDefinition definition, CreateDatabaseOptions options) {
Assert.notNull(definition, "definition");
Assert.hasLength(name, "name");
DatabaseCreationRequest req = definition.asRequest();
req.setName(name);
if (definition.getPCUGroupId() != null) {
validatePCUGroup(definition);
}
UUID newDbId = UUID.fromString(devopsDbClient.create(req));
log.info("Database {} is starting (id={}): it will take about a minute please wait...", name, newDbId);
if (options != null && options.isWaitForDb()) {
waitForDatabase(devopsDbClient.database(newDbId.toString()));
}
return getDatabaseAdmin(newDbId);
}

/**
* Delete a Database if exists from its identifier.
*
Expand Down Expand Up @@ -436,6 +552,47 @@ public AstraDBDatabaseAdmin getDatabaseAdmin(String databaseEndpoint) {
return getDatabaseAdmin(AstraApiEndpoint.parse(databaseEndpoint).getDatabaseId());
}

/**
* Validates that the PCU group specified in the database definition exists and is in the correct region.
* This method checks both the existence of the PCU group globally and its availability in the
* specified cloud provider and region.
*
* @param definition
* the database definition containing PCU group ID, cloud provider, and region
* @throws AstraDevOpsAPIException
* if the PCU group does not exist or is not in the expected cloud/region
*/
private void validatePCUGroup(DatabaseDefinition definition) {
// Testing PCUGroup in proper region but swallow error if cannot list the PCU groupsInRegion.
List<PCUGroupDefinition> groupsInRegion = null;
List<PCUGroupDefinition> all = null;
try {
all = listPCUGroups();
groupsInRegion = listPCUGroups(definition.getCloudProvider(), definition.getRegion());
} catch (AstraDevOpsAPIException e) {
log.warn("Could not list PCU group - The PCUGroup id will not be tested " + e.getMessage());
}
if (all != null) {
boolean groupExist = all
.stream()
.anyMatch(pcuGroup -> definition.getPCUGroupId().equals(pcuGroup.getId()));
if (!groupExist) {
throw new AstraDevOpsAPIException("Pcu group " + definition.getPCUGroupId() + " does not exist");
}
}
if (groupsInRegion != null) {
boolean groupExist = groupsInRegion
.stream()
.anyMatch(pcuGroup -> definition.getPCUGroupId().equals(pcuGroup.getId()));
if (!groupExist) {
throw new AstraDevOpsAPIException("Pcu group " + definition.getPCUGroupId()
+ " is not in expected cloud/region : "
+ definition.getCloudProvider() + "/"
+ definition.getRegion());
}
}
}

/**
* Wait for db to have proper status.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package com.datastax.astra.client.admin.definition;

/*-
* #%L
* Data API Java Client
* --
* Copyright (C) 2024 - 2026 DataStax
* --
* Licensed under the Apache License, Version 2.0
* 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.
* #L%
*/

import com.dtsx.astra.sdk.db.domain.CloudProviderType;
import com.dtsx.astra.sdk.db.domain.DatabaseCreationBuilder;
import com.dtsx.astra.sdk.db.domain.DatabaseCreationRequest;
import com.dtsx.astra.sdk.db.domain.DatabaseCreationType;
import lombok.Builder;
import lombok.Data;

import java.util.UUID;

@Data
@Builder
public class DatabaseDefinition {

/** Default region. **/
public static final String DEFAULT_REGION = "us-east1";

/** Default tier. **/
public static final String DEFAULT_TIER = "serverless";

/** Default cloud. **/
public static final CloudProviderType DEFAULT_CLOUD = CloudProviderType.GCP;

/** CloudProvider where the database lives. */
private CloudProviderType cloudProvider = DEFAULT_CLOUD;

/** Region. */
private String region = DEFAULT_REGION;

/** Database type. */
private String tier = DEFAULT_TIER;

/** Name of the database--user friendly identifier. */
private String name;

/** Keyspace name in database */
private String keyspace;

/**
* CapacityUnits is the amount of space available (horizontal scaling)
* for the database. For free tier the max CU's is 1, and 100
* for CXX/DXX the max is 12 on startup.
*/
private Integer capacityUnits = 1;

/**
* Default is null, if vector will be added
*/
private DatabaseCreationType dbType;

/**
* Identifier to assign a database to a PCU group directly.
*/
private UUID PCUGroupId;

/**
* Projection as the creation request
*
* @return
* db creation request
*/
public DatabaseCreationRequest asRequest() {
DatabaseCreationBuilder builder = DatabaseCreationRequest.builder();
builder.capacityUnit(capacityUnits);
builder.name(name);
builder.cloudProvider(cloudProvider);
builder.cloudRegion(region);
builder.tier(tier);
builder.keyspace(keyspace);
builder.withVector();
builder.dbType(dbType);
if (PCUGroupId != null) {
builder.assignToPCUGroup(PCUGroupId);
}
return builder.build();
}
}
Loading