Skip to content

Commit

Permalink
private endpoint services: support all clouds (#189)
Browse files Browse the repository at this point in the history
* private endpoint services: support all clouds

Previously, the private_endpoint_services resource only supported the
creation of AWS private endpoint services. This commit removes this
restriction, now all clouds are supported. Additionally this commit
fixes a bug that caused the private_endpoint_service resource to be
created without the resource state being loaded into the state file.
Lastly, this commit bumps the CRDB version used for testing.

* changelog: update for v1.3.2
  • Loading branch information
carloruiz authored Mar 15, 2024
1 parent 3e7b9af commit f641a7e
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 34 deletions.
18 changes: 12 additions & 6 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Changed

- Migrated the testing framework to
https://github.com/hashicorp/terraform-plugin-testing.

## [1.3.2] - 2024-03-13
## [1.3.2] - 2024-03-15

### Changed

Expand All @@ -21,8 +16,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
except Serverless clusters on Azure as that configuration is not yet
available.

- Migrated the testing framework to
https://github.com/hashicorp/terraform-plugin-testing.

- The `private_endpoint_services` resource can now be used to create private
endpoint services on every supported cloud provider.

- Use CockroachDB v23.1 and v23.2 in tests.

### Fixed

- The `private_endpoint_services` resource could be created without populating
the state file with the service information.

- Renamed example files to the correct name so they are automatically included
in the docs.

Expand Down
9 changes: 6 additions & 3 deletions docs/resources/private_endpoint_services.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
page_title: "cockroach_private_endpoint_services Resource - terraform-provider-cockroach"
subcategory: ""
description: |-
PrivateEndpointServices contains services that allow for VPC communication, either via PrivateLink (AWS) or Peering (GCP).
PrivateEndpointServices contains services that allow for for private connectivity to the CockroachDB Cloud cluster.
---

# cockroach_private_endpoint_services (Resource)

PrivateEndpointServices contains services that allow for VPC communication, either via PrivateLink (AWS) or Peering (GCP).
PrivateEndpointServices contains services that allow for for private connectivity to the CockroachDB Cloud cluster.

## Example Usage

Expand Down Expand Up @@ -39,8 +39,11 @@ resource "cockroach_private_endpoint_services" "cockroach" {

Read-Only:

- `aws` (Attributes) (see [below for nested schema](#nestedatt--services--aws))
- `availability_zone_ids` (List of String) AZ IDs users should create their VPCs in to minimize their cost.
- `aws` (Attributes, Deprecated) (see [below for nested schema](#nestedatt--services--aws))
- `cloud_provider` (String) Cloud provider associated with this service.
- `endpoint_service_id` (String) Server side ID of the private endpoint connection.
- `name` (String) Name of the endpoint service.
- `region_name` (String) Cloud provider region code associated with this service.
- `status` (String) Operation status of the service.

Expand Down
8 changes: 4 additions & 4 deletions internal/provider/cluster_resource_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,10 @@ const (
// The patch versions are just for mocks. They don't need to be the actual
// latest available patch versions; they just need to resolve to the correct
// major versions.
minSupportedClusterMajorVersion = "v22.2"
minSupportedClusterPatchVersion = "v22.2.0"
latestClusterMajorVersion = "v23.1"
latestClusterPatchVersion = "v23.1.0"
minSupportedClusterMajorVersion = "v23.1"
minSupportedClusterPatchVersion = "v23.1.0"
latestClusterMajorVersion = "v23.2"
latestClusterPatchVersion = "v23.2.0"
)

// TestAccClusterResource attempts to create, check, update, and destroy
Expand Down
11 changes: 7 additions & 4 deletions internal/provider/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,13 @@ type PrivateLinkServiceAWSDetail struct {
}

type PrivateEndpointService struct {
RegionName types.String `tfsdk:"region_name"`
CloudProvider types.String `tfsdk:"cloud_provider"`
Status types.String `tfsdk:"status"`
Aws PrivateLinkServiceAWSDetail `tfsdk:"aws"`
RegionName types.String `tfsdk:"region_name"`
CloudProvider types.String `tfsdk:"cloud_provider"`
Status types.String `tfsdk:"status"`
Name types.String `tfsdk:"name"`
EndpointServiceId types.String `tfsdk:"endpoint_service_id"`
AvailabilityZoneIds []types.String `tfsdk:"availability_zone_ids"`
Aws PrivateLinkServiceAWSDetail `tfsdk:"aws"`
}

type PrivateEndpointServices struct {
Expand Down
52 changes: 35 additions & 17 deletions internal/provider/private_endpoint_services_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ type privateEndpointServicesResource struct {
const endpointServicesCreateTimeout = time.Hour

var endpointServicesSchema = schema.Schema{
MarkdownDescription: "PrivateEndpointServices contains services that allow for VPC communication, either via PrivateLink (AWS) or Peering (GCP).",
MarkdownDescription: "PrivateEndpointServices contains services that allow for private connectivity to the CockroachDB Cloud cluster.",
Attributes: map[string]schema.Attribute{
"cluster_id": schema.StringAttribute{
Required: true,
Expand Down Expand Up @@ -76,8 +76,22 @@ var endpointServicesSchema = schema.Schema{
Computed: true,
Description: "Operation status of the service.",
},
"name": schema.StringAttribute{
Computed: true,
Description: "Name of the endpoint service.",
},
"endpoint_service_id": schema.StringAttribute{
Computed: true,
Description: "Server side ID of the private endpoint connection.",
},
"availability_zone_ids": schema.ListAttribute{
Computed: true,
ElementType: types.StringType,
MarkdownDescription: "Availability Zone IDs of the private endpoint service. It is recommended, for cost optimization purposes, to create the private endpoint spanning these same availability zones. For more information, see data transfer cost information for your cloud provider.",
},
"aws": schema.SingleNestedAttribute{
Computed: true,
DeprecationMessage: "nested aws fields have been moved one level up. These fields will be removed in a future version",
Computed: true,
PlanModifiers: []planmodifier.Object{
objectplanmodifier.UseStateForUnknown(),
},
Expand Down Expand Up @@ -152,14 +166,6 @@ func (r *privateEndpointServicesResource) Create(
return
}

if cluster.CloudProvider != client.CLOUDPROVIDERTYPE_AWS {
resp.Diagnostics.AddError(
"Incompatible cluster cloud provider",
"Private endpoint services are currently only available for AWS clusters",
)
return
}

// Only create an endpoint service if it is a dedicated cluster. Serverless
// clusters have endpoint services by default, and will error out if the
// Create API is called.
Expand Down Expand Up @@ -236,19 +242,26 @@ func loadEndpointServicesIntoTerraformState(
services := make([]PrivateEndpointService, len(serviceList))
for i, service := range serviceList {
services[i] = PrivateEndpointService{
RegionName: types.StringValue(service.GetRegionName()),
CloudProvider: types.StringValue(string(service.GetCloudProvider())),
Status: types.StringValue(string(service.GetStatus())),
Aws: PrivateLinkServiceAWSDetail{
RegionName: types.StringValue(service.GetRegionName()),
CloudProvider: types.StringValue(string(service.GetCloudProvider())),
Status: types.StringValue(string(service.GetStatus())),
Name: types.StringValue(service.GetName()),
EndpointServiceId: types.StringValue(service.GetEndpointServiceId()),
}

if services[i].CloudProvider.String() == "AWS" {
services[i].Aws = PrivateLinkServiceAWSDetail{
ServiceName: types.StringValue(service.Aws.GetServiceName()),
ServiceId: types.StringValue(service.Aws.GetServiceId()),
},
}
}
apiAZs := service.Aws.GetAvailabilityZoneIds()

apiAZs := service.GetAvailabilityZoneIds()
azs := make([]types.String, len(apiAZs))
for j, az := range apiAZs {
azs[j] = types.StringValue(az)
}
services[i].AvailabilityZoneIds = azs
services[i].Aws.AvailabilityZoneIds = azs
}
var diags diag.Diagnostics
Expand Down Expand Up @@ -299,9 +312,14 @@ func waitForEndpointServicesCreatedFunc(
if httpResp != nil && httpResp.StatusCode < http.StatusInternalServerError {
return retry.NonRetryableError(fmt.Errorf("error getting endpoint services: %s", formatAPIErrorMessage(err)))
} else {
return retry.RetryableError(fmt.Errorf("encountered a server error while reading endpoint status - trying again"))
return retry.RetryableError(fmt.Errorf("encountered a server error while reading endpoint status - trying again: %v", err))
}
}

if len(apiServices.Services) == 0 {
return retry.RetryableError(fmt.Errorf("private endpoint services not yet created"))
}

*services = *apiServices
var creating bool
// If there's at least one still creating, keep checking.
Expand Down

0 comments on commit f641a7e

Please sign in to comment.