Add aws_opensearchserverless_collection_group resource - #2160
Conversation
|
/test-examples="examples/opensearchserverless/cluster/v1beta1/collectiongroup.yaml" |
|
@fed-sv thanks for the contribution! Could you rebase your PR to the latest main ? Looks like there are conflicts and I am unable rebase (possibly due to your fork's permissions)
That should be fixed in the latest main after #2151 . If interested, you can also verify that. |
fe9930b to
6bfccdd
Compare
|
@erhancagirici rebased on latest main, thanks |
|
/test-examples="examples/opensearchserverless/cluster/v1beta1/collectiongroup.yaml" |
|
Hi @fed-sv E2E tests are failing due to resource misconfiguration, could you please update the example manifests? Current state: apiVersion: opensearchserverless.aws.upbound.io/v1beta1
kind: CollectionGroup
metadata:
annotations:
crossplane.io/external-create-failed: "2026-07-30T06:07:56Z"
crossplane.io/external-create-pending: "2026-07-30T06:07:56Z"
crossplane.io/external-create-succeeded: "2026-07-30T05:48:50Z"
crossplane.io/external-name: stubcollectiongroup99
meta.upbound.io/example-id: opensearchserverless/v1beta1/collectiongroup
upjet.upbound.io/test: "true"
creationTimestamp: "2026-07-30T05:48:49Z"
finalizers:
- finalizer.managedresource.crossplane.io
generation: 2
labels:
testing.upbound.io/example-name: example
name: example
resourceVersion: "4220"
uid: 6e415168-04b9-498a-a353-a3d226c86ea8
spec:
deletionPolicy: Delete
forProvider:
capacityLimits:
- maxIndexingCapacityInOcu: 10
maxSearchCapacityInOcu: 10
minIndexingCapacityInOcu: 0
minSearchCapacityInOcu: 0
description: Scale-to-zero collection group
generation: NEXTGEN
name: example-group
region: us-west-1
standbyReplicas: ENABLED
tags:
crossplane-kind: collectiongroup.opensearchserverless.aws.upbound.io
crossplane-name: example
crossplane-providerconfig: default
initProvider: {}
managementPolicies:
- '*'
providerConfigRef:
name: default
status:
atProvider: {}
conditions:
- lastTransitionTime: "2026-07-30T05:48:50Z"
observedGeneration: 2
reason: Creating
status: "False"
type: Ready
- lastTransitionTime: "2026-07-30T05:49:22Z"
message: |
create failed: async create failed: resource creation call returned error diags: creating OpenSearch Serverless Collection Group: ID: "example-group"
Cause: operation error OpenSearchServerless: CreateCollectionGroup, , ValidationException: Invalid value for maxIndexingCapacityInOCU. Allowed values are: 0, 2, 4, 8, 16, or any multiple of 16"
observedGeneration: 2
reason: ReconcileError
status: "False"
type: Synced
- lastTransitionTime: "2026-07-30T05:48:50Z"
message: |
async create failed: resource creation call returned error diags: creating OpenSearch Serverless Collection Group: ID: "example-group"
Cause: operation error OpenSearchServerless: CreateCollectionGroup, , ValidationException: Invalid value for maxIndexingCapacityInOCU. Allowed values are: 0, 2, 4, 8, 16, or any multiple of 16"
reason: AsyncCreateFailure
status: "False"
type: LastAsyncOperation |
|
@jonasz-lasut my bad, fixed |
|
/test-examples="examples/opensearchserverless/cluster/v1beta1/collectiongroup.yaml" |
There was a problem hiding this comment.
Sorry for the late change request but I've just went through terraform provider code and found add that there's a missing singleton conversion.
Please add the following resource configuration in config.go for both cluster and namespaced resource:
p.AddResourceConfigurator("aws_opensearchserverless_collection_group", func(r *config.Resource) {
r.AddSingletonListConversion("capacity_limits", "capacityLimits")
})capacity_limits is a framework.ResourceOptionalComputedListOfObjectsAttribute[capacityLimitsModel](ctx, 1, ...) in the Terraform fork, and since framework attribute size validators never surface as max_items in config/schema.json upjet does not pick it up on its own. We need to enforce the singleton conversion via config.
Examples would need an update as well.
Other than that LGTM
| name: example | ||
| spec: | ||
| forProvider: | ||
| capacityLimits: |
There was a problem hiding this comment.
Please update to object
| namespace: upbound-system | ||
| spec: | ||
| forProvider: | ||
| capacityLimits: |
There was a problem hiding this comment.
Please update to object
Signed-off-by: Federico <github-fed-sv.unrigged670@passmail.com>
Signed-off-by: Federico <github-fed-sv.unrigged670@passmail.com>
Signed-off-by: Federico <github-fed-sv.unrigged670@passmail.com>
Signed-off-by: Federico <github-fed-sv.unrigged670@passmail.com>
Signed-off-by: Federico <github-fed-sv.unrigged670@passmail.com>
c9a9560 to
a045e0b
Compare
|
@jonasz-lasut no worries, that's done, also rebased on latest |
|
/test-examples="examples/opensearchserverless/cluster/v1beta1/collectiongroup.yaml" |
jonasz-lasut
left a comment
There was a problem hiding this comment.
Thank you for your contribution @fed-sv ! LGTM
Description of your changes
Adds support for the
aws_opensearchserverless_collection_groupresource,which is available in the pinned Terraform provider (v6.53.0) but was not yet
registered.
Collection groups carry the capacity limits (min/max indexing and search
OCUs) and the
generationsetting (CLASSIC/NEXTGEN) for OpenSearchServerless; NextGen groups with a minimum capacity of 0 OCU are the mechanism
for OpenSearch Serverless scale-to-zero. Registering the resource also causes
the existing
Collectionresource to pick up generated cross-resourcereferences for its
collectionGroupNamefield(
collectionGroupNameRef/collectionGroupNameSelector), since the referencedkind now exists.
Configuration notes:
name config is registered in
TerraformPluginFrameworkExternalNameConfigs.name config mirrors the existing
aws_opensearchserverless_collectionone (
IdentifierFromProviderwith a stub id while the external name isunset).
capacity_limitsis a max-1 listattribute in the Framework schema (not a block), so it generates as a
list; this matches what
make generateproduces without overrides.One behavior reviewers may want to weigh in on: this resource has a
Terraform resource identity (
RegionalSingleParameterIdentity), and when acreate fails (e.g. a capacity-limit validation error from AWS), the stub
external name persists on the managed resource while the stored identity has
a null id. Every subsequent observe then fails with "Unexpected Identity
Change", which also blocks deletion; the MR can only be removed by dropping
its finalizer. The same pattern exists in the already-registered
aws_opensearchserverless_collection(and presumably otherIdentifierFromProvider Framework resources with identities), so this PR
follows the established convention rather than diverging, but a general fix
for the failed-create path may be worth tracking separately.
I have:
make generateand committed the results (ideally in a separate commit).make check-diff.How has this code been tested
Beyond
make generatefrom a clean tree (go buildandgo test ./config/...pass), we built the opensearchserverless familypackage from this branch and ran it on an EKS cluster (Crossplane 2.3,
namespaced
.m.APIs, PodIdentity credentials) against a real AWS account:CollectionGroupwithgeneration: NEXTGEN,standbyReplicas: ENABLEDand capacity limits min 0 / max 16 OCU: thegroup became ACTIVE and the AWS-assigned id was observed as the external
name.
CollectionwithcollectionGroupNamepointing at the group:it joined the group and became ACTIVE; scale-to-zero behavior was
confirmed end-to-end through the collection's data plane (idle to 0 OCU
after ~10 minutes, ~10-20s wake on the next request).
updated without replacement, keeping the same id.
cleanly afterwards.
in {0, 2, 4, 8, 16, multiples of 16} return the service's
ValidationException on create).
Example manifests are provided for both cluster and namespaced APIs with a
NextGen scale-to-zero configuration, suitable for
/test-examples="examples/opensearchserverless/cluster/v1beta1/collectiongroup.yaml".