feat: add ML calendar and calendar event resources#1969
Open
edsavage wants to merge 9 commits into
Open
Conversation
Contributor
|
✅ PR Changelog Check passed — the |
Add two new Terraform resources for managing Elasticsearch ML calendars: - `elasticstack_elasticsearch_ml_calendar` — manages calendar lifecycle and job associations via individual PutCalendarJob/DeleteCalendarJob endpoints for in-place job_ids updates. - `elasticstack_elasticsearch_ml_calendar_event` — manages individual scheduled events with RFC3339 time handling and server-generated event IDs. All attributes require replacement (no update API). Both resources support import and follow the existing Plugin Framework patterns. Includes requirements doc, unit tests (16 cases), acceptance tests (5 cases), and generated documentation. Made-with: Cursor
Made-with: Cursor
Replace defer with immediate Close() calls inside the job add/remove loops to avoid keeping all response bodies open until function return. Made-with: Cursor
- Break long lines in schema descriptions to stay under 200 char limit (lll) - Rename exported types to avoid stuttering (revive): CalendarTFModel→TFModel, CalendarCreateAPIModel→CreateAPIModel, CalendarAPIModel→APIModel - Fix gofmt alignment after renames Made-with: Cursor
- Use ElasticsearchResource envelope, scoped client, and Ml typed APIs for calendar and calendar_event. - Import state sets resource id attributes; composite IDs support nested calendar_id/event_id segments. - Regenerate resource docs; note new resources in CHANGELOG. Co-authored-by: Cursor <[email protected]>
Contributor
There was a problem hiding this comment.
Pull request overview
Adds two new Terraform Plugin Framework resources to manage Elasticsearch ML anomaly detection calendars and their scheduled events, including provider registration, docs, and test coverage.
Changes:
- Register new ML calendar and calendar event resources in the provider.
- Implement
elasticstack_elasticsearch_ml_calendarwith CRUD + in-place job association reconciliation on update. - Implement
elasticstack_elasticsearch_ml_calendar_eventwith create/read/delete + composite IDs and RFC3339 time handling, plus unit/acceptance tests and generated docs.
Reviewed changes
Copilot reviewed 30 out of 30 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| provider/plugin_framework.go | Registers the new ML calendar and calendar event resources. |
| internal/entitycore/resource_envelope.go | Adjusts Elasticsearch envelope ID parsing to support resource IDs that may contain slashes. |
| internal/clients/api_client.go | Adds composite-ID parsing variant that splits only on the first / for Elasticsearch resources. |
| internal/elasticsearch/ml/calendar/resource.go | Introduces the ML calendar resource wrapper and import handling. |
| internal/elasticsearch/ml/calendar/schema.go | Defines calendar schema (calendar_id, description, job_ids) and validation. |
| internal/elasticsearch/ml/calendar/models.go | Adds TF/API models and mapping logic (including null/empty handling). |
| internal/elasticsearch/ml/calendar/create.go | Implements calendar create via PUT calendar API and sets composite id. |
| internal/elasticsearch/ml/calendar/read.go | Implements calendar read via GetCalendars and drift removal behavior. |
| internal/elasticsearch/ml/calendar/update.go | Implements update to reconcile job_ids associations via add/remove job endpoints. |
| internal/elasticsearch/ml/calendar/delete.go | Implements calendar delete via DeleteCalendar with 404 idempotency. |
| internal/elasticsearch/ml/calendar/models_test.go | Unit tests for calendar model conversions and null/empty semantics. |
| internal/elasticsearch/ml/calendar/acc_test.go | Acceptance tests for calendar CRUD/update, no-jobs behavior, and import. |
| internal/elasticsearch/ml/calendar/testdata/TestAccResourceMLCalendar/create/calendar.tf | Acceptance test config for calendar create case. |
| internal/elasticsearch/ml/calendar/testdata/TestAccResourceMLCalendar/update/calendar.tf | Acceptance test config for calendar update (job association) case. |
| internal/elasticsearch/ml/calendar/testdata/TestAccResourceMLCalendarNoJobs/create/calendar.tf | Acceptance test config for calendar with no jobs set. |
| internal/elasticsearch/ml/calendar/testdata/TestAccResourceMLCalendarImport/create/calendar.tf | Acceptance test config for calendar import scenario. |
| internal/elasticsearch/ml/calendar_event/resource.go | Introduces calendar event resource with custom Create/Update and import handling. |
| internal/elasticsearch/ml/calendar_event/schema.go | Defines calendar event schema with RFC3339 time custom types and replace semantics. |
| internal/elasticsearch/ml/calendar_event/models.go | Adds TF/API models and time conversions (RFC3339 ↔ epoch millis). |
| internal/elasticsearch/ml/calendar_event/create.go | Implements event creation via PostCalendarEvents and discovers server-generated event_id. |
| internal/elasticsearch/ml/calendar_event/read.go | Implements event read by listing events and locating the matching event_id. |
| internal/elasticsearch/ml/calendar_event/delete.go | Implements event delete via DeleteCalendarEvent with 404 idempotency. |
| internal/elasticsearch/ml/calendar_event/models_test.go | Unit tests for time conversions and composite ID parsing helpers. |
| internal/elasticsearch/ml/calendar_event/acc_test.go | Acceptance tests for calendar event create and import flows. |
| internal/elasticsearch/ml/calendar_event/testdata/TestAccResourceMLCalendarEvent/create/calendar_event.tf | Acceptance test config for event creation. |
| internal/elasticsearch/ml/calendar_event/testdata/TestAccResourceMLCalendarEventImport/create/calendar_event.tf | Acceptance test config for event import scenario. |
| docs/resources/elasticsearch_ml_calendar.md | Generated docs for the ML calendar resource schema. |
| docs/resources/elasticsearch_ml_calendar_event.md | Generated docs for the ML calendar event resource schema. |
| dev-docs/requirements/elasticsearch/ml/calendar.md | Adds implementation requirements/spec for both new resources. |
| CHANGELOG.md | Adds changelog entry for the two new ML resources (and normalizes formatting in the edited section). |
…ation) - Align calendar_id validators with ml_calendar (length + regex). - Add ValidateConfig so end_time must be strictly after start_time at plan time. - Regenerate resource documentation. Co-authored-by: Cursor <[email protected]>
PostCalendarEventsRequest/Response and GetCalendarEventsResponse were leftover from the low-level client; create/read use typed API structs. Co-authored-by: Cursor <[email protected]>
- Fail if listing events before POST fails (no silent empty snapshot). - Prefer event_id from PostCalendarEvents response when present. - On list diff, disambiguate multiple new events via description and times. - Add tests for time coercion and plan matching helpers. Co-authored-by: Cursor <[email protected]>
Drop the old dev-docs requirements artifact now that OpenSpec is the canonical requirements source. Co-authored-by: Cursor <[email protected]>
Comment on lines
+87
to
+96
| // The API returns epoch milliseconds as float64 (JSON number decoded via any). | ||
| startMillis, ok := apiModel.StartTime.(float64) | ||
| if !ok { | ||
| diags.AddError("Invalid start_time format", "Expected epoch milliseconds as a number from the API") | ||
| return diags | ||
| } | ||
| endMillis, ok := apiModel.EndTime.(float64) | ||
| if !ok { | ||
| diags.AddError("Invalid end_time format", "Expected epoch milliseconds as a number from the API") | ||
| return diags |
Comment on lines
+82
to
+104
| res, err := typedClient.Ml.GetCalendarEvents(calendarID).Size(10000).Do(ctx) | ||
| if err != nil { | ||
| var esErr *types.ElasticsearchError | ||
| if errors.As(err, &esErr) && esErr.Status == 404 { | ||
| return state, false, nil | ||
| } | ||
| diags.AddError("Failed to get ML calendar events", fmt.Sprintf("Unable to get ML calendar events for calendar %s — %s", calendarID, err.Error())) | ||
| return state, false, diags | ||
| } | ||
|
|
||
| for _, event := range res.Events { | ||
| if event.EventId == nil || *event.EventId != eventID { | ||
| continue | ||
| } | ||
| diags.Append(state.fromAPIModel(ctx, calendarEventTypedToAPI(&event))...) | ||
| if diags.HasError() { | ||
| return state, false, diags | ||
| } | ||
| tflog.Debug(ctx, fmt.Sprintf("Successfully read ML calendar event %s from calendar: %s", eventID, calendarID)) | ||
| return state, true, diags | ||
| } | ||
|
|
||
| return state, false, nil |
Comment on lines
+95
to
+103
| existingIDs := make(map[string]struct{}) | ||
| preRes, err := typedClient.Ml.GetCalendarEvents(calendarID).Size(10000).Do(ctx) | ||
| if err != nil { | ||
| diags.AddError( | ||
| "Failed to list calendar events before create", | ||
| fmt.Sprintf("Cannot snapshot existing event IDs for calendar %s — %s", calendarID, err.Error()), | ||
| ) | ||
| return plan, diags | ||
| } |
|
|
||
| if apiModel.Description != "" { | ||
| m.Description = types.StringValue(apiModel.Description) | ||
| } else { |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
elasticstack_elasticsearch_ml_calendarresource for managing ML calendars and job associationselasticstack_elasticsearch_ml_calendar_eventresource for managing individual scheduled events with RFC3339 timesChangelog
Customer impact: enhancement
Summary: Add
elasticstack_elasticsearch_ml_calendarandelasticstack_elasticsearch_ml_calendar_eventresources for managing Elasticsearch ML calendars, scheduled events, and job associations in Terraform.Details
Calendar resource: Creates/deletes via PUT/DELETE calendar API. Updates job associations in-place by diffing
job_idsand calling individual PutCalendarJob/DeleteCalendarJob endpoints.descriptionrequires replacement (PUT is create-only).Calendar event resource: Creates via POST calendar events API, deletes via DELETE. No update API exists — all attributes use RequiresReplace. Server-generated
event_idis discovered by diffing events before/after creation.Test plan
make buildpasses (including doc generation)Made with Cursor
Note
Add
elasticstack_elasticsearch_ml_calendarandelasticstack_elasticsearch_ml_calendar_eventTerraform resources<cluster_uuid>/<calendar_id>/<event_id>; event IDs are assigned by Elasticsearch and discovered by diffing pre/post-create event lists.start_time,end_time) use RFC3339 strings in Terraform state and are converted to/from epoch milliseconds for the API.📊 Macroscope summarized 5a294b1. 29 files reviewed, 5 issues evaluated, 0 issues filtered, 1 comment posted
(Automatic summaries will resume when PR exits draft mode or review begins).🗂️ Filtered Issues