Add ecctl project create and ecctl project delete commands#755
Add ecctl project create and ecctl project delete commands#755
ecctl project create and ecctl project delete commands#755Conversation
Extend the serverless project management capabilities with create and delete operations against the Serverless Projects API. - Add `ecctl project create` with --type, --name, --region, and --tier flags - Add `ecctl project delete <id>` with optional --type flag and auto-detection - Accept "search" as alias for "elasticsearch" project type across all commands - Reject --tier for elasticsearch projects with a clear error message - For observability projects, --tier sets the product_tier field - For security projects, --tier sets all product_types to the given tier - Update global --region flag description for Hosted and Serverless - Add text formatter template for create output - Add unit tests for both commands - Regenerate bindata.go and docs Made-with: Cursor
There was a problem hiding this comment.
Pull request overview
Adds serverless project lifecycle support to ecctl by introducing project create and project delete, expanding project type handling (including search alias), and updating formatting/templates and reference docs accordingly.
Changes:
- Implement
pkg/projectsupport for creating and deleting serverless projects (plussearchtype alias and--tierhandling). - Add new CLI commands
ecctl project create/ecctl project deletewith unit tests and a new text formatter template. - Regenerate bindata and update reference docs/TOC for the new commands and updated flags.
Reviewed changes
Copilot reviewed 15 out of 15 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| pkg/project/project.go | Adds create/delete API calls, type alias handling, and shared request helper updates. |
| cmd/project/create.go | Introduces ecctl project create command and flags. |
| cmd/project/create_test.go | Adds unit tests for create behavior, aliasing, and tier validation. |
| cmd/project/delete.go | Introduces ecctl project delete with optional type autodetection. |
| cmd/project/delete_test.go | Adds unit tests for delete behavior with explicit and autodetected types. |
| cmd/project/list.go | Updates --type help text to include search alias. |
| cmd/project/list_test.go | Updates expected validation error message for type aliasing. |
| cmd/root.go | Updates global --region flag description to include Serverless. |
| pkg/formatter/templates/text/project/create.gotmpl | Adds text output template for project create. |
| pkg/formatter/templates/bindata.go | Regenerates embedded template assets to include the new create template. |
| docs/reference/toc.yml | Adds reference doc entries for create/delete commands. |
| docs/reference/ecctl_project*.md | Adds new command docs and updates existing project docs/flags. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
Address Copilot review comments on PR #755: - Remove local --region flag from project create command; reuse the persistent flag inherited from root. The create command's region validation is handled by CreateParams.Validate(). - Add pagination support to listByType so that all projects are fetched across multiple pages. This fixes project delete auto-detection when the target project isn't on the first page. - Update reference docs to reflect removed local --region flag. Made-with: Cursor
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 15 out of 15 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Add `ecctl project show <id>` command to fetch a single serverless project by ID, with optional --type flag for explicit type or auto-detection via listing all projects. - Add text formatter template and reference docs for the show command. - Fix URL escaping for pagination cursor in listByType: use url.Parse with Query().Set() instead of fmt.Sprintf to handle special chars. - Canonicalize project type in resolveProjectType via ValidateType() instead of a raw ProjectType cast. - Refactor resolveProjectType to be reusable across delete and show. Made-with: Cursor
- Add Endpoints map to Project struct so `project show` displays endpoint URLs (elasticsearch, kibana, apm, ingest) from the API - Add sortKeys template function for deterministic endpoint ordering - Remove CLOUD_ID from project show text output (less relevant for serverless) - Add maxPages=100 safety limit to listByType pagination loop to prevent infinite loops from a misbehaving API Made-with: Cursor
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 21 out of 21 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
pkg/project/project.go
Outdated
| if p.Tier != "" { | ||
| pt, _ := ValidateType(p.Type) | ||
| if pt == Elasticsearch { | ||
| merr = merr.Append(errors.New("--tier is not supported for elasticsearch projects")) |
There was a problem hiding this comment.
CreateParams.Validate returns an error string that includes the CLI flag name (--tier). Since this is in pkg/project (a reusable package), it’s better for the error message to be CLI-agnostic (e.g., refer to the field/concept "tier" rather than a flag) and let the command layer map it to flags if needed.
| merr = merr.Append(errors.New("--tier is not supported for elasticsearch projects")) | |
| merr = merr.Append(errors.New("tier is not supported for elasticsearch projects")) |
cmd/project/create.go
Outdated
| createCmd.Flags().String("type", "", "Project type (elasticsearch/search, observability, security) (required)") | ||
| createCmd.Flags().String("name", "", "Project name (required)") |
There was a problem hiding this comment.
The create command help strings embed "(required)" in the flag descriptions, but the rest of the codebase relies on MarkFlagRequired without adding this suffix in the description (e.g., cmd/user/create.go). For consistency in generated docs/help output, drop the "(required)" text and keep MarkFlagRequired as the single source of truth.
| createCmd.Flags().String("type", "", "Project type (elasticsearch/search, observability, security) (required)") | |
| createCmd.Flags().String("name", "", "Project name (required)") | |
| createCmd.Flags().String("type", "", "Project type (elasticsearch/search, observability, security)") | |
| createCmd.Flags().String("name", "", "Project name") |
- Remove "--" prefix from tier validation error message in pkg/project so the reusable package doesn't reference CLI flag syntax - Remove "(required)" suffix from --type and --name flag descriptions to match codebase convention of relying on MarkFlagRequired Made-with: Cursor
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 21 out of 21 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| var page ListResponse | ||
| if err := json.Unmarshal(body, &page); err != nil { | ||
| return nil, fmt.Errorf("failed to decode response: %w", err) |
There was a problem hiding this comment.
In listByType, the var page ListResponse declaration shadows the loop counter variable page from for page := 0; .... This compiles, but it’s easy to misread and can lead to subtle mistakes if the loop counter is referenced after the shadowing point. Consider renaming one of the variables (e.g., pageNum for the counter or respPage for the response).
| if p.Tier != "" { | ||
| pt, _ := ValidateType(p.Type) | ||
| if pt == Elasticsearch { | ||
| merr = merr.Append(errors.New("tier is not supported for elasticsearch projects")) | ||
| } |
There was a problem hiding this comment.
CreateParams.Validate calls ValidateType(p.Type) but intentionally ignores the returned error (pt, _ := ...). This makes the validation logic harder to follow and can mask why tier validation didn’t run when type is invalid. Either validate type here and append the error to merr, or avoid calling ValidateType and compare the raw type string (including the search alias) explicitly.
| if p.Tier != "" { | |
| pt, _ := ValidateType(p.Type) | |
| if pt == Elasticsearch { | |
| merr = merr.Append(errors.New("tier is not supported for elasticsearch projects")) | |
| } | |
| pt, err := ValidateType(p.Type) | |
| if err != nil { | |
| merr = merr.Append(err) | |
| } else if p.Tier != "" && pt == Elasticsearch { | |
| merr = merr.Append(errors.New("tier is not supported for elasticsearch projects")) |
Summary
ecctl project createcommand with--type,--name,--region, and--tierflags to create serverless projects via the Serverless Projects APIecctl project delete <id>command with optional--typeflag (auto-detects project type when omitted)searchas an alias forelasticsearchproject type across all project commands--tierflag for observability (complete/logs_essentials) and security (complete/essentials) projects; returns a clear error when used with elasticsearch--regionflag description to cover both Hosted and ServerlessTest plan
make lintpasses with 0 issuesmake unitpasses — all newcmd/projecttests pass (create and delete)make bindataregenerated successfullymake docsregenerated successfullyecctl project create --helpshows correct flagsecctl project delete --helpshows correct usageMade with Cursor