Repository navigation
audit(aws): surface OpenSearch RI tag-failure for ops monitoring (closes #250) #831
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
Changes from all commits
1fcec6c
12f908a
7ec6946
c329276
31d0fbd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,77 @@ | ||
| # Runbook: OpenSearch RI purchased but not tagged | ||
|
|
||
| ## Alert | ||
|
|
||
| Log pattern (grep / CloudWatch Logs Insights): | ||
|
|
||
| ```text | ||
| OPENSEARCH_TAG_FAILED commitment_id=<id> error=<msg> | ||
| ``` | ||
|
|
||
| Emitted by `providers/aws/services/opensearch/client.go` when | ||
| `opensearch:AddTags` fails after a successful RI purchase. The RI is active; | ||
| only the CUDly source tag is absent. | ||
|
Comment on lines
+11
to
+13
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win Describe all tags affected by the failed request. Lines 11-13 claim only the CUDly source tag is absent, but Also applies to: 45-59 🤖 Prompt for AI Agents |
||
|
|
||
| ## Background | ||
|
|
||
| AWS's `PurchaseReservedInstanceOffering` API has no inline `Tags` field. | ||
| CUDly attempts a best-effort `AddTags` call after purchase using a | ||
| constructed ARN of the form: | ||
|
|
||
| ```text | ||
| arn:aws:es:<region>:<account>:reserved-instance/<uuid> | ||
| ``` | ||
|
|
||
| AWS has not officially documented `reserved-instance` as a supported ARN | ||
| type for `opensearch:AddTags` (only `domain`, `data-source`, and | ||
| `application` are listed). The call is wrapped in `retry.ErrPermanent` so | ||
| the retry budget is not exhausted on calls AWS will never accept. If AWS | ||
| extends support, the tag call will start succeeding with no code change. | ||
|
|
||
| ## Impact | ||
|
|
||
| The RI is purchased and active. Cost attribution and audit queries that | ||
| rely on the CUDly source tag (key: `cudly:purchase-source`) will not find | ||
| this reservation unless it is manually tagged. | ||
|
|
||
| ## Remediation | ||
|
|
||
| 1. Identify the untagged RI from the log line: | ||
|
|
||
| ```text | ||
| OPENSEARCH_TAG_FAILED commitment_id=<ri-uuid> error=... | ||
| ``` | ||
|
|
||
| 2. Tag it manually via the AWS CLI: | ||
|
|
||
| ```bash | ||
| REGION=<region> | ||
| ACCOUNT=<account-id> | ||
| RI_ID=<ri-uuid> | ||
| SOURCE=<purchase-source> # e.g. cudly-cli or cudly-web | ||
|
|
||
| aws opensearch add-tags \ | ||
| --arn "arn:aws:es:${REGION}:${ACCOUNT}:reserved-instance/${RI_ID}" \ | ||
| --tag-list \ | ||
| Key=Purpose,Value="Reserved Instance Purchase" \ | ||
| Key=Tool,Value=CUDly \ | ||
| "Key=cudly:purchase-source,Value=${SOURCE}" | ||
| ``` | ||
|
|
||
| If the call returns a `ValidationException` the ARN type is still | ||
| unsupported by AWS; proceed to the fallback below. | ||
|
|
||
| 3. **Fallback (AWS still rejects reserved-instance ARN):** Tag the parent | ||
| OpenSearch domain instead, or record the RI ID in your cost-allocation | ||
| spreadsheet until AWS adds native support. | ||
|
Comment on lines
+64
to
+66
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win Do not present parent-domain tagging as RI remediation. Tagging the parent domain does not attach 🤖 Prompt for AI Agents |
||
|
|
||
| ## Follow-up | ||
|
|
||
| If this alert fires repeatedly (not just on ValidationException but on | ||
| transient errors), open an issue to add a retry with backoff instead of | ||
| the current permanent-error short-circuit. Reference issue #250. | ||
|
|
||
| If AWS releases documentation confirming `reserved-instance` support for | ||
| `AddTags`, remove the `retry.ErrPermanent` wrapper in | ||
| `providers/aws/services/opensearch/client.go:tagReservedInstance` and | ||
| update this runbook. | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Validate the count before lookups and idempotency handling.
At Lines 191-195, validation happens after
findOfferingIDandidempotencyGuard. The guard at Lines 182-188 can therefore return success for an existing reservation beforesafeInt32Countruns, allowing an invalid count to bypass the new validation. Move this check immediately afterresultis initialized.Suggested placement
func (c *Client) PurchaseCommitment(ctx context.Context, rec common.Recommendation, opts common.PurchaseOptions) (common.PurchaseResult, error) { result := common.PurchaseResult{ // ... } + + instanceCount, countErr := safeInt32Count(rec.Count) + if countErr != nil { + result.Error = countErr + return result, result.Error + } offeringID, err := c.findOfferingID(ctx, rec, opts.ExecutionID) // ... - instanceCount, countErr := safeInt32Count(rec.Count) - if countErr != nil { - result.Error = countErr - return result, result.Error - }📝 Committable suggestion
🤖 Prompt for AI Agents