Skip to content

Implement deletion protection #40

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 22 commits into from
Jul 30, 2024
Merged

Implement deletion protection #40

merged 22 commits into from
Jul 30, 2024

Conversation

ericapywang
Copy link
Contributor

Problem

Deletion protection was not implemented.

Solution

We updated the OpenAPI code to include deletion protection. This changed the parameters for several structs and functions, so all this code was updated to reflect the changes.

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update
  • Infrastructure change (CI configs, etc)
  • Non-code change (docs, etc)
  • None of the above: (explain here)

Test Plan

Test cases should still pass.

@ericapywang ericapywang marked this pull request as ready for review July 26, 2024 13:20
/// It applies to pod-based indexes only.
/// Serverless indexes scale automatically based on usage.
/// This operation changes the deletion protection specification, the pod type, and the number of replicas for an index.
/// Deletion protection can be changed for both pod and serverless indexes, while pod types and number of replicas can only be changed for pod indexes.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if it would be easier to use if we split this into pod and serverless versions?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good thought. We didn't take this approach for configure_index in any of the other clients, but we did split the create function into separate functions for pod / serverless in Go and Java, and you all did the same in Rust.

I think leaving it as a single function is probably fine for now, and aligns with the other SDKs. If later on we decide to expose more specific configure functions in any of these clients, those could be added additively while maintaining these original base functions.

@@ -901,6 +925,7 @@ mod tests {
state: openapi::models::index_model_status::State::Ready,
}),
host: "mock-host".to_string(),
deletion_protection: None,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does deletion_protection None mean? Would it be confusing to pass DeletionProtection to other functions and then get Option<DeletionProtection> in the returned IndexModel?

Copy link
Contributor Author

@ericapywang ericapywang Jul 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I may be wrong, but I think this is because the describe_index endpoint doesn't return a deletion_protection field in its response, so IndexModel will not always include it. I agree that it's confusing though, but I'm not too sure how to get around it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

describe_index should be returning deletion_protection, are you passing the X-Pinecone-Api-Version header with 2024-07?

Here's an example of curl'ing with the header:

curl -X GET https://api.pinecone.io/indexes/test-configure-index -H "Api-Key: b56c33c1-ba11-4f93-9333-4235ffdaac43" --header "X-Pinecone-Api-Version: 2024-07"

{"name":"test-configure-index","metric":"cosine","dimension":3,"status":{"ready":true,"state":"Ready"},"host":"test-configure-index-1390950.svc.apw5-4e34-81fa.pinecone.io","spec":{"serverless":{"region":"us-west-2","cloud":"aws"}},"deletion_protection":"enabled"}%    

If the header isn't provided, the deletion_protection field is not returned. I believe it's actually marked as an optional field in the OpenAPI spec though, so I think None would be synonymous with "disabled".

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense! I just copied it from the API docs, which didn't seem to include a deletion_protection field

Copy link
Contributor

@austin-denoble austin-denoble left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall looking good. I had some feedback around making deletion_protection an Option in most cases. Primarily, because it's not represented as required in the OpenAPI spec, and we treat it as optional in the other clients generally when creating indexes or configuring them. It may be nice to take the same approach here if possible.

I saw you also mentioned not seeing deletion_protection in describe_index responses - I'd make sure the X-Pinecone-Api-Version header is being properly set for outgoing requests, that's most likely why.

/// It applies to pod-based indexes only.
/// Serverless indexes scale automatically based on usage.
/// This operation changes the deletion protection specification, the pod type, and the number of replicas for an index.
/// Deletion protection can be changed for both pod and serverless indexes, while pod types and number of replicas can only be changed for pod indexes.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good thought. We didn't take this approach for configure_index in any of the other clients, but we did split the create function into separate functions for pod / serverless in Go and Java, and you all did the same in Rust.

I think leaving it as a single function is probably fine for now, and aligns with the other SDKs. If later on we decide to expose more specific configure functions in any of these clients, those could be added additively while maintaining these original base functions.

/// # Ok(())
/// # }
/// ```
pub async fn configure_index(
&self,
name: &str,
replicas: i32,
pod_type: &str,
deletion_protection: DeletionProtection,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually think deletion_protection should also be an option here: Option<DeletionProtection>.

If you don't send the value along with the API request, the server will ignore changing it which is the behavior I think we'd expect here. We probably don't want users that are configuring a pod index to need to know which DeletionProtection value the index was configured with in order to make this request.

In the Go client I went with making all 3 of the fields optional, but I do a small amount of client-side validation to make sure the user supplied at least one argument: https://github.com/pinecone-io/go-pinecone/blob/main/pinecone/client.go#L854-L857

@@ -901,6 +925,7 @@ mod tests {
state: openapi::models::index_model_status::State::Ready,
}),
host: "mock-host".to_string(),
deletion_protection: None,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

describe_index should be returning deletion_protection, are you passing the X-Pinecone-Api-Version header with 2024-07?

Here's an example of curl'ing with the header:

curl -X GET https://api.pinecone.io/indexes/test-configure-index -H "Api-Key: b56c33c1-ba11-4f93-9333-4235ffdaac43" --header "X-Pinecone-Api-Version: 2024-07"

{"name":"test-configure-index","metric":"cosine","dimension":3,"status":{"ready":true,"state":"Ready"},"host":"test-configure-index-1390950.svc.apw5-4e34-81fa.pinecone.io","spec":{"serverless":{"region":"us-west-2","cloud":"aws"}},"deletion_protection":"enabled"}%    

If the header isn't provided, the deletion_protection field is not returned. I believe it's actually marked as an optional field in the OpenAPI spec though, so I think None would be synonymous with "disabled".

@@ -72,6 +74,7 @@ impl PineconeClient {
metric: Metric,
cloud: Cloud,
region: &str,
deletion_protection: DeletionProtection,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense to make this an Option? If it's not provided, it defaults to disabled, but I'm not sure what makes idiomatic sense for Rust here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm inclined to leave it as not an Option, since the DeletionProtection enum implements the Default trait, so the user can just call Default::default() to have it default to disabled. Would love to hear other thoughts though!

.await
.expect("Failed to configure index");

Ok(())
}

#[tokio::test]
async fn test_configure_deletion_protection() -> Result<(), PineconeError> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice test coverage. 👍

If you end up making deletion_protection an Option on configure_index, you may also want to write a test to validate the scenario where you have an index with deletion_protection: "enabled", and you send a configure_index request to configure something other than the deletion_protection value, we want to make sure it's maintained.

Jen had run into an issue where the Python client was defaulting the outgoing deletion_protection value to disabled for configure_index requests where it wasn't explicitly set by the user.

@emily-emily emily-emily force-pushed the emily/regenerate-code branch from f5bf76a to 64a8b9e Compare July 29, 2024 18:17
Copy link
Contributor

@austin-denoble austin-denoble left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, thanks for iterating!

@ericapywang ericapywang merged commit b791291 into main Jul 30, 2024
1 check passed
@ericapywang ericapywang deleted the emily/regenerate-code branch July 30, 2024 14:20
ericapywang added a commit that referenced this pull request Jul 30, 2024
## Problem

Deletion protection was not implemented.

## Solution

We updated the OpenAPI code to include deletion protection. This changed
the parameters for several structs and functions, so all this code was
updated to reflect the changes.

## Type of Change

- [ ] Bug fix (non-breaking change which fixes an issue)
- [x] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality to not work as expected)
- [ ] This change requires a documentation update
- [ ] Infrastructure change (CI configs, etc)
- [ ] Non-code change (docs, etc)
- [ ] None of the above: (explain here)

## Test Plan

Test cases should still pass.

---------

Co-authored-by: Emily Yu <emily.y@pinecone.io>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants