Skip to content

Commit

Permalink
Add support for deletion protection (#141)
Browse files Browse the repository at this point in the history
## Problem

Add support for deletion protection.

## Solution

Generated code using the following commands: 
```
git submodule init && git submodule update
./codegen/build-oas.sh 2024-07
```
Next, as a part of this PR, I have: 
1. Added deletionProtection enum as an argument to createPodsIndex() and
createServerlessIndex()
2. Renamed configureIndex() to configurePodsIndex() and added
deletionProtection enum as an argument.
3. Added configureServerlessIndex() that accepts deletionProtection enum
only.


## Type of Change

- [X] New feature (non-breaking change which adds functionality)

## Test Plan

Added integration tests
  • Loading branch information
rohanshah18 authored Jul 17, 2024
1 parent 3411d21 commit 2ce9ac5
Show file tree
Hide file tree
Showing 42 changed files with 539 additions and 192 deletions.
2 changes: 1 addition & 1 deletion codegen/apis
Submodule apis updated from fbd9d8 to 3e5739
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ public String getOrCreateServerlessIndex() throws InterruptedException, Pinecone
String indexName = RandomStringBuilder.build("serverless-index", 8);

serverlessIndexModel = pineconeClient.createServerlessIndex(indexName, metric, dimension, cloud,
region);
region, DeletionProtection.DISABLED);
waitUntilIndexIsReady(pineconeClient, indexName);

// Explicitly wait after ready to avoid the "no healthy upstream" issue
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.openapitools.control.client.model.DeletionProtection;
import org.openapitools.control.client.model.IndexModel;
import org.openapitools.control.client.model.IndexModelStatus;
import org.openapitools.control.client.model.PodSpec;
Expand Down Expand Up @@ -55,7 +56,7 @@ public void afterEach() throws InterruptedException {
@Test
public void configureIndexWithInvalidIndexName() {
try {
controlPlaneClient.configureIndex("non-existent-index", 3);
controlPlaneClient.configurePodsIndex("non-existent-index", 3, DeletionProtection.DISABLED);

fail("Expected to throw PineconeNotFoundException");
} catch (PineconeNotFoundException expected) {
Expand All @@ -66,7 +67,7 @@ public void configureIndexWithInvalidIndexName() {
@Test
public void configureIndexExceedingQuota() {
try {
controlPlaneClient.configureIndex(indexName, 600);
controlPlaneClient.configurePodsIndex(indexName, 30, DeletionProtection.DISABLED);
fail("Expected to throw PineconeForbiddenException");
} catch (PineconeForbiddenException expected) {
assertTrue(expected.getLocalizedMessage().contains("reached the max pods allowed"));
Expand All @@ -81,7 +82,7 @@ public void scaleUpAndDown() throws InterruptedException {

// Verify the scaled up replicas
assertWithRetry(() -> {
controlPlaneClient.configureIndex(indexName, 3);
controlPlaneClient.configurePodsIndex(indexName, 3, DeletionProtection.DISABLED);
PodSpec podSpec = controlPlaneClient.describeIndex(indexName).getSpec().getPod();
assertNotNull(podSpec);
assertEquals(podSpec.getReplicas(), 3);
Expand All @@ -91,7 +92,7 @@ public void scaleUpAndDown() throws InterruptedException {

// Verify replicas were scaled down
assertWithRetry(() -> {
controlPlaneClient.configureIndex(indexName, 1);
controlPlaneClient.configurePodsIndex(indexName, 1, DeletionProtection.DISABLED);
PodSpec podSpec = controlPlaneClient.describeIndex(indexName).getSpec().getPod();
assertNotNull(podSpec);
assertEquals(podSpec.getReplicas(), 1);
Expand All @@ -107,7 +108,7 @@ public void changingBasePodType() throws InterruptedException {
assertEquals(1, indexModel.getSpec().getPod().getReplicas());

// Try to change the base pod type
controlPlaneClient.configureIndex(indexName, "p2.x2");
controlPlaneClient.configurePodsIndex(indexName, "p2.x2");

fail("Expected to throw PineconeBadRequestException");
} catch (PineconeBadRequestException expected) {
Expand All @@ -125,7 +126,7 @@ public void sizeIncrease() throws InterruptedException {
// Change the pod type to a larger one
// Get the index description to verify the new pod type
assertWithRetry(() -> {
controlPlaneClient.configureIndex(indexName, "p1.x2");
controlPlaneClient.configurePodsIndex(indexName, "p1.x2");
PodSpec podSpec = controlPlaneClient.describeIndex(indexName).getSpec().getPod();
assertNotNull(podSpec);
assertEquals(podSpec.getPodType(), "p1.x2");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package io.pinecone.integration.controlPlane.pod;

import io.pinecone.clients.Pinecone;
import io.pinecone.helpers.RandomStringBuilder;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.openapitools.control.client.model.DeletionProtection;
import org.openapitools.control.client.model.IndexModel;

public class DeletionProtectionTest {
private static final Pinecone controlPlaneClient = new Pinecone
.Builder(System.getenv("PINECONE_API_KEY"))
.withSourceTag("pinecone_test")
.build();

@Test
public void createPodIndexWithDeletionProtectionEnabled() {
String indexName = RandomStringBuilder.build("create-pod", 8);
// Create pod index with deletion protection enabled
controlPlaneClient.createPodsIndex(indexName, 3, "us-east-1-aws", "p1.x1", DeletionProtection.ENABLED);
IndexModel indexModel = controlPlaneClient.describeIndex(indexName);
DeletionProtection deletionProtection = indexModel.getDeletionProtection();
Assertions.assertEquals(deletionProtection, DeletionProtection.ENABLED);
// Configure index to disable deletionProtection
controlPlaneClient.configurePodsIndex(indexName, DeletionProtection.DISABLED);
// Delete index
controlPlaneClient.deleteIndex(indexName);
}

@Test
public void createPodIndexWithDeletionProtectionDisabled() {
String indexName = RandomStringBuilder.build("create-pod", 8);
// Create pod index with deletion protection disabled
controlPlaneClient.createPodsIndex(indexName, 3, "us-east-1-aws", "p1.x1");
IndexModel indexModel = controlPlaneClient.describeIndex(indexName);
DeletionProtection deletionProtection = indexModel.getDeletionProtection();
Assertions.assertEquals(deletionProtection, DeletionProtection.DISABLED);
// Configure index to enable deletionProtection
controlPlaneClient.configurePodsIndex(indexName, DeletionProtection.ENABLED);
indexModel = controlPlaneClient.describeIndex(indexName);
deletionProtection = indexModel.getDeletionProtection();
Assertions.assertEquals(deletionProtection, DeletionProtection.ENABLED);
// Configure index to disable deletionProtection
controlPlaneClient.configurePodsIndex(indexName, DeletionProtection.DISABLED);
// Delete index
controlPlaneClient.deleteIndex(indexName);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public void describeAndListIndex() {
@Test
public void createServerlessIndexWithInvalidName() {
try {
controlPlaneClient.createServerlessIndex("Invalid-name", "cosine", 3, "aws", "us-west-2");
controlPlaneClient.createServerlessIndex("Invalid-name", "cosine", 3, "aws", "us-west-2", DeletionProtection.DISABLED);

fail("Expected to throw PineconeBadRequestException");
} catch (PineconeBadRequestException expected) {
Expand All @@ -59,7 +59,7 @@ public void createServerlessIndexWithInvalidName() {
@Test
public void createServerlessIndexWithInvalidDimension() {
try {
controlPlaneClient.createServerlessIndex("serverless-test-index", "cosine", -3, "aws", "us-west-2");
controlPlaneClient.createServerlessIndex("serverless-test-index", "cosine", -3, "aws", "us-west-2", DeletionProtection.DISABLED);
fail("Expected to throw PineconeValidationException");
} catch (PineconeValidationException expected) {
assertTrue(expected.getLocalizedMessage().contains("Dimension must be greater than 0"));
Expand All @@ -69,7 +69,7 @@ public void createServerlessIndexWithInvalidDimension() {
@Test
public void createServerlessIndexWithInvalidCloud() {
try {
controlPlaneClient.createServerlessIndex("serverless-test-index", "cosine", 3, "blah", "us-west-2");
controlPlaneClient.createServerlessIndex("serverless-test-index", "cosine", 3, "blah", "us-west-2", DeletionProtection.DISABLED);
fail("Expected to throw PineconeValidationException");
} catch (PineconeValidationException expected) {
assertTrue(expected.getLocalizedMessage().contains("Cloud cannot be null or empty. Must be one of " + Arrays.toString(ServerlessSpec.CloudEnum.values())));
Expand All @@ -79,7 +79,7 @@ public void createServerlessIndexWithInvalidCloud() {
@Test
public void createServerlessIndexWithInvalidRegion() {
try {
controlPlaneClient.createServerlessIndex("serverless-test-index", "cosine", 3, "aws", "invalid-region");
controlPlaneClient.createServerlessIndex("serverless-test-index", "cosine", 3, "aws", "invalid-region", DeletionProtection.DISABLED);
fail("Expected to throw PineconeNotFoundException");
} catch (PineconeNotFoundException expected) {
assertTrue(expected.getLocalizedMessage().contains("Resource cloud: aws region: invalid-region not found"));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package io.pinecone.integration.controlPlane.serverless;

import io.pinecone.clients.Pinecone;
import io.pinecone.helpers.RandomStringBuilder;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.openapitools.control.client.model.DeletionProtection;
import org.openapitools.control.client.model.IndexModel;

public class DeletionProtectionTest {
private static final Pinecone controlPlaneClient = new Pinecone
.Builder(System.getenv("PINECONE_API_KEY"))
.withSourceTag("pinecone_test")
.build();

@Test
public void createIndexWithDeletionProtectionEnabled() {
String indexName = RandomStringBuilder.build("create-serv", 8);
// Create serverless index with deletion protection enabled
controlPlaneClient.createServerlessIndex(indexName, "cosine", 3, "aws", "us-west-2", DeletionProtection.ENABLED);
// Describe index to verify deletion protection is enabled
IndexModel indexModel = controlPlaneClient.describeIndex(indexName);
DeletionProtection deletionProtection = indexModel.getDeletionProtection();
Assertions.assertEquals(deletionProtection, DeletionProtection.ENABLED);
}

@Test
public void createPodIndexWithDeletionProtectionDisabled() {
String indexName = RandomStringBuilder.build("create-pod", 8);
// Create serverless index with deletion protection disabled
controlPlaneClient.createServerlessIndex(indexName, "cosine", 3, "aws", "us-west-2", DeletionProtection.DISABLED);
IndexModel indexModel = controlPlaneClient.describeIndex(indexName);
DeletionProtection deletionProtection = indexModel.getDeletionProtection();
Assertions.assertEquals(deletionProtection, DeletionProtection.DISABLED);
// Configure index to enable deletionProtection
controlPlaneClient.configureServerlessIndex(indexName, DeletionProtection.ENABLED);
indexModel = controlPlaneClient.describeIndex(indexName);
deletionProtection = indexModel.getDeletionProtection();
Assertions.assertEquals(deletionProtection, DeletionProtection.ENABLED);
// Configure index to disable deletionProtection
controlPlaneClient.configureServerlessIndex(indexName, DeletionProtection.DISABLED);
// Delete index
controlPlaneClient.deleteIndex(indexName);
}
}
Loading

0 comments on commit 2ce9ac5

Please sign in to comment.