diff --git a/.changie.yaml b/.changie.yaml deleted file mode 100644 index 1390a2198..000000000 --- a/.changie.yaml +++ /dev/null @@ -1,107 +0,0 @@ -# Changie docs -# https://changie.dev/config -# -# Advanced formatting/logic docs -# https://masterminds.github.io/sprig -changesDir: changelog/releases -unreleasedDir: ../unreleased -headerPath: ../header.tpl.md -versionHeaderPath: "" -versionFooterPath: "" -changelogPath: CHANGELOG.md -versionExt: md -componentFormat: "### {{.Component}}" -versionFormat: | - ## [{{.Version}}] _{{.Time.Format "2006-01-02"}}_ -headerFormat: | - Cycloid CLI changelog: -kindFormat: "**{{.Kind}}**" -changeFormat: | - - {{.Body}} ([CLI#{{.Custom.PR}}]) - {{if ne .Custom.DETAILS "" -}} - *{{.Custom.DETAILS}}* - {{- end -}} -footerFormat: | - {{- range (customs .Changes "PR" | uniq) }} - [CLI#{{.}}]: https://github.com/cycloidio/cycloid-cli/pull/{{.}} - {{- end}} -components: - - API Keys - - Authentication - - Budget - - CLI - - Cloud Cost Management - - Concourse - - Config Repo - - Credentials - - Dashboard - - Environments - - Events - - InfraImport - - InfraPolicies - - InfraView - - Inventory - - Invitations - - KPI - - Licence - - Logs - - Members - - Monitoring - - MSP - - Notifications - - Organizations - - Pipeline Designer - - Pipeline view - - Pipelines Overview - - Profile-User-SalesForce - - Project - - Quota - - Roles - - Service Catalog - - StackCraft - - StackForms - - Start&Stop Env - - Status Page - - Teams - - TerraCost - - Workers - - Other - -kinds: - - label: ADDED - - label: BREAKING - - label: CHANGED - - label: DEPRECATED - - label: FIXED - - label: INTERNAL - - label: REMOVED - - label: SECURITY - -# --[Notes]-- -# -# :: key & label :: -# Doesn't print out both key and label in the cmd line -# so you'll need to prepend the label with the key. -# -# :: optional :: -# Contrary to the docs, int is not optional. So if you -# want to make something optional, you need string. -# -# :: order :: -# We cannot dictate the order for custom properties, -# it's also not clear what logic is used to order them. -# -# :: DETAILS :: -# If your command line goes funky after typing then just -# press enter and finish writing in your IDE instead. -custom: - - key: TYPE - type: enum - enumOptions: - - CLI - - key: PR - type: int - minInt: 1 - - key: DETAILS - label: DETAILS - for public release, should be approx 1-2 sentences (user impact), optional. - type: string diff --git a/.env.sample b/.env.sample deleted file mode 100644 index 4d7c894ae..000000000 --- a/.env.sample +++ /dev/null @@ -1,4 +0,0 @@ -export ACCESS_KEY=cy://org/cycloid/credentials/scaleway_cycloid_automation_admin?key=.raw.raw.access_key -export SECRET_ACCESS=cy://org/cycloid/credentials/scaleway_cycloid_automation_admin?key=.raw.raw.secret_key -export SCW_REGION=fr-par -export API_LICENCE_KEY=cy://org/cycloid/credentials/scaleway-cycloid-backend?key=.raw.raw.licence_key diff --git a/.envrc b/.envrc deleted file mode 100644 index 77c1c5477..000000000 --- a/.envrc +++ /dev/null @@ -1,11 +0,0 @@ -dotenv_if_exists .env -dotenv_if_exists .api_key - -if has nix; then - watch_file flake.nix - use flake . -Lv --log-format raw - - if [ -f ../.envrc ]; then - source_env ../.envrc - fi -fi diff --git a/.gitignore b/.gitignore index 1ce57c642..d142b1750 100644 --- a/.gitignore +++ b/.gitignore @@ -1,38 +1,10 @@ .env -.api_key - -# Binaries for programs and plugins *.exe -*.exe~ -*.dll -*.so -*.dylib -cycloid-cli -cy-* - -# Test binary, built with `go test -c` *.test -swagger.yml - -# Output of the go coverage tool, specifically when used with LiteIDE *.out - -# Dependency directories (remove the comment below to include it) -# vendor/ - -plugins/ +cycloid-cli cy -./gen -pkged.go - -# Intellij +cy-* .idea/ -gst - -# direnv .direnv - -# Local tooling artifacts .claude/ -.gitnexus/ - diff --git a/.golangci.yml b/.golangci.yml deleted file mode 100644 index b43460fc0..000000000 --- a/.golangci.yml +++ /dev/null @@ -1,45 +0,0 @@ -version: "2" -run: - concurrency: 4 - go: "1.24" -linters: - default: none - enable: - - ineffassign - - misspell - - staticcheck - - unconvert - - unused - settings: - misspell: - locale: US - ignore-rules: - - licence - - licences - - utilisation - - cancelled - staticcheck: - checks: - - -SA1019 - - -SA5012 - - all - exclusions: - generated: lax - presets: - - comments - - common-false-positives - - legacy - - std-error-handling - paths: - - third_party$ - - builtin$ - - examples$ -formatters: - enable: - - goimports - exclusions: - generated: lax - paths: - - third_party$ - - builtin$ - - examples$ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml deleted file mode 100644 index 3d62d069b..000000000 --- a/.pre-commit-config.yaml +++ /dev/null @@ -1,19 +0,0 @@ -repos: -- repo: https://github.com/pre-commit/pre-commit-hooks - rev: v6.0.0 - hooks: - - id: check-yaml - - id: end-of-file-fixer - - id: trailing-whitespace - - id: detect-private-key - - id: no-commit-to-branch - args: [--branch, develop, --branch, master] - - id: check-shebang-scripts-are-executable -- repo: local - hooks: - - id: format-and-lint - name: Format and Lint - entry: make format lint - language: system - pass_filenames: false - stages: [pre-commit] diff --git a/.rgignore b/.rgignore deleted file mode 100644 index ea1e43897..000000000 --- a/.rgignore +++ /dev/null @@ -1,3 +0,0 @@ -# This file is there to set ignore in ripgrep search -# this won't affect git -client/** diff --git a/AGENTS.md b/AGENTS.md deleted file mode 100644 index 50890d6e8..000000000 --- a/AGENTS.md +++ /dev/null @@ -1,245 +0,0 @@ -# AGENTS.md - -This file mirrors `CLAUDE.md` for LLM agents that use the AGENTS.md convention. Keep in sync when updating either file. - ---- - -# CLAUDE.md - -This file is auto-loaded by Claude Code on every invocation. See also `AGENTS.md` (kept identical, for non-Claude LLM agents). - -## Commands - -```bash -# Build -make build # build all platform binaries -go build -o cy . # quick local build - -# Test (requires local backend) -make be-reset # start backend via docker compose -go test ./... # run all tests -make test # same -make be-stop # stop backend - -# Run a specific test -go test ./e2e/... -run TestProjects -go test ./cmd/cycloid/middleware/... -run TestGetProject - -# Lint & format -make lint # golangci-lint + shellcheck -make format # gci + goimports + shfmt - -# Client regeneration (when swagger.yaml changes) -make client-generate # regenerates ./client/ from swagger.yaml - -# Changelog -make new-changelog-entry # add unreleased changelog entry (uses changie via docker) -``` - -## Architecture - -``` -cmd/cycloid//*.go → cmd/cycloid/middleware/ → GenericRequest() - (cobra commands) (Middleware interface) (generic_client.go) -``` - -### Key packages - -- **`client/models/`** — Auto-generated go-swagger models from `swagger.yaml`. Never edit manually. Regenerate with `make client-generate`. -- **`client/client/`** — Intentionally NOT used. The generated operations package was removed in the middleware refactor. Use `GenericRequest` instead. -- **`cmd/cycloid/middleware/`** — The `Middleware` interface (`middleware.go`) makes HTTP calls via `GenericRequest` (`generic_client.go`). Each feature gets its own file (e.g., `organization_projects.go`). -- **`cmd/cycloid//`** — Cobra command definitions. Each feature directory has: `cmd.go` (registers subcommands), plus one file per verb (`list.go`, `get.go`, `create.go`, `update.go`, `delete.go`), and `common.go` for shared logic. -- **`internal/cyargs/`** — All shared flag definitions and completion functions. Every flag used by multiple commands must be declared here. -- **`printer/`** — Output formatting. Use `printer.SmartPrint(p, obj, err, errStr, opts, writer)` — success to `cmd.OutOrStdout()`, errors to `cmd.OutOrStderr()`. -- **`e2e/`** — End-to-end tests that run real CLI commands against a live backend. - -## Hard Rules - -These are invariants that LLM agents and new contributors must not violate: - -1. **NEVER edit `client/models/`** — auto-generated. Run `make client-generate` to update. -2. **NEVER import or use `client/client/`** — deprecated. Use `GenericRequest` in middleware methods. -3. **NEVER call `NewMiddleware` outside a cobra `RunE` function** — not at package init, not in tests directly. -4. **ALWAYS parse ALL flags via `cyargs.Get*` BEFORE calling `common.NewAPI()` and `NewMiddleware()`** — `GenericRequest` reads `verbosity` from Viper at call time; unparsed flags produce stale values. -5. **ALWAYS add shared flags to `internal/cyargs/`** — never inline a flag used by more than one command. -6. **ALWAYS use `printer.SmartPrint`** — errors go to `OutOrStderr()`, results go to `OutOrStdout()`. -7. **E2E tests require a running backend** (`make be-start`). Never run e2e in parallel. -8. **Run `make format && make lint` after every code change.** -9. **Ship tests with every feature** — in the same change, add or extend coverage for what you introduce: new or changed middleware in `cmd/cycloid/middleware/*_test.go` (or focused unit tests where appropriate), and user-facing CLI behavior in `e2e/*_test.go` when that resource already has e2e tests. Do not land behavior-only changes without tests. - -## `GenericRequest` pattern - -`GenericRequest` handles auth, JSON marshaling, and `{"data":...}` envelope unwrapping. Pass `&result` directly — do not wrap in a `struct{ Data *X }`. - -```go -// Standard middleware method pattern: -func (m *middleware) GetProject(org, project string) (*models.Project, *http.Response, error) { - var result *models.Project - resp, err := m.GenericRequest(Request{ - Method: "GET", - Organization: &org, - Route: []string{"organizations", org, "projects", project}, - }, &result) - if err != nil { - return nil, resp, err - } - return result, resp, nil -} -``` - -`Request` fields: `Method`, `Organization` (*string, for auth), `NoAuth` (bool), `Route` ([]string), `Query` (struct with `url` tags), `LHSFilters` ([]LHSFilter, see below), `Headers` (map), `Accept` (*string), `Body` (any, JSON-marshalled). - -## LHS filters - -The Cycloid API supports LHS bracket filters on `List` routes: `attribute[condition]=value`. The condition is typically `eq`, `rlike`, `gt`, `lt`, etc. - -**Rule: all new `List` middleware methods must accept `filters ...LHSFilter` as their last parameter.** - -`LHSFilter` is defined in `cmd/cycloid/middleware/lhs_filter.go`: - -```go -type LHSFilter struct { - Attribute string - Condition string - Value string -} -``` - -Pass filters via the `LHSFilters` field of `Request`. Brackets are kept literal (not percent-encoded) so the API receives `name[eq]=my-project`, not `name%5Beq%5D=my-project`. Regex metacharacters in values (`?`, `*`, `+`, etc.) are also preserved. - -```go -// Example: list projects filtered by name prefix -func (m *middleware) ListProjects(org string, filters ...LHSFilter) ([]*models.Project, *http.Response, error) { - var result []*models.Project - resp, err := m.GenericRequest(Request{ - Method: "GET", - Organization: &org, - Route: []string{"organizations", org, "projects"}, - LHSFilters: filters, - }, &result) - ... -} - -// Caller usage: -projects, _, err := m.ListProjects(org, middleware.LHSFilter{ - Attribute: "name", - Condition: "rlike", - Value: "proj.*", -}) -``` - -Offline (no-backend) unit tests for LHS filter encoding live in `cmd/cycloid/middleware/offline/lhs_filter_test.go`. - -### Return type conventions - -| Verb | Return | -|------|--------| -| Get / Create | `(*models.X, *http.Response, error)` | -| List | `([]*models.X, *http.Response, error)` | -| Delete / void | `(*http.Response, error)` | - -Always return the `*http.Response` so callers can inspect status codes. Assign `_` if unused. - -## Command pattern - -```go -func getProject(cmd *cobra.Command, args []string) error { - // Step 1: ALL flags first - org, err := cyargs.GetOrg(cmd) - if err != nil { return err } - project, err := cyargs.GetProject(cmd) - if err != nil { return err } - output, err := cmd.Flags().GetString("output") - if err != nil { return errors.Wrap(err, "unable to get output flag") } - - // Step 2: printer - p, err := factory.GetPrinter(output) - if err != nil { return errors.Wrap(err, "unable to get printer") } - - // Step 3: API + middleware - api := common.NewAPI() - m := middleware.NewMiddleware(api) - - // Step 4: call + print - result, _, err := m.GetProject(org, project) - if err != nil { - return printer.SmartPrint(p, nil, err, "unable to get project", printer.Options{}, cmd.OutOrStderr()) - } - return printer.SmartPrint(p, result, nil, "", printer.Options{}, cmd.OutOrStdout()) -} -``` - -## `cyargs` flags - -All shared flag definitions live in `internal/cyargs/`. Pattern: - -```go -func AddWidgetFlag(cmd *cobra.Command) { - cmd.Flags().String("widget", "", "Widget canonical") - _ = cmd.RegisterFlagCompletionFunc("widget", widgetCompletion) -} - -func GetWidget(cmd *cobra.Command) (string, error) { - return cmd.Flags().GetString("widget") -} -``` - -Register in the command constructor (`NewGetX()`), never inside `RunE`. - -## Testing - -- **Tests ship with the feature** (see Hard Rule 9): middleware and command changes should include tests in the same PR; extend existing `e2e/*_test.go` files when the resource is already covered there. -- **Middleware tests** (`cmd/cycloid/middleware/*_test.go`): `TestMain` calls `testcfg.NewConfig("middleware")`. Fixtures: `config.Project`, `config.Environment`, `config.Component`, `config.ConfigRepo`, `config.CatalogRepo`. -- **E2E tests** (`e2e/*_test.go`): `executeCommand(args)` runs the real CLI. Same `testcfg` setup. -- E2E tests are **not parallel** (backend git writes are not concurrent-safe). -- `CY_TEST_VERBOSITY=debug` → full HTTP request/response logs. Auth header redacted to `Bearer ***XXXXX` (last 5 chars). - -## Config & auth - -`common.NewAPI()` resolves config from flags → env vars → config file. Token priority: `--api-key` → `CY_API_KEY` → `CY_API_TOKEN` → per-org token in config file. - -## Deeper docs - -- `@docs/architecture.md` — HTTP layer, Request struct, auth flow, error taxonomy -- `@docs/pipeline-build-watch-output.md` — `pipeline build trigger --watch` human SSE output; how to disable or remove -- `@docs/adding-a-command.md` — full walkthrough with working example -- `@docs/testing.md` — middleware + e2e test patterns, testcfg deep-dive -- `@docs/middleware-refactor.md` — what changed and why, migration reference - - -# GitNexus — Code Intelligence - -This project is indexed by GitNexus as **cycloid-cli** (11392 symbols, 69497 relationships, 300 execution flows). Use the GitNexus MCP tools to understand code, assess impact, and navigate safely. - -> If any GitNexus tool warns the index is stale, run `npx gitnexus analyze` in terminal first. - -## When GitNexus is Available - -- Before modifying a symbol, prefer running `gitnexus_impact({target: "symbolName", direction: "upstream"})` to understand callers and blast radius. -- Before committing, consider running `gitnexus_detect_changes()` to verify the affected scope matches expectations. -- If impact analysis returns HIGH or CRITICAL risk, surface it to the user before proceeding. -- When exploring unfamiliar code, prefer `gitnexus_query({query: "concept"})` over grepping — it returns process-grouped results ranked by relevance. -- For full context on a specific symbol — callers, callees, execution flows — use `gitnexus_context({name: "symbolName"})`. -- Prefer `gitnexus_rename` over find-and-replace for symbol renames — it understands the call graph. - -## Resources - -| Resource | Use for | -|----------|---------| -| `gitnexus://repo/cycloid-cli/context` | Codebase overview, check index freshness | -| `gitnexus://repo/cycloid-cli/clusters` | All functional areas | -| `gitnexus://repo/cycloid-cli/processes` | All execution flows | -| `gitnexus://repo/cycloid-cli/process/{name}` | Step-by-step execution trace | - -## CLI - -| Task | Read this skill file | -|------|---------------------| -| Understand architecture / "How does X work?" | `.claude/skills/gitnexus/gitnexus-exploring/SKILL.md` | -| Blast radius / "What breaks if I change X?" | `.claude/skills/gitnexus/gitnexus-impact-analysis/SKILL.md` | -| Trace bugs / "Why is X failing?" | `.claude/skills/gitnexus/gitnexus-debugging/SKILL.md` | -| Rename / extract / split / refactor | `.claude/skills/gitnexus/gitnexus-refactoring/SKILL.md` | -| Tools, resources, schema reference | `.claude/skills/gitnexus/gitnexus-guide/SKILL.md` | -| Index, status, clean, wiki CLI commands | `.claude/skills/gitnexus/gitnexus-cli/SKILL.md` | - - diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index 57b6ddff1..000000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,208 +0,0 @@ -## [Unreleased] - -- **ADDED** - - `cy catalog-repository create` and `cy catalog-repository update` now accept a `--refresh` flag. - When set, a synchronous version re-index (`GET .../versions/refresh?sync_presence=true`) is triggered - immediately after the create or update succeeds, making all branches and tags resolvable without - waiting for the background cron (~10 min). This fixes the branch-stack presence race. - ([CLI-128](https://linear.app/cycloid/issue/CLI-128)) - - ## [v3.1.3] _2022-06-17_ - - **CHANGED** - - Update client to version v3.1.3 - ([PR #140](https://github.com/cycloidio/cycloid-cli/pull/140)) - ## [v1.0.97] _2022-06-13_ - - **CHANGED** - - Update client to version v1.0.97 - ([PR #137](https://github.com/cycloidio/cycloid-cli/pull/137)) -## [v1.0.89] _2022-03-08_ -- **CHANGED** - - Update client to version v1.0.89 - ([PR #130](https://github.com/cycloidio/cycloid-cli/pull/130)) - - Add the ability to specify canonical for credential create - ([PR #130](https://github.com/cycloidio/cycloid-cli/pull/130)) - - Add new field-file flag to custom credential create - ([PR #130](https://github.com/cycloidio/cycloid-cli/pull/130)) - -## [v1.0.88] _2022-02-10_ -- **CHANGED** - - Update client to version v1.0.88 - ([PR #125](https://github.com/cycloidio/cycloid-cli/pull/125)) - - cy-wrapper: Now use Cycloid URL instead of Github to avoid API request limits - ([PR #126](https://github.com/cycloidio/cycloid-cli/pull/126)) - - cy-wrapper: provide debug mode using CY_DEBUG env var - ([PR #127](https://github.com/cycloidio/cycloid-cli/pull/127)) - - cy-wrapper: CY_WAIT_NETWORK now default to false - ([PR #127](https://github.com/cycloidio/cycloid-cli/pull/127)) - - cy-wrapper: CY_VERSION can be enforced to a specific version - ([PR #127](https://github.com/cycloidio/cycloid-cli/pull/127)) - - cy-wrapper: Reduce the default number of retries and provide new CY_DOWNLOAD_RETRIES variable - ([PR #127](https://github.com/cycloidio/cycloid-cli/pull/127)) - - cy-wrapper: Error handling when CY_RELEASES_URL is not reachable or incorrect - ([PR #127](https://github.com/cycloidio/cycloid-cli/pull/127)) - -## [v1.0.86] _2022-01-04_ -- **CHANGED** - - Update client to version v1.0.86 - ([PR #122](https://github.com/cycloidio/cycloid-cli/pull/122)) - -## [v1.0.85] _2021-12-08_ -- **CHANGED** - - Update client to version v1.0.85 - ([PR #120](https://github.com/cycloidio/cycloid-cli/pull/120)) - -## [v1.0.84] _2021-11-10_ -- **CHANGED** - - Update client to version 1.0.84 - ([PR #115](https://github.com/cycloidio/cycloid-cli/pull/115)) -- **ADDED** - - Adding new pipeline synced command - ([PR #111](https://github.com/cycloidio/cycloid-cli/pull/111)) - - CY wrapper, add more retry on and wait for network - ([PR #110](https://github.com/cycloidio/cycloid-cli/pull/110)) - -## [v1.0.82] _2021-10-04_ -- **ADDED** - - Adding cycloid dev readme and local e2e make targets - ([PR #112](https://github.com/cycloidio/cycloid-cli/pull/105)) - -- **CHANGED** - - Update client to version 1.0.82 - ([PR #105](https://github.com/cycloidio/cycloid-cli/pull/105)) - - Changed makefile to allow better use of targets for the cli automatic bump - ([PR #112](https://github.com/cycloidio/cycloid-cli/pull/105)) - -- **FIXED** - - Fix error in help of delete-env command - ([PR #105](https://github.com/cycloidio/cycloid-cli/pull/105)) - -## [v1.0.76] _2021-07-08_ -- **CHANGED** - - Update client to version 1.0.76 - ([PR #101](https://github.com/cycloidio/cycloid-cli/pull/101)) - - Update client to version 1.0.72 - ([PR #99](https://github.com/cycloidio/cycloid-cli/pull/99)) - -- **BREAKING** - - Switching to API KEY login only - ([PR #79](https://github.com/cycloidio/cycloid-cli/pull/79)) - -## [v1.0.64] _2021-03-23_ -- **CHANGED** - - Update to version 1.0.64 - ([PR #92](https://github.com/cycloidio/cycloid-cli/pull/92)) - -- **BREAKING** - - Remove create api key command - ([PR #92](https://github.com/cycloidio/cycloid-cli/pull/92)) - -- **FIXED** - - Fix wrong list function execution in `members list-invites` - ([PR #94](https://github.com/cycloidio/cycloid-cli/pull/94)) - -## [v1.0.61] _2021-03-15_ -- **ADDED** - - Adding better error details display - ([PR #76](https://github.com/cycloidio/cycloid-cli/pull/76)) - - Adding organizations `list-children` command - ([PR #76](https://github.com/cycloidio/cycloid-cli/pull/76)) - -- **CHANGED** - - Update to version 1.0.61 - ([PR #84](https://github.com/cycloidio/cycloid-cli/pull/84)) - - wrapper: change behavior to look for the closest lower version - ([PR #85](https://github.com/cycloidio/cycloid-cli/pull/85)) - -- **REMOVED** - - Remove deprecated KPIs `list-avaiable` command - ([PR #84](https://github.com/cycloidio/cycloid-cli/pull/84)) - -## [v1.0.58] _2021-02-05_ -- **ADDED** - - Adding new kpis command - ([PR #81](https://github.com/cycloidio/cycloid-cli/pull/81)) - - Adding new list-invites command - ([PR #72](https://github.com/cycloidio/cycloid-cli/pull/72)) - - `gen-doc` subcommand - ([PR #61](https://github.com/cycloidio/cycloid-cli/pull/61)) - - `--insecure` flag to allow TLS verification skipping - ([Issue #70](https://github.com/cycloidio/cycloid-cli/issues/70)) - - Adding all missing creds type into the CLI (GCP, AWS, ...) - ([PR #74](https://github.com/cycloidio/cycloid-cli/pull/74)) - -## [v1.0.53] _2020-12-01_ -- **CHANGED** - - Update to version 1.0.53 - ([PR #62](https://github.com/cycloidio/cycloid-cli/pull/62)) - - Wrapper now fallback to RC version before trying the dev one - ([PR #62](https://github.com/cycloidio/cycloid-cli/pull/62)) - - Add pipeline list command to list all pipeline in an organization - ([PR #62](https://github.com/cycloidio/cycloid-cli/pull/62)) - -## [v1.0.51] _2020-11-12_ -- **CHANGED** - - Update to version 1.0.51 - ([PR #52](https://github.com/cycloidio/cycloid-cli/pull/52)) - -## [v1.0.50] _2020-11-04_ -- **ADDED** - - Add organization create/delete - ([PR #51](https://github.com/cycloidio/cycloid-cli/pull/51)) - - `api-keys` commands - ([PR #57](https://github.com/cycloidio/cycloid-cli/pull/57)) - -- **CHANGED** - - `login` method to allow login using API key - ([PR #57](https://github.com/cycloidio/cycloid-cli/pull/57)) - -## [v1.0.49] _2020-11-02_ -- **ADDED** - - Add validate-form command - ([PR #35](https://github.com/cycloidio/cycloid-cli/pull/35)) - - Bump CLI version - ([PR #35](https://github.com/cycloidio/cycloid-cli/pull/35)) - - printer /helpers for each command - ([PR #25](https://github.com/cycloidio/cycloid-cli/pull/25)) - - `login list` subcommand - ([PR #24](https://github.com/cycloidio/cycloid-cli/pull/24)) - - support for child org login - ([PR #37](https://github.com/cycloidio/cycloid-cli/pull/37)) - - status endpoint implementation - ([PR #42](https://github.com/cycloidio/cycloid-cli/pull/42)) - - bash/zsh auto-complete - ([PR #47](https://github.com/cycloidio/cycloid-cli/pull/47)) - -## [v1.0.47] _2020-09-21_ -- **ADDED** - - Printer with support for `json`, `yaml` and `table` format - ([PR #4](https://github.com/cycloidio/cycloid-cli/pull/4)) - - First iteration of login command - ([PR #9](https://github.com/cycloidio/cycloid-cli/pull/9)) - -- **CHANGED** - - Second iteration of login command : allow multiple orgs login - :warning: the signature of common.ClientCredentials has changed - ([PR #15](https://github.com/cycloidio/cycloid-cli/pull/15)) - -- **DEPRECATED** - -- **REMOVED** - -- **FIXED** - -- **SECURITY** - -## [1.0.46] _2020-09-20_ -- **ADDED** - - First changelog template - ([PR #0](https://github.com/cycloidio/cycloid-cli/pull/0)) - -- **CHANGED** - -- **DEPRECATED** - -- **REMOVED** - -- **FIXED** - -- **SECURITY** diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 100644 index c392ccd9a..000000000 --- a/CLAUDE.md +++ /dev/null @@ -1,238 +0,0 @@ -# CLAUDE.md - -This file is auto-loaded by Claude Code on every invocation. See also `AGENTS.md` (kept identical, for non-Claude LLM agents). - -## Commands - -```bash -# Build -make build # build all platform binaries -go build -o cy . # quick local build - -# Test (requires local backend) -make be-reset # start backend via docker compose -go test ./... # run all tests -make test # same -make be-stop # stop backend - -# Run a specific test -go test ./e2e/... -run TestProjects -go test ./cmd/cycloid/middleware/... -run TestGetProject - -# Lint & format -make lint # golangci-lint + shellcheck -make format # gci + goimports + shfmt - -# Client regeneration (when swagger.yaml changes) -make client-generate # regenerates ./client/ from swagger.yaml - -# Changelog -make new-changelog-entry # add unreleased changelog entry (uses changie via docker) -``` - -## Architecture - -``` -cmd/cycloid//*.go → cmd/cycloid/middleware/ → GenericRequest() - (cobra commands) (Middleware interface) (generic_client.go) -``` - -### Key packages - -- **`client/models/`** — Auto-generated go-swagger models from `swagger.yaml`. Never edit manually. Regenerate with `make client-generate`. -- **`client/client/`** — Intentionally NOT used. The generated operations package was removed in the middleware refactor. Use `GenericRequest` instead. -- **`cmd/cycloid/middleware/`** — The `Middleware` interface (`middleware.go`) makes HTTP calls via `GenericRequest` (`generic_client.go`). Each feature gets its own file (e.g., `organization_projects.go`). -- **`cmd/cycloid//`** — Cobra command definitions. Each feature directory has: `cmd.go` (registers subcommands), plus one file per verb (`list.go`, `get.go`, `create.go`, `update.go`, `delete.go`), and `common.go` for shared logic. -- **`internal/cyargs/`** — All shared flag definitions and completion functions. Every flag used by multiple commands must be declared here. -- **`printer/`** — Output formatting. Use `cyout.PrintWithOptions(cmd, obj, err, errMsg, opts)` — routes errors to `cmd.ErrOrStderr()`, results to `cmd.OutOrStdout()`. Direct `printer.SmartPrint` calls are legacy; migrate on touch. -- **`internal/cyout/`** — One-liner print helpers (`cyout.Print`, `cyout.PrintWithOptions`) and `cyout.RegisterModel` for `--output` shell completion. -- **`e2e/`** — End-to-end tests that run real CLI commands against a live backend. - -## Hard Rules - -These are invariants that LLM agents and new contributors must not violate: - -1. **NEVER edit `client/models/`** — auto-generated. Run `make client-generate` to update. -2. **NEVER import or use `client/client/`** — deprecated. Use `GenericRequest` in middleware methods. -3. **NEVER call `NewMiddleware` outside a cobra `RunE` function** — not at package init, not in tests directly. -4. **ALWAYS parse ALL flags via `cyargs.Get*` BEFORE calling `common.NewAPI()` and `NewMiddleware()`** — `GenericRequest` reads `verbosity` from Viper at call time; unparsed flags produce stale values. -5. **ALWAYS add shared flags to `internal/cyargs/`** — never inline a flag used by more than one command. -6. **ALWAYS use `cyout.PrintWithOptions` (or `cyout.Print`)** — errors go to `ErrOrStderr()`, results go to `OutOrStdout()`. Do not call `printer.SmartPrint` directly in new code. -7. **E2E tests require a running backend** (`make be-start`). Never run e2e in parallel. -8. **Run `make format && make lint` after every code change.** -9. **Ship tests with every feature** — in the same change, add or extend coverage for what you introduce: new or changed middleware in `cmd/cycloid/middleware/*_test.go` (or focused unit tests where appropriate), and user-facing CLI behavior in `e2e/*_test.go` when that resource already has e2e tests. Do not land behavior-only changes without tests. - -## `GenericRequest` pattern - -`GenericRequest` handles auth, JSON marshaling, and `{"data":...}` envelope unwrapping. Pass `&result` directly — do not wrap in a `struct{ Data *X }`. - -```go -// Standard middleware method pattern: -func (m *middleware) GetProject(org, project string) (*models.Project, *http.Response, error) { - var result *models.Project - resp, err := m.GenericRequest(Request{ - Method: "GET", - Organization: &org, - Route: []string{"organizations", org, "projects", project}, - }, &result) - if err != nil { - return nil, resp, err - } - return result, resp, nil -} -``` - -`Request` fields: `Method`, `Organization` (*string, for auth), `NoAuth` (bool), `Route` ([]string), `Query` (struct with `url` tags), `LHSFilters` ([]LHSFilter, see below), `Headers` (map), `Accept` (*string), `Body` (any, JSON-marshalled). - -## LHS filters - -The Cycloid API supports LHS bracket filters on `List` routes: `attribute[condition]=value`. The condition is typically `eq`, `rlike`, `gt`, `lt`, etc. - -**Rule: all new `List` middleware methods must accept `filters ...LHSFilter` as their last parameter.** - -`LHSFilter` is defined in `cmd/cycloid/middleware/lhs_filter.go`: - -```go -type LHSFilter struct { - Attribute string - Condition string - Value string -} -``` - -Pass filters via the `LHSFilters` field of `Request`. Brackets are kept literal (not percent-encoded) so the API receives `name[eq]=my-project`, not `name%5Beq%5D=my-project`. Regex metacharacters in values (`?`, `*`, `+`, etc.) are also preserved. - -```go -// Example: list projects filtered by name prefix -func (m *middleware) ListProjects(org string, filters ...LHSFilter) ([]*models.Project, *http.Response, error) { - var result []*models.Project - resp, err := m.GenericRequest(Request{ - Method: "GET", - Organization: &org, - Route: []string{"organizations", org, "projects"}, - LHSFilters: filters, - }, &result) - ... -} - -// Caller usage: -projects, _, err := m.ListProjects(org, middleware.LHSFilter{ - Attribute: "name", - Condition: "rlike", - Value: "proj.*", -}) -``` - -Offline (no-backend) unit tests for LHS filter encoding live in `cmd/cycloid/middleware/offline/lhs_filter_test.go`. - -### Return type conventions - -| Verb | Return | -|------|--------| -| Get / Create | `(*models.X, *http.Response, error)` | -| List | `([]*models.X, *http.Response, error)` | -| Delete / void | `(*http.Response, error)` | - -Always return the `*http.Response` so callers can inspect status codes. Assign `_` if unused. - -## Command pattern - -```go -var projectTableOptions = printer.Options{ - Columns: []string{"Canonical", "Name", "Description", "Owner.Username"}, - Identifier: "Canonical", -} - -func getProject(cmd *cobra.Command, args []string) error { - // Step 1: ALL flags first - org, err := cyargs.GetOrg(cmd) - if err != nil { return err } - project, err := cyargs.GetProject(cmd) - if err != nil { return err } - - // Step 2: API + middleware - api := common.NewAPI() - m := middleware.NewMiddleware(api) - - // Step 3: call + print (cyout handles printer selection and error routing) - result, _, err := m.GetProject(org, project) - return cyout.PrintWithOptions(cmd, result, err, "unable to get project", projectTableOptions) -} -``` - -`cyout.PrintWithOptions` handles everything: reads `--output`, picks the printer, routes errors to stderr and results to stdout. For commands with no column customisation, use `cyout.Print(cmd, obj, err, errMsg)`. - -## `cyargs` flags - -All shared flag definitions live in `internal/cyargs/`. Pattern: - -```go -func AddWidgetFlag(cmd *cobra.Command) { - cmd.Flags().String("widget", "", "Widget canonical") - _ = cmd.RegisterFlagCompletionFunc("widget", widgetCompletion) -} - -func GetWidget(cmd *cobra.Command) (string, error) { - return cmd.Flags().GetString("widget") -} -``` - -Register in the command constructor (`NewGetX()`), never inside `RunE`. - -## Testing - -- **Tests ship with the feature** (see Hard Rule 9): middleware and command changes should include tests in the same PR; extend existing `e2e/*_test.go` files when the resource is already covered there. -- **Middleware tests** (`cmd/cycloid/middleware/*_test.go`): `TestMain` calls `testcfg.NewConfig("middleware")`. Fixtures: `config.Project`, `config.Environment`, `config.Component`, `config.ConfigRepo`, `config.CatalogRepo`. -- **E2E tests** (`e2e/*_test.go`): `executeCommand(args)` runs the real CLI. Same `testcfg` setup. -- E2E tests are **not parallel** (backend git writes are not concurrent-safe). -- `CY_TEST_VERBOSITY=debug` → full HTTP request/response logs. Auth header redacted to `Bearer ***XXXXX` (last 5 chars). - -## Config & auth - -`common.NewAPI()` resolves config from flags → env vars → config file. Token priority: `--api-key` → `CY_API_KEY` → `CY_API_TOKEN` → per-org token in config file. - -## Deeper docs - -- `@docs/architecture.md` — HTTP layer, Request struct, auth flow, error taxonomy -- `@docs/pipeline-build-watch-output.md` — `pipeline build trigger --watch` human SSE output; how to disable or remove -- `@docs/adding-a-command.md` — full walkthrough with working example -- `@docs/testing.md` — middleware + e2e test patterns, testcfg deep-dive -- `@docs/middleware-refactor.md` — what changed and why, migration reference - - -# GitNexus — Code Intelligence - -This project is indexed by GitNexus as **cycloid-cli** (11392 symbols, 69497 relationships, 300 execution flows). Use the GitNexus MCP tools to understand code, assess impact, and navigate safely. - -> If any GitNexus tool warns the index is stale, run `npx gitnexus analyze` in terminal first. - -## When GitNexus is Available - -- Before modifying a symbol, prefer running `gitnexus_impact({target: "symbolName", direction: "upstream"})` to understand callers and blast radius. -- Before committing, consider running `gitnexus_detect_changes()` to verify the affected scope matches expectations. -- If impact analysis returns HIGH or CRITICAL risk, surface it to the user before proceeding. -- When exploring unfamiliar code, prefer `gitnexus_query({query: "concept"})` over grepping — it returns process-grouped results ranked by relevance. -- For full context on a specific symbol — callers, callees, execution flows — use `gitnexus_context({name: "symbolName"})`. -- Prefer `gitnexus_rename` over find-and-replace for symbol renames — it understands the call graph. - -## Resources - -| Resource | Use for | -|----------|---------| -| `gitnexus://repo/cycloid-cli/context` | Codebase overview, check index freshness | -| `gitnexus://repo/cycloid-cli/clusters` | All functional areas | -| `gitnexus://repo/cycloid-cli/processes` | All execution flows | -| `gitnexus://repo/cycloid-cli/process/{name}` | Step-by-step execution trace | - -## CLI - -| Task | Read this skill file | -|------|---------------------| -| Understand architecture / "How does X work?" | `.claude/skills/gitnexus/gitnexus-exploring/SKILL.md` | -| Blast radius / "What breaks if I change X?" | `.claude/skills/gitnexus/gitnexus-impact-analysis/SKILL.md` | -| Trace bugs / "Why is X failing?" | `.claude/skills/gitnexus/gitnexus-debugging/SKILL.md` | -| Rename / extract / split / refactor | `.claude/skills/gitnexus/gitnexus-refactoring/SKILL.md` | -| Tools, resources, schema reference | `.claude/skills/gitnexus/gitnexus-guide/SKILL.md` | -| Index, status, clean, wiki CLI commands | `.claude/skills/gitnexus/gitnexus-cli/SKILL.md` | - - diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index d6c07f3f5..000000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,40 +0,0 @@ -# Contributing - -## Adding a feature or command - -See [`docs/adding-a-command.md`](docs/adding-a-command.md) for a full walkthrough including middleware methods, cobra commands, flags, and tests. - -## Running tests - -See [`docs/testing.md`](docs/testing.md) for setup, environment variables, and test patterns. - -Quick start: - -```bash -make be-start # start the local backend -go test ./... # run all tests -make be-stop -``` - -## Code style - -```bash -make format # gci + goimports + shfmt -make lint # golangci-lint + shellcheck -``` - -Always run both before submitting a PR. - -## Changelog - -Each PR should include a changelog entry: - -```bash -make new-changelog-entry -``` - -This runs `changie` via docker and creates a file in `changelog/unreleased/`. - -## Architecture overview - -See [`docs/architecture.md`](docs/architecture.md) and [`CLAUDE.md`](CLAUDE.md). diff --git a/DEVELOPING_TIPS.md b/DEVELOPING_TIPS.md deleted file mode 100644 index f33832efc..000000000 --- a/DEVELOPING_TIPS.md +++ /dev/null @@ -1,252 +0,0 @@ -# Cycloid Developer Tips - -> [!NOTE] **ARCHIVED** — Key content has been extracted into `docs/` (see `docs/adding-a-command.md`, `docs/testing.md`, `docs/architecture.md`). This file is kept for internal release process reference only (Concourse CI links, version tagging process) and requires access to private Cycloid repositories. - -> [!NOTE] These are internal notes meant for cycloid developers only since they -> require access to private git repositories. - -This file gives some tips to how to test, change or upgrade cli, for cycloid developers. - -The cli pipeline is available in the [cycloid-stacks](https://github.com/cycloidio/cycloid-stacks/tree/stacks/cycloid-cli) and the prod and staging cli can be checked [here](https://console.cycloid.io/organizations/cycloid/projects/cycloid-cli). - -## Prepare a CLI update - -Right now, the CLI release process and version is tied to the backend release. -This will be changed once the CLI codebase will be merged in the backend, until then, -we will have to make do. - -So the release process is as follows: -- The backend is merged and release in staging/production -- An automatic PR is made with the client update on [this component](https://console.cycloid.io/organizations/cycloid/projects/cycloid-cli/environments/automatic_bump/components/apibump/overview) -- The automatic PR will contain the client update and write the version in the - [`./client/version`](./client/version) file. - -> [!WARNING] -> The version tagging will occur when the PR with the updated client version with -> the updated [`./client/version`](./client/version) file will be merged on develop -> -> This means that every feature PR merged after this one will not be integrated -> in the release - -- Once the Client update PR merged, the version is tagged the pipeline on - [this component must go to completion on the release job](https://console.cycloid.io/organizations/cycloid/projects/cycloid-cli/environments/staging/components/develop/overview) -- To release in prod, use the [`merge-develop-to-master`](https://console.cycloid.io/organizations/cycloid/projects/cycloid-cli/environments/prod/components/master/pipelines/cycloid-cli-prod-master/jobs/merge-develop-to-master/builds/465851136#all) button on the prod pipeline. -- Then the release process will test, build and release on github. - -So we advise the following workflow: - -1. Until a client version update occurs, you can merge any feature PR on develop -2. Once the client PR update is created, and if you need to develop fixes and logic - linked to that client update, create a branch from the client update PR. - (basically treating the client update PR as the new develop) -3. Once you are done with all the changes linked to this version and the test passes, - you can merge the client update PR and proceed to release in production. - -If you need to create the PR update yourself manually to anticipate a version not release yet, -you can generate the client update using the `make client-generate` target. - -### Make a manual client update - -- Download the correct `swagger.yml` and put it at the repository's root at `./swagger.yml` -- Use `make client-generate` -- Wait for the backend release and add the correct version in `./client/version` - -Ping devops if you have any questions or doubt on the release process. - -## Add a new commands to the cli - -To add a new command you can start by verifying the api endpoint to implement in the [API docs](https://docs.cycloid.io/api/index.html). - -While you can follow this guide, I advise you to look up other implemented routes. - -### Implement the middleware method - -1. Ensure your client is up to date, if the backend version is not release yet, - see [the above section](#make-a-manual-client-update) - -2. Define the method that implements the endpoint in the middleware - - 1. Create the method in the middleware interface [here](./cmd/cycloid/middleware/middleware.go) - The naming convention of the function should reflect the naming on the API. - If you have a getComponent route on the API, the middleware should be a GetComponent function. - -> [!NOTE] -> Only exception, if a GET route list resources, we rename it to ListResource -> so the `getComponents` should be named `ListComponents`. - - 2. The function should accept all required parameters as argument in function. - a. Optional argument should be a pointer, a nil value means absent value. - b. Required values must be plain values - c. If a request has a body, use `body.Validate(strfmt.Default)` - - 3. Implement the API call either: - a. By using the generated client parameters, look any other implemented - like [getProject](./cmd/cycloid/middleware/organization_projects.go) - b. If the route can't be implemented using the client, use `net/http`. - - 4. All route should return either some data and error, or just an error: - a. Delete methods -> `return error` - b. Create/Get methods -> `return (*models.object, error)` - c. List methods -> `return ([]*models.object, error)` - - 5. Do not validate payload, it has generated too much issues in the past. - -#### Middleware testing - -Add in the middleware package a basic happy path test to ensure -that given correct parameters, the API responds. - -This is meant mostly to detect any API dift or issues. This way it will enable -developper to differenciate more easily server and client issues. - -Testing setup is done on the [TestMain function](./cmd/cycloid/middleware/middleware_test.go) -that will use the [testcfg package](./pkg/testcfg/config.go) to initialize -the backend, provision the required tools and give you all the required context -for testing (api key, org, api url, basic stuff like project/env/component, config -and catalog repo, etc...). - -Lookup how existing test are made and follow the same logic. - -### Implement the actual CLI command - -Now you need to define the cobra command at `cmd/cycloid//` so that -the method previously defined can be used in the cli. - - Each feature is structured as follows: - -```tree -./cmd/cycloid// -./cmd/cycloid//cmd.go # list and combine all the subcommands -./cmd/cycloid//get.go # each command has its own file -./cmd/cycloid//create.go -./cmd/cycloid//update.go -./cmd/cycloid//list.go -./cmd/cycloid//common.go # add common logic specific to this series of commands -``` - A feature can have subcommands in that case structure it like this: - -```tree -./cmd/cycloid// -./cmd/cycloid//cmd.go # list and combine all the subcommands -./cmd/cycloid//get.go # each command has its own file -./cmd/cycloid//create.go -./cmd/cycloid//update.go -./cmd/cycloid//list.go -./cmd/cycloid//sub_command.go # add your subcommand here, it must behave like the cmd.go file -./cmd/cycloid//sub_command_get.go # prefix all sub sub_command with the sub_command name -./cmd/cycloid//sub_command_create.go -./cmd/cycloid//common.go # add common logic specific to this series of commands -``` - -Command convention is as follow: - -`cy ` - -Example for components: -```bash -cy component create -cy component update -cy component get -cy component list -``` - -You should start by adding the type of command to the set of list of -available commands in `cmd.go` - -Then create a new file on this folder, where you will specify the method -that will return the cobra command that defines the cli command to implement -with the flags possible to use. - -Finally you define a method that will be run by this cobra command that will -take as argument the multiple flags and pass them to the middleware -interface method that you previsouly created. - -#### Implementation directives - -Use and implemant **all flags, arguments and completion definitions and functions** -in the [cyargs package](./internal/cyargs), each flag must be declared and its value -must be retrieved using a function in the cyargs package. - -Only if a flag is declared on only one specific command you can declare them locally. - -Look up how flags and completion are implemented for example [the component flag](./internal/cyargs/component.go). - -The command should: -1. Retrieve all flag -2. Process any pre-requisite (file read, default values management, etc...) -3. Do the action against the API. -4. Use the [printer](./printer/printer.go) to print the output of the API to the console - a. If no error, with valid payload => output on stdout using `cmd.OutOrStdout()` - b. If any error, print error and details on stderr using `cmd.OutOrStderr()` - -This about the UX for the command line: -- Add the completion -- Try to infer values as much as you can (use env vars, context, fetching existing values) -- Make action idempotent as much as possible -- Implement upsert (like `cy component create --update`) - -### Testing commands - -To test commands, do it in the [e2e test packages](./e2e/e2e_test.go). It has -all the required function an context for testing the command directly. - -It also uses the [testcfg package](./pkg/testcfg/config.go) to initialize -the backend, provision the required tools and give you all the required context -for testing (api key, org, api url, basic stuff like project/env/component, config -and catalog repo, etc...). - -Add tests for your command, what you should be testing: -- All basic happy path -- Test that all arguments, flags and env var works to configure your action -- Test that the output match expectations -- Try to test and catch edge cases - -As usual, look up other test commands for examples. - -Tests in CI are not executed in parallel due to some backend issues with concurrency -around git. - -### Add a changelog - -Once your changes are done, add a changelog to it: - -``` -make new-changelog-entry -``` - -## CLI local testing - -### Requirements - -To perform local test you need: -- Access to the Cycloid console on `cycloid` via the API -- A valid API key on `CY_SAAS_API_KEY` - -To start the test, login to docker to pull the backend image: - -```bash -make docker-login docker-pull -``` - -Start the local backend: - -```bash -make be-start -``` - -You can start the tests using `go test ./...` or - -```bash -make test -``` - -You can cleanup the backend with: - -```bash -make be-stop -``` - -And reset it (stop + start): -```bash -make be-reset -``` diff --git a/Makefile b/Makefile deleted file mode 100644 index f5e50dd13..000000000 --- a/Makefile +++ /dev/null @@ -1,162 +0,0 @@ -ifeq ($(GOCACHE),) - GOCACHE := $(HOME)/.cache/go-build -endif - -ifneq (, $(shell which go)) - GOCACHE := $(shell go env GOCACHE) -endif - -SHELL := /bin/sh -REPO_NAME ?= cycloid-cli -MAKEFILE_DIR := $(dir $(realpath $(lastword $(MAKEFILE_LIST)))) - -# IMAGE BUILD -BINARY ?= cy -# VERSION example v1.0.47 -VERSION ?= $(shell cat client/version) -REVISION ?= $(shell git rev-parse --short HEAD 2> /dev/null || echo 'unknown') -BRANCH ?= $(shell git rev-parse --abbrev-ref HEAD 2> /dev/null || echo 'unknown') -BUILD_ORIGIN ?= $(USER)@$(shell hostname -f) -BUILD_DATE ?= $(shell date --utc -Iseconds) -DOCKER_COMPOSE ?= $(shell docker compose --help >/dev/null 2>&1 && echo "docker compose" || echo "docker-compose") -REPO_PATH ?= github.com/cycloidio/cycloid-cli - -# GO -# Setup the -ldflags build option for go here, interpolate the variable values -GO_BUILD_FLAGS ?= -trimpath -GO_LDFLAGS ?= -ldflags \ - "-s -w\ - -X $(REPO_PATH)/internal/version.Version=$(VERSION)\ - -X $(REPO_PATH)/internal/version.Revision=$(REVISION)\ - -X $(REPO_PATH)/internal/version.Branch=$(BRANCH)\ - -X $(REPO_PATH)/internal/version.BuildOrigin=$(BUILD_ORIGIN)\ - -X $(REPO_PATH)/internal/version.BuildDate=$(BUILD_DATE)" - -# SWAGGER -SWAGGER_FILE ?= "swagger.yml" -SWAGGER_GENERATE = swagger generate client \ - --spec=$(SWAGGER_FILE) \ - --default-produces="application/vnd.cycloid.io.v1+json" \ - --target=./client \ - --name=api - --include .env --include .api_key - -.PHONY: help -help: ## Show this help - @grep -F -h "##" $(MAKEFILE_LIST) | grep -F -v fgrep | sed -e 's/:.*##/:##/' | column -t -s '##' - -.PHONY: print-version -print-version: - echo $$BACKEND_TAG - -.PHONY: install -install: .env .git/hooks/pre-commit ## install all pre-requisites - -.PHONY: .env -.env: ## generate the .env files with the required secrets for this repo - @rm .env || true - @CY_API_KEY=$${CY_SAAS_API_KEY?A valid API key to the cycloid org in our saas is required for this target. It must be provided via the CY_SAAS_API_KEY} \ - CY_API_URL=https://http-api.cycloid.io \ - CY_ORG=cycloid \ - cy uri interpolate .env.sample > .env - -source-env: ## source the local env to use cycloid - while read line; do export $$line; done < .api_key - -.PHONY: build -build: ## Build all the binaries - GO111MODULE=on CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build $(GO_BUILD_FLAGS) -o $(BINARY) $(GO_LDFLAGS) $(REPO_PATH) - GO111MODULE=on CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build $(GO_BUILD_FLAGS) -o $(BINARY)-linux-amd64 $(GO_LDFLAGS) $(REPO_PATH) - GO111MODULE=on CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build $(GO_BUILD_FLAGS) -o $(BINARY)-linux-arm64 $(GO_LDFLAGS) $(REPO_PATH) - GO111MODULE=on CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build $(GO_BUILD_FLAGS) -o $(BINARY)-windows-amd64 $(GO_LDFLAGS) $(REPO_PATH) - GO111MODULE=on CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build $(GO_BUILD_FLAGS) -o $(BINARY)-darwin-arm64 $(GO_LDFLAGS) $(REPO_PATH) - GO111MODULE=on CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build $(GO_BUILD_FLAGS) -o $(BINARY)-darwin-amd64 $(GO_LDFLAGS) $(REPO_PATH) - -.PHONY: clean -clean: test-clean - @rm -f .env - go clean - -.PHONY: test test-clean -test: ## Run end to end tests - go test ./... - -test-clean: ## Clean test cache - go clean -testcache - -.PHONY: client-delete client-generate client-generate-from-docs -client-delete: ## Resets old client folder - rm -rf ./client && mkdir -p client - -client-generate: client-delete ## Generate client from file at SWAGGER_FILE path - # Used in CI, do not use docker compose here. - echo "Creating swagger files"; \ - $(SWAGGER_GENERATE) - @# Discard the generated HTTP client package — we only keep models. - @find ./client -mindepth 1 -maxdepth 1 ! -name 'models' ! -name 'version' -exec rm -rf {} + - @export SWAGGER_VERSION=$$(python3 -c 'import yaml, sys; y = yaml.safe_load(sys.stdin); print(y["info"]["version"])' < swagger.yml); \ - if [ -z "$$SWAGGER_VERSION" ]; then echo "Unable to read version from swagger"; exit 1; fi; \ - echo $$SWAGGER_VERSION > client/version; \ - go mod tidy - -client-generate-from-docs: client-delete ## Generates client using docker and swagger from docs (version -> latest-api) - @wget -O swagger.yml https://docs.cycloid.io/api/swagger.yml - @export SWAGGER_VERSION=$$(python3 -c 'import yaml, sys; y = yaml.safe_load(sys.stdin); print(y["info"]["version"])' < swagger.yml); \ - if [ -z "$$SWAGGER_VERSION" ]; then echo "Unable to read version from swagger"; exit 1; fi; \ - echo $$SWAGGER_VERSION > client/version; \ - make client-generate && \ - echo "Please run the following git commands:"; \ - echo "git add client" && \ - echo "git commit -m 'Bump swagger client to version $$SWAGGER_VERSION'" - -.PHONY: docker-login docker-pull -docker-login: .env - echo "$(SECRET_ACCESS)" | docker login rg.fr-par.scw.cloud/cycloidio/cycloid-backend -u $(ACCESS_KEY) --password-stdin - -docker-pull: .env - docker compose pull - -.PHONY: be-start be-stop be-reset -be-start: ## start the local backend - $(DOCKER_COMPOSE) up -dV - -be-stop: ## stop the local backend - $(DOCKER_COMPOSE) down -v - -be-reset: be-stop be-start ## reset the backend - -be-db-connect: ## Connect to the local mysql - $(DOCKER_COMPOSE) exec -it database mysql -uroot -pyoudeploy youdeploy - -.PHONY: new-changelog-entry -new-changelog-entry: ## Create a new entry for unreleased element - @docker run --rm -it -v $(CURDIR):/cycloid-cli -w /cycloid-cli cycloid/cycloid-toolkit:latest changie new - -.PHONY: lint lint-go lint-sh -lint: lint-go lint-sh - -lint-sh: - @find . -type f -name '*.sh' -exec shellcheck -f gcc {} \; - -lint-go: ## Lint the source code - @golangci-lint run -v - -.PHONY: format format-go format-sh -format: format-go format-sh - -format-go: ## format the repo - @gci write --skip-generated -s standard -s default -s "prefix(github.com/cycloidio)" . > /dev/null - @goimports -w -local github.com/cycloidio . - -format-sh: - @shfmt -w . - -.PHONY: ci-test -.ONEFILE: -ci-test: - $(MAKEFILE_DIR)scripts/ci-tests.sh - -.git/hooks/pre-commit: - pre-commit-install diff --git a/README.md b/README.md index 18d383ca2..7201d8a77 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,53 @@ # Cycloid CLI (cy) -This repository hosts the source code of Cycloid command line to use Cycloid APIs. +Command-line interface for the [Cycloid](https://cycloid.io) platform. ## Installation -Precompiled binaries for released versions are available in the [release](https://github.com/cycloidio/cycloid-cli/releases) page on Github. +### Go install (recommended for developers) -Using the latest production release binary is the recommended way of installing the Cycloid CLI. +```sh +go install github.com/cycloidio/cycloid-cli@latest +``` -### In pipeline +This installs a lightweight shim that automatically downloads the correct platform binary on first run. -In a pipeline, use the [`cycloid/cycloid-toolkit`](https://hub.docker.com/r/cycloid/cycloid-toolkit) image that contains a wrapper around `cy` that will automatically download and use the correct CLI version against the Cycloid API version. +### Pre-built binaries -## Getting started +Download pre-built binaries from the [releases page](https://github.com/cycloidio/cycloid-cli/releases). -Look up the official CLI documentation [here](https://docs.cycloid.io/reference/cli/). +### In pipelines +Use the [`cycloid/cycloid-toolkit`](https://hub.docker.com/r/cycloid/cycloid-toolkit) Docker image, which includes a wrapper that automatically downloads the correct CLI version matching your Cycloid API. + +## Usage + +```sh +# First run downloads the real binary (~12 MB), then executes it +cy organizations list + +# Pin a specific version +CY_VERSION=v6.10.24 cy --version + +# Check shim version +cy --shim-version +``` + +## How it works + +The `go install` binary is a thin installer shim (~3 MB). On first run it: + +1. Determines your platform (linux/darwin/windows, amd64/arm64) +2. Downloads the matching pre-built `cy` binary from GitHub Releases +3. Caches it at `~/.cycloid/bin/cy-` +4. Exec's the real binary with all your arguments + +Subsequent runs use the cached binary directly (no network call). + +## Documentation + +Full CLI documentation: [docs.cycloid.io/reference/cli](https://docs.cycloid.io/reference/cli/) + +## License + +[MIT](LICENSE) diff --git a/changelog/releases/.gitkeep b/changelog/releases/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/changelog/releases/0.md b/changelog/releases/0.md deleted file mode 100644 index d79c95e67..000000000 --- a/changelog/releases/0.md +++ /dev/null @@ -1,45 +0,0 @@ -## [0] _2025-07-18_ - -Cycloid CLI changelog: - -### CLI -**ADDED** -- Add support for components CRUD in the CLI ([CLI#339]) -*This allows you to manipulate components using the CLI* -- Add multi platform builds ([CLI#339]) - -- Add cy project list-env command. ([CLI#342]) -*This allow to list the envs linked to a project.* -**BREAKING** -- Remove old `cy project create-env` and `cy project update-env` commands ([CLI#339]) -*Use the `cy components create` and `cy components update` commands instead.* -**CHANGED** -- Update client to version v6.0.8 ([CLI#332]) - -- Update client to version v6.0.9 ([CLI#333]) - -- Update client to version v6.0.17 ([CLI#335]) - -- Update client to version v6.0.69 ([CLI#337]) - -- Update client to version v6.0.98 ([CLI#340]) - -- Updated project / env command to the new component layer ([CLI#339]) -*As with components, what used to be env creation become components.* -- Update client to version v6.1.25 ([CLI#]) - -- Update client to version v6.0.114 ([CLI#351]) - -**FIXED** -- Migrated all project commands to component layer ([CLI#342]) - - -[CLI#339]: https://github.com/cycloidio/cycloid-cli/pull/339 -[CLI#342]: https://github.com/cycloidio/cycloid-cli/pull/342 -[CLI#332]: https://github.com/cycloidio/cycloid-cli/pull/332 -[CLI#333]: https://github.com/cycloidio/cycloid-cli/pull/333 -[CLI#335]: https://github.com/cycloidio/cycloid-cli/pull/335 -[CLI#337]: https://github.com/cycloidio/cycloid-cli/pull/337 -[CLI#340]: https://github.com/cycloidio/cycloid-cli/pull/340 -[CLI#]: https://github.com/cycloidio/cycloid-cli/pull/ -[CLI#351]: https://github.com/cycloidio/cycloid-cli/pull/351 diff --git a/changelog/releases/v3.1.47.md b/changelog/releases/v3.1.47.md deleted file mode 100644 index d70066796..000000000 --- a/changelog/releases/v3.1.47.md +++ /dev/null @@ -1,14 +0,0 @@ -## [v3.1.47] _2022-07-14_ - -Cycloid CLI changelog: - -### CLI -**ADDED** -- Now using Changie for changelog file ([CLI#142]) - -**CHANGED** -- Update client to version v3.1.47 ([CLI#143]) - - -[CLI#142]: https://github.com/cycloidio/cycloid-cli/pull/142 -[CLI#143]: https://github.com/cycloidio/cycloid-cli/pull/143 diff --git a/changelog/releases/v3.2.44.md b/changelog/releases/v3.2.44.md deleted file mode 100644 index 8d3630e9f..000000000 --- a/changelog/releases/v3.2.44.md +++ /dev/null @@ -1,13 +0,0 @@ -## [v3.2.44] _2022-11-11_ - -Cycloid CLI changelog: - -### CLI -**CHANGED** -- Update client to version v3.1.247 ([CLI#154]) - -- Update client to version v3.2.44 ([CLI#162]) - - -[CLI#154]: https://github.com/cycloidio/cycloid-cli/pull/154 -[CLI#162]: https://github.com/cycloidio/cycloid-cli/pull/162 diff --git a/changelog/releases/v3.3.26.md b/changelog/releases/v3.3.26.md deleted file mode 100644 index ffe52a608..000000000 --- a/changelog/releases/v3.3.26.md +++ /dev/null @@ -1,10 +0,0 @@ -## [v3.3.26] _2023-01-12_ - -Cycloid CLI changelog: - -### CLI -**CHANGED** -- Update client to version v3.3.26 ([CLI#171]) - - -[CLI#171]: https://github.com/cycloidio/cycloid-cli/pull/171 diff --git a/changelog/releases/v4.0.11.md b/changelog/releases/v4.0.11.md deleted file mode 100644 index 013484933..000000000 --- a/changelog/releases/v4.0.11.md +++ /dev/null @@ -1,10 +0,0 @@ -## [v4.0.11] _2023-02-09_ - -Cycloid CLI changelog: - -### CLI -**CHANGED** -- Update client to version v4.0.11 ([CLI#176]) - - -[CLI#176]: https://github.com/cycloidio/cycloid-cli/pull/176 diff --git a/changelog/releases/v4.0.133.md b/changelog/releases/v4.0.133.md deleted file mode 100644 index 263ed53d6..000000000 --- a/changelog/releases/v4.0.133.md +++ /dev/null @@ -1,13 +0,0 @@ -## [v4.0.133] _2023-05-23_ - -Cycloid CLI changelog: - -### CLI -**CHANGED** -- Update client to version v4.0.57 ([CLI#182]) - -- Update client to version v4.0.133 ([CLI#189]) - - -[CLI#182]: https://github.com/cycloidio/cycloid-cli/pull/182 -[CLI#189]: https://github.com/cycloidio/cycloid-cli/pull/189 diff --git a/changelog/releases/v4.0.162.md b/changelog/releases/v4.0.162.md deleted file mode 100644 index 59eb0d27f..000000000 --- a/changelog/releases/v4.0.162.md +++ /dev/null @@ -1,13 +0,0 @@ -## [v4.0.162] _2023-06-22_ - -Cycloid CLI changelog: - -### CLI -**CHANGED** -- Update client to version v4.0.140 ([CLI#192]) - -- Update client to version v4.0.162 ([CLI#196]) - - -[CLI#192]: https://github.com/cycloidio/cycloid-cli/pull/192 -[CLI#196]: https://github.com/cycloidio/cycloid-cli/pull/196 diff --git a/changelog/releases/v4.0.17.md b/changelog/releases/v4.0.17.md deleted file mode 100644 index 104dbcdf8..000000000 --- a/changelog/releases/v4.0.17.md +++ /dev/null @@ -1,10 +0,0 @@ -## [v4.0.17] _2023-02-13_ - -Cycloid CLI changelog: - -### CLI -**CHANGED** -- Update client to version v4.0.17 ([CLI#178]) - - -[CLI#178]: https://github.com/cycloidio/cycloid-cli/pull/178 diff --git a/changelog/releases/v4.0.178.md b/changelog/releases/v4.0.178.md deleted file mode 100644 index 3e6bb3c36..000000000 --- a/changelog/releases/v4.0.178.md +++ /dev/null @@ -1,10 +0,0 @@ -## [v4.0.178] _2023-10-26_ - -Cycloid CLI changelog: - -### CLI -**CHANGED** -- Update client to version v4.0.178 ([CLI#198]) - - -[CLI#198]: https://github.com/cycloidio/cycloid-cli/pull/198 diff --git a/changelog/releases/v4.0.20.md b/changelog/releases/v4.0.20.md deleted file mode 100644 index 89ce861fa..000000000 --- a/changelog/releases/v4.0.20.md +++ /dev/null @@ -1,10 +0,0 @@ -## [v4.0.20] _2023-02-15_ - -Cycloid CLI changelog: - -### CLI -**CHANGED** -- Update client to version v4.0.20 ([CLI#179]) - - -[CLI#179]: https://github.com/cycloidio/cycloid-cli/pull/179 diff --git a/changelog/releases/v4.0.290.md b/changelog/releases/v4.0.290.md deleted file mode 100644 index ffe7c3a3e..000000000 --- a/changelog/releases/v4.0.290.md +++ /dev/null @@ -1,13 +0,0 @@ -## [v4.0.290] _2024-01-25_ - -Cycloid CLI changelog: - -### CLI -**CHANGED** -- Update client to version v4.0.220 ([CLI#206]) - -- Update client to version v4.0.290 ([CLI#228]) - - -[CLI#206]: https://github.com/cycloidio/cycloid-cli/pull/206 -[CLI#228]: https://github.com/cycloidio/cycloid-cli/pull/228 diff --git a/changelog/releases/v4.0.295.md b/changelog/releases/v4.0.295.md deleted file mode 100644 index 83b2e2f0d..000000000 --- a/changelog/releases/v4.0.295.md +++ /dev/null @@ -1,13 +0,0 @@ -## [v4.0.295] _2024-02-01_ - -Cycloid CLI changelog: - -### CLI -**CHANGED** -- Update client to version v4.0.294 ([CLI#233]) - -- Update client to version v4.0.295 ([CLI#234]) - - -[CLI#233]: https://github.com/cycloidio/cycloid-cli/pull/233 -[CLI#234]: https://github.com/cycloidio/cycloid-cli/pull/234 diff --git a/changelog/releases/v4.0.340.md b/changelog/releases/v4.0.340.md deleted file mode 100644 index 332c4fc5d..000000000 --- a/changelog/releases/v4.0.340.md +++ /dev/null @@ -1,20 +0,0 @@ -## [v4.0.340] _2024-04-16_ - -Cycloid CLI changelog: - -### CLI -**CHANGED** -- Update client to version v4.0.340 ([CLI#253]) - -### Credentials -**ADDED** -- Added the 'update' for Credentials ([CLI#236]) - -### Other -**ADDED** -- Added more middleware methods for external backends ([CLI#254]) - - -[CLI#253]: https://github.com/cycloidio/cycloid-cli/pull/253 -[CLI#236]: https://github.com/cycloidio/cycloid-cli/pull/236 -[CLI#254]: https://github.com/cycloidio/cycloid-cli/pull/254 diff --git a/changelog/releases/v5.0.20.md b/changelog/releases/v5.0.20.md deleted file mode 100644 index 9bff5ecff..000000000 --- a/changelog/releases/v5.0.20.md +++ /dev/null @@ -1,10 +0,0 @@ -## [v5.0.20] _2024-05-16_ - -Cycloid CLI changelog: - -### CLI -**CHANGED** -- Update client to version v5.0.20 ([CLI#265]) -*Fixed external backend and list project issues associated with the upgrade* - -[CLI#265]: https://github.com/cycloidio/cycloid-cli/pull/265 diff --git a/changelog/releases/v5.0.34.md b/changelog/releases/v5.0.34.md deleted file mode 100644 index 9cfc64f44..000000000 --- a/changelog/releases/v5.0.34.md +++ /dev/null @@ -1,10 +0,0 @@ -## [v5.0.34] _2024-05-23_ - -Cycloid CLI changelog: - -### CLI -**CHANGED** -- Update client to version v5.0.34 ([CLI#267]) - - -[CLI#267]: https://github.com/cycloidio/cycloid-cli/pull/267 diff --git a/changelog/releases/v5.0.49.md b/changelog/releases/v5.0.49.md deleted file mode 100644 index 48224ff29..000000000 --- a/changelog/releases/v5.0.49.md +++ /dev/null @@ -1,15 +0,0 @@ -## [v5.0.49] _2024-06-19_ - -Cycloid CLI changelog: - -### CLI -**ADDED** -- Add a `cy stacks get-config ` to retrieve a stack default config ([CLI#277]) - -- Make `cy project create-stackforms-env` fetch default by default` ([CLI#277]) -*This behavior can be disabled with the `--no-fetch-defaults` flag* -**FIXED** -- Fix forms config parsing for stackforms related commands not sending the correct vars keys. ([CLI#277]) - - -[CLI#277]: https://github.com/cycloidio/cycloid-cli/pull/277 diff --git a/changelog/releases/v5.0.66.md b/changelog/releases/v5.0.66.md deleted file mode 100644 index e45332f13..000000000 --- a/changelog/releases/v5.0.66.md +++ /dev/null @@ -1,33 +0,0 @@ -## [v5.0.66] _2024-07-04_ - -Cycloid CLI changelog: - -### CLI -**BREAKING** -- Env var TOKEN is replaced by CY_API_KEY for giving token via env var. ([CLI#274]) -*The old `TOKEN` env var still works but emits a warning. It will be removed in a futur release.* -**CHANGED** -- Allow to create a project without an environment. ([CLI#278]) -*The env creation with the old flags still exists, but is now deprecated and will be removed in a further release.* -- Allow to use CY_ORG env var to define the current org instead of --org flag ([CLI#274]) -*You can still use the --org flag, the CLI flag will have precedence over the env var.* -- Update client to version v5.0.66 ([CLI#279]) - -**FIXED** -- Fix version for release ([CLI#269]) - -- Remove API validation on bad playload from API for catalog repository refresh ([CLI#278]) - -- --org flag is now global ([CLI#274]) -*This fixes inconsistency between commands, you can also set the org via env vars now.* -**SECURITY** -- Make the configuration write as 0600 permissions in user home config ([CLI#274]) - -- Allow to login using CY_API_TOKEN instead of providing the token via --api-token flag ([CLI#274]) -*This will become the default way, using the flag will be deprecated in the future.* - -[CLI#274]: https://github.com/cycloidio/cycloid-cli/pull/274 -[CLI#278]: https://github.com/cycloidio/cycloid-cli/pull/278 -[CLI#279]: https://github.com/cycloidio/cycloid-cli/pull/279 -[CLI#269]: https://github.com/cycloidio/cycloid-cli/pull/269 - diff --git a/changelog/releases/v5.1.134.md b/changelog/releases/v5.1.134.md deleted file mode 100644 index a3a92ee36..000000000 --- a/changelog/releases/v5.1.134.md +++ /dev/null @@ -1,89 +0,0 @@ -## [v5.1.134] _2024-12-10_ - -Cycloid CLI changelog: - -### CLI -**BREAKING** -- create-env uses now stackforms by default ([CLI#313]) -*the old create-env logic will apply if you give the legacy flags, but they won't be advertised anymore on the CLI.* -**CHANGED** -- Update client to version v5.1.10 ([CLI#290]) - -- Update client to version v5.1.14 ([CLI#291]) - -- Update client to version v5.1.15 ([CLI#292]) - -- Update client to version v5.1.26 ([CLI#293]) - -- Update client to version v5.1.30 ([CLI#294]) - -- Update client to version v5.1.31 ([CLI#295]) - -- Update client to version v5.1.35 ([CLI#296]) - -- Update client to version v5.1.43 ([CLI#297]) - -- Update client to version v5.1.56 ([CLI#302]) - -- Update client to version v5.1.58 ([CLI#303]) - -- Update client to version v5.1.61 ([CLI#304]) - -- Update client to version v5.1.67 ([CLI#305]) - -- Update client to version v5.1.76 ([CLI#306]) - -- Update client to version v5.1.98 ([CLI#308]) - -- Update client to version v5.1.102 ([CLI#309]) - -- Update client to version v5.1.116 ([CLI#311]) - -- Update client to version v5.1.124 ([CLI#312]) - -- Update client to version v5.1.129 ([CLI#314]) - -- Update client to version v5.1.130 ([CLI#315]) - -- Update client to version v5.1.134 ([CLI#316]) - -**FIXED** -- Cycloid CLI now correctly uses CY_API_KEY env var instead of CY_API_TOKEN. ([CLI#299]) -*Old env vars still works, TOKEN and CY_API_TOKEN will be deprecated on the future.* -- Fixed bugs related to the API update ([CLI#313]) -*CLI should behave as expected now.* -- Fixed an issue where stackforms vars input precedence was not respected on certain types ([CLI#313]) - -- Fixed inconsistency on --org and CY_ORG parameter ([CLI#313]) - -### Other -**ADDED** -- Added linter for the CLI code ([CLI#285]) - -- Added go code formatter ([CLI#286]) - - -[CLI#313]: https://github.com/cycloidio/cycloid-cli/pull/313 -[CLI#290]: https://github.com/cycloidio/cycloid-cli/pull/290 -[CLI#291]: https://github.com/cycloidio/cycloid-cli/pull/291 -[CLI#292]: https://github.com/cycloidio/cycloid-cli/pull/292 -[CLI#293]: https://github.com/cycloidio/cycloid-cli/pull/293 -[CLI#294]: https://github.com/cycloidio/cycloid-cli/pull/294 -[CLI#295]: https://github.com/cycloidio/cycloid-cli/pull/295 -[CLI#296]: https://github.com/cycloidio/cycloid-cli/pull/296 -[CLI#297]: https://github.com/cycloidio/cycloid-cli/pull/297 -[CLI#302]: https://github.com/cycloidio/cycloid-cli/pull/302 -[CLI#303]: https://github.com/cycloidio/cycloid-cli/pull/303 -[CLI#304]: https://github.com/cycloidio/cycloid-cli/pull/304 -[CLI#305]: https://github.com/cycloidio/cycloid-cli/pull/305 -[CLI#306]: https://github.com/cycloidio/cycloid-cli/pull/306 -[CLI#308]: https://github.com/cycloidio/cycloid-cli/pull/308 -[CLI#309]: https://github.com/cycloidio/cycloid-cli/pull/309 -[CLI#311]: https://github.com/cycloidio/cycloid-cli/pull/311 -[CLI#312]: https://github.com/cycloidio/cycloid-cli/pull/312 -[CLI#314]: https://github.com/cycloidio/cycloid-cli/pull/314 -[CLI#315]: https://github.com/cycloidio/cycloid-cli/pull/315 -[CLI#316]: https://github.com/cycloidio/cycloid-cli/pull/316 -[CLI#299]: https://github.com/cycloidio/cycloid-cli/pull/299 -[CLI#285]: https://github.com/cycloidio/cycloid-cli/pull/285 -[CLI#286]: https://github.com/cycloidio/cycloid-cli/pull/286 diff --git a/changelog/releases/v5.1.144.md b/changelog/releases/v5.1.144.md deleted file mode 100644 index 14cf7dc1d..000000000 --- a/changelog/releases/v5.1.144.md +++ /dev/null @@ -1,10 +0,0 @@ -## [v5.1.144] _2024-12-12_ - -Cycloid CLI changelog: - -### CLI -**ADDED** -- Add `cy event list` for listing events ([CLI#324]) -*This is a basic implementation of the getEvents API endpoint.* - -[CLI#324]: https://github.com/cycloidio/cycloid-cli/pull/324 diff --git a/changelog/releases/v5.1.151.md b/changelog/releases/v5.1.151.md deleted file mode 100644 index cf3b1022f..000000000 --- a/changelog/releases/v5.1.151.md +++ /dev/null @@ -1,18 +0,0 @@ -## [v5.1.151] _2025-03-03_ - -Cycloid CLI changelog: - -### CLI -**CHANGED** -- cy project create-env / update-env --var (-V) flag now support explicit quoting of strings ([CLI#330]) -*Users can now use the -V `section.group.string="mystring"` to explicitely quote strings that could be misinterpreted as numbers or booleans.* -**FIXED** -- cy project create-env/update-env now correctly support all value update types with --var (-V) flag ([CLI#323]) -*Previously, all value would have been treated as string, we now support all native types (int, float, bool, string) and valid JSON (array and objects).* -- Fixed bugs in variable updates on environment update ([CLI#323]) - -- Fixed cy project get-env command returning null or invalid config. ([CLI#330]) - - -[CLI#330]: https://github.com/cycloidio/cycloid-cli/pull/330 -[CLI#323]: https://github.com/cycloidio/cycloid-cli/pull/323 diff --git a/changelog/releases/v5.1.153.md b/changelog/releases/v5.1.153.md deleted file mode 100644 index a1f43035a..000000000 --- a/changelog/releases/v5.1.153.md +++ /dev/null @@ -1,13 +0,0 @@ -## [v5.1.153] _2025-03-13_ - -Cycloid CLI changelog: - -### CLI -**ADDED** -- Add `cy pipeline last-used` command ([CLI#334]) -*This command allows you to list pipelines not triggered since x days.* -**CHANGED** -- `cy stack update` only manage visibility and team settings now. ([CLI#334]) -*This is on par with our stack visibility update. see changelog for Cycloid v5.1.153.* - -[CLI#334]: https://github.com/cycloidio/cycloid-cli/pull/334 diff --git a/changelog/releases/v5.1.9.md b/changelog/releases/v5.1.9.md deleted file mode 100644 index 8b9577601..000000000 --- a/changelog/releases/v5.1.9.md +++ /dev/null @@ -1,10 +0,0 @@ -## [v5.1.9] _2024-07-15_ - -Cycloid CLI changelog: - -### Members -**CHANGED** -- Updated members commands to fit the recent endpoints changes. ([CLI#270]) - - -[CLI#270]: https://github.com/cycloidio/cycloid-cli/pull/270 diff --git a/changelog/releases/v6.10.24.md b/changelog/releases/v6.10.24.md deleted file mode 100644 index 440fa61a9..000000000 --- a/changelog/releases/v6.10.24.md +++ /dev/null @@ -1,10 +0,0 @@ -## [v6.10.24] _2026-05-27_ - -Cycloid CLI changelog: - -### Environments -**ADDED** -- Org-scoped environment management commands: `cy environment`, `cy cloud-account`, and `cy environment-type` ([CLI#445]) -*New commands let you create, update, get, list, and delete org-level environments (decoupled from pipelines), attach cloud accounts, set environment types, and link/unlink environments to projects. Environment type on create is now optional — the API auto-detects it from canonical keywords.* - -[CLI#445]: https://github.com/cycloidio/cycloid-cli/pull/445 diff --git a/changelog/releases/v6.10.25.md b/changelog/releases/v6.10.25.md deleted file mode 100644 index 1f07e87bd..000000000 --- a/changelog/releases/v6.10.25.md +++ /dev/null @@ -1,10 +0,0 @@ -## [v6.10.25] _2026-06-19_ - -Cycloid CLI changelog: - -### Authentication -**ADDED** -- OIDC group mapping commands: `cy oidc mappings`, `cy oidc settings`, and `cy oidc integration` ([CLI#452]) -*Manage OIDC-driven org access from the CLI: map IdP group claims to teams (`cy oidc mappings create|list|delete`), configure per-org reconciliation (`cy oidc settings set` — default role, oidc-managed mode, no-match policy), and set up the OIDC SSO integration including the groups claim name (`cy oidc integration set`).* - -[CLI#452]: https://github.com/cycloidio/cycloid-cli/pull/452 diff --git a/changelog/releases/v6.10.8.md b/changelog/releases/v6.10.8.md deleted file mode 100644 index fbf58f94a..000000000 --- a/changelog/releases/v6.10.8.md +++ /dev/null @@ -1,40 +0,0 @@ -## [v6.10.8] _2026-05-24_ - -Cycloid CLI changelog: - -### CLI -**ADDED** -- `cy plugin registry plugin version install --retry` to idempotently install a plugin version ([CLI#432]) -*Adds `--retry` flag to `cy plugin registry plugin version install`. When the install returns HTTP 409 (already installed), the command retries via the retry endpoint instead of failing. Safe for use in CI/CD pipelines.* -- `cy plugin registry plugin version publish --docker-image` to publish Docker image-based plugin versions ([CLI#426]) -*Adds `--docker-image` as a mutually exclusive alternative to `--url` in the version publish command. Accepts Docker image references (e.g. `registry:5000/org/plugin:tag`) that are not valid URIs, which the existing `--url` flag rejects.* -- `--stack-version` flag on `cy component create`, `cy component update`, `cy stacks get-config`, and `cy beta config interpolate` unifies stack version selection. Accepts a bare value (auto-detected as tag, branch, or commit hash) or an explicit type prefix: `tag:`, `branch:`, `sha:`. Shell completion is prefix-aware: `--stack-version=tag:` lists tags only. ([CLI#]) -*Bare values are resolved via ListStackVersions with precedence tag > branch > commit-hash-prefix (min 7 chars). Collisions between a tag and branch of the same name produce an actionable error with prefix-form hints. Prefixed values require no API call.* -- Added delete options (skip-hooks, ignore-config-files-err) to delete component/environment/project ([CLI#440]) - -- Added `cy organization licence activate` and `cy organization licence get` commands ([CLI#]) - -**CHANGED** -- `--output` now supports table column selection, jq expressions, and field extraction ([CLI#999]) -*Extended `--output` grammar: `table=col1,col2` selects specific columns; `table:noheader` suppresses the header row; `jq=` runs an arbitrary jq expression over the full JSON response; any other value (e.g. `canonical`, `owner.username`) extracts that field, one value per line. A `--jq ` flag was added as shorthand for `-o jq=`. Shell completion for `--output` is now model-aware: `cy project list -o ` suggests model fields alongside `json`, `yaml`, `table`, and `jq=`. Pipe pattern enabled: `cy project delete $(cy project list -o canonical)`. Default table columns are curated per resource (e.g. projects show Canonical, Name, Description, Owner).* -- Table output has been reworked: configurable borders, dynamic column expansion, and persistent default output format ([CLI#999]) -*The default table uses a kubectl-style separator (─) between header and rows. A new `table:border` option switches to nushell-style rounded-border grid (`╭─┬─╮`). On wide terminals, extra struct fields are shown beyond the curated defaults; as the terminal narrows, extra columns are dropped first while curated columns are preserved. Nested structs render as `{record N fields}` instead of the type name. A new `cy output set ` command persists the default output format to `~/.config/cycloid-cli/config.yaml`; `cy output get` shows the current effective value; `cy output reset` clears it. The `CY_OUTPUT` environment variable sets the default at runtime. Priority: `--jq` > `--output` > `CY_OUTPUT` > `cy output set` > `table`.* -- `cy beta plugin` commands promoted to top-level `cy plugin` ([CLI#426]) -*Plugin management commands are no longer experimental. `cy beta plugin` is removed; use `cy plugin` instead. This release also adds `cy plugin registry update`, `cy plugin registry plugin update`, `cy plugin component list/relation-set`, `cy plugin widget list/query`, and `cy plugin component widget list/query`.* -**DEPRECATED** -- `--stack-tag`, `--stack-branch`, and `--stack-commit-hash` flags are deprecated in favour of `--stack-version`. They remain functional and will be removed in the next major release. ([CLI#]) -*Migrate: --stack-tag=v1.0.0 → --stack-version=tag:v1.0.0 | --stack-branch=main → --stack-version=branch:main | --stack-commit-hash=abc123 → --stack-version=sha:abc123* -**FIXED** -- `cy plugin manager create` now fully registers the plugin manager instead of leaving an unresolvable pending invitation ([CLI#443]) -*Previously the create command sent the invitation-only request, producing an `invite_pending` row that the Plugin Manager never received and that could not be accepted or deleted. The command now sends `auto_register: true` so the Plugin Manager is contacted and activated in one step.* -### Pipelines Overview -**ADDED** -- `cy pipeline builds logs` and `cy pipeline job logs` to stream build event logs from past and in-progress builds ([CLI#426]) -*`builds logs --build-id ` dumps the event log for a specific build (or tails it with `--watch`). `job logs` fetches the latest build's logs for a job; with `--watch` it continuously tails future builds as they start, polling at a configurable `--poll-interval`.* - -[CLI#432]: https://github.com/cycloidio/cycloid-cli/pull/432 -[CLI#426]: https://github.com/cycloidio/cycloid-cli/pull/426 -[CLI#]: https://github.com/cycloidio/cycloid-cli/pull/ -[CLI#440]: https://github.com/cycloidio/cycloid-cli/pull/440 -[CLI#999]: https://github.com/cycloidio/cycloid-cli/pull/999 -[CLI#443]: https://github.com/cycloidio/cycloid-cli/pull/443 diff --git a/changelog/releases/v6.2.112.md b/changelog/releases/v6.2.112.md deleted file mode 100644 index b7a186cca..000000000 --- a/changelog/releases/v6.2.112.md +++ /dev/null @@ -1,10 +0,0 @@ -## [v6.2.112] _2025-09-23_ - -Cycloid CLI changelog: - -### CLI -**INTERNAL** -- Add support for new component creation logic (creation + config split + PUT) ([CLI#385]) - - -[CLI#385]: https://github.com/cycloidio/cycloid-cli/pull/385 diff --git a/changelog/releases/v6.2.43.md b/changelog/releases/v6.2.43.md deleted file mode 100644 index ca66b759f..000000000 --- a/changelog/releases/v6.2.43.md +++ /dev/null @@ -1,43 +0,0 @@ -## [v6.2.43] _2025-07-23_ - -Cycloid CLI changelog: - -### CLI -**ADDED** -- Add completion for --color and --icon flags ([CLI#354]) - -- Added flag completion to the CLI ([CLI#356]) -*The CLI is now able to complete most arguments, fetching resources from the API still requires auth.* -- Add `cy api-key create` command ([CLI#360]) - -- Add `cy credential create --update` flag ([CLI#367]) - -**BREAKING** -- Pipeline subcommand are renamed to follow convention ([CLI#358]) -*build related command are now in the subcommand `cy pipeline build` and jobs are in `cy pipeline jobs` subcommand.* -**CHANGED** -- Make the CLI pick a random icon/color with sane defaults for envs if not set by the user. ([CLI#354]) - -- cy credential get|delete accept now cred canonicals as argument. ([CLI#367]) -*flags have the priority on precedence.* -- Update client to version v6.2.43 ([CLI#372]) - -**FIXED** -- Project and env updates will persist current icon / color instead of using the default one if not set by the user. ([CLI#354]) - -- Update pipelines commands to work with components layer ([CLI#358]) - -- Fixed CLI version ([CLI#369]) - -**REMOVED** -- Removed the version warning on each commands ([CLI#364]) - - -[CLI#354]: https://github.com/cycloidio/cycloid-cli/pull/354 -[CLI#356]: https://github.com/cycloidio/cycloid-cli/pull/356 -[CLI#360]: https://github.com/cycloidio/cycloid-cli/pull/360 -[CLI#367]: https://github.com/cycloidio/cycloid-cli/pull/367 -[CLI#358]: https://github.com/cycloidio/cycloid-cli/pull/358 -[CLI#372]: https://github.com/cycloidio/cycloid-cli/pull/372 -[CLI#369]: https://github.com/cycloidio/cycloid-cli/pull/369 -[CLI#364]: https://github.com/cycloidio/cycloid-cli/pull/364 diff --git a/changelog/releases/v6.2.62.md b/changelog/releases/v6.2.62.md deleted file mode 100644 index a1cea1d34..000000000 --- a/changelog/releases/v6.2.62.md +++ /dev/null @@ -1,34 +0,0 @@ -## [v6.2.62] _2025-08-21_ - -Cycloid CLI changelog: - -### CLI -**ADDED** -- Add `cy stack create` ([CLI#373]) -*This command allow you to create a stack with our Blueprint feature: https://docs.cycloid.io/reference/stack-blueprint/#using-a-blueprint* -**CHANGED** -- Move child org creation to the `cy org create --name --parent-canonical ` ([CLI#375]) -*This will give more clarity to the child org creation process. Deprecating the `cy org create-child` command.* -- `cy credential create` now requires the `--canonical` flag ([CLI#380]) - -- Update client to version v6.2.62 ([CLI#381]) - -**DEPRECATED** -- `cy org create-child` command is officially deprecated, replaced by `cy org create --name --parent-canonical ` ([CLI#375]) -*This command was confusing and non standard.* -**FIXED** -- `cy comp create --var`: Fixed trailling quote when forcing string type with single quotes `'` ([CLI#377]) - -- Fixed a bug where create commands with `--update` flag would misbehave on API error ([CLI#382]) -*In some cases, like a 5xx from the API, the CLI would try to update a non-existent resource and fail to report the correct error message.* -**INTERNAL** -- Removed payload validation ([CLI#378]) - - -[CLI#373]: https://github.com/cycloidio/cycloid-cli/pull/373 -[CLI#375]: https://github.com/cycloidio/cycloid-cli/pull/375 -[CLI#380]: https://github.com/cycloidio/cycloid-cli/pull/380 -[CLI#381]: https://github.com/cycloidio/cycloid-cli/pull/381 -[CLI#377]: https://github.com/cycloidio/cycloid-cli/pull/377 -[CLI#382]: https://github.com/cycloidio/cycloid-cli/pull/382 -[CLI#378]: https://github.com/cycloidio/cycloid-cli/pull/378 diff --git a/changelog/releases/v6.3.3.md b/changelog/releases/v6.3.3.md deleted file mode 100644 index 283279e62..000000000 --- a/changelog/releases/v6.3.3.md +++ /dev/null @@ -1,13 +0,0 @@ -## [v6.3.3] _2025-09-29_ - -Cycloid CLI changelog: - -### CLI -**CHANGED** -- Update client to version v6.3.2 ([CLI#388]) - -- Update client to version v6.3.3 ([CLI#390]) - - -[CLI#388]: https://github.com/cycloidio/cycloid-cli/pull/388 -[CLI#390]: https://github.com/cycloidio/cycloid-cli/pull/390 diff --git a/changelog/releases/v6.4.1.md b/changelog/releases/v6.4.1.md deleted file mode 100644 index 4f571ac6a..000000000 --- a/changelog/releases/v6.4.1.md +++ /dev/null @@ -1,13 +0,0 @@ -## [v6.4.1] _2025-10-03_ - -Cycloid CLI changelog: - -### CLI -**CHANGED** -- Update client to version v6.3.9 ([CLI#391]) - -- Update client to version v6.4.1 ([CLI#393]) - - -[CLI#391]: https://github.com/cycloidio/cycloid-cli/pull/391 -[CLI#393]: https://github.com/cycloidio/cycloid-cli/pull/393 diff --git a/changelog/releases/v6.7.16.md b/changelog/releases/v6.7.16.md deleted file mode 100644 index 940ca1276..000000000 --- a/changelog/releases/v6.7.16.md +++ /dev/null @@ -1,14 +0,0 @@ -## [v6.7.16] _2026-02-03_ - -Cycloid CLI changelog: - -### CLI -**ADDED** -- Add support for common proxy env vars (`HTTP_PROXY`, `HTTPS_PROXY`, `NO_PROXY`) ([CLI#405]) - -**CHANGED** -- Update client to version v6.7.16 ([CLI#403]) - - -[CLI#405]: https://github.com/cycloidio/cycloid-cli/pull/405 -[CLI#403]: https://github.com/cycloidio/cycloid-cli/pull/403 diff --git a/changelog/releases/v6.7.2.md b/changelog/releases/v6.7.2.md deleted file mode 100644 index 28fda0d6b..000000000 --- a/changelog/releases/v6.7.2.md +++ /dev/null @@ -1,24 +0,0 @@ -## [v6.7.2] _2026-01-14_ - -Cycloid CLI changelog: - -### CLI -**ADDED** -- Add cycloid uri schema commands `cy get` and `cy uri interpolate` ([CLI#383]) -*Those commands allows you to fetch and inject values from Cycloid in files.* -**CHANGED** -- Update user registration and login to support new API schema ([CLI#]) -*User registration now uses full_name instead of separate given_name/family_name fields. Username is now optional. Login now only accepts email (username parameter removed).* -- Update client to version v6.7.2 ([CLI#401]) - -**FIXED** -- Make interpolator output consistent regarding trailling newlines ([CLI#395]) -*All output will end with a newline.* -- Fixed cases where component update would error on non-configured components ([CLI#396]) - - -[CLI#383]: https://github.com/cycloidio/cycloid-cli/pull/383 -[CLI#]: https://github.com/cycloidio/cycloid-cli/pull/ -[CLI#401]: https://github.com/cycloidio/cycloid-cli/pull/401 -[CLI#395]: https://github.com/cycloidio/cycloid-cli/pull/395 -[CLI#396]: https://github.com/cycloidio/cycloid-cli/pull/396 diff --git a/changelog/releases/v6.7.3.md b/changelog/releases/v6.7.3.md deleted file mode 100644 index 32cd533c3..000000000 --- a/changelog/releases/v6.7.3.md +++ /dev/null @@ -1,14 +0,0 @@ -## [v6.7.3] _2026-01-15_ - -Cycloid CLI changelog: - -### CLI -**ADDED** -- Add support for stack versioning ([CLI#399]) - -**FIXED** -- Fixed component version inference ([CLI#402]) -*Version by default will fallback to branch unless specified.* - -[CLI#399]: https://github.com/cycloidio/cycloid-cli/pull/399 -[CLI#402]: https://github.com/cycloidio/cycloid-cli/pull/402 diff --git a/changelog/releases/v6.7.38.md b/changelog/releases/v6.7.38.md deleted file mode 100644 index b47a70f37..000000000 --- a/changelog/releases/v6.7.38.md +++ /dev/null @@ -1,10 +0,0 @@ -## [v6.7.38] _2026-02-05_ - -Cycloid CLI changelog: - -### CLI -**CHANGED** -- Update client to version v6.7.38 ([CLI#406]) - - -[CLI#406]: https://github.com/cycloidio/cycloid-cli/pull/406 diff --git a/changelog/releases/v6.7.48.md b/changelog/releases/v6.7.48.md deleted file mode 100644 index 10a110aa7..000000000 --- a/changelog/releases/v6.7.48.md +++ /dev/null @@ -1,14 +0,0 @@ -## [v6.7.48] _2026-02-19_ - -Cycloid CLI changelog: - -### CLI -**ADDED** -- Update teams commands and added member management commands ([CLI#411]) -*Lookup `cy team --help` and `cy team members --help` commands* -**CHANGED** -- Update client to version v6.7.48 ([CLI#407]) - - -[CLI#411]: https://github.com/cycloidio/cycloid-cli/pull/411 -[CLI#407]: https://github.com/cycloidio/cycloid-cli/pull/407 diff --git a/changelog/releases/v6.7.57.md b/changelog/releases/v6.7.57.md deleted file mode 100644 index 1bd43b9de..000000000 --- a/changelog/releases/v6.7.57.md +++ /dev/null @@ -1,13 +0,0 @@ -## [v6.7.57] _2026-02-27_ - -Cycloid CLI changelog: - -### CLI -**ADDED** -- Add `cy organization subscription update` command to register a subscription to an organization. ([CLI#410]) - -**CHANGED** -- Update client to version v6.7.57 ([CLI#410]) - - -[CLI#410]: https://github.com/cycloidio/cycloid-cli/pull/410 diff --git a/changelog/releases/v6.8.23.md b/changelog/releases/v6.8.23.md deleted file mode 100644 index 0461e46be..000000000 --- a/changelog/releases/v6.8.23.md +++ /dev/null @@ -1,40 +0,0 @@ -## [v6.8.23] _2026-04-01_ - -Cycloid CLI changelog: - -### CLI -**ADDED** -- `debug` verbosity level will now dump the content of the HTTP requests and response with the API ([CLI#418]) -*This is usefull to debug errors with the backend. Be warned that playload -may include sensitive values for e.g. credentials. Be careful in uses in CI/CD. -* -- `cy roles update` and `cy roles create --update` commands ([CLI#423]) -*Add also a `cy role` alias* -- **Beta:** `cy pipeline build trigger --watch` streams Concourse build events with human-readable output, optional raw JSON via `--output json`, and debug-verbosity event detail ([CLI#420]) -*Beta feature: watch polls until the build finishes while printing formatted SSE lines (or NDJSON when `--output json`). -Includes default console deep link (`https://console.cycloid.io`, overridable with `CY_CONSOLE_URL`), stderr hints for Ctrl+C (first aborts the build, second exits watch with code 130), `--watch-cancel-on-timeout`, and `--job` required on trigger. -Set `--verbosity debug` for verbose watch output. See `docs/pipeline-build-watch-output.md`. -* -- Add `--update` to `organization create`, `config-repo create`, `catalog-repo create`, and `stack create`; fix `team create --update` when only `--name` is set ([CLI#420]) -*Catalog-repo create accepts optional `--canonical` for identity. AGENTS.md and CLAUDE.md require shipping tests with each feature. E2E and docs/testing.md cover upsert flows.* -- Project and environment create can infer missing canonicals from `--name` when appropriate ([CLI#420]) - -**CHANGED** -- API errors may include the request path and a raw response body fallback when JSON error parsing fails ([CLI#420]) - -- Environment create picks a random theme color when `--color` is left at the default ([CLI#420]) - -- Regenerate API client models; `client/version` set to v6.8.22 ([CLI#420]) - -**FIXED** -- Improve help examples for pipeline job commands and `stack forms validate` ([CLI#420]) - -- `cy credentials create --update` resolves an existing credential by path/name instead of always attempting a create ([CLI#420]) - -**INTERNAL** -- Refactor middleware out of go-swagger client ([CLI#418]) - - -[CLI#418]: https://github.com/cycloidio/cycloid-cli/pull/418 -[CLI#423]: https://github.com/cycloidio/cycloid-cli/pull/423 -[CLI#420]: https://github.com/cycloidio/cycloid-cli/pull/420 diff --git a/changelog/releases/v6.9.9.md b/changelog/releases/v6.9.9.md deleted file mode 100644 index fb0b3d627..000000000 --- a/changelog/releases/v6.9.9.md +++ /dev/null @@ -1,34 +0,0 @@ -## [v6.9.9] _2026-05-01_ - -Cycloid CLI changelog: - -### API Keys -**ADDED** -- `api-key create --recreate` flag to delete-and-recreate an existing key in one step ([CLI#999]) -*Without `--recreate`, creating an API key that already exists now fails with an explicit error instead of silently succeeding or failing. With `--recreate`, the existing key is deleted and a new one is created with the provided settings. Useful for rotating keys in automation.* -### CLI -**CHANGED** -- get/delete commands now accept resource canonicals as positional arguments ([CLI#999]) -*Affected commands: `catalog-repo get/delete/refresh`, `config-repo get/delete`, `api-key get/delete`, `project get/delete`. The previous `--canonical` / `--project` flags are still accepted for backward compatibility. Example: `cy catalog-repo get my-repo` instead of `cy catalog-repo get --canonical my-repo`. Multiple args are supported: `cy catalog-repo delete repo-a repo-b`.* -- Shell completion improvements across all normalized commands ([CLI#999]) -*get/delete commands now complete resource canonicals from the API. `stack forms validate` completion is restricted to `.yml` / `.yaml` files only. `members` command gains `member` alias; `events` `e` alias removed (was conflicting with `environments`).* -**FIXED** -- `cy component update` without `--stack-branch`/`--stack-tag`/`--stack-commit-hash` no longer resets the stack version to the catalog default ([CLI#427]) - -**REMOVED** -- `infra-policy` commands removed (get, list, create, update, delete, validate) ([CLI#999]) -*The infra-policy feature has been dropped from the CLI. Remove any scripts using `cy infra-policy` commands.* -### Service Catalog -**ADDED** -- `catalog-repo refresh` now accepts multiple repository canonicals at once ([CLI#999]) -*Refresh several catalog repositories in a single command: `cy catalog-repo refresh repo-a repo-b repo-c`. Previously only one canonical was accepted.* -### StackForms -**CHANGED** -- `stack forms validate` accepts multiple files and defaults to `.forms.yml` / `.forms.yaml` in the current directory ([CLI#999]) -*Running `cy stack forms validate` with no arguments now auto-discovers `.forms.yml` or `.forms.yaml` in the current directory. Multiple files can be validated at once: `cy stack forms validate .forms.yml other/.forms.yaml`. The command now exits with a non-zero status code when validation errors are found, making it usable in CI pipelines.* -**FIXED** -- `stack get-config ` positional argument now works correctly ([CLI#999]) -*Passing the use-case as a positional argument (e.g. `cy stack get-config -p proj -e env -c comp my-usecase`) was silently ignored and produced a "missing use-case argument" error. The `--use-case` flag is still supported.* - -[CLI#999]: https://github.com/cycloidio/cycloid-cli/pull/999 -[CLI#427]: https://github.com/cycloidio/cycloid-cli/pull/427 diff --git a/changelog/unreleased/.gitkeep b/changelog/unreleased/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/client/models/infra_import.go b/client/models/infra_import.go deleted file mode 100644 index 9e16d521d..000000000 --- a/client/models/infra_import.go +++ /dev/null @@ -1,250 +0,0 @@ -// Code generated by go-swagger; DO NOT EDIT. - -package models - -import ( - "context" - "encoding/json" - - "github.com/go-openapi/errors" - "github.com/go-openapi/strfmt" - "github.com/go-openapi/swag" - "github.com/go-openapi/validate" -) - -// InfraImport Infra Import -// -// The entity which represents the information of for the import of a new Stack or Project. -// -// swagger:model InfraImport -type InfraImport struct { - - // component canonical - // Max Length: 100 - // Min Length: 1 - // Pattern: ^[\da-zA-Z]+(?:(?:[\da-zA-Z\-._]+)?[\da-zA-Z])?$ - ComponentCanonical string `json:"component_canonical,omitempty"` - - // environment canonical - // Max Length: 100 - // Min Length: 1 - // Pattern: ^[\da-zA-Z]+(?:(?:[\da-zA-Z\-._]+)?[\da-zA-Z])?$ - EnvironmentCanonical string `json:"environment_canonical,omitempty"` - - // error - // Required: true - Error *string `json:"error"` - - // logs - // Required: true - Logs *string `json:"logs"` - - // project canonical - // Max Length: 100 - // Min Length: 1 - // Pattern: (^[a-z0-9]+(([a-z0-9\-_]+)?[a-z0-9]+)?$) - ProjectCanonical string `json:"project_canonical,omitempty"` - - // It's the ref of the Service Catalog, like 'cycloidio:stack-magento' - // Required: true - ServiceCatalogRef *string `json:"service_catalog_ref"` - - // The import process status. - // Required: true - // Enum: ["succeeded","failed","importing"] - Status *string `json:"status"` -} - -// Validate validates this infra import -func (m *InfraImport) Validate(formats strfmt.Registry) error { - var res []error - - if err := m.validateComponentCanonical(formats); err != nil { - res = append(res, err) - } - - if err := m.validateEnvironmentCanonical(formats); err != nil { - res = append(res, err) - } - - if err := m.validateError(formats); err != nil { - res = append(res, err) - } - - if err := m.validateLogs(formats); err != nil { - res = append(res, err) - } - - if err := m.validateProjectCanonical(formats); err != nil { - res = append(res, err) - } - - if err := m.validateServiceCatalogRef(formats); err != nil { - res = append(res, err) - } - - if err := m.validateStatus(formats); err != nil { - res = append(res, err) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (m *InfraImport) validateComponentCanonical(formats strfmt.Registry) error { - if swag.IsZero(m.ComponentCanonical) { // not required - return nil - } - - if err := validate.MinLength("component_canonical", "body", m.ComponentCanonical, 1); err != nil { - return err - } - - if err := validate.MaxLength("component_canonical", "body", m.ComponentCanonical, 100); err != nil { - return err - } - - if err := validate.Pattern("component_canonical", "body", m.ComponentCanonical, `^[\da-zA-Z]+(?:(?:[\da-zA-Z\-._]+)?[\da-zA-Z])?$`); err != nil { - return err - } - - return nil -} - -func (m *InfraImport) validateEnvironmentCanonical(formats strfmt.Registry) error { - if swag.IsZero(m.EnvironmentCanonical) { // not required - return nil - } - - if err := validate.MinLength("environment_canonical", "body", m.EnvironmentCanonical, 1); err != nil { - return err - } - - if err := validate.MaxLength("environment_canonical", "body", m.EnvironmentCanonical, 100); err != nil { - return err - } - - if err := validate.Pattern("environment_canonical", "body", m.EnvironmentCanonical, `^[\da-zA-Z]+(?:(?:[\da-zA-Z\-._]+)?[\da-zA-Z])?$`); err != nil { - return err - } - - return nil -} - -func (m *InfraImport) validateError(formats strfmt.Registry) error { - - if err := validate.Required("error", "body", m.Error); err != nil { - return err - } - - return nil -} - -func (m *InfraImport) validateLogs(formats strfmt.Registry) error { - - if err := validate.Required("logs", "body", m.Logs); err != nil { - return err - } - - return nil -} - -func (m *InfraImport) validateProjectCanonical(formats strfmt.Registry) error { - if swag.IsZero(m.ProjectCanonical) { // not required - return nil - } - - if err := validate.MinLength("project_canonical", "body", m.ProjectCanonical, 1); err != nil { - return err - } - - if err := validate.MaxLength("project_canonical", "body", m.ProjectCanonical, 100); err != nil { - return err - } - - if err := validate.Pattern("project_canonical", "body", m.ProjectCanonical, `(^[a-z0-9]+(([a-z0-9\-_]+)?[a-z0-9]+)?$)`); err != nil { - return err - } - - return nil -} - -func (m *InfraImport) validateServiceCatalogRef(formats strfmt.Registry) error { - - if err := validate.Required("service_catalog_ref", "body", m.ServiceCatalogRef); err != nil { - return err - } - - return nil -} - -var infraImportTypeStatusPropEnum []any - -func init() { - var res []string - if err := json.Unmarshal([]byte(`["succeeded","failed","importing"]`), &res); err != nil { - panic(err) - } - for _, v := range res { - infraImportTypeStatusPropEnum = append(infraImportTypeStatusPropEnum, v) - } -} - -const ( - - // InfraImportStatusSucceeded captures enum value "succeeded" - InfraImportStatusSucceeded string = "succeeded" - - // InfraImportStatusFailed captures enum value "failed" - InfraImportStatusFailed string = "failed" - - // InfraImportStatusImporting captures enum value "importing" - InfraImportStatusImporting string = "importing" -) - -// prop value enum -func (m *InfraImport) validateStatusEnum(path, location string, value string) error { - if err := validate.EnumCase(path, location, value, infraImportTypeStatusPropEnum, true); err != nil { - return err - } - return nil -} - -func (m *InfraImport) validateStatus(formats strfmt.Registry) error { - - if err := validate.Required("status", "body", m.Status); err != nil { - return err - } - - // value enum - if err := m.validateStatusEnum("status", "body", *m.Status); err != nil { - return err - } - - return nil -} - -// ContextValidate validates this infra import based on context it is used -func (m *InfraImport) ContextValidate(ctx context.Context, formats strfmt.Registry) error { - return nil -} - -// MarshalBinary interface implementation -func (m *InfraImport) MarshalBinary() ([]byte, error) { - if m == nil { - return nil, nil - } - return swag.WriteJSON(m) -} - -// UnmarshalBinary interface implementation -func (m *InfraImport) UnmarshalBinary(b []byte) error { - var res InfraImport - if err := swag.ReadJSON(b, &res); err != nil { - return err - } - *m = res - return nil -} diff --git a/client/models/infra_import_preset.go b/client/models/infra_import_preset.go deleted file mode 100644 index 552e53e7f..000000000 --- a/client/models/infra_import_preset.go +++ /dev/null @@ -1,87 +0,0 @@ -// Code generated by go-swagger; DO NOT EDIT. - -package models - -import ( - "context" - - "github.com/go-openapi/errors" - "github.com/go-openapi/strfmt" - "github.com/go-openapi/swag" - "github.com/go-openapi/validate" -) - -// InfraImportPreset InfraImportPreset -// -// Infra Import's pre-configured group with Resources commonly used together in a specific context. -// -// swagger:model InfraImportPreset -type InfraImportPreset struct { - - // name - // Required: true - Name *string `json:"name"` - - // resources - // Required: true - Resources []string `json:"resources"` -} - -// Validate validates this infra import preset -func (m *InfraImportPreset) Validate(formats strfmt.Registry) error { - var res []error - - if err := m.validateName(formats); err != nil { - res = append(res, err) - } - - if err := m.validateResources(formats); err != nil { - res = append(res, err) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (m *InfraImportPreset) validateName(formats strfmt.Registry) error { - - if err := validate.Required("name", "body", m.Name); err != nil { - return err - } - - return nil -} - -func (m *InfraImportPreset) validateResources(formats strfmt.Registry) error { - - if err := validate.Required("resources", "body", m.Resources); err != nil { - return err - } - - return nil -} - -// ContextValidate validates this infra import preset based on context it is used -func (m *InfraImportPreset) ContextValidate(ctx context.Context, formats strfmt.Registry) error { - return nil -} - -// MarshalBinary interface implementation -func (m *InfraImportPreset) MarshalBinary() ([]byte, error) { - if m == nil { - return nil, nil - } - return swag.WriteJSON(m) -} - -// UnmarshalBinary interface implementation -func (m *InfraImportPreset) UnmarshalBinary(b []byte) error { - var res InfraImportPreset - if err := swag.ReadJSON(b, &res); err != nil { - return err - } - *m = res - return nil -} diff --git a/client/models/infra_import_resource.go b/client/models/infra_import_resource.go deleted file mode 100644 index 8a13a9fe5..000000000 --- a/client/models/infra_import_resource.go +++ /dev/null @@ -1,70 +0,0 @@ -// Code generated by go-swagger; DO NOT EDIT. - -package models - -import ( - "context" - - "github.com/go-openapi/errors" - "github.com/go-openapi/strfmt" - "github.com/go-openapi/swag" - "github.com/go-openapi/validate" -) - -// InfraImportResource Infra Import Resource -// -// The representation of the Infra Import's Resource of a Cloud Provider. -// -// swagger:model InfraImportResource -type InfraImportResource struct { - - // id - // Required: true - ID *string `json:"id"` -} - -// Validate validates this infra import resource -func (m *InfraImportResource) Validate(formats strfmt.Registry) error { - var res []error - - if err := m.validateID(formats); err != nil { - res = append(res, err) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (m *InfraImportResource) validateID(formats strfmt.Registry) error { - - if err := validate.Required("id", "body", m.ID); err != nil { - return err - } - - return nil -} - -// ContextValidate validates this infra import resource based on context it is used -func (m *InfraImportResource) ContextValidate(ctx context.Context, formats strfmt.Registry) error { - return nil -} - -// MarshalBinary interface implementation -func (m *InfraImportResource) MarshalBinary() ([]byte, error) { - if m == nil { - return nil, nil - } - return swag.WriteJSON(m) -} - -// UnmarshalBinary interface implementation -func (m *InfraImportResource) UnmarshalBinary(b []byte) error { - var res InfraImportResource - if err := swag.ReadJSON(b, &res); err != nil { - return err - } - *m = res - return nil -} diff --git a/client/models/infra_import_resource_body.go b/client/models/infra_import_resource_body.go deleted file mode 100644 index 27ae47fe4..000000000 --- a/client/models/infra_import_resource_body.go +++ /dev/null @@ -1,225 +0,0 @@ -// Code generated by go-swagger; DO NOT EDIT. - -package models - -import ( - "bytes" - "context" - "encoding/json" - stderrors "errors" - "io" - - "github.com/go-openapi/errors" - "github.com/go-openapi/runtime" - "github.com/go-openapi/strfmt" - "github.com/go-openapi/swag" - "github.com/go-openapi/validate" -) - -// InfraImportResourceBody Provider Resources body -// -// # Entry that represents all the data needed for fetching resource -// -// swagger:model InfraImportResourceBody -type InfraImportResourceBody struct { - configurationField CloudProviderConfiguration - - // Credential that will be used to import from the provider - // Required: true - // Max Length: 100 - // Min Length: 3 - // Pattern: ^[a-z0-9]+[a-z0-9\-_]+[a-z0-9]+$ - CredentialCanonical *string `json:"credential_canonical"` - - // tags - Tags []string `json:"tags"` -} - -// Configuration gets the configuration of this base type -func (m *InfraImportResourceBody) Configuration() CloudProviderConfiguration { - return m.configurationField -} - -// SetConfiguration sets the configuration of this base type -func (m *InfraImportResourceBody) SetConfiguration(val CloudProviderConfiguration) { - m.configurationField = val -} - -// UnmarshalJSON unmarshals this object with a polymorphic type from a JSON structure -func (m *InfraImportResourceBody) UnmarshalJSON(raw []byte) error { - var data struct { - Configuration json.RawMessage `json:"configuration"` - - CredentialCanonical *string `json:"credential_canonical"` - - Tags []string `json:"tags"` - } - buf := bytes.NewBuffer(raw) - dec := json.NewDecoder(buf) - dec.UseNumber() - - if err := dec.Decode(&data); err != nil { - return err - } - - propConfiguration, err := UnmarshalCloudProviderConfiguration(bytes.NewBuffer(data.Configuration), runtime.JSONConsumer()) - if err != nil && !stderrors.Is(err, io.EOF) { - return err - } - - var result InfraImportResourceBody - - // configuration - result.configurationField = propConfiguration - - // credential_canonical - result.CredentialCanonical = data.CredentialCanonical - - // tags - result.Tags = data.Tags - - *m = result - - return nil -} - -// MarshalJSON marshals this object with a polymorphic type to a JSON structure -func (m InfraImportResourceBody) MarshalJSON() ([]byte, error) { - var b1, b2, b3 []byte - var err error - b1, err = json.Marshal(struct { - CredentialCanonical *string `json:"credential_canonical"` - - Tags []string `json:"tags"` - }{ - - CredentialCanonical: m.CredentialCanonical, - - Tags: m.Tags, - }) - if err != nil { - return nil, err - } - b2, err = json.Marshal(struct { - Configuration CloudProviderConfiguration `json:"configuration"` - }{ - - Configuration: m.configurationField, - }) - if err != nil { - return nil, err - } - - return swag.ConcatJSON(b1, b2, b3), nil -} - -// Validate validates this infra import resource body -func (m *InfraImportResourceBody) Validate(formats strfmt.Registry) error { - var res []error - - if err := m.validateConfiguration(formats); err != nil { - res = append(res, err) - } - - if err := m.validateCredentialCanonical(formats); err != nil { - res = append(res, err) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (m *InfraImportResourceBody) validateConfiguration(formats strfmt.Registry) error { - - if err := validate.Required("configuration", "body", m.Configuration()); err != nil { - return err - } - - if err := m.Configuration().Validate(formats); err != nil { - ve := new(errors.Validation) - if stderrors.As(err, &ve) { - return ve.ValidateName("configuration") - } - ce := new(errors.CompositeError) - if stderrors.As(err, &ce) { - return ce.ValidateName("configuration") - } - - return err - } - - return nil -} - -func (m *InfraImportResourceBody) validateCredentialCanonical(formats strfmt.Registry) error { - - if err := validate.Required("credential_canonical", "body", m.CredentialCanonical); err != nil { - return err - } - - if err := validate.MinLength("credential_canonical", "body", *m.CredentialCanonical, 3); err != nil { - return err - } - - if err := validate.MaxLength("credential_canonical", "body", *m.CredentialCanonical, 100); err != nil { - return err - } - - if err := validate.Pattern("credential_canonical", "body", *m.CredentialCanonical, `^[a-z0-9]+[a-z0-9\-_]+[a-z0-9]+$`); err != nil { - return err - } - - return nil -} - -// ContextValidate validate this infra import resource body based on the context it is used -func (m *InfraImportResourceBody) ContextValidate(ctx context.Context, formats strfmt.Registry) error { - var res []error - - if err := m.contextValidateConfiguration(ctx, formats); err != nil { - res = append(res, err) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (m *InfraImportResourceBody) contextValidateConfiguration(ctx context.Context, formats strfmt.Registry) error { - - if err := m.Configuration().ContextValidate(ctx, formats); err != nil { - ve := new(errors.Validation) - if stderrors.As(err, &ve) { - return ve.ValidateName("configuration") - } - ce := new(errors.CompositeError) - if stderrors.As(err, &ce) { - return ce.ValidateName("configuration") - } - - return err - } - - return nil -} - -// MarshalBinary interface implementation -func (m *InfraImportResourceBody) MarshalBinary() ([]byte, error) { - if m == nil { - return nil, nil - } - return swag.WriteJSON(m) -} - -// UnmarshalBinary interface implementation -func (m *InfraImportResourceBody) UnmarshalBinary(b []byte) error { - var res InfraImportResourceBody - if err := swag.ReadJSON(b, &res); err != nil { - return err - } - *m = res - return nil -} diff --git a/client/models/infra_import_resources_body.go b/client/models/infra_import_resources_body.go deleted file mode 100644 index 77b73aa64..000000000 --- a/client/models/infra_import_resources_body.go +++ /dev/null @@ -1,213 +0,0 @@ -// Code generated by go-swagger; DO NOT EDIT. - -package models - -import ( - "bytes" - "context" - "encoding/json" - stderrors "errors" - "io" - - "github.com/go-openapi/errors" - "github.com/go-openapi/runtime" - "github.com/go-openapi/strfmt" - "github.com/go-openapi/swag" - "github.com/go-openapi/validate" -) - -// InfraImportResourcesBody Provider's Resources body -// -// # Entry that represents all the data needed for fetching resources -// -// swagger:model InfraImportResourcesBody -type InfraImportResourcesBody struct { - configurationField CloudProviderConfiguration - - // Credential that will be used to import from the provider - // Required: true - // Max Length: 100 - // Min Length: 3 - // Pattern: ^[a-z0-9]+[a-z0-9\-_]+[a-z0-9]+$ - CredentialCanonical *string `json:"credential_canonical"` -} - -// Configuration gets the configuration of this base type -func (m *InfraImportResourcesBody) Configuration() CloudProviderConfiguration { - return m.configurationField -} - -// SetConfiguration sets the configuration of this base type -func (m *InfraImportResourcesBody) SetConfiguration(val CloudProviderConfiguration) { - m.configurationField = val -} - -// UnmarshalJSON unmarshals this object with a polymorphic type from a JSON structure -func (m *InfraImportResourcesBody) UnmarshalJSON(raw []byte) error { - var data struct { - Configuration json.RawMessage `json:"configuration"` - - CredentialCanonical *string `json:"credential_canonical"` - } - buf := bytes.NewBuffer(raw) - dec := json.NewDecoder(buf) - dec.UseNumber() - - if err := dec.Decode(&data); err != nil { - return err - } - - propConfiguration, err := UnmarshalCloudProviderConfiguration(bytes.NewBuffer(data.Configuration), runtime.JSONConsumer()) - if err != nil && !stderrors.Is(err, io.EOF) { - return err - } - - var result InfraImportResourcesBody - - // configuration - result.configurationField = propConfiguration - - // credential_canonical - result.CredentialCanonical = data.CredentialCanonical - - *m = result - - return nil -} - -// MarshalJSON marshals this object with a polymorphic type to a JSON structure -func (m InfraImportResourcesBody) MarshalJSON() ([]byte, error) { - var b1, b2, b3 []byte - var err error - b1, err = json.Marshal(struct { - CredentialCanonical *string `json:"credential_canonical"` - }{ - - CredentialCanonical: m.CredentialCanonical, - }) - if err != nil { - return nil, err - } - b2, err = json.Marshal(struct { - Configuration CloudProviderConfiguration `json:"configuration"` - }{ - - Configuration: m.configurationField, - }) - if err != nil { - return nil, err - } - - return swag.ConcatJSON(b1, b2, b3), nil -} - -// Validate validates this infra import resources body -func (m *InfraImportResourcesBody) Validate(formats strfmt.Registry) error { - var res []error - - if err := m.validateConfiguration(formats); err != nil { - res = append(res, err) - } - - if err := m.validateCredentialCanonical(formats); err != nil { - res = append(res, err) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (m *InfraImportResourcesBody) validateConfiguration(formats strfmt.Registry) error { - - if err := validate.Required("configuration", "body", m.Configuration()); err != nil { - return err - } - - if err := m.Configuration().Validate(formats); err != nil { - ve := new(errors.Validation) - if stderrors.As(err, &ve) { - return ve.ValidateName("configuration") - } - ce := new(errors.CompositeError) - if stderrors.As(err, &ce) { - return ce.ValidateName("configuration") - } - - return err - } - - return nil -} - -func (m *InfraImportResourcesBody) validateCredentialCanonical(formats strfmt.Registry) error { - - if err := validate.Required("credential_canonical", "body", m.CredentialCanonical); err != nil { - return err - } - - if err := validate.MinLength("credential_canonical", "body", *m.CredentialCanonical, 3); err != nil { - return err - } - - if err := validate.MaxLength("credential_canonical", "body", *m.CredentialCanonical, 100); err != nil { - return err - } - - if err := validate.Pattern("credential_canonical", "body", *m.CredentialCanonical, `^[a-z0-9]+[a-z0-9\-_]+[a-z0-9]+$`); err != nil { - return err - } - - return nil -} - -// ContextValidate validate this infra import resources body based on the context it is used -func (m *InfraImportResourcesBody) ContextValidate(ctx context.Context, formats strfmt.Registry) error { - var res []error - - if err := m.contextValidateConfiguration(ctx, formats); err != nil { - res = append(res, err) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (m *InfraImportResourcesBody) contextValidateConfiguration(ctx context.Context, formats strfmt.Registry) error { - - if err := m.Configuration().ContextValidate(ctx, formats); err != nil { - ve := new(errors.Validation) - if stderrors.As(err, &ve) { - return ve.ValidateName("configuration") - } - ce := new(errors.CompositeError) - if stderrors.As(err, &ce) { - return ce.ValidateName("configuration") - } - - return err - } - - return nil -} - -// MarshalBinary interface implementation -func (m *InfraImportResourcesBody) MarshalBinary() ([]byte, error) { - if m == nil { - return nil, nil - } - return swag.WriteJSON(m) -} - -// UnmarshalBinary interface implementation -func (m *InfraImportResourcesBody) UnmarshalBinary(b []byte) error { - var res InfraImportResourcesBody - if err := swag.ReadJSON(b, &res); err != nil { - return err - } - *m = res - return nil -} diff --git a/client/models/new_infra_import.go b/client/models/new_infra_import.go deleted file mode 100644 index bb545150d..000000000 --- a/client/models/new_infra_import.go +++ /dev/null @@ -1,600 +0,0 @@ -// Code generated by go-swagger; DO NOT EDIT. - -package models - -import ( - "bytes" - "context" - "encoding/json" - stderrors "errors" - "io" - - "github.com/go-openapi/errors" - "github.com/go-openapi/runtime" - "github.com/go-openapi/strfmt" - "github.com/go-openapi/swag" - "github.com/go-openapi/validate" -) - -// NewInfraImport New Infra Import -// -// # Entry that represents all the data needed to import a stack -// -// swagger:model NewInfraImport -type NewInfraImport struct { - - // component - Component *NewInfraImportComponent `json:"component,omitempty"` - - configurationField CloudProviderConfiguration - - // Credential that will be used to import from the provider - // Required: true - // Max Length: 100 - // Min Length: 3 - // Pattern: ^[a-z0-9]+[a-z0-9\-_]+[a-z0-9]+$ - CredentialCanonical *string `json:"credential_canonical"` - - // environment - Environment *NewEnvironment `json:"environment,omitempty"` - - // external backend - ExternalBackend *NewInfraImportExternalBackend `json:"external_backend,omitempty"` - - // List of resources to import, these names are the ones on TF (ex: aws_instance). If not set then it means that all the resources will be imported - Include []string `json:"include"` - - // It's a KV where the key is the resource name and the value is the list (array) of attributes to include as part of the module - ModuleVariables map[string][]string `json:"module_variables,omitempty"` - - // project - Project *NewInfraImportProject `json:"project,omitempty"` - - // stack - // Required: true - Stack *NewServiceCatalog `json:"stack"` - - // List of tags to filter with format NAME:VALUE - Tags []string `json:"tags"` - - // List of resources to import via ID, those IDs are the ones documented on Terraform that are needed to Import. The format is 'aws_instance.ID' - Targets []string `json:"targets"` -} - -// Configuration gets the configuration of this base type -func (m *NewInfraImport) Configuration() CloudProviderConfiguration { - return m.configurationField -} - -// SetConfiguration sets the configuration of this base type -func (m *NewInfraImport) SetConfiguration(val CloudProviderConfiguration) { - m.configurationField = val -} - -// UnmarshalJSON unmarshals this object with a polymorphic type from a JSON structure -func (m *NewInfraImport) UnmarshalJSON(raw []byte) error { - var data struct { - Component *NewInfraImportComponent `json:"component,omitempty"` - - Configuration json.RawMessage `json:"configuration"` - - CredentialCanonical *string `json:"credential_canonical"` - - Environment *NewEnvironment `json:"environment,omitempty"` - - ExternalBackend *NewInfraImportExternalBackend `json:"external_backend,omitempty"` - - Include []string `json:"include"` - - ModuleVariables map[string][]string `json:"module_variables,omitempty"` - - Project *NewInfraImportProject `json:"project,omitempty"` - - Stack *NewServiceCatalog `json:"stack"` - - Tags []string `json:"tags"` - - Targets []string `json:"targets"` - } - buf := bytes.NewBuffer(raw) - dec := json.NewDecoder(buf) - dec.UseNumber() - - if err := dec.Decode(&data); err != nil { - return err - } - - propConfiguration, err := UnmarshalCloudProviderConfiguration(bytes.NewBuffer(data.Configuration), runtime.JSONConsumer()) - if err != nil && !stderrors.Is(err, io.EOF) { - return err - } - - var result NewInfraImport - - // component - result.Component = data.Component - - // configuration - result.configurationField = propConfiguration - - // credential_canonical - result.CredentialCanonical = data.CredentialCanonical - - // environment - result.Environment = data.Environment - - // external_backend - result.ExternalBackend = data.ExternalBackend - - // include - result.Include = data.Include - - // module_variables - result.ModuleVariables = data.ModuleVariables - - // project - result.Project = data.Project - - // stack - result.Stack = data.Stack - - // tags - result.Tags = data.Tags - - // targets - result.Targets = data.Targets - - *m = result - - return nil -} - -// MarshalJSON marshals this object with a polymorphic type to a JSON structure -func (m NewInfraImport) MarshalJSON() ([]byte, error) { - var b1, b2, b3 []byte - var err error - b1, err = json.Marshal(struct { - Component *NewInfraImportComponent `json:"component,omitempty"` - - CredentialCanonical *string `json:"credential_canonical"` - - Environment *NewEnvironment `json:"environment,omitempty"` - - ExternalBackend *NewInfraImportExternalBackend `json:"external_backend,omitempty"` - - Include []string `json:"include"` - - ModuleVariables map[string][]string `json:"module_variables,omitempty"` - - Project *NewInfraImportProject `json:"project,omitempty"` - - Stack *NewServiceCatalog `json:"stack"` - - Tags []string `json:"tags"` - - Targets []string `json:"targets"` - }{ - - Component: m.Component, - - CredentialCanonical: m.CredentialCanonical, - - Environment: m.Environment, - - ExternalBackend: m.ExternalBackend, - - Include: m.Include, - - ModuleVariables: m.ModuleVariables, - - Project: m.Project, - - Stack: m.Stack, - - Tags: m.Tags, - - Targets: m.Targets, - }) - if err != nil { - return nil, err - } - b2, err = json.Marshal(struct { - Configuration CloudProviderConfiguration `json:"configuration"` - }{ - - Configuration: m.configurationField, - }) - if err != nil { - return nil, err - } - - return swag.ConcatJSON(b1, b2, b3), nil -} - -// Validate validates this new infra import -func (m *NewInfraImport) Validate(formats strfmt.Registry) error { - var res []error - - if err := m.validateComponent(formats); err != nil { - res = append(res, err) - } - - if err := m.validateConfiguration(formats); err != nil { - res = append(res, err) - } - - if err := m.validateCredentialCanonical(formats); err != nil { - res = append(res, err) - } - - if err := m.validateEnvironment(formats); err != nil { - res = append(res, err) - } - - if err := m.validateExternalBackend(formats); err != nil { - res = append(res, err) - } - - if err := m.validateProject(formats); err != nil { - res = append(res, err) - } - - if err := m.validateStack(formats); err != nil { - res = append(res, err) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (m *NewInfraImport) validateComponent(formats strfmt.Registry) error { - if swag.IsZero(m.Component) { // not required - return nil - } - - if m.Component != nil { - if err := m.Component.Validate(formats); err != nil { - ve := new(errors.Validation) - if stderrors.As(err, &ve) { - return ve.ValidateName("component") - } - ce := new(errors.CompositeError) - if stderrors.As(err, &ce) { - return ce.ValidateName("component") - } - - return err - } - } - - return nil -} - -func (m *NewInfraImport) validateConfiguration(formats strfmt.Registry) error { - - if err := validate.Required("configuration", "body", m.Configuration()); err != nil { - return err - } - - if err := m.Configuration().Validate(formats); err != nil { - ve := new(errors.Validation) - if stderrors.As(err, &ve) { - return ve.ValidateName("configuration") - } - ce := new(errors.CompositeError) - if stderrors.As(err, &ce) { - return ce.ValidateName("configuration") - } - - return err - } - - return nil -} - -func (m *NewInfraImport) validateCredentialCanonical(formats strfmt.Registry) error { - - if err := validate.Required("credential_canonical", "body", m.CredentialCanonical); err != nil { - return err - } - - if err := validate.MinLength("credential_canonical", "body", *m.CredentialCanonical, 3); err != nil { - return err - } - - if err := validate.MaxLength("credential_canonical", "body", *m.CredentialCanonical, 100); err != nil { - return err - } - - if err := validate.Pattern("credential_canonical", "body", *m.CredentialCanonical, `^[a-z0-9]+[a-z0-9\-_]+[a-z0-9]+$`); err != nil { - return err - } - - return nil -} - -func (m *NewInfraImport) validateEnvironment(formats strfmt.Registry) error { - if swag.IsZero(m.Environment) { // not required - return nil - } - - if m.Environment != nil { - if err := m.Environment.Validate(formats); err != nil { - ve := new(errors.Validation) - if stderrors.As(err, &ve) { - return ve.ValidateName("environment") - } - ce := new(errors.CompositeError) - if stderrors.As(err, &ce) { - return ce.ValidateName("environment") - } - - return err - } - } - - return nil -} - -func (m *NewInfraImport) validateExternalBackend(formats strfmt.Registry) error { - if swag.IsZero(m.ExternalBackend) { // not required - return nil - } - - if m.ExternalBackend != nil { - if err := m.ExternalBackend.Validate(formats); err != nil { - ve := new(errors.Validation) - if stderrors.As(err, &ve) { - return ve.ValidateName("external_backend") - } - ce := new(errors.CompositeError) - if stderrors.As(err, &ce) { - return ce.ValidateName("external_backend") - } - - return err - } - } - - return nil -} - -func (m *NewInfraImport) validateProject(formats strfmt.Registry) error { - if swag.IsZero(m.Project) { // not required - return nil - } - - if m.Project != nil { - if err := m.Project.Validate(formats); err != nil { - ve := new(errors.Validation) - if stderrors.As(err, &ve) { - return ve.ValidateName("project") - } - ce := new(errors.CompositeError) - if stderrors.As(err, &ce) { - return ce.ValidateName("project") - } - - return err - } - } - - return nil -} - -func (m *NewInfraImport) validateStack(formats strfmt.Registry) error { - - if err := validate.Required("stack", "body", m.Stack); err != nil { - return err - } - - if m.Stack != nil { - if err := m.Stack.Validate(formats); err != nil { - ve := new(errors.Validation) - if stderrors.As(err, &ve) { - return ve.ValidateName("stack") - } - ce := new(errors.CompositeError) - if stderrors.As(err, &ce) { - return ce.ValidateName("stack") - } - - return err - } - } - - return nil -} - -// ContextValidate validate this new infra import based on the context it is used -func (m *NewInfraImport) ContextValidate(ctx context.Context, formats strfmt.Registry) error { - var res []error - - if err := m.contextValidateComponent(ctx, formats); err != nil { - res = append(res, err) - } - - if err := m.contextValidateConfiguration(ctx, formats); err != nil { - res = append(res, err) - } - - if err := m.contextValidateEnvironment(ctx, formats); err != nil { - res = append(res, err) - } - - if err := m.contextValidateExternalBackend(ctx, formats); err != nil { - res = append(res, err) - } - - if err := m.contextValidateProject(ctx, formats); err != nil { - res = append(res, err) - } - - if err := m.contextValidateStack(ctx, formats); err != nil { - res = append(res, err) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (m *NewInfraImport) contextValidateComponent(ctx context.Context, formats strfmt.Registry) error { - - if m.Component != nil { - - if swag.IsZero(m.Component) { // not required - return nil - } - - if err := m.Component.ContextValidate(ctx, formats); err != nil { - ve := new(errors.Validation) - if stderrors.As(err, &ve) { - return ve.ValidateName("component") - } - ce := new(errors.CompositeError) - if stderrors.As(err, &ce) { - return ce.ValidateName("component") - } - - return err - } - } - - return nil -} - -func (m *NewInfraImport) contextValidateConfiguration(ctx context.Context, formats strfmt.Registry) error { - - if err := m.Configuration().ContextValidate(ctx, formats); err != nil { - ve := new(errors.Validation) - if stderrors.As(err, &ve) { - return ve.ValidateName("configuration") - } - ce := new(errors.CompositeError) - if stderrors.As(err, &ce) { - return ce.ValidateName("configuration") - } - - return err - } - - return nil -} - -func (m *NewInfraImport) contextValidateEnvironment(ctx context.Context, formats strfmt.Registry) error { - - if m.Environment != nil { - - if swag.IsZero(m.Environment) { // not required - return nil - } - - if err := m.Environment.ContextValidate(ctx, formats); err != nil { - ve := new(errors.Validation) - if stderrors.As(err, &ve) { - return ve.ValidateName("environment") - } - ce := new(errors.CompositeError) - if stderrors.As(err, &ce) { - return ce.ValidateName("environment") - } - - return err - } - } - - return nil -} - -func (m *NewInfraImport) contextValidateExternalBackend(ctx context.Context, formats strfmt.Registry) error { - - if m.ExternalBackend != nil { - - if swag.IsZero(m.ExternalBackend) { // not required - return nil - } - - if err := m.ExternalBackend.ContextValidate(ctx, formats); err != nil { - ve := new(errors.Validation) - if stderrors.As(err, &ve) { - return ve.ValidateName("external_backend") - } - ce := new(errors.CompositeError) - if stderrors.As(err, &ce) { - return ce.ValidateName("external_backend") - } - - return err - } - } - - return nil -} - -func (m *NewInfraImport) contextValidateProject(ctx context.Context, formats strfmt.Registry) error { - - if m.Project != nil { - - if swag.IsZero(m.Project) { // not required - return nil - } - - if err := m.Project.ContextValidate(ctx, formats); err != nil { - ve := new(errors.Validation) - if stderrors.As(err, &ve) { - return ve.ValidateName("project") - } - ce := new(errors.CompositeError) - if stderrors.As(err, &ce) { - return ce.ValidateName("project") - } - - return err - } - } - - return nil -} - -func (m *NewInfraImport) contextValidateStack(ctx context.Context, formats strfmt.Registry) error { - - if m.Stack != nil { - - if err := m.Stack.ContextValidate(ctx, formats); err != nil { - ve := new(errors.Validation) - if stderrors.As(err, &ve) { - return ve.ValidateName("stack") - } - ce := new(errors.CompositeError) - if stderrors.As(err, &ce) { - return ce.ValidateName("stack") - } - - return err - } - } - - return nil -} - -// MarshalBinary interface implementation -func (m *NewInfraImport) MarshalBinary() ([]byte, error) { - if m == nil { - return nil, nil - } - return swag.WriteJSON(m) -} - -// UnmarshalBinary interface implementation -func (m *NewInfraImport) UnmarshalBinary(b []byte) error { - var res NewInfraImport - if err := swag.ReadJSON(b, &res); err != nil { - return err - } - *m = res - return nil -} diff --git a/client/models/new_infra_import_component.go b/client/models/new_infra_import_component.go deleted file mode 100644 index 645095c34..000000000 --- a/client/models/new_infra_import_component.go +++ /dev/null @@ -1,137 +0,0 @@ -// Code generated by go-swagger; DO NOT EDIT. - -package models - -import ( - "context" - - "github.com/go-openapi/errors" - "github.com/go-openapi/strfmt" - "github.com/go-openapi/swag" - "github.com/go-openapi/validate" -) - -// NewInfraImportComponent Create Component for the Infra Import -// -// The entity which represents the information of a new component. -// -// swagger:model NewInfraImportComponent -type NewInfraImportComponent struct { - - // canonical - // Max Length: 100 - // Min Length: 1 - // Pattern: ^[\da-zA-Z]+(?:[\da-zA-Z\-._]+[\da-zA-Z]|[\da-zA-Z])$ - Canonical string `json:"canonical,omitempty"` - - // cloud provider canonical - // Required: true - // Max Length: 100 - // Min Length: 3 - // Pattern: ^[a-z0-9]+[a-z0-9\-_]+[a-z0-9]+$ - CloudProviderCanonical *string `json:"cloud_provider_canonical"` - - // name - // Required: true - // Min Length: 1 - Name *string `json:"name"` -} - -// Validate validates this new infra import component -func (m *NewInfraImportComponent) Validate(formats strfmt.Registry) error { - var res []error - - if err := m.validateCanonical(formats); err != nil { - res = append(res, err) - } - - if err := m.validateCloudProviderCanonical(formats); err != nil { - res = append(res, err) - } - - if err := m.validateName(formats); err != nil { - res = append(res, err) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (m *NewInfraImportComponent) validateCanonical(formats strfmt.Registry) error { - if swag.IsZero(m.Canonical) { // not required - return nil - } - - if err := validate.MinLength("canonical", "body", m.Canonical, 1); err != nil { - return err - } - - if err := validate.MaxLength("canonical", "body", m.Canonical, 100); err != nil { - return err - } - - if err := validate.Pattern("canonical", "body", m.Canonical, `^[\da-zA-Z]+(?:[\da-zA-Z\-._]+[\da-zA-Z]|[\da-zA-Z])$`); err != nil { - return err - } - - return nil -} - -func (m *NewInfraImportComponent) validateCloudProviderCanonical(formats strfmt.Registry) error { - - if err := validate.Required("cloud_provider_canonical", "body", m.CloudProviderCanonical); err != nil { - return err - } - - if err := validate.MinLength("cloud_provider_canonical", "body", *m.CloudProviderCanonical, 3); err != nil { - return err - } - - if err := validate.MaxLength("cloud_provider_canonical", "body", *m.CloudProviderCanonical, 100); err != nil { - return err - } - - if err := validate.Pattern("cloud_provider_canonical", "body", *m.CloudProviderCanonical, `^[a-z0-9]+[a-z0-9\-_]+[a-z0-9]+$`); err != nil { - return err - } - - return nil -} - -func (m *NewInfraImportComponent) validateName(formats strfmt.Registry) error { - - if err := validate.Required("name", "body", m.Name); err != nil { - return err - } - - if err := validate.MinLength("name", "body", *m.Name, 1); err != nil { - return err - } - - return nil -} - -// ContextValidate validates this new infra import component based on context it is used -func (m *NewInfraImportComponent) ContextValidate(ctx context.Context, formats strfmt.Registry) error { - return nil -} - -// MarshalBinary interface implementation -func (m *NewInfraImportComponent) MarshalBinary() ([]byte, error) { - if m == nil { - return nil, nil - } - return swag.WriteJSON(m) -} - -// UnmarshalBinary interface implementation -func (m *NewInfraImportComponent) UnmarshalBinary(b []byte) error { - var res NewInfraImportComponent - if err := swag.ReadJSON(b, &res); err != nil { - return err - } - *m = res - return nil -} diff --git a/client/models/new_infra_import_external_backend.go b/client/models/new_infra_import_external_backend.go deleted file mode 100644 index 6dc4aa3d1..000000000 --- a/client/models/new_infra_import_external_backend.go +++ /dev/null @@ -1,211 +0,0 @@ -// Code generated by go-swagger; DO NOT EDIT. - -package models - -import ( - "bytes" - "context" - "encoding/json" - stderrors "errors" - "io" - - "github.com/go-openapi/errors" - "github.com/go-openapi/runtime" - "github.com/go-openapi/strfmt" - "github.com/go-openapi/swag" - "github.com/go-openapi/validate" -) - -// NewInfraImportExternalBackend New External backend -// -// An external backend contains the configuration needed in order to be plugged into the Cycloid system. A backend is a general purpose concept, but Cycloid specifies which ones are supported and the list of those which are supported for every concrete feature. -// -// swagger:model NewInfraImportExternalBackend -type NewInfraImportExternalBackend struct { - configurationField ExternalBackendConfiguration - - // credential canonical - // Max Length: 100 - // Min Length: 3 - // Pattern: ^[a-z0-9]+[a-z0-9\-_]+[a-z0-9]+$ - CredentialCanonical string `json:"credential_canonical,omitempty"` -} - -// Configuration gets the configuration of this base type -func (m *NewInfraImportExternalBackend) Configuration() ExternalBackendConfiguration { - return m.configurationField -} - -// SetConfiguration sets the configuration of this base type -func (m *NewInfraImportExternalBackend) SetConfiguration(val ExternalBackendConfiguration) { - m.configurationField = val -} - -// UnmarshalJSON unmarshals this object with a polymorphic type from a JSON structure -func (m *NewInfraImportExternalBackend) UnmarshalJSON(raw []byte) error { - var data struct { - Configuration json.RawMessage `json:"configuration"` - - CredentialCanonical string `json:"credential_canonical,omitempty"` - } - buf := bytes.NewBuffer(raw) - dec := json.NewDecoder(buf) - dec.UseNumber() - - if err := dec.Decode(&data); err != nil { - return err - } - - propConfiguration, err := UnmarshalExternalBackendConfiguration(bytes.NewBuffer(data.Configuration), runtime.JSONConsumer()) - if err != nil && !stderrors.Is(err, io.EOF) { - return err - } - - var result NewInfraImportExternalBackend - - // configuration - result.configurationField = propConfiguration - - // credential_canonical - result.CredentialCanonical = data.CredentialCanonical - - *m = result - - return nil -} - -// MarshalJSON marshals this object with a polymorphic type to a JSON structure -func (m NewInfraImportExternalBackend) MarshalJSON() ([]byte, error) { - var b1, b2, b3 []byte - var err error - b1, err = json.Marshal(struct { - CredentialCanonical string `json:"credential_canonical,omitempty"` - }{ - - CredentialCanonical: m.CredentialCanonical, - }) - if err != nil { - return nil, err - } - b2, err = json.Marshal(struct { - Configuration ExternalBackendConfiguration `json:"configuration"` - }{ - - Configuration: m.configurationField, - }) - if err != nil { - return nil, err - } - - return swag.ConcatJSON(b1, b2, b3), nil -} - -// Validate validates this new infra import external backend -func (m *NewInfraImportExternalBackend) Validate(formats strfmt.Registry) error { - var res []error - - if err := m.validateConfiguration(formats); err != nil { - res = append(res, err) - } - - if err := m.validateCredentialCanonical(formats); err != nil { - res = append(res, err) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (m *NewInfraImportExternalBackend) validateConfiguration(formats strfmt.Registry) error { - - if err := validate.Required("configuration", "body", m.Configuration()); err != nil { - return err - } - - if err := m.Configuration().Validate(formats); err != nil { - ve := new(errors.Validation) - if stderrors.As(err, &ve) { - return ve.ValidateName("configuration") - } - ce := new(errors.CompositeError) - if stderrors.As(err, &ce) { - return ce.ValidateName("configuration") - } - - return err - } - - return nil -} - -func (m *NewInfraImportExternalBackend) validateCredentialCanonical(formats strfmt.Registry) error { - if swag.IsZero(m.CredentialCanonical) { // not required - return nil - } - - if err := validate.MinLength("credential_canonical", "body", m.CredentialCanonical, 3); err != nil { - return err - } - - if err := validate.MaxLength("credential_canonical", "body", m.CredentialCanonical, 100); err != nil { - return err - } - - if err := validate.Pattern("credential_canonical", "body", m.CredentialCanonical, `^[a-z0-9]+[a-z0-9\-_]+[a-z0-9]+$`); err != nil { - return err - } - - return nil -} - -// ContextValidate validate this new infra import external backend based on the context it is used -func (m *NewInfraImportExternalBackend) ContextValidate(ctx context.Context, formats strfmt.Registry) error { - var res []error - - if err := m.contextValidateConfiguration(ctx, formats); err != nil { - res = append(res, err) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (m *NewInfraImportExternalBackend) contextValidateConfiguration(ctx context.Context, formats strfmt.Registry) error { - - if err := m.Configuration().ContextValidate(ctx, formats); err != nil { - ve := new(errors.Validation) - if stderrors.As(err, &ve) { - return ve.ValidateName("configuration") - } - ce := new(errors.CompositeError) - if stderrors.As(err, &ce) { - return ce.ValidateName("configuration") - } - - return err - } - - return nil -} - -// MarshalBinary interface implementation -func (m *NewInfraImportExternalBackend) MarshalBinary() ([]byte, error) { - if m == nil { - return nil, nil - } - return swag.WriteJSON(m) -} - -// UnmarshalBinary interface implementation -func (m *NewInfraImportExternalBackend) UnmarshalBinary(b []byte) error { - var res NewInfraImportExternalBackend - if err := swag.ReadJSON(b, &res); err != nil { - return err - } - *m = res - return nil -} diff --git a/client/models/new_infra_import_project.go b/client/models/new_infra_import_project.go deleted file mode 100644 index 6b56ad7cc..000000000 --- a/client/models/new_infra_import_project.go +++ /dev/null @@ -1,142 +0,0 @@ -// Code generated by go-swagger; DO NOT EDIT. - -package models - -import ( - "context" - - "github.com/go-openapi/errors" - "github.com/go-openapi/strfmt" - "github.com/go-openapi/swag" - "github.com/go-openapi/validate" -) - -// NewInfraImportProject Create Project for the Infra Import -// -// The entity which represents the information of a new project. -// -// swagger:model NewInfraImportProject -type NewInfraImportProject struct { - - // canonical - // Max Length: 100 - // Min Length: 1 - // Pattern: (^[a-z0-9]+(([a-z0-9\-_]+)?[a-z0-9]+)?$) - Canonical string `json:"canonical,omitempty"` - - // config repository canonical - // Required: true - // Max Length: 100 - // Min Length: 3 - // Pattern: ^[a-z0-9]+[a-z0-9\-_]+[a-z0-9]+$ - ConfigRepositoryCanonical *string `json:"config_repository_canonical"` - - // A description regarding the project to help identify/remember details, - // implementation, purpose, etc. - // - Description string `json:"description,omitempty"` - - // name - // Required: true - // Min Length: 1 - Name *string `json:"name"` -} - -// Validate validates this new infra import project -func (m *NewInfraImportProject) Validate(formats strfmt.Registry) error { - var res []error - - if err := m.validateCanonical(formats); err != nil { - res = append(res, err) - } - - if err := m.validateConfigRepositoryCanonical(formats); err != nil { - res = append(res, err) - } - - if err := m.validateName(formats); err != nil { - res = append(res, err) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (m *NewInfraImportProject) validateCanonical(formats strfmt.Registry) error { - if swag.IsZero(m.Canonical) { // not required - return nil - } - - if err := validate.MinLength("canonical", "body", m.Canonical, 1); err != nil { - return err - } - - if err := validate.MaxLength("canonical", "body", m.Canonical, 100); err != nil { - return err - } - - if err := validate.Pattern("canonical", "body", m.Canonical, `(^[a-z0-9]+(([a-z0-9\-_]+)?[a-z0-9]+)?$)`); err != nil { - return err - } - - return nil -} - -func (m *NewInfraImportProject) validateConfigRepositoryCanonical(formats strfmt.Registry) error { - - if err := validate.Required("config_repository_canonical", "body", m.ConfigRepositoryCanonical); err != nil { - return err - } - - if err := validate.MinLength("config_repository_canonical", "body", *m.ConfigRepositoryCanonical, 3); err != nil { - return err - } - - if err := validate.MaxLength("config_repository_canonical", "body", *m.ConfigRepositoryCanonical, 100); err != nil { - return err - } - - if err := validate.Pattern("config_repository_canonical", "body", *m.ConfigRepositoryCanonical, `^[a-z0-9]+[a-z0-9\-_]+[a-z0-9]+$`); err != nil { - return err - } - - return nil -} - -func (m *NewInfraImportProject) validateName(formats strfmt.Registry) error { - - if err := validate.Required("name", "body", m.Name); err != nil { - return err - } - - if err := validate.MinLength("name", "body", *m.Name, 1); err != nil { - return err - } - - return nil -} - -// ContextValidate validates this new infra import project based on context it is used -func (m *NewInfraImportProject) ContextValidate(ctx context.Context, formats strfmt.Registry) error { - return nil -} - -// MarshalBinary interface implementation -func (m *NewInfraImportProject) MarshalBinary() ([]byte, error) { - if m == nil { - return nil, nil - } - return swag.WriteJSON(m) -} - -// UnmarshalBinary interface implementation -func (m *NewInfraImportProject) UnmarshalBinary(b []byte) error { - var res NewInfraImportProject - if err := swag.ReadJSON(b, &res); err != nil { - return err - } - *m = res - return nil -} diff --git a/client/version b/client/version deleted file mode 100644 index ffad31c96..000000000 --- a/client/version +++ /dev/null @@ -1 +0,0 @@ -v6.10.25 diff --git a/cmd/cycloid/middleware/catalog_repositories.go b/cmd/apiclient/catalog_repositories.go similarity index 79% rename from cmd/cycloid/middleware/catalog_repositories.go rename to cmd/apiclient/catalog_repositories.go index 266649927..5356c3472 100644 --- a/cmd/cycloid/middleware/catalog_repositories.go +++ b/cmd/apiclient/catalog_repositories.go @@ -1,12 +1,11 @@ -package middleware +package apiclient import ( + "fmt" "net/http" "net/url" - "github.com/pkg/errors" - - "github.com/cycloidio/cycloid-cli/client/models" + "github.com/cycloidio/cycloid-cli/gen/models" ) // ListCatalogRepositories lists catalog repositories for an organization. @@ -73,7 +72,7 @@ func (m *middleware) CreateCatalogRepository(org, name, url, branch, cred, visib case "": break default: - return nil, nil, errors.New("invalid visibility parameter for CreateCatalogRepository, accepted values are 'local', 'shared' or 'hidden'") + return nil, nil, fmt.Errorf("invalid visibility parameter for CreateCatalogRepository, accepted values are 'local', 'shared' or 'hidden'") } if teamCanonical != "" { @@ -93,7 +92,7 @@ func (m *middleware) CreateCatalogRepository(org, name, url, branch, cred, visib return result, resp, nil } -func (m *middleware) UpdateCatalogRepository(org, catalogRepo string, name, url, branch, cred string, visibility *string) (*models.ServiceCatalogSource, *http.Response, error) { +func (m *middleware) UpdateCatalogRepository(org, catalogRepo, name, url, branch, cred string, visibility *string) (*models.ServiceCatalogSource, *http.Response, error) { body := &models.UpdateServiceCatalogSource{ Branch: branch, CredentialCanonical: cred, @@ -127,21 +126,13 @@ func (m *middleware) RefreshCatalogRepository(org, catalogRepo string) (*models. return result, resp, nil } -// RefreshCatalogRepositoryVersions triggers an immediate re-index of all branches and tags -// for the given catalog repository. The backend clones the git repository, fetches all refs, -// and updates the service_catalog_source_versions table synchronously before returning. -// -// This resolves the eventual-consistency race where a freshly created catalog repository has no -// version rows yet (the background cron that populates them runs every ~10 minutes by default). -func (m *middleware) RefreshCatalogRepositoryVersions(org, catalogRepo string) ([]*StackVersion, *http.Response, error) { - var result []*StackVersion +func (m *middleware) RefreshCatalogRepositoryVersions(org, catalogRepo string) ([]*models.ServiceCatalogSourceVersion, *http.Response, error) { + var result []*models.ServiceCatalogSourceVersion resp, err := m.GenericRequest(Request{ Method: "GET", Organization: &org, Route: []string{"organizations", org, "service_catalog_sources", catalogRepo, "versions", "refresh"}, - Query: url.Values{ - "sync_presence": []string{"true"}, - }, + Query: url.Values{"sync_presence": []string{"true"}}, }, &result) if err != nil { return nil, resp, err diff --git a/cmd/cycloid/middleware/component_pipelines.go b/cmd/apiclient/component_pipelines.go similarity index 98% rename from cmd/cycloid/middleware/component_pipelines.go rename to cmd/apiclient/component_pipelines.go index daf473829..217c08282 100644 --- a/cmd/cycloid/middleware/component_pipelines.go +++ b/cmd/apiclient/component_pipelines.go @@ -1,10 +1,10 @@ -package middleware +package apiclient import ( "net/http" "net/url" - "github.com/cycloidio/cycloid-cli/client/models" + "github.com/cycloidio/cycloid-cli/gen/models" ) func componentsPipelineName(project, env string) string { diff --git a/cmd/cycloid/middleware/component_pipelines_jobs.go b/cmd/apiclient/component_pipelines_jobs.go similarity index 97% rename from cmd/cycloid/middleware/component_pipelines_jobs.go rename to cmd/apiclient/component_pipelines_jobs.go index 7406ca5c4..034b96754 100644 --- a/cmd/cycloid/middleware/component_pipelines_jobs.go +++ b/cmd/apiclient/component_pipelines_jobs.go @@ -1,9 +1,9 @@ -package middleware +package apiclient import ( "net/http" - "github.com/cycloidio/cycloid-cli/client/models" + "github.com/cycloidio/cycloid-cli/gen/models" ) func (m *middleware) GetJobs(org, project, env, component, pipeline string) ([]*models.Job, *http.Response, error) { diff --git a/cmd/cycloid/middleware/component_pipelines_jobs_builds.go b/cmd/apiclient/component_pipelines_jobs_builds.go similarity index 98% rename from cmd/cycloid/middleware/component_pipelines_jobs_builds.go rename to cmd/apiclient/component_pipelines_jobs_builds.go index 2fec5bf42..9abd8bc5c 100644 --- a/cmd/cycloid/middleware/component_pipelines_jobs_builds.go +++ b/cmd/apiclient/component_pipelines_jobs_builds.go @@ -1,4 +1,4 @@ -package middleware +package apiclient import ( "bytes" @@ -9,7 +9,7 @@ import ( "net/url" "path" - "github.com/cycloidio/cycloid-cli/client/models" + "github.com/cycloidio/cycloid-cli/gen/models" ) func (m *middleware) GetBuilds(org, project, env, component, pipeline, job string) ([]*models.Build, *http.Response, error) { diff --git a/cmd/cycloid/middleware/config_repositories.go b/cmd/apiclient/config_repositories.go similarity index 97% rename from cmd/cycloid/middleware/config_repositories.go rename to cmd/apiclient/config_repositories.go index df0782e7d..5e180417b 100644 --- a/cmd/cycloid/middleware/config_repositories.go +++ b/cmd/apiclient/config_repositories.go @@ -1,9 +1,9 @@ -package middleware +package apiclient import ( "net/http" - "github.com/cycloidio/cycloid-cli/client/models" + "github.com/cycloidio/cycloid-cli/gen/models" ) // ListConfigRepositories lists config repositories for an organization. diff --git a/cmd/cycloid/middleware/cost_estimation.go b/cmd/apiclient/cost_estimation.go similarity index 90% rename from cmd/cycloid/middleware/cost_estimation.go rename to cmd/apiclient/cost_estimation.go index b197e642e..0ae0f847c 100644 --- a/cmd/cycloid/middleware/cost_estimation.go +++ b/cmd/apiclient/cost_estimation.go @@ -1,10 +1,10 @@ -package middleware +package apiclient import ( "fmt" "net/http" - "github.com/cycloidio/cycloid-cli/client/models" + "github.com/cycloidio/cycloid-cli/gen/models" ) // CostEstimation will consume the backend API endpoint for cost estimation diff --git a/cmd/cycloid/middleware/credentials.go b/cmd/apiclient/credentials.go similarity index 97% rename from cmd/cycloid/middleware/credentials.go rename to cmd/apiclient/credentials.go index 5e4c099c4..83769f9ce 100644 --- a/cmd/cycloid/middleware/credentials.go +++ b/cmd/apiclient/credentials.go @@ -1,11 +1,11 @@ -package middleware +package apiclient import ( "net/http" "net/url" "regexp" - "github.com/cycloidio/cycloid-cli/client/models" + "github.com/cycloidio/cycloid-cli/gen/models" ) func (m *middleware) CreateCredential(org, name, credentialType string, rawCred *models.CredentialRaw, path, canonical, description string) (*models.Credential, *http.Response, error) { diff --git a/cmd/cycloid/middleware/cycloid.go b/cmd/apiclient/cycloid.go similarity index 91% rename from cmd/cycloid/middleware/cycloid.go rename to cmd/apiclient/cycloid.go index 982d16a24..58a4eae83 100644 --- a/cmd/cycloid/middleware/cycloid.go +++ b/cmd/apiclient/cycloid.go @@ -1,9 +1,9 @@ -package middleware +package apiclient import ( "net/http" - "github.com/cycloidio/cycloid-cli/client/models" + "github.com/cycloidio/cycloid-cli/gen/models" ) // GetAppVersion returns the version of the running Cycloid server diff --git a/cmd/cycloid/middleware/debug.go b/cmd/apiclient/debug.go similarity index 99% rename from cmd/cycloid/middleware/debug.go rename to cmd/apiclient/debug.go index d3480a3a6..c49e5e7a4 100644 --- a/cmd/cycloid/middleware/debug.go +++ b/cmd/apiclient/debug.go @@ -1,4 +1,4 @@ -package middleware +package apiclient import ( "bytes" diff --git a/cmd/cycloid/middleware/environment_pipelines.go b/cmd/apiclient/environment_pipelines.go similarity index 87% rename from cmd/cycloid/middleware/environment_pipelines.go rename to cmd/apiclient/environment_pipelines.go index 7b1046676..215088d18 100644 --- a/cmd/cycloid/middleware/environment_pipelines.go +++ b/cmd/apiclient/environment_pipelines.go @@ -1,9 +1,9 @@ -package middleware +package apiclient import ( "net/http" - "github.com/cycloidio/cycloid-cli/client/models" + "github.com/cycloidio/cycloid-cli/gen/models" ) // GetEnvPipelines list all pipeline of a designated env. diff --git a/cmd/cycloid/middleware/errors.go b/cmd/apiclient/errors.go similarity index 95% rename from cmd/cycloid/middleware/errors.go rename to cmd/apiclient/errors.go index 26388aa5a..763b70e86 100644 --- a/cmd/cycloid/middleware/errors.go +++ b/cmd/apiclient/errors.go @@ -1,10 +1,10 @@ -package middleware +package apiclient import ( "fmt" "regexp" - "github.com/cycloidio/cycloid-cli/client/models" + "github.com/cycloidio/cycloid-cli/gen/models" ) type ErrorPayloader interface { diff --git a/cmd/cycloid/middleware/event.go b/cmd/apiclient/event.go similarity index 95% rename from cmd/cycloid/middleware/event.go rename to cmd/apiclient/event.go index d36932790..a7b0b83f8 100644 --- a/cmd/cycloid/middleware/event.go +++ b/cmd/apiclient/event.go @@ -1,4 +1,4 @@ -package middleware +package apiclient import ( "fmt" @@ -6,7 +6,7 @@ import ( "net/url" "strconv" - "github.com/cycloidio/cycloid-cli/client/models" + "github.com/cycloidio/cycloid-cli/gen/models" ) func (m *middleware) SendEvent(org, eventType, title, message, severity string, tags map[string]string, color string) (*http.Response, error) { diff --git a/cmd/cycloid/middleware/external_backends.go b/cmd/apiclient/external_backends.go similarity index 98% rename from cmd/cycloid/middleware/external_backends.go rename to cmd/apiclient/external_backends.go index 61a6d1965..c92224916 100644 --- a/cmd/cycloid/middleware/external_backends.go +++ b/cmd/apiclient/external_backends.go @@ -1,4 +1,4 @@ -package middleware +package apiclient import ( "errors" @@ -6,7 +6,7 @@ import ( "net/http" "strconv" - "github.com/cycloidio/cycloid-cli/client/models" + "github.com/cycloidio/cycloid-cli/gen/models" ) func (m *middleware) GetRemoteTFExternalBackend(org string) (*models.ExternalBackend, error) { diff --git a/cmd/apiclient/generate.go b/cmd/apiclient/generate.go new file mode 100644 index 000000000..6f75222d7 --- /dev/null +++ b/cmd/apiclient/generate.go @@ -0,0 +1,3 @@ +package apiclient + +//go:generate go tool mockgen -destination=mock/middleware.go -mock_names=Middleware=Middleware -package=mock -source=middleware.go diff --git a/cmd/cycloid/middleware/generic_client.go b/cmd/apiclient/generic_client.go similarity index 99% rename from cmd/cycloid/middleware/generic_client.go rename to cmd/apiclient/generic_client.go index e00f50b68..39865b515 100644 --- a/cmd/cycloid/middleware/generic_client.go +++ b/cmd/apiclient/generic_client.go @@ -1,4 +1,4 @@ -package middleware +package apiclient import ( "bytes" diff --git a/cmd/cycloid/middleware/http_client.go b/cmd/apiclient/http_client.go similarity index 98% rename from cmd/cycloid/middleware/http_client.go rename to cmd/apiclient/http_client.go index 757b99287..45d222651 100644 --- a/cmd/cycloid/middleware/http_client.go +++ b/cmd/apiclient/http_client.go @@ -1,4 +1,4 @@ -package middleware +package apiclient import ( "encoding/json" @@ -6,7 +6,7 @@ import ( "net/http" "strings" - "github.com/cycloidio/cycloid-cli/client/models" + "github.com/cycloidio/cycloid-cli/gen/models" ) // StackVersion is the local representation of a stack catalog version. diff --git a/cmd/cycloid/middleware/init_first_org.go b/cmd/apiclient/init_first_org.go similarity index 96% rename from cmd/cycloid/middleware/init_first_org.go rename to cmd/apiclient/init_first_org.go index d4dfb493a..2c6fafdbb 100644 --- a/cmd/cycloid/middleware/init_first_org.go +++ b/cmd/apiclient/init_first_org.go @@ -1,14 +1,13 @@ -package middleware +package apiclient import ( + "errors" "fmt" "net/http" "strings" - "github.com/pkg/errors" - - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/internal/ptr" + "github.com/cycloidio/cycloid-cli/gen/models" + "github.com/cycloidio/cycloid-cli/utils/ptr" ) // InitFirstOrg will create the first user, org and inject the licence to the diff --git a/cmd/cycloid/middleware/inventory.go b/cmd/apiclient/inventory.go similarity index 97% rename from cmd/cycloid/middleware/inventory.go rename to cmd/apiclient/inventory.go index 66e39ee2d..8210c376c 100644 --- a/cmd/cycloid/middleware/inventory.go +++ b/cmd/apiclient/inventory.go @@ -1,10 +1,10 @@ -package middleware +package apiclient import ( "net/http" "strconv" - "github.com/cycloidio/cycloid-cli/client/models" + "github.com/cycloidio/cycloid-cli/gen/models" ) // ListInventoryResources lists inventory resources for an organization. diff --git a/cmd/cycloid/middleware/lhs_filter.go b/cmd/apiclient/lhs_filter.go similarity index 98% rename from cmd/cycloid/middleware/lhs_filter.go rename to cmd/apiclient/lhs_filter.go index e5240d6aa..12a342d20 100644 --- a/cmd/cycloid/middleware/lhs_filter.go +++ b/cmd/apiclient/lhs_filter.go @@ -1,4 +1,4 @@ -package middleware +package apiclient import ( "fmt" diff --git a/cmd/cycloid/middleware/middleware.go b/cmd/apiclient/middleware.go similarity index 96% rename from cmd/cycloid/middleware/middleware.go rename to cmd/apiclient/middleware.go index 8696f2b95..a25d75b8a 100644 --- a/cmd/cycloid/middleware/middleware.go +++ b/cmd/apiclient/middleware.go @@ -1,4 +1,4 @@ -package middleware +package apiclient import ( "context" @@ -7,8 +7,8 @@ import ( "net/http" "time" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" + "github.com/cycloidio/cycloid-cli/cmd/common" + "github.com/cycloidio/cycloid-cli/gen/models" ) type Middleware interface { @@ -29,9 +29,9 @@ type Middleware interface { ListCatalogRepositories(org string, filters ...LHSFilter) ([]*models.ServiceCatalogSource, *http.Response, error) GetCatalogRepository(org, catalogRepo string) (*models.ServiceCatalogSource, *http.Response, error) DeleteCatalogRepository(org, catalogRepo string) (*http.Response, error) - UpdateCatalogRepository(org, catalogRepo string, name, url, branch, cred string, visibility *string) (*models.ServiceCatalogSource, *http.Response, error) + UpdateCatalogRepository(org, catalogRepo, name, url, branch, cred string, visibility *string) (*models.ServiceCatalogSource, *http.Response, error) RefreshCatalogRepository(org, catalogRepo string) (*models.ServiceCatalogChanges, *http.Response, error) - RefreshCatalogRepositoryVersions(org, catalogRepo string) ([]*StackVersion, *http.Response, error) + RefreshCatalogRepositoryVersions(org, catalogRepo string) ([]*models.ServiceCatalogSourceVersion, *http.Response, error) CreateConfigRepository(org, name, canonical, url, branch, cred string, setDefault bool) (*models.ConfigRepository, *http.Response, error) DeleteConfigRepository(org, configRepo string) (*http.Response, error) @@ -84,8 +84,8 @@ type Middleware interface { DeleteTeam(org, team string) (*http.Response, error) // organization_team_members - ListTeamMembers(org string, team string, filters ...LHSFilter) ([]*models.MemberTeam, *http.Response, error) - GetTeamMember(org string, team string, memberID uint32) (*models.MemberTeam, *http.Response, error) + ListTeamMembers(org, team string, filters ...LHSFilter) ([]*models.MemberTeam, *http.Response, error) + GetTeamMember(org, team string, memberID uint32) (*models.MemberTeam, *http.Response, error) AssignMemberToTeam(org, team string, username, email *string) (*models.MemberTeam, *http.Response, error) UnAssignMemberFromTeam(org, team string, memberID uint32) (*http.Response, error) @@ -156,7 +156,7 @@ type Middleware interface { CreateProject(org, projectName, project, description, configRepository, owner, team, color, icon string) (*models.Project, *http.Response, error) UpdateProject(org, projectName, project, description, configRepository, owner, team, color, icon, cloudProvider string) (*models.Project, *http.Response, error) DeleteProject(org, project string, opts DeleteOptions) (*http.Response, error) - GetProject(org string, project string) (*models.Project, *http.Response, error) + GetProject(org, project string) (*models.Project, *http.Response, error) ListProjects(org string, filters ...LHSFilter) ([]*models.Project, *http.Response, error) ListProjectEnvs(org, project string, filters ...LHSFilter) ([]*models.ProjectEnvironment, *http.Response, error) diff --git a/cmd/cycloid/middleware/organization.go b/cmd/apiclient/organization.go similarity index 97% rename from cmd/cycloid/middleware/organization.go rename to cmd/apiclient/organization.go index 41976e5f0..fdf3d4f73 100644 --- a/cmd/cycloid/middleware/organization.go +++ b/cmd/apiclient/organization.go @@ -1,10 +1,10 @@ -package middleware +package apiclient import ( "net/http" "net/url" - "github.com/cycloidio/cycloid-cli/client/models" + "github.com/cycloidio/cycloid-cli/gen/models" ) func (m *middleware) CreateOrganization(name string) (*models.Organization, *http.Response, error) { diff --git a/cmd/cycloid/middleware/organization_api_key.go b/cmd/apiclient/organization_api_key.go similarity index 96% rename from cmd/cycloid/middleware/organization_api_key.go rename to cmd/apiclient/organization_api_key.go index c196d7c55..c4258671f 100644 --- a/cmd/cycloid/middleware/organization_api_key.go +++ b/cmd/apiclient/organization_api_key.go @@ -1,10 +1,10 @@ -package middleware +package apiclient import ( "fmt" "net/http" - "github.com/cycloidio/cycloid-cli/client/models" + "github.com/cycloidio/cycloid-cli/gen/models" ) // ListAPIKeys lists API keys for an organization. diff --git a/cmd/cycloid/middleware/organization_cloud_accounts.go b/cmd/apiclient/organization_cloud_accounts.go similarity index 97% rename from cmd/cycloid/middleware/organization_cloud_accounts.go rename to cmd/apiclient/organization_cloud_accounts.go index c37cc07d9..3fb992052 100644 --- a/cmd/cycloid/middleware/organization_cloud_accounts.go +++ b/cmd/apiclient/organization_cloud_accounts.go @@ -1,9 +1,9 @@ -package middleware +package apiclient import ( "net/http" - "github.com/cycloidio/cycloid-cli/client/models" + "github.com/cycloidio/cycloid-cli/gen/models" ) func (m *middleware) ListCloudAccounts(org string) ([]*models.CloudAccountDetail, *http.Response, error) { diff --git a/cmd/cycloid/middleware/organization_components.go b/cmd/apiclient/organization_components.go similarity index 98% rename from cmd/cycloid/middleware/organization_components.go rename to cmd/apiclient/organization_components.go index 9a1410aa7..e42bce9e7 100644 --- a/cmd/cycloid/middleware/organization_components.go +++ b/cmd/apiclient/organization_components.go @@ -1,4 +1,4 @@ -package middleware +package apiclient import ( "fmt" @@ -6,8 +6,8 @@ import ( "net/url" "strconv" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/internal/ptr" + "github.com/cycloidio/cycloid-cli/gen/models" + "github.com/cycloidio/cycloid-cli/utils/ptr" ) func (m *middleware) GetComponentConfig(org, project, env, component string) (models.FormVariables, *http.Response, error) { diff --git a/cmd/cycloid/middleware/organization_environment_types.go b/cmd/apiclient/organization_environment_types.go similarity index 96% rename from cmd/cycloid/middleware/organization_environment_types.go rename to cmd/apiclient/organization_environment_types.go index f1810b418..88cbdf440 100644 --- a/cmd/cycloid/middleware/organization_environment_types.go +++ b/cmd/apiclient/organization_environment_types.go @@ -1,10 +1,10 @@ -package middleware +package apiclient import ( "fmt" "net/http" - "github.com/cycloidio/cycloid-cli/client/models" + "github.com/cycloidio/cycloid-cli/gen/models" ) func (m *middleware) ListEnvironmentTypes(org string) ([]*models.EnvironmentType, *http.Response, error) { diff --git a/cmd/cycloid/middleware/organization_environments.go b/cmd/apiclient/organization_environments.go similarity index 97% rename from cmd/cycloid/middleware/organization_environments.go rename to cmd/apiclient/organization_environments.go index 4b35f970c..7080e0180 100644 --- a/cmd/cycloid/middleware/organization_environments.go +++ b/cmd/apiclient/organization_environments.go @@ -1,9 +1,9 @@ -package middleware +package apiclient import ( "net/http" - "github.com/cycloidio/cycloid-cli/client/models" + "github.com/cycloidio/cycloid-cli/gen/models" ) func (m *middleware) ListOrgEnvs(org string, filters ...LHSFilter) ([]*models.Environment, *http.Response, error) { diff --git a/cmd/cycloid/middleware/organization_forms.go b/cmd/apiclient/organization_forms.go similarity index 96% rename from cmd/cycloid/middleware/organization_forms.go rename to cmd/apiclient/organization_forms.go index c7df5fc74..68d9a4c10 100644 --- a/cmd/cycloid/middleware/organization_forms.go +++ b/cmd/apiclient/organization_forms.go @@ -1,4 +1,4 @@ -package middleware +package apiclient import ( "errors" @@ -6,7 +6,7 @@ import ( "gopkg.in/yaml.v3" - "github.com/cycloidio/cycloid-cli/client/models" + "github.com/cycloidio/cycloid-cli/gen/models" ) func (m *middleware) ValidateForm(org string, rawForms []byte) (*models.FormsValidationResult, *http.Response, error) { diff --git a/cmd/cycloid/middleware/organization_licence.go b/cmd/apiclient/organization_licence.go similarity index 90% rename from cmd/cycloid/middleware/organization_licence.go rename to cmd/apiclient/organization_licence.go index 5a78b3f0b..2c6b166b3 100644 --- a/cmd/cycloid/middleware/organization_licence.go +++ b/cmd/apiclient/organization_licence.go @@ -1,9 +1,9 @@ -package middleware +package apiclient import ( "net/http" - "github.com/cycloidio/cycloid-cli/client/models" + "github.com/cycloidio/cycloid-cli/gen/models" ) func (m *middleware) GetLicence(org string) (*models.Licence, *http.Response, error) { diff --git a/cmd/cycloid/middleware/organization_members.go b/cmd/apiclient/organization_members.go similarity index 97% rename from cmd/cycloid/middleware/organization_members.go rename to cmd/apiclient/organization_members.go index 8a8e98940..009ffcbd8 100644 --- a/cmd/cycloid/middleware/organization_members.go +++ b/cmd/apiclient/organization_members.go @@ -1,4 +1,4 @@ -package middleware +package apiclient import ( "fmt" @@ -8,7 +8,7 @@ import ( "github.com/go-openapi/strfmt" - "github.com/cycloidio/cycloid-cli/client/models" + "github.com/cycloidio/cycloid-cli/gen/models" ) // ListMembers lists organization members. diff --git a/cmd/cycloid/middleware/organization_oidc.go b/cmd/apiclient/organization_oidc.go similarity index 97% rename from cmd/cycloid/middleware/organization_oidc.go rename to cmd/apiclient/organization_oidc.go index b203f35b6..0ccfaa1c1 100644 --- a/cmd/cycloid/middleware/organization_oidc.go +++ b/cmd/apiclient/organization_oidc.go @@ -1,11 +1,11 @@ -package middleware +package apiclient import ( "fmt" "net/http" "strconv" - "github.com/cycloidio/cycloid-cli/client/models" + "github.com/cycloidio/cycloid-cli/gen/models" ) // OIDCGroupMapping maps an OIDC provider group-claim value to a Cycloid team. @@ -177,7 +177,7 @@ type authenticationEnvelope struct { // The secret and CA cert are never included (HasSecret / HasCaCertificate report // presence only). func (m *middleware) GetOIDCIntegration(org string) (*OIDCIntegration, *http.Response, error) { - var result authenticationEnvelope + var result OIDCIntegration resp, err := m.GenericRequest(Request{ Method: "GET", Organization: &org, @@ -186,7 +186,7 @@ func (m *middleware) GetOIDCIntegration(org string) (*OIDCIntegration, *http.Res if err != nil { return nil, resp, fmt.Errorf("failed to get OIDC integration: %w", err) } - return result.Config, resp, nil + return &result, resp, nil } // UpdateOIDCIntegration creates-or-updates the org's AuthenticationOIDC config. @@ -195,7 +195,7 @@ func (m *middleware) GetOIDCIntegration(org string) (*OIDCIntegration, *http.Res // value, and an absent/empty oidc_client_secret or oidc_ca_cert preserves the // stored secret. Pass only the keys you intend to change. func (m *middleware) UpdateOIDCIntegration(org string, config map[string]interface{}) (*OIDCIntegration, *http.Response, error) { - var result authenticationEnvelope + var result OIDCIntegration resp, err := m.GenericRequest(Request{ Method: "PUT", Organization: &org, @@ -205,5 +205,5 @@ func (m *middleware) UpdateOIDCIntegration(org string, config map[string]interfa if err != nil { return nil, resp, fmt.Errorf("failed to update OIDC integration: %w", err) } - return result.Config, resp, nil + return &result, resp, nil } diff --git a/cmd/cycloid/middleware/organization_pipelines.go b/cmd/apiclient/organization_pipelines.go similarity index 92% rename from cmd/cycloid/middleware/organization_pipelines.go rename to cmd/apiclient/organization_pipelines.go index 4a8e9f649..e9565f5cc 100644 --- a/cmd/cycloid/middleware/organization_pipelines.go +++ b/cmd/apiclient/organization_pipelines.go @@ -1,10 +1,10 @@ -package middleware +package apiclient import ( "net/http" "net/url" - "github.com/cycloidio/cycloid-cli/client/models" + "github.com/cycloidio/cycloid-cli/gen/models" ) // GetOrgPipelines list all pipeline of a designated org. diff --git a/cmd/cycloid/middleware/organization_projects.go b/cmd/apiclient/organization_projects.go similarity index 98% rename from cmd/cycloid/middleware/organization_projects.go rename to cmd/apiclient/organization_projects.go index b93115a7a..52aab2efb 100644 --- a/cmd/cycloid/middleware/organization_projects.go +++ b/cmd/apiclient/organization_projects.go @@ -1,10 +1,10 @@ -package middleware +package apiclient import ( "fmt" "net/http" - "github.com/cycloidio/cycloid-cli/client/models" + "github.com/cycloidio/cycloid-cli/gen/models" ) // ListProjects lists projects for an organization. diff --git a/cmd/cycloid/middleware/organization_roles.go b/cmd/apiclient/organization_roles.go similarity index 96% rename from cmd/cycloid/middleware/organization_roles.go rename to cmd/apiclient/organization_roles.go index abc681f8e..c0b07ca02 100644 --- a/cmd/cycloid/middleware/organization_roles.go +++ b/cmd/apiclient/organization_roles.go @@ -1,11 +1,11 @@ -package middleware +package apiclient import ( "fmt" "net/http" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/internal/ptr" + "github.com/cycloidio/cycloid-cli/gen/models" + "github.com/cycloidio/cycloid-cli/utils/ptr" ) // ListRoles lists roles for an organization. diff --git a/cmd/cycloid/middleware/organization_subscriptions.go b/cmd/apiclient/organization_subscriptions.go similarity index 87% rename from cmd/cycloid/middleware/organization_subscriptions.go rename to cmd/apiclient/organization_subscriptions.go index 9dca5ac8c..17a724b71 100644 --- a/cmd/cycloid/middleware/organization_subscriptions.go +++ b/cmd/apiclient/organization_subscriptions.go @@ -1,11 +1,11 @@ -package middleware +package apiclient import ( "fmt" "net/http" "time" - "github.com/cycloidio/cycloid-cli/client/models" + "github.com/cycloidio/cycloid-cli/gen/models" ) type SubscriptionPlan = string @@ -15,12 +15,10 @@ const ( PlatformTeam = "platform_teams" ) -var ( - AvailableSubscriptionPlans = []string{ - FreeTrial, - PlatformTeam, - } -) +var AvailableSubscriptionPlans = []string{ + FreeTrial, + PlatformTeam, +} type SubscriptionRequest struct { ExpiresAt string `json:"expires_at"` diff --git a/cmd/cycloid/middleware/organization_team_members.go b/cmd/apiclient/organization_team_members.go similarity index 86% rename from cmd/cycloid/middleware/organization_team_members.go rename to cmd/apiclient/organization_team_members.go index 6fd229a1e..0ec3db6fe 100644 --- a/cmd/cycloid/middleware/organization_team_members.go +++ b/cmd/apiclient/organization_team_members.go @@ -1,18 +1,18 @@ -package middleware +package apiclient import ( "fmt" "net/http" "strconv" - "github.com/cycloidio/cycloid-cli/client/models" + "github.com/cycloidio/cycloid-cli/gen/models" ) // ListTeamMembers lists members of a team. // // NOTE: the backend handler for this route does not call lhs.ParseQuery, so // LHS filters are accepted by the middleware but silently ignored server-side. -func (m *middleware) ListTeamMembers(org string, team string, filters ...LHSFilter) ([]*models.MemberTeam, *http.Response, error) { +func (m *middleware) ListTeamMembers(org, team string, filters ...LHSFilter) ([]*models.MemberTeam, *http.Response, error) { var result []*models.MemberTeam resp, err := m.GenericRequest(Request{ Method: "GET", @@ -26,7 +26,7 @@ func (m *middleware) ListTeamMembers(org string, team string, filters ...LHSFilt return result, resp, nil } -func (m *middleware) GetTeamMember(org string, team string, memberID uint32) (*models.MemberTeam, *http.Response, error) { +func (m *middleware) GetTeamMember(org, team string, memberID uint32) (*models.MemberTeam, *http.Response, error) { var result *models.MemberTeam resp, err := m.GenericRequest(Request{ Method: "GET", diff --git a/cmd/cycloid/middleware/organization_teams.go b/cmd/apiclient/organization_teams.go similarity index 97% rename from cmd/cycloid/middleware/organization_teams.go rename to cmd/apiclient/organization_teams.go index 63aad7165..c503bd72e 100644 --- a/cmd/cycloid/middleware/organization_teams.go +++ b/cmd/apiclient/organization_teams.go @@ -1,4 +1,4 @@ -package middleware +package apiclient import ( "fmt" @@ -6,7 +6,7 @@ import ( "net/url" "strconv" - "github.com/cycloidio/cycloid-cli/client/models" + "github.com/cycloidio/cycloid-cli/gen/models" ) type TeamOrderByParam string diff --git a/cmd/cycloid/middleware/pagination.go b/cmd/apiclient/pagination.go similarity index 92% rename from cmd/cycloid/middleware/pagination.go rename to cmd/apiclient/pagination.go index ed65b065f..7c6217d99 100644 --- a/cmd/cycloid/middleware/pagination.go +++ b/cmd/apiclient/pagination.go @@ -1,4 +1,4 @@ -package middleware +package apiclient import ( "encoding/json" @@ -7,11 +7,13 @@ import ( "net/url" "strconv" - "github.com/cycloidio/cycloid-cli/client/models" + "github.com/cycloidio/cycloid-cli/gen/models" ) -const defaultPageSize = 100 -const maxPages = 1_000 +const ( + defaultPageSize = 100 + maxPages = 1_000 +) type paginatedListResponse[T any] struct { Data []T `json:"data"` diff --git a/cmd/cycloid/middleware/plugins.go b/cmd/apiclient/plugins.go similarity index 99% rename from cmd/cycloid/middleware/plugins.go rename to cmd/apiclient/plugins.go index eb99171a8..1e929bc22 100644 --- a/cmd/cycloid/middleware/plugins.go +++ b/cmd/apiclient/plugins.go @@ -1,4 +1,4 @@ -package middleware +package apiclient import ( "fmt" @@ -6,7 +6,7 @@ import ( "github.com/go-openapi/strfmt" - "github.com/cycloidio/cycloid-cli/client/models" + "github.com/cycloidio/cycloid-cli/gen/models" ) func registryPluginsRoute(org string, registryID uint32, extra ...string) []string { diff --git a/cmd/cycloid/middleware/project_kpi.go b/cmd/apiclient/project_kpi.go similarity index 94% rename from cmd/cycloid/middleware/project_kpi.go rename to cmd/apiclient/project_kpi.go index d059e0983..f8e26c946 100644 --- a/cmd/cycloid/middleware/project_kpi.go +++ b/cmd/apiclient/project_kpi.go @@ -1,4 +1,4 @@ -package middleware +package apiclient // import ( // "encoding/json" @@ -6,8 +6,8 @@ package middleware // strfmt "github.com/go-openapi/strfmt" // // "github.com/cycloidio/cycloid-cli/client/client/organization_kpis" -// "github.com/cycloidio/cycloid-cli/client/models" -// "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" +// "github.com/cycloidio/cycloid-cli/gen/models" +// "github.com/cycloidio/cycloid-cli/cmd/common" // ) // // func (m *middleware) CreateKpi(name, kpiType, widget, org, project, job, env, config string) (*models.KPI, error) { diff --git a/cmd/cycloid/middleware/project_pipelines.go b/cmd/apiclient/project_pipelines.go similarity index 87% rename from cmd/cycloid/middleware/project_pipelines.go rename to cmd/apiclient/project_pipelines.go index 57c4bf83b..68f4539ac 100644 --- a/cmd/cycloid/middleware/project_pipelines.go +++ b/cmd/apiclient/project_pipelines.go @@ -1,9 +1,9 @@ -package middleware +package apiclient import ( "net/http" - "github.com/cycloidio/cycloid-cli/client/models" + "github.com/cycloidio/cycloid-cli/gen/models" ) // GetProjectPipelines lists all pipelines of a designated project. diff --git a/cmd/cycloid/middleware/query_encode.go b/cmd/apiclient/query_encode.go similarity index 99% rename from cmd/cycloid/middleware/query_encode.go rename to cmd/apiclient/query_encode.go index 56c7f613f..614ce79df 100644 --- a/cmd/cycloid/middleware/query_encode.go +++ b/cmd/apiclient/query_encode.go @@ -1,4 +1,4 @@ -package middleware +package apiclient import ( "fmt" diff --git a/cmd/cycloid/middleware/sanitize.go b/cmd/apiclient/sanitize.go similarity index 99% rename from cmd/cycloid/middleware/sanitize.go rename to cmd/apiclient/sanitize.go index 93f9de67e..af057e30e 100644 --- a/cmd/cycloid/middleware/sanitize.go +++ b/cmd/apiclient/sanitize.go @@ -1,4 +1,4 @@ -package middleware +package apiclient import ( "encoding/json" diff --git a/cmd/cycloid/middleware/stacks.go b/cmd/apiclient/stacks.go similarity index 94% rename from cmd/cycloid/middleware/stacks.go rename to cmd/apiclient/stacks.go index d2f751d42..2c1032e2f 100644 --- a/cmd/cycloid/middleware/stacks.go +++ b/cmd/apiclient/stacks.go @@ -1,4 +1,4 @@ -package middleware +package apiclient import ( "fmt" @@ -6,10 +6,8 @@ import ( "net/url" "strconv" - "github.com/pkg/errors" - - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/internal/ptr" + "github.com/cycloidio/cycloid-cli/gen/models" + "github.com/cycloidio/cycloid-cli/utils/ptr" ) func (m *middleware) GetStack(org, ref string) (*models.ServiceCatalog, *http.Response, error) { @@ -56,7 +54,7 @@ func (m *middleware) resolveStackVersion(org, stackRef, versionTag, versionBranc } if defaultVersion == nil || defaultVersion.ID == nil || defaultVersion.CommitHash == nil { - return 0, "", errors.New("no stack catalog version found") + return 0, "", fmt.Errorf("no stack catalog version found") } return *defaultVersion.ID, *defaultVersion.CommitHash, nil @@ -232,7 +230,7 @@ func (m *middleware) CreateStackFromBlueprint(org, blueprintRef, name, stack, ca Body: body, }, &result) if err != nil { - return nil, resp, errors.Wrap(err, "failed to create stack from blueprint") + return nil, resp, fmt.Errorf("failed to create stack from blueprint: %w", err) } return result, resp, nil } @@ -261,8 +259,8 @@ func (m *middleware) UpdateStack( // Remove this condition when backend will be fixed // If the team attribute is nil, this means that the backend did not found the maitainer canonical if teamCanonical != "" && result.Team == nil { - return result, resp, errors.Errorf( - "maintainer with canonical '%s' may not exists, maintainer on stack ref '%s' has been removed, please check you team canonical argument and ensure that the team exists.", + return result, resp, fmt.Errorf( + "maintainer with canonical %q may not exist, maintainer on stack ref %q has been removed, please check your team canonical argument and ensure that the team exists", teamCanonical, ref, ) } diff --git a/cmd/cycloid/middleware/user.go b/cmd/apiclient/user.go similarity index 97% rename from cmd/cycloid/middleware/user.go rename to cmd/apiclient/user.go index e2222b8d3..194c5fa72 100644 --- a/cmd/cycloid/middleware/user.go +++ b/cmd/apiclient/user.go @@ -1,4 +1,4 @@ -package middleware +package apiclient import ( "net/http" @@ -6,7 +6,7 @@ import ( "github.com/go-openapi/strfmt" - "github.com/cycloidio/cycloid-cli/client/models" + "github.com/cycloidio/cycloid-cli/gen/models" ) func (m *middleware) UserSignup(username, email, password, fullName string) (*http.Response, error) { diff --git a/cmd/cycloid/middleware/utils.go b/cmd/apiclient/utils.go similarity index 97% rename from cmd/cycloid/middleware/utils.go rename to cmd/apiclient/utils.go index 0bdb972fa..17de9d3d5 100644 --- a/cmd/cycloid/middleware/utils.go +++ b/cmd/apiclient/utils.go @@ -1,11 +1,11 @@ -package middleware +package apiclient import ( "fmt" "regexp" "strings" - "github.com/cycloidio/cycloid-cli/internal/ptr" + "github.com/cycloidio/cycloid-cli/utils/ptr" ) // from https://github.com/cycloidio/youdeploy-http-api/blob/develop/utils/convert.go diff --git a/cmd/cycloid/apikey/cmd.go b/cmd/apikey/cmd.go similarity index 100% rename from cmd/cycloid/apikey/cmd.go rename to cmd/apikey/cmd.go diff --git a/cmd/cycloid/apikey/create.go b/cmd/apikey/create.go similarity index 92% rename from cmd/cycloid/apikey/create.go rename to cmd/apikey/create.go index d5ee82be5..133f289ac 100644 --- a/cmd/cycloid/apikey/create.go +++ b/cmd/apikey/create.go @@ -6,12 +6,12 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" + "github.com/cycloidio/cycloid-cli/gen/models" ) // NewCreateCommand returns the cobra command holding @@ -42,7 +42,7 @@ cy --org myOrg api-key create --canonical "admin-api-key" --rules '[...]' --recr // create the generated tokens func create(cmd *cobra.Command, args []string) error { api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) org, err := cyargs.GetOrg(cmd) if err != nil { diff --git a/cmd/cycloid/apikey/delete.go b/cmd/apikey/delete.go similarity index 93% rename from cmd/cycloid/apikey/delete.go rename to cmd/apikey/delete.go index a787074d5..e4f2fb773 100644 --- a/cmd/cycloid/apikey/delete.go +++ b/cmd/apikey/delete.go @@ -5,8 +5,8 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" @@ -63,7 +63,7 @@ func remove(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) deleted := make([]string, 0, len(args)) for _, canonical := range args { diff --git a/cmd/cycloid/apikey/get.go b/cmd/apikey/get.go similarity index 91% rename from cmd/cycloid/apikey/get.go rename to cmd/apikey/get.go index c0891d15b..813cc1ffe 100644 --- a/cmd/cycloid/apikey/get.go +++ b/cmd/apikey/get.go @@ -5,11 +5,11 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" + "github.com/cycloidio/cycloid-cli/gen/models" ) // NewGetCommand returns the cobra command holding @@ -65,7 +65,7 @@ func get(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) if len(args) == 1 { key, _, err := m.GetAPIKey(org, args[0]) diff --git a/cmd/cycloid/apikey/list.go b/cmd/apikey/list.go similarity index 83% rename from cmd/cycloid/apikey/list.go rename to cmd/apikey/list.go index 8b90bbafe..c6633053b 100644 --- a/cmd/cycloid/apikey/list.go +++ b/cmd/apikey/list.go @@ -3,12 +3,12 @@ package apikey import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" + "github.com/cycloidio/cycloid-cli/gen/models" ) var apiKeyTableOptions = printer.Options{ @@ -34,7 +34,7 @@ cy api-key list --org my-org`, // list the generated tokens func list(cmd *cobra.Command, args []string) error { api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) org, err := cyargs.GetOrg(cmd) if err != nil { diff --git a/cmd/cycloid/beta/bootstrap_first_org/bootstrap.go b/cmd/beta/bootstrap_first_org/bootstrap.go similarity index 90% rename from cmd/cycloid/beta/bootstrap_first_org/bootstrap.go rename to cmd/beta/bootstrap_first_org/bootstrap.go index f417627b0..cf898f648 100644 --- a/cmd/cycloid/beta/bootstrap_first_org/bootstrap.go +++ b/cmd/beta/bootstrap_first_org/bootstrap.go @@ -5,8 +5,8 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" @@ -15,7 +15,7 @@ import ( var bootstrapTableOptions = printer.Options{ Columns: []string{"Org", "Username", "Email", "Token", "APIKey", "CredentialCanonical"}, Transform: func(obj interface{}) map[string]string { - data, ok := obj.(*middleware.FirstOrgData) + data, ok := obj.(*apiclient.FirstOrgData) if !ok || data == nil { return nil } @@ -69,7 +69,7 @@ func bootstrap(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) result, _, err := m.InitFirstOrg(org, username, fullName, email, password, licence, apiKeyCanonical) return cyout.PrintWithOptions(cmd, result, err, "failed to bootstrap first organization", bootstrapTableOptions) diff --git a/cmd/cycloid/beta/bootstrap_first_org/cmd.go b/cmd/beta/bootstrap_first_org/cmd.go similarity index 100% rename from cmd/cycloid/beta/bootstrap_first_org/cmd.go rename to cmd/beta/bootstrap_first_org/cmd.go diff --git a/cmd/cycloid/beta/cmd.go b/cmd/beta/cmd.go similarity index 71% rename from cmd/cycloid/beta/cmd.go rename to cmd/beta/cmd.go index f3828bb79..6bcb92013 100644 --- a/cmd/cycloid/beta/cmd.go +++ b/cmd/beta/cmd.go @@ -3,8 +3,8 @@ package beta import ( "github.com/spf13/cobra" - bootstrapfirstorg "github.com/cycloidio/cycloid-cli/cmd/cycloid/beta/bootstrap_first_org" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/beta/config" + bootstrapfirstorg "github.com/cycloidio/cycloid-cli/cmd/beta/bootstrap_first_org" + "github.com/cycloidio/cycloid-cli/cmd/beta/config" ) func NewCommands() *cobra.Command { diff --git a/cmd/cycloid/beta/config/cmd.go b/cmd/beta/config/cmd.go similarity index 100% rename from cmd/cycloid/beta/config/cmd.go rename to cmd/beta/config/cmd.go diff --git a/cmd/cycloid/beta/config/interpolate.go b/cmd/beta/config/interpolate.go similarity index 88% rename from cmd/cycloid/beta/config/interpolate.go rename to cmd/beta/config/interpolate.go index d22466d21..1c08071fc 100644 --- a/cmd/cycloid/beta/config/interpolate.go +++ b/cmd/beta/config/interpolate.go @@ -3,11 +3,10 @@ package config import ( "fmt" - "github.com/pkg/errors" "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" @@ -46,12 +45,12 @@ func interpolate(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) // Resolve stack version: --stack-version (new) or legacy flags. tag, branch, hash, err := cyargs.ResolveStackVersionArg(cmd, m, org, stackRef) if err != nil { - return errors.Wrap(err, "failed to read stack version flags") + return fmt.Errorf("failed to read stack version flags: %w", err) } // Get default to stacks diff --git a/cmd/cycloid/catalogrepositories/cmd.go b/cmd/catalogrepositories/cmd.go similarity index 93% rename from cmd/cycloid/catalogrepositories/cmd.go rename to cmd/catalogrepositories/cmd.go index 50d8ef354..6ecc9b2b6 100644 --- a/cmd/cycloid/catalogrepositories/cmd.go +++ b/cmd/catalogrepositories/cmd.go @@ -5,7 +5,7 @@ import ( ) func NewCommands() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "catalog-repository", Aliases: []string{ "catalog-repo", diff --git a/cmd/cycloid/catalogrepositories/create.go b/cmd/catalogrepositories/create.go similarity index 63% rename from cmd/cycloid/catalogrepositories/create.go rename to cmd/catalogrepositories/create.go index 534d35c98..64cc11130 100644 --- a/cmd/cycloid/catalogrepositories/create.go +++ b/cmd/catalogrepositories/create.go @@ -7,16 +7,15 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" ) func NewCreateCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "create", Args: cobra.NoArgs, Short: "create a catalog repository", @@ -26,9 +25,6 @@ func NewCreateCommand() *cobra.Command { # create a catalog repository using public git repository cy --org my-org catalog-repo create --branch stacks --url "https://github.com:my/repo.git" --name my-catalog-name - - # create and immediately re-index all branches/tags so they are resolvable (fixes branch-stack presence race) - cy --org my-org catalog-repo create --branch stacks --url "git@github.com:my/repo.git" --name my-catalog-name --refresh `, RunE: createCatalogRepository, } @@ -42,7 +38,6 @@ func NewCreateCommand() *cobra.Command { cmd.Flags().String("visibility", "", "set the stacks base visibility in the catalog. accepted values are 'local', 'shared' or 'hidden' (default: local)") cmd.Flags().String("team", "", "set the team canonical to be set as maintener of the stacks") cmd.Flags().Bool("update", false, "update the catalog repository if it already exists") - cmd.Flags().Bool("refresh", true, "trigger a synchronous version re-index after create (or update) to make all branches and tags immediately resolvable") return cmd } @@ -66,7 +61,7 @@ func createCatalogRepository(cmd *cobra.Command, args []string) error { return err } - displayName, repoCanonical, err := middleware.NameOrCanonical(&name, &canonical) + displayName, repoCanonical, err := apiclient.NameOrCanonical(&name, &canonical) if err != nil { return err } @@ -88,12 +83,12 @@ func createCatalogRepository(cmd *cobra.Command, args []string) error { visibility, err := cmd.Flags().GetString("visibility") if err != nil { - return err + return fmt.Errorf("unable to get visibility flag: %w", err) } teamCanonical, err := cmd.Flags().GetString("team") if err != nil { - return err + return fmt.Errorf("unable to get team flag: %w", err) } update, err := cmd.Flags().GetBool("update") @@ -101,18 +96,13 @@ func createCatalogRepository(cmd *cobra.Command, args []string) error { return err } - refresh, err := cmd.Flags().GetBool("refresh") - if err != nil { - return err - } - api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) _, _, getErr := m.GetCatalogRepository(org, repoCanonical) exists := getErr == nil if getErr != nil { - var apiErr *middleware.APIResponseError + var apiErr *apiclient.APIResponseError if !stderrors.As(getErr, &apiErr) || apiErr.StatusCode != http.StatusNotFound { return cyout.PrintWithOptions(cmd, nil, getErr, "failed to check if catalog repository exists", printer.Options{}) } @@ -124,27 +114,11 @@ func createCatalogRepository(cmd *cobra.Command, args []string) error { "unable to create catalog repository", printer.Options{}) } - var cr *models.ServiceCatalogSource if exists { - cr, _, err = m.UpdateCatalogRepository(org, repoCanonical, displayName, url, branch, cred, nil) - } else { - cr, _, err = m.CreateCatalogRepository(org, displayName, url, branch, cred, visibility, teamCanonical) - } - if err != nil { - errMsg := "unable to create catalog repository" - if exists { - errMsg = "unable to update catalog repository" - } - return cyout.PrintWithOptions(cmd, nil, err, errMsg, printer.Options{}) - } - - if refresh { - if _, _, refreshErr := m.RefreshCatalogRepositoryVersions(org, repoCanonical); refreshErr != nil { - // Print the successful create/update result before returning the refresh error - _ = cyout.PrintWithOptions(cmd, cr, nil, "", printer.Options{}) - return cyout.PrintWithOptions(cmd, nil, refreshErr, "unable to refresh catalog repository versions", printer.Options{}) - } + cr, _, err := m.UpdateCatalogRepository(org, repoCanonical, displayName, url, branch, cred, nil) + return cyout.PrintWithOptions(cmd, cr, err, "unable to update catalog repository", printer.Options{}) } - return cyout.PrintWithOptions(cmd, cr, nil, "", printer.Options{}) + cr, _, err := m.CreateCatalogRepository(org, displayName, url, branch, cred, visibility, teamCanonical) + return cyout.PrintWithOptions(cmd, cr, err, "unable to create catalog repository", printer.Options{}) } diff --git a/cmd/cycloid/catalogrepositories/delete.go b/cmd/catalogrepositories/delete.go similarity index 91% rename from cmd/cycloid/catalogrepositories/delete.go rename to cmd/catalogrepositories/delete.go index d0fad678a..33120aa27 100644 --- a/cmd/cycloid/catalogrepositories/delete.go +++ b/cmd/catalogrepositories/delete.go @@ -3,15 +3,15 @@ package catalogrepositories import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" ) func NewDeleteCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "delete [canonical...]", Aliases: []string{"rm"}, Args: cyargs.RequireArgsOrFlag("canonical"), @@ -39,7 +39,7 @@ func NewDeleteCommand() *cobra.Command { func deleteCatalogRepository(cmd *cobra.Command, args []string) error { api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) org, err := cyargs.GetOrg(cmd) if err != nil { diff --git a/cmd/cycloid/catalogrepositories/get.go b/cmd/catalogrepositories/get.go similarity index 89% rename from cmd/cycloid/catalogrepositories/get.go rename to cmd/catalogrepositories/get.go index a544d7fc6..1433d277d 100644 --- a/cmd/cycloid/catalogrepositories/get.go +++ b/cmd/catalogrepositories/get.go @@ -3,15 +3,15 @@ package catalogrepositories import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" + "github.com/cycloidio/cycloid-cli/gen/models" ) func NewGetCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "get [canonical...]", Args: cyargs.RequireArgsOrFlag("canonical"), ValidArgsFunction: cyargs.CompleteCatalogRepository, @@ -39,7 +39,7 @@ func NewGetCommand() *cobra.Command { func getCatalogRepository(cmd *cobra.Command, args []string) error { api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) org, err := cyargs.GetOrg(cmd) if err != nil { diff --git a/cmd/cycloid/catalogrepositories/list.go b/cmd/catalogrepositories/list.go similarity index 82% rename from cmd/cycloid/catalogrepositories/list.go rename to cmd/catalogrepositories/list.go index 7d9a53fa2..22d50b4ea 100644 --- a/cmd/cycloid/catalogrepositories/list.go +++ b/cmd/catalogrepositories/list.go @@ -3,12 +3,12 @@ package catalogrepositories import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" + "github.com/cycloidio/cycloid-cli/gen/models" ) var catalogSourceTableOptions = printer.Options{ @@ -17,7 +17,7 @@ var catalogSourceTableOptions = printer.Options{ } func NewListCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "list", Args: cobra.NoArgs, Short: "list the catalog repositories", @@ -33,7 +33,7 @@ func NewListCommand() *cobra.Command { func listCatalogRepositories(cmd *cobra.Command, args []string) error { api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) org, err := cyargs.GetOrg(cmd) if err != nil { diff --git a/cmd/cycloid/catalogrepositories/refresh.go b/cmd/catalogrepositories/refresh.go similarity index 92% rename from cmd/cycloid/catalogrepositories/refresh.go rename to cmd/catalogrepositories/refresh.go index b2b5d456a..fba233b70 100644 --- a/cmd/cycloid/catalogrepositories/refresh.go +++ b/cmd/catalogrepositories/refresh.go @@ -3,15 +3,15 @@ package catalogrepositories import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" ) func NewRefreshCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "refresh [canonical...]", Args: cyargs.RequireArgsOrFlag("canonical"), ValidArgsFunction: cyargs.CompleteCatalogRepository, @@ -39,7 +39,7 @@ func NewRefreshCommand() *cobra.Command { func refreshCatalogRepository(cmd *cobra.Command, args []string) error { api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) org, err := cyargs.GetOrg(cmd) if err != nil { diff --git a/cmd/cycloid/catalogrepositories/update.go b/cmd/catalogrepositories/update.go similarity index 54% rename from cmd/cycloid/catalogrepositories/update.go rename to cmd/catalogrepositories/update.go index 6defed5e6..c5e477c6e 100644 --- a/cmd/cycloid/catalogrepositories/update.go +++ b/cmd/catalogrepositories/update.go @@ -3,24 +3,21 @@ package catalogrepositories import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" ) func NewUpdateCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "update", Args: cobra.NoArgs, Short: "update a catalog repository", Example: ` # update a catalog repository cy --org my-org cr update --branch my-branch --cred my-cred --url "git@github.com:my/repo.git" --name my-catalog-name --canonical my-catalog-repository - - # update and immediately re-index all branches/tags so they are resolvable - cy --org my-org cr update --branch my-branch --url "git@github.com:my/repo.git" --name my-catalog-name --canonical my-catalog-repository --refresh `, RunE: updateCatalogRepository, } @@ -30,12 +27,14 @@ func NewUpdateCommand() *cobra.Command { cmd.MarkFlagRequired(cyargs.AddNameFlag(cmd)) cmd.MarkFlagRequired(cyargs.AddRepoBranchFlag(cmd)) cmd.MarkFlagRequired(cyargs.AddRepoURLFlag(cmd)) - cmd.Flags().Bool("refresh", true, "trigger a synchronous version re-index after update to make all branches and tags immediately resolvable") return cmd } func updateCatalogRepository(cmd *cobra.Command, args []string) error { + api := common.NewAPI() + m := apiclient.NewMiddleware(api) + org, err := cyargs.GetOrg(cmd) if err != nil { return err @@ -66,26 +65,6 @@ func updateCatalogRepository(cmd *cobra.Command, args []string) error { return err } - refresh, err := cmd.Flags().GetBool("refresh") - if err != nil { - return err - } - - api := common.NewAPI() - m := middleware.NewMiddleware(api) - cr, _, err := m.UpdateCatalogRepository(org, can, name, url, branch, cred, nil) - if err != nil { - return cyout.PrintWithOptions(cmd, nil, err, "unable to update catalog repository", printer.Options{}) - } - - if refresh { - if _, _, refreshErr := m.RefreshCatalogRepositoryVersions(org, can); refreshErr != nil { - // Print the successful update result before returning the refresh error - _ = cyout.PrintWithOptions(cmd, cr, nil, "", printer.Options{}) - return cyout.PrintWithOptions(cmd, nil, refreshErr, "unable to refresh catalog repository versions", printer.Options{}) - } - } - - return cyout.PrintWithOptions(cmd, cr, nil, "", printer.Options{}) + return cyout.PrintWithOptions(cmd, cr, err, "unable to update catalog repository", printer.Options{}) } diff --git a/cmd/cycloid/cloudaccounts/cmd.go b/cmd/cloudaccounts/cmd.go similarity index 96% rename from cmd/cycloid/cloudaccounts/cmd.go rename to cmd/cloudaccounts/cmd.go index 33c7944f4..5ea6a1ceb 100644 --- a/cmd/cycloid/cloudaccounts/cmd.go +++ b/cmd/cloudaccounts/cmd.go @@ -3,8 +3,8 @@ package cloudaccounts import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" "github.com/cycloidio/cycloid-cli/printer" + "github.com/cycloidio/cycloid-cli/gen/models" ) func NewCommands() *cobra.Command { diff --git a/cmd/cycloid/cloudaccounts/create.go b/cmd/cloudaccounts/create.go similarity index 90% rename from cmd/cycloid/cloudaccounts/create.go rename to cmd/cloudaccounts/create.go index a01b719d8..1fab2b5dd 100644 --- a/cmd/cycloid/cloudaccounts/create.go +++ b/cmd/cloudaccounts/create.go @@ -7,13 +7,13 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" - "github.com/cycloidio/cycloid-cli/internal/ptr" "github.com/cycloidio/cycloid-cli/printer" + "github.com/cycloidio/cycloid-cli/gen/models" + "github.com/cycloidio/cycloid-cli/utils/ptr" ) func NewCreateCommand() *cobra.Command { @@ -54,7 +54,7 @@ func create(cmd *cobra.Command, args []string) error { if err != nil { return err } - name, canonical, err = middleware.NameOrCanonical(&name, &canonical) + name, canonical, err = apiclient.NameOrCanonical(&name, &canonical) if err != nil { return err } @@ -93,14 +93,14 @@ func create(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) if cyargs.GetUpdate(cmd) { _, _, getErr := m.GetCloudAccount(org, canonical) if getErr == nil { return updateCloudAccount(cmd, args) } - var apiErr *middleware.APIResponseError + var apiErr *apiclient.APIResponseError if !stderrors.As(getErr, &apiErr) || apiErr.StatusCode != http.StatusNotFound { return cyout.PrintWithOptions(cmd, nil, getErr, "failed to check existing cloud account", printer.Options{}) } diff --git a/cmd/cycloid/cloudaccounts/credential.go b/cmd/cloudaccounts/credential.go similarity index 86% rename from cmd/cycloid/cloudaccounts/credential.go rename to cmd/cloudaccounts/credential.go index c2ae13703..83cb7ed29 100644 --- a/cmd/cycloid/cloudaccounts/credential.go +++ b/cmd/cloudaccounts/credential.go @@ -3,11 +3,11 @@ package cloudaccounts import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/credentials" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/credentials" "github.com/cycloidio/cycloid-cli/internal/cyargs" - "github.com/cycloidio/cycloid-cli/internal/ptr" + "github.com/cycloidio/cycloid-cli/gen/models" + "github.com/cycloidio/cycloid-cli/utils/ptr" ) // addCredentialFlags wires every flag a credential type might need on a @@ -19,7 +19,7 @@ func addCredentialFlags(cmd *cobra.Command) { // createInlineCredential creates a standalone Credential for an existing // cloud account (used by `cy cloud-account update --new-credential …`). -func createInlineCredential(cmd *cobra.Command, m middleware.Middleware, org, credType, name string) (*models.Credential, error) { +func createInlineCredential(cmd *cobra.Command, m apiclient.Middleware, org, credType, name string) (*models.Credential, error) { raw, err := credentials.BuildCredentialRaw(cmd, credType) if err != nil { return nil, err diff --git a/cmd/cycloid/cloudaccounts/delete.go b/cmd/cloudaccounts/delete.go similarity index 86% rename from cmd/cycloid/cloudaccounts/delete.go rename to cmd/cloudaccounts/delete.go index a9532ea22..9331893fa 100644 --- a/cmd/cycloid/cloudaccounts/delete.go +++ b/cmd/cloudaccounts/delete.go @@ -5,8 +5,8 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" ) @@ -30,7 +30,7 @@ func deleteCloudAccount(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) for _, canonical := range args { if _, err := m.DeleteCloudAccount(org, canonical); err != nil { diff --git a/cmd/cycloid/cloudaccounts/get.go b/cmd/cloudaccounts/get.go similarity index 86% rename from cmd/cycloid/cloudaccounts/get.go rename to cmd/cloudaccounts/get.go index 7cc958f5c..2ac83e643 100644 --- a/cmd/cycloid/cloudaccounts/get.go +++ b/cmd/cloudaccounts/get.go @@ -3,11 +3,11 @@ package cloudaccounts import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" + "github.com/cycloidio/cycloid-cli/gen/models" ) func NewGetCommand() *cobra.Command { @@ -30,7 +30,7 @@ func get(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) if len(args) == 1 { account, _, err := m.GetCloudAccount(org, args[0]) diff --git a/cmd/cycloid/cloudaccounts/list.go b/cmd/cloudaccounts/list.go similarity index 77% rename from cmd/cycloid/cloudaccounts/list.go rename to cmd/cloudaccounts/list.go index 224f57f8e..575b51bb8 100644 --- a/cmd/cycloid/cloudaccounts/list.go +++ b/cmd/cloudaccounts/list.go @@ -3,11 +3,11 @@ package cloudaccounts import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" + "github.com/cycloidio/cycloid-cli/gen/models" ) func NewListCommand() *cobra.Command { @@ -29,7 +29,7 @@ func list(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) accounts, _, err := m.ListCloudAccounts(org) return cyout.PrintWithOptions(cmd, accounts, err, "failed to list cloud accounts", cloudAccountTableOptions) diff --git a/cmd/cycloid/cloudaccounts/update.go b/cmd/cloudaccounts/update.go similarity index 90% rename from cmd/cycloid/cloudaccounts/update.go rename to cmd/cloudaccounts/update.go index bc4c8b7a6..7509ceb2e 100644 --- a/cmd/cycloid/cloudaccounts/update.go +++ b/cmd/cloudaccounts/update.go @@ -5,13 +5,13 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" - "github.com/cycloidio/cycloid-cli/internal/ptr" - "github.com/cycloidio/cycloid-cli/internal/utils" + "github.com/cycloidio/cycloid-cli/gen/models" + "github.com/cycloidio/cycloid-cli/utils" + "github.com/cycloidio/cycloid-cli/utils/ptr" ) func NewUpdateCommand() *cobra.Command { @@ -44,7 +44,7 @@ func updateCloudAccount(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) current, _, err := m.GetCloudAccount(org, canonical) if err != nil { diff --git a/cmd/cycloid/common/console_url.go b/cmd/common/console_url.go similarity index 100% rename from cmd/cycloid/common/console_url.go rename to cmd/common/console_url.go diff --git a/cmd/cycloid/common/flags.go b/cmd/common/flags.go similarity index 100% rename from cmd/cycloid/common/flags.go rename to cmd/common/flags.go diff --git a/cmd/cycloid/common/formsUtils.go b/cmd/common/formsUtils.go similarity index 94% rename from cmd/cycloid/common/formsUtils.go rename to cmd/common/formsUtils.go index 32fd441bc..eb9304d2e 100644 --- a/cmd/cycloid/common/formsUtils.go +++ b/cmd/common/formsUtils.go @@ -3,7 +3,7 @@ package common import ( "fmt" - "github.com/cycloidio/cycloid-cli/client/models" + "github.com/cycloidio/cycloid-cli/gen/models" ) func FormUseCaseToFormVars(stackConfig models.ServiceCatalogConfigs, useCaseName string) (models.FormVariables, error) { diff --git a/cmd/cycloid/common/helpers.go b/cmd/common/helpers.go similarity index 92% rename from cmd/cycloid/common/helpers.go rename to cmd/common/helpers.go index 5cabe63e4..e26b2bd30 100644 --- a/cmd/cycloid/common/helpers.go +++ b/cmd/common/helpers.go @@ -2,6 +2,7 @@ package common import ( "encoding/json" + "errors" "fmt" "os" "regexp" @@ -9,21 +10,23 @@ import ( "strings" "time" - "github.com/pkg/errors" "github.com/spf13/cobra" "github.com/spf13/viper" "github.com/cycloidio/cycloid-cli/config" ) -var orgRe = regexp.MustCompile(`\(\$ organization_canonical \$\)`) -var envRe = regexp.MustCompile(`\(\$ environment \$\)`) -var projRe = regexp.MustCompile(`\(\$ project \$\)`) +var ( + orgRe = regexp.MustCompile(`\(\$ organization_canonical \$\)`) + envRe = regexp.MustCompile(`\(\$ environment \$\)`) + projRe = regexp.MustCompile(`\(\$ project \$\)`) +) func RequiredPersistentFlag(withFlag func(cmd *cobra.Command) string, cmd *cobra.Command) { flagName := withFlag(cmd) cmd.MarkPersistentFlagRequired(flagName) } + func RequiredFlag(withFlag func(cmd *cobra.Command) string, cmd *cobra.Command) { flagName := withFlag(cmd) cmd.MarkFlagRequired(flagName) @@ -182,11 +185,11 @@ func GenerateCanonical(name string) string { // the field must be in dot notation // e.g. field='one.nested.key' value='myValue' // If the map is nil, it will be created -func UpdateMapField(field string, value string, m map[string]map[string]map[string]any) error { +func UpdateMapField(field, value string, m map[string]map[string]map[string]any) error { keys := strings.Split(field, ".") if len(keys) != 3 { - return errors.New("key=val update failed, you can only update a value using `section.group.var=value` syntax") + return fmt.Errorf("key=val update failed, you can only update a value using `section.group.var=value` syntax") } if m == nil { @@ -200,7 +203,7 @@ func UpdateMapField(field string, value string, m map[string]map[string]map[stri var data any err := json.Unmarshal([]byte(trimmedValue), &data) if err != nil { - return errors.Wrapf(err, "invalid JSON value in key=val update with value '%s'", trimmedValue) + return fmt.Errorf("invalid JSON value in key=val update with value '%s': %w", trimmedValue, err) } m[keys[0]][keys[1]][keys[2]] = data diff --git a/cmd/cycloid/completion.go b/cmd/completion.go similarity index 93% rename from cmd/cycloid/completion.go rename to cmd/completion.go index 259fe8878..eda7d127f 100644 --- a/cmd/cycloid/completion.go +++ b/cmd/completion.go @@ -1,4 +1,4 @@ -package cycloid +package cmd import ( "fmt" @@ -7,9 +7,7 @@ import ( "github.com/spf13/cobra" ) -var ( - supportedShells = []string{"bash", "fish", "zsh", "powershell"} -) +var supportedShells = []string{"bash", "fish", "zsh", "powershell"} // NewCompletionCmd returns the cobra command that outputs shell completion code func NewCompletionCmd() *cobra.Command { diff --git a/cmd/cycloid/components/cmd.go b/cmd/components/cmd.go similarity index 94% rename from cmd/cycloid/components/cmd.go rename to cmd/components/cmd.go index 7362d4e79..eed270911 100644 --- a/cmd/cycloid/components/cmd.go +++ b/cmd/components/cmd.go @@ -3,12 +3,12 @@ package components import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" "github.com/cycloidio/cycloid-cli/printer" + "github.com/cycloidio/cycloid-cli/gen/models" ) func NewCommands() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "components", Args: cobra.NoArgs, Aliases: []string{ diff --git a/cmd/cycloid/components/config.go b/cmd/components/config.go similarity index 100% rename from cmd/cycloid/components/config.go rename to cmd/components/config.go diff --git a/cmd/cycloid/components/config_get.go b/cmd/components/config_get.go similarity index 86% rename from cmd/cycloid/components/config_get.go rename to cmd/components/config_get.go index 346790d64..a382e8074 100644 --- a/cmd/cycloid/components/config_get.go +++ b/cmd/components/config_get.go @@ -3,8 +3,8 @@ package components import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" @@ -29,7 +29,7 @@ func getComponentConfig(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) config, _, err := m.GetComponentConfig(org, project, env, component) return cyout.PrintWithOptions(cmd, config, err, "failed to fetch config of component '"+component+"'", printer.Options{}) diff --git a/cmd/cycloid/components/create.go b/cmd/components/create.go similarity index 91% rename from cmd/cycloid/components/create.go rename to cmd/components/create.go index 67693a6d7..6d76b37d3 100644 --- a/cmd/cycloid/components/create.go +++ b/cmd/components/create.go @@ -4,15 +4,14 @@ import ( "fmt" "slices" - "github.com/pkg/errors" "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" + "github.com/cycloidio/cycloid-cli/gen/models" ) func NewCreateComponentCommand() *cobra.Command { @@ -77,12 +76,12 @@ func createComponent(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) // Resolve stack version: --stack-version (new) or legacy flags. tag, branch, hash, err := cyargs.ResolveStackVersionArg(cmd, m, org, stackRef) if err != nil { - return errors.Wrap(err, "failed to read stack version flags") + return fmt.Errorf("failed to read stack version flags: %w", err) } if update { @@ -98,7 +97,7 @@ func createComponent(cmd *cobra.Command, args []string) error { currentComponent := components[componentIndex] // Fetch base forms value from current component - var currentConfig = make(models.FormVariables) + currentConfig := make(models.FormVariables) if currentComponent.UseCase != "" { currentConfig, _, err = m.GetComponentConfig(org, project, env, component) if err != nil { diff --git a/cmd/cycloid/components/delete.go b/cmd/components/delete.go similarity index 86% rename from cmd/cycloid/components/delete.go rename to cmd/components/delete.go index 373375078..841e6e4e9 100644 --- a/cmd/cycloid/components/delete.go +++ b/cmd/components/delete.go @@ -3,8 +3,8 @@ package components import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" ) @@ -67,9 +67,9 @@ func deleteComponent(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) - opts := middleware.DeleteOptions{Force: force, SkipHooks: skipHooks, IgnoreConfigFilesErr: ignoreConfigFilesErr} + opts := apiclient.DeleteOptions{Force: force, SkipHooks: skipHooks, IgnoreConfigFilesErr: ignoreConfigFilesErr} for _, component := range args { _, err = m.DeleteComponent(org, project, env, component, opts) if err != nil { diff --git a/cmd/cycloid/components/get.go b/cmd/components/get.go similarity index 90% rename from cmd/cycloid/components/get.go rename to cmd/components/get.go index 416a53f56..330363c76 100644 --- a/cmd/cycloid/components/get.go +++ b/cmd/components/get.go @@ -3,11 +3,11 @@ package components import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" + "github.com/cycloidio/cycloid-cli/gen/models" ) func NewGetComponentCommand() *cobra.Command { @@ -63,7 +63,7 @@ func getComponent(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) if len(args) == 1 { c, _, err := m.GetComponent(org, project, env, args[0]) diff --git a/cmd/cycloid/components/list.go b/cmd/components/list.go similarity index 83% rename from cmd/cycloid/components/list.go rename to cmd/components/list.go index f4043d17c..c284c4408 100644 --- a/cmd/cycloid/components/list.go +++ b/cmd/components/list.go @@ -3,11 +3,11 @@ package components import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" + "github.com/cycloidio/cycloid-cli/gen/models" ) func NewGetComponentsCommand() *cobra.Command { @@ -40,7 +40,7 @@ func getComponents(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) components, _, err := m.ListComponents(org, project, env) errMsg := "failed to fetch list of components in '" + project + "', '" + env + "'" diff --git a/cmd/cycloid/components/migrate.go b/cmd/components/migrate.go similarity index 92% rename from cmd/cycloid/components/migrate.go rename to cmd/components/migrate.go index 6bcf6d6d1..f5eb5c90d 100644 --- a/cmd/cycloid/components/migrate.go +++ b/cmd/components/migrate.go @@ -3,8 +3,8 @@ package components import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" @@ -65,7 +65,7 @@ func migrate(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) compResponse, _, err := m.MigrateComponent(org, project, env, component, newProject, newEnv, newComponent, newComponentName) return cyout.PrintWithOptions(cmd, compResponse, err, "failed to migrate component", printer.Options{}) diff --git a/cmd/cycloid/components/update.go b/cmd/components/update.go similarity index 88% rename from cmd/cycloid/components/update.go rename to cmd/components/update.go index 443c35251..6409a2055 100644 --- a/cmd/cycloid/components/update.go +++ b/cmd/components/update.go @@ -1,16 +1,17 @@ package components import ( - "github.com/pkg/errors" + "fmt" + "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" - "github.com/cycloidio/cycloid-cli/internal/ptr" "github.com/cycloidio/cycloid-cli/printer" + "github.com/cycloidio/cycloid-cli/gen/models" + "github.com/cycloidio/cycloid-cli/utils/ptr" ) func NewUpdateComponentCommand() *cobra.Command { @@ -71,7 +72,7 @@ func updateComponent(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) currentComponent, _, err := m.GetComponent(org, project, env, component) if err != nil { @@ -83,7 +84,7 @@ func updateComponent(cmd *cobra.Command, args []string) error { } if useCase == "" && currentComponent.UseCase == "" { - return errors.New("cannot determine the use case, please fill it with -(-u)se-case flag") + return fmt.Errorf("cannot determine the use case, please fill it with -(-u)se-case flag") } else if useCase == "" { useCase = currentComponent.UseCase } @@ -91,7 +92,7 @@ func updateComponent(cmd *cobra.Command, args []string) error { // Resolve stack version: --stack-version (new) or legacy flags; empty = preserve current. tag, branch, hash, err := cyargs.ResolveStackVersionArg(cmd, m, org, stackRef) if err != nil { - return errors.Wrap(err, "failed to read stack version flags") + return fmt.Errorf("failed to read stack version flags: %w", err) } // If no version flag was specified, preserve the current component's version @@ -114,7 +115,7 @@ func updateComponent(cmd *cobra.Command, args []string) error { } } - var currentConfig = make(models.FormVariables) + currentConfig := make(models.FormVariables) if currentComponent.UseCase != "" { currentConfig, _, err = m.GetComponentConfig(org, project, env, component) if err != nil { diff --git a/cmd/cycloid/configrepositories/cmd.go b/cmd/configrepositories/cmd.go similarity index 93% rename from cmd/cycloid/configrepositories/cmd.go rename to cmd/configrepositories/cmd.go index 8a2d0eb27..41904db5b 100644 --- a/cmd/cycloid/configrepositories/cmd.go +++ b/cmd/configrepositories/cmd.go @@ -5,7 +5,7 @@ import ( ) func NewCommands() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "config-repository", Aliases: []string{ "config-repo", diff --git a/cmd/cycloid/configrepositories/create.go b/cmd/configrepositories/create.go similarity index 89% rename from cmd/cycloid/configrepositories/create.go rename to cmd/configrepositories/create.go index 6c2c2f9a8..209e88b2a 100644 --- a/cmd/cycloid/configrepositories/create.go +++ b/cmd/configrepositories/create.go @@ -7,15 +7,15 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" ) func NewCreateCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "create", Args: cobra.NoArgs, Short: "create a config repository", @@ -53,7 +53,7 @@ func createConfigRepository(cmd *cobra.Command, args []string) error { return err } - displayName, repoCanonical, err := middleware.NameOrCanonical(&name, &canonical) + displayName, repoCanonical, err := apiclient.NameOrCanonical(&name, &canonical) if err != nil { return err } @@ -84,12 +84,12 @@ func createConfigRepository(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) _, _, getErr := m.GetConfigRepository(org, repoCanonical) exists := getErr == nil if getErr != nil { - var apiErr *middleware.APIResponseError + var apiErr *apiclient.APIResponseError if !stderrors.As(getErr, &apiErr) || apiErr.StatusCode != http.StatusNotFound { return cyout.PrintWithOptions(cmd, nil, getErr, "failed to check if config repository exists", printer.Options{}) } diff --git a/cmd/cycloid/configrepositories/delete.go b/cmd/configrepositories/delete.go similarity index 91% rename from cmd/cycloid/configrepositories/delete.go rename to cmd/configrepositories/delete.go index 54bdcfb18..e92b48568 100644 --- a/cmd/cycloid/configrepositories/delete.go +++ b/cmd/configrepositories/delete.go @@ -3,15 +3,15 @@ package configrepositories import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" ) func NewDeleteCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "delete [canonical...]", Aliases: []string{"rm"}, Args: cyargs.RequireArgsOrFlag("canonical"), @@ -39,7 +39,7 @@ func NewDeleteCommand() *cobra.Command { func deleteConfigRepository(cmd *cobra.Command, args []string) error { api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) org, err := cyargs.GetOrg(cmd) if err != nil { diff --git a/cmd/cycloid/configrepositories/get.go b/cmd/configrepositories/get.go similarity index 89% rename from cmd/cycloid/configrepositories/get.go rename to cmd/configrepositories/get.go index 90dbca801..98166dd3f 100644 --- a/cmd/cycloid/configrepositories/get.go +++ b/cmd/configrepositories/get.go @@ -3,15 +3,15 @@ package configrepositories import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" + "github.com/cycloidio/cycloid-cli/gen/models" ) func NewGetCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "get [canonical...]", Args: cyargs.RequireArgsOrFlag("canonical"), ValidArgsFunction: cyargs.CompleteConfigRepository, @@ -39,7 +39,7 @@ func NewGetCommand() *cobra.Command { func getConfigRepository(cmd *cobra.Command, args []string) error { api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) org, err := cyargs.GetOrg(cmd) if err != nil { diff --git a/cmd/cycloid/configrepositories/list.go b/cmd/configrepositories/list.go similarity index 82% rename from cmd/cycloid/configrepositories/list.go rename to cmd/configrepositories/list.go index 95986c8b8..cd094943b 100644 --- a/cmd/cycloid/configrepositories/list.go +++ b/cmd/configrepositories/list.go @@ -3,12 +3,12 @@ package configrepositories import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" + "github.com/cycloidio/cycloid-cli/gen/models" ) var configRepoTableOptions = printer.Options{ @@ -17,7 +17,7 @@ var configRepoTableOptions = printer.Options{ } func NewListCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "list", Args: cobra.NoArgs, Short: "list the config repositories", @@ -33,7 +33,7 @@ func NewListCommand() *cobra.Command { func listConfigRepositories(cmd *cobra.Command, args []string) error { api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) org, err := cyargs.GetOrg(cmd) if err != nil { diff --git a/cmd/cycloid/configrepositories/update.go b/cmd/configrepositories/update.go similarity index 90% rename from cmd/cycloid/configrepositories/update.go rename to cmd/configrepositories/update.go index f13e63e75..5b3399cf7 100644 --- a/cmd/cycloid/configrepositories/update.go +++ b/cmd/configrepositories/update.go @@ -3,15 +3,15 @@ package configrepositories import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" ) func NewUpdateCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "update", Args: cobra.NoArgs, Short: "update a config repository", @@ -34,7 +34,7 @@ func NewUpdateCommand() *cobra.Command { func updateConfigRepository(cmd *cobra.Command, args []string) error { api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) org, err := cyargs.GetOrg(cmd) if err != nil { diff --git a/cmd/cycloid/credentials/cmd.go b/cmd/credentials/cmd.go similarity index 93% rename from cmd/cycloid/credentials/cmd.go rename to cmd/credentials/cmd.go index 8e8466e2c..ca456a9b4 100644 --- a/cmd/cycloid/credentials/cmd.go +++ b/cmd/credentials/cmd.go @@ -5,7 +5,7 @@ import ( ) func NewCommands() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "credential", Aliases: []string{ "creds", diff --git a/cmd/cycloid/credentials/common.go b/cmd/credentials/common.go similarity index 100% rename from cmd/cycloid/credentials/common.go rename to cmd/credentials/common.go diff --git a/cmd/cycloid/credentials/create.go b/cmd/credentials/create.go similarity index 93% rename from cmd/cycloid/credentials/create.go rename to cmd/credentials/create.go index 84344315e..a7b5efb6b 100644 --- a/cmd/cycloid/credentials/create.go +++ b/cmd/credentials/create.go @@ -5,16 +5,16 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" + "github.com/cycloidio/cycloid-cli/gen/models" ) func NewCreateCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "create [ssh|basic_auth|custom|aws|azure|azure_storage|gcp|elasticsearch|swift]", Short: "create a credential", Example: `# create a credential for basic authentication @@ -48,7 +48,7 @@ func NewCreateCommand() *cobra.Command { cyargs.AddCredentialPathPersistentFlag(cmd) cmd.PersistentFlags().Bool(cyargs.UpdateFlag, false, "update this credential if it already exists.") - var sshCmd = &cobra.Command{ + sshCmd := &cobra.Command{ Use: "ssh", Args: cobra.NoArgs, RunE: create, @@ -59,7 +59,7 @@ func NewCreateCommand() *cobra.Command { } sshCmd.MarkFlagRequired(cyargs.AddCredentialSSHKeyFlag(sshCmd)) - var basicAuthCmd = &cobra.Command{ + basicAuthCmd := &cobra.Command{ Use: "basic_auth", Args: cobra.NoArgs, RunE: create, @@ -71,7 +71,7 @@ func NewCreateCommand() *cobra.Command { cyargs.AddCredentialUsernameFlag(basicAuthCmd) cyargs.AddCredentialPasswordFlag(basicAuthCmd) - var customCmd = &cobra.Command{ + customCmd := &cobra.Command{ Use: "custom", Args: cobra.NoArgs, RunE: create, @@ -83,7 +83,7 @@ func NewCreateCommand() *cobra.Command { cyargs.AddCredentialFieldFlag(customCmd) cyargs.AddCredentialFieldFileFlag(customCmd) - var awsCmd = &cobra.Command{ + awsCmd := &cobra.Command{ Use: "aws", Args: cobra.NoArgs, RunE: create, @@ -95,7 +95,7 @@ func NewCreateCommand() *cobra.Command { awsCmd.MarkFlagRequired(cyargs.AddCredentialAccessKeyFlag(awsCmd)) awsCmd.MarkFlagRequired(cyargs.AddCredentialSecretKeyFlag(awsCmd)) - var azureCmd = &cobra.Command{ + azureCmd := &cobra.Command{ Use: "azure", Args: cobra.NoArgs, RunE: create, @@ -109,7 +109,7 @@ func NewCreateCommand() *cobra.Command { azureCmd.MarkFlagRequired(cyargs.AddCredentialSubscriptionIDFlag(azureCmd)) azureCmd.MarkFlagRequired(cyargs.AddCredentialTenantIDFlag(azureCmd)) - var azureStorageCmd = &cobra.Command{ + azureStorageCmd := &cobra.Command{ Use: "azure_storage", Args: cobra.NoArgs, RunE: create, @@ -121,7 +121,7 @@ func NewCreateCommand() *cobra.Command { azureStorageCmd.MarkFlagRequired(cyargs.AddCredentialAccountNameFlag(azureStorageCmd)) azureStorageCmd.MarkFlagRequired(cyargs.AddCredentialAccessKeyFlag(azureStorageCmd)) - var gcpCmd = &cobra.Command{ + gcpCmd := &cobra.Command{ Use: "gcp", Args: cobra.NoArgs, RunE: create, @@ -132,7 +132,7 @@ func NewCreateCommand() *cobra.Command { } gcpCmd.MarkFlagRequired(cyargs.AddCredentialJSONKeyFlag(gcpCmd)) - var swiftCmd = &cobra.Command{ + swiftCmd := &cobra.Command{ Use: "swift", Args: cobra.NoArgs, RunE: create, @@ -147,7 +147,7 @@ func NewCreateCommand() *cobra.Command { swiftCmd.MarkFlagRequired(cyargs.AddCredentialAuthURLFlag(swiftCmd)) swiftCmd.MarkFlagRequired(cyargs.AddCredentialDomainIDFlag(swiftCmd)) - var elasticsearchCmd = &cobra.Command{ + elasticsearchCmd := &cobra.Command{ Use: "elasticsearch", Args: cobra.NoArgs, RunE: create, @@ -201,7 +201,7 @@ func create(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) if cyargs.GetUpdate(cmd) { creds, _, err := m.ListCredentials(org, credentialType) diff --git a/cmd/cycloid/credentials/delete.go b/cmd/credentials/delete.go similarity index 87% rename from cmd/cycloid/credentials/delete.go rename to cmd/credentials/delete.go index e4709e707..5c1b6ab2b 100644 --- a/cmd/cycloid/credentials/delete.go +++ b/cmd/credentials/delete.go @@ -3,20 +3,19 @@ package credentials import ( "fmt" - "github.com/pkg/errors" "github.com/spf13/cobra" "golang.org/x/exp/slices" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" + "github.com/cycloidio/cycloid-cli/gen/models" ) func NewDeleteCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "delete [canonicals...]", Args: cobra.OnlyValidArgs, ValidArgsFunction: cyargs.CompleteCredentialCanonical, @@ -33,7 +32,7 @@ cy --org my-org credential delete credential-canonical-1 credential-canonical-2 func del(cmd *cobra.Command, args []string) error { api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) org, err := cyargs.GetOrg(cmd) if err != nil { @@ -43,7 +42,7 @@ func del(cmd *cobra.Command, args []string) error { credentialFlag, _ := cyargs.GetCredentialCanonical(cmd) credentialPath, _ := cyargs.GetCredentialPath(cmd) if credentialPath == "" && credentialFlag == "" && len(args) == 0 { - return errors.New("please fill --canonical or --path flags or pass canonicals as arguments") + return fmt.Errorf("please fill --canonical or --path flags or pass canonicals as arguments") } if credentialPath != "" && credentialFlag == "" { diff --git a/cmd/cycloid/credentials/get.go b/cmd/credentials/get.go similarity index 90% rename from cmd/cycloid/credentials/get.go rename to cmd/credentials/get.go index 8e8e9214a..5f50495f3 100644 --- a/cmd/cycloid/credentials/get.go +++ b/cmd/credentials/get.go @@ -3,16 +3,15 @@ package credentials import ( "fmt" - "github.com/pkg/errors" "github.com/spf13/cobra" "golang.org/x/exp/slices" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" + "github.com/cycloidio/cycloid-cli/gen/models" ) // credentialGetTableOptions excludes the Raw field (sensitive) but shows Keys. @@ -22,7 +21,7 @@ var credentialGetTableOptions = printer.Options{ } func NewGetCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "get [canonical...]", Args: cobra.ArbitraryArgs, ValidArgsFunction: cyargs.CompleteCredentialCanonical, @@ -48,7 +47,7 @@ func NewGetCommand() *cobra.Command { func get(cmd *cobra.Command, args []string) error { api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) org, err := cyargs.GetOrg(cmd) if err != nil { @@ -106,7 +105,7 @@ func get(cmd *cobra.Command, args []string) error { } else if len(args) == 1 { credential = args[0] } else { - return errors.New("please fill --canonical or --path flags or as argument") + return fmt.Errorf("please fill --canonical or --path flags or as argument") } c, _, err := m.GetCredential(org, credential) diff --git a/cmd/cycloid/credentials/list.go b/cmd/credentials/list.go similarity index 81% rename from cmd/cycloid/credentials/list.go rename to cmd/credentials/list.go index bc457b7b3..d42779b02 100644 --- a/cmd/cycloid/credentials/list.go +++ b/cmd/credentials/list.go @@ -3,12 +3,12 @@ package credentials import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" + "github.com/cycloidio/cycloid-cli/gen/models" ) var credentialTableOptions = printer.Options{ @@ -17,7 +17,7 @@ var credentialTableOptions = printer.Options{ } func NewListCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "list", Args: cobra.NoArgs, Short: "list the credentials", @@ -32,7 +32,7 @@ func NewListCommand() *cobra.Command { func list(cmd *cobra.Command, args []string) error { api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) org, err := cyargs.GetOrg(cmd) if err != nil { diff --git a/cmd/cycloid/credentials/raw.go b/cmd/credentials/raw.go similarity index 94% rename from cmd/cycloid/credentials/raw.go rename to cmd/credentials/raw.go index 7b13ec1f2..5b3b4fd68 100644 --- a/cmd/cycloid/credentials/raw.go +++ b/cmd/credentials/raw.go @@ -5,11 +5,10 @@ import ( "os" "strings" - "github.com/pkg/errors" "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" "github.com/cycloidio/cycloid-cli/internal/cyargs" + "github.com/cycloidio/cycloid-cli/gen/models" ) // AddAllRawFlags registers every flag that any credential type may consume. @@ -51,7 +50,7 @@ func BuildCredentialRaw(cmd *cobra.Command, credType string) (*models.Credential } sshKey, err := os.ReadFile(sshKeyPath) if err != nil { - return nil, errors.Wrap(err, "unable to read SSH key") + return nil, fmt.Errorf("unable to read SSH key: %w", err) } return &models.CredentialRaw{SSHKey: string(sshKey)}, nil @@ -81,7 +80,7 @@ func BuildCredentialRaw(cmd *cobra.Command, credType string) (*models.Credential for field, path := range fileFields { content, err := os.ReadFile(path) if err != nil { - return nil, errors.Wrap(err, fmt.Sprintf("unable to read file at path %q", path)) + return nil, fmt.Errorf("unable to read file at path %q: %w", path, err) } fields[field] = strings.TrimSuffix(string(content), "\n") } @@ -140,7 +139,7 @@ func BuildCredentialRaw(cmd *cobra.Command, credType string) (*models.Credential } jsonKey, err := os.ReadFile(jsonKeyPath) if err != nil { - return nil, errors.Wrap(err, "unable to read JSON key") + return nil, fmt.Errorf("unable to read JSON key: %w", err) } return &models.CredentialRaw{JSONKey: string(jsonKey)}, nil @@ -159,7 +158,7 @@ func BuildCredentialRaw(cmd *cobra.Command, credType string) (*models.Credential } caCert, err := os.ReadFile(caCertPath) if err != nil { - return nil, errors.Wrap(err, "unable to read CA cert") + return nil, fmt.Errorf("unable to read CA cert: %w", err) } return &models.CredentialRaw{ Username: username, diff --git a/cmd/cycloid/credentials/update.go b/cmd/credentials/update.go similarity index 93% rename from cmd/cycloid/credentials/update.go rename to cmd/credentials/update.go index 914905932..0aec06eae 100644 --- a/cmd/cycloid/credentials/update.go +++ b/cmd/credentials/update.go @@ -5,15 +5,15 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" ) func NewUpdateCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "update [ssh|basic_auth|custom|aws|azure|azure_storage|gcp|elasticsearch|swift]", Args: cobra.NoArgs, Short: "update a credential", @@ -54,7 +54,7 @@ func NewUpdateCommand() *cobra.Command { } // SSH - var sshCmd = &cobra.Command{ + sshCmd := &cobra.Command{ Use: "ssh", Args: cobra.NoArgs, RunE: update, @@ -66,7 +66,7 @@ func NewUpdateCommand() *cobra.Command { sshCmd.MarkFlagRequired(cyargs.AddCredentialSSHKeyFlag(sshCmd)) // Basic auth - var basicAuthCmd = &cobra.Command{ + basicAuthCmd := &cobra.Command{ Use: "basic_auth", Args: cobra.NoArgs, RunE: update, @@ -79,7 +79,7 @@ func NewUpdateCommand() *cobra.Command { cyargs.AddCredentialPasswordFlag(basicAuthCmd) // Custom - var customCmd = &cobra.Command{ + customCmd := &cobra.Command{ Use: "custom", Args: cobra.NoArgs, RunE: update, @@ -93,7 +93,7 @@ func NewUpdateCommand() *cobra.Command { cyargs.AddCredentialFieldFileFlag(customCmd) // AWS - var awsCmd = &cobra.Command{ + awsCmd := &cobra.Command{ Use: "aws", Args: cobra.NoArgs, RunE: update, @@ -106,7 +106,7 @@ func NewUpdateCommand() *cobra.Command { awsCmd.MarkFlagRequired(cyargs.AddCredentialSecretKeyFlag(awsCmd)) // Azure - var azureCmd = &cobra.Command{ + azureCmd := &cobra.Command{ Use: "azure", Args: cobra.NoArgs, RunE: update, @@ -121,7 +121,7 @@ func NewUpdateCommand() *cobra.Command { azureCmd.MarkFlagRequired(cyargs.AddCredentialTenantIDFlag(azureCmd)) // Azure Storage - var azureStorageCmd = &cobra.Command{ + azureStorageCmd := &cobra.Command{ Use: "azure_storage", Args: cobra.NoArgs, RunE: update, @@ -134,7 +134,7 @@ func NewUpdateCommand() *cobra.Command { azureStorageCmd.MarkFlagRequired(cyargs.AddCredentialAccessKeyFlag(azureStorageCmd)) // GCP - var gcpCmd = &cobra.Command{ + gcpCmd := &cobra.Command{ Use: "gcp", Args: cobra.NoArgs, RunE: update, @@ -146,7 +146,7 @@ func NewUpdateCommand() *cobra.Command { gcpCmd.MarkFlagRequired(cyargs.AddCredentialJSONKeyFlag(gcpCmd)) // Swift - var swiftCmd = &cobra.Command{ + swiftCmd := &cobra.Command{ Use: "swift", Args: cobra.NoArgs, RunE: update, @@ -162,7 +162,7 @@ func NewUpdateCommand() *cobra.Command { swiftCmd.MarkFlagRequired(cyargs.AddCredentialDomainIDFlag(swiftCmd)) // Elasticsearch - var elasticsearchCmd = &cobra.Command{ + elasticsearchCmd := &cobra.Command{ Use: "elasticsearch", Args: cobra.NoArgs, RunE: update, @@ -205,7 +205,7 @@ func NewUpdateCommand() *cobra.Command { // * swift: auth_url, username, password, domain_id, tenant_id func update(cmd *cobra.Command, args []string) error { api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) credT := cmd.CalledAs() org, err := cyargs.GetOrg(cmd) diff --git a/cmd/cycloid/cloudaccounts/cmd_test.go b/cmd/cycloid/cloudaccounts/cmd_test.go deleted file mode 100644 index 7d9e14f9e..000000000 --- a/cmd/cycloid/cloudaccounts/cmd_test.go +++ /dev/null @@ -1,69 +0,0 @@ -package cloudaccounts - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestCloudAccountsCommandTree(t *testing.T) { - t.Parallel() - root := NewCommands() - assert.Equal(t, "cloud-account", root.Name()) - - names := make(map[string]int) - for _, c := range root.Commands() { - names[c.Name()]++ - } - - require.Equal(t, 1, names["list"]) - require.Equal(t, 1, names["get"]) - require.Equal(t, 1, names["create"]) - require.Equal(t, 1, names["update"]) - require.Equal(t, 1, names["delete"]) -} - -func TestCloudAccountCreateFlags(t *testing.T) { - t.Parallel() - cmd := NewCreateCommand() - - require.NotNil(t, cmd.Flags().Lookup("cloud-provider"), "cloud-provider flag must be registered") - require.NotNil(t, cmd.Flags().Lookup("credential"), "credential flag must be registered") - require.NotNil(t, cmd.Flags().Lookup("new-credential"), "new-credential flag must be registered") -} - -func TestCloudAccountCreateHasUpdateFlag(t *testing.T) { - t.Parallel() - cmd := NewCreateCommand() - f := cmd.Flags().Lookup("update") - require.NotNil(t, f, "create must carry --update for upsert") - assert.Equal(t, "bool", f.Value.Type()) -} - -func TestCloudAccountUpdateNoUpdateFlag(t *testing.T) { - t.Parallel() - cmd := NewUpdateCommand() - // update subcommand is always an update; no upsert --update flag - assert.Nil(t, cmd.Flags().Lookup("update")) -} - -func TestCloudAccountUpdateRequiresCanonical(t *testing.T) { - t.Parallel() - cmd := NewUpdateCommand() - f := cmd.Flags().Lookup("cloud-account") - require.NotNil(t, f, "update must require --cloud-account (canonical)") -} - -func TestCloudAccountNameFallsBackToCanonical(t *testing.T) { - t.Parallel() - // cloudAccountName() is exercised via the cobra command flags; verify - // the function directly: when --name is empty it should use --cloud-account. - cmd := NewCreateCommand() - require.NoError(t, cmd.Flags().Set("cloud-account", "my-canonical")) - require.NoError(t, cmd.Flags().Set("cloud-provider", "aws")) - - name, err := cloudAccountName(cmd) - require.NoError(t, err) - assert.Equal(t, "my-canonical", name, "name must fall back to canonical when --name is absent") -} diff --git a/cmd/cycloid/common/console_url_test.go b/cmd/cycloid/common/console_url_test.go deleted file mode 100644 index b8d700e8a..000000000 --- a/cmd/cycloid/common/console_url_test.go +++ /dev/null @@ -1,20 +0,0 @@ -package common - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestPipelineBuildConsoleURL(t *testing.T) { - t.Parallel() - - u, ok := PipelineBuildConsoleURL("", "o", "p", "e", "c", "pl", "j", "42") - assert.False(t, ok) - assert.Empty(t, u) - - u, ok = PipelineBuildConsoleURL("https://console.example.com/", "my org", "p", "e", "c", "pl", "j", "99") - require.True(t, ok) - assert.Equal(t, "https://console.example.com/organizations/my%20org/projects/p/environments/e/components/c/pipelines/pl/jobs/j/builds/99", u) -} diff --git a/cmd/cycloid/common/helpers_test.go b/cmd/cycloid/common/helpers_test.go deleted file mode 100644 index d0606dd61..000000000 --- a/cmd/cycloid/common/helpers_test.go +++ /dev/null @@ -1,113 +0,0 @@ -package common - -import "testing" - -func TestUpdateMapField(t *testing.T) { - type Args struct { - field string - value string - m map[string]map[string]map[string]any - } - tests := []struct { - name string - args Args - wantErr bool - }{ - // TODO: Add test cases. - { - name: "StringDoubleQuote", - args: Args{ - field: "section.group.string", - value: `"my-string"`, - m: map[string]map[string]map[string]any{ - "section": {"group": {"string": "my-string"}}, - }, - }, - wantErr: false, - }, - { - name: "StringSimpleQuote", - args: Args{ - field: "section.group.string", - value: `'my-string'`, - m: map[string]map[string]map[string]any{ - "section": {"group": {"string": "my-string"}}, - }, - }, - wantErr: false, - }, - { - name: "StringNoQuote", - args: Args{ - field: "section.group.string", - value: `my-string`, - m: map[string]map[string]map[string]any{ - "section": {"group": {"string": "my-string"}}, - }, - }, - wantErr: false, - }, - { - name: "Int", - args: Args{ - field: "section.group.int", - value: `1`, - m: map[string]map[string]map[string]any{ - "section": {"group": {"int": 1}}, - }, - }, - wantErr: false, - }, - { - name: "IntAsString", - args: Args{ - field: "section.group.string", - value: `"1"`, - m: map[string]map[string]map[string]any{ - "section": {"group": {"string": "1"}}, - }, - }, - wantErr: false, - }, - { - name: "Array", - args: Args{ - field: "section.group.array", - value: `["hello", "world"]`, - m: map[string]map[string]map[string]any{ - "section": {"group": {"array": []string{"hello", "world"}}}, - }, - }, - wantErr: false, - }, - { - name: "ArraySingleValue", - args: Args{ - field: "section.group.array", - value: `["hi"]`, - m: map[string]map[string]map[string]any{ - "section": {"group": {"array": []string{"hi"}}}, - }, - }, - wantErr: false, - }, - { - name: "Map", - args: Args{ - field: "section.group.array", - value: `{"hello": "world"}`, - m: map[string]map[string]map[string]any{ - "section": {"group": {"array": map[string]string{"hello": "world"}}}, - }, - }, - wantErr: false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if err := UpdateMapField(tt.args.field, tt.args.value, tt.args.m); (err != nil) != tt.wantErr { - t.Errorf("UpdateMapField() error = %v, wantErr %v", err, tt.wantErr) - } - }) - } -} diff --git a/cmd/cycloid/credentials/create_test.go b/cmd/cycloid/credentials/create_test.go deleted file mode 100644 index 8fa24446b..000000000 --- a/cmd/cycloid/credentials/create_test.go +++ /dev/null @@ -1,87 +0,0 @@ -package credentials - -import ( - "testing" - - "github.com/stretchr/testify/assert" - - "github.com/cycloidio/cycloid-cli/client/models" -) - -func TestDefaultCredentialPath(t *testing.T) { - t.Run("keep explicit path", func(t *testing.T) { - assert.Equal(t, "explicit-path", defaultCredentialPath("explicit-path", "canonical", "name")) - }) - - t.Run("fallback to canonical", func(t *testing.T) { - assert.Equal(t, "my-canonical", defaultCredentialPath("", "my-canonical", "name")) - }) - - t.Run("fallback to name when canonical missing", func(t *testing.T) { - assert.Equal(t, "my-name", defaultCredentialPath("", "", "my-name")) - }) - - t.Run("CLI-104 name-only derives path like create", func(t *testing.T) { - assert.Equal(t, "testflotmp", defaultCredentialPath("", "", "testflotmp")) - }) - - t.Run("empty when no identifier", func(t *testing.T) { - assert.Equal(t, "", defaultCredentialPath("", "", "")) - }) -} - -func TestFindCredentialForUpdate(t *testing.T) { - credentials := []*models.CredentialSimple{ - { - Canonical: ptr("cred-canonical"), - Path: ptr("cred-path"), - Name: ptr("cred-name"), - }, - { - Canonical: ptr("another-canonical"), - Path: ptr("another-path"), - Name: ptr("another-name"), - }, - } - - t.Run("match by canonical first", func(t *testing.T) { - got := findCredentialForUpdate(credentials, "cred-canonical", "another-path", "another-name") - assert.NotNil(t, got) - assert.Equal(t, "cred-canonical", *got.Canonical) - }) - - t.Run("match by path when canonical missing", func(t *testing.T) { - got := findCredentialForUpdate(credentials, "", "cred-path", "") - assert.NotNil(t, got) - assert.Equal(t, "cred-canonical", *got.Canonical) - }) - - t.Run("match by name when canonical and path missing", func(t *testing.T) { - got := findCredentialForUpdate(credentials, "", "", "cred-name") - assert.NotNil(t, got) - assert.Equal(t, "cred-canonical", *got.Canonical) - }) - - // CLI-104: `create --name X --update` leaves canonical empty; path defaults from name (e.g. testflotmp). - t.Run("match by path from name defaulting (CLI-104)", func(t *testing.T) { - issue := []*models.CredentialSimple{ - { - Canonical: ptr("testflotmp"), - Path: ptr("testflotmp"), - Name: ptr("testflotmp"), - }, - } - got := findCredentialForUpdate(issue, "", "testflotmp", "testflotmp") - assert.NotNil(t, got) - assert.Equal(t, "testflotmp", *got.Canonical) - }) - - t.Run("no match", func(t *testing.T) { - got := findCredentialForUpdate(credentials, "", "missing-path", "missing-name") - assert.Nil(t, got) - }) -} - -func ptr(value string) *string { - return &value -} diff --git a/cmd/cycloid/environmenttypes/cmd_test.go b/cmd/cycloid/environmenttypes/cmd_test.go deleted file mode 100644 index 43a809d57..000000000 --- a/cmd/cycloid/environmenttypes/cmd_test.go +++ /dev/null @@ -1,68 +0,0 @@ -package environmenttypes - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestEnvironmentTypesCommandTree(t *testing.T) { - t.Parallel() - root := NewCommands() - assert.Equal(t, "environment-type", root.Name()) - - names := make(map[string]int) - for _, c := range root.Commands() { - names[c.Name()]++ - } - - require.Equal(t, 1, names["list"]) - require.Equal(t, 1, names["get"]) - require.Equal(t, 1, names["create"]) - require.Equal(t, 1, names["update"]) - require.Equal(t, 1, names["delete"]) -} - -func TestEnvironmentTypeCreateFlags(t *testing.T) { - t.Parallel() - cmd := NewCreateCommand() - - require.NotNil(t, cmd.Flags().Lookup("color"), "color flag must be registered") - require.NotNil(t, cmd.Flags().Lookup("environment-type-name"), "environment-type-name flag must be registered") - require.NotNil(t, cmd.Flags().Lookup("environment-type"), "environment-type (canonical) flag must be registered") -} - -func TestEnvironmentTypeCreateHasUpdateFlag(t *testing.T) { - t.Parallel() - cmd := NewCreateCommand() - f := cmd.Flags().Lookup("update") - require.NotNil(t, f, "create must carry --update for upsert") - assert.Equal(t, "bool", f.Value.Type()) -} - -func TestEnvironmentTypeUpdateNoUpdateFlag(t *testing.T) { - t.Parallel() - cmd := NewUpdateCommand() - // update subcommand is always an update; no upsert --update flag - assert.Nil(t, cmd.Flags().Lookup("update")) -} - -func TestAppendUniqueArg(t *testing.T) { - t.Parallel() - - t.Run("appends new value", func(t *testing.T) { - result := appendUniqueArg([]string{"a", "b"}, "c") - assert.Equal(t, []string{"a", "b", "c"}, result) - }) - - t.Run("deduplicates existing value", func(t *testing.T) { - result := appendUniqueArg([]string{"a", "b"}, "b") - assert.Equal(t, []string{"a", "b"}, result) - }) - - t.Run("works on empty slice", func(t *testing.T) { - result := appendUniqueArg(nil, "x") - assert.Equal(t, []string{"x"}, result) - }) -} diff --git a/cmd/cycloid/middleware/catalog_repositories_test.go b/cmd/cycloid/middleware/catalog_repositories_test.go deleted file mode 100644 index 02381dec7..000000000 --- a/cmd/cycloid/middleware/catalog_repositories_test.go +++ /dev/null @@ -1,32 +0,0 @@ -package middleware_test - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestListCatalogRepositories(t *testing.T) { - m := config.Middleware - - repos, _, err := m.ListCatalogRepositories(config.Org) - require.NoError(t, err) - assert.NotEmpty(t, repos) -} - -func TestGetCatalogRepository(t *testing.T) { - m := config.Middleware - - repo, _, err := m.GetCatalogRepository(config.Org, *config.CatalogRepo.Canonical) - require.NoError(t, err) - assert.Equal(t, *config.CatalogRepo.Canonical, *repo.Canonical) -} - -func TestRefreshCatalogRepository(t *testing.T) { - m := config.Middleware - - changes, _, err := m.RefreshCatalogRepository(config.Org, *config.CatalogRepo.Canonical) - require.NoError(t, err) - assert.NotNil(t, changes) -} diff --git a/cmd/cycloid/middleware/component_pipelines_jobs_builds_test.go b/cmd/cycloid/middleware/component_pipelines_jobs_builds_test.go deleted file mode 100644 index d5f93dceb..000000000 --- a/cmd/cycloid/middleware/component_pipelines_jobs_builds_test.go +++ /dev/null @@ -1,23 +0,0 @@ -package middleware_test - -import ( - "fmt" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestGetBuilds(t *testing.T) { - m := config.Middleware - - pipelineName := fmt.Sprintf("%s-%s-%s", *config.Project.Canonical, *config.Environment.Canonical, *config.Component.Canonical) - - jobs, _, err := m.GetJobs(config.Org, *config.Project.Canonical, *config.Environment.Canonical, *config.Component.Canonical, pipelineName) - require.NoError(t, err) - require.NotEmpty(t, jobs, "expected at least one job in the default component pipeline") - - builds, _, err := m.GetBuilds(config.Org, *config.Project.Canonical, *config.Environment.Canonical, *config.Component.Canonical, pipelineName, *jobs[0].Name) - require.NoError(t, err) - assert.NotNil(t, builds) -} diff --git a/cmd/cycloid/middleware/component_pipelines_jobs_test.go b/cmd/cycloid/middleware/component_pipelines_jobs_test.go deleted file mode 100644 index d7d24ac2d..000000000 --- a/cmd/cycloid/middleware/component_pipelines_jobs_test.go +++ /dev/null @@ -1,19 +0,0 @@ -package middleware_test - -import ( - "fmt" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestGetJobs(t *testing.T) { - m := config.Middleware - - pipelineName := fmt.Sprintf("%s-%s-%s", *config.Project.Canonical, *config.Environment.Canonical, *config.Component.Canonical) - - jobs, _, err := m.GetJobs(config.Org, *config.Project.Canonical, *config.Environment.Canonical, *config.Component.Canonical, pipelineName) - require.NoError(t, err) - assert.NotNil(t, jobs) -} diff --git a/cmd/cycloid/middleware/component_pipelines_test.go b/cmd/cycloid/middleware/component_pipelines_test.go deleted file mode 100644 index 232c19b66..000000000 --- a/cmd/cycloid/middleware/component_pipelines_test.go +++ /dev/null @@ -1,144 +0,0 @@ -package middleware_test - -import ( - "fmt" - "strconv" - "testing" - "time" - - "github.com/stretchr/testify/require" -) - -func TestComponentPipeline(t *testing.T) { - m := config.Middleware - - component, err := config.NewTestComponent( - *config.Project.Canonical, *config.Environment.Canonical, t.Name(), config.Org+":"+pipelineTestStackCanonical, pipelineTestStackUseCase, "", "", *config.CatalogRepoVersionStacks.CommitHash, pipelineTestDefaultVars, - ) - if err != nil { - t.Errorf("failed to setup base component for test %q: %v", t.Name(), err) - } - - t.Run("GetPipeline", func(t *testing.T) { - pipelineName := fmt.Sprintf("%s-%s-%s", *config.Project.Canonical, *config.Environment.Canonical, *component.Canonical) - got, _, err := m.GetPipeline(config.Org, *config.Project.Canonical, *config.Environment.Canonical, *component.Canonical, pipelineName) - if err != nil { - t.Errorf("middleware.GetComponentPipelines() error = %v", err) - return - } - - got.Component.Project.Owner = component.Project.Owner - require.Equal(t, *got.Component, *component) - }) - - t.Run("PausePipeline", func(t *testing.T) { - pipelineName := fmt.Sprintf("%s-%s-%s", *config.Project.Canonical, *config.Environment.Canonical, *component.Canonical) - _, err := m.PausePipeline(config.Org, *config.Project.Canonical, *config.Environment.Canonical, *component.Canonical, pipelineName) - if err != nil { - t.Errorf("%s error = %v", t.Name(), err) - return - } - }) - - t.Run("UnpausePipeline", func(t *testing.T) { - pipelineName := fmt.Sprintf("%s-%s-%s", *config.Project.Canonical, *config.Environment.Canonical, *component.Canonical) - _, err := m.UnpausePipeline(config.Org, *config.Project.Canonical, *config.Environment.Canonical, *component.Canonical, pipelineName) - if err != nil { - t.Errorf("%s error = %v", t.Name(), err) - return - } - }) - - t.Run("SynchedPipelineOk", func(t *testing.T) { - pipelineName := fmt.Sprintf("%s-%s-%s", *config.Project.Canonical, *config.Environment.Canonical, *component.Canonical) - got, _, err := m.SyncedPipeline(config.Org, *config.Project.Canonical, *config.Environment.Canonical, *component.Canonical, pipelineName) - if err != nil { - t.Errorf("%s error = %v", t.Name(), err) - return - } - - if *got.Synced != "synced" { - t.Errorf("pipeline must be in sync: %v", *got) - } - }) - - t.Run("UpdatePipelineAndGetJobs", func(t *testing.T) { - newPipeline := `--- -jobs: -- name: job-hello-world - build_logs_to_retain: 1 - plan: - - task: hello-world - config: - platform: linux - image_resource: - type: registry-image - source: {repository: busybox, tag: latest} - run: - path: /bin/sh - args: - - -ec - - | - echo ${MESSAGE} - params: - MESSAGE: ((message)) -` - pipelineName := fmt.Sprintf("%s-%s-%s", *config.Project.Canonical, *config.Environment.Canonical, *component.Canonical) - updatedPipeline, _, err := m.UpdatePipeline(config.Org, *config.Project.Canonical, *config.Environment.Canonical, *component.Canonical, pipelineName, newPipeline, "---\nmessage: hello", false) - if err != nil { - t.Errorf("%s error = %v", t.Name(), err) - return - } - - pipelineJobs, _, err := m.GetJobs(config.Org, *updatedPipeline.Project.Canonical, *updatedPipeline.Environment.Canonical, *updatedPipeline.Component.Canonical, *updatedPipeline.Name) - if err != nil { - t.Logf("failed to get jobs in pipeline '%s' in test '%s': %s", *updatedPipeline.Name, t.Name(), err) - return - } - - if len(pipelineJobs) != 1 { - t.Errorf("invalid number of jobs, must be only one, got: %d", len(pipelineJobs)) - return - } - - if *pipelineJobs[0].Name != "job-hello-world" { - t.Errorf("job name should be 'job-hello-world' as in the updated pipeline, got: %s", *pipelineJobs[0].Name) - return - } - - t.Run("TestBuilds", func(t *testing.T) { - build, _, err := m.CreateBuild(config.Org, *config.Project.Canonical, *config.Environment.Canonical, *component.Canonical, *updatedPipeline.Name, *pipelineJobs[0].Name) - if err != nil { - t.Errorf("failed to trigger build in job '%s': %s", *pipelineJobs[0].Name, err) - return - } - - buildIDStr := strconv.Itoa(int(*build.ID)) - getBuild, _, err := m.GetBuild(config.Org, *config.Project.Canonical, *config.Environment.Canonical, *component.Canonical, *updatedPipeline.Name, *pipelineJobs[0].Name, buildIDStr) - if err != nil { - t.Errorf("failed to get build in job '%s': %s", *pipelineJobs[0].Name, err) - return - } - - if *build.ID != *getBuild.ID { - t.Errorf("build are not matching:\ngot: %v\nexpected:\n%v", *getBuild, *build) - return - } - - time.Sleep(1 * time.Second) - - _, err = m.AbortBuild(config.Org, *config.Project.Canonical, *config.Environment.Canonical, *component.Canonical, *updatedPipeline.Name, *pipelineJobs[0].Name, buildIDStr) - if err != nil { - t.Errorf("failed to abort build '%s': %s", buildIDStr, err) - } - - // // Add a bit of time, concourse seems to not like it - // time.Sleep(3 * time.Second) - // - // _, err = m.RerunBuild(config.Org, *config.Project.Canonical, *config.Environment.Canonical, *component.Canonical, *updatedPipeline.Name, *pipelineJobs[0].Name, buildIDStr) - // if err != nil { - // t.Errorf("failed to re-run build '%s': %s", buildIDStr, err) - // } - }) - }) -} diff --git a/cmd/cycloid/middleware/config_repositories_test.go b/cmd/cycloid/middleware/config_repositories_test.go deleted file mode 100644 index 0d993b55c..000000000 --- a/cmd/cycloid/middleware/config_repositories_test.go +++ /dev/null @@ -1,24 +0,0 @@ -package middleware_test - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestListConfigRepositories(t *testing.T) { - m := config.Middleware - - repos, _, err := m.ListConfigRepositories(config.Org) - require.NoError(t, err) - assert.NotEmpty(t, repos) -} - -func TestGetConfigRepository(t *testing.T) { - m := config.Middleware - - repo, _, err := m.GetConfigRepository(config.Org, *config.ConfigRepo.Canonical) - require.NoError(t, err) - assert.Equal(t, *config.ConfigRepo.Canonical, *repo.Canonical) -} diff --git a/cmd/cycloid/middleware/credentials_test.go b/cmd/cycloid/middleware/credentials_test.go deleted file mode 100644 index 15014d48b..000000000 --- a/cmd/cycloid/middleware/credentials_test.go +++ /dev/null @@ -1,43 +0,0 @@ -package middleware_test - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/pkg/testcfg" -) - -func TestCredentialsCRUD(t *testing.T) { - m := config.Middleware - - canonical := testcfg.RandomCanonical("test-cred") - name := "Test Credential" - raw := &models.CredentialRaw{ - Password: "test-password", - Username: "test-user", - } - - created, _, err := m.CreateCredential(config.Org, name, "basic_auth", raw, "", canonical, "test credential") - require.NoError(t, err, "CreateCredential should succeed") - require.NotNil(t, created) - - defer func() { - _, err := m.DeleteCredential(config.Org, *created.Canonical) - require.NoError(t, err, "DeleteCredential should succeed") - }() - - got, _, err := m.GetCredential(config.Org, *created.Canonical) - require.NoError(t, err, "GetCredential should succeed") - assert.Equal(t, *created.Canonical, *got.Canonical) - - list, _, err := m.ListCredentials(config.Org, "") - require.NoError(t, err, "ListCredentials should succeed") - assert.NotEmpty(t, list) - - updated, _, err := m.UpdateCredential(config.Org, name, "basic_auth", raw, "", canonical, "updated description") - require.NoError(t, err, "UpdateCredential should succeed") - assert.Equal(t, "updated description", updated.Description) -} diff --git a/cmd/cycloid/middleware/cycloid_test.go b/cmd/cycloid/middleware/cycloid_test.go deleted file mode 100644 index 26b24008b..000000000 --- a/cmd/cycloid/middleware/cycloid_test.go +++ /dev/null @@ -1,24 +0,0 @@ -package middleware_test - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestGetAppVersion(t *testing.T) { - m := config.Middleware - - version, _, err := m.GetAppVersion() - require.NoError(t, err) - assert.NotNil(t, version) -} - -func TestGetStatus(t *testing.T) { - m := config.Middleware - - status, _, err := m.GetStatus() - require.NoError(t, err) - assert.NotNil(t, status) -} diff --git a/cmd/cycloid/middleware/environment_pipelines_test.go b/cmd/cycloid/middleware/environment_pipelines_test.go deleted file mode 100644 index f6f633d76..000000000 --- a/cmd/cycloid/middleware/environment_pipelines_test.go +++ /dev/null @@ -1,16 +0,0 @@ -package middleware_test - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestGetEnvPipelines(t *testing.T) { - m := config.Middleware - - pipelines, _, err := m.GetEnvPipelines(config.Org, *config.Project.Canonical, *config.Environment.Canonical) - require.NoError(t, err) - assert.NotNil(t, pipelines) -} diff --git a/cmd/cycloid/middleware/errors_test.go b/cmd/cycloid/middleware/errors_test.go deleted file mode 100644 index dfe69336d..000000000 --- a/cmd/cycloid/middleware/errors_test.go +++ /dev/null @@ -1,78 +0,0 @@ -package middleware_test - -import ( - "net/http" - "testing" - - "github.com/stretchr/testify/assert" - - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" -) - -func ptrStr(s string) *string { return &s } - -func TestAPIResponseError(t *testing.T) { - t.Run("ErrorWithPayload", func(t *testing.T) { - err := &middleware.APIResponseError{ - StatusCode: 422, - Status: "422 Unprocessable Entity", - Payload: &models.ErrorPayload{ - Errors: []*models.ErrorDetailsItem{ - { - Code: ptrStr("code"), - Details: []string{"some", "details"}, - Message: ptrStr("the error that actually returned the BE"), - }, - }, - }, - } - - assert.Equal(t, 422, err.StatusCode) - assert.Equal(t, "API error 422: the error that actually returned the BE", err.Error()) - }) - - t.Run("ErrorWithoutPayload", func(t *testing.T) { - err := &middleware.APIResponseError{ - StatusCode: 500, - Status: "500 Internal Server Error", - } - assert.Equal(t, "API error 500: 500 Internal Server Error", err.Error()) - }) - - t.Run("ErrorWithoutPayloadFallbackToRawBodyAndPath", func(t *testing.T) { - err := &middleware.APIResponseError{ - StatusCode: 422, - Status: "422 Unprocessable Entity", - Path: "/organizations/org/projects/project/environments/env/components", - Body: []byte("stack branch simple-terraform not found"), - } - assert.Equal( - t, - `API error 422 on "/organizations/org/projects/project/environments/env/components": stack branch simple-terraform not found`, - err.Error(), - ) - }) - - t.Run("GetPayload", func(t *testing.T) { - payload := &models.ErrorPayload{} - err := &middleware.APIResponseError{ - StatusCode: http.StatusConflict, - Payload: payload, - } - assert.Equal(t, payload, err.GetPayload()) - }) - - t.Run("ErrorWithoutPayloadFallbackToRawBodyWithoutPath", func(t *testing.T) { - err := &middleware.APIResponseError{ - StatusCode: 422, - Status: "422 Unprocessable Entity", - Body: []byte("stack branch simple-terraform not found"), - } - assert.Equal( - t, - "API error 422: stack branch simple-terraform not found", - err.Error(), - ) - }) -} diff --git a/cmd/cycloid/middleware/event_test.go b/cmd/cycloid/middleware/event_test.go deleted file mode 100644 index 8e1b15007..000000000 --- a/cmd/cycloid/middleware/event_test.go +++ /dev/null @@ -1,23 +0,0 @@ -package middleware_test - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestSendEvent(t *testing.T) { - m := config.Middleware - - _, err := m.SendEvent(config.Org, "Cycloid", "test event", "middleware test", "info", map[string]string{"env": "test"}, "blue") - require.NoError(t, err) -} - -func TestListEvents(t *testing.T) { - m := config.Middleware - - events, _, err := m.ListEvents(config.Org, nil, nil, 0, 0) - require.NoError(t, err) - assert.NotNil(t, events) -} diff --git a/cmd/cycloid/middleware/external_backends_test.go b/cmd/cycloid/middleware/external_backends_test.go deleted file mode 100644 index 14b3d0303..000000000 --- a/cmd/cycloid/middleware/external_backends_test.go +++ /dev/null @@ -1,16 +0,0 @@ -package middleware_test - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestListExternalBackends(t *testing.T) { - m := config.Middleware - - backends, _, err := m.ListExternalBackends(config.Org) - require.NoError(t, err) - assert.NotNil(t, backends) -} diff --git a/cmd/cycloid/middleware/generic_client_test.go b/cmd/cycloid/middleware/generic_client_test.go deleted file mode 100644 index a95867dbe..000000000 --- a/cmd/cycloid/middleware/generic_client_test.go +++ /dev/null @@ -1,63 +0,0 @@ -package middleware_test - -import ( - "net/http" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" -) - -func TestGenericRequest_ListProjects(t *testing.T) { - m := config.Middleware - - var projects []*models.Project - httpResp, err := m.GenericRequest(middleware.Request{ - Method: http.MethodGet, - Organization: &config.Org, - Route: []string{"organizations", config.Org, "projects"}, - }, &projects) - - require.NoError(t, err) - require.NotNil(t, httpResp) - assert.Equal(t, http.StatusOK, httpResp.StatusCode) - assert.NotNil(t, projects) -} - -func TestGenericRequest_NotFound(t *testing.T) { - m := config.Middleware - - var out any - httpResp, err := m.GenericRequest(middleware.Request{ - Method: http.MethodGet, - Organization: &config.Org, - Route: []string{"organizations", config.Org, "projects", "this-project-does-not-exist-xyz"}, - }, &out) - - require.Error(t, err) - require.NotNil(t, httpResp) - assert.Equal(t, http.StatusNotFound, httpResp.StatusCode) - - var apiErr *middleware.APIResponseError - require.ErrorAs(t, err, &apiErr) - assert.Equal(t, http.StatusNotFound, apiErr.StatusCode) - assert.NotEmpty(t, apiErr.Error()) -} - -func TestGenericRequest_NoAuth(t *testing.T) { - m := config.Middleware - - var out any - httpResp, err := m.GenericRequest(middleware.Request{ - Method: http.MethodGet, - Route: []string{"organizations", config.Org, "projects"}, - NoAuth: true, - }, &out) - - require.Error(t, err) - require.NotNil(t, httpResp) - assert.Equal(t, http.StatusForbidden, httpResp.StatusCode) -} diff --git a/cmd/cycloid/middleware/http_client_test.go b/cmd/cycloid/middleware/http_client_test.go deleted file mode 100644 index c2d3cea2c..000000000 --- a/cmd/cycloid/middleware/http_client_test.go +++ /dev/null @@ -1,27 +0,0 @@ -package middleware - -import ( - "net/http" - "net/url" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestNewAPIResponseError_PathFallback(t *testing.T) { - u, err := url.Parse("https://http-api.cycloid.io/organizations/org/projects/project?foo=bar") - assert.NoError(t, err) - - resp := &http.Response{ - StatusCode: http.StatusBadRequest, - Status: "400 Bad Request", - Request: &http.Request{ - URL: u, - }, - } - - apiErr := newAPIResponseError(resp, []byte("raw backend error"), nil, "GET") - assert.Equal(t, http.StatusBadRequest, apiErr.StatusCode) - assert.Equal(t, "/organizations/org/projects/project?foo=bar", apiErr.Path) - assert.Equal(t, "API error 400 on \"/organizations/org/projects/project?foo=bar\": raw backend error", apiErr.Error()) -} diff --git a/cmd/cycloid/middleware/init_first_org_test.go b/cmd/cycloid/middleware/init_first_org_test.go deleted file mode 100644 index 53ac9e810..000000000 --- a/cmd/cycloid/middleware/init_first_org_test.go +++ /dev/null @@ -1,47 +0,0 @@ -package middleware_test - -import ( - "os" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestInitFirstOrgIdempotent(t *testing.T) { - m := config.Middleware - - licenceKey, ok := os.LookupEnv("API_LICENCE_KEY") - require.True(t, ok, "API_LICENCE_KEY must be set for bootstrap tests") - - apiKeyCanonical := "admin-init-first-org-test" - result, _, err := m.InitFirstOrg( - config.Org, - "administrator", - "administrator", - "admin@cycloid.io", - "cycloidadmin", - licenceKey, - &apiKeyCanonical, - ) - require.NoError(t, err) - require.NotNil(t, result) - assert.Equal(t, config.Org, result.Org) - assert.NotEmpty(t, result.Token) - require.NotNil(t, result.APIKey) - assert.NotEmpty(t, *result.APIKey) - - resultAgain, _, err := m.InitFirstOrg( - config.Org, - "administrator", - "administrator", - "admin@cycloid.io", - "cycloidadmin", - licenceKey, - &apiKeyCanonical, - ) - require.NoError(t, err) - require.NotNil(t, resultAgain) - assert.Equal(t, config.Org, resultAgain.Org) - assert.NotEmpty(t, resultAgain.Token) -} diff --git a/cmd/cycloid/middleware/lhs_filter_discovery_test.go b/cmd/cycloid/middleware/lhs_filter_discovery_test.go deleted file mode 100644 index d4baafe33..000000000 --- a/cmd/cycloid/middleware/lhs_filter_discovery_test.go +++ /dev/null @@ -1,301 +0,0 @@ -package middleware_test - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" - "github.com/cycloidio/cycloid-cli/internal/testcfg" -) - -// TestLHSFilterDiscovery verifies which attributes the backend accepts as LHS -// filters on each List route that supports them. Field names follow the -// backend's filtersMappings convention: _. -// -// Routes confirmed to NOT support LHS filters (backend handler does not call -// lhs.ParseQuery): ListTeamMembers, ListRoles, ListCredentials, -// ListCatalogRepositories, ListConfigRepositories, ListStackVersions, -// ListStackUseCases. -// -// A subtest failure means the attribute is not supported for that route. -// Results inform the godoc on each List* middleware method. -func TestLHSFilterDiscovery(t *testing.T) { - m := config.Middleware - org := config.Org - - t.Run("Projects", func(t *testing.T) { - projA := testcfg.RandomCanonical("lhs-disc-a") - projB := testcfg.RandomCanonical("lhs-disc-b") - nameA := "LHS Discovery Alpha " + projA - nameB := "LHS Discovery Beta " + projB - configRepo := *config.ConfigRepo.Canonical - - _, _, err := m.CreateProject(org, nameA, projA, "desc a", configRepo, "", "", "default", "world") - require.NoError(t, err, "setup: create projA") - defer func() { _, _ = m.DeleteProject(org, projA, middleware.DeleteOptions{}) }() - - _, _, err = m.CreateProject(org, nameB, projB, "desc b", configRepo, "", "", "default", "world") - require.NoError(t, err, "setup: create projB") - defer func() { _, _ = m.DeleteProject(org, projB, middleware.DeleteOptions{}) }() - - t.Run("project_canonical[eq]", func(t *testing.T) { - results, _, err := m.ListProjects(org, middleware.LHSFilter{Attribute: "project_canonical", Condition: "eq", Value: projA}) - require.NoError(t, err) - require.NotEmpty(t, results) - for _, p := range results { - assert.Equal(t, projA, *p.Canonical) - } - }) - - t.Run("project_name[eq]", func(t *testing.T) { - results, _, err := m.ListProjects(org, middleware.LHSFilter{Attribute: "project_name", Condition: "eq", Value: nameA}) - require.NoError(t, err) - require.NotEmpty(t, results) - for _, p := range results { - assert.Equal(t, nameA, *p.Name) - } - }) - - t.Run("project_name[rlike]", func(t *testing.T) { - results, _, err := m.ListProjects(org, middleware.LHSFilter{Attribute: "project_name", Condition: "rlike", Value: "LHS Discovery .*"}) - require.NoError(t, err) - var found int - for _, p := range results { - if *p.Canonical == projA || *p.Canonical == projB { - found++ - } - } - assert.Equal(t, 2, found, "rlike must match both lhs-disc projects") - }) - }) - - t.Run("Stacks", func(t *testing.T) { - // Stack creation requires complex catalog-repo setup — rely on the - // test stack seeded by testcfg. - testCanonical := "stack-e2e-stackforms" - testRef := org + ":" + testCanonical - - all, _, err := m.ListStacks(org) - require.NoError(t, err) - require.NotEmpty(t, all, "test stacks must exist") - - t.Run("service_catalog_ref[eq]", func(t *testing.T) { - results, _, err := m.ListStacks(org, middleware.LHSFilter{Attribute: "service_catalog_ref", Condition: "eq", Value: testRef}) - require.NoError(t, err) - require.NotEmpty(t, results) - for _, s := range results { - assert.Equal(t, testRef, *s.Ref) - } - assert.Less(t, len(results), len(all), "filtered must be smaller than full list") - }) - - t.Run("service_catalog_visibility[eq]", func(t *testing.T) { - // valid values: local, shared, hidden (handled with custom logic in backend) - results, _, err := m.ListStacks(org, middleware.LHSFilter{Attribute: "service_catalog_visibility", Condition: "eq", Value: "local"}) - require.NoError(t, err) - for _, s := range results { - assert.Equal(t, "local", *s.Visibility) - } - }) - - t.Run("service_catalog_blueprint[eq]", func(t *testing.T) { - results, _, err := m.ListStacks(org, middleware.LHSFilter{Attribute: "service_catalog_blueprint", Condition: "eq", Value: "false"}) - require.NoError(t, err) - assert.NotNil(t, results) - }) - }) - - t.Run("Components", func(t *testing.T) { - knownCanonical := *config.Component.Canonical - proj := *config.Project.Canonical - env := *config.Environment.Canonical - - all, _, err := m.ListComponents(org, proj, env) - require.NoError(t, err) - require.NotEmpty(t, all, "test component must exist") - - t.Run("component_canonical[eq]", func(t *testing.T) { - results, _, err := m.ListComponents(org, proj, env, middleware.LHSFilter{Attribute: "component_canonical", Condition: "eq", Value: knownCanonical}) - require.NoError(t, err) - require.NotEmpty(t, results) - for _, c := range results { - assert.Equal(t, knownCanonical, *c.Canonical) - } - }) - - t.Run("service_catalog_ref[eq]", func(t *testing.T) { - stackRef := org + ":stack-e2e-stackforms" - results, _, err := m.ListComponents(org, proj, env, middleware.LHSFilter{Attribute: "service_catalog_ref", Condition: "eq", Value: stackRef}) - require.NoError(t, err) - assert.NotNil(t, results) - }) - - t.Run("environment_canonical[eq]", func(t *testing.T) { - results, _, err := m.ListComponents(org, proj, env, middleware.LHSFilter{Attribute: "environment_canonical", Condition: "eq", Value: env}) - require.NoError(t, err) - assert.NotEmpty(t, results) - }) - }) - - t.Run("Members", func(t *testing.T) { - // List all members to get a known canonical for filtering - all, _, err := m.ListMembers(org) - require.NoError(t, err) - require.NotEmpty(t, all, "org must have at least one member") - knownCanonical := all[0].Username - - t.Run("user_canonical[eq]", func(t *testing.T) { - results, _, err := m.ListMembers(org, middleware.LHSFilter{Attribute: "user_canonical", Condition: "eq", Value: knownCanonical}) - require.NoError(t, err) - require.NotEmpty(t, results) - for _, member := range results { - assert.Equal(t, knownCanonical, member.Username) - } - }) - - t.Run("invitation_state[eq]", func(t *testing.T) { - // accepted is the normal state for active members - results, _, err := m.ListMembers(org, middleware.LHSFilter{Attribute: "invitation_state", Condition: "eq", Value: "accepted"}) - require.NoError(t, err) - assert.NotNil(t, results) - }) - }) - - t.Run("Teams", func(t *testing.T) { - // List all teams; test env may or may not have teams, so we just verify - // the filter is accepted without error. If teams exist, verify filtering. - all, _, err := m.ListTeams(org, nil, nil, nil, nil) - require.NoError(t, err) - - t.Run("team_canonical[eq]", func(t *testing.T) { - if len(all) == 0 { - t.Skip("no teams in test org") - } - knownCanonical := *all[0].Canonical - results, _, err2 := m.ListTeams(org, nil, nil, nil, nil, middleware.LHSFilter{Attribute: "team_canonical", Condition: "eq", Value: knownCanonical}) - require.NoError(t, err2) - for _, team := range results { - assert.Equal(t, knownCanonical, *team.Canonical) - } - }) - - t.Run("team_name[rlike]", func(t *testing.T) { - if len(all) == 0 { - t.Skip("no teams in test org") - } - _, _, err2 := m.ListTeams(org, nil, nil, nil, nil, middleware.LHSFilter{Attribute: "team_name", Condition: "rlike", Value: ".*"}) - require.NoError(t, err2) - }) - }) - - t.Run("InventoryResources", func(t *testing.T) { - label := "lhs-disc-label" - provider := "custom_resources" - resType := "custom_instance" - nameA := testcfg.RandomCanonical("lhs-res-a") - nameB := testcfg.RandomCanonical("lhs-res-b") - - resA, _, err := m.CreateInventoryResource(org, &models.NewInventoryResource{ - Label: &label, - Name: &nameA, - Provider: &provider, - Type: &resType, - }) - require.NoError(t, err, "setup: create inventory resource A") - defer func() { _, _ = m.DeleteInventoryResource(org, resA.ID) }() - - resB, _, err := m.CreateInventoryResource(org, &models.NewInventoryResource{ - Label: &label, - Name: &nameB, - Provider: &provider, - Type: &resType, - }) - require.NoError(t, err, "setup: create inventory resource B") - defer func() { _, _ = m.DeleteInventoryResource(org, resB.ID) }() - - t.Run("resources_provider[eq]", func(t *testing.T) { - results, _, err := m.ListInventoryResources(org, middleware.LHSFilter{Attribute: "resources_provider", Condition: "eq", Value: provider}) - require.NoError(t, err) - for _, r := range results { - assert.Equal(t, provider, *r.Provider) - } - }) - - t.Run("resources_type[eq]", func(t *testing.T) { - results, _, err := m.ListInventoryResources(org, middleware.LHSFilter{Attribute: "resources_type", Condition: "eq", Value: resType}) - require.NoError(t, err) - for _, r := range results { - assert.Equal(t, resType, *r.Type) - } - }) - - t.Run("resources_label[eq]", func(t *testing.T) { - results, _, err := m.ListInventoryResources(org, middleware.LHSFilter{Attribute: "resources_label", Condition: "eq", Value: label}) - require.NoError(t, err) - require.GreaterOrEqual(t, len(results), 2) - for _, r := range results { - assert.Equal(t, label, r.Label) - } - }) - - t.Run("resources_name[rlike]", func(t *testing.T) { - results, _, err := m.ListInventoryResources(org, middleware.LHSFilter{Attribute: "resources_name", Condition: "rlike", Value: "lhs-res-.*"}) - require.NoError(t, err) - var found int - for _, r := range results { - if *r.Name == nameA || *r.Name == nameB { - found++ - } - } - assert.Equal(t, 2, found, "rlike must match both lhs-disc inventory resources") - }) - }) - - t.Run("InventoryOutputs", func(t *testing.T) { - // Outputs come from TF states — cannot be created directly. We verify - // the filter attributes are accepted by the route without error. - t.Run("output_key[eq] accepted", func(t *testing.T) { - _, _, err := m.ListInventoryOutputs(org, middleware.LHSFilter{Attribute: "output_key", Condition: "eq", Value: "nonexistent"}) - require.NoError(t, err) - }) - - t.Run("output_is_pinned[eq] accepted", func(t *testing.T) { - _, _, err := m.ListInventoryOutputs(org, middleware.LHSFilter{Attribute: "output_is_pinned", Condition: "eq", Value: "false"}) - require.NoError(t, err) - }) - - t.Run("output_type[eq] accepted", func(t *testing.T) { - _, _, err := m.ListInventoryOutputs(org, middleware.LHSFilter{Attribute: "output_type", Condition: "eq", Value: "string"}) - require.NoError(t, err) - }) - - t.Run("project_canonical[eq] accepted", func(t *testing.T) { - _, _, err := m.ListInventoryOutputs(org, middleware.LHSFilter{Attribute: "project_canonical", Condition: "eq", Value: "nonexistent"}) - require.NoError(t, err) - }) - }) - - t.Run("APIKeys", func(t *testing.T) { - all, _, err := m.ListAPIKeys(org) - require.NoError(t, err) - - t.Run("organization_canonical[eq]", func(t *testing.T) { - // organization_canonical is always org in this context - results, _, err2 := m.ListAPIKeys(org, middleware.LHSFilter{Attribute: "organization_canonical", Condition: "eq", Value: org}) - require.NoError(t, err2) - assert.Equal(t, len(all), len(results), "filtering by org canonical should return same count") - }) - - t.Run("user_canonical[eq]", func(t *testing.T) { - if len(all) == 0 { - t.Skip("no API keys in test org") - } - // Verify filter is accepted; nonexistent user returns empty not error - _, _, err2 := m.ListAPIKeys(org, middleware.LHSFilter{Attribute: "user_canonical", Condition: "eq", Value: "nonexistent"}) - require.NoError(t, err2) - }) - }) -} diff --git a/cmd/cycloid/middleware/middleware_test.go b/cmd/cycloid/middleware/middleware_test.go deleted file mode 100644 index c7c62a898..000000000 --- a/cmd/cycloid/middleware/middleware_test.go +++ /dev/null @@ -1,45 +0,0 @@ -package middleware_test - -import ( - "context" - "fmt" - "log" - "os" - "testing" - - "github.com/spf13/viper" - - "github.com/cycloidio/cycloid-cli/pkg/testcfg" -) - -var config *testcfg.Config - -// Put any preparation code here so that defer() can work -func runMain(ctx context.Context, main *testing.M) (int, error) { - _ = ctx - // Initialize global vars - var err error - config, err = testcfg.NewConfig("middleware") - defer config.Cleanup() - if err != nil { - return 1, fmt.Errorf("config setup failed for package middleware: %w", err) - } - - os.Setenv("CY_API_URL", config.APIUrl) - os.Setenv("CY_API_KEY", config.APIKey) - os.Setenv("CY_ORG", config.Org) - if v := os.Getenv("CY_TEST_VERBOSITY"); v != "" { - viper.Set("verbosity", v) - } - return main.Run(), nil -} - -func TestMain(main *testing.M) { - ctx := context.Background() - code, err := runMain(ctx, main) - if err != nil { - log.Fatal(err) - } - - os.Exit(code) -} diff --git a/cmd/cycloid/middleware/offline/catalog_repository_refresh_versions_test.go b/cmd/cycloid/middleware/offline/catalog_repository_refresh_versions_test.go deleted file mode 100644 index bfe6329b9..000000000 --- a/cmd/cycloid/middleware/offline/catalog_repository_refresh_versions_test.go +++ /dev/null @@ -1,200 +0,0 @@ -package offline_test - -import ( - "encoding/json" - "fmt" - "net/http" - "net/http/httptest" - "sync/atomic" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" -) - -// catalogRepoResponse returns a minimal valid service_catalog_source JSON response. -func catalogRepoResponse(canonical string) string { - return fmt.Sprintf(`{"data":{"canonical":%q,"name":%q,"url":"git@github.com:my/repo.git","branch":"main"}}`, canonical, canonical) -} - -// versionsRefreshResponse returns a minimal versions/refresh JSON response. -func versionsRefreshResponse() string { - return `{"data":[{"id":1,"commit_hash":"abc1234","name":"main","type":"branch"},{"id":2,"commit_hash":"def5678","name":"feat/my-branch","type":"branch"}]}` -} - -// TestRefreshCatalogRepositoryVersions_CalledOnceWithFlag verifies that RefreshCatalogRepositoryVersions -// hits the versions/refresh endpoint exactly once when invoked. -func TestRefreshCatalogRepositoryVersions_CalledOnceWithFlag(t *testing.T) { - var refreshCalls int32 - - srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/json") - switch { - case r.Method == http.MethodGet && r.URL.Path == "/organizations/org/service_catalog_sources/my-catalog/versions/refresh": - atomic.AddInt32(&refreshCalls, 1) - assert.Equal(t, "true", r.URL.Query().Get("sync_presence"), "sync_presence query param must be true") - fmt.Fprint(w, versionsRefreshResponse()) - default: - http.NotFound(w, r) - } - })) - defer srv.Close() - - m := middleware.NewMiddleware(common.NewAPI(common.WithURL(srv.URL), common.WithToken("token"))) - - versions, _, err := m.RefreshCatalogRepositoryVersions("org", "my-catalog") - require.NoError(t, err) - assert.Equal(t, int32(1), atomic.LoadInt32(&refreshCalls), "versions/refresh called exactly once") - assert.Len(t, versions, 2) -} - -// TestCreateCatalogRepository_RefreshCalledWhenFlagSet simulates the full create + refresh flow: -// POST creates the repo, then GET versions/refresh is called, confirming --refresh triggers exactly -// one refresh call and zero calls without the flag. -func TestCreateCatalogRepository_RefreshCalledWhenFlagSet(t *testing.T) { - var createCalls int32 - var refreshCalls int32 - - srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/json") - switch { - case r.Method == http.MethodPost && r.URL.Path == "/organizations/org/service_catalog_sources": - atomic.AddInt32(&createCalls, 1) - // Verify body has required fields - var body map[string]any - require.NoError(t, json.NewDecoder(r.Body).Decode(&body)) - assert.NotEmpty(t, body["name"]) - fmt.Fprint(w, catalogRepoResponse("my-catalog")) - case r.Method == http.MethodGet && r.URL.Path == "/organizations/org/service_catalog_sources/my-catalog/versions/refresh": - atomic.AddInt32(&refreshCalls, 1) - assert.Equal(t, "true", r.URL.Query().Get("sync_presence"), "sync_presence query param must be true") - fmt.Fprint(w, versionsRefreshResponse()) - default: - http.NotFound(w, r) - } - })) - defer srv.Close() - - m := middleware.NewMiddleware(common.NewAPI(common.WithURL(srv.URL), common.WithToken("token"))) - - // Simulate create (the command does this then calls RefreshCatalogRepositoryVersions when --refresh is set) - cr, _, err := m.CreateCatalogRepository("org", "my-catalog", "git@github.com:my/repo.git", "main", "", "", "") - require.NoError(t, err) - require.NotNil(t, cr) - assert.Equal(t, int32(1), atomic.LoadInt32(&createCalls)) - assert.Equal(t, int32(0), atomic.LoadInt32(&refreshCalls), "no refresh yet — flag not set") - - // Now simulate --refresh: the command calls RefreshCatalogRepositoryVersions after create - _, _, err = m.RefreshCatalogRepositoryVersions("org", "my-catalog") - require.NoError(t, err) - assert.Equal(t, int32(1), atomic.LoadInt32(&refreshCalls), "refresh called exactly once with flag") -} - -// TestUpdateCatalogRepository_RefreshCalledWhenFlagSet mirrors the create test for update. -func TestUpdateCatalogRepository_RefreshCalledWhenFlagSet(t *testing.T) { - var updateCalls int32 - var refreshCalls int32 - - srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/json") - switch { - case r.Method == http.MethodPut && r.URL.Path == "/organizations/org/service_catalog_sources/my-catalog": - atomic.AddInt32(&updateCalls, 1) - fmt.Fprint(w, catalogRepoResponse("my-catalog")) - case r.Method == http.MethodGet && r.URL.Path == "/organizations/org/service_catalog_sources/my-catalog/versions/refresh": - atomic.AddInt32(&refreshCalls, 1) - assert.Equal(t, "true", r.URL.Query().Get("sync_presence"), "sync_presence query param must be true") - fmt.Fprint(w, versionsRefreshResponse()) - default: - http.NotFound(w, r) - } - })) - defer srv.Close() - - m := middleware.NewMiddleware(common.NewAPI(common.WithURL(srv.URL), common.WithToken("token"))) - - // Simulate update without --refresh - cr, _, err := m.UpdateCatalogRepository("org", "my-catalog", "my-catalog", "git@github.com:my/repo.git", "main", "", nil) - require.NoError(t, err) - require.NotNil(t, cr) - assert.Equal(t, int32(1), atomic.LoadInt32(&updateCalls)) - assert.Equal(t, int32(0), atomic.LoadInt32(&refreshCalls), "no refresh — flag not set") - - // Now simulate --refresh: the command calls RefreshCatalogRepositoryVersions after update - _, _, err = m.RefreshCatalogRepositoryVersions("org", "my-catalog") - require.NoError(t, err) - assert.Equal(t, int32(1), atomic.LoadInt32(&refreshCalls), "refresh called exactly once with flag") -} - -// TestCreateCatalogRepository_NoRefreshWithoutFlag verifies that when --refresh is not set, -// the versions/refresh endpoint is NOT called (zero calls). -func TestCreateCatalogRepository_NoRefreshWithoutFlag(t *testing.T) { - var refreshCalls int32 - - srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/json") - switch { - case r.Method == http.MethodPost && r.URL.Path == "/organizations/org/service_catalog_sources": - fmt.Fprint(w, catalogRepoResponse("my-catalog")) - case r.Method == http.MethodGet && r.URL.Path == "/organizations/org/service_catalog_sources/my-catalog/versions/refresh": - atomic.AddInt32(&refreshCalls, 1) - t.Error("RefreshCatalogRepositoryVersions must not be called when --refresh flag is absent") - default: - http.NotFound(w, r) - } - })) - defer srv.Close() - - m := middleware.NewMiddleware(common.NewAPI(common.WithURL(srv.URL), common.WithToken("token"))) - - // Create without --refresh: only the POST happens, no refresh - cr, _, err := m.CreateCatalogRepository("org", "my-catalog", "git@github.com:my/repo.git", "main", "", "", "") - require.NoError(t, err) - require.NotNil(t, cr) - assert.Equal(t, int32(0), atomic.LoadInt32(&refreshCalls), "zero refresh calls without --refresh flag") -} - -// TestUpdateCatalogRepository_NoRefreshWithoutFlag mirrors the create test for update. -func TestUpdateCatalogRepository_NoRefreshWithoutFlag(t *testing.T) { - var refreshCalls int32 - - srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/json") - switch { - case r.Method == http.MethodPut && r.URL.Path == "/organizations/org/service_catalog_sources/my-catalog": - fmt.Fprint(w, catalogRepoResponse("my-catalog")) - case r.Method == http.MethodGet && r.URL.Path == "/organizations/org/service_catalog_sources/my-catalog/versions/refresh": - atomic.AddInt32(&refreshCalls, 1) - t.Error("RefreshCatalogRepositoryVersions must not be called when --refresh flag is absent") - default: - http.NotFound(w, r) - } - })) - defer srv.Close() - - m := middleware.NewMiddleware(common.NewAPI(common.WithURL(srv.URL), common.WithToken("token"))) - - // Update without --refresh: only the PUT happens, no refresh - cr, _, err := m.UpdateCatalogRepository("org", "my-catalog", "my-catalog", "git@github.com:my/repo.git", "main", "", nil) - require.NoError(t, err) - require.NotNil(t, cr) - assert.Equal(t, int32(0), atomic.LoadInt32(&refreshCalls), "zero refresh calls without --refresh flag") -} - -// TestRefreshCatalogRepositoryVersions_PropagatesError verifies that a non-2xx response -// from the versions/refresh endpoint is propagated as an error to the caller. -func TestRefreshCatalogRepositoryVersions_PropagatesError(t *testing.T) { - srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - http.Error(w, `{"errors":[{"code":"ServerError","message":"backend error"}]}`, http.StatusInternalServerError) - })) - defer srv.Close() - - m := middleware.NewMiddleware(common.NewAPI(common.WithURL(srv.URL), common.WithToken("token"))) - - versions, _, err := m.RefreshCatalogRepositoryVersions("org", "my-catalog") - require.Error(t, err) - assert.Nil(t, versions) -} diff --git a/cmd/cycloid/middleware/offline/generic_client_decode_test.go b/cmd/cycloid/middleware/offline/generic_client_decode_test.go deleted file mode 100644 index 26b0c569f..000000000 --- a/cmd/cycloid/middleware/offline/generic_client_decode_test.go +++ /dev/null @@ -1,65 +0,0 @@ -package offline_test - -import ( - "net/http" - "net/http/httptest" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" - "github.com/cycloidio/cycloid-cli/printer" -) - -func TestGenericRequest_200InvalidJSON(t *testing.T) { - srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusOK) - _, _ = w.Write([]byte(`not-valid-json`)) - })) - defer srv.Close() - - api := common.NewAPI(common.WithURL(srv.URL), common.WithToken("test-token")) - m := middleware.NewMiddleware(api) - - var out map[string]any - httpResp, err := m.GenericRequest(middleware.Request{ - Method: http.MethodGet, - Route: []string{"test"}, - }, &out) - - require.Error(t, err) - require.NotNil(t, httpResp) - assert.Equal(t, http.StatusOK, httpResp.StatusCode) - - var httpErr printer.ErrHTTPResponse - require.ErrorAs(t, err, &httpErr) - assert.Equal(t, http.StatusOK, httpErr.HTTPStatusCode()) - assert.Contains(t, string(httpErr.HTTPResponseBody()), "not-valid-json") -} - -func TestGenericRequest_200EnvelopeDataTypeMismatch(t *testing.T) { - srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusOK) - _, _ = w.Write([]byte(`{"data":true}`)) - })) - defer srv.Close() - - api := common.NewAPI(common.WithURL(srv.URL), common.WithToken("test-token")) - m := middleware.NewMiddleware(api) - - var out map[string]any - httpResp, err := m.GenericRequest(middleware.Request{ - Method: http.MethodGet, - Route: []string{"test"}, - }, &out) - - require.Error(t, err) - require.NotNil(t, httpResp) - assert.Equal(t, http.StatusOK, httpResp.StatusCode) - - var httpErr printer.ErrHTTPResponse - require.ErrorAs(t, err, &httpErr) - assert.Equal(t, `{"data":true}`, string(httpErr.HTTPResponseBody())) -} diff --git a/cmd/cycloid/middleware/offline/lhs_filter_test.go b/cmd/cycloid/middleware/offline/lhs_filter_test.go deleted file mode 100644 index dc090b95c..000000000 --- a/cmd/cycloid/middleware/offline/lhs_filter_test.go +++ /dev/null @@ -1,138 +0,0 @@ -package offline_test - -import ( - "net/http" - "net/http/httptest" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" -) - -// captureRawQuery runs a GenericRequest with the given LHSFilters against a local -// test server and returns the raw query string the server received. -func captureRawQuery(t *testing.T, filters []middleware.LHSFilter) string { - t.Helper() - var captured string - srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - captured = r.URL.RawQuery - w.WriteHeader(http.StatusOK) - _, _ = w.Write([]byte(`{"data":[]}`)) - })) - defer srv.Close() - - api := common.NewAPI(common.WithURL(srv.URL), common.WithToken("test-token")) - m := middleware.NewMiddleware(api) - - var out []any - _, err := m.GenericRequest(middleware.Request{ - Method: http.MethodGet, - Route: []string{"test"}, - LHSFilters: filters, - }, &out) - require.NoError(t, err) - return captured -} - -func TestLHSFilterBracketsNotEncoded(t *testing.T) { - raw := captureRawQuery(t, []middleware.LHSFilter{ - {Attribute: "name", Condition: "eq", Value: "my-project"}, - }) - assert.Equal(t, "name[eq]=my-project", raw, "brackets must be literal, not percent-encoded") -} - -func TestLHSFilterMultipleFilters(t *testing.T) { - raw := captureRawQuery(t, []middleware.LHSFilter{ - {Attribute: "name", Condition: "eq", Value: "my-project"}, - {Attribute: "canonical", Condition: "rlike", Value: "proj.*"}, - }) - assert.Equal(t, "name[eq]=my-project&canonical[rlike]=proj.*", raw) -} - -func TestLHSFilterRegexMetacharsPreserved(t *testing.T) { - tests := []struct { - name string - value string - wantValue string - }{ - {"dot wildcard", "dg.growy", "dg.growy"}, - {"question mark", "dg.?growy", "dg.?growy"}, - {"star wildcard", "dg.*growy", "dg.*growy"}, - {"plus quantifier", "dg.+growy", "dg.+growy"}, - {"brackets", "[A-Z]+", "[A-Z]+"}, - {"pipe alternation", "foo|bar", "foo|bar"}, - {"caret anchor", "^foo", "^foo"}, - {"dollar anchor", "foo$", "foo$"}, - {"backslash escape", `foo\.bar`, `foo\.bar`}, - {"parens groups", "(foo|bar)", "(foo|bar)"}, - {"curly braces", "a{2,4}", "a{2,4}"}, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - raw := captureRawQuery(t, []middleware.LHSFilter{ - {Attribute: "name", Condition: "rlike", Value: tt.value}, - }) - assert.Equal(t, "name[rlike]="+tt.wantValue, raw) - }) - } -} - -func TestLHSFilterStructuralCharsEncoded(t *testing.T) { - tests := []struct { - name string - value string - wantValue string - }{ - {"ampersand", "foo&bar", "foo%26bar"}, - {"equals", "foo=bar", "foo%3Dbar"}, - {"hash", "foo#bar", "foo%23bar"}, - {"space", "foo bar", "foo%20bar"}, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - raw := captureRawQuery(t, []middleware.LHSFilter{ - {Attribute: "name", Condition: "eq", Value: tt.value}, - }) - assert.Equal(t, "name[eq]="+tt.wantValue, raw) - }) - } -} - -func TestLHSFilterCombinedWithRegularQuery(t *testing.T) { - var captured string - srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - captured = r.URL.RawQuery - w.WriteHeader(http.StatusOK) - _, _ = w.Write([]byte(`{"data":[]}`)) - })) - defer srv.Close() - - api := common.NewAPI(common.WithURL(srv.URL), common.WithToken("test-token")) - m := middleware.NewMiddleware(api) - - type queryParams struct { - PageSize int `url:"page_size"` - } - - var out []any - _, err := m.GenericRequest(middleware.Request{ - Method: http.MethodGet, - Route: []string{"test"}, - Query: queryParams{PageSize: 100}, - LHSFilters: []middleware.LHSFilter{ - {Attribute: "name", Condition: "eq", Value: "my-project"}, - }, - }, &out) - require.NoError(t, err) - - assert.Contains(t, captured, "page_size=100") - assert.Contains(t, captured, "name[eq]=my-project") -} - -func TestLHSFilterEmpty(t *testing.T) { - raw := captureRawQuery(t, nil) - assert.Equal(t, "", raw, "no filters should produce no query string") -} diff --git a/cmd/cycloid/middleware/organization_api_key_test.go b/cmd/cycloid/middleware/organization_api_key_test.go deleted file mode 100644 index f7fee0750..000000000 --- a/cmd/cycloid/middleware/organization_api_key_test.go +++ /dev/null @@ -1,37 +0,0 @@ -package middleware_test - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/internal/ptr" - "github.com/cycloidio/cycloid-cli/pkg/testcfg" -) - -func TestAPIKeyCRUD(t *testing.T) { - m := config.Middleware - - canonical := testcfg.RandomCanonical("test-apikey") - name := ptr.Ptr("Test API Key") - - rule := &models.NewRule{Action: ptr.Ptr("*"), Effect: ptr.Ptr(models.NewRuleEffectAllow)} - created, _, err := m.CreateAPIKey(config.Org, canonical, "test api key", "administrator", name, []*models.NewRule{rule}) - require.NoError(t, err, "CreateAPIKey should succeed") - require.NotNil(t, created) - - defer func() { - _, err := m.DeleteAPIKey(config.Org, canonical) - require.NoError(t, err, "DeleteAPIKey should succeed") - }() - - got, _, err := m.GetAPIKey(config.Org, canonical) - require.NoError(t, err, "GetAPIKey should succeed") - assert.Equal(t, canonical, *got.Canonical) - - list, _, err := m.ListAPIKeys(config.Org) - require.NoError(t, err, "ListAPIKeys should succeed") - assert.NotEmpty(t, list) -} diff --git a/cmd/cycloid/middleware/organization_cloud_accounts_test.go b/cmd/cycloid/middleware/organization_cloud_accounts_test.go deleted file mode 100644 index 3e75f0ee2..000000000 --- a/cmd/cycloid/middleware/organization_cloud_accounts_test.go +++ /dev/null @@ -1,86 +0,0 @@ -package middleware_test - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/internal/ptr" - "github.com/cycloidio/cycloid-cli/pkg/testcfg" -) - -func TestCloudAccountCRUD(t *testing.T) { - m := config.Middleware - - // Pre-create a credential — cloud accounts require one at create time. - credCanonical := testcfg.RandomCanonical("test-ca-cred") - cred, _, err := m.CreateCredential(config.Org, credCanonical, "aws", - &models.CredentialRaw{AccessKey: "AKIAIOSFODNN7EXAMPLE", SecretKey: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"}, - "", credCanonical, "", - ) - require.NoError(t, err, "CreateCredential should succeed") - require.NotNil(t, cred) - defer func() { - // The backend cascades credential deletion when a cloud account is deleted, - // so a 404 here is expected when the cloud account cleanup ran first. - _, _ = m.DeleteCredential(config.Org, *cred.Canonical) - }() - - // Create - canonical := testcfg.RandomCanonical("test-ca") - createBody := &models.NewCloudAccount{ - Canonical: canonical, - Name: ptr.Ptr(canonical), - CloudProvider: ptr.Ptr("aws"), - CredentialCanonical: ptr.Ptr(*cred.Canonical), - } - created, _, err := m.CreateCloudAccount(config.Org, createBody) - require.NoError(t, err, "CreateCloudAccount should succeed") - require.NotNil(t, created) - assert.Equal(t, canonical, *created.Canonical) - - defer func() { - _, err := m.DeleteCloudAccount(config.Org, *created.Canonical) - require.NoError(t, err, "DeleteCloudAccount cleanup should succeed") - }() - - // Get - got, _, err := m.GetCloudAccount(config.Org, *created.Canonical) - require.NoError(t, err, "GetCloudAccount should succeed") - assert.Equal(t, *created.Canonical, *got.Canonical) - assert.Equal(t, "aws", *got.CloudProvider) - - // List — created account must appear - list, _, err := m.ListCloudAccounts(config.Org) - require.NoError(t, err, "ListCloudAccounts should succeed") - assert.NotEmpty(t, list) - found := false - for _, ca := range list { - if ca.Canonical != nil && *ca.Canonical == *created.Canonical { - found = true - break - } - } - assert.True(t, found, "created cloud account must appear in list") - - // Update — rename only; credential stays the same - updatedName := canonical + "-updated" - updateBody := &models.UpdateCloudAccount{ - Name: ptr.Ptr(updatedName), - CredentialCanonical: cred.Canonical, - } - updated, _, err := m.UpdateCloudAccount(config.Org, *created.Canonical, updateBody) - require.NoError(t, err, "UpdateCloudAccount should succeed") - assert.Equal(t, updatedName, *updated.Name) -} - -func TestGetCloudAccount_NotFound(t *testing.T) { - m := config.Middleware - - _, resp, err := m.GetCloudAccount(config.Org, "nonexistent-cloud-account-xyz") - assert.Error(t, err, "GetCloudAccount should return an error for an unknown canonical") - require.NotNil(t, resp) - assert.Equal(t, 404, resp.StatusCode) -} diff --git a/cmd/cycloid/middleware/organization_components_test.go b/cmd/cycloid/middleware/organization_components_test.go deleted file mode 100644 index 91a74efa6..000000000 --- a/cmd/cycloid/middleware/organization_components_test.go +++ /dev/null @@ -1,142 +0,0 @@ -package middleware_test - -import ( - "errors" - "log" - "strconv" - "testing" - - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" -) - -func TestComponentCRUD(t *testing.T) { - m := config.Middleware - for index := range 2 { // Made only two to speed up tests - var ( - componentName = "Test Component " + strconv.Itoa(index) - component = "test-component-" + strconv.Itoa(index) - componentDescription = "My cool component" - stackRef = config.Org + ":stack-e2e-stackforms" - useCase = "default" - newVar = models.FormVariables{ - "can two sections have same name with different caps ?": { - "can two groups have same name with different caps ?": { - "group1": "EDITED", - }, - }, - } - formVars = &models.FormVariables{ - "can two sections have same name with different caps ?": { - "can two groups have same name with different caps ?": { - "group1": "osef", - }, - }, - "CAN TWO SECTIONS HAVE SAME NAME WITH DIFFERENT CAPS ?": { - "CAN TWO GROUPS HAVE SAME NAME WITH DIFFERENT CAPS ?": { - "group2": "osef", - }, - }, - "section spaces AND CAPS": { - "group spaces AND CAPS": { - "no_spaces_no_caps": "osef", - }, - }, - "section with spaces": { - "group with spaces": { - "no_spaces": "osef", - }, - }, - "types": { - "tests": { - "array": []any{ - "hello", - "world", - false, - index, - 1.1, - }, - "bool": true, - "float": 0.1, - "integer": 1, - "map": map[string]any{ - "array": []any{ - "hello", - "world", - }, - "bool": false, - "float": 0.1, - "integer": 1, - "nested": map[string]string{ - "map": "hello", - }, - "string": "string", - }, - "string": "stringValue1", - }, - }, - } - ) - - var createdComponent *models.Component - var err, errList error - for range 3 { // retries due to concurenccy bug in backend - createdComponent, _, err = m.GetComponent(config.Org, *config.Project.Canonical, *config.Environment.Canonical, component) - if err == nil { - errList = nil - break - } - - createdComponent, _, err = m.CreateOrUpdateComponent(config.Org, *config.Project.Canonical, *config.Environment.Canonical, component, componentDescription, componentName, stackRef, "", "", "", useCase, "", *formVars) - if err != nil { - errList = errors.Join(errList, err) - continue - } - - errList = nil - break - } - - if errList != nil { - t.Errorf("Failed to create component '%s':\n%v", component, err) - } - - defer func() { - _, err := m.DeleteComponent(config.Org, *config.Project.Canonical, *config.Environment.Canonical, *createdComponent.Canonical, middleware.DeleteOptions{}) - if err != nil { - log.Fatalf("Failed to delete component '%s': %v", *createdComponent.Canonical, err) - return - } - }() - - var ( - newDescription = "New desc" - newComponentName = "New name" + strconv.Itoa(index) - ) - errList, err = nil, nil - for range 3 { - _, _, err = m.CreateOrUpdateComponent(config.Org, *config.Project.Canonical, *config.Environment.Canonical, *createdComponent.Canonical, newDescription, newComponentName, stackRef, "", "", *config.CatalogRepoVersionStacks.CommitHash, useCase, "", newVar) - if err != nil { - errList = errors.Join(errList, err) - continue - } - - errList = nil - break - } - if errList != nil { - t.Errorf("Failed to update component '%s':\n%v", *createdComponent.Canonical, err) - } - - // TODO: Fix after issue: https://linear.app/cycloid/issue/BE-801/invalid-response-for-updatecomponent - // assert.NotNil(t, updatedComponent, "response should not be nil.") - // assert.NotNil(t, updatedComponent.Name, "Name should not be nil.") - // assert.Equal(t, newComponentName, *updatedComponent.Name) - // assert.Equal(t, newDescription, *updatedComponent.Canonical) - } - - _, _, err := m.ListComponents(config.Org, *config.Project.Canonical, *config.Environment.Canonical) - if err != nil { - t.Errorf("Failed to list components in project '%s':\n%v", *config.Project.Canonical, err) - } -} diff --git a/cmd/cycloid/middleware/organization_environment_types_test.go b/cmd/cycloid/middleware/organization_environment_types_test.go deleted file mode 100644 index 96407e868..000000000 --- a/cmd/cycloid/middleware/organization_environment_types_test.go +++ /dev/null @@ -1,73 +0,0 @@ -package middleware_test - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/internal/ptr" - "github.com/cycloidio/cycloid-cli/pkg/testcfg" -) - -func TestEnvironmentTypeCRUD(t *testing.T) { - m := config.Middleware - - canonical := testcfg.RandomCanonical("test-env-type") - name := "Test Env Type" - color := "#3498db" - - createBody := &models.NewEnvironmentType{ - Canonical: canonical, - Name: ptr.Ptr(name), - Color: ptr.Ptr(color), - } - created, _, err := m.CreateEnvironmentType(config.Org, createBody) - require.NoError(t, err, "CreateEnvironmentType should succeed") - require.NotNil(t, created) - assert.Equal(t, canonical, *created.Canonical) - assert.Equal(t, name, *created.Name) - - defer func() { - _, err := m.DeleteEnvironmentType(config.Org, *created.Canonical) - require.NoError(t, err, "DeleteEnvironmentType cleanup should succeed") - }() - - // Get — must round-trip through list since GET-by-canonical is list-based - got, _, err := m.GetEnvironmentType(config.Org, *created.Canonical) - require.NoError(t, err, "GetEnvironmentType should succeed") - assert.Equal(t, *created.Canonical, *got.Canonical) - assert.Equal(t, color, *got.Color) - - // List — created type must appear - list, _, err := m.ListEnvironmentTypes(config.Org) - require.NoError(t, err, "ListEnvironmentTypes should succeed") - assert.NotEmpty(t, list) - found := false - for _, et := range list { - if et.Canonical != nil && *et.Canonical == *created.Canonical { - found = true - break - } - } - assert.True(t, found, "created environment type must appear in list") - - // Update - updatedName := name + " Updated" - updateBody := &models.UpdateEnvironmentType{ - Name: ptr.Ptr(updatedName), - Color: ptr.Ptr(color), - } - updated, _, err := m.UpdateEnvironmentType(config.Org, *created.Canonical, updateBody) - require.NoError(t, err, "UpdateEnvironmentType should succeed") - assert.Equal(t, updatedName, *updated.Name) -} - -func TestGetEnvironmentType_NotFound(t *testing.T) { - m := config.Middleware - - _, _, err := m.GetEnvironmentType(config.Org, "nonexistent-env-type-xyz") - assert.Error(t, err, "GetEnvironmentType should return an error for an unknown canonical") - assert.Contains(t, err.Error(), "nonexistent-env-type-xyz") -} diff --git a/cmd/cycloid/middleware/organization_forms_test.go b/cmd/cycloid/middleware/organization_forms_test.go deleted file mode 100644 index 0ac9e6a0b..000000000 --- a/cmd/cycloid/middleware/organization_forms_test.go +++ /dev/null @@ -1,38 +0,0 @@ -package middleware_test - -import ( - "testing" - - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" -) - -func TestValidateFormYamlAnchors(t *testing.T) { - api := common.NewAPI() - m := middleware.NewMiddleware(api) - - var org = "cycloid-sandbox" - var rawForms = []byte( - `--- - shared: - - &some_anchor - key: hello - name: hello - type: string - widget: simple_text - - sections: - - name: "section" - groups: - - name: "group" - technologies: [pipeline] - vars: - - *some_anchor - `, - ) - - _, _, err := m.ValidateForm(org, rawForms) - if err != nil { - t.Errorf("Using yaml anchor should not error:\nerr: '%s'\nyaml files: '%v'", err, rawForms) - } -} diff --git a/cmd/cycloid/middleware/organization_licence_test.go b/cmd/cycloid/middleware/organization_licence_test.go deleted file mode 100644 index b6b488f5e..000000000 --- a/cmd/cycloid/middleware/organization_licence_test.go +++ /dev/null @@ -1,42 +0,0 @@ -package middleware_test - -import ( - "os" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestGetLicence(t *testing.T) { - m := config.Middleware - - licence, _, err := m.GetLicence(config.Org) - require.NoError(t, err) - require.NotNil(t, licence) - require.NotNil(t, licence.Key) - assert.NotEmpty(t, *licence.Key) -} - -func TestActivateLicenceOverwrite(t *testing.T) { - m := config.Middleware - - licenceKey, ok := os.LookupEnv("API_LICENCE_KEY") - require.True(t, ok, "API_LICENCE_KEY must be set for licence tests") - - _, err := m.ActivateLicence(config.Org, licenceKey) - require.NoError(t, err) - - got, _, err := m.GetLicence(config.Org) - require.NoError(t, err) - require.NotNil(t, got.Key) - assert.Equal(t, licenceKey, *got.Key) - - _, err = m.ActivateLicence(config.Org, licenceKey) - require.NoError(t, err) - - gotAgain, _, err := m.GetLicence(config.Org) - require.NoError(t, err) - require.NotNil(t, gotAgain.Key) - assert.Equal(t, licenceKey, *gotAgain.Key) -} diff --git a/cmd/cycloid/middleware/organization_members_test.go b/cmd/cycloid/middleware/organization_members_test.go deleted file mode 100644 index 63da8fc5d..000000000 --- a/cmd/cycloid/middleware/organization_members_test.go +++ /dev/null @@ -1,37 +0,0 @@ -package middleware_test - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestListMembers(t *testing.T) { - m := config.Middleware - - members, _, err := m.ListMembers(config.Org) - require.NoError(t, err) - assert.NotEmpty(t, members) -} - -func TestListInvites(t *testing.T) { - m := config.Middleware - - invites, _, err := m.ListInvites(config.Org) - require.NoError(t, err) - assert.NotNil(t, invites) -} - -func TestGetMember(t *testing.T) { - m := config.Middleware - - members, _, err := m.ListMembers(config.Org) - require.NoError(t, err) - require.NotEmpty(t, members) - - got, _, - err := m.GetMember(config.Org, *members[0].ID) - require.NoError(t, err) - assert.Equal(t, *members[0].ID, *got.ID) -} diff --git a/cmd/cycloid/middleware/organization_pipelines_test.go b/cmd/cycloid/middleware/organization_pipelines_test.go deleted file mode 100644 index 5eae453ac..000000000 --- a/cmd/cycloid/middleware/organization_pipelines_test.go +++ /dev/null @@ -1,36 +0,0 @@ -package middleware_test - -import ( - "fmt" - "slices" - "testing" - - "github.com/sanity-io/litter" - - "github.com/cycloidio/cycloid-cli/client/models" -) - -var ( - pipelineTestStackCanonical = "stack-test-pipeline" - pipelineTestStackUseCase = "default" - pipelineTestDefaultVars = models.FormVariables{"section": {"group": {"var": "hello"}}} -) - -func TestGetOrgPipelines(t *testing.T) { - m := config.Middleware - - pipelineName := fmt.Sprintf("%s-%s-%s", *config.Project.Canonical, *config.Environment.Canonical, *config.Component.Canonical) - got, _, err := m.GetOrgPipelines(config.Org, &pipelineName, config.Project.Canonical, config.Environment.Canonical, []string{}) - if err != nil { - t.Errorf("middleware.GetOrgPipelines() error = %v", err) - return - } - - index := slices.IndexFunc(got, func(p *models.Pipeline) bool { - return *p.Component.Canonical == *config.Component.Canonical - }) - - if index == -1 { - t.Errorf("failed to find created component in the list: %v\nexpected component: %v", litter.Sdump(got), litter.Sdump(config.Component)) - } -} diff --git a/cmd/cycloid/middleware/organization_project_environment_test.go b/cmd/cycloid/middleware/organization_project_environment_test.go deleted file mode 100644 index febd05fad..000000000 --- a/cmd/cycloid/middleware/organization_project_environment_test.go +++ /dev/null @@ -1,87 +0,0 @@ -package middleware_test - -import ( - "log" - "testing" - - "github.com/stretchr/testify/assert" - - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" - "github.com/cycloidio/cycloid-cli/internal/ptr" - "github.com/cycloidio/cycloid-cli/pkg/testcfg" -) - -func TestEnvCrud(t *testing.T) { - m := config.Middleware - - var ( - projectName = "Test CRUD ENV" - project = testcfg.RandomCanonical("test-crud-env") - description = "Testing env" - configRepository = *config.ConfigRepo.Canonical - owner = "" - team = "" - color = "blue" - icon = "planet" - ) - - defer func() { - _, err := m.DeleteProject(config.Org, project, middleware.DeleteOptions{}) - if err != nil { - log.Fatalf("Failed to decommission project '%s' from CRUD tests: %v", project, err) - } - }() - - createdProject, _, err := m.CreateProject(config.Org, projectName, project, description, configRepository, owner, team, color, icon) - if err != nil { - t.Fatalf("Failed to create pre-requisite project: %v", err) - } - - var ( - env = testcfg.RandomCanonical("test-crud") - envName = "TestCRUD" - ) - - createBody := &models.NewEnvironment{ - Canonical: env, - Name: ptr.Ptr(envName), - Type: ptr.Ptr("production"), - } - createdEnv, _, err := m.CreateOrgEnv(config.Org, createBody) - if err != nil { - t.Fatalf("Failed to create env %q: %v", env, err) - } - - defer func() { - if createdEnv == nil { - return - } - // Org-level envs cannot be deleted while still linked to a project - // (backend returns 409). Unlink first so cleanup is best-effort even - // when the test panics mid-flight. - if _, err := m.UnlinkEnvFromProject(config.Org, *createdProject.Canonical, *createdEnv.Canonical, middleware.DeleteOptions{}); err != nil { - log.Printf("Warning: failed to unlink env %q from project %q during cleanup: %v", env, *createdProject.Canonical, err) - } - if _, err := m.DeleteOrgEnv(config.Org, *createdEnv.Canonical); err != nil { - log.Fatalf("Failed to delete org env %q: %v", env, err) - } - }() - - _, err = m.LinkEnvToProject(config.Org, *createdProject.Canonical, env) - if err != nil { - t.Fatalf("Failed to link env %q to project: %v", env, err) - } - - newEnvName := "New" - updateBody := &models.UpdateEnvironment{ - Name: ptr.Ptr(newEnvName), - Type: ptr.Ptr("production"), - } - updatedEnv, _, err := m.UpdateOrgEnv(config.Org, *createdEnv.Canonical, updateBody) - if err != nil { - t.Fatalf("Failed to update env %q: %v", env, err) - } - - assert.Equal(t, newEnvName, updatedEnv.Name) -} diff --git a/cmd/cycloid/middleware/organization_projects_test.go b/cmd/cycloid/middleware/organization_projects_test.go deleted file mode 100644 index 2dab496c7..000000000 --- a/cmd/cycloid/middleware/organization_projects_test.go +++ /dev/null @@ -1,61 +0,0 @@ -package middleware_test - -import ( - "testing" - - "github.com/stretchr/testify/assert" - - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" - "github.com/cycloidio/cycloid-cli/pkg/testcfg" -) - -func TestProjectCrud(t *testing.T) { - m := config.Middleware - - var ( - projectName = "Test CRUD Projects" - project = testcfg.RandomCanonical("test-crud-project") - description = "My cool project description !\nWith a nexline" - owner = "" - team = "" - color = "default" - icon = "world" - ) - - createProjet, _, err := m.CreateProject(config.Org, projectName, project, description, *config.ConfigRepo.Canonical, owner, team, color, icon) - if err != nil { - t.Errorf("Failed to create project '%s': %v", project, err) - } - - _, _, err = m.GetProject(config.Org, *createProjet.Canonical) - if err != nil { - t.Errorf("Did not found create project '%s' with get request: %v", *createProjet.Canonical, err) - } - - defer func() { - _, err := m.DeleteProject(config.Org, project, middleware.DeleteOptions{}) - if err != nil { - t.Errorf("Failed to delete project '%s': %v", project, err) - } - }() - - var ( - newIcon = "world" - newName = "My cool new name" - newDescription = "Updated description" - newColor = "red" - ) - - updatedProject, _, err := m.UpdateProject( - config.Org, newName, project, newDescription, *config.ConfigRepo.Canonical, - owner, team, newColor, newIcon, "aws", - ) - if err != nil { - t.Errorf("Failed to update project '%s': %v", project, err) - } - - assert.Equal(t, newName, *updatedProject.Name) - assert.Equal(t, newDescription, updatedProject.Description) - assert.Equal(t, newIcon, *updatedProject.Icon) - assert.Equal(t, newColor, *updatedProject.Color) -} diff --git a/cmd/cycloid/middleware/organization_roles_test.go b/cmd/cycloid/middleware/organization_roles_test.go deleted file mode 100644 index f190c4ef1..000000000 --- a/cmd/cycloid/middleware/organization_roles_test.go +++ /dev/null @@ -1,46 +0,0 @@ -package middleware_test - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/internal/ptr" - "github.com/cycloidio/cycloid-cli/pkg/testcfg" -) - -func TestRolesCRUD(t *testing.T) { - m := config.Middleware - - canonical := testcfg.RandomCanonical("test-role") - - rule := &models.NewRule{Action: ptr.Ptr("*"), Effect: ptr.Ptr(models.NewRuleEffectAllow)} - created, _, err := m.CreateRole(config.Org, ptr.Ptr("Test Role"), ptr.Ptr(canonical), ptr.Ptr("test role description"), []*models.NewRule{rule}) - require.NoError(t, err, "CreateRole should succeed") - require.NotNil(t, created) - - defer func() { - _, err := m.DeleteRole(config.Org, canonical) - require.NoError(t, err, "DeleteRole should succeed") - }() - - got, _, err := m.GetRole(config.Org, canonical) - require.NoError(t, err, "GetRole should succeed") - assert.Equal(t, canonical, *got.Canonical) - - updated, _, err := m.UpdateRole(config.Org, canonical, ptr.Ptr("Updated Role Name"), ptr.Ptr(canonical), ptr.Ptr("updated description"), []*models.NewRule{rule}) - require.NoError(t, err, "UpdateRole should succeed") - require.NotNil(t, updated) - assert.Equal(t, "Updated Role Name", *updated.Name) - assert.Equal(t, "updated description", *updated.Description) - - got, _, err = m.GetRole(config.Org, canonical) - require.NoError(t, err) - assert.Equal(t, "Updated Role Name", *got.Name) - - list, _, err := m.ListRoles(config.Org) - require.NoError(t, err, "ListRoles should succeed") - assert.NotEmpty(t, list) -} diff --git a/cmd/cycloid/middleware/organization_team_members_test.go b/cmd/cycloid/middleware/organization_team_members_test.go deleted file mode 100644 index 17c156950..000000000 --- a/cmd/cycloid/middleware/organization_team_members_test.go +++ /dev/null @@ -1,40 +0,0 @@ -package middleware_test - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/cycloidio/cycloid-cli/internal/ptr" - "github.com/cycloidio/cycloid-cli/pkg/testcfg" -) - -func TestTeamMembersCRUD(t *testing.T) { - m := config.Middleware - - canonical := testcfg.RandomCanonical("test-team-members") - - _, _, err := m.CreateTeam(config.Org, ptr.Ptr("Test Team Members"), ptr.Ptr(canonical), nil, []string{}) - require.NoError(t, err, "CreateTeam should succeed") - - defer func() { - _, err := m.DeleteTeam(config.Org, canonical) - require.NoError(t, err, "DeleteTeam cleanup should succeed") - }() - - members, _, err := m.ListTeamMembers(config.Org, canonical) - require.NoError(t, err, "ListTeamMembers should succeed on empty team") - assert.NotNil(t, members) - - assigned, _, err := m.AssignMemberToTeam(config.Org, canonical, ptr.Ptr("administrator"), nil) - require.NoError(t, err, "AssignMemberToTeam should succeed") - require.NotNil(t, assigned) - - got, _, err := m.GetTeamMember(config.Org, canonical, *assigned.ID) - require.NoError(t, err, "GetTeamMember should succeed") - assert.Equal(t, *assigned.ID, *got.ID) - - _, err = m.UnAssignMemberFromTeam(config.Org, canonical, *assigned.ID) - require.NoError(t, err, "UnAssignMemberFromTeam should succeed") -} diff --git a/cmd/cycloid/middleware/organization_teams_test.go b/cmd/cycloid/middleware/organization_teams_test.go deleted file mode 100644 index 11e20928c..000000000 --- a/cmd/cycloid/middleware/organization_teams_test.go +++ /dev/null @@ -1,40 +0,0 @@ -package middleware_test - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/cycloidio/cycloid-cli/internal/ptr" - "github.com/cycloidio/cycloid-cli/pkg/testcfg" -) - -func TestTeamsCRUD(t *testing.T) { - m := config.Middleware - - canonical := testcfg.RandomCanonical("test-team") - - created, _, err := m.CreateTeam(config.Org, ptr.Ptr("Test Team"), ptr.Ptr(canonical), nil, []string{}) - require.NoError(t, err, "CreateTeam should succeed") - require.NotNil(t, created) - - defer func() { - _, err := m.DeleteTeam(config.Org, canonical) - require.NoError(t, err, "DeleteTeam should succeed") - }() - - got, _, err := m.GetTeam(config.Org, canonical) - require.NoError(t, err, "GetTeam should succeed") - assert.Equal(t, canonical, *got.Canonical) - - list, _, err := m.ListTeams(config.Org, nil, nil, nil, nil) - require.NoError(t, err, "ListTeams should succeed") - assert.NotEmpty(t, list) - - newName := ptr.Ptr("Updated Team Name") - updated, _, err := m.UpdateTeam(config.Org, newName, ptr.Ptr(canonical), nil, []string{}) - require.NoError(t, err, "UpdateTeam should succeed") - assert.Equal(t, *newName, *updated.Name) - -} diff --git a/cmd/cycloid/middleware/organization_test.go b/cmd/cycloid/middleware/organization_test.go deleted file mode 100644 index 777044c22..000000000 --- a/cmd/cycloid/middleware/organization_test.go +++ /dev/null @@ -1,47 +0,0 @@ -package middleware_test - -import ( - "log" - "testing" -) - -// We need to ensure the Child org CRUD works before kicking off tests. -func TestChildOrgCrud(t *testing.T) { - // config, err := testcfg.NewConfig() - // defer config.Cleanup() - // if err != nil { - // t.Errorf("Config setup failed: %v", err) - // } - m := config.Middleware - - var childOrg = "test-create-child-org" - defer func() { - _, err := m.DeleteOrganization(childOrg) - if err != nil { - log.Fatalf("Failed to delete org '%s': %v", childOrg, err) - return - } - }() - - _, _, err := m.CreateOrganizationChild(config.Org, childOrg, nil) - if err != nil { - t.Errorf("Failed to create org '%s': %v", childOrg, err) - return - } - - var newName = "test-update-child-org" - newOrg, _, err := m.UpdateOrganization(childOrg, newName) - if err != nil { - t.Errorf("Failed to update org '%s': %v", childOrg, err) - } - - if *newOrg.Name != newName { - t.Errorf("Update org failed.\nExpected: %s | Got: %s", newName, *newOrg.Name) - } - - _, _, err = m.GetOrganization(childOrg) - if err != nil { - t.Errorf("Org '%s' is not created: %v", childOrg, err) - return - } -} diff --git a/cmd/cycloid/middleware/plugins_test.go b/cmd/cycloid/middleware/plugins_test.go deleted file mode 100644 index 5fc443611..000000000 --- a/cmd/cycloid/middleware/plugins_test.go +++ /dev/null @@ -1,317 +0,0 @@ -package middleware_test - -import ( - "fmt" - "math/rand" - "net/http" - "os" - "os/exec" - "testing" - "time" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/cycloidio/cycloid-cli/pkg/testcfg" -) - -// pluginsMiddlewareEnabled reports whether the plugin middleware tests should run. -func pluginsMiddlewareEnabled() bool { - return os.Getenv("CY_TEST_E2E_PLUGINS") == "1" -} - -// uniquePluginImage generates a unique semver-tagged plugin image URL for use with -// CreatePluginVersion. The plugin-registry enforces a global unique constraint on -// version URLs, so each version creation requires a different docker image tag. -func uniquePluginImage(t *testing.T) string { - t.Helper() - tag := fmt.Sprintf("1.0.%d", rand.Intn(999999)) - local := fmt.Sprintf("localhost:5000/plugin-hello-world:%s", tag) - api := fmt.Sprintf("docker-registry:5000/plugin-hello-world:%s", tag) - - run := func(name string, args ...string) { - t.Helper() - cmd := exec.Command(name, args...) - if err := cmd.Run(); err != nil { - t.Fatalf("uniquePluginImage: %q %v failed: %v", name, args, err) - } - } - run("docker", "tag", "cycloid/plugin-hello-world:latest", local) - run("docker", "push", local) - return api -} - -func TestPluginManagersCRUD(t *testing.T) { - if !pluginsMiddlewareEnabled() { - t.Skip("set CY_TEST_E2E_PLUGINS=1 to run plugin middleware tests") - } - - m := config.Middleware - org := config.Org - - t.Run("List", func(t *testing.T) { - managers, resp, err := m.ListPluginManagers(org) - require.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) - assert.NotNil(t, managers) - }) - - t.Run("AcceptTestPluginManager", func(t *testing.T) { - mgr, err := config.AcceptPluginManager(t) - require.NoError(t, err) - require.NotNil(t, mgr) - // API returns "invite_accepted" once accepted (not "accepted"). - assert.Contains(t, []string{"accepted", "invite_accepted"}, *mgr.InviteStatus) - }) -} - -func TestPluginRegistryCRUD(t *testing.T) { - if !pluginsMiddlewareEnabled() { - t.Skip("set CY_TEST_E2E_PLUGINS=1 to run plugin middleware tests") - } - - m := config.Middleware - org := config.Org - name := testcfg.RandomCanonical("mw-registry") - regURL := "http://plugin-registry:4000" - - reg, _, err := m.CreatePluginRegistry(org, name, regURL) - require.NoError(t, err) - require.NotNil(t, reg) - assert.Equal(t, name, *reg.Name) - - defer func() { - if _, delErr := m.DeletePluginRegistry(org, *reg.ID); delErr != nil { - t.Logf("cleanup: delete registry %d: %v", *reg.ID, delErr) - } - }() - - t.Run("Get", func(t *testing.T) { - got, resp, err := m.GetPluginRegistry(org, *reg.ID) - require.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) - assert.Equal(t, name, *got.Name) - }) - - t.Run("List", func(t *testing.T) { - regs, resp, err := m.ListPluginRegistries(org) - require.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) - var found bool - for _, r := range regs { - if *r.ID == *reg.ID { - found = true - break - } - } - assert.True(t, found, "created registry not found in list") - }) - - t.Run("Update", func(t *testing.T) { - newName := name + "-upd" - updated, resp, err := m.UpdatePluginRegistry(org, *reg.ID, newName) - require.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) - assert.Equal(t, newName, *updated.Name) - }) -} - -func TestRegistryPluginCRUD(t *testing.T) { - if !pluginsMiddlewareEnabled() { - t.Skip("set CY_TEST_E2E_PLUGINS=1 to run plugin middleware tests") - } - - m := config.Middleware - org := config.Org - - reg, err := config.NewTestPluginRegistry(t, testcfg.RandomCanonical("mw-reg-pl"), "http://plugin-registry:4000") - require.NoError(t, err) - - pluginName := testcfg.RandomCanonical("mw-plugin") - plugin, _, err := m.CreateRegistryPlugin(org, *reg.ID, pluginName) - require.NoError(t, err) - require.NotNil(t, plugin) - - defer func() { - if _, delErr := m.DeleteRegistryPlugin(org, *reg.ID, *plugin.ID); delErr != nil { - t.Logf("cleanup: delete plugin %d: %v", *plugin.ID, delErr) - } - }() - - t.Run("Get", func(t *testing.T) { - got, resp, err := m.GetRegistryPlugin(org, *reg.ID, *plugin.ID) - require.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) - assert.Equal(t, pluginName, *got.Name) - }) - - t.Run("List", func(t *testing.T) { - plugins, resp, err := m.ListRegistryPlugins(org, *reg.ID) - require.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) - var found bool - for _, p := range plugins { - if *p.ID == *plugin.ID { - found = true - break - } - } - assert.True(t, found, "created plugin not found in list") - }) - - t.Run("Update", func(t *testing.T) { - newName := pluginName + "-upd" - updated, resp, err := m.UpdateRegistryPlugin(org, *reg.ID, *plugin.ID, newName) - require.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) - assert.Equal(t, newName, *updated.Name) - }) -} - -func TestPluginVersionCRUD(t *testing.T) { - if !pluginsMiddlewareEnabled() { - t.Skip("set CY_TEST_E2E_PLUGINS=1 to run plugin middleware tests") - } - - m := config.Middleware - org := config.Org - - reg, err := config.NewTestPluginRegistry(t, testcfg.RandomCanonical("mw-reg-ver"), "http://plugin-registry:4000") - require.NoError(t, err) - - plugin, err := config.NewTestPluginInRegistry(t, *reg.ID, testcfg.RandomCanonical("mw-plver")) - require.NoError(t, err) - - ver, _, err := m.CreatePluginVersion(org, *reg.ID, *plugin.ID, uniquePluginImage(t)) - require.NoError(t, err) - require.NotNil(t, ver) - - defer func() { - if _, delErr := m.DeletePluginVersion(org, *reg.ID, *plugin.ID, *ver.ID); delErr != nil { - t.Logf("cleanup: delete version %d: %v", *ver.ID, delErr) - } - }() - - t.Run("Get", func(t *testing.T) { - got, resp, err := m.GetPluginVersion(org, *reg.ID, *plugin.ID, *ver.ID) - require.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) - assert.Equal(t, *ver.ID, *got.ID) - }) - - t.Run("List", func(t *testing.T) { - versions, resp, err := m.ListPluginVersions(org, *reg.ID, *plugin.ID) - require.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) - assert.NotEmpty(t, versions) - }) - - t.Run("ListLogs", func(t *testing.T) { - logs, resp, err := m.ListPluginVersionLogs(org, *reg.ID, *plugin.ID, *ver.ID) - require.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) - assert.NotNil(t, logs) - }) -} - -func TestPluginInstallAndGet(t *testing.T) { - if !pluginsMiddlewareEnabled() { - t.Skip("set CY_TEST_E2E_PLUGINS=1 to run plugin middleware tests") - } - - m := config.Middleware - org := config.Org - - _, err := config.AcceptPluginManager(t) - require.NoError(t, err) - - reg, err := config.NewTestPluginRegistry(t, testcfg.RandomCanonical("mw-reg-ins"), "http://plugin-registry:4000") - require.NoError(t, err) - - plugin, err := config.NewTestPluginInRegistry(t, *reg.ID, testcfg.RandomCanonical("mw-plinst")) - require.NoError(t, err) - - ver, err := config.NewTestPluginVersion(t, *reg.ID, *plugin.ID, uniquePluginImage(t)) - require.NoError(t, err) - - // Install returns 200 with PluginInstall body (swagger: "200 The Plugin Install data"). - resp, err := m.InstallPluginVersion(org, *reg.ID, *plugin.ID, *ver.ID, nil) - require.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) - - // Resolve install ID from list — allow a moment for the record to appear. - var installID uint32 - for i := 0; i < 10; i++ { - plugins, _, _ := m.ListPlugins(org) - for _, p := range plugins { - if p.Name != nil && *p.Name == *plugin.Name && p.Install != nil { - installID = *p.Install.ID - } - } - if installID != 0 { - break - } - time.Sleep(2 * time.Second) - } - require.NotZero(t, installID, "install record not found in ListPlugins") - - t.Cleanup(func() { - if _, delErr := m.DeletePlugin(org, installID); delErr != nil { - t.Logf("cleanup: delete plugin install %d: %v", installID, delErr) - } - }) - - t.Run("GetInstall", func(t *testing.T) { - install, resp, err := m.GetPlugin(org, installID) - require.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) - require.NotNil(t, install) - // The plugin-manager deploys asynchronously; status may be pending/running. - assert.NotNil(t, install.ID) - }) - - t.Run("ListInstalls", func(t *testing.T) { - plugins, resp, err := m.ListPlugins(org) - require.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) - var found bool - for _, p := range plugins { - if p.Install != nil && *p.Install.ID == installID { - found = true - break - } - } - assert.True(t, found, "install %d not found in ListPlugins", installID) - }) - - t.Run("RetryIdempotent", func(t *testing.T) { - // Second install should return 409 Conflict; retry endpoint returns 204. - retryResp, err := m.InstallPluginVersion(org, *reg.ID, *plugin.ID, *ver.ID, nil) - if err == nil { - // First install on a freshly reset DB — no conflict yet. - assert.Contains(t, []int{http.StatusOK, http.StatusAccepted}, retryResp.StatusCode) - return - } - if retryResp != nil && retryResp.StatusCode == http.StatusConflict { - retryResp2, retryErr := m.RetryPluginVersion(org, *reg.ID, *plugin.ID, *ver.ID) - require.NoError(t, retryErr) - assert.Equal(t, http.StatusNoContent, retryResp2.StatusCode) - return - } - t.Fatalf("unexpected error on second install: %v", err) - }) - - t.Run("Logs", func(t *testing.T) { - logs, resp, err := m.ListPluginLogs(org, installID) - require.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) - assert.NotNil(t, logs) - }) - - t.Run("ListWidgets", func(t *testing.T) { - widgets, resp, err := m.ListPluginWidgets(org, "sideMenuPage") - require.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) - assert.NotNil(t, widgets) - }) -} diff --git a/cmd/cycloid/middleware/project_pipelines_test.go b/cmd/cycloid/middleware/project_pipelines_test.go deleted file mode 100644 index f6b9a667b..000000000 --- a/cmd/cycloid/middleware/project_pipelines_test.go +++ /dev/null @@ -1,28 +0,0 @@ -package middleware_test - -import ( - "slices" - "testing" - - "github.com/sanity-io/litter" - - "github.com/cycloidio/cycloid-cli/client/models" -) - -func TestGetProjectPipelines(t *testing.T) { - m := config.Middleware - - got, _, err := m.GetProjectPipelines(config.Org, *config.Project.Canonical) - if err != nil { - t.Errorf("middleware.GetProjectPipelines() error = %v", err) - return - } - - index := slices.IndexFunc(got, func(p *models.Pipeline) bool { - return *p.Component.Canonical == *config.Component.Canonical - }) - - if index == -1 { - t.Errorf("failed to find created component in the list: %v\nexpected component: %v", litter.Sdump(got), litter.Sdump(config.Component)) - } -} diff --git a/cmd/cycloid/middleware/sanitize_test.go b/cmd/cycloid/middleware/sanitize_test.go deleted file mode 100644 index beca12356..000000000 --- a/cmd/cycloid/middleware/sanitize_test.go +++ /dev/null @@ -1,119 +0,0 @@ -package middleware - -import ( - "encoding/json" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestSanitizeBody(t *testing.T) { - t.Run("NilInput", func(t *testing.T) { - assert.Nil(t, sanitizeBody(nil)) - }) - - t.Run("EmptyInput", func(t *testing.T) { - assert.Nil(t, sanitizeBody([]byte{})) - }) - - t.Run("InvalidJSON", func(t *testing.T) { - input := []byte("not json") - assert.Equal(t, input, sanitizeBody(input)) - }) - - t.Run("RedactsKnownKeys", func(t *testing.T) { - input := []byte(`{"name":"my-cred","password":"secret123","type":"ssh"}`) - out := sanitizeBody(input) - require.NotNil(t, out) - - var m map[string]interface{} - require.NoError(t, json.Unmarshal(out, &m)) - assert.Equal(t, "my-cred", m["name"]) - assert.Equal(t, "[REDACTED]", m["password"]) - assert.Equal(t, "ssh", m["type"]) - }) - - t.Run("RedactsSSHKey", func(t *testing.T) { - input := []byte(`{"ssh_key":"-----BEGIN RSA PRIVATE KEY-----"}`) - out := sanitizeBody(input) - var m map[string]interface{} - require.NoError(t, json.Unmarshal(out, &m)) - assert.Equal(t, "[REDACTED]", m["ssh_key"]) - }) - - t.Run("RawKeyIsRedacted", func(t *testing.T) { - // "raw" is a sensitive catch-all field in CredentialRaw - input := []byte(`{"name":"cred","raw":{"ssh_key":"secret","type":"ssh"}}`) - out := sanitizeBody(input) - var m map[string]interface{} - require.NoError(t, json.Unmarshal(out, &m)) - assert.Equal(t, "[REDACTED]", m["raw"], "raw key itself should be redacted") - }) - - t.Run("NestedSensitiveField", func(t *testing.T) { - input := []byte(`{"credential":{"password":"x","name":"foo"}}`) - out := sanitizeBody(input) - var m map[string]interface{} - require.NoError(t, json.Unmarshal(out, &m)) - nested := m["credential"].(map[string]interface{}) - assert.Equal(t, "[REDACTED]", nested["password"]) - assert.Equal(t, "foo", nested["name"]) - }) - - t.Run("ArrayElements", func(t *testing.T) { - input := []byte(`[{"token":"abc"},{"token":"def","name":"foo"}]`) - out := sanitizeBody(input) - var arr []map[string]interface{} - require.NoError(t, json.Unmarshal(out, &arr)) - assert.Equal(t, "[REDACTED]", arr[0]["token"]) - assert.Equal(t, "[REDACTED]", arr[1]["token"]) - assert.Equal(t, "foo", arr[1]["name"]) - }) - - t.Run("CaseInsensitiveKey", func(t *testing.T) { - input := []byte(`{"Password":"xxx","SECRET_KEY":"yyy"}`) - out := sanitizeBody(input) - var m map[string]interface{} - require.NoError(t, json.Unmarshal(out, &m)) - assert.Equal(t, "[REDACTED]", m["Password"]) - assert.Equal(t, "[REDACTED]", m["SECRET_KEY"]) - }) - - t.Run("NoSensitiveKeys", func(t *testing.T) { - input := []byte(`{"name":"foo","canonical":"bar"}`) - out := sanitizeBody(input) - var m map[string]interface{} - require.NoError(t, json.Unmarshal(out, &m)) - assert.Equal(t, "foo", m["name"]) - assert.Equal(t, "bar", m["canonical"]) - }) - - t.Run("RedactsOIDCSecrets", func(t *testing.T) { - // `oidc integration set` sends oidc_client_secret / oidc_ca_cert in - // the request body; these must never reach DEBUG or error output. Non-secret - // OIDC fields must stay visible so debugging stays useful. - input := []byte(`{"config":{"type":"AuthenticationOIDC","enabled":true,"oidc_issuer":"https://idp.example.com","oidc_client_id":"public-id","oidc_client_secret":"s3cr3t","oidc_ca_cert":"-----BEGIN CERTIFICATE-----"}}`) - out := sanitizeBody(input) - var m map[string]interface{} - require.NoError(t, json.Unmarshal(out, &m)) - cfg := m["config"].(map[string]interface{}) - assert.Equal(t, "[REDACTED]", cfg["oidc_client_secret"], "oidc_client_secret must be redacted") - assert.Equal(t, "[REDACTED]", cfg["oidc_ca_cert"], "oidc_ca_cert must be redacted") - assert.Equal(t, "https://idp.example.com", cfg["oidc_issuer"], "non-secret oidc_issuer must stay visible") - assert.Equal(t, "public-id", cfg["oidc_client_id"], "non-secret oidc_client_id must stay visible") - }) - - t.Run("RedactsSecretSuffixKeys", func(t *testing.T) { - // Defense-in-depth: any *_secret / *_ca_cert field is redacted by suffix, - // so a new provider's secret field does not leak by default. - input := []byte(`{"saml_client_secret":"x","some_secret":"y","azure_ca_cert":"z","name":"ok"}`) - out := sanitizeBody(input) - var m map[string]interface{} - require.NoError(t, json.Unmarshal(out, &m)) - assert.Equal(t, "[REDACTED]", m["saml_client_secret"]) - assert.Equal(t, "[REDACTED]", m["some_secret"]) - assert.Equal(t, "[REDACTED]", m["azure_ca_cert"]) - assert.Equal(t, "ok", m["name"]) - }) -} diff --git a/cmd/cycloid/middleware/stacks_test.go b/cmd/cycloid/middleware/stacks_test.go deleted file mode 100644 index e61233409..000000000 --- a/cmd/cycloid/middleware/stacks_test.go +++ /dev/null @@ -1,227 +0,0 @@ -package middleware_test - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/cycloidio/cycloid-cli/internal/ptr" -) - -const ( - testStackCanonical = "stack-e2e-stackforms" - testStackRef = "cycloid:stack-e2e-stackforms" - testStackUseCase = "default" -) - -func TestStacksGetStack(t *testing.T) { - m := config.Middleware - t.Run("GetStackOk", func(t *testing.T) { - stack, _, err := m.GetStack(config.Org, testStackRef) - require.NoError(t, err) - require.NotNil(t, stack) - assert.Equal(t, testStackCanonical, *stack.Canonical) - assert.NotNil(t, stack.Ref) - assert.Equal(t, testStackRef, *stack.Ref) - }) - t.Run("GetStackNotFound", func(t *testing.T) { - _, _, err := m.GetStack(config.Org, "org:nonexistent-stack") - require.Error(t, err) - assert.Contains(t, err.Error(), "404") - }) -} -func TestStacksListStacks(t *testing.T) { - m := config.Middleware - t.Run("ListStacksOk", func(t *testing.T) { - stacks, _, err := m.ListStacks(config.Org) - require.NoError(t, err) - require.NotNil(t, stacks) - assert.NotEmpty(t, stacks, "should have at least one stack") - // Verify the test stack is in the list - found := false - for _, stack := range stacks { - if stack.Canonical != nil && *stack.Canonical == testStackCanonical { - found = true - assert.Equal(t, testStackRef, *stack.Ref) - break - } - } - assert.True(t, found, "test stack should be in the list") - }) -} -func TestStacksListStackVersions(t *testing.T) { - m := config.Middleware - t.Run("ListStackVersionsOk", func(t *testing.T) { - versions, _, err := m.ListStackVersions(config.Org, testStackRef) - require.NoError(t, err) - require.NotNil(t, versions) - assert.NotEmpty(t, versions, "should have at least one version") - // Verify all versions have required fields - for _, version := range versions { - assert.NotNil(t, version.ID, "version should have an ID") - assert.NotNil(t, version.CommitHash, "version should have a commit hash") - assert.NotNil(t, version.Type, "version should have a type") - assert.NotNil(t, version.Name, "version should have a name") - } - }) - t.Run("ListStackVersionsNotFound", func(t *testing.T) { - _, _, err := m.ListStackVersions(config.Org, "org:nonexistent-stack") - require.Error(t, err) - }) -} -func TestStacksListStackUseCases(t *testing.T) { - m := config.Middleware - t.Run("ListStackUseCasesWithDefaultVersion", func(t *testing.T) { - // When all version params are empty, should use default version - useCases, _, err := m.ListStackUseCases(config.Org, testStackRef, "", "", "") - require.NoError(t, err) - require.NotNil(t, useCases) - assert.NotEmpty(t, useCases, "should have at least one use case") - found := false - for _, uc := range useCases { - if uc.UseCase != nil && *uc.UseCase == testStackUseCase { - found = true - assert.NotNil(t, uc.Name, "use case should have a name") - break - } - } - assert.True(t, found, "default use case should be in the list") - }) - t.Run("ListStackUseCasesWithCommitHash", func(t *testing.T) { - // First, get a valid commit hash. We'll use commit hash from the stacks - // branch version to ensure we're getting use cases - versions, _, err := m.ListStackVersions(config.Org, testStackRef) - require.NoError(t, err) - require.NotEmpty(t, versions) - var commitHash string - for _, version := range versions { - if version.Type != nil && *version.Type == "branch" && version.Name != nil && *version.Name == "stacks" { - commitHash = *version.CommitHash - break - } - } - // Use the commit hash to list use cases - useCases, _, err := m.ListStackUseCases(config.Org, testStackRef, "", "", commitHash) - require.NoError(t, err) - require.NotNil(t, useCases) - assert.NotEmpty(t, useCases, "should have at least one use case") - }) - t.Run("ListStackUseCasesWithTag", func(t *testing.T) { - versions, _, err := m.ListStackVersions(config.Org, testStackRef) - require.NoError(t, err) - require.NotEmpty(t, versions) - - useCases, _, err := m.ListStackUseCases(config.Org, testStackRef, "stack-e2e-stackforms/v1", "", "") - require.NoError(t, err) - require.NotNil(t, useCases) - assert.NotEmpty(t, useCases, "should have at least one use case") - }) - t.Run("ListStackUseCasesWithStacksBranch", func(t *testing.T) { - // Use the branch to list use cases - useCases, _, err := m.ListStackUseCases(config.Org, testStackRef, "", "stacks", "") - require.NoError(t, err) - require.NotNil(t, useCases) - assert.NotEmpty(t, useCases, "should have at least one use case") - }) - t.Run("ListStackUseCasesTagNotFound", func(t *testing.T) { - _, _, err := m.ListStackUseCases(config.Org, testStackRef, "v999.999.999", "", "") - require.Error(t, err) - assert.Contains(t, err.Error(), "not found") - }) - t.Run("ListStackUseCasesBranchNotFound", func(t *testing.T) { - _, _, err := m.ListStackUseCases(config.Org, testStackRef, "", "nonexistent-branch-xyz", "") - require.Error(t, err) - assert.Contains(t, err.Error(), "not found") - }) - t.Run("ListStackUseCasesCommitHashNotFound", func(t *testing.T) { - _, _, err := m.ListStackUseCases(config.Org, testStackRef, "", "", "0000000000000000000000000000000000000000") - require.Error(t, err) - assert.Contains(t, err.Error(), "not found") - }) - t.Run("ListStackUseCasesStackNotFound", func(t *testing.T) { - _, _, err := m.ListStackUseCases(config.Org, "org:nonexistent-stack", "", "", "") - require.Error(t, err) - }) -} -func TestStacksUpdateStack(t *testing.T) { - m := config.Middleware - t.Run("UpdateStackVisibility", func(t *testing.T) { - stack, _, err := m.GetStack(config.Org, testStackRef) - require.NoError(t, err) - originalVisibility := stack.Visibility - teamCanonical := "" - if stack.Team != nil && stack.Team.Canonical != nil { - teamCanonical = *stack.Team.Canonical - } - // Toggle visibility - newVisibility := "local" - if originalVisibility != nil && *originalVisibility == "local" { - newVisibility = "shared" - } - updatedStack, _, err := m.UpdateStack(config.Org, testStackRef, teamCanonical, ptr.Ptr(newVisibility)) - require.NoError(t, err) - require.NotNil(t, updatedStack) - assert.Equal(t, newVisibility, *updatedStack.Visibility) - - _, _, err = m.UpdateStack(config.Org, testStackRef, teamCanonical, originalVisibility) - require.NoError(t, err) - }) - t.Run("UpdateStackNotFound", func(t *testing.T) { - _, _, err := m.UpdateStack(config.Org, "org:nonexistent-stack", "", ptr.Ptr("private")) - require.Error(t, err) - }) -} - -func TestResolveStackVersionIntegration(t *testing.T) { - // These tests verify that resolveStackVersion works correctly through the public method ListStackUseCases - - m := config.Middleware - t.Run("ResolveDefaultVersionThroughListStackUseCases", func(t *testing.T) { - // When no version is specified, should use default version - useCases1, _, err1 := m.ListStackUseCases(config.Org, testStackRef, "", "", "") - require.NoError(t, err1) - require.NotEmpty(t, useCases1) - // Should return the same use cases each time with default version - useCases2, _, err2 := m.ListStackUseCases(config.Org, testStackRef, "", "", "") - require.NoError(t, err2) - require.NotEmpty(t, useCases2) - assert.Equal(t, len(useCases1), len(useCases2), "default version should be consistent") - }) - t.Run("ResolveCommitHashThroughListStackUseCases", func(t *testing.T) { - versions, _, err := m.ListStackVersions(config.Org, testStackRef) - require.NoError(t, err) - require.NotEmpty(t, versions) - commitHash := *versions[0].CommitHash - useCases, _, err := m.ListStackUseCases(config.Org, testStackRef, "", "", commitHash) - require.NoError(t, err) - require.NotEmpty(t, useCases) - }) - t.Run("PriorityTagOverBranchOverCommitHash", func(t *testing.T) { - versions, _, err := m.ListStackVersions(config.Org, testStackRef) - require.NoError(t, err) - require.NotEmpty(t, versions) - var commitHash string - // Make sure commit hash is from the stacks branch - for _, version := range versions { - if version.Type != nil && *version.Type == "branch" && version.Name != nil && *version.Name == "stacks" { - commitHash = *version.CommitHash - break - } - } - // If we have a tag, it should be used - useCases, _, err := m.ListStackUseCases(config.Org, testStackRef, "stack-e2e-stackforms/v1", "", "") - require.NoError(t, err) - require.NotEmpty(t, useCases) - - // If we have a branch, it should be used - useCases, _, err = m.ListStackUseCases(config.Org, testStackRef, "", "stacks", "") - require.NoError(t, err) - require.NotEmpty(t, useCases) - - // If we have a commit hash, it should be used - useCases, _, err = m.ListStackUseCases(config.Org, testStackRef, "", "", commitHash) - require.NoError(t, err) - require.NotEmpty(t, useCases) - }) -} diff --git a/cmd/cycloid/middleware/user_test.go b/cmd/cycloid/middleware/user_test.go deleted file mode 100644 index f3c79c018..000000000 --- a/cmd/cycloid/middleware/user_test.go +++ /dev/null @@ -1,17 +0,0 @@ -package middleware_test - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestRefreshToken(t *testing.T) { - m := config.Middleware - - session, _, err := m.RefreshToken(&config.Org, nil, config.APIKey) - require.NoError(t, err) - assert.NotNil(t, session) - assert.NotEmpty(t, session.Token) -} diff --git a/cmd/cycloid/middleware/utils_test.go b/cmd/cycloid/middleware/utils_test.go deleted file mode 100644 index 0bc92a8ee..000000000 --- a/cmd/cycloid/middleware/utils_test.go +++ /dev/null @@ -1,83 +0,0 @@ -package middleware_test - -import ( - "testing" - - "github.com/stretchr/testify/assert" - - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" -) - -func TestToCanonical(t *testing.T) { - testCanonicals := []struct { - testCase string - name string - expect string - }{ - {"AllowedChar", "azAZ02-azAZ02", "azaz02-azaz02"}, - {"SpaceConversionChar", "azAZ02 azAZ02", "azaz02_azaz02"}, - {"RemoveUnallowedChar", "az@@$$02 azŷùù&éZ02", "az02_azz02"}, - {"EndWith-", "canonical-", "canonical"}, - {"StartWith-", "-canonical", "canonical"}, - {"EndWith_", "canonical_", "canonical"}, - {"StartWith_", "_canonical", "canonical"}, - } - - for _, tc := range testCanonicals { - t.Run(tc.testCase, func(t *testing.T) { - assert.Equal(t, tc.expect, middleware.ToCanonical(tc.name)) - }) - } -} - -func TestNameOrCanonical(t *testing.T) { - testCases := []struct { - name string - inputName string - inputCanonical string - expectedName string - expectedCan string - expectErr bool - }{ - { - name: "name-only infers canonical", - inputName: "My Cool Project", - expectedName: "My Cool Project", - expectedCan: "my_cool_project", - expectErr: false, - }, - { - name: "canonical-only infers name", - inputCanonical: "my-project", - expectedName: "My-project", - expectedCan: "my-project", - expectErr: false, - }, - { - name: "both provided keep values", - inputName: "Existing Name", - inputCanonical: "existing-canonical", - expectedName: "Existing Name", - expectedCan: "existing-canonical", - expectErr: false, - }, - { - name: "both empty return error", - expectErr: true, - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - gotName, gotCanonical, err := middleware.NameOrCanonical(&tc.inputName, &tc.inputCanonical) - if tc.expectErr { - assert.Error(t, err) - return - } - - assert.NoError(t, err) - assert.Equal(t, tc.expectedName, gotName) - assert.Equal(t, tc.expectedCan, gotCanonical) - }) - } -} diff --git a/cmd/cycloid/roles/cmd_test.go b/cmd/cycloid/roles/cmd_test.go deleted file mode 100644 index 81fe16d05..000000000 --- a/cmd/cycloid/roles/cmd_test.go +++ /dev/null @@ -1,40 +0,0 @@ -package roles - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestRolesCommandTree(t *testing.T) { - t.Parallel() - root := NewCommands() - assert.Equal(t, "roles", root.Name()) - - names := make(map[string]int) - for _, c := range root.Commands() { - names[c.Name()]++ - } - - require.Equal(t, 1, names["list"]) - require.Equal(t, 1, names["get"]) - require.Equal(t, 1, names["create"]) - require.Equal(t, 1, names["update"]) - require.Equal(t, 1, names["delete"], "delete must be registered exactly once") -} - -func TestRolesCreateHasUpdateFlag(t *testing.T) { - t.Parallel() - cmd := NewCreateCommand() - f := cmd.Flags().Lookup("update") - require.NotNil(t, f) - assert.Equal(t, "bool", f.Value.Type()) -} - -func TestRolesUpdateCommandNoUpdateFlag(t *testing.T) { - t.Parallel() - cmd := NewUpdateCommand() - // update subcommand is always upsert; no --update flag - assert.Nil(t, cmd.Flags().Lookup("update")) -} diff --git a/cmd/cycloid/uri/expand_test.go b/cmd/cycloid/uri/expand_test.go deleted file mode 100644 index 2671d04d5..000000000 --- a/cmd/cycloid/uri/expand_test.go +++ /dev/null @@ -1,75 +0,0 @@ -package uri - -import ( - "testing" -) - -func TestIsIgnored(t *testing.T) { - type args struct { - path string - ignores []string - } - tests := []struct { - name string - args args - want bool - wantErr bool - }{ - { - "TestSimpleRelPathOk", - args{ - "ignore-me/", - []string{ - "ignore-me/", - }, - }, - true, - false, - }, - { - "TestSimpleAbsOk", - args{ - "/home/toto", - []string{ - "/home/toto", - }, - }, - true, - false, - }, - { - "TestAbsPatternOk", - args{ - "/home/toto/something", - []string{ - "/home/toto/*", - }, - }, - true, - false, - }, - { - "TestAbsPatternNestedOk", - args{ - "/home/toto/something/else", - []string{ - "/home/toto/*", - }, - }, - true, - false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := IsIgnored(tt.args.path, tt.args.ignores) - if (err != nil) != tt.wantErr { - t.Errorf("IsIgnored() error = %v, wantErr %v", err, tt.wantErr) - return - } - if got != tt.want { - t.Errorf("IsIgnored() = %v, want %v", got, tt.want) - } - }) - } -} diff --git a/cmd/cycloid/version_integration_test.go b/cmd/cycloid/version_integration_test.go deleted file mode 100644 index e04dc0753..000000000 --- a/cmd/cycloid/version_integration_test.go +++ /dev/null @@ -1,49 +0,0 @@ -package cycloid_test - -import ( - "bytes" - "strings" - "testing" - - "github.com/stretchr/testify/require" - - "github.com/cycloidio/cycloid-cli/cmd" -) - -// TestVersion_JSONWithBadAPIURL runs `cy version -o json` against a non-API host. -// The response body is HTML; errors are always shown in human-readable format on stderr -// regardless of --output flag, so the HTML content should appear in the error block. -func TestVersion_JSONWithBadAPIURL(t *testing.T) { - t.Setenv("CY_API_URL", "http://google.com") - t.Setenv("CY_API_KEY", "") - - root := cmd.NewRootCommand() - var stdout, stderr bytes.Buffer - root.SetOut(&stdout) - root.SetErr(&stderr) - root.SetArgs([]string{"version", "-o", "json"}) - - err := root.Execute() - require.Error(t, err) - - rawErr := strings.TrimSpace(stderr.String()) - require.NotEmpty(t, rawErr, "expected error output on stderr (stdout=%q)", stdout.String()) - - // Errors are always rendered as a human-readable block, not JSON - lower := strings.ToLower(rawErr) - require.True(t, - strings.Contains(lower, "api error"), - "expected 'API Error' header in error output, got: %q", truncateRunes(rawErr, 200)) - - require.True(t, - strings.Contains(lower, "? -Use cy environment delete --env to destroy the org-level environment.`, cmd.Flag("project").Value.String()) + return fmt.Errorf("--project is no longer accepted on environment delete, did you mean cy environment unlink --project %s --env ", cmd.Flag("project").Value.String()) } org, err := cyargs.GetOrg(cmd) @@ -44,7 +42,7 @@ Use cy environment delete --env to destroy the org-level environment.`, cm return err } - if envFlag, err := cyargs.GetEnv(cmd); err != nil { + if envFlag, err := cyargs.GetEnvOrEmpty(cmd); err != nil { return err } else if envFlag != "" { found := false @@ -60,7 +58,7 @@ Use cy environment delete --env to destroy the org-level environment.`, cm } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) for _, env := range args { _, err = m.DeleteOrgEnv(org, env) diff --git a/cmd/cycloid/environments/get.go b/cmd/environments/get.go similarity index 87% rename from cmd/cycloid/environments/get.go rename to cmd/environments/get.go index 9069d309d..51b2b2bfe 100644 --- a/cmd/cycloid/environments/get.go +++ b/cmd/environments/get.go @@ -3,15 +3,15 @@ package environments import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" + "github.com/cycloidio/cycloid-cli/gen/models" ) func NewGetCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "get [canonical...]", Args: cyargs.RequireArgsOrFlag("env"), Short: "get an environment", @@ -32,14 +32,14 @@ func NewGetCommand() *cobra.Command { func get(cmd *cobra.Command, args []string) error { api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) org, err := cyargs.GetOrg(cmd) if err != nil { return err } - if envFlag, err := cyargs.GetEnv(cmd); err != nil { + if envFlag, err := cyargs.GetEnvOrEmpty(cmd); err != nil { return err } else if envFlag != "" { found := false diff --git a/cmd/cycloid/environments/link.go b/cmd/environments/link.go similarity index 84% rename from cmd/cycloid/environments/link.go rename to cmd/environments/link.go index 73011ddc3..d45531ead 100644 --- a/cmd/cycloid/environments/link.go +++ b/cmd/environments/link.go @@ -3,14 +3,14 @@ package environments import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" ) func NewLinkCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "link", Args: cobra.NoArgs, Short: "link an environment to a project", @@ -42,7 +42,7 @@ func link(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) _, err = m.LinkEnvToProject(org, project, env) if err != nil { @@ -52,7 +52,7 @@ func link(cmd *cobra.Command, args []string) error { } func NewUnlinkCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "unlink", Args: cobra.NoArgs, Short: "unlink an environment from a project", @@ -90,9 +90,9 @@ func unlink(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) - opts := middleware.DeleteOptions{Force: force, SkipHooks: skipHooks, IgnoreConfigFilesErr: ignoreConfigFilesErr} + opts := apiclient.DeleteOptions{Force: force, SkipHooks: skipHooks, IgnoreConfigFilesErr: ignoreConfigFilesErr} _, err = m.UnlinkEnvFromProject(org, project, env, opts) if err != nil { return cyout.Print(cmd, nil, err, "failed to unlink environment from project") diff --git a/cmd/cycloid/environments/list.go b/cmd/environments/list.go similarity index 86% rename from cmd/cycloid/environments/list.go rename to cmd/environments/list.go index 1403db278..356907972 100644 --- a/cmd/cycloid/environments/list.go +++ b/cmd/environments/list.go @@ -3,12 +3,12 @@ package environments import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" + "github.com/cycloidio/cycloid-cli/gen/models" ) var environmentTableOptions = printer.Options{ @@ -17,7 +17,7 @@ var environmentTableOptions = printer.Options{ } func NewListCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "list", Args: cobra.NoArgs, Short: "list environments", @@ -32,7 +32,7 @@ func NewListCommand() *cobra.Command { func list(cmd *cobra.Command, args []string) error { api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) org, err := cyargs.GetOrg(cmd) if err != nil { diff --git a/cmd/cycloid/environments/update.go b/cmd/environments/update.go similarity index 87% rename from cmd/cycloid/environments/update.go rename to cmd/environments/update.go index 8d520a957..486530a77 100644 --- a/cmd/cycloid/environments/update.go +++ b/cmd/environments/update.go @@ -3,15 +3,15 @@ package environments import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" ) func NewUpdateCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "update", Args: cobra.NoArgs, Short: "update an environment", @@ -44,7 +44,7 @@ func update(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) result, err := createOrUpdateEnvironment(cmd, m, org, env, true) return cyout.PrintWithOptions(cmd, result, err, "failed to update environment", printer.Options{}) diff --git a/cmd/cycloid/environments/utils.go b/cmd/environments/utils.go similarity index 90% rename from cmd/cycloid/environments/utils.go rename to cmd/environments/utils.go index 2742ccd1a..de35cc0f6 100644 --- a/cmd/cycloid/environments/utils.go +++ b/cmd/environments/utils.go @@ -7,10 +7,10 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" "github.com/cycloidio/cycloid-cli/internal/cyargs" - "github.com/cycloidio/cycloid-cli/internal/ptr" + "github.com/cycloidio/cycloid-cli/gen/models" + "github.com/cycloidio/cycloid-cli/utils/ptr" ) func envTypeFromCurrent(current *models.Environment) string { @@ -58,10 +58,10 @@ func buildNewEnvironment(cmd *cobra.Command, name, canonical string, current *mo if err != nil { return nil, err } - body.Type = ptr.Ptr(value) + body.Type = value } else if current != nil { if t := envTypeFromCurrent(current); t != "" { - body.Type = ptr.Ptr(t) + body.Type = t } } @@ -175,12 +175,12 @@ func buildUpdateEnvironment(cmd *cobra.Command, current *models.Environment) (*m return body, nil } -func createOrUpdateEnvironment(cmd *cobra.Command, m middleware.Middleware, org, canonical string, allowUpdate bool) (*models.Environment, error) { +func createOrUpdateEnvironment(cmd *cobra.Command, m apiclient.Middleware, org, canonical string, allowUpdate bool) (*models.Environment, error) { name, err := cyargs.GetName(cmd) if err != nil { return nil, err } - name, canonical, err = middleware.NameOrCanonical(&name, &canonical) + name, canonical, err = apiclient.NameOrCanonical(&name, &canonical) if err != nil { return nil, err } @@ -198,7 +198,7 @@ func createOrUpdateEnvironment(cmd *cobra.Command, m middleware.Middleware, org, return updated, err } - var apiErr *middleware.APIResponseError + var apiErr *apiclient.APIResponseError if !stderrors.As(err, &apiErr) || apiErr.StatusCode != http.StatusNotFound { return nil, err } diff --git a/cmd/cycloid/environmenttypes/cmd.go b/cmd/environmenttypes/cmd.go similarity index 100% rename from cmd/cycloid/environmenttypes/cmd.go rename to cmd/environmenttypes/cmd.go diff --git a/cmd/cycloid/environmenttypes/create.go b/cmd/environmenttypes/create.go similarity index 89% rename from cmd/cycloid/environmenttypes/create.go rename to cmd/environmenttypes/create.go index 17eda129b..1bdefd20e 100644 --- a/cmd/cycloid/environmenttypes/create.go +++ b/cmd/environmenttypes/create.go @@ -6,13 +6,13 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" - "github.com/cycloidio/cycloid-cli/internal/ptr" "github.com/cycloidio/cycloid-cli/printer" + "github.com/cycloidio/cycloid-cli/gen/models" + "github.com/cycloidio/cycloid-cli/utils/ptr" ) func NewCreateCommand() *cobra.Command { @@ -48,7 +48,7 @@ func create(cmd *cobra.Command, args []string) error { if err != nil { return err } - name, canonical, err = middleware.NameOrCanonical(&name, &canonical) + name, canonical, err = apiclient.NameOrCanonical(&name, &canonical) if err != nil { return err } @@ -59,14 +59,14 @@ func create(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) if cyargs.GetUpdate(cmd) { _, _, getErr := m.GetEnvironmentType(org, canonical) if getErr == nil { return updateEnvironmentType(cmd, args) } - var apiErr *middleware.APIResponseError + var apiErr *apiclient.APIResponseError if !stderrors.As(getErr, &apiErr) || apiErr.StatusCode != http.StatusNotFound { return cyout.PrintWithOptions(cmd, nil, getErr, "failed to check existing environment type", printer.Options{}) } @@ -108,7 +108,7 @@ func updateEnvironmentType(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) current, _, err := m.GetEnvironmentType(org, canonical) if err != nil { diff --git a/cmd/cycloid/environmenttypes/list.go b/cmd/environmenttypes/list.go similarity index 89% rename from cmd/cycloid/environmenttypes/list.go rename to cmd/environmenttypes/list.go index 269741295..31941c8cf 100644 --- a/cmd/cycloid/environmenttypes/list.go +++ b/cmd/environmenttypes/list.go @@ -5,19 +5,19 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" + "github.com/cycloidio/cycloid-cli/gen/models" ) func NewListCommand() *cobra.Command { cmd := &cobra.Command{ - Use: "list", - Short: "List environment types", - RunE: list, - Args: cobra.NoArgs, + Use: "list", + Short: "List environment types", + RunE: list, + Args: cobra.NoArgs, } cyout.RegisterModel(cmd, models.EnvironmentType{}) @@ -31,7 +31,7 @@ func list(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) types, _, err := m.ListEnvironmentTypes(org) return cyout.PrintWithOptions(cmd, types, err, "failed to list environment types", environmentTypeTableOptions) @@ -64,7 +64,7 @@ func get(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) if len(args) == 1 { envType, _, err := m.GetEnvironmentType(org, args[0]) @@ -108,7 +108,7 @@ func deleteEnvironmentType(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) for _, canonical := range args { if _, err := m.DeleteEnvironmentType(org, canonical); err != nil { diff --git a/cmd/cycloid/events/cmd.go b/cmd/events/cmd.go similarity index 90% rename from cmd/cycloid/events/cmd.go rename to cmd/events/cmd.go index ecb942539..cc6316920 100644 --- a/cmd/cycloid/events/cmd.go +++ b/cmd/events/cmd.go @@ -5,7 +5,7 @@ import ( ) func NewCommands() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "event", Aliases: []string{ "events", diff --git a/cmd/cycloid/events/list.go b/cmd/events/list.go similarity index 91% rename from cmd/cycloid/events/list.go rename to cmd/events/list.go index 512a260ef..806e7bba7 100644 --- a/cmd/cycloid/events/list.go +++ b/cmd/events/list.go @@ -5,15 +5,15 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" ) func NewListCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "list", Args: cobra.NoArgs, Aliases: []string{"ls"}, @@ -36,7 +36,7 @@ cy --org my-org event list --begin 0 --end "$(date --date "last week" +"%s")" -- func list(cmd *cobra.Command, args []string) error { api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) var err error diff --git a/cmd/cycloid/events/send.go b/cmd/events/send.go similarity index 93% rename from cmd/cycloid/events/send.go rename to cmd/events/send.go index 06760cb52..a5a5b519e 100644 --- a/cmd/cycloid/events/send.go +++ b/cmd/events/send.go @@ -6,8 +6,8 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" @@ -25,7 +25,7 @@ var ( ) func NewSendCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "create", Args: cobra.NoArgs, Short: "create an event", @@ -53,7 +53,7 @@ func NewSendCommand() *cobra.Command { func send(cmd *cobra.Command, args []string) error { api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) var err error diff --git a/cmd/cycloid/externalbackends/cmd.go b/cmd/externalbackends/cmd.go similarity index 92% rename from cmd/cycloid/externalbackends/cmd.go rename to cmd/externalbackends/cmd.go index db5a03ad5..f9ff402e1 100644 --- a/cmd/cycloid/externalbackends/cmd.go +++ b/cmd/externalbackends/cmd.go @@ -5,7 +5,7 @@ import ( ) func NewCommands() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "external-backend", Aliases: []string{ "external-backends", diff --git a/cmd/cycloid/externalbackends/common.go b/cmd/externalbackends/common.go similarity index 99% rename from cmd/cycloid/externalbackends/common.go rename to cmd/externalbackends/common.go index e935de62d..a7377f761 100644 --- a/cmd/cycloid/externalbackends/common.go +++ b/cmd/externalbackends/common.go @@ -32,6 +32,7 @@ func WithFlagBucketName(cmd *cobra.Command) string { cmd.Flags().StringVar(&awsBucketName, flagName, "", "bucket name") return flagName } + func WithFlagBucketPath(cmd *cobra.Command) string { flagName := "bucket-path" cmd.Flags().StringVar(&awsBucketPath, flagName, "", "bucket path") @@ -43,16 +44,19 @@ func WithFlagS3BucketEndpoint(cmd *cobra.Command) string { cmd.Flags().StringVar(&awsS3BucketEndpoint, flagName, "", "Aws S3 endpoint") return flagName } + func WithFlagS3ForcePathStyle(cmd *cobra.Command) string { flagName := "s3-force-path-style" cmd.Flags().BoolVar(&awsS3ForcePathStyle, flagName, true, "") return flagName } + func WithFlagSkipVerifySSL(cmd *cobra.Command) string { flagName := "skip-verify-ssl" cmd.Flags().BoolVar(&skipVerifySSL, flagName, false, "") return flagName } + func WithFlagDefault(cmd *cobra.Command) string { flagName := "default" cmd.Flags().BoolVar(&def, flagName, false, "") @@ -64,6 +68,7 @@ func WithFlagURL(cmd *cobra.Command) string { cmd.Flags().StringSliceVar(&urls, flagName, nil, "urls") return flagName } + func WithFlagPrefilter(cmd *cobra.Command) string { flagName := "prefilter" cmd.Flags().StringToStringVar(&prefilters, flagName, nil, "key=value") diff --git a/cmd/cycloid/externalbackends/create.go b/cmd/externalbackends/create.go similarity index 89% rename from cmd/cycloid/externalbackends/create.go rename to cmd/externalbackends/create.go index 1b50b526d..fcb4b4bdb 100644 --- a/cmd/cycloid/externalbackends/create.go +++ b/cmd/externalbackends/create.go @@ -3,7 +3,7 @@ package externalbackends import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" + "github.com/cycloidio/cycloid-cli/cmd/common" ) const noDefault = false @@ -11,7 +11,7 @@ const noDefault = false var hostMapping, messageMapping, timestampMapping, esIndex string func NewCreateCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "create [log|infraview]", Args: cobra.NoArgs, Short: "create an external-backend", @@ -33,8 +33,7 @@ func NewCreateCommand() *cobra.Command { } func newInfraViewCommand() *cobra.Command { - - var infraViewCmd = &cobra.Command{ + infraViewCmd := &cobra.Command{ Use: "infraview [backend]", // RunE: create, } @@ -42,7 +41,7 @@ func newInfraViewCommand() *cobra.Command { common.RequiredPersistentFlag(common.WithFlagEnv, infraViewCmd) // AWSRemoteTFState - var aWSRemoteTFState = &cobra.Command{ + aWSRemoteTFState := &cobra.Command{ Use: "AWSRemoteTFState", Args: cobra.NoArgs, RunE: createInfraView, @@ -56,7 +55,7 @@ func newInfraViewCommand() *cobra.Command { WithFlagSkipVerifySSL(aWSRemoteTFState) WithFlagDefault(aWSRemoteTFState) - var gCPRemoteTFState = &cobra.Command{ + gCPRemoteTFState := &cobra.Command{ Use: "GCPRemoteTFState", Args: cobra.NoArgs, RunE: createInfraView, @@ -66,7 +65,7 @@ func newInfraViewCommand() *cobra.Command { WithFlagBucketPath(gCPRemoteTFState) WithFlagDefault(gCPRemoteTFState) - var swiftRemoteTFState = &cobra.Command{ + swiftRemoteTFState := &cobra.Command{ Use: "SwiftRemoteTFState", Args: cobra.NoArgs, RunE: createInfraView, @@ -87,13 +86,13 @@ func newInfraViewCommand() *cobra.Command { } func newEventsCommand() *cobra.Command { - var eventCmd = &cobra.Command{ + eventCmd := &cobra.Command{ Use: "events [backend]", Hidden: true, } // Aws CW logs - var eventsAWSCloudWatchLogsCmd = &cobra.Command{ + eventsAWSCloudWatchLogsCmd := &cobra.Command{ Use: "AWSCloudWatchLogs", Args: cobra.NoArgs, RunE: createEvents, @@ -106,12 +105,12 @@ func newEventsCommand() *cobra.Command { } func newLogsCommand() *cobra.Command { - var logsCmd = &cobra.Command{ + logsCmd := &cobra.Command{ Use: "logs [backend]", } // Aws CW logs - var logsAWSCloudWatchLogsCmd = &cobra.Command{ + logsAWSCloudWatchLogsCmd := &cobra.Command{ Use: "AWSCloudWatchLogs", RunE: createLogs, } @@ -120,7 +119,7 @@ func newLogsCommand() *cobra.Command { common.RequiredFlag(common.WithFlagCred, logsAWSCloudWatchLogsCmd) // Elasticsearch - var logsElasticsearchLogsCmd = &cobra.Command{ + logsElasticsearchLogsCmd := &cobra.Command{ Use: "ElasticsearchLogs [SourceName]", Args: cobra.ExactArgs(1), RunE: createLogs, diff --git a/cmd/cycloid/externalbackends/create_events.go b/cmd/externalbackends/create_events.go similarity index 85% rename from cmd/cycloid/externalbackends/create_events.go rename to cmd/externalbackends/create_events.go index cb9371923..a44f1b6b8 100644 --- a/cmd/cycloid/externalbackends/create_events.go +++ b/cmd/externalbackends/create_events.go @@ -5,17 +5,17 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" + "github.com/cycloidio/cycloid-cli/gen/models" ) func createEvents(cmd *cobra.Command, args []string) error { api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) var ( err error diff --git a/cmd/cycloid/externalbackends/create_infra_view.go b/cmd/externalbackends/create_infra_view.go similarity index 92% rename from cmd/cycloid/externalbackends/create_infra_view.go rename to cmd/externalbackends/create_infra_view.go index 66b528fb6..1485d99d8 100644 --- a/cmd/cycloid/externalbackends/create_infra_view.go +++ b/cmd/externalbackends/create_infra_view.go @@ -5,17 +5,17 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" + "github.com/cycloidio/cycloid-cli/gen/models" ) func createInfraView(cmd *cobra.Command, args []string) error { api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) var ( purpose = "remote_tfstate" @@ -43,7 +43,7 @@ func createInfraView(cmd *cobra.Command, args []string) error { return err } - //Common + // Common cred, err := cmd.Flags().GetString("cred") if err != nil { return err diff --git a/cmd/cycloid/externalbackends/create_logs.go b/cmd/externalbackends/create_logs.go similarity index 90% rename from cmd/cycloid/externalbackends/create_logs.go rename to cmd/externalbackends/create_logs.go index d99a45201..892e1e8b5 100644 --- a/cmd/cycloid/externalbackends/create_logs.go +++ b/cmd/externalbackends/create_logs.go @@ -6,17 +6,17 @@ import ( "github.com/go-openapi/strfmt" "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" + "github.com/cycloidio/cycloid-cli/gen/models" ) func createLogs(cmd *cobra.Command, args []string) error { api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) var ( ebC models.ExternalBackendConfiguration @@ -81,7 +81,7 @@ func createLogs(cmd *cobra.Command, args []string) error { } // In this case we know there is exactly one arg - var sourceName = args[0] + sourceName := args[0] esM := models.ElasticsearchLogsSourcesAnonMapping{ Host: &hostMapping, @@ -104,7 +104,7 @@ func createLogs(cmd *cobra.Command, args []string) error { } sources := map[string]map[string]models.ElasticsearchLogsSourcesAnon{ - env: map[string]models.ElasticsearchLogsSourcesAnon{ + env: { sourceName: esS, }, } diff --git a/cmd/cycloid/externalbackends/delete.go b/cmd/externalbackends/delete.go similarity index 83% rename from cmd/cycloid/externalbackends/delete.go rename to cmd/externalbackends/delete.go index 88825be0e..3dff54a17 100644 --- a/cmd/cycloid/externalbackends/delete.go +++ b/cmd/externalbackends/delete.go @@ -3,15 +3,15 @@ package externalbackends import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" ) func NewDeleteCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "delete", Args: cobra.NoArgs, Short: "delete an external backend configuration", @@ -28,7 +28,7 @@ func NewDeleteCommand() *cobra.Command { func del(cmd *cobra.Command, args []string) error { api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) org, err := cyargs.GetOrg(cmd) if err != nil { diff --git a/cmd/cycloid/externalbackends/get.go b/cmd/externalbackends/get.go similarity index 94% rename from cmd/cycloid/externalbackends/get.go rename to cmd/externalbackends/get.go index 0020b340d..e73e0735b 100644 --- a/cmd/cycloid/externalbackends/get.go +++ b/cmd/externalbackends/get.go @@ -7,7 +7,7 @@ import ( ) func NewGetCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "get", Args: cobra.NoArgs, Hidden: true, diff --git a/cmd/cycloid/externalbackends/list.go b/cmd/externalbackends/list.go similarity index 85% rename from cmd/cycloid/externalbackends/list.go rename to cmd/externalbackends/list.go index 1cd6e9ae2..17a9c31b1 100644 --- a/cmd/cycloid/externalbackends/list.go +++ b/cmd/externalbackends/list.go @@ -3,8 +3,8 @@ package externalbackends import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" @@ -23,7 +23,7 @@ var ( ) func NewListCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "list", Args: cobra.NoArgs, Example: example, @@ -37,7 +37,7 @@ func NewListCommand() *cobra.Command { func list(cmd *cobra.Command, args []string) error { api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) org, err := cyargs.GetOrg(cmd) if err != nil { diff --git a/cmd/cycloid/externalbackends/update.go b/cmd/externalbackends/update.go similarity index 95% rename from cmd/cycloid/externalbackends/update.go rename to cmd/externalbackends/update.go index c678fea9c..ce17be0be 100644 --- a/cmd/cycloid/externalbackends/update.go +++ b/cmd/externalbackends/update.go @@ -7,7 +7,7 @@ import ( ) func NewUpdateCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "update", Args: cobra.NoArgs, Hidden: true, diff --git a/cmd/cycloid/get.go b/cmd/get.go similarity index 61% rename from cmd/cycloid/get.go rename to cmd/get.go index 4d0d3d3eb..49cc539f0 100644 --- a/cmd/cycloid/get.go +++ b/cmd/get.go @@ -1,9 +1,9 @@ -package cycloid +package cmd import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/uri" + "github.com/cycloidio/cycloid-cli/cmd/uri" ) func NewGetCommand() *cobra.Command { diff --git a/cmd/cycloid/internal/version.go b/cmd/internal/version.go similarity index 100% rename from cmd/cycloid/internal/version.go rename to cmd/internal/version.go diff --git a/cmd/cycloid/kpis/cmd.go b/cmd/kpis/cmd.go similarity index 90% rename from cmd/cycloid/kpis/cmd.go rename to cmd/kpis/cmd.go index c2452ae3a..c85a308f8 100644 --- a/cmd/cycloid/kpis/cmd.go +++ b/cmd/kpis/cmd.go @@ -5,7 +5,7 @@ import ( ) func NewCommands() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "kpi", Aliases: []string{ "kpis", diff --git a/cmd/cycloid/kpis/common.go b/cmd/kpis/common.go similarity index 100% rename from cmd/cycloid/kpis/common.go rename to cmd/kpis/common.go diff --git a/cmd/cycloid/kpis/create.go b/cmd/kpis/create.go similarity index 92% rename from cmd/cycloid/kpis/create.go rename to cmd/kpis/create.go index 09ddda18a..f09819a5b 100644 --- a/cmd/cycloid/kpis/create.go +++ b/cmd/kpis/create.go @@ -3,11 +3,11 @@ package kpis import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" + "github.com/cycloidio/cycloid-cli/cmd/common" ) func NewCreateCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "create", Args: cobra.NoArgs, Short: "create a kpi", @@ -21,7 +21,7 @@ func NewCreateCommand() *cobra.Command { --env environment-name \ --job hello `, - RunE: func(cmd *cobra.Command, args []string) error { panic("Not implemented") }, //create, + RunE: func(cmd *cobra.Command, args []string) error { panic("Not implemented") }, // create, } common.RequiredFlag(WithFlagName, cmd) common.RequiredFlag(WithFlagType, cmd) @@ -37,7 +37,7 @@ func NewCreateCommand() *cobra.Command { // func create(cmd *cobra.Command, args []string) error { // api := common.NewAPI() -// m := middleware.NewMiddleware(api) +// m := apiclient.NewMiddleware(api) // // org, err := cy_args.GetOrg(cmd) // if err != nil { diff --git a/cmd/cycloid/kpis/delete.go b/cmd/kpis/delete.go similarity index 87% rename from cmd/cycloid/kpis/delete.go rename to cmd/kpis/delete.go index 36e9fbcd3..2c28a2dec 100644 --- a/cmd/cycloid/kpis/delete.go +++ b/cmd/kpis/delete.go @@ -3,11 +3,11 @@ package kpis import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" + "github.com/cycloidio/cycloid-cli/cmd/common" ) func NewDeleteCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "delete", Args: cobra.NoArgs, Short: "delete a kpi", @@ -17,7 +17,7 @@ func NewDeleteCommand() *cobra.Command { --canonical kpi `, // RunE: delete, - RunE: func(cmd *cobra.Command, args []string) error { panic("Not implemented") }, //create, + RunE: func(cmd *cobra.Command, args []string) error { panic("Not implemented") }, // create, } common.RequiredFlag(common.WithFlagCan, cmd) @@ -27,7 +27,7 @@ func NewDeleteCommand() *cobra.Command { // func delete(cmd *cobra.Command, args []string) error { // api := common.NewAPI() -// m := middleware.NewMiddleware(api) +// m := apiclient.NewMiddleware(api) // // org, err := cy_args.GetOrg(cmd) // if err != nil { diff --git a/cmd/cycloid/kpis/list.go b/cmd/kpis/list.go similarity index 88% rename from cmd/cycloid/kpis/list.go rename to cmd/kpis/list.go index de5920114..e38ced3c5 100644 --- a/cmd/cycloid/kpis/list.go +++ b/cmd/kpis/list.go @@ -3,11 +3,11 @@ package kpis import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" + "github.com/cycloidio/cycloid-cli/cmd/common" ) func NewListCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "list", Args: cobra.NoArgs, Short: "list kpis", @@ -16,7 +16,7 @@ func NewListCommand() *cobra.Command { cy --org my-org kpi list `, // RunE: list, - RunE: func(cmd *cobra.Command, args []string) error { panic("Not implemented") }, //create, + RunE: func(cmd *cobra.Command, args []string) error { panic("Not implemented") }, // create, } common.WithFlagProject(cmd) @@ -27,7 +27,7 @@ func NewListCommand() *cobra.Command { // func list(cmd *cobra.Command, args []string) error { // api := common.NewAPI() -// m := middleware.NewMiddleware(api) +// m := apiclient.NewMiddleware(api) // // org, err := cy_args.GetOrg(cmd) // if err != nil { diff --git a/cmd/cycloid/login/list.go b/cmd/login/list.go similarity index 100% rename from cmd/cycloid/login/list.go rename to cmd/login/list.go diff --git a/cmd/cycloid/login/login.go b/cmd/login/login.go similarity index 93% rename from cmd/cycloid/login/login.go rename to cmd/login/login.go index 6f82b2ad3..e4acb9485 100644 --- a/cmd/cycloid/login/login.go +++ b/cmd/login/login.go @@ -1,11 +1,12 @@ package login import ( - "github.com/pkg/errors" + "fmt" + "github.com/spf13/cobra" "github.com/spf13/viper" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/internal" + "github.com/cycloidio/cycloid-cli/cmd/internal" "github.com/cycloidio/cycloid-cli/config" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" @@ -41,7 +42,7 @@ func login(cmd *cobra.Command, args []string) error { org, err := cyargs.GetOrg(cmd) if err != nil { - return errors.Wrap(err, "unable to get org flag") + return fmt.Errorf("unable to get org flag: %w", err) } // Get api key via env var or cli flag diff --git a/cmd/cycloid/members/cmd.go b/cmd/members/cmd.go similarity index 95% rename from cmd/cycloid/members/cmd.go rename to cmd/members/cmd.go index adb9940d4..3f772eb34 100644 --- a/cmd/cycloid/members/cmd.go +++ b/cmd/members/cmd.go @@ -14,7 +14,7 @@ func NewCommands() *cobra.Command { long = short ) - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "members", Aliases: []string{"member"}, Example: example, diff --git a/cmd/cycloid/members/delete.go b/cmd/members/delete.go similarity index 88% rename from cmd/cycloid/members/delete.go rename to cmd/members/delete.go index 74bfe04eb..f0129c3fb 100644 --- a/cmd/cycloid/members/delete.go +++ b/cmd/members/delete.go @@ -6,14 +6,14 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" ) func NewDeleteCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "delete [id...]", Aliases: []string{"rm"}, Args: cyargs.RequireArgsOrFlag("id"), @@ -35,7 +35,7 @@ func NewDeleteCommand() *cobra.Command { func deleteMember(cmd *cobra.Command, args []string) error { api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) org, err := cyargs.GetOrg(cmd) if err != nil { diff --git a/cmd/cycloid/members/get.go b/cmd/members/get.go similarity index 89% rename from cmd/cycloid/members/get.go rename to cmd/members/get.go index f3eae6b81..a1e7db6ca 100644 --- a/cmd/cycloid/members/get.go +++ b/cmd/members/get.go @@ -6,15 +6,15 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" + "github.com/cycloidio/cycloid-cli/gen/models" ) func NewGetCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "get [id...]", Args: cyargs.RequireArgsOrFlag("id"), Short: "Get the organization member", @@ -36,7 +36,7 @@ func NewGetCommand() *cobra.Command { func getMember(cmd *cobra.Command, args []string) error { api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) org, err := cyargs.GetOrg(cmd) if err != nil { diff --git a/cmd/cycloid/members/invite.go b/cmd/members/invite.go similarity index 85% rename from cmd/cycloid/members/invite.go rename to cmd/members/invite.go index e2ac93815..4ae10b7f8 100644 --- a/cmd/cycloid/members/invite.go +++ b/cmd/members/invite.go @@ -3,15 +3,15 @@ package members import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" ) func NewInviteCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "invite", Args: cobra.NoArgs, Short: "Invite a user to the organization", @@ -30,7 +30,7 @@ func NewInviteCommand() *cobra.Command { func inviteMember(cmd *cobra.Command, args []string) error { api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) org, err := cyargs.GetOrg(cmd) if err != nil { diff --git a/cmd/cycloid/members/list-invites.go b/cmd/members/list-invites.go similarity index 82% rename from cmd/cycloid/members/list-invites.go rename to cmd/members/list-invites.go index 61b1bd884..177ee0c83 100644 --- a/cmd/cycloid/members/list-invites.go +++ b/cmd/members/list-invites.go @@ -3,8 +3,8 @@ package members import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" @@ -20,7 +20,7 @@ func NewListInvitesCommand() *cobra.Command { long = short ) - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "list-invites", Args: cobra.NoArgs, Example: example, @@ -34,7 +34,7 @@ func NewListInvitesCommand() *cobra.Command { func listInvites(cmd *cobra.Command, args []string) error { api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) org, err := cyargs.GetOrg(cmd) if err != nil { diff --git a/cmd/cycloid/members/list.go b/cmd/members/list.go similarity index 81% rename from cmd/cycloid/members/list.go rename to cmd/members/list.go index c6ec1399b..01aed67df 100644 --- a/cmd/cycloid/members/list.go +++ b/cmd/members/list.go @@ -3,12 +3,12 @@ package members import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" + "github.com/cycloidio/cycloid-cli/gen/models" ) var memberTableOptions = printer.Options{ @@ -26,7 +26,7 @@ func NewListCommand() *cobra.Command { long = short ) - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "list", Args: cobra.NoArgs, Example: example, @@ -40,7 +40,7 @@ func NewListCommand() *cobra.Command { func listMembers(cmd *cobra.Command, args []string) error { api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) org, err := cyargs.GetOrg(cmd) if err != nil { diff --git a/cmd/cycloid/members/update.go b/cmd/members/update.go similarity index 85% rename from cmd/cycloid/members/update.go rename to cmd/members/update.go index 428369c87..ef8477fed 100644 --- a/cmd/cycloid/members/update.go +++ b/cmd/members/update.go @@ -3,15 +3,15 @@ package members import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" ) func NewUpdateCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "update", Args: cobra.NoArgs, Short: "Update a member", @@ -30,7 +30,7 @@ func NewUpdateCommand() *cobra.Command { func updateMember(cmd *cobra.Command, args []string) error { api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) org, err := cyargs.GetOrg(cmd) if err != nil { diff --git a/cmd/cycloid/oidc/cmd.go b/cmd/oidc/cmd.go similarity index 70% rename from cmd/cycloid/oidc/cmd.go rename to cmd/oidc/cmd.go index c4fd5c47b..5695dcb6b 100644 --- a/cmd/cycloid/oidc/cmd.go +++ b/cmd/oidc/cmd.go @@ -3,9 +3,9 @@ package oidc import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/oidc/integration" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/oidc/mappings" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/oidc/settings" + "github.com/cycloidio/cycloid-cli/cmd/oidc/integration" + "github.com/cycloidio/cycloid-cli/cmd/oidc/mappings" + "github.com/cycloidio/cycloid-cli/cmd/oidc/settings" ) // NewCommands returns the top-level `oidc` cobra command. diff --git a/cmd/cycloid/oidc/integration/cmd.go b/cmd/oidc/integration/cmd.go similarity index 100% rename from cmd/cycloid/oidc/integration/cmd.go rename to cmd/oidc/integration/cmd.go diff --git a/cmd/cycloid/oidc/integration/get.go b/cmd/oidc/integration/get.go similarity index 84% rename from cmd/cycloid/oidc/integration/get.go rename to cmd/oidc/integration/get.go index 29b25dd29..3e5d9fb34 100644 --- a/cmd/cycloid/oidc/integration/get.go +++ b/cmd/oidc/integration/get.go @@ -3,8 +3,8 @@ package integration import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" @@ -37,7 +37,7 @@ func NewGetCommand() *cobra.Command { RunE: getIntegration, } - cyout.RegisterModel(cmd, middleware.OIDCIntegration{}) + cyout.RegisterModel(cmd, apiclient.OIDCIntegration{}) return cmd } @@ -48,7 +48,7 @@ func getIntegration(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) result, _, err := m.GetOIDCIntegration(org) return cyout.PrintWithOptions(cmd, result, err, "unable to get OIDC integration", integrationTableOptions) diff --git a/cmd/cycloid/oidc/integration/set.go b/cmd/oidc/integration/set.go similarity index 95% rename from cmd/cycloid/oidc/integration/set.go rename to cmd/oidc/integration/set.go index 72e7c9fee..fdf2a39be 100644 --- a/cmd/cycloid/oidc/integration/set.go +++ b/cmd/oidc/integration/set.go @@ -6,8 +6,8 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" ) @@ -66,7 +66,7 @@ environment variable; the CA certificate via CY_OIDC_CA_CERT.`, cyargs.AddOIDCAllowInsecureDiscoveryFlag(cmd) cyargs.AddOIDCAdoptManualMembersFlag(cmd) - cyout.RegisterModel(cmd, middleware.OIDCIntegration{}) + cyout.RegisterModel(cmd, apiclient.OIDCIntegration{}) return cmd } @@ -139,15 +139,15 @@ func setIntegration(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) // Read-merge-write: fetch current config so we can preserve 'enabled' when // the user does not explicitly pass --enabled. A 404 means the integration // does not exist yet — treat as a fresh create (current == nil). - var current *middleware.OIDCIntegration + var current *apiclient.OIDCIntegration current, _, err = m.GetOIDCIntegration(org) if err != nil { - var apiErr *middleware.APIResponseError + var apiErr *apiclient.APIResponseError if !errors.As(err, &apiErr) || apiErr.StatusCode != http.StatusNotFound { return cyout.Print(cmd, nil, err, "unable to read current OIDC integration") } diff --git a/cmd/cycloid/oidc/mappings/cmd.go b/cmd/oidc/mappings/cmd.go similarity index 100% rename from cmd/cycloid/oidc/mappings/cmd.go rename to cmd/oidc/mappings/cmd.go diff --git a/cmd/cycloid/oidc/mappings/create.go b/cmd/oidc/mappings/create.go similarity index 84% rename from cmd/cycloid/oidc/mappings/create.go rename to cmd/oidc/mappings/create.go index 35fe3bfa2..033630c44 100644 --- a/cmd/cycloid/oidc/mappings/create.go +++ b/cmd/oidc/mappings/create.go @@ -3,8 +3,8 @@ package mappings import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" ) @@ -25,7 +25,7 @@ func NewCreateCommand() *cobra.Command { cmd.MarkFlagRequired(cyargs.AddOIDCGroupNameFlag(cmd)) cmd.MarkFlagRequired(cyargs.AddTeamFlag(cmd)) - cyout.RegisterModel(cmd, middleware.OIDCGroupMapping{}) + cyout.RegisterModel(cmd, apiclient.OIDCGroupMapping{}) return cmd } @@ -46,7 +46,7 @@ func createMapping(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) result, _, err := m.CreateOIDCGroupMapping(org, groupName, team) return cyout.PrintWithOptions(cmd, result, err, "unable to create OIDC group mapping", mappingTableOptions) diff --git a/cmd/cycloid/oidc/mappings/delete.go b/cmd/oidc/mappings/delete.go similarity index 86% rename from cmd/cycloid/oidc/mappings/delete.go rename to cmd/oidc/mappings/delete.go index 28e4bab86..0f25ffd16 100644 --- a/cmd/cycloid/oidc/mappings/delete.go +++ b/cmd/oidc/mappings/delete.go @@ -3,8 +3,8 @@ package mappings import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" ) @@ -39,7 +39,7 @@ func deleteMapping(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) _, err = m.DeleteOIDCGroupMapping(org, id) return cyout.Print(cmd, nil, err, "unable to delete OIDC group mapping") diff --git a/cmd/cycloid/oidc/mappings/list.go b/cmd/oidc/mappings/list.go similarity index 82% rename from cmd/cycloid/oidc/mappings/list.go rename to cmd/oidc/mappings/list.go index 0019ca9ca..70668c9ae 100644 --- a/cmd/cycloid/oidc/mappings/list.go +++ b/cmd/oidc/mappings/list.go @@ -3,8 +3,8 @@ package mappings import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" @@ -28,7 +28,7 @@ func NewListCommand() *cobra.Command { RunE: listMappings, } - cyout.RegisterModel(cmd, middleware.OIDCGroupMapping{}) + cyout.RegisterModel(cmd, apiclient.OIDCGroupMapping{}) return cmd } @@ -39,7 +39,7 @@ func listMappings(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) result, _, err := m.ListOIDCGroupMappings(org) return cyout.PrintWithOptions(cmd, result, err, "unable to list OIDC group mappings", mappingTableOptions) diff --git a/cmd/cycloid/oidc/settings/cmd.go b/cmd/oidc/settings/cmd.go similarity index 100% rename from cmd/cycloid/oidc/settings/cmd.go rename to cmd/oidc/settings/cmd.go diff --git a/cmd/cycloid/oidc/settings/get.go b/cmd/oidc/settings/get.go similarity index 81% rename from cmd/cycloid/oidc/settings/get.go rename to cmd/oidc/settings/get.go index ef23cb0db..3667fb99f 100644 --- a/cmd/cycloid/oidc/settings/get.go +++ b/cmd/oidc/settings/get.go @@ -3,8 +3,8 @@ package settings import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" @@ -27,7 +27,7 @@ func NewGetCommand() *cobra.Command { RunE: getSettings, } - cyout.RegisterModel(cmd, middleware.OIDCOrganizationSettings{}) + cyout.RegisterModel(cmd, apiclient.OIDCOrganizationSettings{}) return cmd } @@ -38,7 +38,7 @@ func getSettings(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) result, _, err := m.GetOIDCOrganizationSettings(org) return cyout.PrintWithOptions(cmd, result, err, "unable to get OIDC organization settings", settingsTableOptions) diff --git a/cmd/cycloid/oidc/settings/set.go b/cmd/oidc/settings/set.go similarity index 90% rename from cmd/cycloid/oidc/settings/set.go rename to cmd/oidc/settings/set.go index 64c905a43..4853cd419 100644 --- a/cmd/cycloid/oidc/settings/set.go +++ b/cmd/oidc/settings/set.go @@ -6,8 +6,8 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" ) @@ -37,7 +37,7 @@ the API returns HTTP 422 otherwise.`, cyargs.AddOIDCNoMatchPolicyFlag(cmd) cyargs.AddOIDCDefaultRoleFlag(cmd) - cyout.RegisterModel(cmd, middleware.OIDCOrganizationSettings{}) + cyout.RegisterModel(cmd, apiclient.OIDCOrganizationSettings{}) return cmd } @@ -63,7 +63,7 @@ func setSettings(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) // The settings endpoint is a full-replace PUT. Read the current settings and // override only the flags the user explicitly set, so an unspecified flag @@ -71,12 +71,12 @@ func setSettings(cmd *cobra.Command, args []string) error { // from defaults. // Default for fresh-create (404 on read). Must stay in sync with the // server-side default in the OIDC organization settings endpoint. - merged := middleware.UpdateOIDCOrganizationSettings{ + merged := apiclient.UpdateOIDCOrganizationSettings{ OIDCNoMatchPolicy: "keep_membership", } current, _, err := m.GetOIDCOrganizationSettings(org) if err != nil { - var apiErr *middleware.APIResponseError + var apiErr *apiclient.APIResponseError if !errors.As(err, &apiErr) || apiErr.StatusCode != http.StatusNotFound { return cyout.Print(cmd, nil, err, "unable to read current OIDC organization settings") } diff --git a/cmd/cycloid/organizations/cmd.go b/cmd/organizations/cmd.go similarity index 83% rename from cmd/cycloid/organizations/cmd.go rename to cmd/organizations/cmd.go index 4e76931bc..5fad20147 100644 --- a/cmd/cycloid/organizations/cmd.go +++ b/cmd/organizations/cmd.go @@ -3,11 +3,11 @@ package organizations import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/organizations/licence" + "github.com/cycloidio/cycloid-cli/cmd/organizations/licence" ) func NewCommands() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "organization", Aliases: []string{ "org", diff --git a/cmd/cycloid/organizations/create.go b/cmd/organizations/create.go similarity index 90% rename from cmd/cycloid/organizations/create.go rename to cmd/organizations/create.go index 027202f42..9b6e1548a 100644 --- a/cmd/cycloid/organizations/create.go +++ b/cmd/organizations/create.go @@ -7,18 +7,18 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" + "github.com/cycloidio/cycloid-cli/gen/models" ) // This command have been Hidden because it is not compatible with API key login. // Advanced user still can use it passing a user token in CY_API_KEY env var during a login. func NewCreateCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "create", Args: cobra.NoArgs, Short: "create an organization", @@ -65,12 +65,12 @@ func create(cmd *cobra.Command, args []string) error { canonical := common.GenerateCanonical(name) api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) _, _, getErr := m.GetOrganization(canonical) exists := getErr == nil if getErr != nil { - var apiErr *middleware.APIResponseError + var apiErr *apiclient.APIResponseError if !stderrors.As(getErr, &apiErr) || apiErr.StatusCode != http.StatusNotFound { return cyout.PrintWithOptions(cmd, nil, getErr, "failed to check if organization exists", printer.Options{}) } diff --git a/cmd/cycloid/organizations/create_children.go b/cmd/organizations/create_children.go similarity index 85% rename from cmd/cycloid/organizations/create_children.go rename to cmd/organizations/create_children.go index 7e848c2db..fb28e7403 100644 --- a/cmd/cycloid/organizations/create_children.go +++ b/cmd/organizations/create_children.go @@ -3,15 +3,15 @@ package organizations import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" ) func NewCreateChildCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "create-child", Args: cobra.NoArgs, Short: "create a child organization", @@ -28,7 +28,7 @@ func NewCreateChildCommand() *cobra.Command { func createChild(cmd *cobra.Command, args []string) error { api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) org, err := cyargs.GetOrg(cmd) if err != nil { diff --git a/cmd/cycloid/organizations/delete.go b/cmd/organizations/delete.go similarity index 85% rename from cmd/cycloid/organizations/delete.go rename to cmd/organizations/delete.go index 3f4fd817c..cff807528 100644 --- a/cmd/cycloid/organizations/delete.go +++ b/cmd/organizations/delete.go @@ -3,14 +3,14 @@ package organizations import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" ) func NewDeleteCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "delete [canonical...]", Args: cobra.ArbitraryArgs, Short: "delete an organization (require root API_KEY)", @@ -30,7 +30,7 @@ func NewDeleteCommand() *cobra.Command { func del(cmd *cobra.Command, args []string) error { api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) var orgs []string if len(args) > 0 { diff --git a/cmd/cycloid/organizations/get.go b/cmd/organizations/get.go similarity index 86% rename from cmd/cycloid/organizations/get.go rename to cmd/organizations/get.go index 11c3eb09e..e448cb1c3 100644 --- a/cmd/cycloid/organizations/get.go +++ b/cmd/organizations/get.go @@ -3,12 +3,12 @@ package organizations import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" + "github.com/cycloidio/cycloid-cli/gen/models" ) var orgTableOptions = printer.Options{ @@ -17,7 +17,7 @@ var orgTableOptions = printer.Options{ } func NewGetCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "get [canonical...]", Args: cobra.ArbitraryArgs, Short: "get an organization", @@ -37,7 +37,7 @@ func NewGetCommand() *cobra.Command { func get(cmd *cobra.Command, args []string) error { api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) // Multi-arg if len(args) > 1 { diff --git a/cmd/cycloid/organizations/licence/activate.go b/cmd/organizations/licence/activate.go similarity index 89% rename from cmd/cycloid/organizations/licence/activate.go rename to cmd/organizations/licence/activate.go index 2d1b19b04..9048c6fef 100644 --- a/cmd/cycloid/organizations/licence/activate.go +++ b/cmd/organizations/licence/activate.go @@ -3,8 +3,8 @@ package licence import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" @@ -46,7 +46,7 @@ func activate(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) _, err = m.ActivateLicence(org, key) return cyout.PrintWithOptions(cmd, nil, err, "failed to activate licence", printer.Options{}) diff --git a/cmd/cycloid/organizations/licence/cmd.go b/cmd/organizations/licence/cmd.go similarity index 100% rename from cmd/cycloid/organizations/licence/cmd.go rename to cmd/organizations/licence/cmd.go diff --git a/cmd/cycloid/organizations/licence/get.go b/cmd/organizations/licence/get.go similarity index 82% rename from cmd/cycloid/organizations/licence/get.go rename to cmd/organizations/licence/get.go index 99a5248db..a1a6b3ec7 100644 --- a/cmd/cycloid/organizations/licence/get.go +++ b/cmd/organizations/licence/get.go @@ -3,12 +3,12 @@ package licence import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" + "github.com/cycloidio/cycloid-cli/gen/models" ) var licenceTableOptions = printer.Options{ @@ -36,7 +36,7 @@ func get(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) licence, _, err := m.GetLicence(org) return cyout.PrintWithOptions(cmd, licence, err, "failed to get licence", licenceTableOptions) diff --git a/cmd/cycloid/organizations/list-children.go b/cmd/organizations/list-children.go similarity index 80% rename from cmd/cycloid/organizations/list-children.go rename to cmd/organizations/list-children.go index 3c15f6c7c..a02abceab 100644 --- a/cmd/cycloid/organizations/list-children.go +++ b/cmd/organizations/list-children.go @@ -3,15 +3,15 @@ package organizations import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" ) func NewListChildrensCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "list-children", Args: cobra.NoArgs, Aliases: []string{ @@ -26,7 +26,7 @@ func NewListChildrensCommand() *cobra.Command { func listChildrens(cmd *cobra.Command, args []string) error { api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) org, err := cyargs.GetOrg(cmd) if err != nil { diff --git a/cmd/cycloid/organizations/list-workers.go b/cmd/organizations/list-workers.go similarity index 79% rename from cmd/cycloid/organizations/list-workers.go rename to cmd/organizations/list-workers.go index b555a45d0..c86511fbf 100644 --- a/cmd/cycloid/organizations/list-workers.go +++ b/cmd/organizations/list-workers.go @@ -3,15 +3,15 @@ package organizations import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" ) func NewListWorkersCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "list-workers", Args: cobra.NoArgs, Short: "list the organization workers", @@ -23,7 +23,7 @@ func NewListWorkersCommand() *cobra.Command { func listWorkers(cmd *cobra.Command, args []string) error { api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) org, err := cyargs.GetOrg(cmd) if err != nil { diff --git a/cmd/cycloid/organizations/list.go b/cmd/organizations/list.go similarity index 72% rename from cmd/cycloid/organizations/list.go rename to cmd/organizations/list.go index a34cce297..15ddda46c 100644 --- a/cmd/cycloid/organizations/list.go +++ b/cmd/organizations/list.go @@ -3,14 +3,14 @@ package organizations import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyout" + "github.com/cycloidio/cycloid-cli/gen/models" ) func NewListCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "list", Args: cobra.NoArgs, Short: "list the organizations", @@ -23,12 +23,11 @@ func NewListCommand() *cobra.Command { } cyout.RegisterModel(cmd, models.Organization{}) return cmd - } func list(cmd *cobra.Command, args []string) error { api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) orgs, _, err := m.ListOrganizations() return cyout.PrintWithOptions(cmd, orgs, err, "unable to list organizations", orgTableOptions) diff --git a/cmd/cycloid/organizations/subscription.go b/cmd/organizations/subscription.go similarity index 100% rename from cmd/cycloid/organizations/subscription.go rename to cmd/organizations/subscription.go diff --git a/cmd/cycloid/organizations/subscription_create_or_update.go b/cmd/organizations/subscription_create_or_update.go similarity index 86% rename from cmd/cycloid/organizations/subscription_create_or_update.go rename to cmd/organizations/subscription_create_or_update.go index 021ecfa7c..6618c2b88 100644 --- a/cmd/cycloid/organizations/subscription_create_or_update.go +++ b/cmd/organizations/subscription_create_or_update.go @@ -7,8 +7,8 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" @@ -29,10 +29,10 @@ func NewCreateOrUpdateSubscriptionCommand() *cobra.Command { defaultDate := time.Now().AddDate(0, 3, 0) cmd.Flags().TimeP("expires-at", "t", defaultDate, []string{time.RFC3339}, "Add an expiration time for the subscription, default in three month ("+defaultDate.Format(time.RFC3339)+")") cmd.MarkFlagRequired("expire-at") - cmd.Flags().StringP("plan", "p", middleware.PlatformTeam, "Select a plan, default to `platform_teams`") + cmd.Flags().StringP("plan", "p", apiclient.PlatformTeam, "Select a plan, default to `platform_teams`") cmd.RegisterFlagCompletionFunc("plan", func(cmd *cobra.Command, args []string, toComplete string) ([]cobra.Completion, cobra.ShellCompDirective) { - var completions = []cobra.Completion{} - for _, p := range middleware.AvailableSubscriptionPlans { + completions := []cobra.Completion{} + for _, p := range apiclient.AvailableSubscriptionPlans { if strings.HasPrefix(p, toComplete) { completions = append(completions, p) } @@ -74,7 +74,7 @@ func createOrUpdateSubscription(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) subscription, _, err := m.CreateOrUpdateSubscription(org, plan, expiresAt, memberCount, update) if err != nil { diff --git a/cmd/cycloid/organizations/update.go b/cmd/organizations/update.go similarity index 80% rename from cmd/cycloid/organizations/update.go rename to cmd/organizations/update.go index 2f453f1da..8a452cd0d 100644 --- a/cmd/cycloid/organizations/update.go +++ b/cmd/organizations/update.go @@ -1,11 +1,12 @@ package organizations import ( - "github.com/pkg/errors" + "fmt" + "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" @@ -14,7 +15,7 @@ import ( // This command have been Hidden because it is not compatible with API key login. // Advanced user still can use it passing a user token in CY_API_KEY env var during a login. func NewUpdateCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "update", Args: cobra.NoArgs, Short: "update an organization", @@ -32,7 +33,7 @@ func NewUpdateCommand() *cobra.Command { func update(cmd *cobra.Command, args []string) error { api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) name, err := cyargs.GetOrgName(cmd) if err != nil { @@ -41,7 +42,7 @@ func update(cmd *cobra.Command, args []string) error { org, err := cyargs.GetOrg(cmd) if err != nil { - return errors.Wrap(err, "unable get org flag") + return fmt.Errorf("unable get org flag: %w", err) } o, _, err := m.UpdateOrganization(org, name) diff --git a/cmd/cycloid/output/cmd.go b/cmd/output/cmd.go similarity index 100% rename from cmd/cycloid/output/cmd.go rename to cmd/output/cmd.go diff --git a/cmd/cycloid/pipelines/build_cmd.go b/cmd/pipelines/build_cmd.go similarity index 95% rename from cmd/cycloid/pipelines/build_cmd.go rename to cmd/pipelines/build_cmd.go index 0064561d8..668c19692 100644 --- a/cmd/cycloid/pipelines/build_cmd.go +++ b/cmd/pipelines/build_cmd.go @@ -7,7 +7,7 @@ import ( ) func NewBuildsCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "builds", Aliases: []string{ "b", diff --git a/cmd/cycloid/pipelines/build_get.go b/cmd/pipelines/build_get.go similarity index 84% rename from cmd/cycloid/pipelines/build_get.go rename to cmd/pipelines/build_get.go index eeaa75540..03f7b5c15 100644 --- a/cmd/cycloid/pipelines/build_get.go +++ b/cmd/pipelines/build_get.go @@ -5,15 +5,15 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" + "github.com/cycloidio/cycloid-cli/gen/models" ) func NewBuildGetCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "get", Short: "Get a build information.", RunE: getBuild, @@ -50,7 +50,7 @@ func getBuild(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) build, _, err := m.GetBuild(org, project, env, component, pipeline, job, buildID) errMsg := fmt.Sprintf("failed to fetch build with ID '%s', in pipeline '%s' of project '%s', env '%s', component '%s'", diff --git a/cmd/cycloid/pipelines/build_list.go b/cmd/pipelines/build_list.go similarity index 84% rename from cmd/cycloid/pipelines/build_list.go rename to cmd/pipelines/build_list.go index d902aa65d..d8eb0949d 100644 --- a/cmd/cycloid/pipelines/build_list.go +++ b/cmd/pipelines/build_list.go @@ -5,15 +5,15 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" + "github.com/cycloidio/cycloid-cli/gen/models" ) func NewBuildListCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "list", Short: "list builds of a pipeline", Example: `cy --org my-org pp list-builds --project my-project --env env --component component --job my-job`, @@ -44,7 +44,7 @@ func listBuilds(cmd *cobra.Command, args []string) error { job, _ := cyargs.GetPipelineJob(cmd) api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) builds, _, err := m.GetBuilds(org, project, env, component, pipeline, job) errMsg := fmt.Sprintf("failed to get builds of pipeline '%s', in project '%s', in env '%s', in component '%s'", diff --git a/cmd/cycloid/pipelines/build_logs.go b/cmd/pipelines/build_logs.go similarity index 89% rename from cmd/cycloid/pipelines/build_logs.go rename to cmd/pipelines/build_logs.go index 1fb405ac0..02a9a2bb1 100644 --- a/cmd/cycloid/pipelines/build_logs.go +++ b/cmd/pipelines/build_logs.go @@ -2,14 +2,14 @@ package pipelines import ( "context" + "fmt" "strings" - "github.com/pkg/errors" "github.com/spf13/cobra" "github.com/spf13/viper" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/buildwatch" "github.com/cycloidio/cycloid-cli/internal/cyargs" ) @@ -61,16 +61,16 @@ func streamBuildLogs(cmd *cobra.Command, args []string) error { output, err := cyargs.GetOutput(cmd) if err != nil { - return errors.Wrap(err, "unable to get output flag") + return fmt.Errorf("unable to get output flag: %w", err) } watch, err := cmd.Flags().GetBool("watch") if err != nil { - return errors.Wrap(err, "unable to get --watch flag") + return fmt.Errorf("unable to get --watch flag: %w", err) } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) outMode := buildwatch.OutputHuman if strings.EqualFold(output, "json") { diff --git a/cmd/cycloid/pipelines/build_trigger.go b/cmd/pipelines/build_trigger.go similarity index 84% rename from cmd/cycloid/pipelines/build_trigger.go rename to cmd/pipelines/build_trigger.go index 1e4ee43cb..823d682e8 100644 --- a/cmd/cycloid/pipelines/build_trigger.go +++ b/cmd/pipelines/build_trigger.go @@ -7,19 +7,18 @@ import ( "strings" "time" - "github.com/pkg/errors" "github.com/spf13/cobra" "github.com/spf13/viper" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/buildwatch" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" ) func NewBuildCreateCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "trigger", Aliases: []string{ "create", @@ -58,37 +57,37 @@ func createBuild(cmd *cobra.Command, args []string) error { output, err := cyargs.GetOutput(cmd) if err != nil { - return errors.Wrap(err, "unable to get output flag") + return fmt.Errorf("unable to get output flag: %w", err) } watch, err := cmd.Flags().GetBool("watch") if err != nil { - return errors.Wrap(err, "unable to get watch flag") + return fmt.Errorf("unable to get watch flag: %w", err) } timeoutSeconds, err := cmd.Flags().GetInt("timeout") if err != nil { - return errors.Wrap(err, "unable to get timeout flag") + return fmt.Errorf("unable to get timeout flag: %w", err) } cancelOnTimeout, err := cmd.Flags().GetBool("watch-cancel-on-timeout") if err != nil { - return errors.Wrap(err, "unable to get watch-cancel-on-timeout flag") + return fmt.Errorf("unable to get watch-cancel-on-timeout flag: %w", err) } if timeoutSeconds < 0 { - return errors.New("--timeout must be greater than or equal to 0") + return fmt.Errorf("--timeout must be greater than or equal to 0") } if !watch && timeoutSeconds > 0 { - return errors.New("--timeout can only be used with --watch") + return fmt.Errorf("--timeout can only be used with --watch") } if !watch && cancelOnTimeout { - return errors.New("--watch-cancel-on-timeout can only be used with --watch") + return fmt.Errorf("--watch-cancel-on-timeout can only be used with --watch") } if watch && cancelOnTimeout && timeoutSeconds == 0 { - return errors.New("--watch-cancel-on-timeout requires --timeout to be set") + return fmt.Errorf("--watch-cancel-on-timeout requires --timeout to be set") } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) build, _, err := m.CreateBuild(org, project, env, component, pipeline, job) if err != nil { @@ -97,7 +96,7 @@ func createBuild(cmd *cobra.Command, args []string) error { if watch { if build == nil || build.ID == nil { - return errors.New("triggered build payload is missing id") + return fmt.Errorf("triggered build payload is missing id") } // Human vs raw watch stream: docs/pipeline-build-watch-output.md (quick rollback: force OutputRaw). diff --git a/cmd/cycloid/pipelines/jobs_cmd.go b/cmd/pipelines/jobs_cmd.go similarity index 96% rename from cmd/cycloid/pipelines/jobs_cmd.go rename to cmd/pipelines/jobs_cmd.go index 7bf5b5270..c8e7c8b16 100644 --- a/cmd/cycloid/pipelines/jobs_cmd.go +++ b/cmd/pipelines/jobs_cmd.go @@ -5,8 +5,8 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" "github.com/cycloidio/cycloid-cli/printer" + "github.com/cycloidio/cycloid-cli/gen/models" ) func NewJobsCommand() *cobra.Command { diff --git a/cmd/cycloid/pipelines/jobs_get.go b/cmd/pipelines/jobs_get.go similarity index 82% rename from cmd/cycloid/pipelines/jobs_get.go rename to cmd/pipelines/jobs_get.go index 5d181bcd8..bb8545ee7 100644 --- a/cmd/cycloid/pipelines/jobs_get.go +++ b/cmd/pipelines/jobs_get.go @@ -3,15 +3,15 @@ package pipelines import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" + "github.com/cycloidio/cycloid-cli/gen/models" ) func NewJobsGetCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "get", Short: "get a pipeline's job", Example: `cy --org my-org pp job get --project my-project --env env --component component --pipeline pipeline --job my-job -o json`, @@ -28,7 +28,7 @@ func NewJobsGetCommand() *cobra.Command { func getJob(cmd *cobra.Command, args []string) error { api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) org, project, env, component, err := cyargs.GetCyContext(cmd) if err != nil { diff --git a/cmd/cycloid/pipelines/jobs_list.go b/cmd/pipelines/jobs_list.go similarity index 81% rename from cmd/cycloid/pipelines/jobs_list.go rename to cmd/pipelines/jobs_list.go index ac6a7d9a5..23093a795 100644 --- a/cmd/cycloid/pipelines/jobs_list.go +++ b/cmd/pipelines/jobs_list.go @@ -5,15 +5,15 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" + "github.com/cycloidio/cycloid-cli/gen/models" ) func NewJobsListCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "list", Short: "list a pipeline's jobs", Example: `cy --org my-org pp job list --project my-project --env env --component component --pipeline pipeline -o json`, @@ -39,7 +39,7 @@ func listJobs(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) jobs, _, err := m.GetJobs(org, project, env, component, pipeline) errMsg := fmt.Sprintf("failed to fetch jobs for pipeline %q", pipeline) diff --git a/cmd/cycloid/pipelines/jobs_logs.go b/cmd/pipelines/jobs_logs.go similarity index 90% rename from cmd/cycloid/pipelines/jobs_logs.go rename to cmd/pipelines/jobs_logs.go index abcfabc59..157444510 100644 --- a/cmd/cycloid/pipelines/jobs_logs.go +++ b/cmd/pipelines/jobs_logs.go @@ -2,17 +2,17 @@ package pipelines import ( "context" + "errors" "fmt" "sort" "strings" "time" - "github.com/pkg/errors" "github.com/spf13/cobra" "github.com/spf13/viper" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/buildwatch" "github.com/cycloidio/cycloid-cli/internal/cyargs" ) @@ -64,24 +64,24 @@ func streamJobLogs(cmd *cobra.Command, args []string) error { output, err := cyargs.GetOutput(cmd) if err != nil { - return errors.Wrap(err, "unable to get output flag") + return fmt.Errorf("unable to get output flag: %w", err) } watch, err := cmd.Flags().GetBool("watch") if err != nil { - return errors.Wrap(err, "unable to get --watch flag") + return fmt.Errorf("unable to get --watch flag: %w", err) } pollInterval, err := cmd.Flags().GetDuration("poll-interval") if err != nil { - return errors.Wrap(err, "unable to get --poll-interval flag") + return fmt.Errorf("unable to get --poll-interval flag: %w", err) } if pollInterval <= 0 { - return errors.New("--poll-interval must be a positive duration") + return fmt.Errorf("--poll-interval must be a positive duration") } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) outMode := buildwatch.OutputHuman if strings.EqualFold(output, "json") { @@ -156,7 +156,7 @@ func streamJobLogs(cmd *cobra.Command, args []string) error { // latestBuildID lists builds for the job and returns the ID of the most recent // one (highest numeric build ID). Returns "" if no builds exist. -func latestBuildID(m middleware.Middleware, org, project, env, component, pipeline, job string) (string, error) { +func latestBuildID(m apiclient.Middleware, org, project, env, component, pipeline, job string) (string, error) { builds, _, err := m.GetBuilds(org, project, env, component, pipeline, job) if err != nil { return "", fmt.Errorf("listing builds for job %q: %w", job, err) @@ -186,7 +186,7 @@ func latestBuildID(m middleware.Middleware, org, project, env, component, pipeli // appears. It returns the new build ID. func pollForNewBuild( ctx context.Context, - m middleware.Middleware, + m apiclient.Middleware, org, project, env, component, pipeline, job, lastBuildID string, interval time.Duration, statusWriter interface{ Write([]byte) (int, error) }, diff --git a/cmd/cycloid/pipelines/jobs_pause.go b/cmd/pipelines/jobs_pause.go similarity index 85% rename from cmd/cycloid/pipelines/jobs_pause.go rename to cmd/pipelines/jobs_pause.go index e1b256e1b..65b4cf17c 100644 --- a/cmd/cycloid/pipelines/jobs_pause.go +++ b/cmd/pipelines/jobs_pause.go @@ -3,15 +3,15 @@ package pipelines import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" ) func NewJobsPauseCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "pause", Short: "pause a pipeline job", Example: `cy pp job pause --project my-project --env env --component component --pipeline pipeline --job my-job`, @@ -27,7 +27,7 @@ func NewJobsPauseCommand() *cobra.Command { func pauseJob(cmd *cobra.Command, args []string) error { api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) org, project, env, component, err := cyargs.GetCyContext(cmd) if err != nil { diff --git a/cmd/cycloid/pipelines/jobs_unpause.go b/cmd/pipelines/jobs_unpause.go similarity index 85% rename from cmd/cycloid/pipelines/jobs_unpause.go rename to cmd/pipelines/jobs_unpause.go index c4bdceb04..5fdcae4e4 100644 --- a/cmd/cycloid/pipelines/jobs_unpause.go +++ b/cmd/pipelines/jobs_unpause.go @@ -3,15 +3,15 @@ package pipelines import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" ) func NewJobsUnpauseCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "unpause", Short: "unpause a pipeline job", RunE: unpauseJob, @@ -27,7 +27,7 @@ func NewJobsUnpauseCommand() *cobra.Command { func unpauseJob(cmd *cobra.Command, args []string) error { api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) org, project, env, component, err := cyargs.GetCyContext(cmd) if err != nil { diff --git a/cmd/cycloid/pipelines/pipeline_clear_task_cache.go b/cmd/pipelines/pipeline_clear_task_cache.go similarity index 87% rename from cmd/cycloid/pipelines/pipeline_clear_task_cache.go rename to cmd/pipelines/pipeline_clear_task_cache.go index 604e79dc9..9213b00fc 100644 --- a/cmd/cycloid/pipelines/pipeline_clear_task_cache.go +++ b/cmd/pipelines/pipeline_clear_task_cache.go @@ -3,15 +3,15 @@ package pipelines import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" ) func NewPipelineClearTaskCacheCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "clear-task-cache", Short: "clear cache for a task", Example: `cy pp clear-task-cache --project my-project --job my-job --env my-env --step my-task`, @@ -48,7 +48,7 @@ func cleartaskCache(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) out, _, err := m.ClearTaskCache(org, project, env, component, pipeline, job, step) return cyout.PrintWithOptions(cmd, out, err, "unable to clear task cache", printer.Options{}) diff --git a/cmd/cycloid/pipelines/pipeline_cmd.go b/cmd/pipelines/pipeline_cmd.go similarity index 95% rename from cmd/cycloid/pipelines/pipeline_cmd.go rename to cmd/pipelines/pipeline_cmd.go index 9aec5831d..7aeeed94b 100644 --- a/cmd/cycloid/pipelines/pipeline_cmd.go +++ b/cmd/pipelines/pipeline_cmd.go @@ -5,12 +5,12 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" "github.com/cycloidio/cycloid-cli/printer" + "github.com/cycloidio/cycloid-cli/gen/models" ) func NewCommands() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "pipeline", Aliases: []string{ "pp", diff --git a/cmd/cycloid/pipelines/pipeline_diff.go b/cmd/pipelines/pipeline_diff.go similarity index 89% rename from cmd/cycloid/pipelines/pipeline_diff.go rename to cmd/pipelines/pipeline_diff.go index 672a810ca..aed2021e4 100644 --- a/cmd/cycloid/pipelines/pipeline_diff.go +++ b/cmd/pipelines/pipeline_diff.go @@ -6,15 +6,15 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" ) func NewPipelineDiffCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "diff", Short: "diff the remote pipeline with a local config", RunE: diff, @@ -60,7 +60,7 @@ func diff(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) pipelineDiff, _, err := m.DiffPipeline(org, project, env, component, pipeline, string(rawPipeline), string(rawVars), false) return cyout.PrintWithOptions(cmd, pipelineDiff, err, "failed to get pipeline diff", printer.Options{}) diff --git a/cmd/cycloid/pipelines/pipeline_get.go b/cmd/pipelines/pipeline_get.go similarity index 82% rename from cmd/cycloid/pipelines/pipeline_get.go rename to cmd/pipelines/pipeline_get.go index 005e8e68d..a2f79e9e0 100644 --- a/cmd/cycloid/pipelines/pipeline_get.go +++ b/cmd/pipelines/pipeline_get.go @@ -5,15 +5,15 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" + "github.com/cycloidio/cycloid-cli/gen/models" ) func NewPipelineGetCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "get", Short: "get a pipeline", Example: `cy pipeline get --project my-project --env env --component component --pipeline pipeline_name`, @@ -39,7 +39,7 @@ func getPipeline(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) outPipeline, _, err := m.GetPipeline(org, project, env, component, pipeline) errMsg := fmt.Sprintf("failed to get pipeline %q in context project %q, env %q, component %q", pipeline, project, env, component) diff --git a/cmd/cycloid/pipelines/pipeline_last_used.go b/cmd/pipelines/pipeline_last_used.go similarity index 82% rename from cmd/cycloid/pipelines/pipeline_last_used.go rename to cmd/pipelines/pipeline_last_used.go index 86ed86c02..a05ef34b2 100644 --- a/cmd/cycloid/pipelines/pipeline_last_used.go +++ b/cmd/pipelines/pipeline_last_used.go @@ -1,22 +1,22 @@ package pipelines import ( + "fmt" "slices" "time" - "github.com/pkg/errors" "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" + "github.com/cycloidio/cycloid-cli/gen/models" ) func NewPipelineLastUsedCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "last-used", Short: "output the last trigger date of all pipelines in the selected organization.", Example: `cy pipelines last-used --since-days 10`, @@ -43,7 +43,7 @@ type LastUsed struct { func lastUsed(cmd *cobra.Command, args []string) error { api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) org, err := cyargs.GetOrg(cmd) if err != nil { @@ -54,7 +54,7 @@ func lastUsed(cmd *cobra.Command, args []string) error { return err } - var result = []LastUsedPipeline{} + result := []LastUsedPipeline{} maxTimestamp := uint64(0) pps, _, err := m.GetOrgPipelines(org, nil, nil, nil, nil) if err != nil { @@ -79,19 +79,19 @@ func lastUsed(cmd *cobra.Command, args []string) error { }) if pipeline.Name == nil { - return errors.Errorf("Missing pipeline name in:\n%v", pipeline) + return fmt.Errorf("missing pipeline name in:\n%v", pipeline) } if pipeline.Project == nil { - return errors.Errorf("Missing pipeline project in:\n%v", pipeline) + return fmt.Errorf("missing pipeline project in:\n%v", pipeline) } if pipeline.Environment == nil { - return errors.Errorf("Missing pipeline environment in:\n%v", pipeline) + return fmt.Errorf("missing pipeline environment in:\n%v", pipeline) } if pipeline.Component == nil { - return errors.Errorf("Missing pipeline component in:\n%v", pipeline) + return fmt.Errorf("missing pipeline component in:\n%v", pipeline) } lastUsedTimestamp := maxTimestamp diff --git a/cmd/cycloid/pipelines/pipeline_list.go b/cmd/pipelines/pipeline_list.go similarity index 81% rename from cmd/cycloid/pipelines/pipeline_list.go rename to cmd/pipelines/pipeline_list.go index ab3e14f7e..abdd8287a 100644 --- a/cmd/cycloid/pipelines/pipeline_list.go +++ b/cmd/pipelines/pipeline_list.go @@ -3,15 +3,15 @@ package pipelines import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" + "github.com/cycloidio/cycloid-cli/gen/models" ) func NewPipelineListCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "list", Short: "list all pipelines of the organization", Args: cobra.NoArgs, @@ -39,7 +39,7 @@ func list(cmd *cobra.Command, args []string) error { pipelineName, _ := cyargs.GetPipeline(cmd) api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) pps, _, err := m.GetOrgPipelines(org, &pipelineName, &project, &env, statuses) return cyout.PrintWithOptions(cmd, pps, err, "unable to list pipelines", pipelineTableOptions) diff --git a/cmd/cycloid/pipelines/pipeline_pause.go b/cmd/pipelines/pipeline_pause.go similarity index 84% rename from cmd/cycloid/pipelines/pipeline_pause.go rename to cmd/pipelines/pipeline_pause.go index 276527e0b..3508e8274 100644 --- a/cmd/cycloid/pipelines/pipeline_pause.go +++ b/cmd/pipelines/pipeline_pause.go @@ -3,15 +3,15 @@ package pipelines import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" ) func NewPipelinePauseCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "pause", Short: "pause a pipeline", Example: `cy --org my-org pipeline pause --project my-project --env env --component component --pipeline pipeline-name`, @@ -36,7 +36,7 @@ func pause(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) _, err = m.PausePipeline(org, project, env, component, pipeline) return cyout.PrintWithOptions(cmd, nil, err, "failed to pause pipeline", printer.Options{}) diff --git a/cmd/cycloid/pipelines/pipeline_synced.go b/cmd/pipelines/pipeline_synced.go similarity index 84% rename from cmd/cycloid/pipelines/pipeline_synced.go rename to cmd/pipelines/pipeline_synced.go index 3d348069d..6f7bd6288 100644 --- a/cmd/cycloid/pipelines/pipeline_synced.go +++ b/cmd/pipelines/pipeline_synced.go @@ -3,15 +3,15 @@ package pipelines import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" ) func NewPipelineSyncedCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "synced", Short: "Check if a pipeline is synced with its stacks.", Example: `cy --org my-org pipeline synced --project my-project --env env`, @@ -36,7 +36,7 @@ func synced(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) pp, _, err := m.SyncedPipeline(org, project, env, component, pipeline) return cyout.PrintWithOptions(cmd, pp, err, "unable to pipeline sync status", printer.Options{}) diff --git a/cmd/cycloid/pipelines/pipeline_unpause.go b/cmd/pipelines/pipeline_unpause.go similarity index 84% rename from cmd/cycloid/pipelines/pipeline_unpause.go rename to cmd/pipelines/pipeline_unpause.go index d6ee2bc53..e849148ab 100644 --- a/cmd/cycloid/pipelines/pipeline_unpause.go +++ b/cmd/pipelines/pipeline_unpause.go @@ -3,15 +3,15 @@ package pipelines import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" ) func NewPipelineUnpauseCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "unpause", Short: "unpause a pipeline", Example: `cy --org my-org pipeline unpause --project my-project --env env --component component --pipeline pipeline-name`, @@ -36,7 +36,7 @@ func unpause(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) _, err = m.UnpausePipeline(org, project, env, component, pipeline) return cyout.PrintWithOptions(cmd, nil, err, "failed to unpause pipeline", printer.Options{}) diff --git a/cmd/cycloid/pipelines/pipeline_update.go b/cmd/pipelines/pipeline_update.go similarity index 81% rename from cmd/cycloid/pipelines/pipeline_update.go rename to cmd/pipelines/pipeline_update.go index ede26d61e..6046800b6 100644 --- a/cmd/cycloid/pipelines/pipeline_update.go +++ b/cmd/pipelines/pipeline_update.go @@ -1,20 +1,20 @@ package pipelines import ( + "fmt" "os" - "github.com/pkg/errors" "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" ) func NewPipelineUpdateCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "update", Short: "update a running pipeline", Example: ` @@ -33,7 +33,7 @@ func NewPipelineUpdateCommand() *cobra.Command { func update(cmd *cobra.Command, args []string) error { api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) org, project, env, component, err := cyargs.GetCyContext(cmd) if err != nil { @@ -57,12 +57,12 @@ func update(cmd *cobra.Command, args []string) error { rawPipeline, err := os.ReadFile(pipelinePath) if err != nil { - return errors.Wrap(err, "unable to read pipeline file") + return fmt.Errorf("unable to read pipeline file: %w", err) } rawVars, err := os.ReadFile(pipelineVarsPath) if err != nil { - return errors.Wrap(err, "unable to read variables file") + return fmt.Errorf("unable to read variables file: %w", err) } resp, _, err := m.UpdatePipeline(org, project, env, component, pipeline, string(rawPipeline), string(rawVars), false) diff --git a/cmd/cycloid/plugins/cmd.go b/cmd/plugins/cmd.go similarity index 90% rename from cmd/cycloid/plugins/cmd.go rename to cmd/plugins/cmd.go index 2763b7cde..5bc9ebfc1 100644 --- a/cmd/cycloid/plugins/cmd.go +++ b/cmd/plugins/cmd.go @@ -3,10 +3,10 @@ package plugins import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/plugins/component" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/plugins/manager" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/plugins/registry" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/plugins/widget" + "github.com/cycloidio/cycloid-cli/cmd/plugins/component" + "github.com/cycloidio/cycloid-cli/cmd/plugins/manager" + "github.com/cycloidio/cycloid-cli/cmd/plugins/registry" + "github.com/cycloidio/cycloid-cli/cmd/plugins/widget" ) func NewCommands() *cobra.Command { diff --git a/cmd/cycloid/plugins/component/cmd.go b/cmd/plugins/component/cmd.go similarity index 82% rename from cmd/cycloid/plugins/component/cmd.go rename to cmd/plugins/component/cmd.go index 1a7ba2b6f..775ef14a5 100644 --- a/cmd/cycloid/plugins/component/cmd.go +++ b/cmd/plugins/component/cmd.go @@ -3,7 +3,7 @@ package component import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/plugins/component/widget" + "github.com/cycloidio/cycloid-cli/cmd/plugins/component/widget" ) func NewCommands() *cobra.Command { diff --git a/cmd/cycloid/plugins/component/list.go b/cmd/plugins/component/list.go similarity index 88% rename from cmd/cycloid/plugins/component/list.go rename to cmd/plugins/component/list.go index c324adcff..f00895535 100644 --- a/cmd/cycloid/plugins/component/list.go +++ b/cmd/plugins/component/list.go @@ -3,8 +3,8 @@ package component import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" @@ -49,7 +49,7 @@ func listComponentPlugins(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) result, _, err := m.ListComponentPlugins(org, project, env, component) return cyout.PrintWithOptions(cmd, result, err, "unable to list component plugins", printer.Options{}) diff --git a/cmd/cycloid/plugins/component/relation_set.go b/cmd/plugins/component/relation_set.go similarity index 92% rename from cmd/cycloid/plugins/component/relation_set.go rename to cmd/plugins/component/relation_set.go index 39e9d20d6..05f3a0d3b 100644 --- a/cmd/cycloid/plugins/component/relation_set.go +++ b/cmd/plugins/component/relation_set.go @@ -3,8 +3,8 @@ package component import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" @@ -57,7 +57,7 @@ func setComponentPluginRelation(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) pluginInstallID, err := cyargs.ResolvePluginInstallID(org, args[0], m) if err != nil { diff --git a/cmd/cycloid/plugins/component/widget/cmd.go b/cmd/plugins/component/widget/cmd.go similarity index 100% rename from cmd/cycloid/plugins/component/widget/cmd.go rename to cmd/plugins/component/widget/cmd.go diff --git a/cmd/cycloid/plugins/component/widget/list.go b/cmd/plugins/component/widget/list.go similarity index 88% rename from cmd/cycloid/plugins/component/widget/list.go rename to cmd/plugins/component/widget/list.go index 7b8925017..91efc4a39 100644 --- a/cmd/cycloid/plugins/component/widget/list.go +++ b/cmd/plugins/component/widget/list.go @@ -3,8 +3,8 @@ package widget import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" @@ -49,7 +49,7 @@ func listComponentPluginWidgets(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) result, _, err := m.ListComponentPluginWidgets(org, project, env, component) return cyout.PrintWithOptions(cmd, result, err, "unable to list component plugin widgets", printer.Options{}) diff --git a/cmd/cycloid/plugins/component/widget/query.go b/cmd/plugins/component/widget/query.go similarity index 90% rename from cmd/cycloid/plugins/component/widget/query.go rename to cmd/plugins/component/widget/query.go index 0bce73409..490ab2b66 100644 --- a/cmd/cycloid/plugins/component/widget/query.go +++ b/cmd/plugins/component/widget/query.go @@ -6,8 +6,8 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" @@ -52,7 +52,7 @@ func queryComponentPluginWidget(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) n, err := strconv.ParseUint(args[0], 10, 32) if err != nil { diff --git a/cmd/cycloid/plugins/get.go b/cmd/plugins/get.go similarity index 85% rename from cmd/cycloid/plugins/get.go rename to cmd/plugins/get.go index f8a274822..76426b021 100644 --- a/cmd/cycloid/plugins/get.go +++ b/cmd/plugins/get.go @@ -3,8 +3,8 @@ package plugins import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" @@ -31,7 +31,7 @@ func getPlugin(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) id, err := cyargs.ResolvePluginInstallID(org, args[0], m) if err != nil { diff --git a/cmd/cycloid/plugins/list.go b/cmd/plugins/list.go similarity index 83% rename from cmd/cycloid/plugins/list.go rename to cmd/plugins/list.go index f2f7074e4..496e6c631 100644 --- a/cmd/cycloid/plugins/list.go +++ b/cmd/plugins/list.go @@ -3,8 +3,8 @@ package plugins import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" @@ -30,7 +30,7 @@ func listPlugins(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) result, _, err := m.ListPlugins(org) return cyout.PrintWithOptions(cmd, result, err, "unable to list plugins", printer.Options{}) diff --git a/cmd/cycloid/plugins/logs.go b/cmd/plugins/logs.go similarity index 93% rename from cmd/cycloid/plugins/logs.go rename to cmd/plugins/logs.go index 3395fc624..64e42158e 100644 --- a/cmd/cycloid/plugins/logs.go +++ b/cmd/plugins/logs.go @@ -6,12 +6,12 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" + "github.com/cycloidio/cycloid-cli/gen/models" ) func NewLogsCommand() *cobra.Command { @@ -60,7 +60,7 @@ func pluginLogs(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) id, err := cyargs.ResolvePluginInstallID(org, args[0], m) if err != nil { diff --git a/cmd/cycloid/plugins/manager/accept.go b/cmd/plugins/manager/accept.go similarity index 88% rename from cmd/cycloid/plugins/manager/accept.go rename to cmd/plugins/manager/accept.go index a92aeba1e..fb40537af 100644 --- a/cmd/cycloid/plugins/manager/accept.go +++ b/cmd/plugins/manager/accept.go @@ -3,8 +3,8 @@ package manager import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" @@ -35,7 +35,7 @@ func updateInviteStatus(cmd *cobra.Command, args []string, status string) error } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) id, err := cyargs.ResolvePluginManagerID(org, args[0], m) if err != nil { diff --git a/cmd/cycloid/plugins/manager/cmd.go b/cmd/plugins/manager/cmd.go similarity index 100% rename from cmd/cycloid/plugins/manager/cmd.go rename to cmd/plugins/manager/cmd.go diff --git a/cmd/cycloid/plugins/manager/create.go b/cmd/plugins/manager/create.go similarity index 90% rename from cmd/cycloid/plugins/manager/create.go rename to cmd/plugins/manager/create.go index 0c289d6bf..46e650d00 100644 --- a/cmd/cycloid/plugins/manager/create.go +++ b/cmd/plugins/manager/create.go @@ -3,11 +3,10 @@ package manager import ( "fmt" - "github.com/pkg/errors" "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" @@ -45,7 +44,7 @@ func createPluginManager(cmd *cobra.Command, args []string) error { url, err := cyargs.GetURL(cmd) if err != nil { - return errors.Wrap(err, "unable to get --url flag") + return fmt.Errorf("unable to get --url flag: %w", err) } update, err := cmd.Flags().GetBool("update") @@ -54,7 +53,7 @@ func createPluginManager(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) // Check if a manager with this name already exists. existingID, resolveErr := cyargs.ResolvePluginManagerID(org, name, m) diff --git a/cmd/cycloid/plugins/manager/delete.go b/cmd/plugins/manager/delete.go similarity index 88% rename from cmd/cycloid/plugins/manager/delete.go rename to cmd/plugins/manager/delete.go index 0cca0fcfc..d09d85c48 100644 --- a/cmd/cycloid/plugins/manager/delete.go +++ b/cmd/plugins/manager/delete.go @@ -3,8 +3,8 @@ package manager import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" @@ -32,7 +32,7 @@ func deletePluginManager(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) for _, arg := range args { id, err := cyargs.ResolvePluginManagerID(org, arg, m) diff --git a/cmd/cycloid/plugins/manager/get.go b/cmd/plugins/manager/get.go similarity index 86% rename from cmd/cycloid/plugins/manager/get.go rename to cmd/plugins/manager/get.go index 896be864a..6b486b97c 100644 --- a/cmd/cycloid/plugins/manager/get.go +++ b/cmd/plugins/manager/get.go @@ -3,8 +3,8 @@ package manager import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" @@ -31,7 +31,7 @@ func getPluginManager(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) id, err := cyargs.ResolvePluginManagerID(org, args[0], m) if err != nil { diff --git a/cmd/cycloid/plugins/manager/list.go b/cmd/plugins/manager/list.go similarity index 83% rename from cmd/cycloid/plugins/manager/list.go rename to cmd/plugins/manager/list.go index c2e529bd2..5b515ad31 100644 --- a/cmd/cycloid/plugins/manager/list.go +++ b/cmd/plugins/manager/list.go @@ -3,8 +3,8 @@ package manager import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" @@ -29,7 +29,7 @@ func listPluginManagers(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) result, _, err := m.ListPluginManagers(org) return cyout.PrintWithOptions(cmd, result, err, "unable to list plugin managers", printer.Options{}) diff --git a/cmd/cycloid/plugins/manager/reject.go b/cmd/plugins/manager/reject.go similarity index 100% rename from cmd/cycloid/plugins/manager/reject.go rename to cmd/plugins/manager/reject.go diff --git a/cmd/cycloid/plugins/registry/cmd.go b/cmd/plugins/registry/cmd.go similarity index 84% rename from cmd/cycloid/plugins/registry/cmd.go rename to cmd/plugins/registry/cmd.go index dadc304fb..a63e16d68 100644 --- a/cmd/cycloid/plugins/registry/cmd.go +++ b/cmd/plugins/registry/cmd.go @@ -3,7 +3,7 @@ package registry import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/plugins/registry/plugin" + "github.com/cycloidio/cycloid-cli/cmd/plugins/registry/plugin" ) func NewCommands() *cobra.Command { diff --git a/cmd/cycloid/plugins/registry/create.go b/cmd/plugins/registry/create.go similarity index 91% rename from cmd/cycloid/plugins/registry/create.go rename to cmd/plugins/registry/create.go index afae1681d..81e107951 100644 --- a/cmd/cycloid/plugins/registry/create.go +++ b/cmd/plugins/registry/create.go @@ -3,11 +3,10 @@ package registry import ( "fmt" - "github.com/pkg/errors" "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" @@ -46,7 +45,7 @@ func createPluginRegistry(cmd *cobra.Command, args []string) error { url, err := cyargs.GetURL(cmd) if err != nil { - return errors.Wrap(err, "unable to get --url flag") + return fmt.Errorf("unable to get --url flag: %w", err) } update, err := cmd.Flags().GetBool("update") @@ -55,7 +54,7 @@ func createPluginRegistry(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) // Check if a registry with this name already exists. existingID, resolveErr := cyargs.ResolvePluginRegistryID(org, name, m) diff --git a/cmd/cycloid/plugins/registry/delete.go b/cmd/plugins/registry/delete.go similarity index 88% rename from cmd/cycloid/plugins/registry/delete.go rename to cmd/plugins/registry/delete.go index 2276983c4..38897e67c 100644 --- a/cmd/cycloid/plugins/registry/delete.go +++ b/cmd/plugins/registry/delete.go @@ -3,8 +3,8 @@ package registry import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" @@ -32,7 +32,7 @@ func deletePluginRegistry(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) for _, arg := range args { id, err := cyargs.ResolvePluginRegistryID(org, arg, m) diff --git a/cmd/cycloid/plugins/registry/get.go b/cmd/plugins/registry/get.go similarity index 87% rename from cmd/cycloid/plugins/registry/get.go rename to cmd/plugins/registry/get.go index 8be715583..69ed0e3f1 100644 --- a/cmd/cycloid/plugins/registry/get.go +++ b/cmd/plugins/registry/get.go @@ -3,8 +3,8 @@ package registry import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" @@ -32,7 +32,7 @@ func getPluginRegistry(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) id, err := cyargs.ResolvePluginRegistryID(org, args[0], m) if err != nil { diff --git a/cmd/cycloid/plugins/registry/list.go b/cmd/plugins/registry/list.go similarity index 83% rename from cmd/cycloid/plugins/registry/list.go rename to cmd/plugins/registry/list.go index d3a15daba..253f64c85 100644 --- a/cmd/cycloid/plugins/registry/list.go +++ b/cmd/plugins/registry/list.go @@ -3,8 +3,8 @@ package registry import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" @@ -29,7 +29,7 @@ func listPluginRegistries(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) result, _, err := m.ListPluginRegistries(org) return cyout.PrintWithOptions(cmd, result, err, "unable to list plugin registries", printer.Options{}) diff --git a/cmd/cycloid/plugins/registry/plugin/cmd.go b/cmd/plugins/registry/plugin/cmd.go similarity index 82% rename from cmd/cycloid/plugins/registry/plugin/cmd.go rename to cmd/plugins/registry/plugin/cmd.go index 06b0c14d0..6da976f6d 100644 --- a/cmd/cycloid/plugins/registry/plugin/cmd.go +++ b/cmd/plugins/registry/plugin/cmd.go @@ -3,7 +3,7 @@ package plugin import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/plugins/registry/plugin/version" + "github.com/cycloidio/cycloid-cli/cmd/plugins/registry/plugin/version" ) func NewCommands() *cobra.Command { diff --git a/cmd/cycloid/plugins/registry/plugin/create.go b/cmd/plugins/registry/plugin/create.go similarity index 93% rename from cmd/cycloid/plugins/registry/plugin/create.go rename to cmd/plugins/registry/plugin/create.go index 3a75dbcda..767871329 100644 --- a/cmd/cycloid/plugins/registry/plugin/create.go +++ b/cmd/plugins/registry/plugin/create.go @@ -5,8 +5,8 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" @@ -47,7 +47,7 @@ func createRegistryPlugin(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) registryID, err := cyargs.ResolvePluginRegistryID(org, args[0], m) if err != nil { diff --git a/cmd/cycloid/plugins/registry/plugin/delete.go b/cmd/plugins/registry/plugin/delete.go similarity index 88% rename from cmd/cycloid/plugins/registry/plugin/delete.go rename to cmd/plugins/registry/plugin/delete.go index 2e7879087..498fd665c 100644 --- a/cmd/cycloid/plugins/registry/plugin/delete.go +++ b/cmd/plugins/registry/plugin/delete.go @@ -3,8 +3,8 @@ package plugin import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" @@ -30,7 +30,7 @@ func deleteRegistryPlugin(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) registryID, err := cyargs.ResolvePluginRegistryID(org, args[0], m) if err != nil { diff --git a/cmd/cycloid/plugins/registry/plugin/get.go b/cmd/plugins/registry/plugin/get.go similarity index 90% rename from cmd/cycloid/plugins/registry/plugin/get.go rename to cmd/plugins/registry/plugin/get.go index e7b4de6f7..f2d12bbd5 100644 --- a/cmd/cycloid/plugins/registry/plugin/get.go +++ b/cmd/plugins/registry/plugin/get.go @@ -1,14 +1,14 @@ package plugin import ( - "github.com/cycloidio/cycloid-cli/client/models" "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" + "github.com/cycloidio/cycloid-cli/gen/models" ) func NewGetCommand() *cobra.Command { @@ -40,7 +40,7 @@ func getRegistryPlugin(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) registryID, err := cyargs.ResolvePluginRegistryID(org, registryStr, m) if err != nil { diff --git a/cmd/cycloid/plugins/registry/plugin/list.go b/cmd/plugins/registry/plugin/list.go similarity index 87% rename from cmd/cycloid/plugins/registry/plugin/list.go rename to cmd/plugins/registry/plugin/list.go index 64f3a6fa4..736dff8bd 100644 --- a/cmd/cycloid/plugins/registry/plugin/list.go +++ b/cmd/plugins/registry/plugin/list.go @@ -3,8 +3,8 @@ package plugin import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" @@ -31,7 +31,7 @@ func listRegistryPlugins(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) registryID, err := cyargs.ResolvePluginRegistryID(org, args[0], m) if err != nil { diff --git a/cmd/cycloid/plugins/registry/plugin/update.go b/cmd/plugins/registry/plugin/update.go similarity index 90% rename from cmd/cycloid/plugins/registry/plugin/update.go rename to cmd/plugins/registry/plugin/update.go index 1f49e854d..236417ab7 100644 --- a/cmd/cycloid/plugins/registry/plugin/update.go +++ b/cmd/plugins/registry/plugin/update.go @@ -3,8 +3,8 @@ package plugin import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" @@ -39,7 +39,7 @@ func updateRegistryPlugin(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) registryID, err := cyargs.ResolvePluginRegistryID(org, args[0], m) if err != nil { diff --git a/cmd/cycloid/plugins/registry/plugin/version/cmd.go b/cmd/plugins/registry/plugin/version/cmd.go similarity index 100% rename from cmd/cycloid/plugins/registry/plugin/version/cmd.go rename to cmd/plugins/registry/plugin/version/cmd.go diff --git a/cmd/cycloid/plugins/registry/plugin/version/delete.go b/cmd/plugins/registry/plugin/version/delete.go similarity index 88% rename from cmd/cycloid/plugins/registry/plugin/version/delete.go rename to cmd/plugins/registry/plugin/version/delete.go index 52447fd29..881e37d39 100644 --- a/cmd/cycloid/plugins/registry/plugin/version/delete.go +++ b/cmd/plugins/registry/plugin/version/delete.go @@ -3,8 +3,8 @@ package version import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" @@ -38,7 +38,7 @@ func deleteVersion(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) registryID, pluginID, err := resolveRegistryAndPlugin(org, cmd, m) if err != nil { diff --git a/cmd/cycloid/plugins/registry/plugin/version/get.go b/cmd/plugins/registry/plugin/version/get.go similarity index 88% rename from cmd/cycloid/plugins/registry/plugin/version/get.go rename to cmd/plugins/registry/plugin/version/get.go index b919da74e..f4ec193e1 100644 --- a/cmd/cycloid/plugins/registry/plugin/version/get.go +++ b/cmd/plugins/registry/plugin/version/get.go @@ -3,8 +3,8 @@ package version import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" @@ -38,7 +38,7 @@ func getVersion(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) registryID, pluginID, err := resolveRegistryAndPlugin(org, cmd, m) if err != nil { diff --git a/cmd/cycloid/plugins/registry/plugin/version/helpers.go b/cmd/plugins/registry/plugin/version/helpers.go similarity index 88% rename from cmd/cycloid/plugins/registry/plugin/version/helpers.go rename to cmd/plugins/registry/plugin/version/helpers.go index 576db30fb..004b6c4c8 100644 --- a/cmd/cycloid/plugins/registry/plugin/version/helpers.go +++ b/cmd/plugins/registry/plugin/version/helpers.go @@ -6,12 +6,12 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" "github.com/cycloidio/cycloid-cli/internal/cyargs" ) // resolveRegistryAndPlugin resolves --registry and --plugin flags to their numeric IDs. -func resolveRegistryAndPlugin(org string, cmd *cobra.Command, m middleware.Middleware) (registryID, pluginID uint32, err error) { +func resolveRegistryAndPlugin(org string, cmd *cobra.Command, m apiclient.Middleware) (registryID, pluginID uint32, err error) { registryStr, err := cyargs.GetRegistry(cmd) if err != nil { return 0, 0, err diff --git a/cmd/cycloid/plugins/registry/plugin/version/install.go b/cmd/plugins/registry/plugin/version/install.go similarity index 96% rename from cmd/cycloid/plugins/registry/plugin/version/install.go rename to cmd/plugins/registry/plugin/version/install.go index d14f0ea36..8896d01ff 100644 --- a/cmd/cycloid/plugins/registry/plugin/version/install.go +++ b/cmd/plugins/registry/plugin/version/install.go @@ -5,8 +5,8 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" @@ -92,7 +92,7 @@ func installVersion(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) registryID, pluginID, err := resolveRegistryAndPlugin(org, cmd, m) if err != nil { diff --git a/cmd/cycloid/plugins/registry/plugin/version/list.go b/cmd/plugins/registry/plugin/version/list.go similarity index 88% rename from cmd/cycloid/plugins/registry/plugin/version/list.go rename to cmd/plugins/registry/plugin/version/list.go index 3b5c60a72..6a64b92ee 100644 --- a/cmd/cycloid/plugins/registry/plugin/version/list.go +++ b/cmd/plugins/registry/plugin/version/list.go @@ -3,8 +3,8 @@ package version import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" @@ -33,7 +33,7 @@ func listVersions(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) registryID, pluginID, err := resolveRegistryAndPlugin(org, cmd, m) if err != nil { diff --git a/cmd/cycloid/plugins/registry/plugin/version/logs.go b/cmd/plugins/registry/plugin/version/logs.go similarity index 89% rename from cmd/cycloid/plugins/registry/plugin/version/logs.go rename to cmd/plugins/registry/plugin/version/logs.go index bddabb838..337dbce88 100644 --- a/cmd/cycloid/plugins/registry/plugin/version/logs.go +++ b/cmd/plugins/registry/plugin/version/logs.go @@ -3,8 +3,8 @@ package version import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" @@ -38,7 +38,7 @@ func versionLogs(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) registryID, pluginID, err := resolveRegistryAndPlugin(org, cmd, m) if err != nil { diff --git a/cmd/cycloid/plugins/registry/plugin/version/publish.go b/cmd/plugins/registry/plugin/version/publish.go similarity index 81% rename from cmd/cycloid/plugins/registry/plugin/version/publish.go rename to cmd/plugins/registry/plugin/version/publish.go index cd7656533..24b91c92b 100644 --- a/cmd/cycloid/plugins/registry/plugin/version/publish.go +++ b/cmd/plugins/registry/plugin/version/publish.go @@ -1,11 +1,12 @@ package version import ( - "github.com/pkg/errors" + "fmt" + "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" @@ -42,19 +43,19 @@ func publishVersion(cmd *cobra.Command, args []string) error { url, err := cyargs.GetURL(cmd) if err != nil { - return errors.Wrap(err, "unable to get --url flag") + return fmt.Errorf("unable to get --url flag: %w", err) } dockerImage, err := cyargs.GetDockerImage(cmd) if err != nil { - return errors.Wrap(err, "unable to get --docker-image flag") + return fmt.Errorf("unable to get --docker-image flag: %w", err) } if url == "" && dockerImage == "" { - return errors.New("one of --url or --docker-image is required") + return fmt.Errorf("one of --url or --docker-image is required") } if url != "" && dockerImage != "" { - return errors.New("--url and --docker-image are mutually exclusive") + return fmt.Errorf("--url and --docker-image are mutually exclusive") } versionURL := url @@ -63,7 +64,7 @@ func publishVersion(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) registryID, pluginID, err := resolveRegistryAndPlugin(org, cmd, m) if err != nil { diff --git a/cmd/cycloid/plugins/registry/plugin/version/retry.go b/cmd/plugins/registry/plugin/version/retry.go similarity index 89% rename from cmd/cycloid/plugins/registry/plugin/version/retry.go rename to cmd/plugins/registry/plugin/version/retry.go index a779f592a..8abe1fc02 100644 --- a/cmd/cycloid/plugins/registry/plugin/version/retry.go +++ b/cmd/plugins/registry/plugin/version/retry.go @@ -3,8 +3,8 @@ package version import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" @@ -38,7 +38,7 @@ func retryVersion(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) registryID, pluginID, err := resolveRegistryAndPlugin(org, cmd, m) if err != nil { diff --git a/cmd/cycloid/plugins/registry/update.go b/cmd/plugins/registry/update.go similarity index 88% rename from cmd/cycloid/plugins/registry/update.go rename to cmd/plugins/registry/update.go index bea5e1305..97ed1e948 100644 --- a/cmd/cycloid/plugins/registry/update.go +++ b/cmd/plugins/registry/update.go @@ -3,8 +3,8 @@ package registry import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" @@ -39,7 +39,7 @@ func updatePluginRegistry(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) id, err := cyargs.ResolvePluginRegistryID(org, args[0], m) if err != nil { diff --git a/cmd/cycloid/plugins/uninstall.go b/cmd/plugins/uninstall.go similarity index 88% rename from cmd/cycloid/plugins/uninstall.go rename to cmd/plugins/uninstall.go index 9a63514fc..99a81b1ab 100644 --- a/cmd/cycloid/plugins/uninstall.go +++ b/cmd/plugins/uninstall.go @@ -3,8 +3,8 @@ package plugins import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" @@ -32,7 +32,7 @@ func uninstallPlugin(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) for _, arg := range args { id, err := cyargs.ResolvePluginInstallID(org, arg, m) diff --git a/cmd/cycloid/plugins/upgrade.go b/cmd/plugins/upgrade.go similarity index 81% rename from cmd/cycloid/plugins/upgrade.go rename to cmd/plugins/upgrade.go index b4c567c46..5c7b8a469 100644 --- a/cmd/cycloid/plugins/upgrade.go +++ b/cmd/plugins/upgrade.go @@ -1,11 +1,12 @@ package plugins import ( - "github.com/pkg/errors" + "fmt" + "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" @@ -39,16 +40,16 @@ func upgradePlugin(cmd *cobra.Command, args []string) error { versionID, err := cyargs.GetPluginVersionID(cmd) if err != nil { - return errors.Wrap(err, "unable to get --version-id flag") + return fmt.Errorf("unable to get --version-id flag: %w", err) } config, err := cyargs.GetPluginConfig(cmd) if err != nil { - return errors.Wrap(err, "unable to get plugin configuration") + return fmt.Errorf("unable to get plugin configuration: %w", err) } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) id, err := cyargs.ResolvePluginInstallID(org, args[0], m) if err != nil { diff --git a/cmd/cycloid/plugins/widget/cmd.go b/cmd/plugins/widget/cmd.go similarity index 100% rename from cmd/cycloid/plugins/widget/cmd.go rename to cmd/plugins/widget/cmd.go diff --git a/cmd/cycloid/plugins/widget/list.go b/cmd/plugins/widget/list.go similarity index 87% rename from cmd/cycloid/plugins/widget/list.go rename to cmd/plugins/widget/list.go index 7a44ab4ac..eba7a2ec7 100644 --- a/cmd/cycloid/plugins/widget/list.go +++ b/cmd/plugins/widget/list.go @@ -3,8 +3,8 @@ package widget import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" @@ -37,7 +37,7 @@ func listPluginWidgets(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) result, _, err := m.ListPluginWidgets(org, placement) return cyout.PrintWithOptions(cmd, result, err, "unable to list plugin widgets", printer.Options{}) diff --git a/cmd/cycloid/plugins/widget/query.go b/cmd/plugins/widget/query.go similarity index 92% rename from cmd/cycloid/plugins/widget/query.go rename to cmd/plugins/widget/query.go index 120e0006c..2fe57378a 100644 --- a/cmd/cycloid/plugins/widget/query.go +++ b/cmd/plugins/widget/query.go @@ -6,8 +6,8 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" @@ -49,7 +49,7 @@ func queryPluginWidget(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) n, err := strconv.ParseUint(args[0], 10, 32) if err != nil { diff --git a/cmd/cycloid/projects/cmd.go b/cmd/projects/cmd.go similarity index 92% rename from cmd/cycloid/projects/cmd.go rename to cmd/projects/cmd.go index faf0e6817..72c0e3b9b 100644 --- a/cmd/cycloid/projects/cmd.go +++ b/cmd/projects/cmd.go @@ -5,7 +5,7 @@ import ( ) func NewCommands() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "project", Aliases: []string{ "p", diff --git a/cmd/cycloid/projects/create.go b/cmd/projects/create.go similarity index 90% rename from cmd/cycloid/projects/create.go rename to cmd/projects/create.go index b60253960..0dc337439 100644 --- a/cmd/cycloid/projects/create.go +++ b/cmd/projects/create.go @@ -6,16 +6,16 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" + "github.com/cycloidio/cycloid-cli/gen/models" ) func NewCreateCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "create", Args: cobra.NoArgs, Short: "create a project", @@ -49,7 +49,7 @@ func create(cmd *cobra.Command, args []string) error { if err != nil { return err } - name, project, err = middleware.NameOrCanonical(&name, &project) + name, project, err = apiclient.NameOrCanonical(&name, &project) if err != nil { return err } @@ -85,7 +85,7 @@ func create(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) if update { projects, _, err := m.ListProjects(org) diff --git a/cmd/cycloid/projects/delete.go b/cmd/projects/delete.go similarity index 85% rename from cmd/cycloid/projects/delete.go rename to cmd/projects/delete.go index 8ac46c9c8..5634e340c 100644 --- a/cmd/cycloid/projects/delete.go +++ b/cmd/projects/delete.go @@ -3,15 +3,15 @@ package projects import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" ) func NewDeleteCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "delete [canonical...]", Args: cyargs.RequireArgsOrFlag("project"), Aliases: []string{"del", "rm"}, @@ -62,9 +62,9 @@ func deleteProject(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) - opts := middleware.DeleteOptions{Force: force, SkipHooks: skipHooks, IgnoreConfigFilesErr: ignoreConfigFilesErr} + opts := apiclient.DeleteOptions{Force: force, SkipHooks: skipHooks, IgnoreConfigFilesErr: ignoreConfigFilesErr} deleted := make([]string, 0, len(args)) for _, project := range args { _, err = m.DeleteProject(org, project, opts) diff --git a/cmd/cycloid/projects/get.go b/cmd/projects/get.go similarity index 88% rename from cmd/cycloid/projects/get.go rename to cmd/projects/get.go index d1297425a..fecf5e65e 100644 --- a/cmd/cycloid/projects/get.go +++ b/cmd/projects/get.go @@ -3,15 +3,15 @@ package projects import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" + "github.com/cycloidio/cycloid-cli/gen/models" ) func NewGetCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "get [canonical...]", Args: cyargs.RequireArgsOrFlag("project"), ValidArgsFunction: cyargs.CompleteProject, @@ -36,7 +36,7 @@ func NewGetCommand() *cobra.Command { func get(cmd *cobra.Command, args []string) error { api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) org, err := cyargs.GetOrg(cmd) if err != nil { diff --git a/cmd/cycloid/projects/list-env.go b/cmd/projects/list-env.go similarity index 81% rename from cmd/cycloid/projects/list-env.go rename to cmd/projects/list-env.go index 021e9a91d..537982af5 100644 --- a/cmd/cycloid/projects/list-env.go +++ b/cmd/projects/list-env.go @@ -3,14 +3,14 @@ package projects import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" ) func NewListEnvCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "list-env", Args: cobra.NoArgs, Short: "List environments in the current project", @@ -24,7 +24,7 @@ func NewListEnvCommand() *cobra.Command { func listEnv(cmd *cobra.Command, args []string) error { api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) org, err := cyargs.GetOrg(cmd) if err != nil { diff --git a/cmd/cycloid/projects/list.go b/cmd/projects/list.go similarity index 80% rename from cmd/cycloid/projects/list.go rename to cmd/projects/list.go index 04d6aaf41..ca6d064d4 100644 --- a/cmd/cycloid/projects/list.go +++ b/cmd/projects/list.go @@ -3,12 +3,12 @@ package projects import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" + "github.com/cycloidio/cycloid-cli/gen/models" ) var projectTableOptions = printer.Options{ @@ -17,7 +17,7 @@ var projectTableOptions = printer.Options{ } func NewListCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "list", Args: cobra.NoArgs, Short: "list the projects within the organization", @@ -31,7 +31,7 @@ cy --org my-org projects list -o json`, func list(cmd *cobra.Command, args []string) error { api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) org, err := cyargs.GetOrg(cmd) if err != nil { diff --git a/cmd/cycloid/projects/update.go b/cmd/projects/update.go similarity index 92% rename from cmd/cycloid/projects/update.go rename to cmd/projects/update.go index b722dca3b..8e25806d9 100644 --- a/cmd/cycloid/projects/update.go +++ b/cmd/projects/update.go @@ -3,15 +3,15 @@ package projects import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" ) func NewUpdateCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "update", Args: cobra.NoArgs, Short: "update a project", @@ -31,7 +31,7 @@ func NewUpdateCommand() *cobra.Command { func update(cmd *cobra.Command, args []string) error { api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) org, err := cyargs.GetOrg(cmd) if err != nil { diff --git a/cmd/cycloid/roles/cmd.go b/cmd/roles/cmd.go similarity index 95% rename from cmd/cycloid/roles/cmd.go rename to cmd/roles/cmd.go index 90a2d2eeb..09e70b2e0 100644 --- a/cmd/cycloid/roles/cmd.go +++ b/cmd/roles/cmd.go @@ -14,7 +14,7 @@ func NewCommands() *cobra.Command { long = short ) - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "roles", Aliases: []string{"role"}, Example: example, diff --git a/cmd/cycloid/roles/common.go b/cmd/roles/common.go similarity index 88% rename from cmd/cycloid/roles/common.go rename to cmd/roles/common.go index 424b9d3b2..932773d46 100644 --- a/cmd/cycloid/roles/common.go +++ b/cmd/roles/common.go @@ -7,8 +7,8 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" @@ -40,7 +40,7 @@ func runRoleWrite(cmd *cobra.Command, upsert bool) error { roleCan = deprecatedCan } - name, role, err := middleware.NameOrCanonical(&roleName, &roleCan) + name, role, err := apiclient.NameOrCanonical(&roleName, &roleCan) if err != nil { return err } @@ -63,12 +63,12 @@ func runRoleWrite(cmd *cobra.Command, upsert bool) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) _, _, err = m.GetRole(org, role) exists := err == nil if err != nil { - var apiErr *middleware.APIResponseError + var apiErr *apiclient.APIResponseError if stderrors.As(err, &apiErr) && apiErr.StatusCode == http.StatusNotFound { exists = false } else { diff --git a/cmd/cycloid/roles/create.go b/cmd/roles/create.go similarity index 98% rename from cmd/cycloid/roles/create.go rename to cmd/roles/create.go index e129dc802..0196d0924 100644 --- a/cmd/cycloid/roles/create.go +++ b/cmd/roles/create.go @@ -7,7 +7,7 @@ import ( ) func NewCreateCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "create", Args: cobra.NoArgs, Example: ` cy --org my-org roles create --name "New role" --description "My cool role." \ diff --git a/cmd/cycloid/roles/delete.go b/cmd/roles/delete.go similarity index 87% rename from cmd/cycloid/roles/delete.go rename to cmd/roles/delete.go index ce2ef1a81..1c1e4b9b2 100644 --- a/cmd/cycloid/roles/delete.go +++ b/cmd/roles/delete.go @@ -5,8 +5,8 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" @@ -19,7 +19,7 @@ func NewDeleteCommand() *cobra.Command { long = short ) - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "delete", Aliases: []string{"rm"}, Args: cobra.MinimumNArgs(1), @@ -40,7 +40,7 @@ func deleteRole(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) deleted := make([]string, 0, len(args)) for _, role := range args { diff --git a/cmd/cycloid/roles/get.go b/cmd/roles/get.go similarity index 88% rename from cmd/cycloid/roles/get.go rename to cmd/roles/get.go index caca5e97b..fa66b494f 100644 --- a/cmd/cycloid/roles/get.go +++ b/cmd/roles/get.go @@ -3,11 +3,11 @@ package roles import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" + "github.com/cycloidio/cycloid-cli/gen/models" ) func NewGetCommand() *cobra.Command { @@ -23,7 +23,7 @@ func NewGetCommand() *cobra.Command { long = short ) - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "get [canonical...]", Args: cyargs.RequireArgsOrFlag("role"), Example: example, @@ -46,7 +46,7 @@ func NewGetCommand() *cobra.Command { func getRole(cmd *cobra.Command, args []string) error { api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) org, err := cyargs.GetOrg(cmd) if err != nil { diff --git a/cmd/cycloid/roles/list.go b/cmd/roles/list.go similarity index 80% rename from cmd/cycloid/roles/list.go rename to cmd/roles/list.go index 984484c29..cc46c62a4 100644 --- a/cmd/cycloid/roles/list.go +++ b/cmd/roles/list.go @@ -3,12 +3,12 @@ package roles import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" + "github.com/cycloidio/cycloid-cli/gen/models" ) var roleTableOptions = printer.Options{ @@ -23,7 +23,7 @@ func NewListCommand() *cobra.Command { long = short ) - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "list", Args: cobra.NoArgs, Example: example, @@ -37,7 +37,7 @@ func NewListCommand() *cobra.Command { func listRoles(cmd *cobra.Command, args []string) error { api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) org, err := cyargs.GetOrg(cmd) if err != nil { diff --git a/cmd/cycloid/roles/update.go b/cmd/roles/update.go similarity index 97% rename from cmd/cycloid/roles/update.go rename to cmd/roles/update.go index cffe5f9cb..0015e9069 100644 --- a/cmd/cycloid/roles/update.go +++ b/cmd/roles/update.go @@ -7,7 +7,7 @@ import ( ) func NewUpdateCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "update", Args: cobra.NoArgs, Example: ` cy --org my-org roles update --role my-role --name "My role" \ diff --git a/cmd/root.go b/cmd/root.go index 057342bef..27f5ce689 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -7,32 +7,31 @@ import ( "github.com/spf13/cobra" "github.com/spf13/viper" - root "github.com/cycloidio/cycloid-cli/cmd/cycloid" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/apikey" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/beta" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/catalogrepositories" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/cloudaccounts" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/components" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/configrepositories" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/credentials" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/environments" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/environmenttypes" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/events" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/externalbackends" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/kpis" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/login" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/members" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/oidc" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/organizations" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/output" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/pipelines" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/plugins" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/projects" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/roles" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/stacks" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/teams" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/terracost" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/uri" + "github.com/cycloidio/cycloid-cli/cmd/apikey" + "github.com/cycloidio/cycloid-cli/cmd/beta" + "github.com/cycloidio/cycloid-cli/cmd/catalogrepositories" + "github.com/cycloidio/cycloid-cli/cmd/cloudaccounts" + "github.com/cycloidio/cycloid-cli/cmd/components" + "github.com/cycloidio/cycloid-cli/cmd/configrepositories" + "github.com/cycloidio/cycloid-cli/cmd/credentials" + "github.com/cycloidio/cycloid-cli/cmd/environments" + "github.com/cycloidio/cycloid-cli/cmd/environmenttypes" + "github.com/cycloidio/cycloid-cli/cmd/events" + "github.com/cycloidio/cycloid-cli/cmd/externalbackends" + "github.com/cycloidio/cycloid-cli/cmd/kpis" + "github.com/cycloidio/cycloid-cli/cmd/login" + "github.com/cycloidio/cycloid-cli/cmd/members" + "github.com/cycloidio/cycloid-cli/cmd/oidc" + "github.com/cycloidio/cycloid-cli/cmd/organizations" + "github.com/cycloidio/cycloid-cli/cmd/output" + "github.com/cycloidio/cycloid-cli/cmd/pipelines" + "github.com/cycloidio/cycloid-cli/cmd/plugins" + "github.com/cycloidio/cycloid-cli/cmd/projects" + "github.com/cycloidio/cycloid-cli/cmd/roles" + "github.com/cycloidio/cycloid-cli/cmd/stacks" + "github.com/cycloidio/cycloid-cli/cmd/teams" + "github.com/cycloidio/cycloid-cli/cmd/terracost" + "github.com/cycloidio/cycloid-cli/cmd/uri" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/internal/version" ) @@ -154,10 +153,10 @@ NO_PROXY | List of hosts that must bypass proxy configuration func AttachCommands(cmd *cobra.Command) { cmd.AddCommand( - root.NewVersionCmd(), - root.NewStatusCmd(), - root.NewCompletionCmd(), - root.NewGetCommand(), + NewVersionCmd(), + NewStatusCmd(), + NewCompletionCmd(), + NewGetCommand(), apikey.NewCommands(), catalogrepositories.NewCommands(), configrepositories.NewCommands(), diff --git a/cmd/cycloid/stacks/cmd.go b/cmd/stacks/cmd.go similarity index 93% rename from cmd/cycloid/stacks/cmd.go rename to cmd/stacks/cmd.go index bc3b89d34..1a8237a9d 100644 --- a/cmd/cycloid/stacks/cmd.go +++ b/cmd/stacks/cmd.go @@ -5,7 +5,7 @@ import ( ) func NewCommands() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "stack", Aliases: []string{ "s", diff --git a/cmd/cycloid/stacks/create.go b/cmd/stacks/create.go similarity index 88% rename from cmd/cycloid/stacks/create.go rename to cmd/stacks/create.go index 3ff53bc97..a6aeb6764 100644 --- a/cmd/cycloid/stacks/create.go +++ b/cmd/stacks/create.go @@ -6,17 +6,17 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" - "github.com/cycloidio/cycloid-cli/internal/ptr" "github.com/cycloidio/cycloid-cli/printer" + "github.com/cycloidio/cycloid-cli/gen/models" + "github.com/cycloidio/cycloid-cli/utils/ptr" ) func NewCreateFromBlueprintCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "create", Short: "create a new stack from a blueprint", Example: `cy stack create --name "My Stack" --stack my-stack --catalog-repository my-catalog --blueprint-ref org:blueprint --use-case production`, @@ -54,7 +54,7 @@ func createFromBlueprint(cmd *cobra.Command, args []string) error { return err } - displayName, stackCanonical, err := middleware.NameOrCanonical(&name, &stack) + displayName, stackCanonical, err := apiclient.NameOrCanonical(&name, &stack) if err != nil { return err } @@ -76,7 +76,7 @@ func createFromBlueprint(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) stacksList, _, err := m.ListStacks(org) if err != nil { diff --git a/cmd/cycloid/stacks/forms.go b/cmd/stacks/forms.go similarity index 100% rename from cmd/cycloid/stacks/forms.go rename to cmd/stacks/forms.go diff --git a/cmd/cycloid/stacks/forms_validate.go b/cmd/stacks/forms_validate.go similarity index 88% rename from cmd/cycloid/stacks/forms_validate.go rename to cmd/stacks/forms_validate.go index 3121625ff..10f149fb3 100644 --- a/cmd/cycloid/stacks/forms_validate.go +++ b/cmd/stacks/forms_validate.go @@ -5,18 +5,17 @@ import ( "os" "path/filepath" - "github.com/pkg/errors" "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" ) func NewFormsValidateCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "validate [file...]", Args: cobra.ArbitraryArgs, ValidArgsFunction: cyargs.ValidateForms, @@ -58,13 +57,13 @@ func validateForm(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) var hasErrors bool for _, formsPath := range args { rawForm, err := os.ReadFile(formsPath) if err != nil { - return errors.Wrapf(err, "unable to read the form file at path '%s'", formsPath) + return fmt.Errorf("unable to read the form file at path '%s': %w", formsPath, err) } validation, _, err := m.ValidateForm(org, rawForm) diff --git a/cmd/cycloid/stacks/get.go b/cmd/stacks/get.go similarity index 83% rename from cmd/cycloid/stacks/get.go rename to cmd/stacks/get.go index 800b7a855..b4c6f4141 100644 --- a/cmd/cycloid/stacks/get.go +++ b/cmd/stacks/get.go @@ -3,15 +3,15 @@ package stacks import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" ) func NewGetCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "get", Args: cobra.NoArgs, Short: "get information on a stack", @@ -36,7 +36,7 @@ func get(cmd *cobra.Command, args []string) error { // Initialize middleware after all arguments are collected api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) s, _, err := m.GetStack(org, ref) return cyout.PrintWithOptions(cmd, s, err, "failed to get stack from API", printer.Options{}) diff --git a/cmd/cycloid/stacks/get_config.go b/cmd/stacks/get_config.go similarity index 87% rename from cmd/cycloid/stacks/get_config.go rename to cmd/stacks/get_config.go index 80795ae65..8eb9b736f 100644 --- a/cmd/cycloid/stacks/get_config.go +++ b/cmd/stacks/get_config.go @@ -3,18 +3,17 @@ package stacks import ( "fmt" - "github.com/pkg/errors" "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" ) func NewStacksGetComponentStackConfig() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "get-config -p project -e env -c component [flags]", Short: "Output a stack configuration in JSON", Example: ` @@ -45,13 +44,13 @@ func getConfig(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) // Resolve stack version: --stack-version (new) or legacy flags. // Bare --stack-version requires prefix form (tag:/branch:/sha:) since no stack-ref is available here. tag, branch, hash, err := cyargs.ResolveStackVersionArg(cmd, m, org, "") if err != nil { - return errors.Wrap(err, "failed to read stack version flags") + return fmt.Errorf("failed to read stack version flags: %w", err) } stackConfigs, _, err := m.GetComponentStackConfig(org, project, environment, component, useCase, tag, branch, hash) diff --git a/cmd/cycloid/stacks/list.go b/cmd/stacks/list.go similarity index 89% rename from cmd/cycloid/stacks/list.go rename to cmd/stacks/list.go index 0fe0d7e0e..91a9f65af 100644 --- a/cmd/cycloid/stacks/list.go +++ b/cmd/stacks/list.go @@ -5,8 +5,8 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/custommodels" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" @@ -14,7 +14,7 @@ import ( ) func NewListCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "list", Aliases: []string{ "ls", @@ -42,7 +42,7 @@ func list(cmd *cobra.Command, args []string) error { // Initialize middleware after all arguments are collected api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) // list standard stacks if !blueprint { @@ -56,7 +56,7 @@ func list(cmd *cobra.Command, args []string) error { return cyout.PrintWithOptions(cmd, nil, err, "failed to list blueprints from API", printer.Options{}) } - var blueprints = make([]*custommodels.Blueprint, len(stacks)) + blueprints := make([]*custommodels.Blueprint, len(stacks)) for index, stack := range stacks { blueprints[index] = &custommodels.Blueprint{ ServiceCatalog: *stack, diff --git a/cmd/cycloid/stacks/update.go b/cmd/stacks/update.go similarity index 91% rename from cmd/cycloid/stacks/update.go rename to cmd/stacks/update.go index b12559f26..8d965b64b 100644 --- a/cmd/cycloid/stacks/update.go +++ b/cmd/stacks/update.go @@ -5,15 +5,15 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" ) func NewUpdateCommand() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "update", Args: cobra.NoArgs, Short: "update the visibility of a stack", @@ -46,7 +46,7 @@ func update(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) // Fetch the current stack state stack, _, err := m.GetStack(org, stackRef) diff --git a/cmd/cycloid/status.go b/cmd/status.go similarity index 88% rename from cmd/cycloid/status.go rename to cmd/status.go index fd5afd870..723aabb13 100644 --- a/cmd/cycloid/status.go +++ b/cmd/status.go @@ -1,10 +1,10 @@ -package cycloid +package cmd import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" @@ -24,7 +24,7 @@ func NewStatusCmd() *cobra.Command { func getStatus(cmd *cobra.Command, args []string) error { api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) services, _, err := m.GetStatus() if err != nil { diff --git a/cmd/cycloid/teams/cmd.go b/cmd/teams/cmd.go similarity index 96% rename from cmd/cycloid/teams/cmd.go rename to cmd/teams/cmd.go index 2350e00fe..2382b122f 100644 --- a/cmd/cycloid/teams/cmd.go +++ b/cmd/teams/cmd.go @@ -6,8 +6,8 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" "github.com/cycloidio/cycloid-cli/printer" + "github.com/cycloidio/cycloid-cli/gen/models" ) func NewTeamsCommands() *cobra.Command { diff --git a/cmd/cycloid/teams/create.go b/cmd/teams/create.go similarity index 83% rename from cmd/cycloid/teams/create.go rename to cmd/teams/create.go index 920d254eb..50d727fac 100644 --- a/cmd/cycloid/teams/create.go +++ b/cmd/teams/create.go @@ -6,14 +6,14 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" - "github.com/cycloidio/cycloid-cli/internal/ptr" - "github.com/cycloidio/cycloid-cli/internal/utils" "github.com/cycloidio/cycloid-cli/printer" + "github.com/cycloidio/cycloid-cli/gen/models" + "github.com/cycloidio/cycloid-cli/utils" + "github.com/cycloidio/cycloid-cli/utils/ptr" ) func NewCreateTeamCommand() *cobra.Command { @@ -56,7 +56,7 @@ func createTeam(cmd *cobra.Command, args []string) error { return err } - displayName, teamCanonical, err := middleware.NameOrCanonical(&teamName, &team) + displayName, teamCanonical, err := apiclient.NameOrCanonical(&teamName, &team) if err != nil { return err } @@ -72,13 +72,13 @@ func createTeam(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) var newTeam *models.Team if allowUpdate { currentTeam, _, err := m.GetTeam(org, teamCanonical) if err != nil { - var apiErr *middleware.APIResponseError + var apiErr *apiclient.APIResponseError if !stderrors.As(err, &apiErr) || apiErr.StatusCode != http.StatusNotFound { return cyout.PrintWithOptions(cmd, nil, err, "failed to get team to check if it exists", printer.Options{}) } diff --git a/cmd/cycloid/teams/delete.go b/cmd/teams/delete.go similarity index 84% rename from cmd/cycloid/teams/delete.go rename to cmd/teams/delete.go index 4e7f0c748..26c270c1f 100644 --- a/cmd/cycloid/teams/delete.go +++ b/cmd/teams/delete.go @@ -5,8 +5,8 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" @@ -31,9 +31,9 @@ func deleteTeam(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) - var deleted = make([]string, len(args)) + deleted := make([]string, len(args)) for i, team := range args { _, err = m.DeleteTeam(org, team) if err != nil { diff --git a/cmd/cycloid/teams/get.go b/cmd/teams/get.go similarity index 84% rename from cmd/cycloid/teams/get.go rename to cmd/teams/get.go index 5119cd3c5..f2bdd14e4 100644 --- a/cmd/cycloid/teams/get.go +++ b/cmd/teams/get.go @@ -5,11 +5,11 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" + "github.com/cycloidio/cycloid-cli/gen/models" ) func NewGetTeamCommand() *cobra.Command { @@ -31,7 +31,7 @@ func getTeam(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) teams := make([]*models.Team, len(args)) for i, canonical := range args { diff --git a/cmd/cycloid/teams/list.go b/cmd/teams/list.go similarity index 84% rename from cmd/cycloid/teams/list.go rename to cmd/teams/list.go index 702f1b5a1..de22af27d 100644 --- a/cmd/cycloid/teams/list.go +++ b/cmd/teams/list.go @@ -5,12 +5,12 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" - "github.com/cycloidio/cycloid-cli/internal/utils" + "github.com/cycloidio/cycloid-cli/gen/models" + "github.com/cycloidio/cycloid-cli/utils" ) func NewListTeamCommand() *cobra.Command { @@ -58,7 +58,7 @@ func listTeam(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) teams, _, err := m.ListTeams( org, utils.CoalesceNonZeroPtr(teamName), diff --git a/cmd/cycloid/teams/members.go b/cmd/teams/members.go similarity index 100% rename from cmd/cycloid/teams/members.go rename to cmd/teams/members.go diff --git a/cmd/cycloid/teams/members_assign.go b/cmd/teams/members_assign.go similarity index 84% rename from cmd/cycloid/teams/members_assign.go rename to cmd/teams/members_assign.go index e233ec96b..7b712cae8 100644 --- a/cmd/cycloid/teams/members_assign.go +++ b/cmd/teams/members_assign.go @@ -6,12 +6,12 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" + "github.com/cycloidio/cycloid-cli/gen/models" ) func NewTeamMemberAssignCommand() *cobra.Command { @@ -40,9 +40,9 @@ func assignTeamMember(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) - var outMembers = make([]*models.MemberTeam, len(args)) + outMembers := make([]*models.MemberTeam, len(args)) for i, id := range args { var username, email *string = nil, nil if strings.Contains(id, "@") { diff --git a/cmd/cycloid/teams/members_get.go b/cmd/teams/members_get.go similarity index 84% rename from cmd/cycloid/teams/members_get.go rename to cmd/teams/members_get.go index 8f4019401..4fb5fa2d4 100644 --- a/cmd/cycloid/teams/members_get.go +++ b/cmd/teams/members_get.go @@ -7,13 +7,13 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" - "github.com/cycloidio/cycloid-cli/internal/ptr" "github.com/cycloidio/cycloid-cli/printer" + "github.com/cycloidio/cycloid-cli/gen/models" + "github.com/cycloidio/cycloid-cli/utils/ptr" ) func NewTeamMemberGetCommand() *cobra.Command { @@ -41,9 +41,9 @@ func getTeamMember(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) - var outMembers = make([]*models.MemberTeam, len(args)) + outMembers := make([]*models.MemberTeam, len(args)) currentMembers, _, err := m.ListTeamMembers(org, team) if err != nil { return cyout.PrintWithOptions(cmd, nil, fmt.Errorf("failed to list members of team %q: %w", team, err), "", printer.Options{}) diff --git a/cmd/cycloid/teams/members_list.go b/cmd/teams/members_list.go similarity index 89% rename from cmd/cycloid/teams/members_list.go rename to cmd/teams/members_list.go index c8532cfb7..46a29aa75 100644 --- a/cmd/cycloid/teams/members_list.go +++ b/cmd/teams/members_list.go @@ -5,8 +5,8 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" @@ -44,7 +44,7 @@ func listTeamMember(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) members, _, err := m.ListTeamMembers(org, team) if err != nil { diff --git a/cmd/cycloid/teams/members_unassign.go b/cmd/teams/members_unassign.go similarity index 84% rename from cmd/cycloid/teams/members_unassign.go rename to cmd/teams/members_unassign.go index 57162eede..0e0eb4b15 100644 --- a/cmd/cycloid/teams/members_unassign.go +++ b/cmd/teams/members_unassign.go @@ -5,12 +5,12 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" - "github.com/cycloidio/cycloid-cli/internal/ptr" "github.com/cycloidio/cycloid-cli/printer" + "github.com/cycloidio/cycloid-cli/utils/ptr" ) func NewTeamMemberUnAssignCommand() *cobra.Command { @@ -44,9 +44,9 @@ func unassignTeamMember(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) - var outUnassigned = make([]*uint32, len(members)) + outUnassigned := make([]*uint32, len(members)) for i, member := range members { _, err = m.UnAssignMemberFromTeam(org, team, ptr.Value(member)) if err != nil { diff --git a/cmd/cycloid/teams/update.go b/cmd/teams/update.go similarity index 82% rename from cmd/cycloid/teams/update.go rename to cmd/teams/update.go index f6c10c630..8b1353496 100644 --- a/cmd/cycloid/teams/update.go +++ b/cmd/teams/update.go @@ -5,13 +5,13 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" - "github.com/cycloidio/cycloid-cli/internal/ptr" - "github.com/cycloidio/cycloid-cli/internal/utils" "github.com/cycloidio/cycloid-cli/printer" + "github.com/cycloidio/cycloid-cli/utils" + "github.com/cycloidio/cycloid-cli/utils/ptr" ) func NewUpdateTeamCommand() *cobra.Command { @@ -58,9 +58,9 @@ func updateTeam(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) - _, canonical, err := middleware.NameOrCanonical(ptr.Ptr(teamName), ptr.Ptr(team)) + _, canonical, err := apiclient.NameOrCanonical(ptr.Ptr(teamName), ptr.Ptr(team)) if err != nil { return fmt.Errorf("failed to infer canonical: %w", err) } diff --git a/cmd/cycloid/teams/utils.go b/cmd/teams/utils.go similarity index 84% rename from cmd/cycloid/teams/utils.go rename to cmd/teams/utils.go index 44f5330bd..d660b46fa 100644 --- a/cmd/cycloid/teams/utils.go +++ b/cmd/teams/utils.go @@ -4,15 +4,15 @@ import ( "fmt" "strconv" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" - "github.com/cycloidio/cycloid-cli/internal/ptr" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" + "github.com/cycloidio/cycloid-cli/utils/ptr" ) // anyMemberToID convert map any valid member Username or Email to its ID func anyMembersToID(org, team string, members []string) ([]*uint32, error) { api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) teamMembers, _, err := m.ListTeamMembers(org, team) if err != nil { diff --git a/cmd/cycloid/terracost/cmd.go b/cmd/terracost/cmd.go similarity index 100% rename from cmd/cycloid/terracost/cmd.go rename to cmd/terracost/cmd.go diff --git a/cmd/cycloid/terracost/common.go b/cmd/terracost/common.go similarity index 100% rename from cmd/cycloid/terracost/common.go rename to cmd/terracost/common.go diff --git a/cmd/cycloid/terracost/estimate.go b/cmd/terracost/estimate.go similarity index 87% rename from cmd/cycloid/terracost/estimate.go rename to cmd/terracost/estimate.go index 062e9cbcb..275149870 100644 --- a/cmd/cycloid/terracost/estimate.go +++ b/cmd/terracost/estimate.go @@ -6,8 +6,8 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" @@ -40,7 +40,7 @@ func estimate(cmd *cobra.Command, args []string) error { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) res, _, err := m.CostEstimation(org, plan) return cyout.PrintWithOptions(cmd, res, err, "unable to estimate terraform plan file", printer.Options{}) } diff --git a/cmd/testutil/server.go b/cmd/testutil/server.go new file mode 100644 index 000000000..ab509a9b7 --- /dev/null +++ b/cmd/testutil/server.go @@ -0,0 +1,109 @@ +package testutil + +import ( + "bytes" + "encoding/json" + "net/http" + "net/http/httptest" + "strings" + "testing" + + "github.com/spf13/cobra" + "github.com/spf13/viper" + + clicmd "github.com/cycloidio/cycloid-cli/cmd" +) + +// Route defines a canned HTTP response for a given method+path. +type Route struct { + Method string + Path string + Status int + Response any + HandleFunc http.HandlerFunc +} + +// CannedServer creates an httptest.Server that serves canned JSON responses +// for the given routes. Unmatched routes return 404. +func CannedServer(t *testing.T, routes []Route) *httptest.Server { + t.Helper() + + mux := http.NewServeMux() + for _, r := range routes { + r := r + pattern := r.Method + " " + r.Path + mux.HandleFunc(pattern, func(w http.ResponseWriter, req *http.Request) { + if r.HandleFunc != nil { + r.HandleFunc(w, req) + return + } + w.Header().Set("Content-Type", "application/vnd.cycloid.io.v1+json") + w.WriteHeader(r.Status) + if r.Response != nil { + json.NewEncoder(w).Encode(r.Response) + } + }) + } + + srv := httptest.NewServer(mux) + t.Cleanup(srv.Close) + return srv +} + +// initViper re-applies the global viper configuration that root.go's init() +// normally sets up. This must be called after viper.Reset() to restore env-var +// mapping and defaults so that CY_* environment variables and flag bindings +// work correctly in tests. +func initViper() { + viper.SetEnvPrefix("CY") + viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_")) + viper.AutomaticEnv() + viper.SetDefault("console_url", "https://console.cycloid.io") +} + +// RunCLI executes a CLI command against the given test server and returns +// its stdout output and error. It sets up a fresh root command with +// --api-url pointing at the test server and the provided args. +func RunCLI(t *testing.T, serverURL string, args ...string) (string, error) { + t.Helper() + + // Reset viper to avoid state leaking between tests, then re-apply the + // global configuration that root.go's init() normally provides. + viper.Reset() + initViper() + + rootCmd := clicmd.NewRootCommand() + + stdout := new(bytes.Buffer) + stderr := new(bytes.Buffer) + rootCmd.SetOut(stdout) + rootCmd.SetErr(stderr) + rootCmd.SetArgs(append([]string{"--api-url", serverURL}, args...)) + + err := rootCmd.Execute() + return stdout.String(), err +} + +// RunCLIWithSetup is like RunCLI but allows customizing the root command +// before execution (e.g., to set flags or inject environment). +func RunCLIWithSetup(t *testing.T, serverURL string, setup func(cmd *cobra.Command), args ...string) (string, error) { + t.Helper() + + viper.Reset() + initViper() + + rootCmd := clicmd.NewRootCommand() + + stdout := new(bytes.Buffer) + stderr := new(bytes.Buffer) + rootCmd.SetOut(stdout) + rootCmd.SetErr(stderr) + rootCmd.SetArgs(append([]string{"--api-url", serverURL}, args...)) + + if setup != nil { + setup(rootCmd) + } + + err := rootCmd.Execute() + return stdout.String(), err +} diff --git a/cmd/cycloid/uri/cmd.go b/cmd/uri/cmd.go similarity index 100% rename from cmd/cycloid/uri/cmd.go rename to cmd/uri/cmd.go diff --git a/cmd/cycloid/uri/expand.go b/cmd/uri/expand.go similarity index 96% rename from cmd/cycloid/uri/expand.go rename to cmd/uri/expand.go index 9e728bf17..f17785817 100644 --- a/cmd/cycloid/uri/expand.go +++ b/cmd/uri/expand.go @@ -14,7 +14,7 @@ import ( // RecurseFS will walk through each paths excluding paths that matches // all the ignores patterns. This function is ment to process the paths // for commands that uses --recurse and --ignore flags. -func RecurseFS(paths []string, ignores []string) ([]string, error) { +func RecurseFS(paths, ignores []string) ([]string, error) { var result []string var outErr error diff --git a/cmd/cycloid/uri/get.go b/cmd/uri/get.go similarity index 100% rename from cmd/cycloid/uri/get.go rename to cmd/uri/get.go diff --git a/cmd/cycloid/uri/interpolate.go b/cmd/uri/interpolate.go similarity index 96% rename from cmd/cycloid/uri/interpolate.go rename to cmd/uri/interpolate.go index 2761cd03b..7f92d7b33 100644 --- a/cmd/cycloid/uri/interpolate.go +++ b/cmd/uri/interpolate.go @@ -9,7 +9,7 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyargs" "github.com/cycloidio/cycloid-cli/interpolator" "github.com/cycloidio/cycloid-cli/interpolator/parsers" @@ -79,7 +79,7 @@ func interpolate(cmd *cobra.Command, args []string) error { // Ensure the target dir is created if targetDir != "" { - err = os.MkdirAll(targetDir, 0750) + err = os.MkdirAll(targetDir, 0o750) if err != nil { return fmt.Errorf("failed to create target directory %q: %w", targetDir, err) } @@ -151,7 +151,7 @@ func interpolate(cmd *cobra.Command, args []string) error { target = filepath.Join(targetDir, filepath.Base(filename)) } - err = os.WriteFile(target, []byte(out+"\n"), 0640) + err = os.WriteFile(target, []byte(out+"\n"), 0o640) if err != nil { return fmt.Errorf("failed to write file %q in dir %q: %w", filename, targetDir, err) } diff --git a/cmd/cycloid/version.go b/cmd/version.go similarity index 75% rename from cmd/cycloid/version.go rename to cmd/version.go index e50e48187..ee8cfee27 100644 --- a/cmd/cycloid/version.go +++ b/cmd/version.go @@ -1,16 +1,16 @@ -package cycloid +package cmd import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/internal/cyout" "github.com/cycloidio/cycloid-cli/printer" ) func NewVersionCmd() *cobra.Command { - var cmd = &cobra.Command{ + cmd := &cobra.Command{ Use: "version", Args: cobra.NoArgs, Short: "Get the version of the consumed API", @@ -25,7 +25,7 @@ func NewVersionCmd() *cobra.Command { func getVersion(cmd *cobra.Command, args []string) error { api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) d, _, err := m.GetAppVersion() return cyout.PrintWithOptions(cmd, d, err, "unable to get API version", printer.Options{}) diff --git a/compose.yml b/compose.yml deleted file mode 100644 index 9d68f61a7..000000000 --- a/compose.yml +++ /dev/null @@ -1,536 +0,0 @@ -services: - # Override API service to create an API from a builded docker image. - youdeploy-api: - image: rg.fr-par.scw.cloud/cycloidio/cycloid-backend:${BACKEND_TAG:-staging} - healthcheck: - test: - - "CMD-SHELL" - - | - test \ - "$(curl -s http://localhost:3001/status \ - | jq -r '.data.checks | map(select((.canonical | contains("database", "pipeline", "secret")) and .status == "Success")) | length' \ - )" = "3" - start_period: 5s - interval: 3s - timeout: 45s - retries: 30 - - ports: - - 3001:3001 - ulimits: - nproc: 65535 - nofile: - soft: 20000 - hard: 40000 - - working_dir: /go/src/github.com/cycloidio/youdeploy-http-api - configs: - - source: youdeploy-config.yml - target: /ci/config.yml - entrypoint: - - bash - - -ec - - | - echo -e "# \e[33mDB migrate ...\e[0m" - timeout 120 bash -c ' - until /go/youdeploy-http-api migrate up --config-file /ci/config.yml --migrations-dir /opt/migrations --db-name=youdeploy_fake && echo "ok"; do - >&2 echo -e "\e[36mWaiting for DB migrations\e[0m" - sleep 1 - done - ' - - echo -e "# \e[33mRunning Cycloid API ...\e[0m" - exec /go/youdeploy-http-api server --config-file /ci/config.yml - - networks: - - cycloid - - depends_on: - database: - condition: service_healthy - redis: &service_started - condition: service_started - concourse-web: *service_started - concourse-db: *service_started - - ## Mysql - database: - restart: always - image: mysql:9.3.0 - platform: linux/x86_64 - configs: - - source: my.cnf - target: /etc/my.cnf - environment: - MYSQL_ROOT_PASSWORD: youdeploy - MYSQL_DATABASE: youdeploy - healthcheck: - test: ["CMD", "mysqladmin", "ping", "-h", "database", "-P3306", "-p=${MYSQL_ROOT_PASSWORD:-youdeploy}"] - start_period: 5s - interval: 1s - timeout: 30s - retries: 30 - tmpfs: [/var/lib/mysql] - networks: - - cycloid - - ## Email - email-smtp-no-tls-auth: - image: axllent/mailpit:v1.27.3 - attach: false - restart: always - environment: - MP_SMTP_AUTH: admin:admin - MP_SMTP_AUTH_ALLOW_INSECURE: "1" - networks: - - cycloid - - ## Vault - vault: - image: hashicorp/vault:1.19 - restart: always - configs: [policy.hcl] - environment: - VAULT_DEV_ROOT_TOKEN_ID: root_token - VAULT_ADDR: http://0.0.0.0:8200 - VAULT_TOKEN: root_token - cap_add: [IPC_LOCK] - tmpfs: [/vault/file] - networks: - - cycloid - - # Override vault entrypoint adding a post script to init our approles - vault-init: - image: hashicorp/vault:1.19 - configs: [policy.hcl] - tmpfs: [/vault/file] - depends_on: [vault] - environment: - VAULT_ADDR: "http://vault:8200" - VAULT_TOKEN: root_token - VAULT_SKIP_VERIFY: true - entrypoint: - - sh - - -ec - - | - # This script must be idempotent - until vault login "$${VAULT_TOKEN:?}" ; do - >&2 echo -e "Waiting for Vault..." - sleep 1 - done - - vault auth enable approle || true - vault write sys/mounts/cycloid type=kv >/dev/null 2>&1 || true - vault write sys/policy/cycloid policy=@policy.hcl >/dev/null 2>&1 - vault write auth/approle/role/cycloid token_ttl=20m token_max_ttl=1h policies=cycloid >/dev/null 2>&1 - vault write auth/approle/role/cycloid/role-id role_id=custom-role-id >/dev/null 2>&1 - vault write auth/approle/role/cycloid/custom-secret-id secret_id=custom-secret-id >/dev/null 2>&1 || true - - networks: - - cycloid - - - redis: - image: redis:8.0.2 - command: - # Port 6379 defaults to TLS, change ports to keep tests pass - - --port - - "6379" - - --tls-port - - "6383" - # Provide self-signed certificate to REDIS TLS - - --tls-ca-cert-file - - /etc/redis/tls/cert - - --tls-cert-file - - /etc/redis/tls/cert - - --tls-key-file - - /etc/redis/tls/key - - --tls-auth-clients - - no - # Configuration Environment for REDIS with self-signed TLS - # Didn't found anything for that - # - ALLOW_EMPTY_PASSWORD=true - configs: - - source: redisTLSCert - target: /etc/redis/tls/cert - - source: redisTLSKey - target: /etc/redis/tls/key - tmpfs: [/data] - networks: - - cycloid - - - git-server: - image: cycloid/backend-tests-git-server:latest - attach: false - restart: always - networks: - - cycloid - tmpfs: - - /git-server/repos:exec - - /git-server/keys - - ## Concourse - concourse-db: - image: postgres:17 - attach: false - environment: - POSTGRES_DB: concourse - POSTGRES_USER: concourse - POSTGRES_PASSWORD: concourse - # warning: starting at version 18, change this path to /var/lib/postgresql - tmpfs: [/var/lib/postgresql/data] - networks: - - cycloid - - concourse-web: - image: concourse/concourse:7.9.1 - links: [concourse-db] - command: web - depends_on: [concourse-db, vault, vault-init] - attach: false - networks: - - cycloid - configs: - - source: base_resource_types_defaults.yml - target: /brt/base_resource_types_defaults.yml - - source: authorized_worker_keys - target: /concourse-keys/authorized_worker_keys - - source: session_signing_key - target: /concourse-keys/session_signing_key - - source: session_signing_key.pub - target: /concourse-keys/session_signing_key.pub - - source: tsa_host_key - target: /concourse-keys/tsa_host_key - - source: tsa_host_key.pub - target: /concourse-keys/tsa_host_key.pub - restart: unless-stopped # required so that it retries until concourse-db comes up - environment: - CONCOURSE_ADD_LOCAL_USER: concourse:concourse - CONCOURSE_MAIN_TEAM_LOCAL_USER: concourse - CONCOURSE_BIND_PORT: 8080 - # Important CF https://github.com/concourse/concourse/issues/2463 "error : named cookie not present" - CONCOURSE_EXTERNAL_URL: "http://localhost:8080" - CONCOURSE_POSTGRES_HOST: "concourse-db" - CONCOURSE_POSTGRES_USER: concourse - CONCOURSE_POSTGRES_PASSWORD: concourse - CONCOURSE_POSTGRES_DATABASE: concourse - CONCOURSE_BASE_RESOURCE_TYPE_DEFAULTS: /brt/base_resource_types_defaults.yml - CONCOURSE_VAULT_URL: "http://vault:8200" - CONCOURSE_VAULT_AUTH_BACKEND: token - CONCOURSE_VAULT_CLIENT_TOKEN: root_token - CONCOURSE_VAULT_PATH_PREFIX: /cycloid - CONCOURSE_VAULT_AUTH_BACKEND_MAX_TTL: 3600s - CONCOURSE_CLUSTER_NAME: dev - - ## Plugin registry (docker image store for plugins) - docker-registry: - image: registry:3.0.0 - ports: - - "${DOCKER_REGISTRY_HOST_PORT:-5000}:5000" - volumes: - - ./docker/auth:/auth - environment: - REGISTRY_AUTH: htpasswd - REGISTRY_AUTH_HTPASSWD_REALM: cycloid - REGISTRY_AUTH_HTPASSWD_PATH: /auth/htpasswd - networks: - - cycloid - - ## Plugin registry service - plugin-registry: - image: cycloid/plugin-registry:latest - environment: - PORT: "4000" - DB_HOST: database - DB_PORT: "3306" - DB_USER: root - DB_PASSWORD: youdeploy - DB_NAME: registry_develop - REDIS_URI: redis://redis:6379 - ORGS_CANS: cycloid - CY_URL: http://youdeploy-api:3001 - REGISTRY_URI: docker-registry:5000 - REGISTRY_USERNAME: cycloid - REGISTRY_PASSWORD: cycloid123 - RUN_MIGRATIONS: "true" - privileged: true - networks: - - cycloid - depends_on: - database: - condition: service_healthy - youdeploy-api: - condition: service_healthy - - ## Plugin manager service - plugin-manager: - image: cycloid/plugin-manager:latest - ports: - - "${PLUGIN_MANAGER_HOST_PORT:-4000}:4000" - environment: - LOG_LEVEL: debug - PORT: "4000" - DB_HOST: database - DB_PORT: "3306" - DB_USER: root - DB_PASSWORD: youdeploy - DB_NAME: manager_develop - REDIS_URI: redis://redis:6379 - CY_URL: http://youdeploy-api:3001 - CY_TOKEN_SECRET: local-test-secret - ORGS_CANS: cycloid - ADMIN_USERNAME: cycloid - ADMIN_PASSWORD: cycloid123 - RUN_MIGRATIONS: "true" - PLUGIN_MANAGER_NAME: test-plugin-manager - PLUGIN_MANAGER_BASE_URL: http://plugin-manager:4000 - privileged: true - networks: - - cycloid - depends_on: - database: - condition: service_healthy - youdeploy-api: - condition: service_healthy - -configs: - ## Mysql - my.cnf: - content: | - [client] - default-character-set = utf8mb4 - - [mysql] - default-character-set = utf8mb4 - - [mysqld] - collation_server = utf8mb4_unicode_ci - character_set_server = utf8mb4 - - ## Concourse - base_resource_types_defaults.yml: - content: | - registry-image: - registry_mirror: - host: 'registry-mirror.owl.cycloid.io' - - docker-image: - registry_mirror: 'https://registry-mirror.owl.cycloid.io' - - authorized_worker_keys: - content: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDo7QaU+1NrYGhiE6XDnkcWYP5w/rUt32VnFemo9XyX8sPUcQwMOh+xVwlqLlSlNZGeZ7zWY+eopR+T9Un5tFILjSpsx83t8fTHBYwno2m0kHw5EixIJY3S6wBs4gm8D2IRHLjT0GDcv39sgfug4PnpIDK/WFLJrJaVbQrMpJ03tm7LjpCWk+uL3gmkU8pglNWehPcGM3KEmlgUVIsAiNXJKYEGPVSrD8TmebaNygwELV9rjuxQcmmYGhJRl01S5mZvfVs7Xj0jW6vBUZHcNkKAjHUOjS4ag1NEr5mA1SRgVKCEGlF0PpQyxgHeYW9pa05iMl1XZpGIC08up1sktNZH ugo@dragonfly - - session_signing_key: - content: | - -----BEGIN RSA PRIVATE KEY----- - MIIEpQIBAAKCAQEA96VDmpRMpzaKl7D1FYsbQLi9jFr2J0EY1MPhvxM4vg8RhgXj - cunyepk3g2ZFFzhR6H9i/p17naDSN99eTl5MGS2HDaqZ8BLAoK/oZx7JLnAkWLIm - QPRfiERQmtUmmVYfdUHeJ7oSQuLuCop/5WUoPSHuqFqqc+uEixQAoF3i0ASRLmS9 - QQg5ZKTAu3ah9j4y8SMWOcKIYe9pg1PcK9HIw6AjknyFyG5rEIylJy/6AWqekavd - filc1JZ8BEBGO4K+4dkXU8Z7RA4MPGA2HpKQBiz0aQCjeJg+BFmpQK1RVMSVYF2b - URQd7fO3mH7OfO+mtARrRDdivgWVEYI0D8x7DQIDAQABAoIBAQDHP2+iGnmF+8sM - ezLlb3Ow4jKXj8QHF0gcP7IM4zE/Ma5+r5Qtq+8NFuNkVE94fDbiokOK6jhAPdmF - XLFqylHd3BSSOVX7o4rafk21Uj65nz6PIl7G2hdW8ugLez3AF1veIu3T9tCkgiLV - 1lNKxNXYQcncKH6GH9MXdzN906wegkkCOzBkg4QJx/HIuzSHBzlqlfEKfPYonAF1 - PmTDR36rqPE9NUBao7NkxZKWAMfXCWYOPrK5yyNNN0PEfXML9s5ddD/79UbvBXtV - byY3bNpfWRXvEhhjLQ2qihxKJzvvBEFPgTcXbCevoImSiI/4XN/Bs5wD4+PYuS3S - 4DkcHzx9AoGBAP37gUzCFrd9/l+D3aWgRqC1OA3IQAbf01S9lGHpoxqRASZFYzwj - ph9X4JAy4/pR+1/MAxc/1dKNS6V53IFdwOH8qmsyrIyokGJW59dwaNd+Vx3LO812 - yKE5W4aSH3b9Eh7nYuJ3Q3Ag3W6QnOe8+F5EvBg05g2etV/eZkmO5TmvAoGBAPmc - 31a6Fm1X6aDvmkfdNuIfzQzb/+hiGYvnT7cS8ljyo4KNFx/cqdDbrVAzuw7Ws2PE - 37u4Ywqv4FQvRk5h6pNOeZBN4Liahw5vNF9KDWDUI6ruHAjd66ucx2fejtVMB5RM - T4qGq/5waJsdOXMKaxgHBPKs+ZqLyK1tzlGD+ZIDAoGBAIgbrTomVSg2ZAhp0XE+ - CDt9gjGYm/9TGZyzD/68x0SoarZIvxpufEsVu+lq7FOsdYrr+MgP1JXGVMC0IqBN - Tt2MmwNhn6iteNrKeeoxem3pbeQwkrbULkaAR3VBf40zp+9ZzttQUJqZcjEbXIqv - 8WYLbcWHK7Ym1EoxFB3dbyhPAoGAVc6QlB66UPJUtOdJEQVBtbAa7B3AtiDrCUYG - CDgyKVOX0+wuk9xmYA70YEq4NhymZFisVLrJCUZ2hloOACn22paygWHUK4GrhdHC - njM1sCCc9kiOSJoJRuBJSDKgxUAyps8o1MUA4SHBQ/li42IkeIkJMWc3EuKUpNHH - iAwnQgMCgYEA2eAOj9kRZE0nC2aXeU/EbhSHNVuz7OBvROMJMmYBb9DQxw5g1vcV - Df2ty+b+5eIl6mivv4dmp2D1YLyYyUXkI/ccfZ7fmQrjKdWywKTlTP2G+rklCSHk - N9aORmeB+s3V4c5lRHYslRevdIOxSd/H0Z45T8s/bEMojozG3swrXSc= - -----END RSA PRIVATE KEY----- - - session_signing_key.pub: - content: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQD3pUOalEynNoqXsPUVixtAuL2MWvYnQRjUw+G/Ezi+DxGGBeNy6fJ6mTeDZkUXOFHof2L+nXudoNI3315OXkwZLYcNqpnwEsCgr+hnHskucCRYsiZA9F+IRFCa1SaZVh91Qd4nuhJC4u4Kin/lZSg9Ie6oWqpz64SLFACgXeLQBJEuZL1BCDlkpMC7dqH2PjLxIxY5wohh72mDU9wr0cjDoCOSfIXIbmsQjKUnL/oBap6Rq91+KVzUlnwEQEY7gr7h2RdTxntEDgw8YDYekpAGLPRpAKN4mD4EWalArVFUxJVgXZtRFB3t87eYfs5876a0BGtEN2K+BZURgjQPzHsN ugo@dragonfly - - tsa_host_key: - content: | - -----BEGIN RSA PRIVATE KEY----- - MIIEowIBAAKCAQEAtDaLAcvpkR79VL5M3BtYHUm1rJUSwvNGn0JxBFvjzG+Ni/pv - QUJ9n+CYTNVcmEcB4t0hMTNsrEp1kn1L8QWMC0oQAB796rgHp2kV87UmJuth4ezY - THwp2dvC/ITZ6dn3GSV6koWBEhdC8cNUtS4Zvzq/IQptLVC9twIGM6IlH8WTgTVS - 88MbXJtrzOU5eNgxIxn+FHoh8QHT1CW1FuKdJN0XKP+HPiqzaNb+LcyuEl3bVtoQ - uaGEKT8/QuPLNuq/PzASwu+Kj/7U51BTlNAnLHDtS4m1xI43QLMrE5Uk9KbbCi9a - C/lsR26+pLt9fqevUyOc5KiiTud0OuySLTdbsQIDAQABAoIBACdT19YWh+wxlRtP - RDqshPgvQ8Rb6/I7YOgUedF3tCjDF2K6zlixh/TB8LqjvUdGB7VYiIvSKx8WSL4l - NdNtYHh+Oyurl8IHUzRHjJDYsXDA4WWKaFGYrxFqEg1FeMC93lzQfwVGuToXdXaJ - KA05+EhxK5CsU9MV0bEEchIGio96EmR9IWWKIfgUg597momwfeNyUKOxNJu/9rJP - dUFl2YuC5UDCGHPB7KKxTfw/mFOcXRp7/ARtzSuYIDlECRGGZKBuw81tgmZhsqsJ - yTZQ0wlI51d36xswciloxWqC/z+h8HsSpooqyqAaPsy+94W3dB9zA5lwws9bFfAi - Di3Nc5kCgYEA69DZNsqLljoa2pdfM28dMbIAIfJ/rMBj3kcH2DokWR963zJHw4Tz - k7LXr6IkeWpMD1c/LHFf0/j6FMajo/dRIzJj98UHYIT2NnVa0dNn5uCXkcxSg6p4 - CfyzRMsaW8/qBIx2n6hiK+0rdnaTeOyDtRUq/3dWdeXCBywt0AdnewsCgYEAw6NW - Ylnphb1TNwft4Gz7sctiB46Yiqb+pRHbdohqlgxkddS4YyPRjfYdXbJT42gVgdfZ - NYn8tdsLfylMmv691ewoyQtFtemYcPeNr0pNfCaMIJnBjJ5D52yLG5nYAtcs4yVZ - VIaUH2a9vB26igSb3zKREJ7le4+GWNhUm7Ow2bMCgYEAhq5TQL3Rl008RRgrIT8W - 12koNjs/vDRtVWgQDOi4Fcaq8IrQ/dQTIYoFMaRTXJzfL+vOgt2Fs5UBj5gboewA - hS+kdMAtBG0sCdJgunIZZ31iU7z0a4qS4HFZGbM+LK3EpDBtF6ad2ySrrA7xDyFV - 37hlRF6uHMvKUzpiN+viqB0CgYBUY+rpdfuD001IGcWE374aza61r88hUDPcJL3U - fbfsjd/v7Bi1u0ezwwyb1EbXe5h7cA6kR6eZEqn86mW/Hk/pLXvSbWhetisp379g - c97ExSQBFBInhEWqWGoRN+W0I/ma6guEqKDQgtMpiHFlA+Pw/bERyFkZWaoMPRUS - LQsGfQKBgAdWOVC6Nk3gO1T6r2Lmy2mFD++g/+pmEnPVH9snsNJmh9aw4f9lptHA - H3Q8JR44XozKfo/874Uv5q1BoWyD0vC8mhZoDiwsJ0M1LWXS4CIKVS3gkj2mLpoE - Xpwf1oIKDxZfiIxWtGLbQj1aMclohJ2qvzuNnx6YnASKVHw25EUg - -----END RSA PRIVATE KEY----- - - tsa_host_key.pub: - content: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC0NosBy+mRHv1UvkzcG1gdSbWslRLC80afQnEEW+PMb42L+m9BQn2f4JhM1VyYRwHi3SExM2ysSnWSfUvxBYwLShAAHv3quAenaRXztSYm62Hh7NhMfCnZ28L8hNnp2fcZJXqShYESF0Lxw1S1Lhm/Or8hCm0tUL23AgYzoiUfxZOBNVLzwxtcm2vM5Tl42DEjGf4UeiHxAdPUJbUW4p0k3Rco/4c+KrNo1v4tzK4SXdtW2hC5oYQpPz9C48s26r8/MBLC74qP/tTnUFOU0CcscO1LibXEjjdAsysTlST0ptsKL1oL+WxHbr6ku31+p69TI5zkqKJO53Q67JItN1ux ugo@dragonfly - - ## Vault - policy.hcl: - content: | - path "cycloid/*" { - capabilities = ["create", "read", "update", "delete", "list"] - } - - path "sys/policy/cycloid/*" { - capabilities = ["create", "read", "update", "delete", "list"] - } - - path "auth/approle/role/cycloid-*" { - capabilities = ["create", "read", "update", "delete", "list"] - } - - path "auth/approle/role/" { - capabilities = ["read", "list"] - } - - path "policies" { - capabilities = ["read", "list"] - } - - path "auth/token/create" { - capabilities = ["create"] - } - - path "auth/token/renew-self" { - capabilities = ["create"] - } - - youdeploy-config.yml: - content: | - start-timeout: 10s - max-header-size: "1MB" - port: 3001 - host: 0.0.0.0 - schema: - - http - cleanup-timeout: 1ms - - log-dev-mode: false - log-level: "INFO" - log-svc-level: "INFO" - - db-host: database - db-port: 3306 - db-user: root - db-pwd: youdeploy - db-name: youdeploy - db-max-conns: 15 - db-max-idle-conns: 10 - db-max-lifetime-conn: 5m - - concourse-url: "http://concourse-web" - concourse-port: 8080 - concourse-username: concourse - concourse-password: concourse - concourse-team: main - - vault-role-id: custom-role-id - vault-secret-id: custom-secret-id - vault-url: "http://vault:8200" - - frontend-base-url: "http://localhost:3000" - backend-base-url: "http://youdeploy-api:3001" - - redis-uri: "redis://redis:6379" - - email-smtp-svr-addr: "email-smtp-no-tls-auth:1025" - email-smtp-username: admin - email-smtp-password: admin - email-addr-from: "Cycloid Platform " - email-addr-return-path: "admin+ydbounce@cycloid.io" - email-dev-mode: true - crypto-signing-key: totally-random-secret-key - jwt-keys: - - 2f2122de-63f2-4eec-9c6f-c6abb3e1f007:7cdyHps2tYDp6e7VKPEstE5sDMQbK6WLyN3GmTsF7x7QpE6ZP5ra6yfVSkvXakbB - local-auth-enabled: true - - contact-us-form-url: https://www.cycloid.io/contact-us - tell-us-why-licence-form-url: https://www.cycloid.io/contact-us - - worker-queues: [emails,hubspot,cost_explorer,checks,terracost] - worker-run-internal: true - worker-run-scheduler: true - - redisTLSCert: - content: | - -----BEGIN CERTIFICATE----- - MIID1TCCAr2gAwIBAgIUDFcFTeEQSIK32cpl5/Ca4gxgAKowDQYJKoZIhvcNAQEL - BQAwgZIxCzAJBgNVBAYTAkZSMQ4wDAYDVQQIDAVQYXJpczEOMAwGA1UEBwwFUGFy - aXMxFDASBgNVBAoMC0N5Y2xvaWQgU0FTMRAwDgYDVQQLDAdCYWNrZW5kMRYwFAYD - VQQDDA1MbGFtYSBEZWwgUmV5MSMwIQYJKoZIhvcNAQkBFhRjeWNsb2lkaW9AY3lj - bG9pZC5pbzAeFw0yNTAxMjkxNzA3NTZaFw0yNTAyMjgxNzA3NTZaMIGSMQswCQYD - VQQGEwJGUjEOMAwGA1UECAwFUGFyaXMxDjAMBgNVBAcMBVBhcmlzMRQwEgYDVQQK - DAtDeWNsb2lkIFNBUzEQMA4GA1UECwwHQmFja2VuZDEWMBQGA1UEAwwNTGxhbWEg - RGVsIFJleTEjMCEGCSqGSIb3DQEJARYUY3ljbG9pZGlvQGN5Y2xvaWQuaW8wggEi - MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCbqtopbLmkSf1My6SPuAZcd0rP - mF33XxQb3/DM0lf0HIiBy9gyaVBTvZvceIxWnUb72qHir8x52CFei9mSLUY30uVK - labtTwTWmaE7bylp2NGucRsB88u2SCkmepkaYugLppD908Ua9+PCQVrC34PGnIMG - ZjxhNtDBq/jqDoRpBuK0XwHuvQPvFWaX2OV73cHgFwtKrDdwuuhR/HLQwXwP9tts - wDGn0Lfr1bET0yztpeMz55SJLFcCOMn0/vfELLEIgegHOSRDAslJpAybcHDXtMUW - LGNZ/UXp28LVWJdNcqIKTGfsXL9R6bNfD4If3ukJwXB/DR0BquTrZK2oKxRzAgMB - AAGjITAfMB0GA1UdDgQWBBTo2BtkBMqcNKkwmKGTk02dgyTObTANBgkqhkiG9w0B - AQsFAAOCAQEAVASa88dwuyI6tNyvJGusynBW7gqcOtr+AmYTBDdSulkblaAbcSjQ - jEYS1dZDCzLb35mZVDcs/z3E4ZFtaXjBERrxa5sRfOqHpYPT5jx4LFP/LS+XIpqa - psX6rSmdO84sc14D4xXlewZ6CnA2NNSqkJbxxoTm0mqd/MV9kKXHXkKgKDOeWM3U - roLaJZq5QDukVrMGPUQS6D9pSrTj0oZgxnN0r5o+xy6FMVXK0vJej6x5LH7/i1nk - 3omuCMM6iZSNbMotlK0jy5QPP1g+i+JX2PawFv0rZIDj4NfDBxHt4BIOToyZSrZa - RUwxOeyu4/4XTbtxnIMJwv0avllw2wpVUQ== - -----END CERTIFICATE----- - - redisTLSKey: - content: | - -----BEGIN PRIVATE KEY----- - MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCbqtopbLmkSf1M - y6SPuAZcd0rPmF33XxQb3/DM0lf0HIiBy9gyaVBTvZvceIxWnUb72qHir8x52CFe - i9mSLUY30uVKlabtTwTWmaE7bylp2NGucRsB88u2SCkmepkaYugLppD908Ua9+PC - QVrC34PGnIMGZjxhNtDBq/jqDoRpBuK0XwHuvQPvFWaX2OV73cHgFwtKrDdwuuhR - /HLQwXwP9ttswDGn0Lfr1bET0yztpeMz55SJLFcCOMn0/vfELLEIgegHOSRDAslJ - pAybcHDXtMUWLGNZ/UXp28LVWJdNcqIKTGfsXL9R6bNfD4If3ukJwXB/DR0BquTr - ZK2oKxRzAgMBAAECggEACAdDwScuW97FBZTrI85l5ZbxcMt27S8mJlniXW3rw1dF - YwxUViVAU1FQHIrLEhyCcLLR7pMKhK406l9kFTnoiTCDStl1BoAwy7CYtCwDgsX/ - 6nNC5VLhisEl/ioMg2Pee9tXVv/5Bm8KfBZKzAojDbc8urPDIXBmS9bGu6uMAK6Z - mZgGNU23CxcMF0qHiIBaXbrc26Ud+yqxdoFpalMRD1PZE9o7BLdUj8WBrVM5uBRY - 2Tn1bIOjDSszfs+7j2zvEWNLbS/MaYJ+qyWIg/SIQ5kjTIqraL/IBnSSvz1cySir - OK1jwO7hPqvrjwaxH2sV/U+uJa/sO+yDVsYq4VUEIQKBgQDUDp014UeWEVJzvbOO - 2J8BovSN63K7S6Dj2vOhLPqet3/pnSemmRxZHlhuH1Pt+EkpjajpLf6mbWKICKQ/ - XHrjlcEe4cwjkZjlxgIwWopoXQeWh8+gOyJ6EOo5dfeObiGnMVjpjX1TExXdLbGH - n5iSEs/3+ooa7aBngqCskGrULQKBgQC77NRK5EMcnMUhojP4MCElknnZSAzTra9U - DWMbR1aDfQ3JikVQqozjkQs9SY9gCJhWdne6URm6Nw1YfiLL27C0bgedyWKUvZ1g - 0JGGtNozfUwEA8Lc6oEP1/1CzCIEcKBTgyrnBLHQaD6cteR7GUDHopgjle0zeN6d - 4TqjhDfPHwKBgBlQEUYQOSpZsPzt5RQlGX3phMW4GD7xPShVx4UyyEvP3a32O3hw - iGi+7ZFfnfYnEByssz/6ZI5bOkrAtVJ26JhoFOBp1aNdSuIKq9I3zJO+nxxB4+/d - fzUQ9dScF0viK5Q4mMNwR0h2W8LGJI3q6BxvsHGKb5fdS6tvdVyD9KyVAoGAQM96 - n6F9a769Vc4k8jFXHSgZEdCBa/d4ghpj1aKSuaJFQP6IzTskf88j+y0FX29XampM - /Fq/7rLRzXUi9v97P566zbYIY5fJUPxdVAHHRv6tWq0ZZSsS+63X0FOqX7Gf+W1B - PI8n6+InxdANTk71QmRW597rAVdsHzLwEDinLq0CgYBeUrIVRQDYRqmSiI0JRXk7 - Xn0Dx1J5cpYpCQADo6jdddcHZQsOfVqGFIq2sn/omi+Xyq/N7I5bbm09jNwtf3Zi - cPJlbRttQ1YxFH4KzMOdzeh2jKF8uNXW211Adk/VXNqlN95Ky4kSm7Lrpy92+uux - pVy90/uiPe/6CsFk7ceoDA== - -----END PRIVATE KEY----- - -networks: - cycloid: {} - diff --git a/config/config.go b/config/config.go index e40e4bc7a..99ca6f5b6 100644 --- a/config/config.go +++ b/config/config.go @@ -5,7 +5,6 @@ import ( "os" "github.com/adrg/xdg" - "github.com/pkg/errors" "gopkg.in/yaml.v3" ) @@ -14,68 +13,60 @@ var ( path = "config.yaml" ) -// Config is the structure handling the config -// of the CLI +// Config handles the CLI configuration type Config struct { - // Organizations is the list of Organization where the user - // is currently logged in Organizations map[string]Organization `yaml:"organizations"` - // Output is the default output format (e.g. "table", "json", "table:border"). - // Overridden by CY_OUTPUT env var or the --output / --jq flags at runtime. - Output string `yaml:"output,omitempty"` + Output string `yaml:"output,omitempty"` } -// Organization is an organization where the user -// is logged in +// Organization represents a logged-in organization session type Organization struct { - // Organization token Token string `yaml:"token"` } func GetConfigPath() (string, error) { configFilePath, err := xdg.ConfigFile(fmt.Sprintf("%s/%s", appName, path)) if err != nil { - return "", err + return "", fmt.Errorf("invalid config: unable to find XDG config path: %w", err) } return configFilePath, nil } -// Read will read the config from the -// path and returns a config struct +// Read reads the config from the XDG path and returns a Config struct func Read() (*Config, error) { configFilePath, err := xdg.ConfigFile(fmt.Sprintf("%s/%s", appName, path)) if err != nil { return &Config{ Organizations: make(map[string]Organization), - }, errors.Wrap(err, "unable to find XDG config path") + }, fmt.Errorf("invalid config: unable to find XDG config path: %w", err) } content, err := os.ReadFile(configFilePath) if err != nil { - // we return an empty Config in case it's the first time we try to access - // the config and it does not exist yet return &Config{ Organizations: make(map[string]Organization), - }, errors.Wrap(err, "unable to read config from file") + }, fmt.Errorf("invalid config: unable to read config from file: %w", err) } var c Config if err := yaml.Unmarshal(content, &c); err != nil { - return nil, errors.Wrap(err, "unable to decode config from file") + return nil, fmt.Errorf("invalid config: unable to decode config from file: %w", err) } return &c, nil } -// Write will write the config into the -// path location +// Write writes the config into the XDG path func Write(c *Config) error { content, err := yaml.Marshal(c) if err != nil { - return errors.Wrap(err, "unable to marshal config structure") + return fmt.Errorf("invalid config: unable to marshal config structure: %w", err) } configFilePath, err := xdg.ConfigFile(fmt.Sprintf("%s/%s", appName, path)) if err != nil { - return errors.Wrap(err, "unable to find XDG config path") + return fmt.Errorf("invalid config: unable to find XDG config path: %w", err) } - return os.WriteFile(configFilePath, content, 0600) + if err := os.WriteFile(configFilePath, content, 0o600); err != nil { + return fmt.Errorf("invalid config: unable to write config file: %w", err) + } + return nil } diff --git a/docker/auth/htpasswd b/docker/auth/htpasswd deleted file mode 100644 index f62e96a31..000000000 --- a/docker/auth/htpasswd +++ /dev/null @@ -1,2 +0,0 @@ -cycloid:$2y$05$sNTvLFbEI0nZzjV3wAgpROU7kIM07zm1MtUH5RBEteXhLnknSrMH2 - diff --git a/docs/adding-a-command.md b/docs/adding-a-command.md deleted file mode 100644 index 25e4bc53c..000000000 --- a/docs/adding-a-command.md +++ /dev/null @@ -1,374 +0,0 @@ -# Adding a Command - -This walkthrough adds a hypothetical `GET /organizations/{org}/widgets/{widget}` endpoint as a concrete example. - -## 1. Find the endpoint - -Check the Cycloid API reference at https://docs.cycloid.io/api/index.html. Note: - -- The HTTP method and path -- Required vs optional parameters -- The response model name (e.g., `Widget`) - -## 2. Ensure the model exists - -Models live in `client/models/` — auto-generated from `swagger.yaml`. If the model already exists, skip this step. - -If `swagger.yaml` was updated: - -```bash -make client-generate # regenerates client/models/ and client/ from swagger.yaml -``` - -Never edit files in `client/models/` by hand. - -## 3. Add middleware interface methods (prefer idempotent flows) - -Open `cmd/cycloid/middleware/middleware.go` and add the required signatures to the `Middleware` interface. -When the resource can be managed idempotently, also expose a `CreateOrUpdateX` helper: - -```go -// cmd/cycloid/middleware/middleware.go -GetWidget(org, widget string) (*models.Widget, *http.Response, error) -CreateWidget(org string, newWidget *models.NewWidget) (*models.Widget, *http.Response, error) -UpdateWidget(org, widget string, update *models.UpdateWidget) (*models.Widget, *http.Response, error) -CreateOrUpdateWidget(org string, widget string, payload *models.NewWidget) (*models.Widget, *http.Response, error) -``` - -Return type conventions: -- Get/Create → `(*models.X, *http.Response, error)` -- List → `([]*models.X, *http.Response, error)` -- Delete/void → `(*http.Response, error)` - -## 4. Implement middleware methods - -Create or extend the feature file. Keep the category name aligned with the API docs tag/category. -For an org-scoped resource in the `Organization` category, use `organization_widgets.go`: - -```go -// cmd/cycloid/middleware/organization_widgets.go -package middleware - -import ( - "net/http" - "github.com/cycloidio/cycloid-cli/client/models" -) - -func (m *middleware) GetWidget(org, widget string) (*models.Widget, *http.Response, error) { - var result *models.Widget - resp, err := m.GenericRequest(Request{ - Method: "GET", - Organization: &org, - Route: []string{"organizations", org, "widgets", widget}, - }, &result) - if err != nil { - return nil, resp, err - } - return result, resp, nil -} - -// Prefer idempotent flows when possible: detect state, then create or update. -func (m *middleware) CreateOrUpdateWidget(org, widget string, payload *models.NewWidget) (*models.Widget, *http.Response, error) { - current, resp, err := m.GetWidget(org, widget) - if err == nil && current != nil { - update := &models.UpdateWidget{ - Name: payload.Name, - } - return m.UpdateWidget(org, widget, update) - } - if resp != nil && resp.StatusCode == http.StatusNotFound { - return m.CreateWidget(org, payload) - } - return nil, resp, err -} -``` - -Key points: -- `Organization: &org` enables auth token lookup -- `Route` segments are path-joined onto `CY_API_URL` -- `GenericRequest` unwraps `{"data": ...}` automatically; pass `&result` directly -- Return `nil, resp, err` on error so callers can inspect the HTTP response -- If no dedicated idempotent API route exists, implement idempotency in middleware (`Get`/`List` then `Create` or `Update`) - -## 5. Follow the `cmd/cycloid/teams` command pattern - -`cmd/cycloid/teams` is the reference pattern for subcommands. The important logic: - -- `cmd.go` defines the category command and wires all subcommands in one place (`AddCommand(...)`). -- Subcommands explicitly define `Args` (`cobra.NoArgs`, `cobra.MinimumNArgs(1)`, etc.) for consistent completion and UX. -- `get` and `delete` support multiple identifiers via positional args and return either one resource or a list. -- `create` supports idempotent behavior with `--update` and can update an existing resource when requested. -- Shared flag/completion logic lives in `internal/cyargs`; command files consume `cyargs.Add*Flag` / `cyargs.Get*`. -- Nested domains are modeled with nested commands (e.g. `teams members ...`). - -## 6. Add cobra command files - -Use a command directory name that matches the API docs category/tag naming. - -``` -cmd/cycloid/widgets/ - cmd.go ← registers subcommands, called from cmd/root.go - get.go ← accepts identifiers as args and/or --widget - create.go ← supports --update idempotent behavior - update.go ← can delegate to create --update flow - delete.go ← accepts one or many identifiers -``` - -```go -// cmd/cycloid/widgets/get.go -package widgets - -import ( - "fmt" - - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/pkg/errors" - "github.com/spf13/cobra" - - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" - "github.com/cycloidio/cycloid-cli/internal/cyargs" - "github.com/cycloidio/cycloid-cli/internal/cyout" - "github.com/cycloidio/cycloid-cli/printer" -) - -var widgetTableOptions = printer.Options{ - Columns: []string{"Canonical", "Name", "Description"}, - Identifier: "Canonical", -} - -func NewGetWidget() *cobra.Command { - cmd := &cobra.Command{ - Use: "get [widget_identifiers...]", - Short: "Get one or more widgets", - Args: cobra.ArbitraryArgs, - ValidArgsFunction: cyargs.CompleteWidget, - Example: ` -cy --org my-org widgets get my-widget -cy --org my-org widgets get my-widget another-widget -cy --org my-org widgets get --widget my-widget -`, - RunE: getWidget, - } - cyargs.AddOrgFlag(cmd) - cyargs.AddWidgetFlag(cmd) - cyout.RegisterModel(cmd, models.Widget{}) - return cmd -} - -func getWidget(cmd *cobra.Command, args []string) error { - // Step 1: retrieve ALL flags before NewAPI/NewMiddleware - org, err := cyargs.GetOrg(cmd) - if err != nil { - return err - } - - widget, err := cyargs.GetWidget(cmd) - if err != nil { - return err - } - - identifiers := append([]string{}, args...) - if widget != "" { - identifiers = append(identifiers, widget) - } - if len(identifiers) == 0 { - return errors.New("provide at least one widget identifier (arg or --widget)") - } - - // Step 2: build API + middleware - api := common.NewAPI() - m := middleware.NewMiddleware(api) - - // Step 3: call middleware + print - if len(identifiers) == 1 { - result, _, err := m.GetWidget(org, identifiers[0]) - return cyout.PrintWithOptions(cmd, result, err, "unable to get widget", widgetTableOptions) - } - - results := make([]*models.Widget, 0, len(identifiers)) - for _, id := range identifiers { - w, _, err := m.GetWidget(org, id) - if err != nil { - return cyout.PrintWithOptions(cmd, nil, err, fmt.Sprintf("unable to get widget %q", id), widgetTableOptions) - } - results = append(results, w) - } - return cyout.PrintWithOptions(cmd, results, nil, "", widgetTableOptions) -} -``` - -Global command directives to follow: - -- `get`: accept canonical/identifier from args and/or flag; show both styles in `Example`; multiple args return `[]*models.Widget`. -- `create`/`update`: share logic for idempotency (`create --update`); `update` should also allow creation. -- `delete`: accept canonical/identifier from args and/or flag; support multiple values; print deleted identifier(s) only. -- Shared flags/completion must live in `internal/cyargs` (except simple bool flags like `--update`, or truly command-specific flags). - -## 7. Register in `cmd.go` - -```go -// cmd/cycloid/widgets/cmd.go -package widgets - -import "github.com/spf13/cobra" - -func NewWidgetsCmd() *cobra.Command { - cmd := &cobra.Command{ - Use: "widgets", - Short: "Manage widgets", - Args: cobra.NoArgs, - } - cmd.AddCommand(NewGetWidget()) - // cmd.AddCommand(NewListWidgets()) - // cmd.AddCommand(NewCreateWidget()) - return cmd -} -``` - -Register in `cmd/root.go`: - -```go -rootCmd.AddCommand(widgets.NewWidgetsCmd()) -``` - -## 8. Add flags - -**Shared flags** (used by multiple commands) belong in `internal/cyargs/`: - -```go -// internal/cyargs/widgets.go -const widgetFlagName = "widget" - -func AddWidgetFlag(cmd *cobra.Command) string { - cmd.Flags().String(widgetFlagName, "", "Widget canonical or identifier") - _ = cmd.RegisterFlagCompletionFunc(widgetFlagName, CompleteWidget) - return widgetFlagName -} - -func GetWidget(cmd *cobra.Command) (string, error) { - return cmd.Flags().GetString(widgetFlagName) -} -``` - -**Feature-specific flags** (one command only) can be inline in the command file: - -```go -cmd.Flags().String("format", "json", "Output format for widget data") -``` - -Register shared flags in the constructor: - -```go -func NewGetWidget() *cobra.Command { - cmd := &cobra.Command{...} - cyargs.AddOrgFlag(cmd) - widgetFlag := cyargs.AddWidgetFlag(cmd) - _ = widgetFlag // Example: cmd.MarkFlagRequired(widgetFlag) when needed - return cmd -} -``` - -## 9. Write a middleware unit test - -```go -// cmd/cycloid/middleware/organization_widgets_test.go -package middleware_test - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestGetWidget(t *testing.T) { - m := NewTestMiddleware() // helper from middleware_test package - result, _, err := m.GetWidget(config.Org, "my-widget") - require.NoError(t, err) - assert.NotNil(t, result) -} -``` - -The `config` global is set up by `TestMain` in `middleware_test.go`. See `docs/testing.md`. - -## 10. Write an e2e test - -```go -// e2e/widgets_test.go -package e2e_test - -import ( - "encoding/json" - "testing" - - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestWidgets(t *testing.T) { - widgetCanonical := testcfg.RandomCanonical("test-widget") - - t.Run("SuccessWidgetCreate", func(t *testing.T) { - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "widgets", "create", - "--name", widgetCanonical, - }) - require.NoError(t, cmdErr) - defer t.Run("SuccessWidgetDelete", func(t *testing.T) { - _, deleteErr := executeCommand([]string{ - "--output", "json", "--org", config.Org, - "widgets", "delete", "--widget", widgetCanonical, - }) - require.NoError(t, deleteErr) - }) - - var widget models.Widget - err := json.Unmarshal([]byte(cmdOut), &widget) - require.NoError(t, err) - require.NotNil(t, widget.Canonical) - assert.Equal(t, widgetCanonical, *widget.Canonical) - - t.Run("SuccessWidgetGet", func(t *testing.T) { - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", "--org", config.Org, - "widgets", "get", "--widget", widgetCanonical, - }) - require.NoError(t, cmdErr) - var got models.Widget - err := json.Unmarshal([]byte(cmdOut), &got) - require.NoError(t, err) - require.NotNil(t, got.Canonical) - assert.Equal(t, widgetCanonical, *got.Canonical) - }) - }) -} -``` - -Pattern: create → nested subtests → deferred delete. - -## 11. Verify - -```bash -make format # fix formatting -make lint # catch issues -go test ./cmd/cycloid/middleware/... -run TestGetWidget # unit test -go test ./e2e/... -run TestWidgets # e2e test (requires make be-reset) -go build -o cy . # confirm it builds -``` - -## File naming checklist - -``` -cmd/cycloid// - cmd.go ← registers subcommands with cobra - list.go ← ListX command - get.go ← GetX command - create.go ← CreateX command - update.go ← UpdateX command - delete.go ← DeleteX command - common.go ← shared helpers (optional) -``` diff --git a/docs/architecture.md b/docs/architecture.md deleted file mode 100644 index f5c63fbe4..000000000 --- a/docs/architecture.md +++ /dev/null @@ -1,220 +0,0 @@ -# Architecture - -## Request lifecycle - -``` -cmd/cycloid//verb.go - │ (cobra RunE) - ▼ -cyargs.Get*() ← parse ALL flags first (required — see CLAUDE.md Hard Rules) - │ -common.NewAPI() ← build API config (URL, token) from flags/env/config file - │ -middleware.NewMiddleware() ← construct middleware struct with HTTP client - │ -m.GetX / m.ListX / ... ← middleware method in cmd/cycloid/middleware/.go - │ -m.GenericRequest(Request{...}, &result) - │ - ▼ -HTTP → Cycloid REST API - │ - ▼ -JSON {"data": } ← GenericRequest unwraps envelope; &result receives payload - │ -cyout.PrintWithOptions() ← stdout (success) or stderr (error); dispatches to printer -``` - -## The `Request` struct - -Defined in `cmd/cycloid/middleware/http_client.go`: - -```go -type Request struct { - Method string - Organization *string // used for auth token lookup; nil = no org context - NoAuth bool // set true to skip Authorization header - Route []string // joined onto base URL path: ["organizations", org, "projects"] - Query any // struct with `url` tags, or url.Values - Headers map[string]string // extra headers merged into request - Accept *string // overrides default Accept header - Body any // JSON-marshalled when non-nil -} -``` - -`Route` segments are path-joined onto the base URL (e.g., `CY_API_URL`). The route should not start with `/`. - -## `GenericRequest` behaviour - -Defined in `cmd/cycloid/middleware/generic_client.go`. - -1. Builds the full URL from `m.api.Config.URL` + `req.Route` -2. Encodes `req.Query` via struct tags (`url:"param_name"`) -3. JSON-marshals `req.Body` -4. Sets `Content-Type: application/json` and (unless `NoAuth`) `Authorization: Bearer ` -5. Executes the HTTP call -6. On non-2xx: returns `*APIResponseError` -7. On 2xx: unwraps the `{"data": ...}` JSON envelope into `response` (the second argument) - — callers pass `&result` directly, not a `struct{ Data *X }` wrapper - -```go -// Correct pattern: -func (m *middleware) GetProject(org, project string) (*models.Project, *http.Response, error) { - var result *models.Project - resp, err := m.GenericRequest(Request{ - Method: "GET", - Organization: &org, - Route: []string{"organizations", org, "projects", project}, - }, &result) - if err != nil { - return nil, resp, err - } - return result, resp, nil -} -``` - -## Envelope unwrapping - -The Cycloid API wraps all responses: - -```json -{ "data": { ... } } -``` - -`GenericRequest` strips this envelope before deserializing into `response`. If the response body is not envelope-shaped, it falls back to direct unmarshal. - -Pass `nil` as `response` to discard the body (e.g., DELETE calls). - -## Authentication - -`m.api.GetToken(org)` resolves the bearer token in this priority order: - -1. `--api-key` flag -2. `CY_API_KEY` env var -3. `CY_API_TOKEN` env var (legacy) -4. Per-org token stored in the config file (`~/.cy/config.yml`) - -Pass `Organization: &org` in `Request` to allow token lookup. Set `NoAuth: true` for unauthenticated endpoints (e.g., login). - -## Error taxonomy - -| Type | Cause | Go type | -|------|-------|---------| -| API error | Server returned non-2xx | `*APIResponseError` | -| Network error | Transport failure (DNS, TLS, timeout) | `*url.Error` or stdlib | -| Unexpected error | Anything else | `error` (do not wrap) | - -### `APIResponseError` - -```go -type APIResponseError struct { - StatusCode int - Status string - Body []byte // raw response body - Payload *models.ErrorPayload // parsed if body was valid JSON error - Path string // request path (+ query) for fallback errors -} - -// Error() format: -// - payload message available: "API error 422: " -// - fallback body/path: "API error 422 on "/path?query": " -``` - -Check with `errors.As`: - -```go -var apiErr *middleware.APIResponseError -if errors.As(err, &apiErr) { - if apiErr.StatusCode == 409 { - // conflict - } -} -``` - -Common status codes: 400 bad request, 401 unauthorized, 403 forbidden, 404 not found, 409 conflict, 422 unprocessable entity. - -### JSON output and API error diagnostics - -Errors that implement `printer.ErrHTTPResponse` attach the HTTP status code and raw response body (`*APIResponseError` for non-2xx, plus the decode error type returned by `GenericRequest` when a 2xx body cannot be unmarshaled). When `--output json` is used, the JSON printer first tries to marshal the value normally. If marshaling fails but the value is an error satisfying `ErrHTTPResponse`, it prints a small JSON object instead: `cli_marshal_error`, `http_status`, `api_response_preview` (first 10 lines of the body), and optionally `request_path` when the error also implements `printer.RequestPather` (as `*APIResponseError` does). - -## Why `client/client/` is unused - -The repository used to use the go-swagger generated operations package (`client/client/`). It was removed in the middleware refactor (see `docs/middleware-refactor.md`) in favour of `GenericRequest`: - -- Generated operations had inconsistent error handling -- Every API change required re-running the full swagger codegen cycle -- `GenericRequest` gives explicit control over routing, auth, headers, and response decoding - -The `client/models/` package (data types) is still auto-generated from `swagger.yaml` and must not be edited manually. - -## `--output` system - -The `--output` flag (default: `table`) controls how results are rendered. It is parsed by `printer/factory/factory.go` into a `printer.Printer` implementation. - -### Grammar - -| Value | Result | -|-------|--------| -| `table` | Default curated table (columns defined per command) | -| `table=col1,col2` | Table with explicit column selection | -| `table:noheader` | Table without the header row | -| `table=col1,col2:noheader` | Combined column selection + no header | -| `json` | Full JSON (pretty-printed) | -| `yaml` | Full YAML | -| `jq=` | Run jq expression over full JSON; strings printed raw, objects as pretty JSON | -| `` | Extract named field, one value per line (case-insensitive, dot notation OK) | - -`--jq ` is a shorthand flag for `-o jq=` and resolves identically. - -### Field extraction examples - -```sh -cy project list -o canonical # one canonical per line -cy project list -o owner.username # nested field -cy project list -o "jq=.[].canonical" # equivalent via jq -cy project delete $(cy project list -o canonical) # pipe pattern -``` - -### Shell completion - -Commands call `cyout.RegisterModel(cmd, models.X{})` in their constructor to register their model's fields. The global `--output` completion function reads these and suggests field names alongside `json`, `yaml`, `table`, and `jq=`: - -```sh -cy project list -o → json yaml table table= jq= canonical name id ... -cy project list -o table= → table=canonical table=name table=id ... -cy project list -o can → canonical -``` - -### Adding table columns to a command - -Define a `printer.Options` var in the command package and pass it to `cyout.PrintWithOptions`: - -```go -var widgetTableOptions = printer.Options{ - Columns: []string{"Canonical", "Name", "Description"}, - Identifier: "Canonical", // never dropped when terminal is narrow -} - -// in RunE: -return cyout.PrintWithOptions(cmd, result, err, "unable to get widget", widgetTableOptions) -``` - -Column names support dot notation for nested fields (`"Owner.Username"`). The `Identifier` column is always shown even when the terminal is too narrow to show all columns. - -### `cyout` package - -`internal/cyout/` provides two helpers that replace the 3-line `GetOutput`/`GetPrinter`/`SmartPrint` boilerplate: - -```go -// Simple (no column customisation): -cyout.Print(cmd, obj, err, "unable to do X") - -// With column options: -cyout.PrintWithOptions(cmd, obj, err, "unable to do X", tableOptions) -``` - -Errors are routed to `cmd.ErrOrStderr()`, results to `cmd.OutOrStdout()`. - -## Pipeline build watch (human SSE formatting) - -`cy pipeline build trigger --watch` streams build events while polling until the build finishes. Human vs raw NDJSON formatting lives in `internal/buildwatch`; the cobra command only passes options and calls `buildwatch.Watch`. If it causes problems, see [pipeline-build-watch-output.md](./pipeline-build-watch-output.md) for how to disable or remove it without touching the HTTP client. diff --git a/docs/middleware-refactor.md b/docs/middleware-refactor.md deleted file mode 100644 index d9c7e1309..000000000 --- a/docs/middleware-refactor.md +++ /dev/null @@ -1,119 +0,0 @@ -# Middleware Refactor - -## What changed - -The middleware layer was rewritten to remove the go-swagger generated operations package (`client/client/`) in favour of a single generic HTTP client (`GenericRequest` in `cmd/cycloid/middleware/generic_client.go`). - -### Before - -Each API endpoint was represented by a generated operation struct in `client/client/`: - -```go -// OLD — do not use -params := operations.NewGetOrganizationsOrgProjectsProjectParams() -params.SetOrganizationCanonical(org) -params.SetProjectCanonical(project) -resp, err := m.api.Client.Organizations.GetOrganizationsOrgProjectsProject(params, auth) -``` - -### After - -All API calls go through `GenericRequest`: - -```go -// NEW — current pattern -var result *models.Project -resp, err := m.GenericRequest(Request{ - Method: "GET", - Organization: &org, - Route: []string{"organizations", org, "projects", project}, -}, &result) -``` - -## Why the change - -| Pain point | Old (generated operations) | New (GenericRequest) | -|------------|--------------------------|---------------------| -| Error handling | Inconsistent per-operation types | Single `*APIResponseError` | -| Auth | Per-call auth parameter | Automatic via `Organization` field | -| API changes | Full codegen cycle required | Update route string + model | -| Routing | Opaque generated code | Explicit `Route` slice | -| Testing | Required generated mocks | Direct HTTP testing | -| `{"data":...}` envelope | Handled inconsistently | Always unwrapped in one place | - -## New invariants - -Every middleware method follows the same contract: - -```go -// Delete / void -func (m *middleware) DeleteX(org, x string) (*http.Response, error) - -// Get / Create -func (m *middleware) GetX(org, x string) (*models.X, *http.Response, error) - -// List -func (m *middleware) ListX(org string) ([]*models.X, *http.Response, error) -``` - -- Always return `(*http.Response, error)` at minimum so callers can inspect status codes -- Callers assign `_` to the response if they don't need it -- On error, return `nil, resp, err` (include resp so caller can check status) -- Do not validate payloads in middleware — validate in commands or leave it to the API - -## The `client/models/` exception - -Only the **operations** layer was removed. The **models** layer (`client/models/`) is still generated from `swagger.yaml` and is still used everywhere. - -``` -client/ - models/ ← STILL generated, DO NOT edit manually - client/ ← REMOVED (operations layer, do not use) -``` - -If you see an import like `"github.com/cycloidio/cycloid-cli/client/client/..."`, remove it and replace with `GenericRequest`. - -## Local model types - -Some models were removed from the swagger spec but are still needed by the CLI. These live directly in the middleware package: - -```go -// cmd/cycloid/middleware/http_client.go -type StackVersion struct { ... } -type StackUseCase struct { ... } -``` - -This is intentional — do not move them to `client/models/`. - -## Debug logging - -`GenericRequest` emits HTTP debug logs when `CY_VERBOSITY=debug` (set via `--verbosity debug` or the env var). Logs include: - -- Method, full URL, headers, body -- Response status, headers, body, elapsed time -- `Authorization` header is redacted: `Bearer ***XXXXX` (last 5 chars only) - -During tests: `CY_TEST_VERBOSITY=debug` — `TestMain` propagates it to `CY_VERBOSITY`. - -> ⚠️ Debug logs may contain sensitive data in request/response bodies beyond credentials. - -## Migration reference - -If you find code still using the old generated operations client, replace it: - -```go -// OLD — remove -import "github.com/cycloidio/cycloid-cli/client/client/operations" -params := operations.NewGetSomethingParams().WithOrg(org) -resp, err := m.api.Client.Operations.GetSomething(params, auth) -return resp.Payload.Data, nil, err - -// NEW — replace with -var result *models.Something -httpResp, err := m.GenericRequest(Request{ - Method: "GET", - Organization: &org, - Route: []string{"organizations", org, "somethings", id}, -}, &result) -return result, httpResp, err -``` diff --git a/docs/pipeline-build-watch-output.md b/docs/pipeline-build-watch-output.md deleted file mode 100644 index ccfbac601..000000000 --- a/docs/pipeline-build-watch-output.md +++ /dev/null @@ -1,108 +0,0 @@ -# Pipeline build watch: human-formatted SSE output - -This document describes the **optional presentation layer** for `cy pipeline build trigger --watch` (aliases: `pp build create|run --watch`). It lives in `internal/buildwatch`; `cmd/cycloid/pipelines` only wires flags and calls `buildwatch.Watch`. The layer exists so interactive use is readable; it is **not** required for correctness of the watch loop or API. - -If this layer causes regressions (missing lines, wrong parsing, terminal quirks, CI noise), use **Quick disable** below first, then **Full removal** if you want it gone entirely. - ---- - -## User-facing behavior - -| Situation | Stream written to stdout | -|-----------|---------------------------| -| `--watch` and **not** `--output json` | **Human**: one-line prefixes (`[build]`, `[task]`, `[stdout]` / `[stderr]`, `[res]` in verbose mode). Concourse JSON events are parsed and filtered. | -| `--watch` and `--output json` | **Raw**: NDJSON lines exactly as in the SSE `data:` payloads (legacy scripting behavior). | -| TTY + human | ANSI colors from `buildwatch.DefaultStreamTheme` in `internal/buildwatch/theme.go`. | -| Non-TTY or piped stdout + human | No ANSI; ANSI in log payloads is stripped. | -| Global `--verbosity debug` (or `-v debug`) + human + `--watch` | Emits extra “plumbing” events (image checks, workers, etc.). No effect when output is raw JSON (`--output json`). | - -**Log noise control:** Whitespace-only log payloads and blank lines inside a payload are skipped so empty Concourse log events do not print spacer lines. - -**Build link (stderr, before the stream):** With `--watch`, the CLI prints the build id and a console deep link on **stderr** so stdout can stay clean (e.g. raw JSON). The link uses: - -`{console_url}/organizations/{org}/projects/{project}/environments/{env}/components/{component}/pipelines/{pipeline}/jobs/{job}/builds/{build_id}` - -The default `console_url` is `https://console.cycloid.io`. Override with **`CY_CONSOLE_URL`** only (no CLI flag). If `CY_CONSOLE_URL` is set to an empty value, a stderr line explains that no link can be printed. - -**Ctrl+C reminder:** Before the stream, stderr also notes: first Ctrl+C requests a remote build abort; second exits watch immediately (see below). - -## Ctrl+C while watching - -Handled in `internal/buildwatch/watch.go` (not the cobra layer): - -1. **First Ctrl+C:** sends a **build abort** request (`AbortBuild`) so the remote build can stop gracefully. A short hint is printed to stderr (via `StatusWriter`): press Ctrl+C again to leave watch immediately. -2. **Second Ctrl+C:** **cancels** the local watch (stops polling and the event stream). The process exits with code **130** (`watch interrupted`), matching the usual `128 + SIGINT` convention. - -Disable this for tests with `Options.DisableInterruptHandler`. - ---- - -## Code map (files to inspect or delete) - -| File | Role | -|------|------| -| `cmd/cycloid/pipelines/build_trigger.go` | Cobra only: chooses `buildwatch.OutputHuman` vs `OutputRaw`, TTY theme, `StripLogANSI`, verbosity→`Verbose`, calls `buildwatch.Watch`. | -| `internal/buildwatch/watch.go` | `Watch`, `Client`, `Options`, `ExitError`, SSE consumption, reconnect loop, polling, Ctrl+C handling. | -| `internal/buildwatch/format.go` | Human line rendering, `formatHumanBuildEvent`, `paintLogLines`, ANSI stripping in payloads. | -| `internal/buildwatch/theme.go` | `StreamTheme`, `DefaultStreamTheme` (edit here to change colors only). | -| `internal/buildwatch/events.go` | JSON structs for Concourse event envelopes. | -| `internal/buildwatch/watch_test.go` | Tests for formatters and watch wiring. | - -Middleware `OpenBuildEventsStream` (`cmd/cycloid/middleware/component_pipelines_jobs_builds.go`) is unchanged: it still returns `text/event-stream`. - ---- - -## Quick disable (keep package, force raw stream) - -To make **`--watch` always behave like raw NDJSON** regardless of `--output` (fastest rollback): - -1. Open `cmd/cycloid/pipelines/build_trigger.go`. -2. In the `if watch {` block, force raw output mode, for example: - -```go -outMode := buildwatch.OutputRaw -// Was: human unless --output json; temporarily forcing raw — see docs/pipeline-build-watch-output.md -``` - -3. You can drop the `theme` / `stripLogANSI` / `IsTerminalWriter` block when `outMode` is always `OutputRaw` (optional cleanup). - -4. Run `make format && make lint` and `go test ./internal/buildwatch/... ./cmd/cycloid/pipelines/...`. - -Debug verbosity then only affects HTTP logging elsewhere, not the watch stream (already raw). - ---- - -## Full removal (restore passthrough-only watch) - -1. **Delete** (or revert in git) the package directory: - - `internal/buildwatch/` (all `.go` files) - -2. **`cmd/cycloid/pipelines/build_trigger.go`** - - Remove `internal/buildwatch` import. - - Inline a minimal watch loop **or** copy a slim `watch.go` back under `cmd/cycloid/pipelines` that only passthrough-writes SSE `data:` payloads (see git history before `internal/buildwatch`). - -3. **`go.mod`** - - Run `go mod tidy` if `golang.org/x/term` is no longer referenced. - -4. **Docs** - - Delete this file and remove links from `docs/architecture.md`, `CLAUDE.md`, and `AGENTS.md`. - ---- - -## Flags reference - -| Flag | Meaning | -|------|---------| -| `--watch` | Wait for build completion while streaming build events. | -| `--timeout` | With `--watch`, max seconds before giving up (see `--watch-cancel-on-timeout`). | -| `--watch-cancel-on-timeout` | With `--watch`, call abort when `--timeout` elapses. | -| `--output json` | Watch stream stays machine-readable NDJSON. | -| `--verbosity debug` | With human watch output, print all parsed event types. | - ---- - -## Maintenance notes - -- **Do not** tie this to `cyargs` project `--color`; watch colors are isolated in `internal/buildwatch/theme.go`. -- Parser failures on a `data:` line fall back to writing that line unchanged (plus newline), so unknown event shapes still surface as text. -- Changing Concourse event schemas may require updates to `internal/buildwatch/events.go` and the `switch` in `formatHumanBuildEvent` (`format.go`). diff --git a/docs/testing.md b/docs/testing.md deleted file mode 100644 index 752156b02..000000000 --- a/docs/testing.md +++ /dev/null @@ -1,307 +0,0 @@ -# Testing - -## Overview - -There are two test layers: - -| Layer | Location | Runs against | -|-------|----------|--------------| -| Middleware unit tests | `cmd/cycloid/middleware/*_test.go` | Real backend (via `testcfg`) | -| E2E tests | `e2e/*_test.go` | Real backend (via `testcfg`) | - -Both layers require a running Cycloid backend. See [Running tests](#running-tests). - -## Running tests - -```bash -# Start the backend -make be-reset - -# Run all tests -make test -# or -go test ./... - -# Run a specific middleware test -go test ./cmd/cycloid/middleware/... -run TestGetProject - -# Run a specific e2e test -go test ./e2e/... -run TestProjects - -# Stop the backend when done -make be-stop -``` - -`make be-reset` is preferred for test runs because it starts from a clean backend state. - -E2E tests are **not run in parallel** — the backend uses git under the hood and cannot handle concurrent writes. - -## Environment variables - -| Variable | Purpose | -|----------|---------| -| `CY_TEST_API_URL` | Backend URL (default: `http://localhost:3001` — youdeploy-api host port mapped by compose) | -| `CY_API_KEY` | API key for authentication | -| `CY_TEST_ROOT_ORG` | Root org canonical for provisioning | -| `API_LICENCE_KEY` | Licence key (required by some backend features) | -| `CY_TEST_PROVISION_API` | Set to `true` to provision test fixtures via API | -| `CY_TEST_VERBOSITY` | Set to `debug` to enable HTTP debug logs | - -### Generating `.env` from prod credentials - -The repo ships an `.env.sample` with `cy://` URIs that resolve to real secrets. Generate a local `.env` by interpolating against your prod org: - -```bash -# 1. Point cy at prod (uses bao-backed cyset shell function) -cyset API_prod_cycloid - -# 2. Interpolate — resolves cy:// URIs to real values -cy uri interpolate .env.sample > .env -``` - -`.env` is git-ignored. Re-run step 2 whenever secrets rotate. The file is sourced automatically by `docker compose` when you run `make be-reset`. - -The compose stack now uses Docker auto-IPAM (no static `192.168.10.0/24`); services -talk to each other via service DNS names (e.g. `youdeploy-api:3001`, -`docker-registry:5000`). Only `youdeploy-api` (port `3001`) and `docker-registry` -(port `${DOCKER_REGISTRY_HOST_PORT:-5000}`) are bound to the host — everything -else is internal-only. - -`CY_TEST_VERBOSITY=debug` propagates to `CY_VERBOSITY=debug` inside `TestMain`, enabling full request/response logging. Logs include credentials (redacted to last 5 chars of the token). - -## `testcfg` package - -`pkg/testcfg` manages test fixture provisioning. It creates a real org, project, environment, and component against the backend. - -### `NewConfig(name string)` - -```go -config, err := testcfg.NewConfig("middleware") -defer config.Cleanup() -``` - -After a successful call, `config` exposes: - -| Field | Type | Description | -|-------|------|-------------| -| `config.Org` | `string` | Organization canonical | -| `config.APIUrl` | `string` | Backend URL | -| `config.APIKey` | `string` | API key scoped to this test run | -| `config.Project` | `*models.Project` | Pre-created project | -| `config.Environment` | `*models.Environment` | Pre-created environment | -| `config.Component` | `*models.Component` | Pre-created component | -| `config.ConfigRepo` | `*models.ExternalBackend` | Pre-created config repository | -| `config.CatalogRepo` | `*models.ServiceCatalogSource` | Pre-created catalog repository | - -### Cleanup - -`config.Cleanup()` deletes all provisioned resources. Always defer it immediately after `NewConfig`: - -```go -config, err := testcfg.NewConfig("middleware") -defer config.Cleanup() -``` - -### `AppendCleanup` - -Register additional teardown for resources created inside a test: - -```go -config.AppendCleanup(func() { - m.DeleteProject(config.Org, projectCanonical) -}) -``` - -### `RandomCanonical` - -```go -canonical := testcfg.RandomCanonical("prefix") -// returns something like "prefix-a1b2c3" -``` - -Use this for test resource names to avoid conflicts across parallel test runs (different packages). - -## Middleware unit tests - -### Setup - -Each test package has a `TestMain` in `middleware_test.go`: - -```go -var config *testcfg.Config - -func runMain(ctx context.Context, main *testing.M) (int, error) { - var err error - config, err = testcfg.NewConfig("middleware") - defer config.Cleanup() - if err != nil { - return 1, fmt.Errorf("config setup failed: %w", err) - } - - os.Setenv("CY_API_URL", config.APIUrl) - os.Setenv("CY_API_KEY", config.APIKey) - os.Setenv("CY_ORG", config.Org) - - if v := os.Getenv("CY_TEST_VERBOSITY"); v != "" { - viper.Set("verbosity", v) - } - return main.Run(), nil -} -``` - -### Writing a middleware test - -```go -// cmd/cycloid/middleware/organization_projects_test.go -package middleware_test - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestGetProject(t *testing.T) { - m := NewTestMiddleware() // helper from middleware_test package - result, _, err := m.GetProject(config.Org, *config.Project.Canonical) - require.NoError(t, err) - require.NotNil(t, result) - assert.Equal(t, *config.Project.Canonical, *result.Canonical) -} -``` - -Focus on the happy path. Error paths are implicitly covered by e2e tests. - -## E2E tests - -### Setup - -`e2e/e2e_test.go` has its own `TestMain` with the same `testcfg.NewConfig` pattern. Fixtures from `testcfg` are available via the package-level `config` variable. - -### Helpers - -```go -// Execute a CLI command and return stdout, error -cmdOut, cmdErr := executeCommand([]string{"--org", config.Org, "project", "list"}) - -// Execute with stdin input -cmdOut, cmdErr := executeCommandStdin(stdin, []string{"--org", config.Org, "pipeline", "update"}) - -// Write a temporary file -WriteFile(path, content) - -// Random canonical -canonical := randomCanonical("prefix") // local alias for testcfg.RandomCanonical -``` - -### Pattern: create → test → deferred delete - -```go -import ( - "encoding/json" - "testing" - - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestWidgets(t *testing.T) { - canonical := testcfg.RandomCanonical("test-widget") - - t.Run("SuccessWidgetCreate", func(t *testing.T) { - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", "--org", config.Org, - "widgets", "create", "--name", canonical, - }) - require.NoError(t, cmdErr) - - defer t.Run("SuccessWidgetDelete", func(t *testing.T) { - _, err := executeCommand([]string{ - "--output", "json", "--org", config.Org, - "widgets", "delete", "--widget", canonical, - }) - require.NoError(t, err) - }) - - var widget models.Widget - err := json.Unmarshal([]byte(cmdOut), &widget) - require.NoError(t, err) - require.NotNil(t, widget.Canonical) - assert.Equal(t, canonical, *widget.Canonical) - - t.Run("SuccessWidgetGet", func(t *testing.T) { ... }) - t.Run("SuccessWidgetUpdate", func(t *testing.T) { ... }) - }) -} -``` - -The `defer` on `SuccessWidgetDelete` ensures cleanup even if inner tests fail. - -### `create --update` (upsert) coverage - -When you add or change idempotent `create --update` behavior, extend **existing** e2e files for that resource in the same change. Examples in this repo: - -| Area | File | Notes | -|------|------|--------| -| Teams | `e2e/teams_test.go` | Name-only upsert (`SuccessTeamCreateUpdateWithNameOnly`) | -| Projects / envs | `e2e/projects_test.go`, `e2e/environments_test.go` | Already cover inferred canonical + `--update` | -| Child orgs | `e2e/organizations_test.go` | Duplicate create errors; `create --update` succeeds | -| Catalog repos | `e2e/catalog_repositories_test.go` | Nested in `SuccessCatalogRepositoriesCreate`: duplicate create errors; `create --update` succeeds | -| Stacks (blueprint) | `e2e/stacks_test.go` | Existing canonical + `--update` returns same stack | - -`e2e/config_repositories_test.go` is currently skipped (BE-981); when it is re-enabled, add matching `--update` cases there. - -### Known skipped tests - -| Test | File | Reason | -|------|------|--------| -| `SuccessOrganizationsList` | `organizations_test.go` | Requires user token; e2e uses API key (422) | -| `TestInfraPolicies` | `infra_policies_test.go` | Skipped pending backend availability | -| `PipelineClearTaskCacheOk` | `pipelines_test.go` | Pending backend support | -| `TestConfigRepositories` (some subtests) | `config_repositories_test.go` | See BE-981 | - -### JSON helpers - -```go -// Extract field values from a JSON array by matching another field -ids, err := JSONListExtractFields(listOut, "id", "email", "^admin@cycloid.io$") -// Returns []string of "id" values where "email" matches the regex -``` - -## Fixtures - -Shared test fixtures are defined in `e2e/helpers_test.go`: - -- `TestPipelineSample` — minimal Concourse pipeline YAML -- `TestPipelineVariables` — matching pipeline vars YAML -- `TestInfraPolicySample` — Rego policy -- `TestTerraformPlanSample` — minimal Terraform JSON plan (used by terracost + infra policies) - -## Plugin services - -`make be-reset` brings up three additional services for plugin testing: - -| Service | Port (internal) | Host port | Purpose | -|---|---|---|---| -| `plugin-manager` | 4000 | — | Schedules plugin containers via containerd (privileged) | -| `plugin-registry` | 4000 | — | REST API metadata store for plugin definitions | -| `docker-registry` | 5000 | `${DOCKER_REGISTRY_HOST_PORT:-5000}` | OCI image store (htpasswd auth) | - -The docker-registry uses basic auth seeded from `docker/auth/htpasswd` -(`cycloid` / `cycloid123`). The plugin-manager auto-registers itself on -startup as `test-plugin-manager` against the youdeploy-api at -`http://youdeploy-api:3001` using `CY_URL` from compose. - -Smoke-test the plugin lifecycle with: - -```bash -docker login localhost:5000 -u cycloid -p cycloid123 -docker pull docker.io/cycloid/plugin-hello-world -docker tag docker.io/cycloid/plugin-hello-world localhost:5000/plugin-hello-world:1.0.0 -docker push localhost:5000/plugin-hello-world:1.0.0 -``` - -Plugin version tags **must** match `\d+\.\d+\.\d+` — `latest` is rejected by -`plugin registry plugin version publish`. diff --git a/e2e/api_keys_test.go b/e2e/api_keys_test.go deleted file mode 100644 index 3a06ad293..000000000 --- a/e2e/api_keys_test.go +++ /dev/null @@ -1,184 +0,0 @@ -package e2e_test - -import ( - "encoding/json" - "slices" - "testing" - - "github.com/sanity-io/litter" - "github.com/stretchr/testify/assert" - - "github.com/cycloidio/cycloid-cli/client/models" -) - -func TestAPIKeysCmd(t *testing.T) { - var ( - testKeyCanonical = randomCanonical("test-admin") - createdAPIKey models.APIKey - ) - t.Run("CreateAPIKeyAdminOk", func(t *testing.T) { - args := []string{ - "--output", "json", - "--org", config.Org, - "api-key", "create", - "--canonical", testKeyCanonical, - "--description", "hello world", - "--rules", `[{"action":"organization:**","effect":"allow","resources":[]}]`, - } - createOut, createErr := executeCommand(args) - if createErr != nil { - t.Errorf("failed to create api key admin: %s", createErr) - } - - defer t.Run("DeleteAPIKeyOk", func(t *testing.T) { - args := []string{ - "--output", "json", - "--org", config.Org, - "api-key", "delete", - "--canonical", testKeyCanonical, - } - _, deleteErr := executeCommand(args) - if deleteErr != nil { - t.Errorf("failed to delete api key admin: %s", deleteErr) - } - }) - - err := json.Unmarshal([]byte(createOut), &createdAPIKey) - if err != nil { - t.Errorf("CLI output can't be serialize to models.APIKey, out:\n%s\nerr:\n%s", createOut, err) - } - - assert.Equal(t, *createdAPIKey.Canonical, testKeyCanonical) - - var APIKeyList []*models.APIKey - t.Run("ListAPIKeyOk", func(t *testing.T) { - args := []string{ - "--output", "json", - "--org", config.Org, - "api-key", "list", - } - listOut, listErr := executeCommand(args) - if listErr != nil { - t.Errorf("failed to list api keys: %s", listErr) - } - - err := json.Unmarshal([]byte(listOut), &APIKeyList) - if err != nil { - t.Errorf("failed to parse cli output as list of api keys, out: %s\nerr: %s", listOut, err) - } - - if index := slices.IndexFunc(APIKeyList, func(a *models.APIKey) bool { - return *a.Canonical == testKeyCanonical - }); index == -1 { - t.Errorf("failed to find the API key with can '%s' in list: %s", testKeyCanonical, litter.Sdump(APIKeyList)) - } - }) - - t.Run("GetAPIKeyOk", func(t *testing.T) { - args := []string{ - "--output", "json", - "--org", config.Org, - "api-key", "get", - "--canonical", testKeyCanonical, - } - getOut, getErr := executeCommand(args) - if getErr != nil { - t.Errorf("failed to get api key: %s", getErr) - } - - var gotKey models.APIKey - if err := json.Unmarshal([]byte(getOut), &gotKey); err != nil { - t.Errorf("CLI output can't be serialized to models.APIKey, out:\n%s\nerr:\n%s", getOut, err) - } - assert.Equal(t, testKeyCanonical, *gotKey.Canonical) - }) - - t.Run("GetWithPositionalArg", func(t *testing.T) { - args := []string{ - "--output", "json", - "--org", config.Org, - "api-key", "get", - testKeyCanonical, // positional, no --canonical - } - getOut, getErr := executeCommand(args) - if getErr != nil { - t.Errorf("failed to get api key via positional arg: %s", getErr) - } - - var gotKey models.APIKey - if err := json.Unmarshal([]byte(getOut), &gotKey); err != nil { - t.Errorf("CLI output can't be serialized to models.APIKey, out:\n%s\nerr:\n%s", getOut, err) - } - assert.Equal(t, testKeyCanonical, *gotKey.Canonical) - }) - - t.Run("RecreateAPIKey", func(t *testing.T) { - tmpCan := randomCanonical("test-recreate") - rules := `[{"action":"organization:**","effect":"allow","resources":[]}]` - - // Create - _, err := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "api-key", "create", - "--canonical", tmpCan, - "--rules", rules, - }) - if err != nil { - t.Errorf("setup: failed to create api key for recreate test: %s", err) - } - - defer t.Run("RecreateCleanup", func(t *testing.T) { - executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "api-key", "delete", - tmpCan, - }) - }) - - // Second create without --recreate should fail - _, dupErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "api-key", "create", - "--canonical", tmpCan, - "--rules", rules, - }) - assert.Error(t, dupErr, "second create without --recreate should fail") - - // Third create with --recreate should succeed - _, recreateErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "api-key", "create", - "--canonical", tmpCan, - "--rules", rules, - "--recreate", - }) - assert.NoError(t, recreateErr, "create --recreate should succeed for existing api key") - }) - - t.Run("DeleteWithPositionalArg", func(t *testing.T) { - tmpCan := randomCanonical("test-del-pos") - _, err := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "api-key", "create", - "--canonical", tmpCan, - "--rules", `[{"action":"organization:**","effect":"allow","resources":[]}]`, - }) - if err != nil { - t.Errorf("setup: failed to create api key: %s", err) - } - - _, deleteErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "api-key", "delete", - tmpCan, // positional, no --canonical - }) - assert.NoError(t, deleteErr, "delete via positional arg should succeed") - }) - }) -} diff --git a/e2e/catalog_repositories_test.go b/e2e/catalog_repositories_test.go deleted file mode 100644 index 7a168c963..000000000 --- a/e2e/catalog_repositories_test.go +++ /dev/null @@ -1,195 +0,0 @@ -package e2e_test - -import ( - "encoding/json" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/cycloidio/cycloid-cli/client/models" -) - -func TestCatalogRepositories(t *testing.T) { - defer t.Run("SuccessCatalogRepositoriesDelete", func(t *testing.T) { - // Cleanup just in case - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "catalog-repository", - "delete", - "--canonical", "step-by-step", - }) - - assert.Nil(t, cmdErr, "failed to delete test catalog repo:", cmdOut) - }) - - t.Run("SuccessCatalogRepositoriesCreate", func(t *testing.T) { - // Cleanup just in case - executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "catalog-repository", - "delete", - "--canonical", "step-by-step", - }) - - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "catalog-repository", - "create", - "--branch", "stack-aws", - "--url", "https://github.com/cycloid-community-catalog/docs-step-by-step-stack.git", - "--name", "step-by-step", - }) - - require.Nil(t, cmdErr) - - assert.Contains(t, cmdOut, "canonical\": \"stack-aws-sample") - - t.Run("SuccessCatalogRepositoriesCreateDuplicateWithoutUpdateErrors", func(t *testing.T) { - _, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "catalog-repository", - "create", - "--branch", "stack-aws", - "--url", "https://github.com/cycloid-community-catalog/docs-step-by-step-stack.git", - "--name", "step-by-step", - }) - require.Error(t, cmdErr, "second create without --update should fail when catalog repo already exists") - }) - - t.Run("SuccessCatalogRepositoriesCreateWithUpdate", func(t *testing.T) { - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "catalog-repository", - "create", - "--update", - "--branch", "stack-aws", - "--url", "https://github.com/cycloid-community-catalog/docs-step-by-step-stack.git", - "--name", "step-by-step", - }) - require.NoError(t, cmdErr, "create --update should succeed for existing catalog repo") - - var repo models.ServiceCatalogSource - err := json.Unmarshal([]byte(cmdOut), &repo) - require.NoError(t, err, "output should deserialize, got: %s", cmdOut) - require.NotNil(t, repo.Canonical) - assert.Equal(t, "step-by-step", *repo.Canonical) - require.NotNil(t, repo.Name) - assert.Equal(t, "step-by-step", *repo.Name) - }) - }) - - t.Run("SuccessCatalogRepositoriesList", func(t *testing.T) { - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "catalog-repository", - "list", - }) - - require.Nil(t, cmdErr) - assert.Contains(t, cmdOut, "canonical\": \"step-by-step") - }) - - t.Run("SuccessCatalogRepositoriesGet", func(t *testing.T) { - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "catalog-repository", - "get", - "--canonical", "step-by-step", - }) - - require.Nil(t, cmdErr) - assert.Contains(t, cmdOut, "canonical\": \"stack-aws-sample") - }) - - t.Run("SuccessCatalogRepositoriesRefresh", func(t *testing.T) { - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "catalog-repository", - "refresh", - "--canonical", "step-by-step", - }) - - require.Nil(t, cmdErr) - assert.Contains(t, cmdOut, "updated") - }) - - t.Run("SuccessCatalogRepositoryUpdate", func(t *testing.T) { - updatedName := "step-by-step-updated" - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "catalog-repository", - "update", - "--canonical", "step-by-step", - "--name", updatedName, - "--branch", "stack-aws", - "--url", "https://github.com/cycloid-community-catalog/docs-step-by-step-stack.git", - "--cred", "", - }) - - require.Nil(t, cmdErr) - var updatedRepo models.ServiceCatalogSource - err := json.Unmarshal([]byte(cmdOut), &updatedRepo) - require.Nil(t, err, "output should deserialize to ServiceCatalogSource, out: %s", cmdOut) - assert.Equal(t, updatedName, *updatedRepo.Name) - }) - - // Positional-arg tests — verify the new interface works alongside deprecated --canonical - - t.Run("GetWithPositionalArg", func(t *testing.T) { - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "catalog-repository", - "get", - "step-by-step", // positional, no --canonical - }) - require.Nil(t, cmdErr) - assert.Contains(t, cmdOut, "step-by-step") - }) - - t.Run("RefreshWithPositionalArg", func(t *testing.T) { - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "catalog-repository", - "refresh", - "step-by-step", // positional, no --canonical - }) - require.Nil(t, cmdErr) - assert.Contains(t, cmdOut, "updated") - }) - - t.Run("DeleteWithPositionalArg", func(t *testing.T) { - // Create a temporary repo to be deleted via positional arg - tmpCan := randomCanonical("cat-repo-pos") - _, createErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "catalog-repository", - "create", - "--branch", "stack-aws", - "--url", "https://github.com/cycloid-community-catalog/docs-step-by-step-stack.git", - "--name", tmpCan, - }) - require.Nil(t, createErr, "setup: create catalog repo for delete test") - - _, deleteErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "catalog-repository", - "delete", - tmpCan, // positional, no --canonical - }) - require.Nil(t, deleteErr) - }) -} diff --git a/e2e/components_test.go b/e2e/components_test.go deleted file mode 100644 index 46acbd1f1..000000000 --- a/e2e/components_test.go +++ /dev/null @@ -1,482 +0,0 @@ -package e2e_test - -import ( - "encoding/json" - "errors" - "os" - "strings" - "testing" - - "github.com/stretchr/testify/assert" - - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" -) - -func TestComponentCmd(t *testing.T) { - var ( - componentName = "Test Component" - component = randomCanonical("e2e-component") - componentDescription = "My cool component" - stackRef = config.Org + ":stack-e2e-stackforms" - description = "Testing components" - ) - - t.Run("CreateReadListDelete", func(t *testing.T) { - // create - testJSON := `{"types": {"tests": {"map": {"hello": "world", "int": 1, "bool": true}}}}` - testJSONFileContent := `{"types": {"tests": {"string": "myString"}}}` - testJSONStdin := `{"types": {"tests": {"array": ["hello", false, 1, 1.1]}}}` - filename, err := WriteTempFile(testJSONFileContent) - if err != nil { - t.Errorf("comp create setup failed: %v", err) - } - - var stdout, stderr string - args := []string{ - "--output", "json", - "--org", config.Org, - "components", "create", - "--name", componentName, - "-p", *config.Project.Canonical, - "-e", *config.Environment.Canonical, - "-c", component, - "-d", componentDescription, - // test raw var flag - "-j", testJSON, - // test stdin - "-f", "-", - // test file flag - "-f", filename, - // Test var=value flag - "-V", `section with spaces.group with spaces.no_spaces="osef"`, - "-s", stackRef, - "-u", "default", - "--stack-commit-hash", *config.CatalogRepoVersionStacks.CommitHash, - } - stdout, stderr, err = executeCommandStdin(testJSONStdin, args) - if err != nil { - t.Logf("component creation failed: %v\nstdout:\n%s\nstderr\n%s", err, stdout, stderr) - t.FailNow() - } - - // delete - defer t.Run("DeleteCreateComp", func(t *testing.T) { - out, err := executeCommand([]string{ - "--org", config.Org, - "components", "delete", - "-p", *config.Project.Canonical, - "-e", *config.Environment.Canonical, - "-c", component, - }) - if err != nil { - t.Errorf("failed to delete and cleanup component '%s' from Create test: %v\nstdout: %s", component, err, out) - } - }) - - // get - args = []string{ - "--output", "json", - "--org", config.Org, - "components", "get", - "-p", *config.Project.Canonical, - "-e", *config.Environment.Canonical, - "-c", component, - } - out, err := executeCommand(args) - if err != nil { - t.Errorf("failed to execute cmd '%s': %s", strings.Join(args, " "), err) - } - - var comp models.Component - err = json.Unmarshal([]byte(out), &comp) - if err != nil { - t.Errorf("failed to parse output of cy comp get command: %v\noutput: %s", err, out) - } - - assert.NotNil(t, comp) - assert.NotNil(t, comp.Canonical) - assert.Equal(t, component, *comp.Canonical) - assert.Equal(t, componentName, *comp.Name) - - // list - args = []string{ - "--output", "json", - "--org", config.Org, - "components", "list", - "-p", *config.Project.Canonical, - "-e", *config.Environment.Canonical, - } - out, err = executeCommand(args) - if err != nil { - t.Errorf("failed to execute cmd '%s': %s", strings.Join(args, " "), err) - } - - var comps []models.Component - err = json.Unmarshal([]byte(out), &comps) - if err != nil { - t.Errorf("failed to parse output of cy comp get command: %v\noutput: %s", err, out) - } - }) - - t.Run("CreateWithUpdateNew", func(t *testing.T) { - var newComp = randomCanonical("e2e-new") - args := []string{ - "--output", "json", - "--org", config.Org, - "components", "create", - "--name", componentName, - "-p", *config.Project.Canonical, - "-e", *config.Environment.Canonical, - "-c", newComp, - "-d", componentDescription, - "-V", `section with spaces.group with spaces.no_spaces="new"`, - "-s", stackRef, - "-u", "default", - "--update", - "--stack-commit-hash", *config.CatalogRepoVersionStacks.CommitHash, - } - var err, errList error - var stdout, stderr string - for range 3 { - stdout, stderr, err = executeCommandStdin("", args) - if err != nil { - errList = errors.Join(errList, err) - continue - } - errList = nil - break - } - - if errList != nil { - t.Errorf("component creation failed: %v\nstdout:\n%s\nstderr\n%s", err, stdout, stderr) - } - - defer t.Run("DeleteCreateWithUpdateComp", func(t *testing.T) { - out, err := executeCommand([]string{ - "--org", config.Org, - "components", "delete", - "-p", *config.Project.Canonical, - "-e", *config.Environment.Canonical, - "-c", newComp, - }) - if err != nil { - t.Errorf("failed to delete and cleanup component '%s' from '%s' test: %v\nstdout: %s", component, t.Name(), err, out) - } - }) - }) - - t.Run("CreateWithUpdateAndConfig", func(t *testing.T) { - // create - testJSON := `{"types": {"tests": {"map": {"hello": "world", "int": 1, "bool": true}}}}` - testJSONFileContent := `{"types": {"tests": {"string": "myString"}}}` - testJSONStdin := `{"types": {"tests": {"array": ["hello", false, 1, 1.1]}}}` - filename, err := WriteTempFile(testJSONFileContent) - if err != nil { - t.Errorf("comp create setup failed: %v", err) - } - defer os.Remove(filename) - - args := []string{ - "--output", "json", - "--org", config.Org, - "components", "create", - "--name", componentName, - "-p", *config.Project.Canonical, - "-e", *config.Environment.Canonical, - "-c", component, - "-d", componentDescription, - // test raw var flag - "-j", testJSON, - // test stdin - "-f", "-", - // test file flag - "-f", filename, - // Test var=value flag - "-V", `section with spaces.group with spaces.no_spaces="osef"`, - "-s", stackRef, - "-u", "default", - "--update", - "--stack-branch", config.CatalogRepo.Branch, - } - stdout, stderr, err := executeCommandStdin(testJSONStdin, args) - if err != nil { - t.Errorf("component creation failed: %v\nstdout:\n%s\nstderr\n%s", err, stdout, stderr) - } - defer t.Run("DeleteCreateWithUpdateComp", func(t *testing.T) { - out, err := executeCommand([]string{ - "--org", config.Org, - "components", "delete", - "-p", *config.Project.Canonical, - "-e", *config.Environment.Canonical, - "-c", component, - }) - if err != nil { - t.Errorf("failed to delete and cleanup component '%s' from '%s' test: %v\nstdout: %s", component, t.Name(), err, out) - } - }) - - // create with update - testJSON = `{"types": {"tests": {"map": {"update": true}}}}` - testJSONFileContent = `{"types": {"tests": {"string": "updated"}}}` - testJSONStdin = `{"types": {"tests": {"array": []}}}` - filename, err = WriteTempFile(testJSONFileContent) - if err != nil { - t.Errorf("comp create setup failed: %v", err) - } - defer os.Remove(filename) - - args = []string{ - "--output", "json", - "--org", config.Org, - "components", "create", - "--name", componentName, - "-p", *config.Project.Canonical, - "-e", *config.Environment.Canonical, - "-c", component, - "-d", description, - // test raw var flag - "-j", testJSON, - // test stdin - "-f", "-", - // test file flag - "-f", filename, - // Test var=value flag - "-V", `section with spaces.group with spaces.no_spaces=osef`, - "-s", stackRef, - "-u", "default", - "--update", - "--stack-commit-hash", *config.CatalogRepoVersionStacks.CommitHash, - } - - stdout, stderr, err = executeCommandStdin(testJSONStdin, args) - if err != nil { - t.Errorf("component put failed: %v\nstdout:\n%s\nstderr\n%s", err, stdout, stderr) - } - - // get config - args = []string{ - "--output", "json", - "components", "config", "get", - "-p", *config.Project.Canonical, - "-e", *config.Environment.Canonical, - "-c", component, - } - stdout, stderr, err = executeCommandStdin(testJSONStdin, args) - if err != nil { - t.Errorf("component put failed: %v\nstdout:\n%s\nstderr\n%s", err, stdout, stderr) - } - - var outVars models.FormVariables - err = json.Unmarshal([]byte(stdout), &outVars) - if err != nil { - t.Errorf("failed to parse output of CLI as JSON:\n%s\n%s", stdout, err) - } - - value, _ := outVars["types"]["tests"]["map"].(map[string]any)["update"].(bool) - assert.Equal(t, true, value) - assert.Equal(t, "updated", outVars["types"]["tests"]["string"]) - assert.Equal(t, "osef", outVars["section with spaces"]["group with spaces"]["no_spaces"]) - - // update - testJSON = `{"types": {"tests": {"string": "update2"}}}` - testJSONFileContent = `{"types": {"tests": {"integer": 14}}}` - testJSONStdin = `{"types": {"tests": {"float": 2.2}}}` - filename, err = WriteTempFile(testJSONFileContent) - if err != nil { - t.Errorf("comp update setup failed: %v", err) - } - defer os.Remove(filename) - - args = []string{ - "--output", "json", - "--org", config.Org, - "components", "update", - "--name", componentName, - "-p", *config.Project.Canonical, - "-e", *config.Environment.Canonical, - "-c", component, - "-d", description, - // test raw var flag - "-j", testJSON, - // test stdin - "-f", "-", - // test file flag - "-f", filename, - // Test var=value flag - "-V", `section with spaces.group with spaces.no_spaces=update2`, - "-u", "default", - "--stack-commit-hash", *config.CatalogRepoVersionStacks.CommitHash, - } - - stdout, stderr, err = executeCommandStdin(testJSONStdin, args) - if err != nil { - t.Errorf("component update failed: %v\nstdout:\n%s\nstderr\n%s", err, stdout, stderr) - } - - // check config after update - args = []string{ - "--output", "json", - "components", "config", "get", - "-p", *config.Project.Canonical, - "-e", *config.Environment.Canonical, - "-c", component, - } - stdout, stderr, err = executeCommandStdin(testJSONStdin, args) - if err != nil { - t.Errorf("component put failed: %v\nstdout:\n%s\nstderr\n%s", err, stdout, stderr) - } - - outVars = make(models.FormVariables) - err = json.Unmarshal([]byte(stdout), &outVars) - if err != nil { - t.Errorf("failed to parse output of CLI as JSON:\n%s\n%s", stdout, err) - } - - assert.Equal(t, "update2", outVars["types"]["tests"]["string"]) - assert.Equal(t, float64(14), outVars["types"]["tests"]["integer"].(float64)) - assert.Equal(t, 2.2, outVars["types"]["tests"]["float"]) - assert.Equal(t, "update2", outVars["section with spaces"]["group with spaces"]["no_spaces"]) - }) - - t.Run("TestVarsInvalidSectionsAndGroup", func(t *testing.T) { - args := []string{ - "--output", "json", - "--org", config.Org, - "components", "create", - "--update", - "--name", componentName, - "-p", *config.Project.Canonical, - "-e", *config.Environment.Canonical, - "-c", component, - "-d", description, - "-s", stackRef, - "-u", "default", - "--stack-commit-hash", *config.CatalogRepoVersionStacks.CommitHash, - "-V", `section with spaces.thisgroupdoesnotexists.no_spaces=update2`, - "-V", `sectiondoesnotexists.thisgroupdoesnotexists.no_spaces=true`, - } - - cmdOut, cmdErr := executeCommand(args) - if cmdErr != nil { - // We just check that it doesn't panic for now - t.Errorf("component update failed, stdout:\n%s\nstderr\n%s", cmdOut, cmdErr) - } - }) - - t.Run("TestCreateWithUpdateOnNonConfiguredComponentOk", func(t *testing.T) { - component := randomCanonical("created-not-configured") - - m := config.Middleware - created, _, err := m.CreateOrUpdateComponent(config.Org, *config.Project.Canonical, - *config.Environment.Canonical, component, description, component, - stackRef, "", "", *config.CatalogRepoVersionStacks.CommitHash, "default", "", nil) - if err != nil { - t.Logf("test setup failed: component creation %q reported err: %v", component, err) - t.FailNow() - } - defer m.DeleteComponent(config.Org, *created.Project.Canonical, - *created.Environment.Canonical, *created.Canonical, middleware.DeleteOptions{}) - - args := []string{ - "--output", "json", - "--org", config.Org, - "components", "create", - "--update", - "--name", component, - "-p", *config.Project.Canonical, - "-e", *config.Environment.Canonical, - "-c", component, - "-d", description, - "-s", stackRef, - "-u", "default", - "--stack-commit-hash", *config.CatalogRepoVersionStacks.CommitHash, - } - - cmdOut, cmdErr := executeCommand(args) - if cmdErr != nil { - // We just check that it doesn't panic for now - t.Errorf("component update failed, stdout:\n%s\nstderr\n%s", cmdOut, cmdErr) - } - }) - - t.Run("TestUpdateOnNonConfiguredComponentOk", func(t *testing.T) { - component := randomCanonical("created-not-configured") - - m := config.Middleware - created, _, err := m.CreateOrUpdateComponent(config.Org, *config.Project.Canonical, - *config.Environment.Canonical, component, description, component, - stackRef, "", "", *config.CatalogRepoVersionStacks.CommitHash, "default", "", nil) - if err != nil { - t.Logf("test setup failed: component creation %q reported err: %v", component, err) - t.FailNow() - } - defer m.DeleteComponent(config.Org, *created.Project.Canonical, - *created.Environment.Canonical, *created.Canonical, middleware.DeleteOptions{}) - - args := []string{ - "--output", "json", - "--org", config.Org, - "components", "update", - "--name", component, - "-p", *config.Project.Canonical, - "-e", *config.Environment.Canonical, - "-c", component, - "-d", description, - "-u", "default", - "--stack-commit-hash", *config.CatalogRepoVersionStacks.CommitHash, - } - - cmdOut, cmdErr := executeCommand(args) - if cmdErr != nil { - // We just check that it doesn't panic for now - t.Errorf("component update failed, stdout:\n%s\nstderr\n%s", cmdOut, cmdErr) - } - }) - - t.Run("TestUpdatePreservesStackVersionWhenNotSpecified", func(t *testing.T) { - // Regression test: cy component update without any --stack-branch/--stack-tag/ - // --stack-commit-hash flag was silently switching the component to the catalog's - // default branch instead of keeping the current version. - component := randomCanonical("preserve-version") - - m := config.Middleware - created, _, err := m.CreateOrUpdateComponent(config.Org, *config.Project.Canonical, - *config.Environment.Canonical, component, description, component, - stackRef, "", *config.CatalogRepoVersionStacks.Name, "", "default", "", nil) - if err != nil { - t.Logf("test setup failed: component creation %q reported err: %v", component, err) - t.FailNow() - } - defer m.DeleteComponent(config.Org, *created.Project.Canonical, - *created.Environment.Canonical, *created.Canonical, middleware.DeleteOptions{}) - - versionBefore := created.ServiceCatalog.Version - - // Update without specifying any version flag — version must be preserved. - args := []string{ - "--output", "json", - "--org", config.Org, - "components", "update", - "-p", *config.Project.Canonical, - "-e", *config.Environment.Canonical, - "-c", component, - "-d", description, - "-u", "default", - } - cmdOut, cmdErr := executeCommand(args) - if cmdErr != nil { - t.Errorf("component update failed, stdout:\n%s\nstderr\n%s", cmdOut, cmdErr) - t.FailNow() - } - - var updated models.Component - if err := json.Unmarshal([]byte(cmdOut), &updated); err != nil { - t.Errorf("failed to parse update output as JSON: %v\noutput: %s", err, cmdOut) - t.FailNow() - } - - assert.Equal(t, versionBefore, updated.ServiceCatalog.Version, - "stack version must not change when no version flag is specified") - }) -} diff --git a/e2e/config_repositories_test.go b/e2e/config_repositories_test.go deleted file mode 100644 index 6dc9de2db..000000000 --- a/e2e/config_repositories_test.go +++ /dev/null @@ -1,107 +0,0 @@ -package e2e_test - -import ( - "encoding/json" - "slices" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/cycloidio/cycloid-cli/client/models" -) - -func TestConfigRepositories(t *testing.T) { - // Bug: https://linear.app/cycloid/issue/BE-981/catalog-repository-creation-fail-on-staging - t.Skip() - // - - var ( - CRUrl = "git@github.com:cycloidio/cycloid-cli-test-catalog.git" - CRBranch = "config-e2e" - CRCanonical = "config-repo-e2e" - CRCred = config.ConfigRepo.CredentialCanonical - ) - - defer t.Run("SuccessConfigRepositoriesDelete", func(t *testing.T) { - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "config-repo", - "delete", - "--canonical", CRCanonical, - }) - - assert.Nil(t, cmdErr) - require.Empty(t, cmdOut) - }) - - t.Run("SuccessConfigRepositoriesCreate", func(t *testing.T) { - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "config-repo", - "create", - "--name", CRCanonical, - "--branch", CRBranch, - "--cred", CRCanonical, - "--url", CRUrl, - }) - - assert.Nil(t, cmdErr) - - var result models.ConfigRepository - err := json.Unmarshal([]byte(cmdOut), &result) - assert.NoError(t, err) - assert.Equal(t, CRUrl, *result.URL) - assert.Equal(t, CRBranch, result.Branch) - assert.Equal(t, CRCanonical, *result.Canonical) - assert.Equal(t, CRCred, result.CredentialCanonical) - }) - - t.Run("SuccessConfigRepositoriesList", func(t *testing.T) { - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "config-repo", - "list", - }) - - assert.Nil(t, cmdErr) - var list []models.ConfigRepository - err := json.Unmarshal([]byte(cmdOut), &list) - assert.NoError(t, err) - - if index := slices.IndexFunc(list, func(cr models.ConfigRepository) bool { - return *cr.Canonical == CRCanonical - }); index != -1 { - result := list[index] - assert.Equal(t, CRUrl, *result.URL) - assert.Equal(t, CRBranch, result.Branch) - assert.Equal(t, CRCanonical, *result.Canonical) - assert.Equal(t, CRCred, result.CredentialCanonical) - } else { - t.Fatal("did not found our config repo in cmd output: " + cmdOut) - } - }) - - t.Run("SuccessConfigRepositoriesGet", func(t *testing.T) { - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "config-repo", - "get", - "--canonical", CRCanonical, - }) - - assert.Nil(t, cmdErr) - - var result models.ConfigRepository - err := json.Unmarshal([]byte(cmdOut), &result) - assert.NoError(t, err) - assert.Equal(t, CRUrl, *result.URL) - assert.Equal(t, CRBranch, result.Branch) - assert.Equal(t, CRCanonical, *result.Canonical) - assert.Equal(t, CRCred, result.CredentialCanonical) - }) -} diff --git a/e2e/creds_test.go b/e2e/creds_test.go deleted file mode 100644 index 28380908a..000000000 --- a/e2e/creds_test.go +++ /dev/null @@ -1,190 +0,0 @@ -package e2e_test - -import ( - "encoding/json" - "os" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/cycloidio/cycloid-cli/client/models" -) - -func TestCreds(t *testing.T) { - t.Run("SuccessCredsList", func(t *testing.T) { - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "creds", - "list", - }) - - assert.Nil(t, cmdErr) - require.Contains(t, cmdOut, "canonical\": \"vault") - }) - - t.Run("SuccessCredsGet", func(t *testing.T) { - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "creds", - "get", - "--canonical", "vault", - }) - - assert.Nil(t, cmdErr) - require.Contains(t, cmdOut, "canonical\": \"vault") - }) - - t.Run("SuccessCredsCreateCustom", func(t *testing.T) { - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "creds", - "create", - "custom", - "--name", "cli-custom", - "--canonical", "cli-custom-canonical", - "--path", "cli-custom-path", - "--field", "foo=bar", - "--field", "int=1", - }) - - defer t.Run("SuccessDelete", func(t *testing.T) { - _, err := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "creds", - "delete", - "--canonical", "cli-custom-canonical", - }) - if err != nil { - t.Errorf("failed to delete cred cli-custom: %s", err.Error()) - } - }) - - assert.Nil(t, cmdErr) - var outCred *models.Credential - err := json.Unmarshal([]byte(cmdOut), &outCred) - if err != nil { - t.Errorf("should be able to marshal cli output to a credential, cmdOut: %s\ncmdErr: %s\nerr: %s", cmdOut, cmdErr, err.Error()) - } - - // Test that the flag works - assert.NotNil(t, outCred, "cli output should contain a credential:", cmdOut, cmdErr) - assert.NotNil(t, outCred.Name, "cli output should contain a name:", cmdOut, cmdErr, outCred) - assert.NotNil(t, outCred.Canonical, "cli output should contain a canonical:", cmdOut, cmdErr, outCred) - assert.NotNil(t, outCred.Path, "cli output should contain a path:", cmdOut, cmdErr, outCred) - assert.Equal(t, "cli-custom", *outCred.Name) - assert.Equal(t, "cli-custom-canonical", *outCred.Canonical) - assert.Equal(t, "cli-custom-path", *outCred.Path) - - t.Run("Update", func(t *testing.T) { - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "creds", - "update", - "custom", - "--canonical", "cli-custom-canonical", - "--name", "cli-custom", - "--field", "foo=bar", - "--field", "int=1", - "--field", "new=field", - }) - - assert.Nil(t, cmdErr) - var outCred *models.Credential - err := json.Unmarshal([]byte(cmdOut), &outCred) - if err != nil { - t.Errorf("should be able to marshal cli output to a credential, cmdOut: %s\ncmdErr: %s\nerr: %s", cmdOut, cmdErr, err.Error()) - } - - cmdOut, cmdErr = executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "creds", - "get", - "--canonical", "cli-custom-canonical", - }) - assert.Nil(t, cmdErr) - require.Contains(t, cmdOut, "new\": \"field") - }) - - t.Run("SuccessCredsCreateCustomWithFile", func(t *testing.T) { - fileContent := "hello world" - fileName, err := WriteTempFile(fileContent) - if err != nil { - t.Errorf("failed to setup test, temp file write failed: %s", err.Error()) - } - defer os.Remove(fileName) - - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "creds", - "create", - "custom", - "--name", "cli-custom-file", - "--field", "foo=bar", - "--field-file", "key=" + fileName, - }) - assert.Nil(t, cmdErr) - defer t.Run("SuccessDelete", func(t *testing.T) { - _, err := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "creds", - "delete", - "--canonical", "cli-custom-file", - }) - if err != nil { - t.Errorf("failed to delete cred 'cli-custom-file'") - } - }) - - var outCred *models.Credential - err = json.Unmarshal([]byte(cmdOut), &outCred) - if err != nil { - t.Errorf("should be able to marshal cli output to a credential, cmdOut: %s\ncmdErr: %s\nerr: %s", cmdOut, cmdErr, err.Error()) - } - }) - - t.Run("SuccessCredsCreateSSH", func(t *testing.T) { - fileName, err := WriteTempFile(string(TestGitSSHKey)) - if err != nil { - t.Errorf("failed to setup test, temp file write failed: %s", err.Error()) - } - defer os.Remove(fileName) - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "creds", - "create", - "ssh", - "--name", "cli-ssh", - "--ssh-key", fileName, - }) - assert.Nil(t, cmdErr) - defer t.Run("SuccessDelete", func(t *testing.T) { - _, err := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "creds", - "delete", - "--canonical", "cli-ssh", - }) - if err != nil { - t.Errorf("failed to delete cred 'cli-ssh'") - } - }) - - var outCred *models.Credential - err = json.Unmarshal([]byte(cmdOut), &outCred) - if err != nil { - t.Errorf("should be able to marshal cli output to a credential, cmdOut: %s\ncmdErr: %s\nerr: %s", cmdOut, cmdErr, err.Error()) - } - }) - }) -} diff --git a/e2e/e2e.go b/e2e/e2e.go deleted file mode 100644 index 28249a0c8..000000000 --- a/e2e/e2e.go +++ /dev/null @@ -1,3 +0,0 @@ -package e2e - -// Fake package so that the e2e_test package can exists diff --git a/e2e/e2e_test.go b/e2e/e2e_test.go deleted file mode 100644 index b095d354b..000000000 --- a/e2e/e2e_test.go +++ /dev/null @@ -1,44 +0,0 @@ -package e2e_test - -import ( - "fmt" - "log" - "os" - "testing" - - "github.com/spf13/viper" - - "github.com/cycloidio/cycloid-cli/pkg/testcfg" -) - -var config *testcfg.Config - -// Put any preparation code here so that defer() can work -func runMain(main *testing.M) (int, error) { - // We must wait a bit that the middleware test are done initializing the config - // Otherwise there will be conflcts -_- - var err error - config, err = testcfg.NewConfig("e2e") - defer config.Cleanup() - if err != nil { - return 1, fmt.Errorf("test config setup failed for e2e tests: %w", err) - } - - os.Setenv("CY_API_URL", config.APIUrl) - os.Setenv("CY_API_KEY", config.APIKey) - os.Setenv("CY_ORG", config.Org) - if v := os.Getenv("CY_TEST_VERBOSITY"); v != "" { - viper.Set("verbosity", v) - } - - return main.Run(), nil -} - -func TestMain(main *testing.M) { - code, err := runMain(main) - if err != nil { - log.Fatal(err) - } - - os.Exit(code) -} diff --git a/e2e/env_var_test.go b/e2e/env_var_test.go deleted file mode 100644 index cd72b8b4e..000000000 --- a/e2e/env_var_test.go +++ /dev/null @@ -1,26 +0,0 @@ -package e2e_test - -import ( - "os" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestAPIKeyEnvVar(t *testing.T) { - for _, envVar := range []string{"CY_API_KEY", "CY_API_TOKEN", "TOKEN"} { - // We do a project list to check if we are authenticater - t.Run("SuccessProjectListWithEnvVarAuth", func(t *testing.T) { - os.Setenv(envVar, config.APIKey) - _, err := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "project", - "list", - }) - - assert.Nil(t, err, "Command should not fail using an env var for authentication") - os.Unsetenv(envVar) - }) - } -} diff --git a/e2e/environments_test.go b/e2e/environments_test.go deleted file mode 100644 index 28e2d82bf..000000000 --- a/e2e/environments_test.go +++ /dev/null @@ -1,251 +0,0 @@ -package e2e_test - -import ( - "encoding/json" - "os" - "testing" - - "github.com/stretchr/testify/assert" - - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" -) - -func TestEnvs(t *testing.T) { - os.Setenv("CY_API_URL", config.APIUrl) - os.Setenv("CY_API_KEY", config.APIKey) - os.Setenv("CY_ORG", config.Org) - - var ( - project = *config.Project.Canonical - envName = "Test E2E env" - env = randomCanonical("e2e") - ) - - t.Run("Create", func(t *testing.T) { - args := []string{ - "env", "create", - "--env", env, - "--name", envName, - } - _, err := executeCommand(args) - if err != nil { - t.Errorf("failed to create env %q: %v", env, err) - } - }) - - t.Run("Link", func(t *testing.T) { - args := []string{ - "env", "link", - "--project", project, - "--env", env, - } - _, err := executeCommand(args) - if err != nil { - t.Errorf("failed to link env %q: %v", env, err) - } - }) - - t.Run("CreateWithNameOnly", func(t *testing.T) { - var ( - nameOnly = "Environment Name " + randomCanonical("e2e") - inferred = middleware.ToCanonical(nameOnly) - ) - - args := []string{ - "--output", "json", - "env", "create", - "--name", nameOnly, - } - out, err := executeCommand(args) - if err != nil { - t.Errorf("failed to create env with name-only %q: %v", nameOnly, err) - } - - defer t.Run("DeleteNameOnlyEnv", func(t *testing.T) { - args := []string{ - "env", "delete", - "--env", inferred, - } - _, err := executeCommand(args) - if err != nil { - t.Errorf("failed to delete inferred env %q: %v", inferred, err) - } - }) - - var createdEnv models.Environment - err = json.Unmarshal([]byte(out), &createdEnv) - if err != nil { - t.Errorf("failed to parse json output for inferred env creation: %v\noutput: %s", err, out) - } - - assert.Equal(t, inferred, *createdEnv.Canonical) - assert.Equal(t, nameOnly, createdEnv.Name) - }) - - defer t.Run("Delete", func(t *testing.T) { - unlinkArgs := []string{ - "env", "unlink", - "-p", project, - "-e", env, - } - if _, err := executeCommand(unlinkArgs); err != nil { - t.Errorf("failed to unlink env %q: %v", env, err) - } - - args := []string{ - "env", "delete", - "-e", env, - } - _, err := executeCommand(args) - if err != nil { - t.Errorf("failed to delete env %q: %v", env, err) - } - }) - - t.Run("Get", func(t *testing.T) { - args := []string{ - "env", "get", - "--env", env, - "--output", "json", - } - cmdOut, err := executeCommand(args) - if err != nil { - t.Errorf("failed to get env %q: %v", env, err) - } - - var got models.Environment - err = json.Unmarshal([]byte(cmdOut), &got) - if err != nil { - t.Errorf("failed to marshal json cli output: %s\nerr: %s", cmdOut, err) - } - - assert.EqualValues(t, env, *got.Canonical) - }) - - t.Run("CreateWithUpdate", func(t *testing.T) { - createUpdateName := "helloUpdate" - args := []string{ - "-o", "json", - "env", "create", - "--env", env, - "--name", createUpdateName, - "--update", - } - out, err := executeCommand(args) - if err != nil { - t.Errorf("failed to create env %q: %v", env, err) - } - - var envResult models.Environment - err = json.Unmarshal([]byte(out), &envResult) - if err != nil { - t.Errorf("failed to parse json output from the CLI on create --update: %v\noutput: %s", err, out) - } - - assert.Equal(t, createUpdateName, envResult.Name) - }) - - t.Run("CreateWithUpdateNew", func(t *testing.T) { - newEnv := randomCanonical("e2e-env") - args := []string{ - "-o", "json", - "env", "create", - "--env", newEnv, - "--update", - } - _, err := executeCommand(args) - if err != nil { - t.Errorf("failed to create env %q: %v", newEnv, err) - } - - defer t.Run("DeleteCreateUpdate", func(t *testing.T) { - args := []string{ - "env", "delete", - "--env", newEnv, - } - _, err := executeCommand(args) - if err != nil { - t.Errorf("failed to delete env %q: %v", newEnv, err) - } - }) - }) - - t.Run("Update", func(t *testing.T) { - newName := "NewName" - args := []string{ - "-o", "json", - "env", "update", - "--name", newName, - "--env", env, - } - out, err := executeCommand(args) - if err != nil { - t.Errorf("failed to update env %q: %v", env, err) - } - - var envResult models.Environment - err = json.Unmarshal([]byte(out), &envResult) - if err != nil { - t.Errorf("failed to parse json output from the CLI on update: %v", err) - } - - assert.Equal(t, newName, envResult.Name) - }) - - t.Run("UpdateUpsertNew", func(t *testing.T) { - upsertEnv := randomCanonical("e2e-upsert") - upsertName := "Upserted Environment" - args := []string{ - "-o", "json", - "env", "update", - "--env", upsertEnv, - "--name", upsertName, - } - out, err := executeCommand(args) - if err != nil { - t.Errorf("failed to upsert env %q via update: %v", upsertEnv, err) - } - - defer t.Run("DeleteUpsertedEnv", func(t *testing.T) { - args := []string{ - "env", "delete", - "--env", upsertEnv, - } - _, err := executeCommand(args) - if err != nil { - t.Errorf("failed to delete upserted env %q: %v", upsertEnv, err) - } - }) - - var envResult models.Environment - err = json.Unmarshal([]byte(out), &envResult) - if err != nil { - t.Errorf("failed to parse json output from update upsert: %v\noutput: %s", err, out) - } - - assert.Equal(t, upsertEnv, *envResult.Canonical) - assert.Equal(t, upsertName, envResult.Name) - }) - - t.Run("UpdateExplicitEmptyCloudAccounts", func(t *testing.T) { - args := []string{ - "-o", "json", - "env", "update", - "--env", env, - "--cloud-account", "", - } - out, err := executeCommand(args) - if err != nil { - t.Errorf("failed to clear cloud accounts on env %q: %v", env, err) - } - - var envResult models.Environment - err = json.Unmarshal([]byte(out), &envResult) - if err != nil { - t.Errorf("failed to parse json output from explicit empty cloud-account update: %v\noutput: %s", err, out) - } - - assert.Empty(t, envResult.CloudAccounts) - }) -} diff --git a/e2e/events_test.go b/e2e/events_test.go deleted file mode 100644 index cf495f9d4..000000000 --- a/e2e/events_test.go +++ /dev/null @@ -1,42 +0,0 @@ -package e2e_test - -import ( - "encoding/json" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/cycloidio/cycloid-cli/client/models" -) - -func TestEvents(t *testing.T) { - t.Run("SuccessEventsSend", func(t *testing.T) { - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "events", - "create", - "--tag", "foo=bar", - "--title", "CLI e2e", - "--message", "hello", - }) - - require.Nil(t, cmdErr) - assert.Equal(t, "", cmdOut) - }) - - t.Run("SuccessEventsList", func(t *testing.T) { - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "events", - "list", - }) - - require.Nil(t, cmdErr) - var events []*models.Event - err := json.Unmarshal([]byte(cmdOut), &events) - require.Nil(t, err, "CLI output should deserialize to []*models.Event, out: %s", cmdOut) - }) -} diff --git a/e2e/external_backends_test.go b/e2e/external_backends_test.go deleted file mode 100644 index 3974c58f7..000000000 --- a/e2e/external_backends_test.go +++ /dev/null @@ -1,101 +0,0 @@ -package e2e_test - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestExternalBackends(t *testing.T) { - // Prepare: create the AWS credential needed for the logs backend test - t.Run("CleanupAndPrepare", func(t *testing.T) { - // Clean external backends if exist - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "external-backends", - "list", - }) - - require.Nil(t, cmdErr) - cs, err := JSONListExtractFields(cmdOut, "id", "", "") - require.Nil(t, err) - - for _, c := range cs { - executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "eb", - "delete", - "--id", c, - }) - } - - // Create AWS credential for the CloudWatch logs test - executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "creds", - "create", - "aws", - "--name", "eb-aws", - "--access-key", "foo", - "--secret-key", "bar", - }) - }) - - t.Run("SuccessExternalBackendsCreateAWSRemoteTFState", func(t *testing.T) { - // TODO: Fix tests when components are implemented (BE-XXXX) - t.Skip("blocked: requires component-level infraview support") - - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "external-backends", - "create", - "infraview", - "AWSRemoteTFState", - "--bucket-name", "eb-ifraview-aws", - "--bucket-path", "/foo", - "--cred", "eb-aws", - "--project", *config.Project.Canonical, - "--env", *config.Environment.Canonical, - }) - - assert.Nil(t, cmdErr) - require.Contains(t, cmdOut, "purpose\": \"remote_tfstate") - }) - - t.Run("SuccessExternalBackendsCreateAWSCloudWatchLogs", func(t *testing.T) { - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "external-backends", - "create", - "logs", - "AWSCloudWatchLogs", - "--cred", "eb-aws", - "--project", *config.Project.Canonical, - "--region", "eu-west-1", - }) - - assert.Nil(t, cmdErr) - require.Contains(t, cmdOut, "purpose\": \"logs") - }) - - t.Run("SuccessExternalBackendsList", func(t *testing.T) { - // TODO: Fix tests when components are implemented (BE-XXXX) - t.Skip("blocked: list expects remote_tfstate entry from skipped infraview test") - - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "external-backends", - "list", - }) - - assert.Nil(t, cmdErr) - require.Contains(t, cmdOut, "purpose\": \"remote_tfstate") - }) -} diff --git a/e2e/helpers_test.go b/e2e/helpers_test.go deleted file mode 100644 index c479bbfd8..000000000 --- a/e2e/helpers_test.go +++ /dev/null @@ -1,275 +0,0 @@ -package e2e_test - -import ( - "bytes" - "encoding/json" - "errors" - "fmt" - "io" - "math/rand" - "os" - "regexp" - "strings" - "testing" - "time" - - "github.com/spf13/cobra" - "github.com/stretchr/testify/assert" - - "github.com/cycloidio/cycloid-cli/cmd" -) - -func TestExecuteCommandStdin(t *testing.T) { - cmd := &cobra.Command{ - RunE: func(cmd *cobra.Command, args []string) error { - in, err := io.ReadAll(cmd.InOrStdin()) - if err != nil { - return err - } - - cmd.OutOrStdout().Write(in) - return nil - }, - } - - expected := `My stdin` - stdoutBuf := new(bytes.Buffer) - reader := strings.NewReader(expected) - _, err := reader.Seek(0, 0) - if err != nil { - t.Fatal(err) - } - - cmd.SetIn(reader) - cmd.SetOut(stdoutBuf) - err = cmd.Execute() - if err != nil { - t.Errorf("command failed: %s", err) - } - - stdout, err := io.ReadAll(stdoutBuf) - if err != nil { - t.Errorf("failed to read cmd output: %s", err) - } - - assert.Equal(t, expected, string(stdout)) -} - -var ( - now = time.Now() - NowTimestamp = now.UnixNano() - - TestGitSSHKey = []byte(`-----BEGIN OPENSSH PRIVATE KEY----- -b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW -QyNTUxOQAAACD8O9mhkl5CAiD0NLeQcoPf1duYHImQlTjOXcCOgHmC+AAAAJjCF9jzwhfY -8wAAAAtzc2gtZWQyNTUxOQAAACD8O9mhkl5CAiD0NLeQcoPf1duYHImQlTjOXcCOgHmC+A -AAAEC0ryBZ1uJQ2drmjsO+WpsC2E/5SWheJD/r8+Q4LghWxfw72aGSXkICIPQ0t5Byg9/V -25gciZCVOM5dwI6AeYL4AAAAE2N5Y2xvaWRAZXhhbXBsZS5jb20BAg== ------END OPENSSH PRIVATE KEY-----`) - - TestPipelineSample = []byte(`jobs: -- name: job-hello-world - build_logs_to_retain: 3 - plan: - - task: hello-world - config: - platform: linux - image_resource: - type: docker-image - source: {repository: busybox} - run: - path: /bin/sh - args: - - -ec - - | - echo ${MESSAGE} - params: - MESSAGE: ((message))`) - - TestPipelineVariables = []byte(`message: "hello world and especially to ($ organization_canonical $)"`) - - // TestTerraformPlanSample is a minimal valid Terraform plan JSON used for - // terracost estimate and infrapolicy validate tests. - TestTerraformPlanSample = []byte(`{ - "format_version": "1.1", - "terraform_version": "1.5.0", - "variables": {}, - "planned_values": {"root_module": {}}, - "resource_changes": [], - "prior_state": {"format_version": "1.0", "values": {"root_module": {}}}, - "configuration": {"root_module": {}} -}`) - - TestInfraPolicySample = []byte(` - package test - import input.tfplan as tfplan - resource_types = { "aws_instance" } - - tags_ok(index) { - tfplan.resource_changes[index].change.after.tags["env"] == "test" - } - - deny[reason] { - resources_not_ok := [resource_not_ok | resource_types[i] == tfplan.resource_changes[j].type - not tags_ok(j); - resource_not_ok := resource_types[i]] - reason = sprintf("tag not in env: %s %s", [(resources_not_ok), test]) - } -`) -) - -// executeCommandStdin will execute the command with args + stdin input -// and return stdin, stderr and err -func executeCommandStdin(stdin string, args []string) (string, string, error) { - cmd := cmd.NewRootCommand() - - stdoutBuf := new(bytes.Buffer) - stderrBuf := new(bytes.Buffer) - cmd.SetOut(stdoutBuf) - cmd.SetErr(stderrBuf) - - cmd.SetIn(strings.NewReader(stdin)) - oldStdin := os.Stdin - defer func() { - os.Stdin = oldStdin - }() - file, err := os.CreateTemp("", "stdin") - if err != nil { - return "", "", fmt.Errorf("test setup failed: %w", err) - } - defer file.Close() - defer os.Remove(file.Name()) - - err = os.WriteFile(file.Name(), []byte(stdin), 0666) - if err != nil { - return "", "", fmt.Errorf("test setup failed: %w", err) - } - os.Stdin = file - - cmd.SetArgs(args) - cmdErr := cmd.Execute() - stdout, err := io.ReadAll(stdoutBuf) - if err != nil { - return "", "", errors.Join(cmdErr, fmt.Errorf("failed to read stdout buffer from cli: %w", err)) - } - - stderr, err := io.ReadAll(stderrBuf) - if err != nil { - return string(stdout), "", errors.Join(cmdErr, fmt.Errorf("failed to read stderr buffer from cli: %w", err)) - } - - return string(stdout), string(stderr), cmdErr -} - -func executeCommand(args []string) (string, error) { - cmd := cmd.NewRootCommand() - - buf := new(bytes.Buffer) - errBuf := new(bytes.Buffer) - cmd.SetOut(buf) - cmd.SetErr(errBuf) - - cmd.SetArgs(args) - cmdErr := cmd.Execute() - cmdOut, err := io.ReadAll(buf) - if err != nil { - panic("Unable to read command output buffer") - } - return string(cmdOut), cmdErr -} - -// AddNowTimestamp add a timestamp suffix to a string -func AddNowTimestamp(txt string) string { - return fmt.Sprintf(txt, NowTimestamp) -} - -func WriteFile(path string, data []byte) { - err := os.WriteFile(path, data, 0644) - if err != nil { - panic(fmt.Sprintf("Test setup, unable to write file %q: %v", path, err)) - } -} - -// toString convert interface from default json unmarchal to string -func toString(value any) string { - out := "" - // Handle the value conversion based on unmarchal default types - switch v := value.(type) { - case string: - out = v - case float64: - out = fmt.Sprint(v) - default: - // Skip, unsuported - } - return out -} - -// JSONListExtractFields Extract a field from a json entity -func JSONListExtractFields(js string, field, filterField, filterRegex string) ([]string, error) { - var es []any - var out []string - - err := json.Unmarshal([]byte(js), &es) - if err != nil { - return nil, err - } - - for _, e := range es { - // Cast our map from default json unmarchal - m := e.(map[string]any) - - value := toString(m[field]) - - // Filter - if filterField != "" { - fv := toString(m[filterField]) - re := regexp.MustCompile(filterRegex) - if re.MatchString(fv) { - out = append(out, value) - } - } else { - out = append(out, value) - } - } - - return out, nil -} - -func JSONListFindObjectValue(list []map[string]any, key, value string) bool { - for _, item := range list { - if item[key] == value { - return true - } - } - - return false -} - -// WriteTempFile will write the content to a temporary file and -// return the file path. -func WriteTempFile(content string) (string, error) { - file, err := os.CreateTemp("", "cli-test-*") - if err != nil { - return "", fmt.Errorf("failed to create temp file: %w", err) - } - - _, err = file.WriteString(content) - if err != nil { - return "", fmt.Errorf("failed to write to temp file %q: %w", file.Name(), err) - } - - return file.Name(), nil -} - -// randomCanonical will add 4 random letter after the baseName -func randomCanonical(baseName string) string { - var size = 4 - var letterRunes = []rune("abcdefghijklmnopqrstuvwxyz") - - b := make([]rune, size) - for i := range b { - b[i] = letterRunes[rand.Intn(len(letterRunes))] - } - return baseName + "-" + strings.ToLower(string(b)) -} diff --git a/e2e/kpis_test.go b/e2e/kpis_test.go deleted file mode 100644 index 53dfb8c6f..000000000 --- a/e2e/kpis_test.go +++ /dev/null @@ -1,170 +0,0 @@ -package e2e_test - -import ( - "fmt" - "regexp" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -var createdKpi string - -func TestKpis(t *testing.T) { - t.Skip() - - // Prepare a running project - t.Run("CleanupAndPrepare", func(t *testing.T) { - - // Clean kpi if exist - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "kpis", - "list", - }) - require.Nil(t, cmdErr) - cs, err := JSONListExtractFields(cmdOut, "canonical", "canonical", "^test-.*") - require.Nil(t, err) - - for _, c := range cs { - executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "kpis", - "delete", - "--canonical", c, - }) - } - - // Create ssh cred - WriteFile("/tmp/test_cli-ssh", TestGitSSHKey) - executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "creds", - "create", - "ssh", - "--name", "git-project-creds", - "--ssh-key", "/tmp/test_cli-ssh", - }) - - // // Create config repo - // executeCommand([]string{ - // "--output", "json", - // "--org", config.Org, - // "config-repo", - // "create", - // "--name", "project-config", - // "--branch", CY_TEST_GIT_CR_BRANCH, - // "--cred", "git-project-creds", - // "--url", CY_TEST_GIT_CR_URL, - // }) - - // Provide service catalog public - executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "catalog-repository", - "create", - "--branch", "master", - "--url", "https://github.com/cycloid-community-catalog/stack-dummy.git", - "--name", "dummy", - }) - - // Create project - WriteFile("/tmp/test_cli-pp-vars", TestPipelineVariables) - WriteFile("/tmp/test_cli-pp", TestPipelineSample) - executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "project", - "create", - "--name", "kpi-test", - "--description", "this is a test project", - "--stack-ref", fmt.Sprintf("%s:stack-dummy", config.Org), - "--config-repo", "project-config", - }) - - executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "project", - "create-env", - "--project", "kpi-test", - "--env", "test", - "--use-case", "default", - "--vars", "/tmp/test_cli-pp-vars", - "--pipeline", "/tmp/test_cli-pp", - "--config", "/tmp/test_cli-pp=/snowy/test/test_cli-pp", - }) - - // Ensure the catalog is present - cmdOut, cmdErr = executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "project", - "get", - "--project", "kpi-test", - }) - - assert.Nil(t, cmdErr) - require.Contains(t, cmdOut, "canonical\": \"kpi-test") - }) - - t.Run("SuccessKpisCreate", func(t *testing.T) { - // TODO: Fix tests when components are implemented - t.Skip() - - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "kpis", - "create", - "--name", "test", - "--type", "build_history", - "--widget", "history", - "--project", "kpi-test", - "--env", "test", - "--job", "job-hello-world", - }) - - require.Nil(t, cmdErr) - require.Contains(t, cmdOut, "canonical\": \"test-") - }) - - t.Run("SuccessKpisList", func(t *testing.T) { - // TODO: Fix tests when components are implemented - t.Skip() - - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "kpis", - "list", - }) - - require.Nil(t, cmdErr) - require.Contains(t, cmdOut, "canonical\": \"test-") - - re := regexp.MustCompile(`canonical": "(test-[^"]+)"`) - createdKpi = re.FindAllStringSubmatch(cmdOut, 1)[0][1] - }) - - t.Run("SuccessKpisDelete", func(t *testing.T) { - // TODO: Fix tests when components are implemented - t.Skip() - - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "kpis", - "delete", - "--canonical", createdKpi, - }) - - require.Nil(t, cmdErr) - assert.Equal(t, "", cmdOut) - }) -} diff --git a/e2e/licence_test.go b/e2e/licence_test.go deleted file mode 100644 index aacefc0dc..000000000 --- a/e2e/licence_test.go +++ /dev/null @@ -1,95 +0,0 @@ -package e2e_test - -import ( - "encoding/json" - "os" - "path/filepath" - "strings" - "testing" - - "github.com/matryer/is" - "github.com/stretchr/testify/require" - - "github.com/cycloidio/cycloid-cli/client/models" -) - -func TestLicence(t *testing.T) { - licenceKey, ok := os.LookupEnv("API_LICENCE_KEY") - require.True(t, ok, "API_LICENCE_KEY must be set for licence e2e tests") - - t.Run("SuccessLicenceActivateAndGet", func(t *testing.T) { - is := is.New(t) - - _, cmdErr := executeCommand([]string{ - "--org", config.Org, - "organization", "licence", "activate", - "--key", licenceKey, - }) - is.NoErr(cmdErr) - - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "organization", "licence", "get", - }) - is.NoErr(cmdErr) - - var out models.Licence - err := json.Unmarshal([]byte(cmdOut), &out) - is.NoErr(err) - require.NotNil(t, out.Key) - is.Equal(licenceKey, *out.Key) - }) - - t.Run("SuccessLicenceActivateFromFile", func(t *testing.T) { - is := is.New(t) - - dir := t.TempDir() - licenceFile := filepath.Join(dir, "licence.jwt") - err := os.WriteFile(licenceFile, []byte(licenceKey), 0o600) - require.NoError(t, err) - - _, cmdErr := executeCommand([]string{ - "--org", config.Org, - "organization", "licence", "activate", - "--key-file", licenceFile, - }) - is.NoErr(cmdErr) - }) - - t.Run("SuccessLicenceActivateFromStdin", func(t *testing.T) { - is := is.New(t) - - _, _, err := executeCommandStdin(licenceKey, []string{ - "--org", config.Org, - "organization", "licence", "activate", - }) - is.NoErr(err) - }) - - t.Run("SuccessLicenceActivateOverwrite", func(t *testing.T) { - is := is.New(t) - - _, cmdErr := executeCommand([]string{ - "--org", config.Org, - "organization", "licence", "activate", - "--key", licenceKey, - }) - is.NoErr(cmdErr) - - _, cmdErr = executeCommand([]string{ - "--org", config.Org, - "organization", "licence", "activate", - "--key", licenceKey, - }) - is.NoErr(cmdErr) - - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "organization", "licence", "get", - }) - is.NoErr(cmdErr) - is.True(strings.Contains(cmdOut, licenceKey)) - }) -} diff --git a/e2e/login_test.go b/e2e/login_test.go deleted file mode 100644 index 921c60687..000000000 --- a/e2e/login_test.go +++ /dev/null @@ -1,35 +0,0 @@ -package e2e_test - -import ( - "os" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestLogin(t *testing.T) { - t.Run("SuccessOrgLoginLegacy", func(t *testing.T) { - cmdOut, cmdErr := executeCommand([]string{ - "login", - "--org", config.Org, - "--api-key", config.APIKey, - }) - - require.Nil(t, cmdErr) - assert.Equal(t, "", cmdOut) - }) - - t.Run("SuccessOrgLogin", func(t *testing.T) { - err := os.Setenv("CY_API_KEY", config.APIKey) - require.Nil(t, err) - - cmdOut, cmdErr := executeCommand([]string{ - "login", - "--org", config.Org, - }) - - require.Nil(t, cmdErr) - assert.Equal(t, "", cmdOut) - }) -} diff --git a/e2e/members_test.go b/e2e/members_test.go deleted file mode 100644 index d33d7b9d7..000000000 --- a/e2e/members_test.go +++ /dev/null @@ -1,147 +0,0 @@ -package e2e_test - -import ( - "encoding/json" - "fmt" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestMembers(t *testing.T) { - // Cleanup invites in case of a previous test - t.Run("CleanupPreviousInvites", func(t *testing.T) { - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "members", - "list-invites", - }) - - require.Nil(t, cmdErr) - ids, err := JSONListExtractFields(cmdOut, "id", "email", "^foo@bli.fr$") - require.Nil(t, err) - - for _, id := range ids { - executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "members", - "delete-invite", - "--invite", id, - }) - } - }) - - t.Run("SuccessMembersList", func(t *testing.T) { - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "members", - "list", - }) - - require.Nil(t, cmdErr) - - var memberList []map[string]interface{} - err := json.Unmarshal([]byte(cmdOut), &memberList) - require.Nil(t, err, "unmarshalling cli json output") - - ok := JSONListFindObjectValue(memberList, "email", "admin@cycloid.io") - assert.True(t, ok, fmt.Sprint("member with admin@cycloid.io email address not found in json:\n", cmdOut)) - }) - - t.Run("SuccessMembersGet", func(t *testing.T) { - // Look up the admin member's numeric ID from the list - listOut, listErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "members", - "list", - }) - require.Nil(t, listErr, "members list should not fail") - - ids, err := JSONListExtractFields(listOut, "id", "email", "^admin@cycloid.io$") - require.Nil(t, err) - require.NotEmpty(t, ids, "admin member should be in the list") - - adminID := ids[0] - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "members", - "get", - "--id", adminID, - }) - - require.Nil(t, cmdErr, "CLI should not error on members get") - - var member map[string]any - err = json.Unmarshal([]byte(cmdOut), &member) - require.Nil(t, err, "we should be able to serialize the CLI json output: ", cmdOut) - - assert.Equal(t, "admin@cycloid.io", member["email"], - "member with admin@cycloid.io email address not found in json:\n", cmdOut) - }) - - t.Run("SuccessMembersUpdate", func(t *testing.T) { - // Look up the admin member's numeric ID from the list - listOut, listErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "members", - "list", - }) - require.Nil(t, listErr, "members list should not fail") - - ids, err := JSONListExtractFields(listOut, "id", "email", "^admin@cycloid.io$") - require.Nil(t, err) - require.NotEmpty(t, ids, "admin member should be in the list") - - adminID := ids[0] - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "members", - "update", - "--id", adminID, - "--role", "organization-admin", - }) - - require.Nil(t, cmdErr, "members update should not fail") - assert.NotEmpty(t, cmdOut, "members update should return the updated member") - }) - - t.Run("SuccessMembersInvite", func(t *testing.T) { - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "members", - "invite", - "--email", "foo@bli.fr", - "--role", "organization-admin", - }) - - require.Nil(t, cmdErr) - assert.NotEmpty(t, cmdOut, "invite should return the created invitation") - }) - - t.Run("SuccessMembersListInvite", func(t *testing.T) { - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "members", - "list-invites", - }) - - require.Nil(t, cmdErr) - - var memberList []map[string]interface{} - err := json.Unmarshal([]byte(cmdOut), &memberList) - require.Nil(t, err, "unmarshalling cli json output") - - ok := JSONListFindObjectValue(memberList, "invitation_email", "foo@bli.fr") - assert.True(t, ok, fmt.Sprint("member with foo@bli.fr email address not found in json:\n", cmdOut)) - }) -} diff --git a/e2e/oidc_test.go b/e2e/oidc_test.go deleted file mode 100644 index 77ee35d91..000000000 --- a/e2e/oidc_test.go +++ /dev/null @@ -1,207 +0,0 @@ -package e2e_test - -import ( - "encoding/json" - "fmt" - "strconv" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" -) - -func TestOIDC(t *testing.T) { - // -------------------------------------------------------------------- - // Mappings CRUD - // -------------------------------------------------------------------- - - // We need a team to map to. Reuse the fixture team created by TestTeams - // if available, or create a disposable one here. - teamCan := randomCanonical("oidc-team") - - t.Run("SetupTeam", func(t *testing.T) { - _, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "team", "create", - "--name", teamCan, - "--role", "organization-member", - }) - require.NoError(t, cmdErr, "setup: team create should succeed") - }) - - // defer t.Run ensures cleanup runs after all subtests, even on failure. - // This is safe because t is still alive when deferred functions execute. - defer t.Run("TeardownTeam", func(t *testing.T) { - executeCommand([]string{ //nolint:errcheck - "--output", "json", - "--org", config.Org, - "team", "delete", teamCan, - }) - }) - - var mappingID uint32 - - t.Run("SuccessOIDCMappingCreate", func(t *testing.T) { - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "oidc", "mappings", "create", - "--group-name", "my-oidc-group", - "--team", teamCan, - }) - require.NoError(t, cmdErr, "mappings create should succeed") - - var m middleware.OIDCGroupMapping - err := json.Unmarshal([]byte(cmdOut), &m) - require.NoError(t, err, "output should be a valid OIDCGroupMapping JSON") - assert.NotZero(t, m.ID, "created mapping should have a non-zero ID") - assert.Equal(t, "my-oidc-group", m.GroupName, "group name should match") - require.NotNil(t, m.Team, "team should be set") - assert.Equal(t, teamCan, m.Team.Canonical, "team canonical should match") - - mappingID = m.ID - }) - - t.Run("SuccessOIDCMappingList", func(t *testing.T) { - require.NotZero(t, mappingID, "create test must have run successfully first") - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "oidc", "mappings", "list", - }) - require.NoError(t, cmdErr, "mappings list should succeed") - - var mappings []middleware.OIDCGroupMapping - err := json.Unmarshal([]byte(cmdOut), &mappings) - require.NoError(t, err, "output should be a valid JSON array of OIDCGroupMapping") - - found := false - for _, m := range mappings { - if m.ID == mappingID { - found = true - assert.Equal(t, "my-oidc-group", m.GroupName) - break - } - } - assert.True(t, found, fmt.Sprintf("mapping ID %d should appear in list output", mappingID)) - }) - - t.Run("SuccessOIDCMappingDelete", func(t *testing.T) { - require.NotZero(t, mappingID, "create test must have run successfully first") - _, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "oidc", "mappings", "delete", - "--mapping-id", strconv.FormatUint(uint64(mappingID), 10), - }) - require.NoError(t, cmdErr, "mappings delete should succeed") - }) - - // Verify deletion - t.Run("SuccessOIDCMappingListAfterDelete", func(t *testing.T) { - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "oidc", "mappings", "list", - }) - require.NoError(t, cmdErr, "mappings list after delete should succeed") - - var mappings []middleware.OIDCGroupMapping - err := json.Unmarshal([]byte(cmdOut), &mappings) - require.NoError(t, err, "output should parse as JSON array") - - for _, m := range mappings { - assert.NotEqual(t, mappingID, m.ID, "deleted mapping should no longer appear in list") - } - }) - - // -------------------------------------------------------------------- - // Settings get / set - // -------------------------------------------------------------------- - - t.Run("SuccessOIDCSettingsGet", func(t *testing.T) { - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "oidc", "settings", "get", - }) - require.NoError(t, cmdErr, "settings get should succeed") - - var s middleware.OIDCOrganizationSettings - err := json.Unmarshal([]byte(cmdOut), &s) - require.NoError(t, err, "output should be a valid OIDCOrganizationSettings JSON") - }) - - t.Run("SuccessOIDCSettingsSet", func(t *testing.T) { - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "oidc", "settings", "set", - "--oidc-managed=false", - "--no-match-policy", "keep_membership", - }) - require.NoError(t, cmdErr, "settings set should succeed") - - var s middleware.OIDCOrganizationSettings - err := json.Unmarshal([]byte(cmdOut), &s) - require.NoError(t, err, "output should be a valid OIDCOrganizationSettings JSON") - assert.Equal(t, "keep_membership", s.OIDCNoMatchPolicy) - assert.False(t, s.OIDCManaged) - }) - - t.Run("SuccessOIDCSettingsGetAfterSet", func(t *testing.T) { - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "oidc", "settings", "get", - }) - require.NoError(t, cmdErr, "settings get after set should succeed") - - var s middleware.OIDCOrganizationSettings - err := json.Unmarshal([]byte(cmdOut), &s) - require.NoError(t, err, "output should parse as JSON") - assert.Equal(t, "keep_membership", s.OIDCNoMatchPolicy, "no-match-policy should persist") - }) - - // -------------------------------------------------------------------- - // Integration get / set - // -------------------------------------------------------------------- - - t.Run("SuccessOIDCIntegrationSet", func(t *testing.T) { - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "oidc", "integration", "set", - "--issuer", "https://idp.example.com", - "--client-id", "test-client", - "--enabled", - }) - require.NoError(t, cmdErr, "integration set should succeed") - - var i middleware.OIDCIntegration - err := json.Unmarshal([]byte(cmdOut), &i) - require.NoError(t, err, "output should be a valid OIDCIntegration JSON") - assert.True(t, i.Enabled, "integration should be enabled") - assert.Equal(t, "test-client", i.OidcClientID, "client ID should match") - assert.Equal(t, "https://idp.example.com", i.OidcIssuer, "issuer should match") - }) - - t.Run("SuccessOIDCIntegrationGet", func(t *testing.T) { - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "oidc", "integration", "get", - }) - require.NoError(t, cmdErr, "integration get should succeed") - - var i middleware.OIDCIntegration - err := json.Unmarshal([]byte(cmdOut), &i) - require.NoError(t, err, "output should be a valid OIDCIntegration JSON") - assert.True(t, i.Enabled, "integration should still be enabled after get") - assert.Equal(t, "test-client", i.OidcClientID, "client ID should persist") - assert.Equal(t, "https://idp.example.com", i.OidcIssuer, "issuer should persist") - }) -} diff --git a/e2e/organizations_test.go b/e2e/organizations_test.go deleted file mode 100644 index 5df8df8f8..000000000 --- a/e2e/organizations_test.go +++ /dev/null @@ -1,175 +0,0 @@ -package e2e_test - -import ( - "encoding/json" - "slices" - "testing" - "time" - - "github.com/matryer/is" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/pkg/testcfg" -) - -func TestOrganizations(t *testing.T) { - t.Run("SuccessOrganizationsList", func(t *testing.T) { - // organization list requires a user token; it returns 422 when called with an API key. - // The e2e tests authenticate via API key, so this endpoint cannot be tested here. - t.Skip("organization list is not supported with API key authentication (422)") - }) - - t.Run("SuccessOrganizationsGet", func(t *testing.T) { - is := is.New(t) - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "organization", - "get", - }) - is.NoErr(cmdErr) // cmd should not fail - - var outOrg *models.Organization - err := json.Unmarshal([]byte(cmdOut), &outOrg) - is.NoErr(err) // JSON output should be a valid model - is.Equal(config.Org, *outOrg.Canonical) // org canonicals should match - }) - - childOrg := testcfg.RandomCanonical("e2e-child") - t.Run("SuccessOrganizationsCreateChild", func(t *testing.T) { - is := is.New(t) - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "organization", - "create", - "--name", childOrg, - "--parent-canonical", config.Org, - }) - is.NoErr(cmdErr) // command should not fail - defer t.Run("SuccessDeleteOrg", func(t *testing.T) { - is := is.New(t) - _, deleteErr := executeCommand([]string{ - "--output", "json", - "organization", - "delete", - "--org", childOrg, - }) - is.NoErr(deleteErr) // command should not fail - }) - - var outOrg *models.Organization - err := json.Unmarshal([]byte(cmdOut), &outOrg) - is.NoErr(err) // JSON output should be a valid model - is.Equal(childOrg, *outOrg.Canonical) // org canonicals should match - - t.Run("SuccessOrganizationsCreateChildDuplicateWithoutUpdateErrors", func(t *testing.T) { - _, cmdErr := executeCommand([]string{ - "--output", "json", - "organization", - "create", - "--name", childOrg, - "--parent-canonical", config.Org, - }) - require.Error(t, cmdErr, "second create without --update must fail") - }) - - t.Run("SuccessOrganizationsCreateChildWithUpdate", func(t *testing.T) { - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "organization", - "create", - "--update", - "--name", childOrg, - "--parent-canonical", config.Org, - }) - require.NoError(t, cmdErr) - - var again *models.Organization - err := json.Unmarshal([]byte(cmdOut), &again) - require.NoError(t, err) - require.NotNil(t, again) - require.NotNil(t, again.Canonical) - assert.Equal(t, childOrg, *again.Canonical) - }) - - t.Run("SuccessOrganizationsUpdate", func(t *testing.T) { - is := is.New(t) - updatedName := childOrg + "-updated" - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", childOrg, - "organization", "update", - "--name", updatedName, - }) - is.NoErr(cmdErr) // update should not fail - - var outOrg *models.Organization - err := json.Unmarshal([]byte(cmdOut), &outOrg) - is.NoErr(err) // output should be deserializable - is.Equal(updatedName, *outOrg.Name) // name should be updated - }) - - t.Run("SuccessOrganizationsAddSubscription", func(t *testing.T) { - _, cmdErr := executeCommand([]string{ - "--output", "json", - "organization", "subscription", - "update", - "--org", childOrg, - "--member-count", "10", - "--expires-at", time.Now().AddDate(1, 0, 0).Format(time.RFC3339), - }) - assert.NoError(t, cmdErr, "command should be okay") - }) - - t.Run("SuccessOrganizationsAddSubscriptionOverwriteOk", func(t *testing.T) { - _, cmdErr := executeCommand([]string{ - "--output", "json", - "organization", "subscription", - "update", - "--update", - "--org", childOrg, - "--member-count", "5", - "--expires-at", time.Now().AddDate(1, 0, 0).Format(time.RFC3339), - }) - assert.NoError(t, cmdErr, "We should be able to overwrite the sub") - }) - - t.Run("SuccessOrganizationsListChildrens", func(t *testing.T) { - is := is.New(t) - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "organization", - "list-childrens", - "--org", config.Org, - }) - is.NoErr(cmdErr) // command should not fail - - var outOrgs []*models.Organization - err := json.Unmarshal([]byte(cmdOut), &outOrgs) - is.NoErr(err) // output should be deserializable orgs - - // We try to find the new child org - index := slices.IndexFunc(outOrgs, func(o *models.Organization) bool { - return *o.Canonical == childOrg - }) - is.True(index != -1) // if -1, means that we can't find our new child org in list. Should be there. - }) - - t.Run("SuccessOrganizationsListWorkers", func(t *testing.T) { - is := is.New(t) - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "organization", - "list-workers", - }) - is.NoErr(cmdErr) // cmd should not fail - - var workers []*models.Worker - err := json.Unmarshal([]byte(cmdOut), &workers) - is.NoErr(err) // output should be deserializable - }) - }) -} diff --git a/e2e/pipelines_test.go b/e2e/pipelines_test.go deleted file mode 100644 index d789a68d5..000000000 --- a/e2e/pipelines_test.go +++ /dev/null @@ -1,309 +0,0 @@ -package e2e_test - -import ( - "encoding/json" - "os" - "strconv" - "testing" - - "github.com/sanity-io/litter" - "github.com/stretchr/testify/assert" - - "github.com/cycloidio/cycloid-cli/client/models" -) - -func TestPipelines(t *testing.T) { - // Pipelines - var pipelineList []*models.Pipeline - t.Run("PipelineListOk", func(t *testing.T) { - listOut, listErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "pipelines", "list", - }) - if listErr != nil { - t.Errorf("List org pipeline should not err, out: %s\nerr: %s", listOut, listErr) - } - - err := json.Unmarshal([]byte(listOut), &pipelineList) - if err != nil { - t.Errorf("failed to unmarshall list test output, out: %s\nerr: %s", listOut, err) - } - - if len(pipelineList) == 0 { - t.Errorf("There should be at least one pipeline in this org:\n%s", listOut) - } - }) - - firstPipeline := *pipelineList[0] - t.Run("GetPipelineOk", func(t *testing.T) { - getOut, getErr := executeCommand([]string{ - "--output", "json", - "pipelines", "get", - "--project", *firstPipeline.Project.Canonical, - "--env", *firstPipeline.Environment.Canonical, - "--component", *firstPipeline.Component.Canonical, - "--pipeline", *firstPipeline.Name, - }) - if getErr != nil { - t.Errorf("get pipeline should not err, out: %s\nerr: %s", getOut, getErr) - } - - var getPipeline models.Pipeline - err := json.Unmarshal([]byte(getOut), &getPipeline) - if err != nil { - t.Errorf("Failed to parse json output of pipelines get cmd, out: %s\nerr: %s", getOut, err) - } - - if assert.ObjectsAreEqualValues(firstPipeline, getPipeline) { - t.Errorf("both pipelines should be equal:\nexpect: %v\ngot: %v", firstPipeline, getPipeline) - } - }) - - t.Run("PipelinePauseOk", func(t *testing.T) { - _, pauseErr := executeCommand([]string{ - "--output", "json", - "pipelines", "pause", - "--project", *firstPipeline.Project.Canonical, - "--env", *firstPipeline.Environment.Canonical, - "--component", *firstPipeline.Component.Canonical, - "--pipeline", *firstPipeline.Name, - }) - if pauseErr != nil { - t.Errorf("failed to pause pipeline '%s': %s", *firstPipeline.Name, pauseErr) - } - }) - - t.Run("PipelineUnpauseOk", func(t *testing.T) { - _, unpauseErr := executeCommand([]string{ - "--output", "json", - "pipelines", "unpause", - "--project", *firstPipeline.Project.Canonical, - "--env", *firstPipeline.Environment.Canonical, - "--component", *firstPipeline.Component.Canonical, - "--pipeline", *firstPipeline.Name, - }) - if unpauseErr != nil { - t.Errorf("failed to unpause pipeline '%s': %s", *firstPipeline.Name, unpauseErr) - } - }) - - t.Run("PipelineSynced", func(t *testing.T) { - _, syncedErr := executeCommand([]string{ - "--output", "json", - "pipelines", "synced", - "--project", *firstPipeline.Project.Canonical, - "--env", *firstPipeline.Environment.Canonical, - "--component", *firstPipeline.Component.Canonical, - "--pipeline", *firstPipeline.Name, - }) - if syncedErr != nil { - t.Errorf("failed to pause pipeline '%s': %s", *firstPipeline.Name, syncedErr) - } - }) - - t.Run("PipelineLastUsedOk", func(t *testing.T) { - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "pipelines", "last-used", - "--since-days", "99", - }) - if cmdErr != nil { - t.Errorf("failed to list last-used pipelines, out: %s\nerr: %s", cmdOut, cmdErr) - } - }) - - t.Run("PipelineDiffOk", func(t *testing.T) { - if len(pipelineList) == 0 { - t.Skip("no pipelines available") - } - - pipelineFile, err := os.CreateTemp("", "test-pipeline-*.yml") - if err != nil { - t.Fatalf("failed to create temp pipeline file: %s", err) - } - defer os.Remove(pipelineFile.Name()) - WriteFile(pipelineFile.Name(), TestPipelineSample) - - varsFile, err := os.CreateTemp("", "test-pipeline-vars-*.yml") - if err != nil { - t.Fatalf("failed to create temp pipeline vars file: %s", err) - } - defer os.Remove(varsFile.Name()) - WriteFile(varsFile.Name(), TestPipelineVariables) - - _, diffErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "pipeline", "diff", - "--project", *firstPipeline.Project.Canonical, - "--env", *firstPipeline.Environment.Canonical, - "--component", *firstPipeline.Component.Canonical, - "--pipeline", *firstPipeline.Name, - "--pipeline-config", pipelineFile.Name(), - "--pipeline-vars", varsFile.Name(), - }) - if diffErr != nil { - t.Errorf("pipeline diff should not err: %s", diffErr) - } - }) - - // Jobs - var jobList []*models.Job - t.Run("ListJobsOk", func(t *testing.T) { - if len(pipelineList) == 0 { - t.Fatal("Test setup error: pipeline list length should not be 0.") - } - - firstPipeline := pipelineList[0] - listOut, listErr := executeCommand([]string{ - "--output", "json", - "pipeline", "jobs", "list", - "--project", *firstPipeline.Project.Canonical, - "--env", *firstPipeline.Environment.Canonical, - "--component", *firstPipeline.Component.Canonical, - "--pipeline", *firstPipeline.Name, - }) - if listErr != nil { - t.Errorf("List job in pipeline %q should not err, out: %s\nerr: %s", *firstPipeline.Name, listOut, listErr) - } - - err := json.Unmarshal([]byte(listOut), &jobList) - if err != nil { - t.Errorf("failed to marshal output of cy pp job list, out: %s\nerr: %s", listOut, err) - } - - if len(jobList) == 0 { - t.Errorf("job list should not be empty:\n%s", litter.Sdump(jobList)) - } - - firstJob := jobList[0] - t.Run("JobGetOk", func(t *testing.T) { - getOut, getErr := executeCommand([]string{ - "--output", "json", - "pipeline", "job", "get", - "--project", *firstPipeline.Project.Canonical, - "--env", *firstPipeline.Environment.Canonical, - "--component", *firstPipeline.Component.Canonical, - "--pipeline", *firstPipeline.Name, - "--job", *firstJob.Name, - }) - if getErr != nil { - t.Errorf("cy get job in pipeline '%s' should not fail, out: %s\nerr: %s", *firstJob.Name, getOut, getErr) - } - - var getJob *models.Job - err := json.Unmarshal([]byte(getOut), &getJob) - if err != nil { - t.Errorf("failed to unmarshall get job cmd output, out: %s\nerr: %s", getOut, err) - } - - assert.Equal(t, *firstJob.ID, *getJob.ID) - }) - - t.Run("PauseJobOk", func(t *testing.T) { - pauseOut, pauseErr := executeCommand([]string{ - "--output", "json", - "pipeline", "job", "pause", - "--project", *firstPipeline.Project.Canonical, - "--env", *firstPipeline.Environment.Canonical, - "--component", *firstPipeline.Component.Canonical, - "--pipeline", *firstPipeline.Name, - "--job", *firstJob.Name, - }) - if pauseErr != nil { - t.Errorf("cmd cy pp job pause failed for pipeline '%s', out: %s, err: %s", *firstPipeline.Name, pauseOut, pauseErr) - } - - t.Run("UnpauseJobOk", func(t *testing.T) { - unpauseOut, unpauseErr := executeCommand([]string{ - "--output", "json", - "pipeline", "job", "unpause", - "--project", *firstPipeline.Project.Canonical, - "--env", *firstPipeline.Environment.Canonical, - "--component", *firstPipeline.Component.Canonical, - "--pipeline", *firstPipeline.Name, - "--job", *firstJob.Name, - }) - if unpauseErr != nil { - t.Errorf("cmd cy pp job unpause failed for pipeline '%s', out: %s, err: %s", *firstPipeline.Name, unpauseOut, unpauseErr) - } - }) - }) - - t.Run("PipelineClearTaskCacheOk", func(t *testing.T) { - t.Skip() - _, clearErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "pipeline", "clear-task-cache", - "--project", *firstPipeline.Project.Canonical, - "--env", *firstPipeline.Environment.Canonical, - "--component", *firstPipeline.Component.Canonical, - "--pipeline", *firstPipeline.Name, - "--job", *firstJob.Name, - }) - if clearErr != nil { - t.Errorf("pipeline clear-task-cache should not err: %s", clearErr) - } - }) - - var triggeredBuild *models.Build - // Builds - t.Run("CreateBuildOk", func(t *testing.T) { - triggerOut, triggerErr := executeCommand([]string{ - "--output", "json", - "pipeline", "build", "create", - "--project", *firstPipeline.Project.Canonical, - "--env", *firstPipeline.Environment.Canonical, - "--component", *firstPipeline.Component.Canonical, - "--pipeline", *firstPipeline.Name, - "--job", *firstJob.Name, - }) - if triggerErr != nil { - t.Errorf("cmd cy pp build create failed for job '%s' in pipeline '%s', out: %s, err: %s", *firstJob.Name, *firstPipeline.Name, triggerOut, triggerErr) - } - - err := json.Unmarshal([]byte(triggerOut), &triggeredBuild) - if err != nil { - t.Errorf("cmd output is not a models.Build, out: %s\nerr: %s", triggerOut, triggerErr) - } - - buildIDStr := strconv.Itoa(int(*triggeredBuild.ID)) - if err != nil { - t.Errorf("invalid build id in:\n%v\n%s", triggeredBuild, err) - } - - t.Run("GetBuildOk", func(t *testing.T) { - getOut, getErr := executeCommand([]string{ - "--output", "json", - "pipeline", "build", "get", - "--project", *firstPipeline.Project.Canonical, - "--env", *firstPipeline.Environment.Canonical, - "--component", *firstPipeline.Component.Canonical, - "--pipeline", *firstPipeline.Name, - "--job", *firstJob.Name, - "--build-id", buildIDStr, - }) - if getErr != nil { - t.Errorf("cmd cy pp build get failed for job '%s' in pipeline '%s', out: %s, err: %s", *firstJob.Name, *firstPipeline.Name, getOut, getErr) - } - }) - - t.Run("ListBuildOk", func(t *testing.T) { - listOut, listErr := executeCommand([]string{ - "--output", "json", - "pipeline", "build", "list", - "--project", *firstPipeline.Project.Canonical, - "--env", *firstPipeline.Environment.Canonical, - "--component", *firstPipeline.Component.Canonical, - "--pipeline", *firstPipeline.Name, - "--job", *firstJob.Name, - }) - if listErr != nil { - t.Errorf("cmd cy pp build list failed for job '%s' in pipeline '%s', out: %s, err: %s", *firstJob.Name, *firstPipeline.Name, listOut, listErr) - } - }) - }) - }) -} diff --git a/e2e/plugin_setup_test.go b/e2e/plugin_setup_test.go deleted file mode 100644 index 2322e8c8b..000000000 --- a/e2e/plugin_setup_test.go +++ /dev/null @@ -1,66 +0,0 @@ -package e2e_test - -import ( - "fmt" - "math/rand" - "os" - "os/exec" - "sync" - "testing" -) - -const ( - helloWorldSource = "cycloid/plugin-hello-world:latest" - // baseLocalImage is the base path in the host-reachable registry. - baseLocalImage = "localhost:5000/plugin-hello-world" - // baseAPIImage is the base path as seen from inside the docker network. - // Must match the registry URL configured in the plugin-registry service. - baseAPIImage = "docker-registry:5000/plugin-hello-world" -) - -var imageOnce sync.Once - -// ensureHelloWorldImage ensures the plugin-hello-world source image is pulled once. -// Unique tags are pushed on demand by uniqueHelloWorldVersion. -func ensureHelloWorldImage(t *testing.T) { - t.Helper() - imageOnce.Do(func() { - run := func(name string, args ...string) { - cmd := exec.Command(name, args...) - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - if err := cmd.Run(); err != nil { - t.Fatalf("command %q %v failed: %v", name, args, err) - } - } - run("docker", "pull", helloWorldSource) - run("docker", "login", "localhost:5000", "-u", "cycloid", "-p", "cycloid123") - }) -} - -// uniqueHelloWorldVersion generates a unique semver-compatible image tag, pushes it -// to the local registry, and returns the docker-registry:5000 URL for use with the API. -// The plugin-registry enforces a global unique constraint on version URLs, so each -// call to CreatePluginVersion must use a different image tag. -func uniqueHelloWorldVersion(t *testing.T) string { - t.Helper() - ensureHelloWorldImage(t) - - tag := fmt.Sprintf("1.0.%d", rand.Intn(999999)) - local := fmt.Sprintf("%s:%s", baseLocalImage, tag) - api := fmt.Sprintf("%s:%s", baseAPIImage, tag) - - run := func(name string, args ...string) { - t.Helper() - cmd := exec.Command(name, args...) - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - if err := cmd.Run(); err != nil { - t.Fatalf("uniqueHelloWorldVersion: %q %v failed: %v", name, args, err) - } - } - - run("docker", "tag", helloWorldSource, local) - run("docker", "push", local) - return api -} diff --git a/e2e/plugins_test.go b/e2e/plugins_test.go deleted file mode 100644 index 5676834f1..000000000 --- a/e2e/plugins_test.go +++ /dev/null @@ -1,586 +0,0 @@ -package e2e_test - -import ( - "encoding/json" - "fmt" - "io" - "net/http" - "os" - "strings" - "testing" - "time" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -// pluginsEnabled reports whether the plugin e2e suite should run. -func pluginsEnabled() bool { - return os.Getenv("CY_TEST_E2E_PLUGINS") == "1" -} - -// pollPluginRunning polls GetPlugin until Status == "running" or timeout. -// Returns true if "running" was reached, false on timeout (plugin-manager may lack -// a container runtime in the compose test environment). -func pollPluginRunning(t *testing.T, org string, installID uint32) bool { - t.Helper() - deadline := time.Now().Add(90 * time.Second) - for time.Now().Before(deadline) { - install, _, err := config.Middleware.GetPlugin(org, installID) - if err == nil && install != nil && install.Status != nil && *install.Status == "running" { - return true - } - if err == nil && install != nil && install.Status != nil && *install.Status == "failed" { - t.Logf("plugin install %d entered failed state (plugin-manager may lack container runtime)", installID) - return false - } - time.Sleep(3 * time.Second) - } - t.Logf("plugin install %d did not reach running state within 90s (plugin-manager may lack container runtime)", installID) - return false -} - -func TestPluginManagers(t *testing.T) { - if !pluginsEnabled() { - t.Skip("set CY_TEST_E2E_PLUGINS=1 to run plugin e2e tests") - } - - org := config.Org - - t.Run("List", func(t *testing.T) { - out, err := executeCommand([]string{"plugin", "manager", "list", "--output", "json"}) - require.NoError(t, err, "plugin manager list failed: %s", out) - var managers []map[string]any - require.NoError(t, json.Unmarshal([]byte(out), &managers), "output not valid JSON") - }) - - t.Run("AcceptTestPluginManager", func(t *testing.T) { - mgr, err := config.AcceptPluginManager(t) - require.NoError(t, err, "failed to accept test-plugin-manager") - require.NotNil(t, mgr) - // API returns "invite_accepted" once accepted. - assert.Contains(t, []string{"accepted", "invite_accepted"}, *mgr.InviteStatus) - }) - - t.Run("GetAfterAccept", func(t *testing.T) { - managers, _, err := config.Middleware.ListPluginManagers(org) - require.NoError(t, err) - var found bool - for _, m := range managers { - if m.Name != nil && *m.Name == "test-plugin-manager" { - found = true - assert.Contains(t, []string{"accepted", "invite_accepted"}, *m.InviteStatus) - break - } - } - assert.True(t, found, "test-plugin-manager not found after accept") - }) -} - -func TestPluginRegistries(t *testing.T) { - if !pluginsEnabled() { - t.Skip("set CY_TEST_E2E_PLUGINS=1 to run plugin e2e tests") - } - - name := randomCanonical("e2e-registry") - // Use a unique offline URL per test run to avoid the API's one-URL-per-registry constraint. - regURL := fmt.Sprintf("http://test-reg-%s:9999", name) - - t.Run("Create", func(t *testing.T) { - out, err := executeCommand([]string{ - "plugin", "registry", "create", - "--name", name, - "--url", regURL, - "--output", "json", - }) - require.NoError(t, err, "create failed: %s", out) - var reg map[string]any - require.NoError(t, json.Unmarshal([]byte(out), ®)) - assert.Equal(t, name, reg["name"]) - }) - - defer t.Run("Cleanup", func(t *testing.T) { - _, err := executeCommand([]string{"plugin", "registry", "delete", name}) - assert.NoError(t, err, "cleanup delete failed") - }) - - t.Run("List", func(t *testing.T) { - out, err := executeCommand([]string{"plugin", "registry", "list", "--output", "json"}) - require.NoError(t, err) - names, err := JSONListExtractFields(out, "name", "", "") - require.NoError(t, err) - assert.Contains(t, names, name) - }) - - t.Run("Get", func(t *testing.T) { - out, err := executeCommand([]string{"plugin", "registry", "get", name, "--output", "json"}) - require.NoError(t, err, "get failed: %s", out) - var reg map[string]any - require.NoError(t, json.Unmarshal([]byte(out), ®)) - assert.Equal(t, name, reg["name"]) - }) - - t.Run("UpdateName", func(t *testing.T) { - renamed := name + "-r" - out, err := executeCommand([]string{ - "plugin", "registry", "update", name, - "--name", renamed, - "--output", "json", - }) - require.NoError(t, err, "update failed: %s", out) - var reg map[string]any - require.NoError(t, json.Unmarshal([]byte(out), ®)) - assert.Equal(t, renamed, reg["name"]) - // Rename back so subsequent subtests can find by original name. - _, err = executeCommand([]string{ - "plugin", "registry", "update", renamed, - "--name", name, - }) - require.NoError(t, err) - }) - - t.Run("CreateIdempotentWithUpdate", func(t *testing.T) { - out, err := executeCommand([]string{ - "plugin", "registry", "create", - "--name", name, - "--url", regURL, - "--update", - "--output", "json", - }) - require.NoError(t, err, "create --update failed: %s", out) - var reg map[string]any - require.NoError(t, json.Unmarshal([]byte(out), ®)) - assert.Equal(t, name, reg["name"]) - }) - - t.Run("CreateDuplicateFails", func(t *testing.T) { - _, err := executeCommand([]string{ - "plugin", "registry", "create", - "--name", name, - "--url", regURL, - }) - assert.Error(t, err, "expected error creating duplicate registry without --update") - }) -} - -func TestRegistryPlugins(t *testing.T) { - if !pluginsEnabled() { - t.Skip("set CY_TEST_E2E_PLUGINS=1 to run plugin e2e tests") - } - - regURL := "http://plugin-registry:4000" - reg, err := config.NewTestPluginRegistry(t, randomCanonical("e2e-reg-pl"), regURL) - require.NoError(t, err) - regID := *reg.ID - regName := *reg.Name - - pluginName := randomCanonical("e2e-plugin") - - t.Run("Create", func(t *testing.T) { - out, err := executeCommand([]string{ - "plugin", "registry", "plugin", "create", - regName, - "--name", pluginName, - "--output", "json", - }) - require.NoError(t, err, "create plugin failed: %s", out) - var p map[string]any - require.NoError(t, json.Unmarshal([]byte(out), &p)) - assert.Equal(t, pluginName, p["name"]) - }) - - defer t.Run("CleanupPlugin", func(t *testing.T) { - _, _ = executeCommand([]string{ - "plugin", "registry", "plugin", "delete", - regName, - pluginName, - }) - }) - - t.Run("List", func(t *testing.T) { - out, err := executeCommand([]string{ - "plugin", "registry", "plugin", "list", - regName, - "--output", "json", - }) - require.NoError(t, err) - names, err := JSONListExtractFields(out, "name", "", "") - require.NoError(t, err) - assert.Contains(t, names, pluginName) - }) - - t.Run("Get", func(t *testing.T) { - out, err := executeCommand([]string{ - "plugin", "registry", "plugin", "get", - pluginName, - "--registry", regName, - "--output", "json", - }) - require.NoError(t, err, "get plugin failed: %s", out) - var p map[string]any - require.NoError(t, json.Unmarshal([]byte(out), &p)) - assert.Equal(t, pluginName, p["name"]) - }) - - t.Run("Update", func(t *testing.T) { - renamed := pluginName + "-r" - out, err := executeCommand([]string{ - "plugin", "registry", "plugin", "update", - regName, - pluginName, - "--name", renamed, - "--output", "json", - }) - require.NoError(t, err, "update plugin failed: %s", out) - var p map[string]any - require.NoError(t, json.Unmarshal([]byte(out), &p)) - assert.Equal(t, renamed, p["name"]) - // Rename back. - _, err = executeCommand([]string{ - "plugin", "registry", "plugin", "update", - regName, - renamed, - "--name", pluginName, - }) - require.NoError(t, err) - }) - - _ = regID -} - -func TestPluginVersions(t *testing.T) { - if !pluginsEnabled() { - t.Skip("set CY_TEST_E2E_PLUGINS=1 to run plugin e2e tests") - } - - ensureHelloWorldImage(t) - - regURL := "http://plugin-registry:4000" - reg, err := config.NewTestPluginRegistry(t, randomCanonical("e2e-reg-ver"), regURL) - require.NoError(t, err) - regName := *reg.Name - - plugin, err := config.NewTestPluginInRegistry(t, *reg.ID, randomCanonical("e2e-plver")) - require.NoError(t, err) - pluginID := *plugin.ID - pluginName := *plugin.Name - - t.Run("Publish", func(t *testing.T) { - out, err := executeCommand([]string{ - "plugin", "registry", "plugin", "version", "publish", - "--registry", regName, - "--plugin", pluginName, - "--docker-image", uniqueHelloWorldVersion(t), - "--output", "json", - }) - require.NoError(t, err, "publish failed: %s", out) - var v map[string]any - require.NoError(t, json.Unmarshal([]byte(out), &v)) - assert.NotEmpty(t, v["id"]) - }) - - versions, _, err := config.Middleware.ListPluginVersions(config.Org, *reg.ID, pluginID) - require.NoError(t, err) - require.NotEmpty(t, versions, "no versions after publish") - versionID := *versions[0].ID - - t.Run("List", func(t *testing.T) { - out, err := executeCommand([]string{ - "plugin", "registry", "plugin", "version", "list", - "--registry", regName, - "--plugin", pluginName, - "--output", "json", - }) - require.NoError(t, err) - var vs []map[string]any - require.NoError(t, json.Unmarshal([]byte(out), &vs)) - assert.NotEmpty(t, vs) - }) - - t.Run("Get", func(t *testing.T) { - out, err := executeCommand([]string{ - "plugin", "registry", "plugin", "version", "get", - fmt.Sprint(versionID), - "--registry", regName, - "--plugin", pluginName, - "--output", "json", - }) - require.NoError(t, err, "get version failed: %s", out) - var v map[string]any - require.NoError(t, json.Unmarshal([]byte(out), &v)) - assert.NotEmpty(t, v["id"]) - }) - - t.Run("Logs", func(t *testing.T) { - // Version logs endpoint should succeed even when empty. - out, err := executeCommand([]string{ - "plugin", "registry", "plugin", "version", "logs", - fmt.Sprint(versionID), - "--registry", regName, - "--plugin", pluginName, - "--output", "json", - }) - require.NoError(t, err, "version logs failed: %s", out) - }) - - defer t.Run("Delete", func(t *testing.T) { - _, err := executeCommand([]string{ - "plugin", "registry", "plugin", "version", "delete", - fmt.Sprint(versionID), - "--registry", regName, - "--plugin", pluginName, - }) - assert.NoError(t, err) - }) -} - -func TestPluginInstallLifecycle(t *testing.T) { - if !pluginsEnabled() { - t.Skip("set CY_TEST_E2E_PLUGINS=1 to run plugin e2e tests") - } - - ensureHelloWorldImage(t) - - org := config.Org - - // Ensure test-plugin-manager is accepted. - _, err := config.AcceptPluginManager(t) - require.NoError(t, err, "failed to accept test-plugin-manager") - - regURL := "http://plugin-registry:4000" - reg, err := config.NewTestPluginRegistry(t, randomCanonical("e2e-reg-inst"), regURL) - require.NoError(t, err) - regName := *reg.Name - - plugin, err := config.NewTestPluginInRegistry(t, *reg.ID, randomCanonical("e2e-plinst")) - require.NoError(t, err) - pluginName := *plugin.Name - - version, err := config.NewTestPluginVersion(t, *reg.ID, *plugin.ID, uniqueHelloWorldVersion(t)) - require.NoError(t, err) - versionID := *version.ID - - var installID uint32 - - t.Run("Install", func(t *testing.T) { - _, err := executeCommand([]string{ - "plugin", "registry", "plugin", "version", "install", - fmt.Sprint(versionID), - "--registry", regName, - "--plugin", pluginName, - }) - require.NoError(t, err, "install failed") - - // Resolve the install ID from the plugin list. - installs, _, err := config.Middleware.ListPlugins(org) - require.NoError(t, err) - for _, p := range installs { - if p.Name != nil && *p.Name == pluginName && p.Install != nil { - installID = *p.Install.ID - break - } - } - require.NotZero(t, installID, "install record not found after install") - }) - - var pluginRunning bool - t.Run("PollRunning", func(t *testing.T) { - if installID == 0 { - t.Skip("install step did not complete") - } - pluginRunning = pollPluginRunning(t, org, installID) - if !pluginRunning { - t.Skip("plugin did not reach running state (plugin-manager may lack container runtime)") - } - }) - - t.Run("Get", func(t *testing.T) { - if installID == 0 { - t.Skip("install step did not complete") - } - out, err := executeCommand([]string{ - "plugin", "get", fmt.Sprint(installID), - "--output", "json", - }) - require.NoError(t, err, "plugin get failed: %s", out) - var install map[string]any - require.NoError(t, json.Unmarshal([]byte(out), &install)) - assert.NotNil(t, install["id"], "install record should have an id") - }) - - t.Run("List", func(t *testing.T) { - out, err := executeCommand([]string{"plugin", "list", "--output", "json"}) - require.NoError(t, err) - var installs []map[string]any - require.NoError(t, json.Unmarshal([]byte(out), &installs)) - assert.NotEmpty(t, installs) - }) - - t.Run("RetryIdempotent", func(t *testing.T) { - // A second install with --retry should not fail with 409. - _, err := executeCommand([]string{ - "plugin", "registry", "plugin", "version", "install", - fmt.Sprint(versionID), - "--registry", regName, - "--plugin", pluginName, - "--retry", - }) - require.NoError(t, err, "install --retry on already-installed version should succeed") - }) - - defer t.Run("Uninstall", func(t *testing.T) { - if installID == 0 { - return - } - _, err := executeCommand([]string{"plugin", "uninstall", fmt.Sprint(installID)}) - assert.NoError(t, err, "uninstall failed") - }) -} - -func TestPluginWidgets(t *testing.T) { - if !pluginsEnabled() { - t.Skip("set CY_TEST_E2E_PLUGINS=1 to run plugin e2e tests") - } - - ensureHelloWorldImage(t) - - org := config.Org - - // Ensure test-plugin-manager is accepted. - _, err := config.AcceptPluginManager(t) - require.NoError(t, err, "failed to accept test-plugin-manager") - - regURL := "http://plugin-registry:4000" - reg, err := config.NewTestPluginRegistry(t, randomCanonical("e2e-reg-wgt"), regURL) - require.NoError(t, err) - regName := *reg.Name - - plugin, err := config.NewTestPluginInRegistry(t, *reg.ID, randomCanonical("e2e-plwgt")) - require.NoError(t, err) - pluginName := *plugin.Name - - version, err := config.NewTestPluginVersion(t, *reg.ID, *plugin.ID, uniqueHelloWorldVersion(t)) - require.NoError(t, err) - versionID := *version.ID - - // Install and wait for running. - _, err = executeCommand([]string{ - "plugin", "registry", "plugin", "version", "install", - fmt.Sprint(versionID), - "--registry", regName, - "--plugin", pluginName, - }) - require.NoError(t, err) - - installs, _, err := config.Middleware.ListPlugins(org) - require.NoError(t, err) - var installID uint32 - for _, p := range installs { - if p.Name != nil && *p.Name == pluginName && p.Install != nil { - installID = *p.Install.ID - break - } - } - require.NotZero(t, installID) - - defer t.Run("CleanupInstall", func(t *testing.T) { - _, _ = config.Middleware.DeletePlugin(org, installID) - }) - - running := pollPluginRunning(t, org, installID) - - t.Run("ListWidgets", func(t *testing.T) { - if !running { - t.Skip("plugin not running — skipping widget test (plugin-manager may lack container runtime)") - } - out, err := executeCommand([]string{ - "plugin", "widget", "list", - "--placement", "sideMenuPage", - "--output", "json", - }) - require.NoError(t, err, "widget list failed: %s", out) - var widgets []map[string]any - require.NoError(t, json.Unmarshal([]byte(out), &widgets)) - assert.NotEmpty(t, widgets, "expected at least one widget after install") - }) - - t.Run("IframeServedContent", func(t *testing.T) { - if !running { - t.Skip("plugin not running — skipping iframe test (plugin-manager may lack container runtime)") - } - // Resolve the widget URL from the plugin widget list and verify it - // serves HTML containing "Hello World". - widgets, _, err := config.Middleware.ListPluginWidgets(org, "sideMenuPage") - require.NoError(t, err) - require.NotEmpty(t, widgets, "no widgets found for sideMenuPage placement") - - // Find the iframe widget belonging to our install. - var iframeURL string - for _, w := range widgets { - if w.Type == nil || *w.Type != "iframe" { - continue - } - // Widget field is a map with a "url" key. - wmap, ok := w.Widget.(map[string]any) - if !ok { - continue - } - rawURL, ok := wmap["url"].(string) - if !ok { - continue - } - iframeURL = rawURL - break - } - require.NotEmpty(t, iframeURL, "no iframe widget URL found") - - // plugin-manager is reachable on localhost:4000 (compose port mapping). - hostURL := strings.ReplaceAll(iframeURL, "plugin-manager:4000", "localhost:4000") - - resp, err := http.Get(hostURL) //nolint:noctx - require.NoError(t, err, "GET iframe URL failed: %s", hostURL) - defer resp.Body.Close() - - assert.Equal(t, http.StatusOK, resp.StatusCode) - - body, err := io.ReadAll(resp.Body) - require.NoError(t, err) - assert.Contains(t, strings.ToLower(string(body)), "hello world", - "iframe URL %s did not return Hello World content", hostURL) - }) -} - -func TestPluginCommandsErrorPaths(t *testing.T) { - if !pluginsEnabled() { - t.Skip("set CY_TEST_E2E_PLUGINS=1 to run plugin e2e tests") - } - - t.Run("WatchIntervalTooShort", func(t *testing.T) { - _, err := executeCommand([]string{ - "plugin", "logs", "999", - "--watch-interval", "100ms", - }) - assert.Error(t, err, "expected error for --watch-interval below 500ms") - assert.Contains(t, err.Error(), "500ms") - }) - - t.Run("RegistryCreateMissingURL", func(t *testing.T) { - _, err := executeCommand([]string{ - "plugin", "registry", "create", - "--name", "missing-url-test", - }) - assert.Error(t, err, "expected error when --url is absent") - }) - - t.Run("InstallRetryOnNonExistent", func(t *testing.T) { - // Should fail cleanly, not panic. - _, err := executeCommand([]string{ - "plugin", "registry", "plugin", "version", "install", - "--registry", "nonexistent-registry-e2e", - "--plugin", "nonexistent-plugin-e2e", - "99999", - "--retry", - }) - assert.Error(t, err) - }) -} diff --git a/e2e/projects_test.go b/e2e/projects_test.go deleted file mode 100644 index 354108898..000000000 --- a/e2e/projects_test.go +++ /dev/null @@ -1,323 +0,0 @@ -package e2e_test - -import ( - "encoding/json" - "os" - "testing" - - "github.com/stretchr/testify/assert" - - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" - "github.com/cycloidio/cycloid-cli/internal/cyargs" -) - -func TestProjects(t *testing.T) { - - os.Setenv("CY_API_URL", config.APIUrl) - os.Setenv("CY_API_KEY", config.APIKey) - os.Setenv("CY_ORG", config.Org) - - var ( - projectName = "Test E2E project" - project = randomCanonical("test-e2e-project") - description = "Testing project" - owner = "" - color = "demo" - icon = "public" - ) - - t.Run("Create", func(t *testing.T) { - args := []string{ - "project", "create", - "--project", project, - "--name", projectName, - "--description", description, - "--owner", owner, - "--icon", icon, - "--color", color, - } - _, err := executeCommand(args) - if err != nil { - t.Errorf("failed to create project '%s': %v", project, err) - } - }) - - t.Run("CreateWithNameOnlyAndUpdate", func(t *testing.T) { - var ( - nameOnly = "Project Name " + randomCanonical("e2e") - canonical = middleware.ToCanonical(nameOnly) - updatedDesc = "Updated inferred project description" - newIcon = cyargs.PickRandomIcon(nil) - newColor = cyargs.PickRandomColor(nil) - ) - - createArgs := []string{ - "--output", "json", - "project", "create", - "--name", nameOnly, - "--description", description, - "--owner", owner, - "--icon", icon, - "--color", color, - } - createOut, err := executeCommand(createArgs) - if err != nil { - t.Errorf("failed to create project with name-only '%s': %v", nameOnly, err) - } - - defer t.Run("DeleteNameOnlyProject", func(t *testing.T) { - args := []string{ - "project", "delete", - "--project", canonical, - } - _, err := executeCommand(args) - if err != nil { - t.Errorf("failed to delete project '%s': %v", canonical, err) - } - }) - - var createdProject models.Project - err = json.Unmarshal([]byte(createOut), &createdProject) - if err != nil { - t.Errorf("failed to parse create output for inferred project: %v\noutput: %s", err, createOut) - } - assert.Equal(t, nameOnly, *createdProject.Name) - assert.Equal(t, canonical, *createdProject.Canonical) - - updateArgs := []string{ - "--output", "json", - "project", "create", - "--name", nameOnly, - "--description", updatedDesc, - "--owner", owner, - "--icon", newIcon, - "--color", newColor, - "--update", - } - updateOut, err := executeCommand(updateArgs) - if err != nil { - t.Errorf("failed to create --update project with name-only '%s': %v", nameOnly, err) - } - - var updatedProject models.Project - err = json.Unmarshal([]byte(updateOut), &updatedProject) - if err != nil { - t.Errorf("failed to parse update output for inferred project: %v\noutput: %s", err, updateOut) - } - assert.Equal(t, canonical, *updatedProject.Canonical) - assert.Equal(t, nameOnly, *updatedProject.Name) - assert.Equal(t, updatedDesc, updatedProject.Description) - assert.Equal(t, newColor, *updatedProject.Color) - assert.Equal(t, newIcon, *updatedProject.Icon) - }) - - defer t.Run("Delete", func(t *testing.T) { - args := []string{ - "project", "delete", - "--project", project, - } - _, err := executeCommand(args) - if err != nil { - t.Errorf("failed to delete project '%s': %v", project, err) - } - }) - - t.Run("CreateWithUpdateExisting", func(t *testing.T) { - var ( - createUpdateName = "helloUpdate" - newIcon = cyargs.PickRandomIcon(nil) - newColor = cyargs.PickRandomColor(nil) - ) - args := []string{ - "-o", "json", - "project", "create", - "--project", project, - "--name", createUpdateName, - "--description", description, - "--owner", owner, - "--icon", newIcon, - "--color", newColor, - "--update", - } - out, err := executeCommand(args) - if err != nil { - t.Errorf("failed to create project '%s': %v", project, err) - } - - var projectResult models.Project - err = json.Unmarshal([]byte(out), &projectResult) - if err != nil { - t.Errorf("failed to parse json output from the CLI on create --update: %v\noutput: %s", err, out) - } - - assert.Equal(t, createUpdateName, *projectResult.Name) - assert.Equal(t, newColor, *projectResult.Color) - assert.Equal(t, newIcon, *projectResult.Icon) - }) - - t.Run("CreateWithUpdateNew", func(t *testing.T) { - var newProject = randomCanonical("e2e-new") - args := []string{ - "-o", "json", - "project", "create", - "--project", newProject, - "--description", description, - "--owner", owner, - "--icon", icon, - "--color", color, - "--update", - } - _, err := executeCommand(args) - if err != nil { - t.Errorf("failed to create project '%s': %v", newProject, err) - } - - defer t.Run("DeleteCreateUpdate", func(t *testing.T) { - args := []string{ - "project", "delete", - "--project", newProject, - } - _, err := executeCommand(args) - if err != nil { - t.Errorf("failed to delete project '%s': %v", newProject, err) - } - }) - }) - - t.Run("Update", func(t *testing.T) { - var updateDesc = "NewDesc" - args := []string{ - "project", "update", - "--output", "json", - "--project", project, - "--name", projectName, - "--description", updateDesc, - "--owner", owner, - "--icon", icon, - "--color", color, - } - jsonOut, err := executeCommand(args) - if err != nil { - t.Errorf("failed to update project '%s': %v", project, err) - } - - var projectResult models.Project - err = json.Unmarshal([]byte(jsonOut), &projectResult) - if err != nil { - t.Errorf("failed to parse json output from the CLI on update: %v\noutput: %s", err, jsonOut) - } - - assert.Equal(t, updateDesc, projectResult.Description) - }) - - t.Run("ListEnv", func(t *testing.T) { - args := []string{ - "--output", "json", - "project", "list-env", - "--project", project, - } - out, err := executeCommand(args) - if err != nil { - t.Errorf("failed to list project environments for '%s': %v", project, err) - } - - var envList []*models.Environment - if jsonErr := json.Unmarshal([]byte(out), &envList); jsonErr != nil { - t.Errorf("failed to parse json output of list-env: %v\noutput: %s", jsonErr, out) - } - }) - - // Positional-arg tests — verify the new interface works alongside deprecated --project flag - - t.Run("GetWithPositionalArg", func(t *testing.T) { - args := []string{ - "--output", "json", - "project", "get", - project, // positional, no --project flag - } - out, err := executeCommand(args) - if err != nil { - t.Errorf("failed to get project '%s' via positional arg: %v", project, err) - } - - var got models.Project - if jsonErr := json.Unmarshal([]byte(out), &got); jsonErr != nil { - t.Errorf("failed to parse get output: %v\noutput: %s", jsonErr, out) - } - assert.Equal(t, project, *got.Canonical) - }) - - t.Run("DeleteWithPositionalArg", func(t *testing.T) { - // Create a dedicated project to delete via positional arg - tmpProject := randomCanonical("e2e-del-pos") - _, createErr := executeCommand([]string{ - "--output", "json", - "project", "create", - "--project", tmpProject, - "--name", tmpProject, - "--icon", icon, - "--color", color, - }) - if createErr != nil { - t.Errorf("setup: failed to create project '%s': %v", tmpProject, createErr) - } - - _, deleteErr := executeCommand([]string{ - "--output", "json", - "project", "delete", - tmpProject, // positional, no --project flag - }) - assert.NoError(t, deleteErr, "delete via positional arg should succeed") - }) - - t.Run("DeleteDefaultTableOutput", func(t *testing.T) { - // Verify delete uses table mode by default and shows the deleted canonical. - tmpProject := randomCanonical("e2e-del-tbl") - _, createErr := executeCommand([]string{ - "project", "create", - "--project", tmpProject, - "--name", tmpProject, - "--icon", icon, - "--color", color, - }) - if createErr != nil { - t.Fatalf("setup: failed to create project '%s': %v", tmpProject, createErr) - } - - out, deleteErr := executeCommand([]string{ - "project", "delete", - tmpProject, - }) - assert.NoError(t, deleteErr, "delete should succeed") - assert.Contains(t, out, tmpProject, "default table output should contain the deleted canonical") - assert.NotContains(t, out, "[", "default output should not be JSON array") - }) - - t.Run("DeleteMultiplePositionalArgs", func(t *testing.T) { - // Verify deleting multiple projects at once outputs a table with all canonicals. - proj1 := randomCanonical("e2e-del-m1") - proj2 := randomCanonical("e2e-del-m2") - for _, p := range []string{proj1, proj2} { - _, createErr := executeCommand([]string{ - "project", "create", - "--project", p, - "--name", p, - "--icon", icon, - "--color", color, - }) - if createErr != nil { - t.Fatalf("setup: failed to create project '%s': %v", p, createErr) - } - } - - out, deleteErr := executeCommand([]string{ - "project", "delete", - proj1, proj2, - }) - assert.NoError(t, deleteErr, "bulk delete should succeed") - assert.Contains(t, out, proj1, "output should contain first deleted canonical") - assert.Contains(t, out, proj2, "output should contain second deleted canonical") - assert.NotContains(t, out, "[", "default output should not be JSON array") - }) -} diff --git a/e2e/roles_test.go b/e2e/roles_test.go deleted file mode 100644 index 7563ca04b..000000000 --- a/e2e/roles_test.go +++ /dev/null @@ -1,98 +0,0 @@ -package e2e_test - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestRoles(t *testing.T) { - t.Run("SuccessRolesList", func(t *testing.T) { - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "roles", - "list", - }) - - require.Nil(t, cmdErr) - assert.Contains(t, cmdOut, "canonical\": \"organization-member") - }) - - t.Run("SuccessRolesCreate", func(t *testing.T) { - ruleFile, err := WriteTempFile(`[ - {"action": "organization:update", "effect": "allow", "resources": []}, - {"action": "organization:list", "effect": "allow", "resources": []} - ]`) - assert.NoError(t, err, "test setup failed to write temp file", ruleFile) - - roleCan := randomCanonical("role") - cmd := []string{ - "--output", "json", - "--org", config.Org, - "roles", - "create", - "--name", "Team leader", - "--role", roleCan, - "--description", "big boss", - "--rule-json", `{"action": "organization:delete", "effect": "allow", "resources": []}`, - "--rule-json", `{"action": "organization:create", "effect": "allow", "resources": []}`, - "--rule-file", ruleFile, - } - cmdOut, cmdErr := executeCommand(cmd) - - require.Nil(t, cmdErr) - assert.Contains(t, cmdOut, roleCan) - - defer t.Run("SuccessRoleDelete", func(t *testing.T) { - _, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "roles", - "delete", - roleCan, - }) - require.Nil(t, cmdErr) - }) - }) - - t.Run("SuccessRolesGet", func(t *testing.T) { - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "roles", - "get", - "organization-member", - }) - - require.Nil(t, cmdErr) - assert.Contains(t, cmdOut, "canonical\": \"organization-member") - }) - - t.Run("SuccessRolesUpsertIdempotent", func(t *testing.T) { - roleCan := randomCanonical("role") - rule := `{"action": "organization:list", "effect": "allow", "resources": []}` - base := []string{"--output", "json", "--org", config.Org, "roles"} - - createCmd := append(base, "create", "--role", roleCan, "--name", "Upsert Role", "--description", "v1", "--rule-json", rule) - _, err := executeCommand(createCmd) - require.Nil(t, err) - - t.Cleanup(func() { - _, delErr := executeCommand(append(base, "delete", roleCan)) - require.Nil(t, delErr) - }) - - _, err = executeCommand(append(base, "create", "--update", "--role", roleCan, "--name", "Upsert Role", "--description", "v1", "--rule-json", rule)) - require.Nil(t, err, "create --update should succeed idempotently") - - _, err = executeCommand(append(base, "update", "--role", roleCan, "--name", "Upsert Role v2", "--description", "v2", "--rule-json", rule)) - require.Nil(t, err, "roles update should succeed") - - getOut, err := executeCommand(append(base, "get", roleCan)) - require.Nil(t, err) - assert.Contains(t, getOut, "Upsert Role v2") - assert.Contains(t, getOut, roleCan) - }) -} diff --git a/e2e/stacks_test.go b/e2e/stacks_test.go deleted file mode 100644 index 00bed0b37..000000000 --- a/e2e/stacks_test.go +++ /dev/null @@ -1,439 +0,0 @@ -package e2e_test - -import ( - "bytes" - "encoding/json" - "fmt" - "net/http" - "os" - "testing" - - "github.com/matryer/is" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/internal/custommodels" - "github.com/cycloidio/cycloid-cli/internal/ptr" -) - -func TestStacks(t *testing.T) { - t.Run("SuccessStacksListJSON", func(t *testing.T) { - is := is.New(t) - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "stacks", - "list", - }) - - is.NoErr(cmdErr) - var stackList []*models.ServiceCatalog - err := json.Unmarshal([]byte(cmdOut), &stackList) - is.NoErr(err) - is.True(len(stackList) >= 1) // We should have at least one stack in our test org - }) - - var testStackRef = config.Org + ":stack-e2e-stackforms" - var testStackCanonical = "stack-e2e-stackforms" - - t.Run("SuccessStackCreateDuplicateWithoutUpdateErrors", func(t *testing.T) { - is := is.New(t) - catalogRepo := ptr.Value(config.CatalogRepo.Canonical) - is.True(catalogRepo != "") - - // Required flags; blueprint-ref is not used when the stack canonical already exists (CLI short-circuits). - _, dupErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "stack", "create", - "--name", "E2E existing stack", - "--stack", testStackCanonical, - "--catalog-repository", catalogRepo, - "--blueprint-ref", testStackRef, - "--use-case", "default", - }) - require.Error(t, dupErr, "create without --update must fail when stack canonical already exists") - }) - - t.Run("SuccessStackCreateWithUpdateIdempotent", func(t *testing.T) { - is := is.New(t) - catalogRepo := ptr.Value(config.CatalogRepo.Canonical) - is.True(catalogRepo != "") - - cmdOut2, cmdErr2 := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "stack", "create", - "--update", - "--name", "E2E existing stack", - "--stack", testStackCanonical, - "--catalog-repository", catalogRepo, - "--blueprint-ref", testStackRef, - "--use-case", "default", - }) - require.NoError(t, cmdErr2) - - var outStack models.ServiceCatalog - err := json.Unmarshal([]byte(cmdOut2), &outStack) - require.NoError(t, err) - require.NotNil(t, outStack.Canonical) - assert.Equal(t, testStackCanonical, *outStack.Canonical) - require.NotNil(t, outStack.Ref) - assert.Equal(t, testStackRef, *outStack.Ref) - }) - - t.Run("SuccessStacksGet", func(t *testing.T) { - is := is.New(t) - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "stacks", - "get", - "--stack-ref", testStackRef, - }) - is.NoErr(cmdErr) - var outStack *models.ServiceCatalog - err := json.Unmarshal([]byte(cmdOut), &outStack) - is.NoErr(err) - }) - - t.Run("SuccessStacksUpdateVisibilty", func(t *testing.T) { - is := is.New(t) - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "stack", - "update", - "--stack-ref", testStackRef, - "--visibility", "shared", - }) - is.NoErr(cmdErr) - - var updatedStack *models.ServiceCatalog - err := json.Unmarshal([]byte(cmdOut), &updatedStack) - is.NoErr(err) - is.Equal(*updatedStack.Visibility, "shared") - }) - - t.Run("SuccessAddStackMaintainer", func(t *testing.T) { - var teamCanonical = "test-team" - body := map[string]any{ - "canonical": teamCanonical, - "name": teamCanonical, - "roles_canonical": []string{ - "default-project-viewer", - }, - } - jsonBody, err := json.Marshal(body) - if err != nil { - t.Errorf("[preparation]: json serialization shouldn't fail: %s", err.Error()) - } - - // team management is not implemented on the CLI, so making the call ourselves - request, err := http.NewRequest("POST", fmt.Sprintf("%s/organizations/%s/teams", config.APIUrl, config.Org), bytes.NewBuffer(jsonBody)) - if err != nil { - t.Errorf("[preparation]: request creationg shoudn't fail: %s", err.Error()) - } - - request.Header.Add("Authorization", fmt.Sprintf("Bearer %s", config.APIKey)) - request.Header.Add("Content-Type", "application/vnd.cycloid.io.v1+json") - - client := &http.Client{} - _, err = client.Do(request) - if err != nil { - t.Errorf("[Preparation]: request to create teams shouldn't fail: %s", err.Error()) - } - - // At this point we should have a team, I assume CR and stacks are present too - is := is.New(t) - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "stack", "update", - "--stack-ref", testStackRef, - "--team", teamCanonical, - }) - is.NoErr(cmdErr) - var updatedStack *models.ServiceCatalog - err = json.Unmarshal([]byte(cmdOut), &updatedStack) - is.NoErr(err) - is.Equal(*updatedStack.Team.Canonical, teamCanonical) // New team canonical must match - }) - - t.Run("SuccessRemoveMaintainer", func(t *testing.T) { - is := is.New(t) - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "stack", "update", - "--stack-ref", testStackRef, - "--team", "", // setting the flag with empty string should remove the maintainer - }) - is.NoErr(cmdErr) // This command must not fail - var updatedStack *models.ServiceCatalog - err := json.Unmarshal([]byte(cmdOut), &updatedStack) - is.NoErr(err) // We should be able to deserialize a valid model - is.Equal(updatedStack.Team, nil) // Team should be unset - }) - - t.Run("InvalidMaintainerShouldError", func(t *testing.T) { - is := is.New(t) - _, cmdErr := executeCommand([]string{ - "--output", "json", - "stack", "update", - "--stack-ref", testStackRef, - "--team", "invalidteam", - }) - is.True(cmdErr != nil) // CLI should output an error if we try to update a stack with a team that doesn't exists - }) - t.Run("SuccessStacksGetConfig", func(t *testing.T) { - is := is.New(t) - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "--project", *config.Project.Canonical, - "--env", *config.Environment.Canonical, - "--component", *config.Component.Canonical, - "stack", "get-config", - "--use-case", "default", - }) - is.NoErr(cmdErr) // get-config should not fail - - // Output should be valid JSON - var out interface{} - err := json.Unmarshal([]byte(cmdOut), &out) - is.NoErr(err) // output should be deserializable JSON - }) - - t.Run("SuccessStacksValidateForm", func(t *testing.T) { - is := is.New(t) - var TestForms = []byte(`--- -version: "4" -shared: -- &anchor2 - name: "hello" - key: "toto3" - widget: "simple_text" - type: "string" -use_cases: -- name: use_cases - sections: - - name: "hello" - groups: - - name: "toto" - technlogies: ["tutu"] - vars: - - &anchor1 - name: "hello" - key: "toto" - widget: "simple_text" - type: "string" - - <<: *anchor1 - key: "toto1" - - *anchor2 - - <<: *anchor2 - key: "toto4" -`) - testForms, err := os.CreateTemp("", "test-stackforms.yml") - if err != nil { - t.Errorf("setup failed: error while writing test forms at '%s'", testForms.Name()) - } - testFormsPath := testForms.Name() - WriteFile(testFormsPath, TestForms) - defer os.Remove(testFormsPath) - - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "stacks", - "forms", "validate", - testFormsPath, - }) - is.NoErr(cmdErr) - is.Equal(cmdOut, "") - }) - - t.Run("SuccessStacksListWithBlueprintFlag", func(t *testing.T) { - is := is.New(t) - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "stacks", - "list", - "--blueprint", - }) - is.NoErr(cmdErr) // cmd should not fail - - var blueprints []*custommodels.Blueprint - err := json.Unmarshal([]byte(cmdOut), &blueprints) - is.NoErr(err) // json output should be deserializable - }) - - t.Run("SuccessCreateStackFromBlueprint", func(t *testing.T) { - t.Skip("Skipping due to missing way to cleanup stack afterwards") - }) - - // Completion tests - t.Run("SuccessCompleteStackVersionCommitHash", func(t *testing.T) { - is := is.New(t) - // Test completion for component create with stack-ref - cmdOut, cmdErr := executeCommand([]string{ - "__complete", - "component", "create", - "--org", config.Org, - "--stack-ref", testStackRef, - "--stack-commit-hash", "", - }) - is.NoErr(cmdErr) - // The output should contain commit hashes - // Format: commitHash\tDescription\n:4\nCompletion ended with directive: ShellCompDirectiveNoFileComp - is.True(len(cmdOut) > 0) // Should have some output - is.True(!bytes.Contains([]byte(cmdOut), []byte("_activeHelp"))) // Should not have error help - is.True(bytes.Contains([]byte(cmdOut), []byte(":4"))) // Should have NoFileComp directive (4) - }) - - t.Run("SuccessCompleteStackVersionCommitHashWithPartialInput", func(t *testing.T) { - is := is.New(t) - // First, get a valid commit hash from the stack versions - cmdOut, cmdErr := executeCommand([]string{ - "__complete", - "component", "create", - "--org", config.Org, - "--stack-ref", testStackRef, - "--stack-commit-hash", "", - }) - is.NoErr(cmdErr) - - // Parse the first commit hash (before the tab character) - lines := bytes.Split([]byte(cmdOut), []byte("\n")) - if len(lines) > 0 && len(lines[0]) > 3 { - // Take first 3 characters as partial input - partial := string(lines[0][:3]) - - // Test completion with partial input - cmdOut2, cmdErr2 := executeCommand([]string{ - "__complete", - "component", "create", - "--org", config.Org, - "--stack-ref", testStackRef, - "--stack-commit-hash", partial, - }) - is.NoErr(cmdErr2) - is.True(len(cmdOut2) > 0) // Should have some output - is.True(!bytes.Contains([]byte(cmdOut2), []byte("_activeHelp"))) // Should not have error help - is.True(bytes.Contains([]byte(cmdOut2), []byte(partial))) // Should contain the partial string - } - }) - - t.Run("FailCompleteStackVersionCommitHashNoStackRef", func(t *testing.T) { - is := is.New(t) - // Test completion without stack-ref should provide helpful error - cmdOut, cmdErr := executeCommand([]string{ - "__complete", - "component", "create", - "--org", config.Org, - "--stack-commit-hash", "", - }) - // The command itself doesn't error, but completion should show active help - is.NoErr(cmdErr) - is.True(bytes.Contains([]byte(cmdOut), []byte("_activeHelp"))) // Should have error help - is.True(bytes.Contains([]byte(cmdOut), []byte("missing stack-ref"))) // Should mention missing stack-ref - }) - - t.Run("SuccessCompleteStackVersionCommitHashForUpdate", func(t *testing.T) { - is := is.New(t) - // For component update, if we provide stack-ref it should work - cmdOut, cmdErr := executeCommand([]string{ - "__complete", - "component", "update", - "--org", config.Org, - "--stack-ref", testStackRef, - "--stack-commit-hash", "", - }) - is.NoErr(cmdErr) - is.True(len(cmdOut) > 0) // Should have some output - is.True(!bytes.Contains([]byte(cmdOut), []byte("_activeHelp"))) // Should not have error help - is.True(bytes.Contains([]byte(cmdOut), []byte(":4"))) // Should have NoFileComp directive - }) - - // Stack version tag completion tests - t.Run("SuccessCompleteStackVersionTag", func(t *testing.T) { - is := is.New(t) - // Test completion for component create with stack-ref - cmdOut, cmdErr := executeCommand([]string{ - "__complete", - "component", "create", - "--org", config.Org, - "--stack-ref", testStackRef, - "--stack-tag", "", - }) - is.NoErr(cmdErr) - // The output should contain version tags - is.True(len(cmdOut) > 0) // Should have some output - is.True(!bytes.Contains([]byte(cmdOut), []byte("_activeHelp"))) // Should not have error help - is.True(bytes.Contains([]byte(cmdOut), []byte(":4"))) // Should have NoFileComp directive (4) - }) - - t.Run("SuccessCompleteStackVersionTagWithPartialInput", func(t *testing.T) { - is := is.New(t) - // First, get a valid version tag from the stack versions - cmdOut, cmdErr := executeCommand([]string{ - "__complete", - "component", "create", - "--org", config.Org, - "--stack-ref", testStackRef, - "--stack-tag", "", - }) - is.NoErr(cmdErr) - - // Parse the first version tag (before the tab character) - lines := bytes.Split([]byte(cmdOut), []byte("\n")) - if len(lines) > 0 && len(lines[0]) > 0 { - // Take first character as partial input - parts := bytes.Split(lines[0], []byte("\t")) - if len(parts) > 0 && len(parts[0]) > 0 { - partial := string(parts[0][:1]) - - // Test completion with partial input - cmdOut2, cmdErr2 := executeCommand([]string{ - "__complete", - "component", "create", - "--org", config.Org, - "--stack-ref", testStackRef, - "--stack-tag", partial, - }) - is.NoErr(cmdErr2) - is.True(len(cmdOut2) > 0) // Should have some output - is.True(!bytes.Contains([]byte(cmdOut2), []byte("_activeHelp"))) // Should not have error help - } - } - }) - - t.Run("FailCompleteStackVersionTagNoStackRef", func(t *testing.T) { - is := is.New(t) - // Test completion without stack-ref should provide helpful error - cmdOut, cmdErr := executeCommand([]string{ - "__complete", - "component", "create", - "--org", config.Org, - "--stack-tag", "", - }) - // The command itself doesn't error, but completion should show active help - is.NoErr(cmdErr) - is.True(bytes.Contains([]byte(cmdOut), []byte("_activeHelp"))) // Should have error help - is.True(bytes.Contains([]byte(cmdOut), []byte("missing stack-ref"))) // Should mention missing stack-ref - }) - - t.Run("SuccessCompleteStackVersionTagForUpdate", func(t *testing.T) { - is := is.New(t) - // For component update, if we provide stack-ref it should work - cmdOut, cmdErr := executeCommand([]string{ - "__complete", - "component", "update", - "--org", config.Org, - "--stack-ref", testStackRef, - "--stack-tag", "", - }) - is.NoErr(cmdErr) - is.True(len(cmdOut) > 0) // Should have some output - is.True(!bytes.Contains([]byte(cmdOut), []byte("_activeHelp"))) // Should not have error help - is.True(bytes.Contains([]byte(cmdOut), []byte(":4"))) // Should have NoFileComp directive - }) -} diff --git a/e2e/teams_test.go b/e2e/teams_test.go deleted file mode 100644 index d6f8345da..000000000 --- a/e2e/teams_test.go +++ /dev/null @@ -1,160 +0,0 @@ -package e2e_test - -import ( - "encoding/json" - "slices" - "testing" - - "github.com/sanity-io/litter" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/internal/ptr" -) - -func TestTeams(t *testing.T) { - teamCan := randomCanonical("team") - t.Run("SuccessTeamCreate", func(t *testing.T) { - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "team", "create", - "--name", teamCan, - "--role", "organization-admin", - }) - require.NoError(t, cmdErr, "cmd should succeed") - - defer t.Run("SuccessTeamDelete", func(t *testing.T) { - _, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "team", "delete", teamCan, - }) - require.NoError(t, cmdErr, "cmd delete should succeed") - }) - - var outTeam models.Team - err := json.Unmarshal([]byte(cmdOut), &outTeam) - assert.NoError(t, err, "unmarshal output should work") - assert.NotNil(t, outTeam, "team should not be empty") - assert.Equal(t, teamCan, ptr.Value(outTeam.Canonical)) - - t.Run("SuccessTeamList", func(t *testing.T) { - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "team", "list", - }) - require.NoError(t, cmdErr, "cmd should succeed") - - var outTeams []*models.Team - err := json.Unmarshal([]byte(cmdOut), &outTeams) - assert.NoError(t, err, "unmarshal output should work") - index := slices.IndexFunc(outTeams, func(t *models.Team) bool { - return ptr.Value(t.Canonical) == teamCan - }) - assert.NotEqual(t, -1, index, "we should find our team index in the out array") - assert.Equal(t, teamCan, ptr.Value(outTeams[index].Canonical)) - }) - - t.Run("SuccessTeamUpdate", func(t *testing.T) { - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "team", "update", - "--name", "newName", - "--team", teamCan, - "--role", "organization-admin", - }) - require.NoError(t, cmdErr, "cmd should succeed") - var outTeam models.Team - err := json.Unmarshal([]byte(cmdOut), &outTeam) - assert.NoError(t, err, "unmarshal output should work") - assert.NotNil(t, outTeam, "team should not be empty") - assert.Equal(t, teamCan, ptr.Value(outTeam.Canonical)) - assert.Equal(t, "newName", ptr.Value(outTeam.Name)) - }) - - t.Run("SuccessTeamGet", func(t *testing.T) { - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "team", "get", teamCan, - }) - require.NoError(t, cmdErr, "cmd should succeed") - - var outTeam models.Team - err := json.Unmarshal([]byte(cmdOut), &outTeam) - assert.NoError(t, err, "unmarshal output should work") - assert.Equal(t, teamCan, ptr.Value(outTeam.Canonical)) - }) - - t.Run("SuccessTeamMemberAssign", func(t *testing.T) { - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "team", "member", "assign", "admin@cycloid.io", - "--team", teamCan, - }) - require.NoError(t, cmdErr, "cmd should succeed") - defer t.Run("SuccessTeamMemberUnAssign", func(t *testing.T) { - _, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "team", "member", "unassign", "admin@cycloid.io", - "--team", teamCan, - }) - require.NoError(t, cmdErr, "cmd should succeed") - }) - - var outMember []models.MemberTeam - litter.Dump(cmdOut) - err := json.Unmarshal([]byte(cmdOut), &outMember) - assert.NoError(t, err, "unmarshal output should work") - assert.NotNil(t, outMember, "we should have a member") - assert.Len(t, outMember, 1, "There should be one member in the team") - assert.Equal(t, "admin@cycloid.io", ptr.Value(outMember[0].Email).String()) - }) - }) - - t.Run("SuccessTeamCreateUpdateWithNameOnly", func(t *testing.T) { - displayName := "Upsert Team " + randomCanonical("team") - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "team", "create", - "--name", displayName, - "--role", "organization-admin", - }) - require.NoError(t, cmdErr, "first create should succeed") - - var first models.Team - require.NoError(t, json.Unmarshal([]byte(cmdOut), &first)) - canonical := ptr.Value(first.Canonical) - require.NotEmpty(t, canonical) - - defer func() { - _, err := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "team", "delete", canonical, - }) - require.NoError(t, err, "cleanup delete should succeed") - }() - - cmdOut2, cmdErr2 := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "team", "create", - "--update", - "--name", displayName, - "--role", "organization-admin", - }) - require.NoError(t, cmdErr2, "create --update with name only should find team by inferred canonical") - - var second models.Team - require.NoError(t, json.Unmarshal([]byte(cmdOut2), &second)) - assert.Equal(t, canonical, ptr.Value(second.Canonical), "upsert should target the same team") - }) -} diff --git a/e2e/terracost_test.go b/e2e/terracost_test.go deleted file mode 100644 index faf8601e4..000000000 --- a/e2e/terracost_test.go +++ /dev/null @@ -1,35 +0,0 @@ -package e2e_test - -import ( - "encoding/json" - "path/filepath" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/cycloidio/cycloid-cli/client/models" -) - -func TestTerracost(t *testing.T) { - t.Run("SuccessTerracostEstimate", func(t *testing.T) { - tmpDir := t.TempDir() - planPath := filepath.Join(tmpDir, "test-plan.json") - WriteFile(planPath, TestTerraformPlanSample) - - cmdOut, cmdErr := executeCommand([]string{ - "--output", "json", - "--org", config.Org, - "terracost", - "estimate", - "--plan-path", planPath, - }) - - require.Nil(t, cmdErr, "terracost estimate should not fail, out: %s", cmdOut) - - // Output should deserialize to a cost estimation result - var result models.CostEstimationResult - err := json.Unmarshal([]byte(cmdOut), &result) - assert.Nil(t, err, "output should deserialize to models.CostEstimationResult, out: %s", cmdOut) - }) -} diff --git a/e2e/uri_test.go b/e2e/uri_test.go deleted file mode 100644 index 3c6382b7a..000000000 --- a/e2e/uri_test.go +++ /dev/null @@ -1,260 +0,0 @@ -package e2e_test - -import ( - "encoding/json" - "fmt" - "os" - "path/filepath" - "strings" - "testing" - - "github.com/stretchr/testify/assert" - "go.yaml.in/yaml/v4" - - "github.com/cycloidio/cycloid-cli/client/models" -) - -func TestGetCmd(t *testing.T) { - var baseURL = fmt.Sprintf("cy://org/%s", config.Org) - testCases := []struct { - name string - args []string - expect func(t *testing.T, actual string) - }{ - { - "getSSHKeyOk", - []string{"uri", "get", baseURL + "/cred/local-git?key=.raw.ssh_key"}, - func(t *testing.T, actual string) { - assert.Equal(t, strings.Join([]string{ - "-----BEGIN OPENSSH PRIVATE KEY-----", - "b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW", - "QyNTUxOQAAACD8O9mhkl5CAiD0NLeQcoPf1duYHImQlTjOXcCOgHmC+AAAAJjCF9jzwhfY", - "8wAAAAtzc2gtZWQyNTUxOQAAACD8O9mhkl5CAiD0NLeQcoPf1duYHImQlTjOXcCOgHmC+A", - "AAAEC0ryBZ1uJQ2drmjsO+WpsC2E/5SWheJD/r8+Q4LghWxfw72aGSXkICIPQ0t5Byg9/V", - "25gciZCVOM5dwI6AeYL4AAAAE2N5Y2xvaWRAZXhhbXBsZS5jb20BAg==", - "-----END OPENSSH PRIVATE KEY-----", - }, "\n"), actual, "ssh key must match") - }, - }, - { - "getSSHKeyLPadOK", - []string{"uri", "get", baseURL + "/cred/local-git?key=.raw.ssh_key&indent=4"}, - func(t *testing.T, actual string) { - assert.Equal(t, strings.Join([]string{ - " -----BEGIN OPENSSH PRIVATE KEY-----", - " b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW", - " QyNTUxOQAAACD8O9mhkl5CAiD0NLeQcoPf1duYHImQlTjOXcCOgHmC+AAAAJjCF9jzwhfY", - " 8wAAAAtzc2gtZWQyNTUxOQAAACD8O9mhkl5CAiD0NLeQcoPf1duYHImQlTjOXcCOgHmC+A", - " AAAEC0ryBZ1uJQ2drmjsO+WpsC2E/5SWheJD/r8+Q4LghWxfw72aGSXkICIPQ0t5Byg9/V", - " 25gciZCVOM5dwI6AeYL4AAAAE2N5Y2xvaWRAZXhhbXBsZS5jb20BAg==", - " -----END OPENSSH PRIVATE KEY-----", - }, "\n"), actual, "ssh key must be indented") - }, - }, - { - "getSSHKeyNLPadOK", - []string{"uri", "get", baseURL + "/cred/local-git?key=.raw.ssh_key&nindent=4"}, - func(t *testing.T, actual string) { - assert.Equal(t, strings.Join([]string{ - "", - " -----BEGIN OPENSSH PRIVATE KEY-----", - " b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW", - " QyNTUxOQAAACD8O9mhkl5CAiD0NLeQcoPf1duYHImQlTjOXcCOgHmC+AAAAJjCF9jzwhfY", - " 8wAAAAtzc2gtZWQyNTUxOQAAACD8O9mhkl5CAiD0NLeQcoPf1duYHImQlTjOXcCOgHmC+A", - " AAAEC0ryBZ1uJQ2drmjsO+WpsC2E/5SWheJD/r8+Q4LghWxfw72aGSXkICIPQ0t5Byg9/V", - " 25gciZCVOM5dwI6AeYL4AAAAE2N5Y2xvaWRAZXhhbXBsZS5jb20BAg==", - " -----END OPENSSH PRIVATE KEY-----", - }, "\n"), actual, "ssh key must be indented after newline") - }, - }, - { - "getJSONListOK", - []string{"uri", "get", baseURL + "/projects"}, - func(t *testing.T, actual string) { - var projects []*models.Project - err := json.Unmarshal([]byte(actual), &projects) - assert.NoError(t, err, "failed to parse JSON response:", actual) - }, - }, - { - "testYAMLOutput", - []string{"uri", "get", baseURL + "/projects?yaml"}, - func(t *testing.T, actual string) { - var projects []*models.Project - err := yaml.Unmarshal([]byte(actual), &projects) - assert.NoError(t, err, "failed to parse YAML response:", actual) - }, - }, - } - for _, testCase := range testCases { - t.Run(testCase.name, func(t *testing.T) { - cmdOut, cmdErr := executeCommand(testCase.args) - if cmdErr != nil { - t.Errorf("failed to get from urls: %v: %s", testCase.args, cmdErr) - } - - testCase.expect(t, cmdOut) - }) - } -} - -func TestE2e(t *testing.T) { - var baseURL = fmt.Sprintf("cy://org/%s", config.Org) - t.Run("TestInterpolateStdinOk", func(t *testing.T) { - stdin := strings.Join([]string{ - "ssh: | " + baseURL + "/cred/local-git?key=.raw.ssh_key&nindent=2", - "json: '" + baseURL + "/cred/local-git?key=.raw&json'", - }, "\n") - args := []string{"uri", "interpolate"} - cmdOut, cmdErr, err := executeCommandStdin(stdin, args) - assert.NoError(t, err, "cmd should not fail") - assert.Empty(t, cmdErr, "stderr should be empty") - assert.Equal(t, "ssh: | \n -----BEGIN OPENSSH PRIVATE KEY-----\n b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW\n QyNTUxOQAAACD8O9mhkl5CAiD0NLeQcoPf1duYHImQlTjOXcCOgHmC+AAAAJjCF9jzwhfY\n 8wAAAAtzc2gtZWQyNTUxOQAAACD8O9mhkl5CAiD0NLeQcoPf1duYHImQlTjOXcCOgHmC+A\n AAAEC0ryBZ1uJQ2drmjsO+WpsC2E/5SWheJD/r8+Q4LghWxfw72aGSXkICIPQ0t5Byg9/V\n 25gciZCVOM5dwI6AeYL4AAAAE2N5Y2xvaWRAZXhhbXBsZS5jb20BAg==\n -----END OPENSSH PRIVATE KEY-----\njson: '{\n \"ssh_key\": \"-----BEGIN OPENSSH PRIVATE KEY-----\\nb3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW\\nQyNTUxOQAAACD8O9mhkl5CAiD0NLeQcoPf1duYHImQlTjOXcCOgHmC+AAAAJjCF9jzwhfY\\n8wAAAAtzc2gtZWQyNTUxOQAAACD8O9mhkl5CAiD0NLeQcoPf1duYHImQlTjOXcCOgHmC+A\\nAAAEC0ryBZ1uJQ2drmjsO+WpsC2E/5SWheJD/r8+Q4LghWxfw72aGSXkICIPQ0t5Byg9/V\\n25gciZCVOM5dwI6AeYL4AAAAE2N5Y2xvaWRAZXhhbXBsZS5jb20BAg==\\n-----END OPENSSH PRIVATE KEY-----\"\n}'\n", cmdOut, "the output should match expectation") - }) -} - -func TestInterpolateCmd(t *testing.T) { - sampleContent := fmt.Sprintf("ssh_key: cy://organizations/%s/credentials/%s?key=.canonical", config.Org, config.ConfigRepo.CredentialCanonical) - sampleExpect := fmt.Sprintf("ssh_key: %s\n", config.ConfigRepo.CredentialCanonical) - - t.Run("InPlaceInterpolationOk", func(t *testing.T) { - tempDir := t.TempDir() - sampleFilePath := tempDir + "/sample.yml" - err := os.WriteFile(sampleFilePath, []byte(sampleContent), 0666) - if err != nil { - t.Logf("test setup failed, cannot write sample file at path %q: %v", tempDir, err) - t.FailNow() - } - - args := []string{ - "uri", "interpolate", "--in-place", sampleFilePath, - } - cmdOut, cmdErr := executeCommand(args) - assert.NoError(t, cmdErr, "the cmd should not fail") - assert.Empty(t, cmdOut, "valid in-place interpolation returns nothing") - fileContent, err := os.ReadFile(sampleFilePath) - assert.NoError(t, err, "we should be able to read the file after interpolation") - assert.Equal(t, sampleExpect, string(fileContent)) - }) - - t.Run("RecurseInterpolationOk", func(t *testing.T) { - // setup - tempDir := t.TempDir() - nestedDir := tempDir + "/nested" - ignoreDir := tempDir + "/ignore-me" - sampleFilePath := tempDir + "/sample.yml" - defaultDotGitDir := tempDir + "/.git" - nestedSampleFilePath := nestedDir + "/nested.yml" - ignoreSampleFilePath := ignoreDir + "/ignored.yml" - dotGitFile := defaultDotGitDir + "/somegitfile" - - for _, dir := range []string{tempDir, nestedDir, ignoreDir, defaultDotGitDir} { - err := os.MkdirAll(dir, 0777) - if err != nil { - t.Logf("test setup failed, create nested dir %q: %v", dir, err) - t.FailNow() - } - } - - for _, file := range []string{sampleFilePath, nestedSampleFilePath, ignoreSampleFilePath, dotGitFile} { - err := os.WriteFile(file, []byte(sampleContent), 0666) - if err != nil { - t.Logf("test setup failed, cannot write sample file at path %q: %v", file, err) - t.FailNow() - } - } - // end setup - - args := []string{ - "uri", "interpolate", "--in-place", "--recurse", tempDir, "--ignore", "ignore-me*", "--ignore", ".git", - } - cmdOut, cmdErr := executeCommand(args) - assert.NoError(t, cmdErr, "the cmd", args, "should not fail") - assert.Empty(t, cmdOut, "valid in-place interpolation returns nothing") - - // check top level - fileContent, err := os.ReadFile(sampleFilePath) - assert.NoError(t, err, "we should be able to read the file after interpolation") - assert.Equal(t, sampleExpect, string(fileContent), "this file must be interpolated") - - // check nested - fileContent, err = os.ReadFile(nestedSampleFilePath) - assert.NoError(t, err, "we should be able to read the nested file after interpolation") - assert.Equal(t, sampleExpect, string(fileContent), "this file must be interpolated") - - // check ignore - fileContent, err = os.ReadFile(ignoreSampleFilePath) - assert.NoError(t, err, "we should be able to read the ignored file after interpolation") - assert.Equal(t, sampleContent, string(fileContent), "this file must not be interpolated") - - // check default ignore - t.Run("defaultDotGitIgnoreOk", func(t *testing.T) { - fileContent, err = os.ReadFile(dotGitFile) - assert.NoError(t, err, "we should be able to read the ignored file after interpolation") - assert.Equal(t, sampleContent, string(fileContent), ".git file must not be interpolated") - }) - - t.Run("StdoutRecuseInterpolationOk", func(t *testing.T) { - args := []string{ - "uri", "interpolate", "--recurse", tempDir, - } - cmdOut, cmdErr := executeCommand(args) - assert.NoError(t, cmdErr, "the cmd should not fail") - assert.Equal(t, "ssh_key: local-git\nssh_key: local-git\nssh_key: local-git\n", cmdOut, "we should get both file content") - }) - }) - - t.Run("StdoutInterpolationOk", func(t *testing.T) { - args := []string{ - "uri", "interpolate", - } - cmdOut, cmdErr, err := executeCommandStdin(sampleContent, args) - assert.NoError(t, err, "cmd should not err") - assert.Empty(t, cmdErr, "cmd should not output on stderr if no err") - assert.Equal(t, sampleExpect, cmdOut, "output should match interpolation") - }) - - t.Run("StdinNoExtraNewlineOrSpaces", func(t *testing.T) { - args := []string{ - "uri", "interpolate", - } - cmdOut, cmdErr, err := executeCommandStdin(" \n \n", args) - assert.NoError(t, err, "cmd should not err") - assert.Empty(t, cmdErr, "cmd should not output on stderr if no err") - assert.Equal(t, "\n", cmdOut, "there should be no more than one newline and no spaces") - }) - - t.Run("FileNoExtraNewlineOrSpaces", func(t *testing.T) { - tempDir := t.TempDir() - tempFile := filepath.Join(tempDir, "testfile") - err := os.WriteFile(tempFile, []byte(" \n \n"), 0640) - if err != nil { - t.Logf("failed to setup test, failed to write to file %q: %v", tempFile, err) - t.FailNow() - } - - args := []string{"uri", "interpolate", tempFile} - cmdOut, cmdErr := executeCommand(args) - assert.NoError(t, cmdErr, "cmdErr should be nil") - assert.Equal(t, "\n", cmdOut, "output should be stripped of extra space and end with a newline.") - }) - - t.Run("FileInPlaceNoExtraNewlineOrSpaces", func(t *testing.T) { - tempDir := t.TempDir() - tempFile := filepath.Join(tempDir, "testfile") - err := os.WriteFile(tempFile, []byte(" \n \n"), 0640) - if err != nil { - t.Logf("failed to setup test, failed to write to file %q: %v", tempFile, err) - t.FailNow() - } - - args := []string{"uri", "interpolate", "--in-place", tempFile} - cmdOut, cmdErr := executeCommand(args) - assert.NoError(t, cmdErr, "cmdErr should be nil") - assert.Equal(t, "", cmdOut, "When using --in-place, output should be empty") - - fileContent, err := os.ReadFile(tempFile) - assert.NoError(t, err, "failed to read test file %q: %w", tempFile, err) - assert.Equal(t, "\n", string(fileContent), "the file should not have trailling space and end with a newline") - }) -} diff --git a/flake.lock b/flake.lock deleted file mode 100644 index 24c7a383e..000000000 --- a/flake.lock +++ /dev/null @@ -1,61 +0,0 @@ -{ - "nodes": { - "flake-utils": { - "inputs": { - "systems": "systems" - }, - "locked": { - "lastModified": 1731533236, - "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, - "nixpkgs": { - "locked": { - "lastModified": 1767313136, - "narHash": "sha256-16KkgfdYqjaeRGBaYsNrhPRRENs0qzkQVUooNHtoy2w=", - "owner": "NixOs", - "repo": "nixpkgs", - "rev": "ac62194c3917d5f474c1a844b6fd6da2db95077d", - "type": "github" - }, - "original": { - "owner": "NixOs", - "ref": "nixos-25.05", - "repo": "nixpkgs", - "type": "github" - } - }, - "root": { - "inputs": { - "flake-utils": "flake-utils", - "nixpkgs": "nixpkgs" - } - }, - "systems": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } - } - }, - "root": "root", - "version": 7 -} diff --git a/flake.nix b/flake.nix deleted file mode 100644 index e94381883..000000000 --- a/flake.nix +++ /dev/null @@ -1,37 +0,0 @@ -{ - description = "A basic dev shell for nix/nixos users"; - - inputs = { - nixpkgs = { url = "github:NixOs/nixpkgs/nixos-25.05"; }; - flake-utils = { url = "github:numtide/flake-utils"; }; - }; - - outputs = inputs@{ self, nixpkgs, flake-utils }: - flake-utils.lib.eachDefaultSystem (system: - let - pkgs = import nixpkgs { inherit system; }; - lib = pkgs.lib; - swaggerPython = (pkgs.python312.withPackages (p: with p; [ - pyyaml - ])); - in - { - devShells.default = pkgs.mkShell { - buildInputs = [ swaggerPython ] - ++ (with pkgs; [ - # You packages here - gnumake - libgcc - - go_1_25 - go-swagger - # gci - # golangci-lint - # golangci-lint-langserver - awscli - docker - pre-commit - ]); - }; - }); -} diff --git a/client/models/a_w_s_cloud_watch_logs.go b/gen/models/a_w_s_cloud_watch_logs.go similarity index 96% rename from client/models/a_w_s_cloud_watch_logs.go rename to gen/models/a_w_s_cloud_watch_logs.go index 66bc89c39..0e0684ea4 100644 --- a/client/models/a_w_s_cloud_watch_logs.go +++ b/gen/models/a_w_s_cloud_watch_logs.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "bytes" "context" diff --git a/client/models/a_w_s_infrastructure_resource_bucket.go b/gen/models/a_w_s_infrastructure_resource_bucket.go similarity index 80% rename from client/models/a_w_s_infrastructure_resource_bucket.go rename to gen/models/a_w_s_infrastructure_resource_bucket.go index 0620a4265..8ce59f005 100644 --- a/client/models/a_w_s_infrastructure_resource_bucket.go +++ b/gen/models/a_w_s_infrastructure_resource_bucket.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + // AWSInfrastructureResourceBucket AWS Infrastructure S3 bucket Resource // // This object contains the items described in the S3 bucket data type described in but it also contains its associated tags which are documented in the properties of this object definition. This object will contain a property named 'Tags' which is of the type defined by the schema definition '#/definitions/AWSTags' diff --git a/client/models/a_w_s_infrastructure_resource_d_b_instance.go b/gen/models/a_w_s_infrastructure_resource_d_b_instance.go similarity index 82% rename from client/models/a_w_s_infrastructure_resource_d_b_instance.go rename to gen/models/a_w_s_infrastructure_resource_d_b_instance.go index 0fb3f6d10..cf009312a 100644 --- a/client/models/a_w_s_infrastructure_resource_d_b_instance.go +++ b/gen/models/a_w_s_infrastructure_resource_d_b_instance.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + // AWSInfrastructureResourceDBInstance AWS Infrastructure RDS DB instance Resource // // This object contains the items described in the RDS DB instance data type described in https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_DBInstance.html but it also contains its associated tags which are documented in the properties of this object definition. This object will contain a property named 'Tags' which is of the type defined by the schema definition '#/definitions/AWSTags' diff --git a/client/models/a_w_s_infrastructure_resource_elasticache_cluster.go b/gen/models/a_w_s_infrastructure_resource_elasticache_cluster.go similarity index 83% rename from client/models/a_w_s_infrastructure_resource_elasticache_cluster.go rename to gen/models/a_w_s_infrastructure_resource_elasticache_cluster.go index cbae1c23b..36b9c541c 100644 --- a/client/models/a_w_s_infrastructure_resource_elasticache_cluster.go +++ b/gen/models/a_w_s_infrastructure_resource_elasticache_cluster.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + // AWSInfrastructureResourceElasticacheCluster AWS Infrastructure Elasticache cluster Resource // // This object contains the items described in the ElastiCache cluster data type described in https://docs.aws.amazon.com/AmazonElastiCache/latest/APIReference/API_CacheCluster.html but it also contains its associated tags which are documented in the properties of this object definition. This object will contain a property named 'Tags' which is of the type defined by the schema definition '#/definitions/AWSTags' diff --git a/client/models/a_w_s_infrastructure_resource_image.go b/gen/models/a_w_s_infrastructure_resource_image.go similarity index 84% rename from client/models/a_w_s_infrastructure_resource_image.go rename to gen/models/a_w_s_infrastructure_resource_image.go index fb5828a03..efc5549d6 100644 --- a/client/models/a_w_s_infrastructure_resource_image.go +++ b/gen/models/a_w_s_infrastructure_resource_image.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + // AWSInfrastructureResourceImage AWS Infrastructure image Resource // // This object contains the items described in the image data type described in https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_Image.html Tags property is set, for guaranteeing that the respond will always have the property of the type array, not allowing null in case that the resource doesn't have any, hence an empty array is used in such case. This object will contain a property named 'Tags' which is of the type defined by the schema definition '#/definitions/AWSTags' diff --git a/client/models/a_w_s_infrastructure_resource_instance.go b/gen/models/a_w_s_infrastructure_resource_instance.go similarity index 84% rename from client/models/a_w_s_infrastructure_resource_instance.go rename to gen/models/a_w_s_infrastructure_resource_instance.go index fc37eada5..4e942419d 100644 --- a/client/models/a_w_s_infrastructure_resource_instance.go +++ b/gen/models/a_w_s_infrastructure_resource_instance.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + // AWSInfrastructureResourceInstance AWS Infrastructure Instance Resource // // This object contains the items described in the instance data type described in https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_Instance.html Tags property is set, for guaranteeing that the respond will always have the property of the type array, not allowing null in case that the resource doesn't have any, hence an empty array is used in such case. This object will contain a property named 'Tags' which is of the type defined by the schema definition '#/definitions/AWSTags' diff --git a/client/models/a_w_s_infrastructure_resource_load_balancer_v1.go b/gen/models/a_w_s_infrastructure_resource_load_balancer_v1.go similarity index 83% rename from client/models/a_w_s_infrastructure_resource_load_balancer_v1.go rename to gen/models/a_w_s_infrastructure_resource_load_balancer_v1.go index c2f857088..1a91151b9 100644 --- a/client/models/a_w_s_infrastructure_resource_load_balancer_v1.go +++ b/gen/models/a_w_s_infrastructure_resource_load_balancer_v1.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + // AWSInfrastructureResourceLoadBalancerV1 AWS Infrastructure load balancer (ELB) Resource // // This object contains the items described in the load balancer (ELB) data type described in https://docs.aws.amazon.com/elasticloadbalancing/2012-06-01/APIReference/API_LoadBalancerDescription.html but it also contains its associated tags which are documented in the properties of this object definition. This object will contain a property named 'Tags' which is of the type defined by the schema definition '#/definitions/AWSTags' diff --git a/client/models/a_w_s_infrastructure_resource_load_balancer_v2.go b/gen/models/a_w_s_infrastructure_resource_load_balancer_v2.go similarity index 84% rename from client/models/a_w_s_infrastructure_resource_load_balancer_v2.go rename to gen/models/a_w_s_infrastructure_resource_load_balancer_v2.go index 13eba48ee..0d96f8d77 100644 --- a/client/models/a_w_s_infrastructure_resource_load_balancer_v2.go +++ b/gen/models/a_w_s_infrastructure_resource_load_balancer_v2.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + // AWSInfrastructureResourceLoadBalancerV2 AWS Infrastructure load balancer (ELB v2 or a.k.a ALB) Resource // // This object contains the items described in the load balancer (ELB v2 or a.k.a ALB) data type described in https://docs.aws.amazon.com/elasticloadbalancing/latest/APIReference/API_LoadBalancer.html but it also contains its associated tags which are documented in the properties of this object definition. This object will contain a property named 'Tags' which is of the type defined by the schema definition '#/definitions/AWSTags' diff --git a/client/models/a_w_s_infrastructure_resource_security_group.go b/gen/models/a_w_s_infrastructure_resource_security_group.go similarity index 85% rename from client/models/a_w_s_infrastructure_resource_security_group.go rename to gen/models/a_w_s_infrastructure_resource_security_group.go index f188a7d0d..5849756e4 100644 --- a/client/models/a_w_s_infrastructure_resource_security_group.go +++ b/gen/models/a_w_s_infrastructure_resource_security_group.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + // AWSInfrastructureResourceSecurityGroup AWS Infrastructure security group Resource // // This object contains the items described in the security group data type described in https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_SecurityGroup.html Tags property is set, for guaranteeing that the respond will always have the property of the type array, not allowing null in case that the resource doesn't have any, hence an empty array is used in such case. This object will contain a property named 'Tags' which is of the type defined by the schema definition '#/definitions/AWSTags' diff --git a/client/models/a_w_s_infrastructure_resource_snapshot.go b/gen/models/a_w_s_infrastructure_resource_snapshot.go similarity index 84% rename from client/models/a_w_s_infrastructure_resource_snapshot.go rename to gen/models/a_w_s_infrastructure_resource_snapshot.go index ae3ac1698..aa8724d11 100644 --- a/client/models/a_w_s_infrastructure_resource_snapshot.go +++ b/gen/models/a_w_s_infrastructure_resource_snapshot.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + // AWSInfrastructureResourceSnapshot AWS Infrastructure snapshot Resource // // This object contains the items described in the snapshot data type described in https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_Snapshot.html Tags property is set, for guaranteeing that the respond will always have the property of the type array, not allowing null in case that the resource doesn't have any, hence an empty array is used in such case. This object will contain a property named 'Tags' which is of the type defined by the schema definition '#/definitions/AWSTags' diff --git a/client/models/a_w_s_infrastructure_resource_subnet.go b/gen/models/a_w_s_infrastructure_resource_subnet.go similarity index 84% rename from client/models/a_w_s_infrastructure_resource_subnet.go rename to gen/models/a_w_s_infrastructure_resource_subnet.go index 14d7b9d82..4fbc89c18 100644 --- a/client/models/a_w_s_infrastructure_resource_subnet.go +++ b/gen/models/a_w_s_infrastructure_resource_subnet.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + // AWSInfrastructureResourceSubnet AWS Infrastructure subnet Resource // // This object contains the items described in the subnet data type described in https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_Subnet.html Tags property is set, for guaranteeing that the respond will always have the property of the type array, not allowing null in case that the resource doesn't have any, hence an empty array is used in such case. This object will contain a property named 'Tags' which is of the type defined by the schema definition '#/definitions/AWSTags' diff --git a/client/models/a_w_s_infrastructure_resource_v_p_c.go b/gen/models/a_w_s_infrastructure_resource_v_p_c.go similarity index 83% rename from client/models/a_w_s_infrastructure_resource_v_p_c.go rename to gen/models/a_w_s_infrastructure_resource_v_p_c.go index b3229f479..3108b3922 100644 --- a/client/models/a_w_s_infrastructure_resource_v_p_c.go +++ b/gen/models/a_w_s_infrastructure_resource_v_p_c.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + // AWSInfrastructureResourceVPC AWS Infrastructure VPC Resource // // This object contains the items described in the VPC data type described in https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_Vpc.html Tags property is set, for guaranteeing that the respond will always have the property of the type array, not allowing null in case that the resource doesn't have any, hence an empty array is used in such case. This object will contain a property named 'Tags' which is of the type defined by the schema definition '#/definitions/AWSTags' diff --git a/client/models/a_w_s_infrastructure_resource_volume.go b/gen/models/a_w_s_infrastructure_resource_volume.go similarity index 84% rename from client/models/a_w_s_infrastructure_resource_volume.go rename to gen/models/a_w_s_infrastructure_resource_volume.go index 7d5f75e5f..2c5b72222 100644 --- a/client/models/a_w_s_infrastructure_resource_volume.go +++ b/gen/models/a_w_s_infrastructure_resource_volume.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + // AWSInfrastructureResourceVolume AWS Infrastructure volume Resource // // This object contains the items described in the volume data type described in https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_Volume.html Tags property is set, for guaranteeing that the respond will always have the property of the type array, not allowing null in case that the resource doesn't have any, hence an empty array is used in such case. This object will contain a property named 'Tags' which is of the type defined by the schema definition '#/definitions/AWSTags' diff --git a/client/models/a_w_s_infrastructure_resources_aggregation.go b/gen/models/a_w_s_infrastructure_resources_aggregation.go similarity index 99% rename from client/models/a_w_s_infrastructure_resources_aggregation.go rename to gen/models/a_w_s_infrastructure_resources_aggregation.go index c481b6288..c60d59586 100644 --- a/client/models/a_w_s_infrastructure_resources_aggregation.go +++ b/gen/models/a_w_s_infrastructure_resources_aggregation.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" "encoding/json" diff --git a/client/models/a_w_s_remote_t_f_state.go b/gen/models/a_w_s_remote_t_f_state.go similarity index 97% rename from client/models/a_w_s_remote_t_f_state.go rename to gen/models/a_w_s_remote_t_f_state.go index 0ae920c24..e1666b1d3 100644 --- a/client/models/a_w_s_remote_t_f_state.go +++ b/gen/models/a_w_s_remote_t_f_state.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "bytes" "context" diff --git a/client/models/a_w_s_storage.go b/gen/models/a_w_s_storage.go similarity index 97% rename from client/models/a_w_s_storage.go rename to gen/models/a_w_s_storage.go index dfb979567..652936741 100644 --- a/client/models/a_w_s_storage.go +++ b/gen/models/a_w_s_storage.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "bytes" "context" diff --git a/client/models/api_key.go b/gen/models/api_key.go similarity index 97% rename from client/models/api_key.go rename to gen/models/api_key.go index cdfcca44a..8031799e9 100644 --- a/client/models/api_key.go +++ b/gen/models/api_key.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/app_configuration.go b/gen/models/app_configuration.go similarity index 93% rename from client/models/app_configuration.go rename to gen/models/app_configuration.go index 016ddfa8e..1d1143636 100644 --- a/client/models/app_configuration.go +++ b/gen/models/app_configuration.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/app_version.go b/gen/models/app_version.go similarity index 95% rename from client/models/app_version.go rename to gen/models/app_version.go index 8e636c1f5..403778369 100644 --- a/client/models/app_version.go +++ b/gen/models/app_version.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/appearance.go b/gen/models/appearance.go similarity index 98% rename from client/models/appearance.go rename to gen/models/appearance.go index 5554b1645..b0681569d 100644 --- a/client/models/appearance.go +++ b/gen/models/appearance.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/authentication.go b/gen/models/authentication.go similarity index 96% rename from client/models/authentication.go rename to gen/models/authentication.go index ca0fb5671..89e6c182a 100644 --- a/client/models/authentication.go +++ b/gen/models/authentication.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "bytes" "context" diff --git a/client/models/authentication_azure_a_d.go b/gen/models/authentication_azure_a_d.go similarity index 96% rename from client/models/authentication_azure_a_d.go rename to gen/models/authentication_azure_a_d.go index f65385463..18f5508df 100644 --- a/client/models/authentication_azure_a_d.go +++ b/gen/models/authentication_azure_a_d.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "bytes" "context" diff --git a/client/models/authentication_config.go b/gen/models/authentication_config.go similarity index 97% rename from client/models/authentication_config.go rename to gen/models/authentication_config.go index 466da949d..eeb7fd971 100644 --- a/client/models/authentication_config.go +++ b/gen/models/authentication_config.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "bytes" "context" diff --git a/client/models/authentication_git_hub.go b/gen/models/authentication_git_hub.go similarity index 97% rename from client/models/authentication_git_hub.go rename to gen/models/authentication_git_hub.go index 805ceeb79..b855628c6 100644 --- a/client/models/authentication_git_hub.go +++ b/gen/models/authentication_git_hub.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "bytes" "context" diff --git a/client/models/authentication_google.go b/gen/models/authentication_google.go similarity index 96% rename from client/models/authentication_google.go rename to gen/models/authentication_google.go index f34e8daef..a7e4f9eca 100644 --- a/client/models/authentication_google.go +++ b/gen/models/authentication_google.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "bytes" "context" diff --git a/client/models/authentication_local.go b/gen/models/authentication_local.go similarity index 96% rename from client/models/authentication_local.go rename to gen/models/authentication_local.go index 9b401bec3..e1581c81a 100644 --- a/client/models/authentication_local.go +++ b/gen/models/authentication_local.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "bytes" "context" diff --git a/client/models/authentication_o_id_c.go b/gen/models/authentication_o_id_c.go similarity index 56% rename from client/models/authentication_o_id_c.go rename to gen/models/authentication_o_id_c.go index 75f2d7be6..d3d745060 100644 --- a/client/models/authentication_o_id_c.go +++ b/gen/models/authentication_o_id_c.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "bytes" "context" @@ -29,6 +32,12 @@ type AuthenticationOIDC struct { // Read Only: true HasSecret *bool `json:"has_secret,omitempty"` + // Allow oidc_discovery_url to use plain HTTP when oidc_issuer is HTTPS. Set to true only when the network path between the Cycloid backend and the discovery URL is privately trusted (VPC, internal LAN, service mesh). Equivalent security trade-off to oidc_skip_tls_verify, scoped to the discovery URL. + OidcAllowInsecureDiscovery *bool `json:"oidc_allow_insecure_discovery,omitempty"` + + // When true, automatically provision a user record on the first OIDC login for this integration (BE-1438). Opt-in; defaults to false. No behaviour change for existing integrations unless explicitly enabled. + OidcAutoCreate bool `json:"oidc_auto_create,omitempty"` + // PEM-encoded CA certificate to verify the OIDC provider's TLS certificate. OidcCaCert string `json:"oidc_ca_cert,omitempty"` @@ -39,17 +48,26 @@ type AuthenticationOIDC struct { OidcClientSecret string `json:"oidc_client_secret,omitempty"` // Enables client authentication via signed JWT (HS512) using the client secret, as per RFC 7523. - OidcClientSecretJwt bool `json:"oidc_client_secret_jwt,omitempty"` + OidcClientSecretJwt *bool `json:"oidc_client_secret_jwt,omitempty"` + + // Optional base URL override for the OIDC provider as seen from the Cycloid backend. The backend appends /.well-known/openid-configuration to fetch the discovery document. Defaults to oidc_issuer when omitted. The discovery document's issuer field MUST equal oidc_issuer (enforced server-side). Useful when the backend reaches the IdP via a different network path than user browsers (corporate DMZ, K8s ingress vs cluster DNS, split-horizon DNS). Send an empty string to clear a previously stored override. + OidcDiscoveryURL *string `json:"oidc_discovery_url,omitempty"` // The friendly name shown on the login button OidcDisplayName string `json:"oidc_display_name,omitempty"` + // Name of the OIDC token claim listing the user's group memberships, used for OIDC group mapping. Defaults to "groups" when omitted. The IdP must be configured to include this claim in the issued ID token — group mapping has no effect if the provider omits it. Enterprise IdPs such as Keycloak, Okta, Azure AD/Entra ID, and Auth0 support configurable group claims; consumer providers such as Google Workspace and GitHub do not include group claims in standard OIDC tokens. + OidcGroupsClaimName string `json:"oidc_groups_claim_name,omitempty"` + // URL of the icon to display on the OIDC authentication login screen. OidcIcon string `json:"oidc_icon,omitempty"` // The base URL of the OIDC provider. Used for automatic endpoint discovery. OidcIssuer string `json:"oidc_issuer,omitempty"` + // Session lifetime in seconds for JWTs issued from a login through this OIDC integration (BE-1424). The backend clamps the effective value to the range 5 minutes .. 30 days. When omitted or null the global default session TTL applies. + OidcSessionTTLSeconds *int64 `json:"oidc_session_ttl_seconds,omitempty"` + // Disables TLS certificate verification when connecting to the OIDC provider. Use only in development or with self-signed certificates. OidcSkipTLSVerify bool `json:"oidc_skip_tls_verify,omitempty"` @@ -88,6 +106,12 @@ func (m *AuthenticationOIDC) UnmarshalJSON(raw []byte) error { // Read Only: true HasSecret *bool `json:"has_secret,omitempty"` + // Allow oidc_discovery_url to use plain HTTP when oidc_issuer is HTTPS. Set to true only when the network path between the Cycloid backend and the discovery URL is privately trusted (VPC, internal LAN, service mesh). Equivalent security trade-off to oidc_skip_tls_verify, scoped to the discovery URL. + OidcAllowInsecureDiscovery *bool `json:"oidc_allow_insecure_discovery,omitempty"` + + // When true, automatically provision a user record on the first OIDC login for this integration (BE-1438). Opt-in; defaults to false. No behaviour change for existing integrations unless explicitly enabled. + OidcAutoCreate bool `json:"oidc_auto_create,omitempty"` + // PEM-encoded CA certificate to verify the OIDC provider's TLS certificate. OidcCaCert string `json:"oidc_ca_cert,omitempty"` @@ -98,17 +122,26 @@ func (m *AuthenticationOIDC) UnmarshalJSON(raw []byte) error { OidcClientSecret string `json:"oidc_client_secret,omitempty"` // Enables client authentication via signed JWT (HS512) using the client secret, as per RFC 7523. - OidcClientSecretJwt bool `json:"oidc_client_secret_jwt,omitempty"` + OidcClientSecretJwt *bool `json:"oidc_client_secret_jwt,omitempty"` + + // Optional base URL override for the OIDC provider as seen from the Cycloid backend. The backend appends /.well-known/openid-configuration to fetch the discovery document. Defaults to oidc_issuer when omitted. The discovery document's issuer field MUST equal oidc_issuer (enforced server-side). Useful when the backend reaches the IdP via a different network path than user browsers (corporate DMZ, K8s ingress vs cluster DNS, split-horizon DNS). Send an empty string to clear a previously stored override. + OidcDiscoveryURL *string `json:"oidc_discovery_url,omitempty"` // The friendly name shown on the login button OidcDisplayName string `json:"oidc_display_name,omitempty"` + // Name of the OIDC token claim listing the user's group memberships, used for OIDC group mapping. Defaults to "groups" when omitted. The IdP must be configured to include this claim in the issued ID token — group mapping has no effect if the provider omits it. Enterprise IdPs such as Keycloak, Okta, Azure AD/Entra ID, and Auth0 support configurable group claims; consumer providers such as Google Workspace and GitHub do not include group claims in standard OIDC tokens. + OidcGroupsClaimName string `json:"oidc_groups_claim_name,omitempty"` + // URL of the icon to display on the OIDC authentication login screen. OidcIcon string `json:"oidc_icon,omitempty"` // The base URL of the OIDC provider. Used for automatic endpoint discovery. OidcIssuer string `json:"oidc_issuer,omitempty"` + // Session lifetime in seconds for JWTs issued from a login through this OIDC integration (BE-1424). The backend clamps the effective value to the range 5 minutes .. 30 days. When omitted or null the global default session TTL applies. + OidcSessionTTLSeconds *int64 `json:"oidc_session_ttl_seconds,omitempty"` + // Disables TLS certificate verification when connecting to the OIDC provider. Use only in development or with self-signed certificates. OidcSkipTLSVerify bool `json:"oidc_skip_tls_verify,omitempty"` @@ -149,13 +182,18 @@ func (m *AuthenticationOIDC) UnmarshalJSON(raw []byte) error { result.HasCaCertificate = data.HasCaCertificate result.HasSecret = data.HasSecret + result.OidcAllowInsecureDiscovery = data.OidcAllowInsecureDiscovery + result.OidcAutoCreate = data.OidcAutoCreate result.OidcCaCert = data.OidcCaCert result.OidcClientID = data.OidcClientID result.OidcClientSecret = data.OidcClientSecret result.OidcClientSecretJwt = data.OidcClientSecretJwt + result.OidcDiscoveryURL = data.OidcDiscoveryURL result.OidcDisplayName = data.OidcDisplayName + result.OidcGroupsClaimName = data.OidcGroupsClaimName result.OidcIcon = data.OidcIcon result.OidcIssuer = data.OidcIssuer + result.OidcSessionTTLSeconds = data.OidcSessionTTLSeconds result.OidcSkipTLSVerify = data.OidcSkipTLSVerify result.OidcUseCaCert = data.OidcUseCaCert @@ -178,6 +216,12 @@ func (m AuthenticationOIDC) MarshalJSON() ([]byte, error) { // Read Only: true HasSecret *bool `json:"has_secret,omitempty"` + // Allow oidc_discovery_url to use plain HTTP when oidc_issuer is HTTPS. Set to true only when the network path between the Cycloid backend and the discovery URL is privately trusted (VPC, internal LAN, service mesh). Equivalent security trade-off to oidc_skip_tls_verify, scoped to the discovery URL. + OidcAllowInsecureDiscovery *bool `json:"oidc_allow_insecure_discovery,omitempty"` + + // When true, automatically provision a user record on the first OIDC login for this integration (BE-1438). Opt-in; defaults to false. No behaviour change for existing integrations unless explicitly enabled. + OidcAutoCreate bool `json:"oidc_auto_create,omitempty"` + // PEM-encoded CA certificate to verify the OIDC provider's TLS certificate. OidcCaCert string `json:"oidc_ca_cert,omitempty"` @@ -188,17 +232,26 @@ func (m AuthenticationOIDC) MarshalJSON() ([]byte, error) { OidcClientSecret string `json:"oidc_client_secret,omitempty"` // Enables client authentication via signed JWT (HS512) using the client secret, as per RFC 7523. - OidcClientSecretJwt bool `json:"oidc_client_secret_jwt,omitempty"` + OidcClientSecretJwt *bool `json:"oidc_client_secret_jwt,omitempty"` + + // Optional base URL override for the OIDC provider as seen from the Cycloid backend. The backend appends /.well-known/openid-configuration to fetch the discovery document. Defaults to oidc_issuer when omitted. The discovery document's issuer field MUST equal oidc_issuer (enforced server-side). Useful when the backend reaches the IdP via a different network path than user browsers (corporate DMZ, K8s ingress vs cluster DNS, split-horizon DNS). Send an empty string to clear a previously stored override. + OidcDiscoveryURL *string `json:"oidc_discovery_url,omitempty"` // The friendly name shown on the login button OidcDisplayName string `json:"oidc_display_name,omitempty"` + // Name of the OIDC token claim listing the user's group memberships, used for OIDC group mapping. Defaults to "groups" when omitted. The IdP must be configured to include this claim in the issued ID token — group mapping has no effect if the provider omits it. Enterprise IdPs such as Keycloak, Okta, Azure AD/Entra ID, and Auth0 support configurable group claims; consumer providers such as Google Workspace and GitHub do not include group claims in standard OIDC tokens. + OidcGroupsClaimName string `json:"oidc_groups_claim_name,omitempty"` + // URL of the icon to display on the OIDC authentication login screen. OidcIcon string `json:"oidc_icon,omitempty"` // The base URL of the OIDC provider. Used for automatic endpoint discovery. OidcIssuer string `json:"oidc_issuer,omitempty"` + // Session lifetime in seconds for JWTs issued from a login through this OIDC integration (BE-1424). The backend clamps the effective value to the range 5 minutes .. 30 days. When omitted or null the global default session TTL applies. + OidcSessionTTLSeconds *int64 `json:"oidc_session_ttl_seconds,omitempty"` + // Disables TLS certificate verification when connecting to the OIDC provider. Use only in development or with self-signed certificates. OidcSkipTLSVerify bool `json:"oidc_skip_tls_verify,omitempty"` @@ -210,6 +263,10 @@ func (m AuthenticationOIDC) MarshalJSON() ([]byte, error) { HasSecret: m.HasSecret, + OidcAllowInsecureDiscovery: m.OidcAllowInsecureDiscovery, + + OidcAutoCreate: m.OidcAutoCreate, + OidcCaCert: m.OidcCaCert, OidcClientID: m.OidcClientID, @@ -218,12 +275,18 @@ func (m AuthenticationOIDC) MarshalJSON() ([]byte, error) { OidcClientSecretJwt: m.OidcClientSecretJwt, + OidcDiscoveryURL: m.OidcDiscoveryURL, + OidcDisplayName: m.OidcDisplayName, + OidcGroupsClaimName: m.OidcGroupsClaimName, + OidcIcon: m.OidcIcon, OidcIssuer: m.OidcIssuer, + OidcSessionTTLSeconds: m.OidcSessionTTLSeconds, + OidcSkipTLSVerify: m.OidcSkipTLSVerify, OidcUseCaCert: m.OidcUseCaCert, diff --git a/client/models/authentication_s_a_m_l.go b/gen/models/authentication_s_a_m_l.go similarity index 97% rename from client/models/authentication_s_a_m_l.go rename to gen/models/authentication_s_a_m_l.go index fe3e75636..62e523e9e 100644 --- a/client/models/authentication_s_a_m_l.go +++ b/gen/models/authentication_s_a_m_l.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "bytes" "context" diff --git a/client/models/azure_cost_export.go b/gen/models/azure_cost_export.go similarity index 96% rename from client/models/azure_cost_export.go rename to gen/models/azure_cost_export.go index d5246a743..b2c63c5a4 100644 --- a/client/models/azure_cost_export.go +++ b/gen/models/azure_cost_export.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "bytes" "context" diff --git a/client/models/azure_remote_t_f_state.go b/gen/models/azure_remote_t_f_state.go similarity index 97% rename from client/models/azure_remote_t_f_state.go rename to gen/models/azure_remote_t_f_state.go index 6e68fbe5c..56b903f0c 100644 --- a/client/models/azure_remote_t_f_state.go +++ b/gen/models/azure_remote_t_f_state.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "bytes" "context" diff --git a/client/models/azure_storage.go b/gen/models/azure_storage.go similarity index 97% rename from client/models/azure_storage.go rename to gen/models/azure_storage.go index 17a68fd4e..d7601763a 100644 --- a/client/models/azure_storage.go +++ b/gen/models/azure_storage.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "bytes" "context" diff --git a/client/models/bare_credential.go b/gen/models/bare_credential.go similarity index 97% rename from client/models/bare_credential.go rename to gen/models/bare_credential.go index 6e7f77163..436a391d4 100644 --- a/client/models/bare_credential.go +++ b/gen/models/bare_credential.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" "encoding/json" diff --git a/client/models/build.go b/gen/models/build.go similarity index 95% rename from client/models/build.go rename to gen/models/build.go index adcdc1eba..6ba045244 100644 --- a/client/models/build.go +++ b/gen/models/build.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/build_inputs_outputs.go b/gen/models/build_inputs_outputs.go similarity index 97% rename from client/models/build_inputs_outputs.go rename to gen/models/build_inputs_outputs.go index 9db475f16..a4a823a47 100644 --- a/client/models/build_inputs_outputs.go +++ b/gen/models/build_inputs_outputs.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/build_summary.go b/gen/models/build_summary.go similarity index 95% rename from client/models/build_summary.go rename to gen/models/build_summary.go index 80afc36e2..49724a1f3 100644 --- a/client/models/build_summary.go +++ b/gen/models/build_summary.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/c_i_version.go b/gen/models/c_i_version.go similarity index 80% rename from client/models/c_i_version.go rename to gen/models/c_i_version.go index 3fe592194..b04b5b308 100644 --- a/client/models/c_i_version.go +++ b/gen/models/c_i_version.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/gen/models/can_do_batch_action_input.go b/gen/models/can_do_batch_action_input.go new file mode 100644 index 000000000..0e2836111 --- /dev/null +++ b/gen/models/can_do_batch_action_input.go @@ -0,0 +1,112 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + + "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" + "github.com/go-openapi/validate" +) + +// CanDoBatchActionInput CanDoBatchActionInput +// +// A single action item in the 'can_do_batch' input +// +// swagger:model CanDoBatchActionInput +type CanDoBatchActionInput struct { + + // action + // Required: true + Action *string `json:"action"` + + // A client-chosen key used to identify this action in the response map + // Required: true + // Min Length: 1 + Canonical *string `json:"canonical"` + + // List of the canonicals to the Resource excluding the Organization + // Required: true + EntityCanonicals []string `json:"entity_canonicals"` +} + +// Validate validates this can do batch action input +func (m *CanDoBatchActionInput) Validate(formats strfmt.Registry) error { + var res []error + + if err := m.validateAction(formats); err != nil { + res = append(res, err) + } + + if err := m.validateCanonical(formats); err != nil { + res = append(res, err) + } + + if err := m.validateEntityCanonicals(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *CanDoBatchActionInput) validateAction(formats strfmt.Registry) error { + + if err := validate.Required("action", "body", m.Action); err != nil { + return err + } + + return nil +} + +func (m *CanDoBatchActionInput) validateCanonical(formats strfmt.Registry) error { + + if err := validate.Required("canonical", "body", m.Canonical); err != nil { + return err + } + + if err := validate.MinLength("canonical", "body", *m.Canonical, 1); err != nil { + return err + } + + return nil +} + +func (m *CanDoBatchActionInput) validateEntityCanonicals(formats strfmt.Registry) error { + + if err := validate.Required("entity_canonicals", "body", m.EntityCanonicals); err != nil { + return err + } + + return nil +} + +// ContextValidate validates this can do batch action input based on context it is used +func (m *CanDoBatchActionInput) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (m *CanDoBatchActionInput) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *CanDoBatchActionInput) UnmarshalBinary(b []byte) error { + var res CanDoBatchActionInput + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/gen/models/can_do_batch_input.go b/gen/models/can_do_batch_input.go new file mode 100644 index 000000000..330fdb861 --- /dev/null +++ b/gen/models/can_do_batch_input.go @@ -0,0 +1,135 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + stderrors "errors" + "strconv" + + "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" + "github.com/go-openapi/validate" +) + +// CanDoBatchInput CanDoBatchInput +// +// The input of the 'can_do_batch' endpoint +// +// swagger:model CanDoBatchInput +type CanDoBatchInput struct { + + // actions + // Required: true + Actions []*CanDoBatchActionInput `json:"actions"` +} + +// Validate validates this can do batch input +func (m *CanDoBatchInput) Validate(formats strfmt.Registry) error { + var res []error + + if err := m.validateActions(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *CanDoBatchInput) validateActions(formats strfmt.Registry) error { + + if err := validate.Required("actions", "body", m.Actions); err != nil { + return err + } + + for i := 0; i < len(m.Actions); i++ { + if swag.IsZero(m.Actions[i]) { // not required + continue + } + + if m.Actions[i] != nil { + if err := m.Actions[i].Validate(formats); err != nil { + ve := new(errors.Validation) + if stderrors.As(err, &ve) { + return ve.ValidateName("actions" + "." + strconv.Itoa(i)) + } + ce := new(errors.CompositeError) + if stderrors.As(err, &ce) { + return ce.ValidateName("actions" + "." + strconv.Itoa(i)) + } + + return err + } + } + + } + + return nil +} + +// ContextValidate validate this can do batch input based on the context it is used +func (m *CanDoBatchInput) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + var res []error + + if err := m.contextValidateActions(ctx, formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *CanDoBatchInput) contextValidateActions(ctx context.Context, formats strfmt.Registry) error { + + for i := 0; i < len(m.Actions); i++ { + + if m.Actions[i] != nil { + + if swag.IsZero(m.Actions[i]) { // not required + return nil + } + + if err := m.Actions[i].ContextValidate(ctx, formats); err != nil { + ve := new(errors.Validation) + if stderrors.As(err, &ve) { + return ve.ValidateName("actions" + "." + strconv.Itoa(i)) + } + ce := new(errors.CompositeError) + if stderrors.As(err, &ce) { + return ce.ValidateName("actions" + "." + strconv.Itoa(i)) + } + + return err + } + } + + } + + return nil +} + +// MarshalBinary interface implementation +func (m *CanDoBatchInput) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *CanDoBatchInput) UnmarshalBinary(b []byte) error { + var res CanDoBatchInput + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/gen/models/can_do_batch_output_item.go b/gen/models/can_do_batch_output_item.go new file mode 100644 index 000000000..657fee0d6 --- /dev/null +++ b/gen/models/can_do_batch_output_item.go @@ -0,0 +1,93 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + + "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" + "github.com/go-openapi/validate" +) + +// CanDoBatchOutputItem CanDoBatchOutputItem +// +// A single result item from the 'can_do_batch' endpoint +// +// swagger:model CanDoBatchOutputItem +type CanDoBatchOutputItem struct { + + // action + // Required: true + Action *string `json:"action"` + + // entity canonicals + EntityCanonicals []string `json:"entity_canonicals"` + + // ok + // Required: true + Ok *bool `json:"ok"` +} + +// Validate validates this can do batch output item +func (m *CanDoBatchOutputItem) Validate(formats strfmt.Registry) error { + var res []error + + if err := m.validateAction(formats); err != nil { + res = append(res, err) + } + + if err := m.validateOk(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *CanDoBatchOutputItem) validateAction(formats strfmt.Registry) error { + + if err := validate.Required("action", "body", m.Action); err != nil { + return err + } + + return nil +} + +func (m *CanDoBatchOutputItem) validateOk(formats strfmt.Registry) error { + + if err := validate.Required("ok", "body", m.Ok); err != nil { + return err + } + + return nil +} + +// ContextValidate validates this can do batch output item based on context it is used +func (m *CanDoBatchOutputItem) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (m *CanDoBatchOutputItem) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *CanDoBatchOutputItem) UnmarshalBinary(b []byte) error { + var res CanDoBatchOutputItem + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/client/models/can_do_input.go b/gen/models/can_do_input.go similarity index 93% rename from client/models/can_do_input.go rename to gen/models/can_do_input.go index 33542aa87..b8be03a3a 100644 --- a/client/models/can_do_input.go +++ b/gen/models/can_do_input.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/can_do_output.go b/gen/models/can_do_output.go similarity index 91% rename from client/models/can_do_output.go rename to gen/models/can_do_output.go index 42ddfbda2..4b6ad2135 100644 --- a/client/models/can_do_output.go +++ b/gen/models/can_do_output.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/check_report.go b/gen/models/check_report.go similarity index 96% rename from client/models/check_report.go rename to gen/models/check_report.go index 310fa170c..fdeae7bc3 100644 --- a/client/models/check_report.go +++ b/gen/models/check_report.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" "encoding/json" diff --git a/client/models/clear_task_cache.go b/gen/models/clear_task_cache.go similarity index 92% rename from client/models/clear_task_cache.go rename to gen/models/clear_task_cache.go index 17f03e83e..7a4f83d81 100644 --- a/client/models/clear_task_cache.go +++ b/gen/models/clear_task_cache.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/cloud_account.go b/gen/models/cloud_account.go similarity index 98% rename from client/models/cloud_account.go rename to gen/models/cloud_account.go index 318366785..415d109b8 100644 --- a/client/models/cloud_account.go +++ b/gen/models/cloud_account.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/cloud_account_detail.go b/gen/models/cloud_account_detail.go similarity index 97% rename from client/models/cloud_account_detail.go rename to gen/models/cloud_account_detail.go index b4710de8b..434f27d95 100644 --- a/client/models/cloud_account_detail.go +++ b/gen/models/cloud_account_detail.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/cloud_account_simple.go b/gen/models/cloud_account_simple.go similarity index 96% rename from client/models/cloud_account_simple.go rename to gen/models/cloud_account_simple.go index 067717534..0724fa40d 100644 --- a/client/models/cloud_account_simple.go +++ b/gen/models/cloud_account_simple.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/cloud_cost_management_account.go b/gen/models/cloud_cost_management_account.go similarity index 98% rename from client/models/cloud_cost_management_account.go rename to gen/models/cloud_cost_management_account.go index 389ca3541..ddc30615e 100644 --- a/client/models/cloud_cost_management_account.go +++ b/gen/models/cloud_cost_management_account.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" "encoding/json" diff --git a/client/models/cloud_cost_management_bucket.go b/gen/models/cloud_cost_management_bucket.go similarity index 97% rename from client/models/cloud_cost_management_bucket.go rename to gen/models/cloud_cost_management_bucket.go index 374f02015..4796c7693 100644 --- a/client/models/cloud_cost_management_bucket.go +++ b/gen/models/cloud_cost_management_bucket.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/cloud_cost_management_dashboard.go b/gen/models/cloud_cost_management_dashboard.go similarity index 98% rename from client/models/cloud_cost_management_dashboard.go rename to gen/models/cloud_cost_management_dashboard.go index 6285e4132..d82a3c1df 100644 --- a/client/models/cloud_cost_management_dashboard.go +++ b/gen/models/cloud_cost_management_dashboard.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/cloud_cost_management_filter_values.go b/gen/models/cloud_cost_management_filter_values.go similarity index 94% rename from client/models/cloud_cost_management_filter_values.go rename to gen/models/cloud_cost_management_filter_values.go index ed719b3cd..c29aa6479 100644 --- a/client/models/cloud_cost_management_filter_values.go +++ b/gen/models/cloud_cost_management_filter_values.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/cloud_cost_management_histogram.go b/gen/models/cloud_cost_management_histogram.go similarity index 96% rename from client/models/cloud_cost_management_histogram.go rename to gen/models/cloud_cost_management_histogram.go index 1099cb106..f3ca6ff12 100644 --- a/client/models/cloud_cost_management_histogram.go +++ b/gen/models/cloud_cost_management_histogram.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/cloud_cost_management_linked_account.go b/gen/models/cloud_cost_management_linked_account.go similarity index 95% rename from client/models/cloud_cost_management_linked_account.go rename to gen/models/cloud_cost_management_linked_account.go index c17ab2c5a..872f3f060 100644 --- a/client/models/cloud_cost_management_linked_account.go +++ b/gen/models/cloud_cost_management_linked_account.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/cloud_cost_management_project_provider_resources.go b/gen/models/cloud_cost_management_project_provider_resources.go similarity index 96% rename from client/models/cloud_cost_management_project_provider_resources.go rename to gen/models/cloud_cost_management_project_provider_resources.go index 7ad402518..f4f4303d0 100644 --- a/client/models/cloud_cost_management_project_provider_resources.go +++ b/gen/models/cloud_cost_management_project_provider_resources.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/cloud_cost_management_project_resources.go b/gen/models/cloud_cost_management_project_resources.go similarity index 96% rename from client/models/cloud_cost_management_project_resources.go rename to gen/models/cloud_cost_management_project_resources.go index f902444b8..e1a2fbf17 100644 --- a/client/models/cloud_cost_management_project_resources.go +++ b/gen/models/cloud_cost_management_project_resources.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/cloud_cost_management_projects_dashboard.go b/gen/models/cloud_cost_management_projects_dashboard.go similarity index 96% rename from client/models/cloud_cost_management_projects_dashboard.go rename to gen/models/cloud_cost_management_projects_dashboard.go index 32c56657b..91443d497 100644 --- a/client/models/cloud_cost_management_projects_dashboard.go +++ b/gen/models/cloud_cost_management_projects_dashboard.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/cloud_cost_management_provider_details.go b/gen/models/cloud_cost_management_provider_details.go similarity index 96% rename from client/models/cloud_cost_management_provider_details.go rename to gen/models/cloud_cost_management_provider_details.go index b41b788da..c244c7913 100644 --- a/client/models/cloud_cost_management_provider_details.go +++ b/gen/models/cloud_cost_management_provider_details.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/cloud_cost_management_providers.go b/gen/models/cloud_cost_management_providers.go similarity index 95% rename from client/models/cloud_cost_management_providers.go rename to gen/models/cloud_cost_management_providers.go index 8d6345f2c..442e3b6e5 100644 --- a/client/models/cloud_cost_management_providers.go +++ b/gen/models/cloud_cost_management_providers.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/cloud_cost_management_tag_mapping.go b/gen/models/cloud_cost_management_tag_mapping.go similarity index 96% rename from client/models/cloud_cost_management_tag_mapping.go rename to gen/models/cloud_cost_management_tag_mapping.go index e581021ce..4be43fba1 100644 --- a/client/models/cloud_cost_management_tag_mapping.go +++ b/gen/models/cloud_cost_management_tag_mapping.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/cloud_provider.go b/gen/models/cloud_provider.go similarity index 98% rename from client/models/cloud_provider.go rename to gen/models/cloud_provider.go index 983e811fa..7ea875b2e 100644 --- a/client/models/cloud_provider.go +++ b/gen/models/cloud_provider.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" "encoding/json" diff --git a/client/models/cloud_provider_a_w_s_configuration.go b/gen/models/cloud_provider_a_w_s_configuration.go similarity index 96% rename from client/models/cloud_provider_a_w_s_configuration.go rename to gen/models/cloud_provider_a_w_s_configuration.go index 9af0828f9..089079fbf 100644 --- a/client/models/cloud_provider_a_w_s_configuration.go +++ b/gen/models/cloud_provider_a_w_s_configuration.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "bytes" "context" diff --git a/client/models/cloud_provider_azure_configuration.go b/gen/models/cloud_provider_azure_configuration.go similarity index 97% rename from client/models/cloud_provider_azure_configuration.go rename to gen/models/cloud_provider_azure_configuration.go index f6a6403a5..cf9709df4 100644 --- a/client/models/cloud_provider_azure_configuration.go +++ b/gen/models/cloud_provider_azure_configuration.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "bytes" "context" diff --git a/client/models/cloud_provider_configuration.go b/gen/models/cloud_provider_configuration.go similarity index 96% rename from client/models/cloud_provider_configuration.go rename to gen/models/cloud_provider_configuration.go index 10d3a0181..ebe0e0a8c 100644 --- a/client/models/cloud_provider_configuration.go +++ b/gen/models/cloud_provider_configuration.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "bytes" "context" diff --git a/client/models/cloud_provider_g_c_p_configuration.go b/gen/models/cloud_provider_g_c_p_configuration.go similarity index 96% rename from client/models/cloud_provider_g_c_p_configuration.go rename to gen/models/cloud_provider_g_c_p_configuration.go index 90c48f4d6..c4efd84eb 100644 --- a/client/models/cloud_provider_g_c_p_configuration.go +++ b/gen/models/cloud_provider_g_c_p_configuration.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "bytes" "context" diff --git a/client/models/cloud_provider_vm_ware_v_sphere_configuration.go b/gen/models/cloud_provider_vm_ware_v_sphere_configuration.go similarity index 97% rename from client/models/cloud_provider_vm_ware_v_sphere_configuration.go rename to gen/models/cloud_provider_vm_ware_v_sphere_configuration.go index 1300c8e8c..911e824a3 100644 --- a/client/models/cloud_provider_vm_ware_v_sphere_configuration.go +++ b/gen/models/cloud_provider_vm_ware_v_sphere_configuration.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "bytes" "context" diff --git a/client/models/component.go b/gen/models/component.go similarity index 89% rename from client/models/component.go rename to gen/models/component.go index a327de4ce..5798dd13e 100644 --- a/client/models/component.go +++ b/gen/models/component.go @@ -2,9 +2,11 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" - "encoding/json" stderrors "errors" "github.com/go-openapi/errors" @@ -50,10 +52,6 @@ type Component struct { // Minimum: 1 ID *uint32 `json:"id"` - // The import process status. - // Enum: ["succeeded","failed","importing"] - ImportStatus string `json:"import_status,omitempty"` - // The status of the component. IsConfigured bool `json:"is_configured,omitempty"` @@ -114,10 +112,6 @@ func (m *Component) Validate(formats strfmt.Registry) error { res = append(res, err) } - if err := m.validateImportStatus(formats); err != nil { - res = append(res, err) - } - if err := m.validateName(formats); err != nil { res = append(res, err) } @@ -246,51 +240,6 @@ func (m *Component) validateID(formats strfmt.Registry) error { return nil } -var componentTypeImportStatusPropEnum []any - -func init() { - var res []string - if err := json.Unmarshal([]byte(`["succeeded","failed","importing"]`), &res); err != nil { - panic(err) - } - for _, v := range res { - componentTypeImportStatusPropEnum = append(componentTypeImportStatusPropEnum, v) - } -} - -const ( - - // ComponentImportStatusSucceeded captures enum value "succeeded" - ComponentImportStatusSucceeded string = "succeeded" - - // ComponentImportStatusFailed captures enum value "failed" - ComponentImportStatusFailed string = "failed" - - // ComponentImportStatusImporting captures enum value "importing" - ComponentImportStatusImporting string = "importing" -) - -// prop value enum -func (m *Component) validateImportStatusEnum(path, location string, value string) error { - if err := validate.EnumCase(path, location, value, componentTypeImportStatusPropEnum, true); err != nil { - return err - } - return nil -} - -func (m *Component) validateImportStatus(formats strfmt.Registry) error { - if swag.IsZero(m.ImportStatus) { // not required - return nil - } - - // value enum - if err := m.validateImportStatusEnum("import_status", "body", m.ImportStatus); err != nil { - return err - } - - return nil -} - func (m *Component) validateName(formats strfmt.Registry) error { if err := validate.Required("name", "body", m.Name); err != nil { diff --git a/client/models/component_simple.go b/gen/models/component_simple.go similarity index 98% rename from client/models/component_simple.go rename to gen/models/component_simple.go index 7c6f0ff37..dfe10d769 100644 --- a/client/models/component_simple.go +++ b/gen/models/component_simple.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/config_file.go b/gen/models/config_file.go similarity index 92% rename from client/models/config_file.go rename to gen/models/config_file.go index 80af2fdde..ffccc0116 100644 --- a/client/models/config_file.go +++ b/gen/models/config_file.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/config_repository.go b/gen/models/config_repository.go similarity index 97% rename from client/models/config_repository.go rename to gen/models/config_repository.go index feb76ea81..0d3cf93f1 100644 --- a/client/models/config_repository.go +++ b/gen/models/config_repository.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/configure_component.go b/gen/models/configure_component.go similarity index 96% rename from client/models/configure_component.go rename to gen/models/configure_component.go index 06a830084..248ad4d73 100644 --- a/client/models/configure_component.go +++ b/gen/models/configure_component.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/cost_estimation_component.go b/gen/models/cost_estimation_component.go similarity index 97% rename from client/models/cost_estimation_component.go rename to gen/models/cost_estimation_component.go index 300aea1ba..bde210444 100644 --- a/client/models/cost_estimation_component.go +++ b/gen/models/cost_estimation_component.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/cost_estimation_component_state.go b/gen/models/cost_estimation_component_state.go similarity index 95% rename from client/models/cost_estimation_component_state.go rename to gen/models/cost_estimation_component_state.go index 482b56e0d..f875fe692 100644 --- a/client/models/cost_estimation_component_state.go +++ b/gen/models/cost_estimation_component_state.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/cost_estimation_resource_estimate.go b/gen/models/cost_estimation_resource_estimate.go similarity index 97% rename from client/models/cost_estimation_resource_estimate.go rename to gen/models/cost_estimation_resource_estimate.go index 9b9efc0a7..51fe2718b 100644 --- a/client/models/cost_estimation_resource_estimate.go +++ b/gen/models/cost_estimation_resource_estimate.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/cost_estimation_result.go b/gen/models/cost_estimation_result.go similarity index 96% rename from client/models/cost_estimation_result.go rename to gen/models/cost_estimation_result.go index 93336fa35..928c50cc0 100644 --- a/client/models/cost_estimation_result.go +++ b/gen/models/cost_estimation_result.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/country.go b/gen/models/country.go similarity index 92% rename from client/models/country.go rename to gen/models/country.go index 2615f2ee8..c20d37ae6 100644 --- a/client/models/country.go +++ b/gen/models/country.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/create_or_update_subscription.go b/gen/models/create_or_update_subscription.go similarity index 96% rename from client/models/create_or_update_subscription.go rename to gen/models/create_or_update_subscription.go index 6b0fc2552..573f91895 100644 --- a/client/models/create_or_update_subscription.go +++ b/gen/models/create_or_update_subscription.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" "encoding/json" diff --git a/client/models/credential.go b/gen/models/credential.go similarity index 98% rename from client/models/credential.go rename to gen/models/credential.go index 21183507a..0d281ab6d 100644 --- a/client/models/credential.go +++ b/gen/models/credential.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" "encoding/json" diff --git a/client/models/credential_in_use.go b/gen/models/credential_in_use.go similarity index 97% rename from client/models/credential_in_use.go rename to gen/models/credential_in_use.go index 77e21e305..976f00df9 100644 --- a/client/models/credential_in_use.go +++ b/gen/models/credential_in_use.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/credential_raw.go b/gen/models/credential_raw.go similarity index 96% rename from client/models/credential_raw.go rename to gen/models/credential_raw.go index d9c954e8c..a75a898db 100644 --- a/client/models/credential_raw.go +++ b/gen/models/credential_raw.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" "encoding/json" diff --git a/client/models/credential_simple.go b/gen/models/credential_simple.go similarity index 98% rename from client/models/credential_simple.go rename to gen/models/credential_simple.go index efb9d6839..78a9245b5 100644 --- a/client/models/credential_simple.go +++ b/gen/models/credential_simple.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" "encoding/json" diff --git a/client/models/elasticsearch_logs.go b/gen/models/elasticsearch_logs.go similarity index 98% rename from client/models/elasticsearch_logs.go rename to gen/models/elasticsearch_logs.go index 4699bbdcb..1b21bbcf5 100644 --- a/client/models/elasticsearch_logs.go +++ b/gen/models/elasticsearch_logs.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "bytes" "context" diff --git a/client/models/ensure_plan.go b/gen/models/ensure_plan.go similarity index 96% rename from client/models/ensure_plan.go rename to gen/models/ensure_plan.go index 1274e5454..6f3aa0586 100644 --- a/client/models/ensure_plan.go +++ b/gen/models/ensure_plan.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/environment.go b/gen/models/environment.go similarity index 99% rename from client/models/environment.go rename to gen/models/environment.go index 3bb54c1e5..968e7e4a3 100644 --- a/client/models/environment.go +++ b/gen/models/environment.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" "encoding/json" diff --git a/client/models/environment_simple.go b/gen/models/environment_simple.go similarity index 95% rename from client/models/environment_simple.go rename to gen/models/environment_simple.go index 1b7eea17f..98f7df47f 100644 --- a/client/models/environment_simple.go +++ b/gen/models/environment_simple.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/environment_type.go b/gen/models/environment_type.go similarity index 97% rename from client/models/environment_type.go rename to gen/models/environment_type.go index 18b77bf88..2f793ec9b 100644 --- a/client/models/environment_type.go +++ b/gen/models/environment_type.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/environment_variable_item.go b/gen/models/environment_variable_item.go similarity index 97% rename from client/models/environment_variable_item.go rename to gen/models/environment_variable_item.go index d2309ef15..f6782f53c 100644 --- a/client/models/environment_variable_item.go +++ b/gen/models/environment_variable_item.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" "encoding/json" diff --git a/client/models/error_details_item.go b/gen/models/error_details_item.go similarity index 93% rename from client/models/error_details_item.go rename to gen/models/error_details_item.go index 982d3629d..37fe16bfc 100644 --- a/client/models/error_details_item.go +++ b/gen/models/error_details_item.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/error_payload.go b/gen/models/error_payload.go similarity index 95% rename from client/models/error_payload.go rename to gen/models/error_payload.go index 6413e6dfd..9b88878ab 100644 --- a/client/models/error_payload.go +++ b/gen/models/error_payload.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/event.go b/gen/models/event.go similarity index 98% rename from client/models/event.go rename to gen/models/event.go index 45724b045..63172dace 100644 --- a/client/models/event.go +++ b/gen/models/event.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" "encoding/json" diff --git a/client/models/events_actions_and_entities.go b/gen/models/events_actions_and_entities.go similarity index 93% rename from client/models/events_actions_and_entities.go rename to gen/models/events_actions_and_entities.go index 5eb3796eb..5bae8fcf9 100644 --- a/client/models/events_actions_and_entities.go +++ b/gen/models/events_actions_and_entities.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/events_count.go b/gen/models/events_count.go similarity index 94% rename from client/models/events_count.go rename to gen/models/events_count.go index 3f47e528b..8b7de124e 100644 --- a/client/models/events_count.go +++ b/gen/models/events_count.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/external_backend.go b/gen/models/external_backend.go similarity index 98% rename from client/models/external_backend.go rename to gen/models/external_backend.go index 87dc40b20..9861ebd24 100644 --- a/client/models/external_backend.go +++ b/gen/models/external_backend.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "bytes" "context" diff --git a/client/models/external_backend_configuration.go b/gen/models/external_backend_configuration.go similarity index 97% rename from client/models/external_backend_configuration.go rename to gen/models/external_backend_configuration.go index 8163c1473..89bdfb64a 100644 --- a/client/models/external_backend_configuration.go +++ b/gen/models/external_backend_configuration.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "bytes" "context" diff --git a/client/models/filters.go b/gen/models/filters.go similarity index 60% rename from client/models/filters.go rename to gen/models/filters.go index 570aaf1ae..0a3e95afb 100644 --- a/client/models/filters.go +++ b/gen/models/filters.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + // Filters Filters // // # Filters is the possible values the filters can have on list requests diff --git a/client/models/form_entity.go b/gen/models/form_entity.go similarity index 83% rename from client/models/form_entity.go rename to gen/models/form_entity.go index 040012e20..1431ceddf 100644 --- a/client/models/form_entity.go +++ b/gen/models/form_entity.go @@ -2,9 +2,14 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" "encoding/json" + stderrors "errors" + "strconv" "github.com/go-openapi/errors" "github.com/go-openapi/strfmt" @@ -19,6 +24,9 @@ import ( // swagger:model FormEntity type FormEntity struct { + // Optional condition expression that gates whether this widget is displayed. Same V2 syntax as Group.condition (e.g. "$other_field == 'aws'"). Variables prefixed with "ctx_" are runtime-injected and bypass the entity-existence validation. + Condition string `json:"condition,omitempty"` + // The current value that was previously configured for this variable upon creation or update. In case of shared variables having different values, it will be empty, and 'mismatch_values' will be filled instead. Current any `json:"current,omitempty"` @@ -42,6 +50,9 @@ type FormEntity struct { // Whether or not the entity should be displayed to the user. This entity must be usable as such (not required, or with a default if required) Folded bool `json:"folded,omitempty"` + // Sub-entity definitions for the repeatable widget. Each item defines a field that users can fill N times. Only valid when widget is 'repeatable'. + Items []*FormEntity `json:"items"` + // The key is the name of variables for the ansible/pipeline/terraform technologies. If this is a first level variable then: keyX. If you have multiple terraform modules then use: module.Y.keyX to help identify the unique variable. // Required: true Key *string `json:"key"` @@ -95,7 +106,7 @@ type FormEntity struct { // The widget used to display the data in the most suitable way // Required: true - // Enum: ["auto_complete","dropdown","radios","slider_list","slider_range","number","simple_text","switch","text_area","cy_cred","cy_scs","cy_crs","cy_branch","cy_inventory_resource","cy_inventory_output","date_time","hidden"] + // Enum: ["auto_complete","dropdown","radios","slider_list","slider_range","number","simple_text","switch","text_area","cy_cred","cy_scs","cy_crs","cy_branch","cy_inventory_resource","cy_inventory_output","date_time","hidden","repeatable"] Widget *string `json:"widget"` // Some specific configuration that could be applied to that widget. Currently only a few widgets can be configured: @@ -132,6 +143,10 @@ type FormEntity struct { // * 'environment' (string): Linked environment canonical // * 'component' (string): Linked component canonical // * 'service_catalogs' (list(string)): Linked service catalog (stack) canonicals + // * repeatable + // * 'min_items' (int): minimum number of repeatable instances (0 = no minimum) + // * 'max_items' (int): maximum number of repeatable instances (0 = no maximum) + // * 'item_label' (string): label template for each instance WidgetConfig any `json:"widget_config,omitempty"` } @@ -139,6 +154,10 @@ type FormEntity struct { func (m *FormEntity) Validate(formats strfmt.Registry) error { var res []error + if err := m.validateItems(formats); err != nil { + res = append(res, err) + } + if err := m.validateKey(formats); err != nil { res = append(res, err) } @@ -161,6 +180,36 @@ func (m *FormEntity) Validate(formats strfmt.Registry) error { return nil } +func (m *FormEntity) validateItems(formats strfmt.Registry) error { + if swag.IsZero(m.Items) { // not required + return nil + } + + for i := 0; i < len(m.Items); i++ { + if swag.IsZero(m.Items[i]) { // not required + continue + } + + if m.Items[i] != nil { + if err := m.Items[i].Validate(formats); err != nil { + ve := new(errors.Validation) + if stderrors.As(err, &ve) { + return ve.ValidateName("items" + "." + strconv.Itoa(i)) + } + ce := new(errors.CompositeError) + if stderrors.As(err, &ce) { + return ce.ValidateName("items" + "." + strconv.Itoa(i)) + } + + return err + } + } + + } + + return nil +} + func (m *FormEntity) validateKey(formats strfmt.Registry) error { if err := validate.Required("key", "body", m.Key); err != nil { @@ -238,7 +287,7 @@ var formEntityTypeWidgetPropEnum []any func init() { var res []string - if err := json.Unmarshal([]byte(`["auto_complete","dropdown","radios","slider_list","slider_range","number","simple_text","switch","text_area","cy_cred","cy_scs","cy_crs","cy_branch","cy_inventory_resource","cy_inventory_output","date_time","hidden"]`), &res); err != nil { + if err := json.Unmarshal([]byte(`["auto_complete","dropdown","radios","slider_list","slider_range","number","simple_text","switch","text_area","cy_cred","cy_scs","cy_crs","cy_branch","cy_inventory_resource","cy_inventory_output","date_time","hidden","repeatable"]`), &res); err != nil { panic(err) } for _, v := range res { @@ -298,6 +347,9 @@ const ( // FormEntityWidgetHidden captures enum value "hidden" FormEntityWidgetHidden string = "hidden" + + // FormEntityWidgetRepeatable captures enum value "repeatable" + FormEntityWidgetRepeatable string = "repeatable" ) // prop value enum @@ -322,8 +374,46 @@ func (m *FormEntity) validateWidget(formats strfmt.Registry) error { return nil } -// ContextValidate validates this form entity based on context it is used +// ContextValidate validate this form entity based on the context it is used func (m *FormEntity) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + var res []error + + if err := m.contextValidateItems(ctx, formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *FormEntity) contextValidateItems(ctx context.Context, formats strfmt.Registry) error { + + for i := 0; i < len(m.Items); i++ { + + if m.Items[i] != nil { + + if swag.IsZero(m.Items[i]) { // not required + return nil + } + + if err := m.Items[i].ContextValidate(ctx, formats); err != nil { + ve := new(errors.Validation) + if stderrors.As(err, &ve) { + return ve.ValidateName("items" + "." + strconv.Itoa(i)) + } + ce := new(errors.CompositeError) + if stderrors.As(err, &ce) { + return ce.ValidateName("items" + "." + strconv.Itoa(i)) + } + + return err + } + } + + } + return nil } diff --git a/client/models/form_group.go b/gen/models/form_group.go similarity index 96% rename from client/models/form_group.go rename to gen/models/form_group.go index cc19980af..01f963f9c 100644 --- a/client/models/form_group.go +++ b/gen/models/form_group.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/form_section.go b/gen/models/form_section.go similarity index 95% rename from client/models/form_section.go rename to gen/models/form_section.go index c1f9ba96d..5b79d7099 100644 --- a/client/models/form_section.go +++ b/gen/models/form_section.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/form_use_case.go b/gen/models/form_use_case.go similarity index 95% rename from client/models/form_use_case.go rename to gen/models/form_use_case.go index 0143a3383..b829651e4 100644 --- a/client/models/form_use_case.go +++ b/gen/models/form_use_case.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/form_variables.go b/gen/models/form_variables.go similarity index 89% rename from client/models/form_variables.go rename to gen/models/form_variables.go index 0d1e549c9..f081c345d 100644 --- a/client/models/form_variables.go +++ b/gen/models/form_variables.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/forms_file_v3.go b/gen/models/forms_file_v3.go similarity index 95% rename from client/models/forms_file_v3.go rename to gen/models/forms_file_v3.go index 18dc9b54a..e4698e6e1 100644 --- a/client/models/forms_file_v3.go +++ b/gen/models/forms_file_v3.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/forms_validation.go b/gen/models/forms_validation.go similarity index 91% rename from client/models/forms_validation.go rename to gen/models/forms_validation.go index 08da53764..da3f3468f 100644 --- a/client/models/forms_validation.go +++ b/gen/models/forms_validation.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/forms_validation_result.go b/gen/models/forms_validation_result.go similarity index 95% rename from client/models/forms_validation_result.go rename to gen/models/forms_validation_result.go index 904a5d3f1..ba6bdd1cd 100644 --- a/client/models/forms_validation_result.go +++ b/gen/models/forms_validation_result.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/forms_values_ref.go b/gen/models/forms_values_ref.go similarity index 91% rename from client/models/forms_values_ref.go rename to gen/models/forms_values_ref.go index d44563817..1841ab5c1 100644 --- a/client/models/forms_values_ref.go +++ b/gen/models/forms_values_ref.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/g_c_p_cost_storage.go b/gen/models/g_c_p_cost_storage.go similarity index 96% rename from client/models/g_c_p_cost_storage.go rename to gen/models/g_c_p_cost_storage.go index b35e06028..917639ad5 100644 --- a/client/models/g_c_p_cost_storage.go +++ b/gen/models/g_c_p_cost_storage.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "bytes" "context" diff --git a/client/models/g_c_p_remote_t_f_state.go b/gen/models/g_c_p_remote_t_f_state.go similarity index 96% rename from client/models/g_c_p_remote_t_f_state.go rename to gen/models/g_c_p_remote_t_f_state.go index c52e4f9ac..15806da7b 100644 --- a/client/models/g_c_p_remote_t_f_state.go +++ b/gen/models/g_c_p_remote_t_f_state.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "bytes" "context" diff --git a/client/models/g_c_p_storage.go b/gen/models/g_c_p_storage.go similarity index 96% rename from client/models/g_c_p_storage.go rename to gen/models/g_c_p_storage.go index 6668238a9..dadedd8d1 100644 --- a/client/models/g_c_p_storage.go +++ b/gen/models/g_c_p_storage.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "bytes" "context" diff --git a/client/models/general_status.go b/gen/models/general_status.go similarity index 97% rename from client/models/general_status.go rename to gen/models/general_status.go index 68d2f0679..af44337c9 100644 --- a/client/models/general_status.go +++ b/gen/models/general_status.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" "encoding/json" diff --git a/client/models/get_plan.go b/gen/models/get_plan.go similarity index 97% rename from client/models/get_plan.go rename to gen/models/get_plan.go index 407c823aa..759631044 100644 --- a/client/models/get_plan.go +++ b/gen/models/get_plan.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/git_lab_http_storage.go b/gen/models/git_lab_http_storage.go similarity index 96% rename from client/models/git_lab_http_storage.go rename to gen/models/git_lab_http_storage.go index dae8a6942..7ed212f5d 100644 --- a/client/models/git_lab_http_storage.go +++ b/gen/models/git_lab_http_storage.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "bytes" "context" diff --git a/client/models/group_config.go b/gen/models/group_config.go similarity index 91% rename from client/models/group_config.go rename to gen/models/group_config.go index 938d08c41..a0a13ea4c 100644 --- a/client/models/group_config.go +++ b/gen/models/group_config.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/http_storage.go b/gen/models/http_storage.go similarity index 95% rename from client/models/http_storage.go rename to gen/models/http_storage.go index 8ce09f902..88b4533ce 100644 --- a/client/models/http_storage.go +++ b/gen/models/http_storage.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "bytes" "context" diff --git a/client/models/in_use_component.go b/gen/models/in_use_component.go similarity index 93% rename from client/models/in_use_component.go rename to gen/models/in_use_component.go index a11f9bc2c..25e659186 100644 --- a/client/models/in_use_component.go +++ b/gen/models/in_use_component.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/in_use_config_repository.go b/gen/models/in_use_config_repository.go similarity index 94% rename from client/models/in_use_config_repository.go rename to gen/models/in_use_config_repository.go index 5dbef6e7f..424d963af 100644 --- a/client/models/in_use_config_repository.go +++ b/gen/models/in_use_config_repository.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/in_use_environment.go b/gen/models/in_use_environment.go similarity index 93% rename from client/models/in_use_environment.go rename to gen/models/in_use_environment.go index e34972f52..2c05d243e 100644 --- a/client/models/in_use_environment.go +++ b/gen/models/in_use_environment.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/in_use_external_backend.go b/gen/models/in_use_external_backend.go similarity index 97% rename from client/models/in_use_external_backend.go rename to gen/models/in_use_external_backend.go index b764b1b39..50c852baa 100644 --- a/client/models/in_use_external_backend.go +++ b/gen/models/in_use_external_backend.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/in_use_project.go b/gen/models/in_use_project.go similarity index 94% rename from client/models/in_use_project.go rename to gen/models/in_use_project.go index 12f42348d..d2c25599f 100644 --- a/client/models/in_use_project.go +++ b/gen/models/in_use_project.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/in_use_service_catalog_source.go b/gen/models/in_use_service_catalog_source.go similarity index 94% rename from client/models/in_use_service_catalog_source.go rename to gen/models/in_use_service_catalog_source.go index 9da231aae..47ea1e3c5 100644 --- a/client/models/in_use_service_catalog_source.go +++ b/gen/models/in_use_service_catalog_source.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/infra_policies_validation_result.go b/gen/models/infra_policies_validation_result.go similarity index 97% rename from client/models/infra_policies_validation_result.go rename to gen/models/infra_policies_validation_result.go index 810671038..15ff4f851 100644 --- a/client/models/infra_policies_validation_result.go +++ b/gen/models/infra_policies_validation_result.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/infra_policies_validation_result_item.go b/gen/models/infra_policies_validation_result_item.go similarity index 95% rename from client/models/infra_policies_validation_result_item.go rename to gen/models/infra_policies_validation_result_item.go index 6d131203f..e3d4c10e6 100644 --- a/client/models/infra_policies_validation_result_item.go +++ b/gen/models/infra_policies_validation_result_item.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/infra_policy.go b/gen/models/infra_policy.go similarity index 98% rename from client/models/infra_policy.go rename to gen/models/infra_policy.go index 31c70ad23..a69191b8a 100644 --- a/client/models/infra_policy.go +++ b/gen/models/infra_policy.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" "encoding/json" diff --git a/client/models/infrastructure.go b/gen/models/infrastructure.go similarity index 95% rename from client/models/infrastructure.go rename to gen/models/infrastructure.go index cfb3ec995..a94f2e6cc 100644 --- a/client/models/infrastructure.go +++ b/gen/models/infrastructure.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/infrastructure_config.go b/gen/models/infrastructure_config.go similarity index 63% rename from client/models/infrastructure_config.go rename to gen/models/infrastructure_config.go index 056c3b2ed..6bdd650b2 100644 --- a/client/models/infrastructure_config.go +++ b/gen/models/infrastructure_config.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + // InfrastructureConfig InfrastructureConfig // // # Holds all the Infrastructure config of the TFState diff --git a/client/models/infrastructure_graph.go b/gen/models/infrastructure_graph.go similarity index 97% rename from client/models/infrastructure_graph.go rename to gen/models/infrastructure_graph.go index 64f99578d..3b4ac120d 100644 --- a/client/models/infrastructure_graph.go +++ b/gen/models/infrastructure_graph.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/infrastructure_graph_edge.go b/gen/models/infrastructure_graph_edge.go similarity index 95% rename from client/models/infrastructure_graph_edge.go rename to gen/models/infrastructure_graph_edge.go index 0d2685ef3..7ffa717ad 100644 --- a/client/models/infrastructure_graph_edge.go +++ b/gen/models/infrastructure_graph_edge.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/infrastructure_graph_node.go b/gen/models/infrastructure_graph_node.go similarity index 96% rename from client/models/infrastructure_graph_node.go rename to gen/models/infrastructure_graph_node.go index 9752a03f4..6c4e76aaf 100644 --- a/client/models/infrastructure_graph_node.go +++ b/gen/models/infrastructure_graph_node.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/infrastructure_resources_aggregation_item.go b/gen/models/infrastructure_resources_aggregation_item.go similarity index 93% rename from client/models/infrastructure_resources_aggregation_item.go rename to gen/models/infrastructure_resources_aggregation_item.go index c12610272..df47d9a84 100644 --- a/client/models/infrastructure_resources_aggregation_item.go +++ b/gen/models/infrastructure_resources_aggregation_item.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/inventory_output.go b/gen/models/inventory_output.go similarity index 94% rename from client/models/inventory_output.go rename to gen/models/inventory_output.go index f67311f27..d077854d1 100644 --- a/client/models/inventory_output.go +++ b/gen/models/inventory_output.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/inventory_resource.go b/gen/models/inventory_resource.go similarity index 98% rename from client/models/inventory_resource.go rename to gen/models/inventory_resource.go index 919b94d84..f5dd8844c 100644 --- a/client/models/inventory_resource.go +++ b/gen/models/inventory_resource.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/inventory_resource_label.go b/gen/models/inventory_resource_label.go similarity index 95% rename from client/models/inventory_resource_label.go rename to gen/models/inventory_resource_label.go index dc14b6407..7b031112d 100644 --- a/client/models/inventory_resource_label.go +++ b/gen/models/inventory_resource_label.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/job.go b/gen/models/job.go similarity index 98% rename from client/models/job.go rename to gen/models/job.go index 75af63d33..704823dd5 100644 --- a/client/models/job.go +++ b/gen/models/job.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/job_input.go b/gen/models/job_input.go similarity index 96% rename from client/models/job_input.go rename to gen/models/job_input.go index 110503b90..7a8b4516d 100644 --- a/client/models/job_input.go +++ b/gen/models/job_input.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/job_output.go b/gen/models/job_output.go similarity index 92% rename from client/models/job_output.go rename to gen/models/job_output.go index ed9254f67..01d5e3b96 100644 --- a/client/models/job_output.go +++ b/gen/models/job_output.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/k_p_i.go b/gen/models/k_p_i.go similarity index 98% rename from client/models/k_p_i.go rename to gen/models/k_p_i.go index 0a13ddf39..7c09a8180 100644 --- a/client/models/k_p_i.go +++ b/gen/models/k_p_i.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" "encoding/json" diff --git a/client/models/licence.go b/gen/models/licence.go similarity index 97% rename from client/models/licence.go rename to gen/models/licence.go index 3491e2138..4ae4adef3 100644 --- a/client/models/licence.go +++ b/gen/models/licence.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/log_source.go b/gen/models/log_source.go similarity index 92% rename from client/models/log_source.go rename to gen/models/log_source.go index 38d86be17..10f9bf8c2 100644 --- a/client/models/log_source.go +++ b/gen/models/log_source.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/log_source_entry.go b/gen/models/log_source_entry.go similarity index 94% rename from client/models/log_source_entry.go rename to gen/models/log_source_entry.go index daae9c64b..967569096 100644 --- a/client/models/log_source_entry.go +++ b/gen/models/log_source_entry.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/member_assignation.go b/gen/models/member_assignation.go similarity index 93% rename from client/models/member_assignation.go rename to gen/models/member_assignation.go index 9761cbee7..76045f211 100644 --- a/client/models/member_assignation.go +++ b/gen/models/member_assignation.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/member_org.go b/gen/models/member_org.go similarity index 98% rename from client/models/member_org.go rename to gen/models/member_org.go index b3e7f4126..cbe49cfb6 100644 --- a/client/models/member_org.go +++ b/gen/models/member_org.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" "encoding/json" diff --git a/client/models/member_team.go b/gen/models/member_team.go similarity index 98% rename from client/models/member_team.go rename to gen/models/member_team.go index 9c9936aae..292470241 100644 --- a/client/models/member_team.go +++ b/gen/models/member_team.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/metadata_field.go b/gen/models/metadata_field.go similarity index 92% rename from client/models/metadata_field.go rename to gen/models/metadata_field.go index 2997dab68..6918a73ec 100644 --- a/client/models/metadata_field.go +++ b/gen/models/metadata_field.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/migrate_component.go b/gen/models/migrate_component.go similarity index 96% rename from client/models/migrate_component.go rename to gen/models/migrate_component.go index a033e6ed9..21fc55109 100644 --- a/client/models/migrate_component.go +++ b/gen/models/migrate_component.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/new_a_w_s_marketplace_user_account.go b/gen/models/new_a_w_s_marketplace_user_account.go similarity index 97% rename from client/models/new_a_w_s_marketplace_user_account.go rename to gen/models/new_a_w_s_marketplace_user_account.go index d5d688f60..113ab5b88 100644 --- a/client/models/new_a_w_s_marketplace_user_account.go +++ b/gen/models/new_a_w_s_marketplace_user_account.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" "encoding/json" diff --git a/client/models/new_and_configured_component.go b/gen/models/new_and_configured_component.go similarity index 97% rename from client/models/new_and_configured_component.go rename to gen/models/new_and_configured_component.go index f4501844f..2731e5419 100644 --- a/client/models/new_and_configured_component.go +++ b/gen/models/new_and_configured_component.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/new_api_key.go b/gen/models/new_api_key.go similarity index 96% rename from client/models/new_api_key.go rename to gen/models/new_api_key.go index 88eb2d6d6..eb1e53d96 100644 --- a/client/models/new_api_key.go +++ b/gen/models/new_api_key.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/new_appearance.go b/gen/models/new_appearance.go similarity index 98% rename from client/models/new_appearance.go rename to gen/models/new_appearance.go index f1da8bece..154f954f9 100644 --- a/client/models/new_appearance.go +++ b/gen/models/new_appearance.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/new_cloud_account.go b/gen/models/new_cloud_account.go similarity index 97% rename from client/models/new_cloud_account.go rename to gen/models/new_cloud_account.go index 496079525..ffd3abdf1 100644 --- a/client/models/new_cloud_account.go +++ b/gen/models/new_cloud_account.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/new_cloud_account_credential.go b/gen/models/new_cloud_account_credential.go similarity index 98% rename from client/models/new_cloud_account_credential.go rename to gen/models/new_cloud_account_credential.go index 262b57e70..da057d665 100644 --- a/client/models/new_cloud_account_credential.go +++ b/gen/models/new_cloud_account_credential.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" "encoding/json" diff --git a/client/models/new_cloud_account_with_credentials.go b/gen/models/new_cloud_account_with_credentials.go similarity index 98% rename from client/models/new_cloud_account_with_credentials.go rename to gen/models/new_cloud_account_with_credentials.go index fb89a0013..f23cfaf34 100644 --- a/client/models/new_cloud_account_with_credentials.go +++ b/gen/models/new_cloud_account_with_credentials.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/new_cloud_cost_management_account.go b/gen/models/new_cloud_cost_management_account.go similarity index 96% rename from client/models/new_cloud_cost_management_account.go rename to gen/models/new_cloud_cost_management_account.go index 51c48b9cd..1be4f659b 100644 --- a/client/models/new_cloud_cost_management_account.go +++ b/gen/models/new_cloud_cost_management_account.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/new_component.go b/gen/models/new_component.go similarity index 96% rename from client/models/new_component.go rename to gen/models/new_component.go index dbc8bbde0..1c2f52fd6 100644 --- a/client/models/new_component.go +++ b/gen/models/new_component.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/new_config_repository.go b/gen/models/new_config_repository.go similarity index 96% rename from client/models/new_config_repository.go rename to gen/models/new_config_repository.go index d1fc319c8..5d973e05d 100644 --- a/client/models/new_config_repository.go +++ b/gen/models/new_config_repository.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/new_credential.go b/gen/models/new_credential.go similarity index 97% rename from client/models/new_credential.go rename to gen/models/new_credential.go index 3b050763b..eeccfe252 100644 --- a/client/models/new_credential.go +++ b/gen/models/new_credential.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" "encoding/json" diff --git a/client/models/new_environment.go b/gen/models/new_environment.go similarity index 91% rename from client/models/new_environment.go rename to gen/models/new_environment.go index 0064b2b18..0f2c057f6 100644 --- a/client/models/new_environment.go +++ b/gen/models/new_environment.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" @@ -45,10 +48,14 @@ type NewEnvironment struct { // Owner string `json:"owner,omitempty"` - // type + // Canonical of the environment type. When omitted, it is auto-detected + // from the environment canonical by matching the keywords + // `production`/`prod`/`prd`/`live`, `pre-prod`/`preprod`/`staging`/`stage`/`stg`/`uat`, + // `development`/`dev`/`test`/`qa`/`sandbox`, or `preview`/`prev`. + // When no keyword is recognised, it defaults to `production`. + // // Example: production - // Required: true - Type *string `json:"type"` + Type string `json:"type,omitempty"` // Environment variables to attach to the new environment. Keys must not contain dots and must include at least one alphanumeric character. Omit or pass an empty array to create the environment without variables. Variables []*EnvironmentVariableItem `json:"variables"` @@ -74,10 +81,6 @@ func (m *NewEnvironment) Validate(formats strfmt.Registry) error { res = append(res, err) } - if err := m.validateType(formats); err != nil { - res = append(res, err) - } - if err := m.validateVariables(formats); err != nil { res = append(res, err) } @@ -157,15 +160,6 @@ func (m *NewEnvironment) validateName(formats strfmt.Registry) error { return nil } -func (m *NewEnvironment) validateType(formats strfmt.Registry) error { - - if err := validate.Required("type", "body", m.Type); err != nil { - return err - } - - return nil -} - func (m *NewEnvironment) validateVariables(formats strfmt.Registry) error { if swag.IsZero(m.Variables) { // not required return nil diff --git a/client/models/new_environment_type.go b/gen/models/new_environment_type.go similarity index 95% rename from client/models/new_environment_type.go rename to gen/models/new_environment_type.go index 3d042b3f7..c83ec1ae2 100644 --- a/client/models/new_environment_type.go +++ b/gen/models/new_environment_type.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/new_event.go b/gen/models/new_event.go similarity index 98% rename from client/models/new_event.go rename to gen/models/new_event.go index 287a38ec2..2a19dec93 100644 --- a/client/models/new_event.go +++ b/gen/models/new_event.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" "encoding/json" diff --git a/client/models/new_external_backend.go b/gen/models/new_external_backend.go similarity index 98% rename from client/models/new_external_backend.go rename to gen/models/new_external_backend.go index 893516c23..b0d4eaa5b 100644 --- a/client/models/new_external_backend.go +++ b/gen/models/new_external_backend.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "bytes" "context" diff --git a/client/models/new_infra_policy.go b/gen/models/new_infra_policy.go similarity index 97% rename from client/models/new_infra_policy.go rename to gen/models/new_infra_policy.go index e6d425ff1..1cf5d4559 100644 --- a/client/models/new_infra_policy.go +++ b/gen/models/new_infra_policy.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" "encoding/json" diff --git a/client/models/new_inventory_resource.go b/gen/models/new_inventory_resource.go similarity index 96% rename from client/models/new_inventory_resource.go rename to gen/models/new_inventory_resource.go index 18376147f..a8408c9bc 100644 --- a/client/models/new_inventory_resource.go +++ b/gen/models/new_inventory_resource.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/new_k_p_i.go b/gen/models/new_k_p_i.go similarity index 97% rename from client/models/new_k_p_i.go rename to gen/models/new_k_p_i.go index b46410f31..522d9f4bf 100644 --- a/client/models/new_k_p_i.go +++ b/gen/models/new_k_p_i.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" "encoding/json" diff --git a/client/models/new_licence.go b/gen/models/new_licence.go similarity index 91% rename from client/models/new_licence.go rename to gen/models/new_licence.go index 73c2e231f..57b6074ef 100644 --- a/client/models/new_licence.go +++ b/gen/models/new_licence.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/new_member_invitation.go b/gen/models/new_member_invitation.go similarity index 95% rename from client/models/new_member_invitation.go rename to gen/models/new_member_invitation.go index b302dd630..5c131627d 100644 --- a/client/models/new_member_invitation.go +++ b/gen/models/new_member_invitation.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/new_o_auth_user.go b/gen/models/new_o_auth_user.go similarity index 97% rename from client/models/new_o_auth_user.go rename to gen/models/new_o_auth_user.go index 20a114892..a450aadec 100644 --- a/client/models/new_o_auth_user.go +++ b/gen/models/new_o_auth_user.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" "encoding/json" @@ -28,9 +31,6 @@ type NewOAuthUser struct { // Format: email Email *strfmt.Email `json:"email"` - // User's email has been verified - EmailVerified bool `json:"email_verified,omitempty"` - // full name // Required: true // Max Length: 255 diff --git a/gen/models/new_o_id_c_group_mapping.go b/gen/models/new_o_id_c_group_mapping.go new file mode 100644 index 000000000..b2d350b03 --- /dev/null +++ b/gen/models/new_o_id_c_group_mapping.go @@ -0,0 +1,115 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + + "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" + "github.com/go-openapi/validate" +) + +// NewOIDCGroupMapping NewOIDCGroupMapping +// +// The information required to create an OIDC group mapping (organization, group, team). Multiple teams are expressed via multiple mappings. +// +// swagger:model NewOIDCGroupMapping +type NewOIDCGroupMapping struct { + + // The OIDC group claim value to match. + // Required: true + // Max Length: 255 + // Min Length: 1 + GroupName *string `json:"group_name"` + + // The canonical of the team to assign the user to. + // Required: true + // Max Length: 100 + // Min Length: 3 + // Pattern: ^[a-z0-9]+[a-z0-9\-_]+[a-z0-9]+$ + TeamCanonical *string `json:"team_canonical"` +} + +// Validate validates this new o ID c group mapping +func (m *NewOIDCGroupMapping) Validate(formats strfmt.Registry) error { + var res []error + + if err := m.validateGroupName(formats); err != nil { + res = append(res, err) + } + + if err := m.validateTeamCanonical(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *NewOIDCGroupMapping) validateGroupName(formats strfmt.Registry) error { + + if err := validate.Required("group_name", "body", m.GroupName); err != nil { + return err + } + + if err := validate.MinLength("group_name", "body", *m.GroupName, 1); err != nil { + return err + } + + if err := validate.MaxLength("group_name", "body", *m.GroupName, 255); err != nil { + return err + } + + return nil +} + +func (m *NewOIDCGroupMapping) validateTeamCanonical(formats strfmt.Registry) error { + + if err := validate.Required("team_canonical", "body", m.TeamCanonical); err != nil { + return err + } + + if err := validate.MinLength("team_canonical", "body", *m.TeamCanonical, 3); err != nil { + return err + } + + if err := validate.MaxLength("team_canonical", "body", *m.TeamCanonical, 100); err != nil { + return err + } + + if err := validate.Pattern("team_canonical", "body", *m.TeamCanonical, `^[a-z0-9]+[a-z0-9\-_]+[a-z0-9]+$`); err != nil { + return err + } + + return nil +} + +// ContextValidate validates this new o ID c group mapping based on context it is used +func (m *NewOIDCGroupMapping) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (m *NewOIDCGroupMapping) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *NewOIDCGroupMapping) UnmarshalBinary(b []byte) error { + var res NewOIDCGroupMapping + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/client/models/new_organization.go b/gen/models/new_organization.go similarity index 94% rename from client/models/new_organization.go rename to gen/models/new_organization.go index 6e8411ffe..ef0ede7b0 100644 --- a/client/models/new_organization.go +++ b/gen/models/new_organization.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/new_pipeline.go b/gen/models/new_pipeline.go similarity index 94% rename from client/models/new_pipeline.go rename to gen/models/new_pipeline.go index 81e9699eb..f00b9f920 100644 --- a/client/models/new_pipeline.go +++ b/gen/models/new_pipeline.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/new_plugin.go b/gen/models/new_plugin.go similarity index 91% rename from client/models/new_plugin.go rename to gen/models/new_plugin.go index b4250f149..93b542600 100644 --- a/client/models/new_plugin.go +++ b/gen/models/new_plugin.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/new_plugin_install.go b/gen/models/new_plugin_install.go similarity index 92% rename from client/models/new_plugin_install.go rename to gen/models/new_plugin_install.go index 0b54dbf21..28f1c1cce 100644 --- a/client/models/new_plugin_install.go +++ b/gen/models/new_plugin_install.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/new_plugin_manager.go b/gen/models/new_plugin_manager.go similarity index 94% rename from client/models/new_plugin_manager.go rename to gen/models/new_plugin_manager.go index bc63e46ae..3ff1ef03c 100644 --- a/client/models/new_plugin_manager.go +++ b/gen/models/new_plugin_manager.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/new_plugin_registry.go b/gen/models/new_plugin_registry.go similarity index 93% rename from client/models/new_plugin_registry.go rename to gen/models/new_plugin_registry.go index 04e6a5ad2..7b17a4843 100644 --- a/client/models/new_plugin_registry.go +++ b/gen/models/new_plugin_registry.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/new_plugin_version.go b/gen/models/new_plugin_version.go similarity index 91% rename from client/models/new_plugin_version.go rename to gen/models/new_plugin_version.go index 1c546114f..f7679880f 100644 --- a/client/models/new_plugin_version.go +++ b/gen/models/new_plugin_version.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/new_project.go b/gen/models/new_project.go similarity index 97% rename from client/models/new_project.go rename to gen/models/new_project.go index e5a561f6a..966480550 100644 --- a/client/models/new_project.go +++ b/gen/models/new_project.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/new_role.go b/gen/models/new_role.go similarity index 96% rename from client/models/new_role.go rename to gen/models/new_role.go index 1dcc01722..8fd9ada5a 100644 --- a/client/models/new_role.go +++ b/gen/models/new_role.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/new_rule.go b/gen/models/new_rule.go similarity index 95% rename from client/models/new_rule.go rename to gen/models/new_rule.go index 2e7e92b8b..4b04beee3 100644 --- a/client/models/new_rule.go +++ b/gen/models/new_rule.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" "encoding/json" diff --git a/client/models/new_service_catalog.go b/gen/models/new_service_catalog.go similarity index 98% rename from client/models/new_service_catalog.go rename to gen/models/new_service_catalog.go index 363ba0cc4..52c79d362 100644 --- a/client/models/new_service_catalog.go +++ b/gen/models/new_service_catalog.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/new_service_catalog_from_template.go b/gen/models/new_service_catalog_from_template.go similarity index 97% rename from client/models/new_service_catalog_from_template.go rename to gen/models/new_service_catalog_from_template.go index 98ccaf2d8..138b54e25 100644 --- a/client/models/new_service_catalog_from_template.go +++ b/gen/models/new_service_catalog_from_template.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/new_service_catalog_source.go b/gen/models/new_service_catalog_source.go similarity index 97% rename from client/models/new_service_catalog_source.go rename to gen/models/new_service_catalog_source.go index 1be51e324..cab9fde2d 100644 --- a/client/models/new_service_catalog_source.go +++ b/gen/models/new_service_catalog_source.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/new_subscription.go b/gen/models/new_subscription.go similarity index 93% rename from client/models/new_subscription.go rename to gen/models/new_subscription.go index fadd3b769..e5cadde5e 100644 --- a/client/models/new_subscription.go +++ b/gen/models/new_subscription.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/new_team.go b/gen/models/new_team.go similarity index 96% rename from client/models/new_team.go rename to gen/models/new_team.go index 24c3e4407..6e4fa2752 100644 --- a/client/models/new_team.go +++ b/gen/models/new_team.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" "strconv" diff --git a/client/models/new_team_member_assignation.go b/gen/models/new_team_member_assignation.go similarity index 94% rename from client/models/new_team_member_assignation.go rename to gen/models/new_team_member_assignation.go index 3d684f6b6..b8de00995 100644 --- a/client/models/new_team_member_assignation.go +++ b/gen/models/new_team_member_assignation.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/new_user_account.go b/gen/models/new_user_account.go similarity index 97% rename from client/models/new_user_account.go rename to gen/models/new_user_account.go index 1646647f4..78e065a65 100644 --- a/client/models/new_user_account.go +++ b/gen/models/new_user_account.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" "encoding/json" diff --git a/client/models/new_watch_rule.go b/gen/models/new_watch_rule.go similarity index 97% rename from client/models/new_watch_rule.go rename to gen/models/new_watch_rule.go index 288b23844..6aebe2ed9 100644 --- a/client/models/new_watch_rule.go +++ b/gen/models/new_watch_rule.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/new_watch_rule_filter.go b/gen/models/new_watch_rule_filter.go similarity index 93% rename from client/models/new_watch_rule_filter.go rename to gen/models/new_watch_rule_filter.go index 4312b4c05..0928abdf2 100644 --- a/client/models/new_watch_rule_filter.go +++ b/gen/models/new_watch_rule_filter.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/notification.go b/gen/models/notification.go similarity index 97% rename from client/models/notification.go rename to gen/models/notification.go index 5c7872130..a027803cf 100644 --- a/client/models/notification.go +++ b/gen/models/notification.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/notification_settings.go b/gen/models/notification_settings.go similarity index 96% rename from client/models/notification_settings.go rename to gen/models/notification_settings.go index b15d71269..5115780f9 100644 --- a/client/models/notification_settings.go +++ b/gen/models/notification_settings.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" "encoding/json" diff --git a/gen/models/o_id_c_group_mapping.go b/gen/models/o_id_c_group_mapping.go new file mode 100644 index 000000000..c049e8b3c --- /dev/null +++ b/gen/models/o_id_c_group_mapping.go @@ -0,0 +1,193 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + stderrors "errors" + + "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" + "github.com/go-openapi/validate" +) + +// OIDCGroupMapping OIDCGroupMapping +// +// Maps an OIDC group claim to a team within an organization. The org-level role is driven by the per-organization OIDC settings (default_role), not by the mapping. Requires the IdP to include group claims in the issued token — enterprise IdPs (Keycloak, Okta, Azure AD/Entra ID, Auth0, EU Login/ECAS) support this; consumer providers such as Google Workspace and GitHub do not. +// +// swagger:model OIDCGroupMapping +type OIDCGroupMapping struct { + + // created at + // Minimum: 0 + CreatedAt *uint64 `json:"created_at,omitempty"` + + // The OIDC group claim value to match. + // Required: true + GroupName *string `json:"group_name"` + + // id + // Required: true + ID *uint32 `json:"id"` + + // The team the user is added to when this mapping matches. + // Required: true + Team *OIDCGroupMappingTeam `json:"team"` + + // updated at + // Minimum: 0 + UpdatedAt *uint64 `json:"updated_at,omitempty"` +} + +// Validate validates this o ID c group mapping +func (m *OIDCGroupMapping) Validate(formats strfmt.Registry) error { + var res []error + + if err := m.validateCreatedAt(formats); err != nil { + res = append(res, err) + } + + if err := m.validateGroupName(formats); err != nil { + res = append(res, err) + } + + if err := m.validateID(formats); err != nil { + res = append(res, err) + } + + if err := m.validateTeam(formats); err != nil { + res = append(res, err) + } + + if err := m.validateUpdatedAt(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *OIDCGroupMapping) validateCreatedAt(formats strfmt.Registry) error { + if swag.IsZero(m.CreatedAt) { // not required + return nil + } + + if err := validate.MinimumUint("created_at", "body", *m.CreatedAt, 0, false); err != nil { + return err + } + + return nil +} + +func (m *OIDCGroupMapping) validateGroupName(formats strfmt.Registry) error { + + if err := validate.Required("group_name", "body", m.GroupName); err != nil { + return err + } + + return nil +} + +func (m *OIDCGroupMapping) validateID(formats strfmt.Registry) error { + + if err := validate.Required("id", "body", m.ID); err != nil { + return err + } + + return nil +} + +func (m *OIDCGroupMapping) validateTeam(formats strfmt.Registry) error { + + if err := validate.Required("team", "body", m.Team); err != nil { + return err + } + + if m.Team != nil { + if err := m.Team.Validate(formats); err != nil { + ve := new(errors.Validation) + if stderrors.As(err, &ve) { + return ve.ValidateName("team") + } + ce := new(errors.CompositeError) + if stderrors.As(err, &ce) { + return ce.ValidateName("team") + } + + return err + } + } + + return nil +} + +func (m *OIDCGroupMapping) validateUpdatedAt(formats strfmt.Registry) error { + if swag.IsZero(m.UpdatedAt) { // not required + return nil + } + + if err := validate.MinimumUint("updated_at", "body", *m.UpdatedAt, 0, false); err != nil { + return err + } + + return nil +} + +// ContextValidate validate this o ID c group mapping based on the context it is used +func (m *OIDCGroupMapping) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + var res []error + + if err := m.contextValidateTeam(ctx, formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *OIDCGroupMapping) contextValidateTeam(ctx context.Context, formats strfmt.Registry) error { + + if m.Team != nil { + + if err := m.Team.ContextValidate(ctx, formats); err != nil { + ve := new(errors.Validation) + if stderrors.As(err, &ve) { + return ve.ValidateName("team") + } + ce := new(errors.CompositeError) + if stderrors.As(err, &ce) { + return ce.ValidateName("team") + } + + return err + } + } + + return nil +} + +// MarshalBinary interface implementation +func (m *OIDCGroupMapping) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *OIDCGroupMapping) UnmarshalBinary(b []byte) error { + var res OIDCGroupMapping + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/gen/models/o_id_c_group_mapping_team.go b/gen/models/o_id_c_group_mapping_team.go new file mode 100644 index 000000000..8997cf64e --- /dev/null +++ b/gen/models/o_id_c_group_mapping_team.go @@ -0,0 +1,211 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + stderrors "errors" + "strconv" + + "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" + "github.com/go-openapi/validate" +) + +// OIDCGroupMappingTeam OIDCGroupMappingTeam +// +// A summary of a team used within an OIDC group mapping, including its associated roles. +// +// swagger:model OIDCGroupMappingTeam +type OIDCGroupMappingTeam struct { + + // canonical + // Required: true + // Max Length: 100 + // Min Length: 3 + // Pattern: ^[a-z0-9]+[a-z0-9\-_]+[a-z0-9]+$ + Canonical *string `json:"canonical"` + + // id + // Required: true + // Minimum: 1 + ID *uint32 `json:"id"` + + // name + // Required: true + // Min Length: 3 + Name *string `json:"name"` + + // The roles granted to members of this team. + // Required: true + Roles []*Role `json:"roles"` +} + +// Validate validates this o ID c group mapping team +func (m *OIDCGroupMappingTeam) Validate(formats strfmt.Registry) error { + var res []error + + if err := m.validateCanonical(formats); err != nil { + res = append(res, err) + } + + if err := m.validateID(formats); err != nil { + res = append(res, err) + } + + if err := m.validateName(formats); err != nil { + res = append(res, err) + } + + if err := m.validateRoles(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *OIDCGroupMappingTeam) validateCanonical(formats strfmt.Registry) error { + + if err := validate.Required("canonical", "body", m.Canonical); err != nil { + return err + } + + if err := validate.MinLength("canonical", "body", *m.Canonical, 3); err != nil { + return err + } + + if err := validate.MaxLength("canonical", "body", *m.Canonical, 100); err != nil { + return err + } + + if err := validate.Pattern("canonical", "body", *m.Canonical, `^[a-z0-9]+[a-z0-9\-_]+[a-z0-9]+$`); err != nil { + return err + } + + return nil +} + +func (m *OIDCGroupMappingTeam) validateID(formats strfmt.Registry) error { + + if err := validate.Required("id", "body", m.ID); err != nil { + return err + } + + if err := validate.MinimumUint("id", "body", uint64(*m.ID), 1, false); err != nil { + return err + } + + return nil +} + +func (m *OIDCGroupMappingTeam) validateName(formats strfmt.Registry) error { + + if err := validate.Required("name", "body", m.Name); err != nil { + return err + } + + if err := validate.MinLength("name", "body", *m.Name, 3); err != nil { + return err + } + + return nil +} + +func (m *OIDCGroupMappingTeam) validateRoles(formats strfmt.Registry) error { + + if err := validate.Required("roles", "body", m.Roles); err != nil { + return err + } + + for i := 0; i < len(m.Roles); i++ { + if swag.IsZero(m.Roles[i]) { // not required + continue + } + + if m.Roles[i] != nil { + if err := m.Roles[i].Validate(formats); err != nil { + ve := new(errors.Validation) + if stderrors.As(err, &ve) { + return ve.ValidateName("roles" + "." + strconv.Itoa(i)) + } + ce := new(errors.CompositeError) + if stderrors.As(err, &ce) { + return ce.ValidateName("roles" + "." + strconv.Itoa(i)) + } + + return err + } + } + + } + + return nil +} + +// ContextValidate validate this o ID c group mapping team based on the context it is used +func (m *OIDCGroupMappingTeam) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + var res []error + + if err := m.contextValidateRoles(ctx, formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *OIDCGroupMappingTeam) contextValidateRoles(ctx context.Context, formats strfmt.Registry) error { + + for i := 0; i < len(m.Roles); i++ { + + if m.Roles[i] != nil { + + if swag.IsZero(m.Roles[i]) { // not required + return nil + } + + if err := m.Roles[i].ContextValidate(ctx, formats); err != nil { + ve := new(errors.Validation) + if stderrors.As(err, &ve) { + return ve.ValidateName("roles" + "." + strconv.Itoa(i)) + } + ce := new(errors.CompositeError) + if stderrors.As(err, &ce) { + return ce.ValidateName("roles" + "." + strconv.Itoa(i)) + } + + return err + } + } + + } + + return nil +} + +// MarshalBinary interface implementation +func (m *OIDCGroupMappingTeam) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *OIDCGroupMappingTeam) UnmarshalBinary(b []byte) error { + var res OIDCGroupMappingTeam + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/gen/models/o_id_c_organization_settings.go b/gen/models/o_id_c_organization_settings.go new file mode 100644 index 000000000..16a1e0285 --- /dev/null +++ b/gen/models/o_id_c_organization_settings.go @@ -0,0 +1,129 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + "encoding/json" + + "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" + "github.com/go-openapi/validate" +) + +// OIDCOrganizationSettings OIDCOrganizationSettings +// +// The per-organization OIDC reconciliation settings. +// +// swagger:model OIDCOrganizationSettings +type OIDCOrganizationSettings struct { + + // The canonical of the org-level role granted on OIDC provisioning. Empty when no default role is configured. + DefaultRoleCanonical string `json:"default_role_canonical,omitempty"` + + // When true, local member/team/invite edits are disabled (strict mode). + // Required: true + OidcManaged *bool `json:"oidc_managed"` + + // The policy applied when no group mapping matches on login. + // Required: true + // Enum: ["keep_membership","eject"] + OidcNoMatchPolicy *string `json:"oidc_no_match_policy"` +} + +// Validate validates this o ID c organization settings +func (m *OIDCOrganizationSettings) Validate(formats strfmt.Registry) error { + var res []error + + if err := m.validateOidcManaged(formats); err != nil { + res = append(res, err) + } + + if err := m.validateOidcNoMatchPolicy(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *OIDCOrganizationSettings) validateOidcManaged(formats strfmt.Registry) error { + + if err := validate.Required("oidc_managed", "body", m.OidcManaged); err != nil { + return err + } + + return nil +} + +var oIdCOrganizationSettingsTypeOidcNoMatchPolicyPropEnum []any + +func init() { + var res []string + if err := json.Unmarshal([]byte(`["keep_membership","eject"]`), &res); err != nil { + panic(err) + } + for _, v := range res { + oIdCOrganizationSettingsTypeOidcNoMatchPolicyPropEnum = append(oIdCOrganizationSettingsTypeOidcNoMatchPolicyPropEnum, v) + } +} + +const ( + + // OIDCOrganizationSettingsOidcNoMatchPolicyKeepMembership captures enum value "keep_membership" + OIDCOrganizationSettingsOidcNoMatchPolicyKeepMembership string = "keep_membership" + + // OIDCOrganizationSettingsOidcNoMatchPolicyEject captures enum value "eject" + OIDCOrganizationSettingsOidcNoMatchPolicyEject string = "eject" +) + +// prop value enum +func (m *OIDCOrganizationSettings) validateOidcNoMatchPolicyEnum(path, location string, value string) error { + if err := validate.EnumCase(path, location, value, oIdCOrganizationSettingsTypeOidcNoMatchPolicyPropEnum, true); err != nil { + return err + } + return nil +} + +func (m *OIDCOrganizationSettings) validateOidcNoMatchPolicy(formats strfmt.Registry) error { + + if err := validate.Required("oidc_no_match_policy", "body", m.OidcNoMatchPolicy); err != nil { + return err + } + + // value enum + if err := m.validateOidcNoMatchPolicyEnum("oidc_no_match_policy", "body", *m.OidcNoMatchPolicy); err != nil { + return err + } + + return nil +} + +// ContextValidate validates this o ID c organization settings based on context it is used +func (m *OIDCOrganizationSettings) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (m *OIDCOrganizationSettings) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *OIDCOrganizationSettings) UnmarshalBinary(b []byte) error { + var res OIDCOrganizationSettings + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/client/models/on_failure_plan.go b/gen/models/on_failure_plan.go similarity index 96% rename from client/models/on_failure_plan.go rename to gen/models/on_failure_plan.go index 6a36449f2..08c973111 100644 --- a/client/models/on_failure_plan.go +++ b/gen/models/on_failure_plan.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/on_success_plan.go b/gen/models/on_success_plan.go similarity index 96% rename from client/models/on_success_plan.go rename to gen/models/on_success_plan.go index 2795ca7eb..f17d6830b 100644 --- a/client/models/on_success_plan.go +++ b/gen/models/on_success_plan.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/organization.go b/gen/models/organization.go similarity index 86% rename from client/models/organization.go rename to gen/models/organization.go index b012ce560..842798de4 100644 --- a/client/models/organization.go +++ b/gen/models/organization.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" @@ -105,6 +108,14 @@ type Organization struct { // When true, SSO users can only join the organization if they have been explicitly invited SsoInviteOnly *bool `json:"sso_invite_only,omitempty"` + // Glob patterns (filepath.Match syntax). Versions matching any of these are hidden from non-team-member users. + // Max Items: 50 + StackBranchExcludePatterns []string `json:"stack_branch_exclude_patterns"` + + // Glob patterns (filepath.Match syntax). When set, only versions whose name matches at least one pattern are shown to non-team-member users. Empty means show all. + // Max Items: 50 + StackBranchIncludePatterns []string `json:"stack_branch_include_patterns"` + // subscription Subscription *Subscription `json:"subscription,omitempty"` @@ -194,6 +205,14 @@ func (m *Organization) Validate(formats strfmt.Registry) error { res = append(res, err) } + if err := m.validateStackBranchExcludePatterns(formats); err != nil { + res = append(res, err) + } + + if err := m.validateStackBranchIncludePatterns(formats); err != nil { + res = append(res, err) + } + if err := m.validateSubscription(formats); err != nil { res = append(res, err) } @@ -449,6 +468,50 @@ func (m *Organization) validateParentCanonical(formats strfmt.Registry) error { return nil } +func (m *Organization) validateStackBranchExcludePatterns(formats strfmt.Registry) error { + if swag.IsZero(m.StackBranchExcludePatterns) { // not required + return nil + } + + iStackBranchExcludePatternsSize := int64(len(m.StackBranchExcludePatterns)) + + if err := validate.MaxItems("stack_branch_exclude_patterns", "body", iStackBranchExcludePatternsSize, 50); err != nil { + return err + } + + for i := 0; i < len(m.StackBranchExcludePatterns); i++ { + + if err := validate.MaxLength("stack_branch_exclude_patterns"+"."+strconv.Itoa(i), "body", m.StackBranchExcludePatterns[i], 200); err != nil { + return err + } + + } + + return nil +} + +func (m *Organization) validateStackBranchIncludePatterns(formats strfmt.Registry) error { + if swag.IsZero(m.StackBranchIncludePatterns) { // not required + return nil + } + + iStackBranchIncludePatternsSize := int64(len(m.StackBranchIncludePatterns)) + + if err := validate.MaxItems("stack_branch_include_patterns", "body", iStackBranchIncludePatternsSize, 50); err != nil { + return err + } + + for i := 0; i < len(m.StackBranchIncludePatterns); i++ { + + if err := validate.MaxLength("stack_branch_include_patterns"+"."+strconv.Itoa(i), "body", m.StackBranchIncludePatterns[i], 200); err != nil { + return err + } + + } + + return nil +} + func (m *Organization) validateSubscription(formats strfmt.Registry) error { if swag.IsZero(m.Subscription) { // not required return nil diff --git a/client/models/organization_messages.go b/gen/models/organization_messages.go similarity index 89% rename from client/models/organization_messages.go rename to gen/models/organization_messages.go index 6daaf769a..913f939e1 100644 --- a/client/models/organization_messages.go +++ b/gen/models/organization_messages.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/organization_naming_rules.go b/gen/models/organization_naming_rules.go similarity index 96% rename from client/models/organization_naming_rules.go rename to gen/models/organization_naming_rules.go index 00c883678..f22c9427d 100644 --- a/client/models/organization_naming_rules.go +++ b/gen/models/organization_naming_rules.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/page_concourse.go b/gen/models/page_concourse.go similarity index 94% rename from client/models/page_concourse.go rename to gen/models/page_concourse.go index fecddfb67..d1737cc05 100644 --- a/client/models/page_concourse.go +++ b/gen/models/page_concourse.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/pagination.go b/gen/models/pagination.go similarity index 94% rename from client/models/pagination.go rename to gen/models/pagination.go index ebe791b24..530ea98b1 100644 --- a/client/models/pagination.go +++ b/gen/models/pagination.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/pagination_a_w_s.go b/gen/models/pagination_a_w_s.go similarity index 91% rename from client/models/pagination_a_w_s.go rename to gen/models/pagination_a_w_s.go index efa9f94b5..07c2fe59f 100644 --- a/client/models/pagination_a_w_s.go +++ b/gen/models/pagination_a_w_s.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/pagination_concourse.go b/gen/models/pagination_concourse.go similarity index 96% rename from client/models/pagination_concourse.go rename to gen/models/pagination_concourse.go index 57d861654..7a9035012 100644 --- a/client/models/pagination_concourse.go +++ b/gen/models/pagination_concourse.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/pending_member_invitation.go b/gen/models/pending_member_invitation.go similarity index 92% rename from client/models/pending_member_invitation.go rename to gen/models/pending_member_invitation.go index 52f9e4916..2989f1c22 100644 --- a/client/models/pending_member_invitation.go +++ b/gen/models/pending_member_invitation.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/pin_comment.go b/gen/models/pin_comment.go similarity index 91% rename from client/models/pin_comment.go rename to gen/models/pin_comment.go index d3dfe06cc..cbd37df84 100644 --- a/client/models/pin_comment.go +++ b/gen/models/pin_comment.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/pipeline.go b/gen/models/pipeline.go similarity index 98% rename from client/models/pipeline.go rename to gen/models/pipeline.go index ee9a92619..e12b07926 100644 --- a/client/models/pipeline.go +++ b/gen/models/pipeline.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/pipeline_diff.go b/gen/models/pipeline_diff.go similarity index 97% rename from client/models/pipeline_diff.go rename to gen/models/pipeline_diff.go index 7e94be464..737e4e6e5 100644 --- a/client/models/pipeline_diff.go +++ b/gen/models/pipeline_diff.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" "encoding/json" diff --git a/client/models/pipeline_diff_record.go b/gen/models/pipeline_diff_record.go similarity index 93% rename from client/models/pipeline_diff_record.go rename to gen/models/pipeline_diff_record.go index 63f292efb..d19351158 100644 --- a/client/models/pipeline_diff_record.go +++ b/gen/models/pipeline_diff_record.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/pipeline_diffs.go b/gen/models/pipeline_diffs.go similarity index 98% rename from client/models/pipeline_diffs.go rename to gen/models/pipeline_diffs.go index a0115e55c..35a4c638d 100644 --- a/client/models/pipeline_diffs.go +++ b/gen/models/pipeline_diffs.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/pipeline_status.go b/gen/models/pipeline_status.go similarity index 97% rename from client/models/pipeline_status.go rename to gen/models/pipeline_status.go index 2d57e1194..5a56c7744 100644 --- a/client/models/pipeline_status.go +++ b/gen/models/pipeline_status.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" "encoding/json" diff --git a/client/models/pipeline_variables.go b/gen/models/pipeline_variables.go similarity index 94% rename from client/models/pipeline_variables.go rename to gen/models/pipeline_variables.go index e4a1733e6..379789360 100644 --- a/client/models/pipeline_variables.go +++ b/gen/models/pipeline_variables.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/plan.go b/gen/models/plan.go similarity index 99% rename from client/models/plan.go rename to gen/models/plan.go index c5c5b7097..ffd1c6ad7 100644 --- a/client/models/plan.go +++ b/gen/models/plan.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/plan_config.go b/gen/models/plan_config.go similarity index 97% rename from client/models/plan_config.go rename to gen/models/plan_config.go index 0b3444400..debe182a1 100644 --- a/client/models/plan_config.go +++ b/gen/models/plan_config.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/plugin.go b/gen/models/plugin.go similarity index 98% rename from client/models/plugin.go rename to gen/models/plugin.go index eb13692f7..f79924a05 100644 --- a/client/models/plugin.go +++ b/gen/models/plugin.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/plugin_install.go b/gen/models/plugin_install.go similarity index 78% rename from client/models/plugin_install.go rename to gen/models/plugin_install.go index 89d7f7aff..9af6eda82 100644 --- a/client/models/plugin_install.go +++ b/gen/models/plugin_install.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" "encoding/json" @@ -34,10 +37,19 @@ type PluginInstall struct { // Minimum: 1 ID *uint32 `json:"id"` + // True when the install comes from an ancestor organization + Inherited bool `json:"inherited,omitempty"` + + // The canonical of the organization that owns the install + OwnerOrganizationCanonical string `json:"owner_organization_canonical,omitempty"` + // Secret used by the frontend to generate webhooks for the Plugin // Required: true PmSecret *string `json:"pm_secret"` + // True when the install is accessed from a non-owning organization + ReadOnly bool `json:"read_only,omitempty"` + // Status of the Plugin deployment process on Plugin Manager // Required: true // Enum: ["pending","running","failed"] @@ -55,6 +67,10 @@ type PluginInstall struct { // version Version *PluginVersion `json:"version,omitempty"` + + // Whether the plugin install is visible only locally or shared with child organizations + // Enum: ["local","shared"] + Visibility *string `json:"visibility,omitempty"` } // Validate validates this plugin install @@ -93,6 +109,10 @@ func (m *PluginInstall) Validate(formats strfmt.Registry) error { res = append(res, err) } + if err := m.validateVisibility(formats); err != nil { + res = append(res, err) + } + if len(res) > 0 { return errors.CompositeValidationError(res...) } @@ -238,6 +258,48 @@ func (m *PluginInstall) validateVersion(formats strfmt.Registry) error { return nil } +var pluginInstallTypeVisibilityPropEnum []any + +func init() { + var res []string + if err := json.Unmarshal([]byte(`["local","shared"]`), &res); err != nil { + panic(err) + } + for _, v := range res { + pluginInstallTypeVisibilityPropEnum = append(pluginInstallTypeVisibilityPropEnum, v) + } +} + +const ( + + // PluginInstallVisibilityLocal captures enum value "local" + PluginInstallVisibilityLocal string = "local" + + // PluginInstallVisibilityShared captures enum value "shared" + PluginInstallVisibilityShared string = "shared" +) + +// prop value enum +func (m *PluginInstall) validateVisibilityEnum(path, location string, value string) error { + if err := validate.EnumCase(path, location, value, pluginInstallTypeVisibilityPropEnum, true); err != nil { + return err + } + return nil +} + +func (m *PluginInstall) validateVisibility(formats strfmt.Registry) error { + if swag.IsZero(m.Visibility) { // not required + return nil + } + + // value enum + if err := m.validateVisibilityEnum("visibility", "body", *m.Visibility); err != nil { + return err + } + + return nil +} + // ContextValidate validate this plugin install based on the context it is used func (m *PluginInstall) ContextValidate(ctx context.Context, formats strfmt.Registry) error { var res []error diff --git a/client/models/plugin_install_deployment_log.go b/gen/models/plugin_install_deployment_log.go similarity index 94% rename from client/models/plugin_install_deployment_log.go rename to gen/models/plugin_install_deployment_log.go index 4f394036e..5601838a5 100644 --- a/client/models/plugin_install_deployment_log.go +++ b/gen/models/plugin_install_deployment_log.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/plugin_install_runtime_log.go b/gen/models/plugin_install_runtime_log.go similarity index 95% rename from client/models/plugin_install_runtime_log.go rename to gen/models/plugin_install_runtime_log.go index f6766273e..7d502c123 100644 --- a/client/models/plugin_install_runtime_log.go +++ b/gen/models/plugin_install_runtime_log.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/gen/models/plugin_install_sharing.go b/gen/models/plugin_install_sharing.go new file mode 100644 index 000000000..f26218692 --- /dev/null +++ b/gen/models/plugin_install_sharing.go @@ -0,0 +1,162 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + "encoding/json" + + "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" + "github.com/go-openapi/validate" +) + +// PluginInstallSharing Plugin Install Sharing +// +// # The sharing configuration for a Plugin Install +// +// swagger:model PluginInstallSharing +type PluginInstallSharing struct { + + // How the sharing list is interpreted + // Enum: ["include","exclude"] + Mode *string `json:"mode,omitempty"` + + // List of child organization canonicals in the sharing list + Organizations []string `json:"organizations"` + + // Whether the plugin install is visible only locally or shared with child organizations + // Required: true + // Enum: ["local","shared"] + Visibility *string `json:"visibility"` +} + +// Validate validates this plugin install sharing +func (m *PluginInstallSharing) Validate(formats strfmt.Registry) error { + var res []error + + if err := m.validateMode(formats); err != nil { + res = append(res, err) + } + + if err := m.validateVisibility(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +var pluginInstallSharingTypeModePropEnum []any + +func init() { + var res []string + if err := json.Unmarshal([]byte(`["include","exclude"]`), &res); err != nil { + panic(err) + } + for _, v := range res { + pluginInstallSharingTypeModePropEnum = append(pluginInstallSharingTypeModePropEnum, v) + } +} + +const ( + + // PluginInstallSharingModeInclude captures enum value "include" + PluginInstallSharingModeInclude string = "include" + + // PluginInstallSharingModeExclude captures enum value "exclude" + PluginInstallSharingModeExclude string = "exclude" +) + +// prop value enum +func (m *PluginInstallSharing) validateModeEnum(path, location string, value string) error { + if err := validate.EnumCase(path, location, value, pluginInstallSharingTypeModePropEnum, true); err != nil { + return err + } + return nil +} + +func (m *PluginInstallSharing) validateMode(formats strfmt.Registry) error { + if swag.IsZero(m.Mode) { // not required + return nil + } + + // value enum + if err := m.validateModeEnum("mode", "body", *m.Mode); err != nil { + return err + } + + return nil +} + +var pluginInstallSharingTypeVisibilityPropEnum []any + +func init() { + var res []string + if err := json.Unmarshal([]byte(`["local","shared"]`), &res); err != nil { + panic(err) + } + for _, v := range res { + pluginInstallSharingTypeVisibilityPropEnum = append(pluginInstallSharingTypeVisibilityPropEnum, v) + } +} + +const ( + + // PluginInstallSharingVisibilityLocal captures enum value "local" + PluginInstallSharingVisibilityLocal string = "local" + + // PluginInstallSharingVisibilityShared captures enum value "shared" + PluginInstallSharingVisibilityShared string = "shared" +) + +// prop value enum +func (m *PluginInstallSharing) validateVisibilityEnum(path, location string, value string) error { + if err := validate.EnumCase(path, location, value, pluginInstallSharingTypeVisibilityPropEnum, true); err != nil { + return err + } + return nil +} + +func (m *PluginInstallSharing) validateVisibility(formats strfmt.Registry) error { + + if err := validate.Required("visibility", "body", m.Visibility); err != nil { + return err + } + + // value enum + if err := m.validateVisibilityEnum("visibility", "body", *m.Visibility); err != nil { + return err + } + + return nil +} + +// ContextValidate validates this plugin install sharing based on context it is used +func (m *PluginInstallSharing) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (m *PluginInstallSharing) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *PluginInstallSharing) UnmarshalBinary(b []byte) error { + var res PluginInstallSharing + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/client/models/plugin_logs.go b/gen/models/plugin_logs.go similarity index 97% rename from client/models/plugin_logs.go rename to gen/models/plugin_logs.go index 037dfd016..435212b5b 100644 --- a/client/models/plugin_logs.go +++ b/gen/models/plugin_logs.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/plugin_manager.go b/gen/models/plugin_manager.go similarity index 97% rename from client/models/plugin_manager.go rename to gen/models/plugin_manager.go index ecde75da6..1b851bdbc 100644 --- a/client/models/plugin_manager.go +++ b/gen/models/plugin_manager.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" "encoding/json" diff --git a/client/models/plugin_registry.go b/gen/models/plugin_registry.go similarity index 97% rename from client/models/plugin_registry.go rename to gen/models/plugin_registry.go index 4a6a3354b..f8e4bdfe4 100644 --- a/client/models/plugin_registry.go +++ b/gen/models/plugin_registry.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" "encoding/json" diff --git a/client/models/plugin_relation.go b/gen/models/plugin_relation.go similarity index 93% rename from client/models/plugin_relation.go rename to gen/models/plugin_relation.go index 551ad60c7..a9897f421 100644 --- a/client/models/plugin_relation.go +++ b/gen/models/plugin_relation.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/plugin_version.go b/gen/models/plugin_version.go similarity index 97% rename from client/models/plugin_version.go rename to gen/models/plugin_version.go index b4b5dedad..8a7e038f3 100644 --- a/client/models/plugin_version.go +++ b/gen/models/plugin_version.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" "encoding/json" diff --git a/client/models/plugin_version_log.go b/gen/models/plugin_version_log.go similarity index 93% rename from client/models/plugin_version_log.go rename to gen/models/plugin_version_log.go index 8c4b0791c..66156f8e3 100644 --- a/client/models/plugin_version_log.go +++ b/gen/models/plugin_version_log.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/plugin_widget.go b/gen/models/plugin_widget.go similarity index 64% rename from client/models/plugin_widget.go rename to gen/models/plugin_widget.go index 74a2d9252..90eb9142a 100644 --- a/client/models/plugin_widget.go +++ b/gen/models/plugin_widget.go @@ -2,8 +2,12 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" + stderrors "errors" "github.com/go-openapi/errors" "github.com/go-openapi/strfmt" @@ -30,6 +34,9 @@ type PluginWidget struct { // Required: true Placement any `json:"placement"` + // relation + Relation *PluginRelation `json:"relation,omitempty"` + // Type of the widget // Required: true Type *string `json:"type"` @@ -55,6 +62,10 @@ func (m *PluginWidget) Validate(formats strfmt.Registry) error { res = append(res, err) } + if err := m.validateRelation(formats); err != nil { + res = append(res, err) + } + if err := m.validateType(formats); err != nil { res = append(res, err) } @@ -99,6 +110,29 @@ func (m *PluginWidget) validatePlacement(formats strfmt.Registry) error { return nil } +func (m *PluginWidget) validateRelation(formats strfmt.Registry) error { + if swag.IsZero(m.Relation) { // not required + return nil + } + + if m.Relation != nil { + if err := m.Relation.Validate(formats); err != nil { + ve := new(errors.Validation) + if stderrors.As(err, &ve) { + return ve.ValidateName("relation") + } + ce := new(errors.CompositeError) + if stderrors.As(err, &ce) { + return ce.ValidateName("relation") + } + + return err + } + } + + return nil +} + func (m *PluginWidget) validateType(formats strfmt.Registry) error { if err := validate.Required("type", "body", m.Type); err != nil { @@ -117,8 +151,42 @@ func (m *PluginWidget) validateWidget(formats strfmt.Registry) error { return nil } -// ContextValidate validates this plugin widget based on context it is used +// ContextValidate validate this plugin widget based on the context it is used func (m *PluginWidget) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + var res []error + + if err := m.contextValidateRelation(ctx, formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *PluginWidget) contextValidateRelation(ctx context.Context, formats strfmt.Registry) error { + + if m.Relation != nil { + + if swag.IsZero(m.Relation) { // not required + return nil + } + + if err := m.Relation.ContextValidate(ctx, formats); err != nil { + ve := new(errors.Validation) + if stderrors.As(err, &ve) { + return ve.ValidateName("relation") + } + ce := new(errors.CompositeError) + if stderrors.As(err, &ce) { + return ce.ValidateName("relation") + } + + return err + } + } + return nil } diff --git a/client/models/plugin_widget_data.go b/gen/models/plugin_widget_data.go similarity index 91% rename from client/models/plugin_widget_data.go rename to gen/models/plugin_widget_data.go index 3da79e885..d4d2c4f08 100644 --- a/client/models/plugin_widget_data.go +++ b/gen/models/plugin_widget_data.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/policy.go b/gen/models/policy.go similarity index 96% rename from client/models/policy.go rename to gen/models/policy.go index 1cc80979d..9091d275d 100644 --- a/client/models/policy.go +++ b/gen/models/policy.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/preparation.go b/gen/models/preparation.go similarity index 96% rename from client/models/preparation.go rename to gen/models/preparation.go index b8409c8a3..cbefcf622 100644 --- a/client/models/preparation.go +++ b/gen/models/preparation.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/project.go b/gen/models/project.go similarity index 98% rename from client/models/project.go rename to gen/models/project.go index a66aa040c..ad2bf7f9e 100644 --- a/client/models/project.go +++ b/gen/models/project.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" "encoding/json" diff --git a/client/models/project_environment.go b/gen/models/project_environment.go similarity index 98% rename from client/models/project_environment.go rename to gen/models/project_environment.go index 5f7e00e92..065bff8c6 100644 --- a/client/models/project_environment.go +++ b/gen/models/project_environment.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" "encoding/json" diff --git a/client/models/project_simple.go b/gen/models/project_simple.go similarity index 97% rename from client/models/project_simple.go rename to gen/models/project_simple.go index 4ee4334e4..3137b9bdc 100644 --- a/client/models/project_simple.go +++ b/gen/models/project_simple.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/public_build_input.go b/gen/models/public_build_input.go similarity index 95% rename from client/models/public_build_input.go rename to gen/models/public_build_input.go index d768f9b79..41cb045db 100644 --- a/client/models/public_build_input.go +++ b/gen/models/public_build_input.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/public_build_output.go b/gen/models/public_build_output.go similarity index 93% rename from client/models/public_build_output.go rename to gen/models/public_build_output.go index a2aadf924..c89dae82e 100644 --- a/client/models/public_build_output.go +++ b/gen/models/public_build_output.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/public_plan.go b/gen/models/public_plan.go similarity index 92% rename from client/models/public_plan.go rename to gen/models/public_plan.go index 55bdbf483..8d2e10f22 100644 --- a/client/models/public_plan.go +++ b/gen/models/public_plan.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/put_plan.go b/gen/models/put_plan.go similarity index 96% rename from client/models/put_plan.go rename to gen/models/put_plan.go index cf9cc0779..4ca30a84b 100644 --- a/client/models/put_plan.go +++ b/gen/models/put_plan.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/resource.go b/gen/models/resource.go similarity index 96% rename from client/models/resource.go rename to gen/models/resource.go index 11efdee70..ab97447f1 100644 --- a/client/models/resource.go +++ b/gen/models/resource.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/resource_version.go b/gen/models/resource_version.go similarity index 96% rename from client/models/resource_version.go rename to gen/models/resource_version.go index 2a89fb73d..94fb001e1 100644 --- a/client/models/resource_version.go +++ b/gen/models/resource_version.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/role.go b/gen/models/role.go similarity index 97% rename from client/models/role.go rename to gen/models/role.go index c1123904e..958ffa098 100644 --- a/client/models/role.go +++ b/gen/models/role.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/rule.go b/gen/models/rule.go similarity index 96% rename from client/models/rule.go rename to gen/models/rule.go index 8779d9313..147f354df 100644 --- a/client/models/rule.go +++ b/gen/models/rule.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" "encoding/json" diff --git a/client/models/s_c_config.go b/gen/models/s_c_config.go similarity index 95% rename from client/models/s_c_config.go rename to gen/models/s_c_config.go index 2999c1380..eaf423ad3 100644 --- a/client/models/s_c_config.go +++ b/gen/models/s_c_config.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/s_c_config_custom_config.go b/gen/models/s_c_config_custom_config.go similarity index 96% rename from client/models/s_c_config_custom_config.go rename to gen/models/s_c_config_custom_config.go index 8503f8ef0..3f3da8f01 100644 --- a/client/models/s_c_config_custom_config.go +++ b/gen/models/s_c_config_custom_config.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/s_c_config_form_data.go b/gen/models/s_c_config_form_data.go similarity index 94% rename from client/models/s_c_config_form_data.go rename to gen/models/s_c_config_form_data.go index bfe2f0837..8fb132f6f 100644 --- a/client/models/s_c_config_form_data.go +++ b/gen/models/s_c_config_form_data.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/s_c_config_path_config.go b/gen/models/s_c_config_path_config.go similarity index 93% rename from client/models/s_c_config_path_config.go rename to gen/models/s_c_config_path_config.go index b5ab2ba03..658c3c430 100644 --- a/client/models/s_c_config_path_config.go +++ b/gen/models/s_c_config_path_config.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/s_c_config_path_dest_config.go b/gen/models/s_c_config_path_dest_config.go similarity index 94% rename from client/models/s_c_config_path_dest_config.go rename to gen/models/s_c_config_path_dest_config.go index 49bdee975..f3727eab4 100644 --- a/client/models/s_c_config_path_dest_config.go +++ b/gen/models/s_c_config_path_dest_config.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/s_c_config_pipeline_config.go b/gen/models/s_c_config_pipeline_config.go similarity index 96% rename from client/models/s_c_config_pipeline_config.go rename to gen/models/s_c_config_pipeline_config.go index f15c2e7db..55cab226b 100644 --- a/client/models/s_c_config_pipeline_config.go +++ b/gen/models/s_c_config_pipeline_config.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/s_c_config_tech_config.go b/gen/models/s_c_config_tech_config.go similarity index 91% rename from client/models/s_c_config_tech_config.go rename to gen/models/s_c_config_tech_config.go index ef819a5cf..37be488b4 100644 --- a/client/models/s_c_config_tech_config.go +++ b/gen/models/s_c_config_tech_config.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/s_c_optional_template_config.go b/gen/models/s_c_optional_template_config.go similarity index 91% rename from client/models/s_c_optional_template_config.go rename to gen/models/s_c_optional_template_config.go index 6b0c146fc..9fb9f924c 100644 --- a/client/models/s_c_optional_template_config.go +++ b/gen/models/s_c_optional_template_config.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/s_c_template_config.go b/gen/models/s_c_template_config.go similarity index 96% rename from client/models/s_c_template_config.go rename to gen/models/s_c_template_config.go index b220b4f81..30253e6b4 100644 --- a/client/models/s_c_template_config.go +++ b/gen/models/s_c_template_config.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/service_catalog.go b/gen/models/service_catalog.go similarity index 91% rename from client/models/service_catalog.go rename to gen/models/service_catalog.go index 0f657a684..ebe3011ca 100644 --- a/client/models/service_catalog.go +++ b/gen/models/service_catalog.go @@ -2,9 +2,11 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" - "encoding/json" stderrors "errors" "strconv" @@ -68,10 +70,6 @@ type ServiceCatalog struct { // Format: uri Image strfmt.URI `json:"image,omitempty"` - // The import process status. - // Enum: ["succeeded","failed","importing"] - ImportStatus string `json:"import_status,omitempty"` - // keywords // Required: true Keywords []string `json:"keywords"` @@ -167,10 +165,6 @@ func (m *ServiceCatalog) Validate(formats strfmt.Registry) error { res = append(res, err) } - if err := m.validateImportStatus(formats); err != nil { - res = append(res, err) - } - if err := m.validateKeywords(formats); err != nil { res = append(res, err) } @@ -370,51 +364,6 @@ func (m *ServiceCatalog) validateImage(formats strfmt.Registry) error { return nil } -var serviceCatalogTypeImportStatusPropEnum []any - -func init() { - var res []string - if err := json.Unmarshal([]byte(`["succeeded","failed","importing"]`), &res); err != nil { - panic(err) - } - for _, v := range res { - serviceCatalogTypeImportStatusPropEnum = append(serviceCatalogTypeImportStatusPropEnum, v) - } -} - -const ( - - // ServiceCatalogImportStatusSucceeded captures enum value "succeeded" - ServiceCatalogImportStatusSucceeded string = "succeeded" - - // ServiceCatalogImportStatusFailed captures enum value "failed" - ServiceCatalogImportStatusFailed string = "failed" - - // ServiceCatalogImportStatusImporting captures enum value "importing" - ServiceCatalogImportStatusImporting string = "importing" -) - -// prop value enum -func (m *ServiceCatalog) validateImportStatusEnum(path, location string, value string) error { - if err := validate.EnumCase(path, location, value, serviceCatalogTypeImportStatusPropEnum, true); err != nil { - return err - } - return nil -} - -func (m *ServiceCatalog) validateImportStatus(formats strfmt.Registry) error { - if swag.IsZero(m.ImportStatus) { // not required - return nil - } - - // value enum - if err := m.validateImportStatusEnum("import_status", "body", m.ImportStatus); err != nil { - return err - } - - return nil -} - func (m *ServiceCatalog) validateKeywords(formats strfmt.Registry) error { if err := validate.Required("keywords", "body", m.Keywords); err != nil { diff --git a/client/models/service_catalog_changes.go b/gen/models/service_catalog_changes.go similarity index 98% rename from client/models/service_catalog_changes.go rename to gen/models/service_catalog_changes.go index 859309e78..c6fc3f4e2 100644 --- a/client/models/service_catalog_changes.go +++ b/gen/models/service_catalog_changes.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/service_catalog_config.go b/gen/models/service_catalog_config.go similarity index 98% rename from client/models/service_catalog_config.go rename to gen/models/service_catalog_config.go index 59e5fd300..88226a09e 100644 --- a/client/models/service_catalog_config.go +++ b/gen/models/service_catalog_config.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/service_catalog_configs.go b/gen/models/service_catalog_configs.go similarity index 91% rename from client/models/service_catalog_configs.go rename to gen/models/service_catalog_configs.go index f62733e2b..3ead2ab50 100644 --- a/client/models/service_catalog_configs.go +++ b/gen/models/service_catalog_configs.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/service_catalog_dependencies_validation_result.go b/gen/models/service_catalog_dependencies_validation_result.go similarity index 94% rename from client/models/service_catalog_dependencies_validation_result.go rename to gen/models/service_catalog_dependencies_validation_result.go index f9a9dc0da..5f14c3ea3 100644 --- a/client/models/service_catalog_dependencies_validation_result.go +++ b/gen/models/service_catalog_dependencies_validation_result.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/service_catalog_dependency.go b/gen/models/service_catalog_dependency.go similarity index 90% rename from client/models/service_catalog_dependency.go rename to gen/models/service_catalog_dependency.go index ac47d70bf..845db473d 100644 --- a/client/models/service_catalog_dependency.go +++ b/gen/models/service_catalog_dependency.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/service_catalog_source.go b/gen/models/service_catalog_source.go similarity index 98% rename from client/models/service_catalog_source.go rename to gen/models/service_catalog_source.go index ec5b59cdf..508adb9e0 100644 --- a/client/models/service_catalog_source.go +++ b/gen/models/service_catalog_source.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/service_catalog_source_version.go b/gen/models/service_catalog_source_version.go similarity index 97% rename from client/models/service_catalog_source_version.go rename to gen/models/service_catalog_source_version.go index 5b653fcb4..62e6d5066 100644 --- a/client/models/service_catalog_source_version.go +++ b/gen/models/service_catalog_source_version.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" "encoding/json" diff --git a/client/models/service_catalog_technology.go b/gen/models/service_catalog_technology.go similarity index 90% rename from client/models/service_catalog_technology.go rename to gen/models/service_catalog_technology.go index 7baf8d85b..94f3e12f3 100644 --- a/client/models/service_catalog_technology.go +++ b/gen/models/service_catalog_technology.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/simple_member_org.go b/gen/models/simple_member_org.go similarity index 97% rename from client/models/simple_member_org.go rename to gen/models/simple_member_org.go index b42d24a39..02377a3c6 100644 --- a/client/models/simple_member_org.go +++ b/gen/models/simple_member_org.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/simple_team.go b/gen/models/simple_team.go similarity index 97% rename from client/models/simple_team.go rename to gen/models/simple_team.go index 3bd4be599..dc65b1f40 100644 --- a/client/models/simple_team.go +++ b/gen/models/simple_team.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/stack_use_case.go b/gen/models/stack_use_case.go similarity index 95% rename from client/models/stack_use_case.go rename to gen/models/stack_use_case.go index 8fdcb13ce..10eae6970 100644 --- a/client/models/stack_use_case.go +++ b/gen/models/stack_use_case.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/state.go b/gen/models/state.go similarity index 95% rename from client/models/state.go rename to gen/models/state.go index 753c4d038..1d0e135ec 100644 --- a/client/models/state.go +++ b/gen/models/state.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/state_lock.go b/gen/models/state_lock.go similarity index 90% rename from client/models/state_lock.go rename to gen/models/state_lock.go index 6ef835867..bb4e6b357 100644 --- a/client/models/state_lock.go +++ b/gen/models/state_lock.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/state_resource.go b/gen/models/state_resource.go similarity index 96% rename from client/models/state_resource.go rename to gen/models/state_resource.go index b4cdc3e32..255d43e5c 100644 --- a/client/models/state_resource.go +++ b/gen/models/state_resource.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/state_resource_instances.go b/gen/models/state_resource_instances.go similarity index 90% rename from client/models/state_resource_instances.go rename to gen/models/state_resource_instances.go index b5d092b72..8d2a6e3dc 100644 --- a/client/models/state_resource_instances.go +++ b/gen/models/state_resource_instances.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/subscription.go b/gen/models/subscription.go similarity index 96% rename from client/models/subscription.go rename to gen/models/subscription.go index 0cece71b3..219d93b4d 100644 --- a/client/models/subscription.go +++ b/gen/models/subscription.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/subscription_plan.go b/gen/models/subscription_plan.go similarity index 94% rename from client/models/subscription_plan.go rename to gen/models/subscription_plan.go index 3c7f1ae52..c0e56fbcc 100644 --- a/client/models/subscription_plan.go +++ b/gen/models/subscription_plan.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/summary.go b/gen/models/summary.go similarity index 96% rename from client/models/summary.go rename to gen/models/summary.go index a4e3802a7..404d4c475 100644 --- a/client/models/summary.go +++ b/gen/models/summary.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/swift_remote_t_f_state.go b/gen/models/swift_remote_t_f_state.go similarity index 97% rename from client/models/swift_remote_t_f_state.go rename to gen/models/swift_remote_t_f_state.go index 6ca801985..6048057fa 100644 --- a/client/models/swift_remote_t_f_state.go +++ b/gen/models/swift_remote_t_f_state.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "bytes" "context" diff --git a/client/models/swift_storage.go b/gen/models/swift_storage.go similarity index 97% rename from client/models/swift_storage.go rename to gen/models/swift_storage.go index 1f4122fd4..241692ff1 100644 --- a/client/models/swift_storage.go +++ b/gen/models/swift_storage.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "bytes" "context" diff --git a/client/models/tag.go b/gen/models/tag.go similarity index 94% rename from client/models/tag.go rename to gen/models/tag.go index 00a9f2096..961f2cdde 100644 --- a/client/models/tag.go +++ b/gen/models/tag.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/task_config.go b/gen/models/task_config.go similarity index 96% rename from client/models/task_config.go rename to gen/models/task_config.go index e8ea85894..d8a711737 100644 --- a/client/models/task_config.go +++ b/gen/models/task_config.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/task_input_config.go b/gen/models/task_input_config.go similarity index 91% rename from client/models/task_input_config.go rename to gen/models/task_input_config.go index 2786ff5fd..e7792ead0 100644 --- a/client/models/task_input_config.go +++ b/gen/models/task_input_config.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/task_plan.go b/gen/models/task_plan.go similarity index 97% rename from client/models/task_plan.go rename to gen/models/task_plan.go index cbf664b8e..7e3dcedcb 100644 --- a/client/models/task_plan.go +++ b/gen/models/task_plan.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/task_run_config.go b/gen/models/task_run_config.go similarity index 92% rename from client/models/task_run_config.go rename to gen/models/task_run_config.go index 25da74fb7..5525bdc71 100644 --- a/client/models/task_run_config.go +++ b/gen/models/task_run_config.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/team.go b/gen/models/team.go similarity index 98% rename from client/models/team.go rename to gen/models/team.go index 1b2144521..2231d99d7 100644 --- a/client/models/team.go +++ b/gen/models/team.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/terraform_h_c_l_config.go b/gen/models/terraform_h_c_l_config.go similarity index 91% rename from client/models/terraform_h_c_l_config.go rename to gen/models/terraform_h_c_l_config.go index 1fd9c0062..3c172667e 100644 --- a/client/models/terraform_h_c_l_config.go +++ b/gen/models/terraform_h_c_l_config.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/terraform_image.go b/gen/models/terraform_image.go similarity index 91% rename from client/models/terraform_image.go rename to gen/models/terraform_image.go index 8bea3cc14..084d578e4 100644 --- a/client/models/terraform_image.go +++ b/gen/models/terraform_image.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/terraform_json_config.go b/gen/models/terraform_json_config.go similarity index 91% rename from client/models/terraform_json_config.go rename to gen/models/terraform_json_config.go index c581f6ef4..956ee274d 100644 --- a/client/models/terraform_json_config.go +++ b/gen/models/terraform_json_config.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/terraform_json_diagram.go b/gen/models/terraform_json_diagram.go similarity index 61% rename from client/models/terraform_json_diagram.go rename to gen/models/terraform_json_diagram.go index 6bfafcea2..c4ee5fccf 100644 --- a/client/models/terraform_json_diagram.go +++ b/gen/models/terraform_json_diagram.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + // TerraformJSONDiagram TerraformDiagram // // # The JSON Diagram structure diff --git a/client/models/terraform_plan_input.go b/gen/models/terraform_plan_input.go similarity index 92% rename from client/models/terraform_plan_input.go rename to gen/models/terraform_plan_input.go index 6f7139ea0..4c7ac0a5b 100644 --- a/client/models/terraform_plan_input.go +++ b/gen/models/terraform_plan_input.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/terraform_provider.go b/gen/models/terraform_provider.go similarity index 95% rename from client/models/terraform_provider.go rename to gen/models/terraform_provider.go index f0905035d..d1507688b 100644 --- a/client/models/terraform_provider.go +++ b/gen/models/terraform_provider.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/terraform_provider_resource.go b/gen/models/terraform_provider_resource.go similarity index 97% rename from client/models/terraform_provider_resource.go rename to gen/models/terraform_provider_resource.go index a40f3e765..5942d3c7f 100644 --- a/client/models/terraform_provider_resource.go +++ b/gen/models/terraform_provider_resource.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/terraform_provider_resource_attributes.go b/gen/models/terraform_provider_resource_attributes.go similarity index 92% rename from client/models/terraform_provider_resource_attributes.go rename to gen/models/terraform_provider_resource_attributes.go index c9c3a84db..8b5aacab6 100644 --- a/client/models/terraform_provider_resource_attributes.go +++ b/gen/models/terraform_provider_resource_attributes.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/terraform_provider_resource_simple.go b/gen/models/terraform_provider_resource_simple.go similarity index 97% rename from client/models/terraform_provider_resource_simple.go rename to gen/models/terraform_provider_resource_simple.go index b97a67b4d..b6505f3ed 100644 --- a/client/models/terraform_provider_resource_simple.go +++ b/gen/models/terraform_provider_resource_simple.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/terraform_provider_simple.go b/gen/models/terraform_provider_simple.go similarity index 95% rename from client/models/terraform_provider_simple.go rename to gen/models/terraform_provider_simple.go index 992a74b15..854b8cf5a 100644 --- a/client/models/terraform_provider_simple.go +++ b/gen/models/terraform_provider_simple.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/terraform_validation_result.go b/gen/models/terraform_validation_result.go similarity index 92% rename from client/models/terraform_validation_result.go rename to gen/models/terraform_validation_result.go index cb895aa4d..7a0a4b104 100644 --- a/client/models/terraform_validation_result.go +++ b/gen/models/terraform_validation_result.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/test_connection_credential.go b/gen/models/test_connection_credential.go similarity index 97% rename from client/models/test_connection_credential.go rename to gen/models/test_connection_credential.go index 47222eccf..54dcfce67 100644 --- a/client/models/test_connection_credential.go +++ b/gen/models/test_connection_credential.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" "encoding/json" diff --git a/client/models/test_external_backend_connection_input.go b/gen/models/test_external_backend_connection_input.go similarity index 98% rename from client/models/test_external_backend_connection_input.go rename to gen/models/test_external_backend_connection_input.go index 196ebe48b..c2858b564 100644 --- a/client/models/test_external_backend_connection_input.go +++ b/gen/models/test_external_backend_connection_input.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "bytes" "context" diff --git a/client/models/timeout_plan.go b/gen/models/timeout_plan.go similarity index 96% rename from client/models/timeout_plan.go rename to gen/models/timeout_plan.go index 81098776c..6acc249d7 100644 --- a/client/models/timeout_plan.go +++ b/gen/models/timeout_plan.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/try_plan.go b/gen/models/try_plan.go similarity index 96% rename from client/models/try_plan.go rename to gen/models/try_plan.go index 15e75e1c6..a7839ef74 100644 --- a/client/models/try_plan.go +++ b/gen/models/try_plan.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/update_api_key.go b/gen/models/update_api_key.go similarity index 93% rename from client/models/update_api_key.go rename to gen/models/update_api_key.go index 8ef6bdc5a..822c2c51f 100644 --- a/client/models/update_api_key.go +++ b/gen/models/update_api_key.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/update_cloud_account.go b/gen/models/update_cloud_account.go similarity index 95% rename from client/models/update_cloud_account.go rename to gen/models/update_cloud_account.go index 74760da7c..fa5fa772d 100644 --- a/client/models/update_cloud_account.go +++ b/gen/models/update_cloud_account.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/update_cloud_account_finops.go b/gen/models/update_cloud_account_finops.go similarity index 97% rename from client/models/update_cloud_account_finops.go rename to gen/models/update_cloud_account_finops.go index 1e9b82ecb..0a78d6361 100644 --- a/client/models/update_cloud_account_finops.go +++ b/gen/models/update_cloud_account_finops.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/update_cloud_cost_management_account.go b/gen/models/update_cloud_cost_management_account.go similarity index 95% rename from client/models/update_cloud_cost_management_account.go rename to gen/models/update_cloud_cost_management_account.go index 8a814d093..9d43a0c22 100644 --- a/client/models/update_cloud_cost_management_account.go +++ b/gen/models/update_cloud_cost_management_account.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/update_cloud_cost_management_linked_account.go b/gen/models/update_cloud_cost_management_linked_account.go similarity index 92% rename from client/models/update_cloud_cost_management_linked_account.go rename to gen/models/update_cloud_cost_management_linked_account.go index 2f61935b0..ee2351665 100644 --- a/client/models/update_cloud_cost_management_linked_account.go +++ b/gen/models/update_cloud_cost_management_linked_account.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/update_cloud_cost_management_tag_mapping.go b/gen/models/update_cloud_cost_management_tag_mapping.go similarity index 92% rename from client/models/update_cloud_cost_management_tag_mapping.go rename to gen/models/update_cloud_cost_management_tag_mapping.go index 1f8e47796..c89c4699d 100644 --- a/client/models/update_cloud_cost_management_tag_mapping.go +++ b/gen/models/update_cloud_cost_management_tag_mapping.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/update_component.go b/gen/models/update_component.go similarity index 92% rename from client/models/update_component.go rename to gen/models/update_component.go index 7ac68b3e9..3df6593b5 100644 --- a/client/models/update_component.go +++ b/gen/models/update_component.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/update_config_repository.go b/gen/models/update_config_repository.go similarity index 96% rename from client/models/update_config_repository.go rename to gen/models/update_config_repository.go index 5ccacc25c..47c294b5e 100644 --- a/client/models/update_config_repository.go +++ b/gen/models/update_config_repository.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/update_credential.go b/gen/models/update_credential.go similarity index 97% rename from client/models/update_credential.go rename to gen/models/update_credential.go index 800baa55c..acbbc8070 100644 --- a/client/models/update_credential.go +++ b/gen/models/update_credential.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" "encoding/json" diff --git a/client/models/update_environment.go b/gen/models/update_environment.go similarity index 97% rename from client/models/update_environment.go rename to gen/models/update_environment.go index 8f580a774..e6ccbd1bd 100644 --- a/client/models/update_environment.go +++ b/gen/models/update_environment.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/update_environment_type.go b/gen/models/update_environment_type.go similarity index 94% rename from client/models/update_environment_type.go rename to gen/models/update_environment_type.go index f2d08c7c6..6b5700e08 100644 --- a/client/models/update_environment_type.go +++ b/gen/models/update_environment_type.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/update_external_backend.go b/gen/models/update_external_backend.go similarity index 98% rename from client/models/update_external_backend.go rename to gen/models/update_external_backend.go index 5972305c3..caaf65c8d 100644 --- a/client/models/update_external_backend.go +++ b/gen/models/update_external_backend.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "bytes" "context" diff --git a/client/models/update_infra_policy.go b/gen/models/update_infra_policy.go similarity index 97% rename from client/models/update_infra_policy.go rename to gen/models/update_infra_policy.go index 65cc96c6d..837c9a29b 100644 --- a/client/models/update_infra_policy.go +++ b/gen/models/update_infra_policy.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" "encoding/json" diff --git a/gen/models/update_o_id_c_organization_settings.go b/gen/models/update_o_id_c_organization_settings.go new file mode 100644 index 000000000..b94dcb6c8 --- /dev/null +++ b/gen/models/update_o_id_c_organization_settings.go @@ -0,0 +1,156 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + "encoding/json" + + "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" + "github.com/go-openapi/validate" +) + +// UpdateOIDCOrganizationSettings UpdateOIDCOrganizationSettings +// +// The per-organization OIDC settings to create or update. 'eject' requires oidc_managed=true. +// +// swagger:model UpdateOIDCOrganizationSettings +type UpdateOIDCOrganizationSettings struct { + + // The canonical of the org-level role granted on OIDC provisioning. Empty clears it. + // Max Length: 100 + // Min Length: 3 + // Pattern: ^[a-z0-9]+[a-z0-9\-_]+[a-z0-9]+$ + DefaultRoleCanonical string `json:"default_role_canonical,omitempty"` + + // When true, local member/team/invite edits are disabled (strict mode). + // Required: true + OidcManaged *bool `json:"oidc_managed"` + + // The policy applied when no group mapping matches on login. 'eject' requires oidc_managed=true. + // Required: true + // Enum: ["keep_membership","eject"] + OidcNoMatchPolicy *string `json:"oidc_no_match_policy"` +} + +// Validate validates this update o ID c organization settings +func (m *UpdateOIDCOrganizationSettings) Validate(formats strfmt.Registry) error { + var res []error + + if err := m.validateDefaultRoleCanonical(formats); err != nil { + res = append(res, err) + } + + if err := m.validateOidcManaged(formats); err != nil { + res = append(res, err) + } + + if err := m.validateOidcNoMatchPolicy(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *UpdateOIDCOrganizationSettings) validateDefaultRoleCanonical(formats strfmt.Registry) error { + if swag.IsZero(m.DefaultRoleCanonical) { // not required + return nil + } + + if err := validate.MinLength("default_role_canonical", "body", m.DefaultRoleCanonical, 3); err != nil { + return err + } + + if err := validate.MaxLength("default_role_canonical", "body", m.DefaultRoleCanonical, 100); err != nil { + return err + } + + if err := validate.Pattern("default_role_canonical", "body", m.DefaultRoleCanonical, `^[a-z0-9]+[a-z0-9\-_]+[a-z0-9]+$`); err != nil { + return err + } + + return nil +} + +func (m *UpdateOIDCOrganizationSettings) validateOidcManaged(formats strfmt.Registry) error { + + if err := validate.Required("oidc_managed", "body", m.OidcManaged); err != nil { + return err + } + + return nil +} + +var updateOIdCOrganizationSettingsTypeOidcNoMatchPolicyPropEnum []any + +func init() { + var res []string + if err := json.Unmarshal([]byte(`["keep_membership","eject"]`), &res); err != nil { + panic(err) + } + for _, v := range res { + updateOIdCOrganizationSettingsTypeOidcNoMatchPolicyPropEnum = append(updateOIdCOrganizationSettingsTypeOidcNoMatchPolicyPropEnum, v) + } +} + +const ( + + // UpdateOIDCOrganizationSettingsOidcNoMatchPolicyKeepMembership captures enum value "keep_membership" + UpdateOIDCOrganizationSettingsOidcNoMatchPolicyKeepMembership string = "keep_membership" + + // UpdateOIDCOrganizationSettingsOidcNoMatchPolicyEject captures enum value "eject" + UpdateOIDCOrganizationSettingsOidcNoMatchPolicyEject string = "eject" +) + +// prop value enum +func (m *UpdateOIDCOrganizationSettings) validateOidcNoMatchPolicyEnum(path, location string, value string) error { + if err := validate.EnumCase(path, location, value, updateOIdCOrganizationSettingsTypeOidcNoMatchPolicyPropEnum, true); err != nil { + return err + } + return nil +} + +func (m *UpdateOIDCOrganizationSettings) validateOidcNoMatchPolicy(formats strfmt.Registry) error { + + if err := validate.Required("oidc_no_match_policy", "body", m.OidcNoMatchPolicy); err != nil { + return err + } + + // value enum + if err := m.validateOidcNoMatchPolicyEnum("oidc_no_match_policy", "body", *m.OidcNoMatchPolicy); err != nil { + return err + } + + return nil +} + +// ContextValidate validates this update o ID c organization settings based on context it is used +func (m *UpdateOIDCOrganizationSettings) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (m *UpdateOIDCOrganizationSettings) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *UpdateOIDCOrganizationSettings) UnmarshalBinary(b []byte) error { + var res UpdateOIDCOrganizationSettings + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/client/models/update_organization.go b/gen/models/update_organization.go similarity index 51% rename from client/models/update_organization.go rename to gen/models/update_organization.go index ce13f534e..ab63ea82d 100644 --- a/client/models/update_organization.go +++ b/gen/models/update_organization.go @@ -2,8 +2,12 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" + "strconv" "github.com/go-openapi/errors" "github.com/go-openapi/strfmt" @@ -40,6 +44,14 @@ type UpdateOrganization struct { // When true, SSO users can only join the organization if they have been explicitly invited SsoInviteOnly *bool `json:"sso_invite_only,omitempty"` + + // Glob patterns (filepath.Match syntax). Versions matching any of these are hidden from non-team-member users. Omitting this field or sending null preserves the current value. Send an empty array [] to clear all patterns. + // Max Items: 50 + StackBranchExcludePatterns []string `json:"stack_branch_exclude_patterns"` + + // Glob patterns (filepath.Match syntax). When set, only versions whose name matches at least one pattern are shown to non-team-member users. Empty means show all. Omitting this field or sending null preserves the current value. Send an empty array [] to clear all patterns. + // Max Items: 50 + StackBranchIncludePatterns []string `json:"stack_branch_include_patterns"` } // Validate validates this update organization @@ -50,6 +62,14 @@ func (m *UpdateOrganization) Validate(formats strfmt.Registry) error { res = append(res, err) } + if err := m.validateStackBranchExcludePatterns(formats); err != nil { + res = append(res, err) + } + + if err := m.validateStackBranchIncludePatterns(formats); err != nil { + res = append(res, err) + } + if len(res) > 0 { return errors.CompositeValidationError(res...) } @@ -69,6 +89,50 @@ func (m *UpdateOrganization) validateName(formats strfmt.Registry) error { return nil } +func (m *UpdateOrganization) validateStackBranchExcludePatterns(formats strfmt.Registry) error { + if swag.IsZero(m.StackBranchExcludePatterns) { // not required + return nil + } + + iStackBranchExcludePatternsSize := int64(len(m.StackBranchExcludePatterns)) + + if err := validate.MaxItems("stack_branch_exclude_patterns", "body", iStackBranchExcludePatternsSize, 50); err != nil { + return err + } + + for i := 0; i < len(m.StackBranchExcludePatterns); i++ { + + if err := validate.MaxLength("stack_branch_exclude_patterns"+"."+strconv.Itoa(i), "body", m.StackBranchExcludePatterns[i], 200); err != nil { + return err + } + + } + + return nil +} + +func (m *UpdateOrganization) validateStackBranchIncludePatterns(formats strfmt.Registry) error { + if swag.IsZero(m.StackBranchIncludePatterns) { // not required + return nil + } + + iStackBranchIncludePatternsSize := int64(len(m.StackBranchIncludePatterns)) + + if err := validate.MaxItems("stack_branch_include_patterns", "body", iStackBranchIncludePatternsSize, 50); err != nil { + return err + } + + for i := 0; i < len(m.StackBranchIncludePatterns); i++ { + + if err := validate.MaxLength("stack_branch_include_patterns"+"."+strconv.Itoa(i), "body", m.StackBranchIncludePatterns[i], 200); err != nil { + return err + } + + } + + return nil +} + // ContextValidate validates this update organization based on context it is used func (m *UpdateOrganization) ContextValidate(ctx context.Context, formats strfmt.Registry) error { return nil diff --git a/client/models/update_organization_messages.go b/gen/models/update_organization_messages.go similarity index 89% rename from client/models/update_organization_messages.go rename to gen/models/update_organization_messages.go index f9ec374f0..efeafa08a 100644 --- a/client/models/update_organization_messages.go +++ b/gen/models/update_organization_messages.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/update_organization_naming_rules.go b/gen/models/update_organization_naming_rules.go similarity index 97% rename from client/models/update_organization_naming_rules.go rename to gen/models/update_organization_naming_rules.go index 72a2537c5..126845099 100644 --- a/client/models/update_organization_naming_rules.go +++ b/gen/models/update_organization_naming_rules.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/update_pipeline.go b/gen/models/update_pipeline.go similarity index 93% rename from client/models/update_pipeline.go rename to gen/models/update_pipeline.go index 8b840b812..811dd0ae9 100644 --- a/client/models/update_pipeline.go +++ b/gen/models/update_pipeline.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/update_plugin.go b/gen/models/update_plugin.go similarity index 91% rename from client/models/update_plugin.go rename to gen/models/update_plugin.go index 0fc046d63..c888dc273 100644 --- a/client/models/update_plugin.go +++ b/gen/models/update_plugin.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/update_plugin_install.go b/gen/models/update_plugin_install.go similarity index 94% rename from client/models/update_plugin_install.go rename to gen/models/update_plugin_install.go index 6cd12c943..970bed283 100644 --- a/client/models/update_plugin_install.go +++ b/gen/models/update_plugin_install.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/update_plugin_manager.go b/gen/models/update_plugin_manager.go similarity index 95% rename from client/models/update_plugin_manager.go rename to gen/models/update_plugin_manager.go index c3a90fe70..1e0903340 100644 --- a/client/models/update_plugin_manager.go +++ b/gen/models/update_plugin_manager.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" "encoding/json" diff --git a/client/models/update_plugin_registry.go b/gen/models/update_plugin_registry.go similarity index 92% rename from client/models/update_plugin_registry.go rename to gen/models/update_plugin_registry.go index 371469e9e..fff35e175 100644 --- a/client/models/update_plugin_registry.go +++ b/gen/models/update_plugin_registry.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/update_project.go b/gen/models/update_project.go similarity index 97% rename from client/models/update_project.go rename to gen/models/update_project.go index cdd121fb1..ff2648c4f 100644 --- a/client/models/update_project.go +++ b/gen/models/update_project.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" "encoding/json" diff --git a/client/models/update_service_catalog.go b/gen/models/update_service_catalog.go similarity index 94% rename from client/models/update_service_catalog.go rename to gen/models/update_service_catalog.go index 4df9fa9ab..ffec8d835 100644 --- a/client/models/update_service_catalog.go +++ b/gen/models/update_service_catalog.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/update_service_catalog_source.go b/gen/models/update_service_catalog_source.go similarity index 96% rename from client/models/update_service_catalog_source.go rename to gen/models/update_service_catalog_source.go index 336d71fd5..938f13f8c 100644 --- a/client/models/update_service_catalog_source.go +++ b/gen/models/update_service_catalog_source.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/update_team.go b/gen/models/update_team.go similarity index 96% rename from client/models/update_team.go rename to gen/models/update_team.go index e639077b2..7427457db 100644 --- a/client/models/update_team.go +++ b/gen/models/update_team.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" "strconv" diff --git a/client/models/update_user_account.go b/gen/models/update_user_account.go similarity index 98% rename from client/models/update_user_account.go rename to gen/models/update_user_account.go index d03e4ab0c..f42298627 100644 --- a/client/models/update_user_account.go +++ b/gen/models/update_user_account.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" "encoding/json" diff --git a/client/models/update_user_account_email.go b/gen/models/update_user_account_email.go similarity index 94% rename from client/models/update_user_account_email.go rename to gen/models/update_user_account_email.go index 37f9c3f31..1be54ae3e 100644 --- a/client/models/update_user_account_email.go +++ b/gen/models/update_user_account_email.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/update_watch_rule.go b/gen/models/update_watch_rule.go similarity index 96% rename from client/models/update_watch_rule.go rename to gen/models/update_watch_rule.go index f104688b9..29a8724d6 100644 --- a/client/models/update_watch_rule.go +++ b/gen/models/update_watch_rule.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/user.go b/gen/models/user.go similarity index 97% rename from client/models/user.go rename to gen/models/user.go index f62c90917..da552c64e 100644 --- a/client/models/user.go +++ b/gen/models/user.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/user_account.go b/gen/models/user_account.go similarity index 98% rename from client/models/user_account.go rename to gen/models/user_account.go index 286ab0490..b4c5a18bd 100644 --- a/client/models/user_account.go +++ b/gen/models/user_account.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" "encoding/json" diff --git a/client/models/user_account_email.go b/gen/models/user_account_email.go similarity index 95% rename from client/models/user_account_email.go rename to gen/models/user_account_email.go index 49edcc6a4..56605a0c8 100644 --- a/client/models/user_account_email.go +++ b/gen/models/user_account_email.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/user_email.go b/gen/models/user_email.go similarity index 91% rename from client/models/user_email.go rename to gen/models/user_email.go index 92cfc6be5..0c291716a 100644 --- a/client/models/user_email.go +++ b/gen/models/user_email.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/user_guide.go b/gen/models/user_guide.go similarity index 59% rename from client/models/user_guide.go rename to gen/models/user_guide.go index 79c07cdb9..fe7c6ac76 100644 --- a/client/models/user_guide.go +++ b/gen/models/user_guide.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + // UserGuide User guide JSON schema // // # The user's guide progress JSON schema diff --git a/client/models/user_login.go b/gen/models/user_login.go similarity index 95% rename from client/models/user_login.go rename to gen/models/user_login.go index 5827ea9e9..b7c247b06 100644 --- a/client/models/user_login.go +++ b/gen/models/user_login.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/user_o_auth.go b/gen/models/user_o_auth.go similarity index 82% rename from client/models/user_o_auth.go rename to gen/models/user_o_auth.go index 233c9a44c..272b8d687 100644 --- a/client/models/user_o_auth.go +++ b/gen/models/user_o_auth.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" @@ -18,6 +21,9 @@ import ( // swagger:model UserOAuth type UserOAuth struct { + // OIDC group names whose mapped team could not be applied during a partial-apply login (the team did not resolve in the login organization). The login still succeeds with the valid teams applied; the frontend surfaces these as a non-blocking banner (FE-1435). Empty or absent when every mapped team applied cleanly. + OidcPartialFailureGroups []string `json:"oidc_partial_failure_groups"` + // Is the JWT of the platform user Token string `json:"token,omitempty"` diff --git a/client/models/user_password_reset_req.go b/gen/models/user_password_reset_req.go similarity index 92% rename from client/models/user_password_reset_req.go rename to gen/models/user_password_reset_req.go index 83de50ee7..dba14bbfa 100644 --- a/client/models/user_password_reset_req.go +++ b/gen/models/user_password_reset_req.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/user_password_reset_update.go b/gen/models/user_password_reset_update.go similarity index 94% rename from client/models/user_password_reset_update.go rename to gen/models/user_password_reset_update.go index 508683ed2..75483a41d 100644 --- a/client/models/user_password_reset_update.go +++ b/gen/models/user_password_reset_update.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/user_session.go b/gen/models/user_session.go similarity index 95% rename from client/models/user_session.go rename to gen/models/user_session.go index fa6037e5a..a4c8e8f06 100644 --- a/client/models/user_session.go +++ b/gen/models/user_session.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/v_mware_vsphere.go b/gen/models/v_mware_vsphere.go similarity index 96% rename from client/models/v_mware_vsphere.go rename to gen/models/v_mware_vsphere.go index 52c76f3e0..fd69547e6 100644 --- a/client/models/v_mware_vsphere.go +++ b/gen/models/v_mware_vsphere.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "bytes" "context" diff --git a/client/models/version_config.go b/gen/models/version_config.go similarity index 89% rename from client/models/version_config.go rename to gen/models/version_config.go index ccff8e95a..42fa4d928 100644 --- a/client/models/version_config.go +++ b/gen/models/version_config.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/versioned_resource_type.go b/gen/models/versioned_resource_type.go similarity index 96% rename from client/models/versioned_resource_type.go rename to gen/models/versioned_resource_type.go index c66e43fc7..008b5c1b5 100644 --- a/client/models/versioned_resource_type.go +++ b/gen/models/versioned_resource_type.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/watch_rule.go b/gen/models/watch_rule.go similarity index 98% rename from client/models/watch_rule.go rename to gen/models/watch_rule.go index b9293c906..e78590c3c 100644 --- a/client/models/watch_rule.go +++ b/gen/models/watch_rule.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" stderrors "errors" diff --git a/client/models/watch_rule_filter.go b/gen/models/watch_rule_filter.go similarity index 95% rename from client/models/watch_rule_filter.go rename to gen/models/watch_rule_filter.go index f3b9b41fd..020bc327d 100644 --- a/client/models/watch_rule_filter.go +++ b/gen/models/watch_rule_filter.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/client/models/worker.go b/gen/models/worker.go similarity index 96% rename from client/models/worker.go rename to gen/models/worker.go index dbf082c23..5e30e38e7 100644 --- a/client/models/worker.go +++ b/gen/models/worker.go @@ -2,6 +2,9 @@ package models +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + import ( "context" diff --git a/go.mod b/go.mod index 87aa30695..772e990b6 100644 --- a/go.mod +++ b/go.mod @@ -1,92 +1,71 @@ module github.com/cycloidio/cycloid-cli -go 1.25 +go 1.25.0 require ( dario.cat/mergo v1.0.2 github.com/adrg/xdg v0.5.3 github.com/charmbracelet/lipgloss v1.1.0 - github.com/go-openapi/errors v0.22.1 - github.com/go-openapi/runtime v0.28.0 - github.com/go-openapi/strfmt v0.23.0 - github.com/go-openapi/swag v0.23.1 - github.com/go-openapi/validate v0.24.0 - github.com/itchyny/gojq v0.12.17 - github.com/matryer/is v1.4.1 - github.com/pkg/errors v0.9.1 - github.com/sanity-io/litter v1.5.8 - github.com/spf13/cobra v1.10.1 - github.com/spf13/pflag v1.0.9 - github.com/spf13/viper v1.20.1 - github.com/stretchr/testify v1.10.0 - go.yaml.in/yaml/v4 v4.0.0-rc.2 - golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 - golang.org/x/term v0.33.0 + github.com/go-openapi/errors v0.22.8 + github.com/go-openapi/runtime v0.32.4 + github.com/go-openapi/strfmt v0.26.3 + github.com/go-openapi/swag v0.26.1 + github.com/go-openapi/validate v0.26.0 + github.com/itchyny/gojq v0.12.19 + github.com/spf13/cobra v1.10.2 + github.com/spf13/pflag v1.0.10 + github.com/spf13/viper v1.21.0 + go.yaml.in/yaml/v4 v4.0.0-rc.6 + golang.org/x/exp v0.0.0-20260611194520-c48552f49976 + golang.org/x/term v0.44.0 gopkg.in/yaml.v3 v3.0.1 ) require ( - github.com/Masterminds/goutils v1.1.1 // indirect - github.com/Masterminds/semver/v3 v3.2.1 // indirect - github.com/Masterminds/sprig/v3 v3.2.3 // indirect - github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect github.com/charmbracelet/x/ansi v0.8.0 // indirect github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd // indirect github.com/charmbracelet/x/term v0.2.1 // indirect - github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/clipperhouse/stringish v0.1.1 // indirect + github.com/clipperhouse/uax29/v2 v2.3.0 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect - github.com/go-openapi/analysis v0.23.0 // indirect - github.com/go-openapi/inflect v0.21.0 // indirect - github.com/go-openapi/jsonpointer v0.21.1 // indirect - github.com/go-openapi/jsonreference v0.21.0 // indirect - github.com/go-openapi/loads v0.22.0 // indirect - github.com/go-openapi/spec v0.21.0 // indirect - github.com/go-swagger/go-swagger v0.31.0 // indirect - github.com/go-viper/mapstructure/v2 v2.2.1 // indirect - github.com/google/go-cmp v0.7.0 // indirect + github.com/go-openapi/analysis v0.25.2 // indirect + github.com/go-openapi/jsonpointer v0.23.1 // indirect + github.com/go-openapi/jsonreference v0.21.6 // indirect + github.com/go-openapi/loads v0.24.0 // indirect + github.com/go-openapi/spec v0.22.6 // indirect + github.com/go-openapi/swag/cmdutils v0.26.1 // indirect + github.com/go-openapi/swag/conv v0.26.1 // indirect + github.com/go-openapi/swag/fileutils v0.26.1 // indirect + github.com/go-openapi/swag/jsonname v0.26.1 // indirect + github.com/go-openapi/swag/jsonutils v0.26.1 // indirect + github.com/go-openapi/swag/loading v0.26.1 // indirect + github.com/go-openapi/swag/mangling v0.26.1 // indirect + github.com/go-openapi/swag/netutils v0.26.1 // indirect + github.com/go-openapi/swag/stringutils v0.26.1 // indirect + github.com/go-openapi/swag/typeutils v0.26.1 // indirect + github.com/go-openapi/swag/yamlutils v0.26.1 // indirect + github.com/go-viper/mapstructure/v2 v2.5.0 // indirect github.com/google/uuid v1.6.0 // indirect - github.com/gorilla/handlers v1.5.2 // indirect - github.com/huandu/xstrings v1.4.0 // indirect - github.com/imdario/mergo v0.3.16 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/itchyny/timefmt-go v0.1.6 // indirect - github.com/jessevdk/go-flags v1.5.0 // indirect - github.com/josharian/intern v1.0.0 // indirect - github.com/kr/pretty v0.3.1 // indirect - github.com/kr/text v0.2.0 // indirect + github.com/itchyny/timefmt-go v0.1.8 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect - github.com/mailru/easyjson v0.9.0 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mattn/go-runewidth v0.0.16 // indirect - github.com/mitchellh/copystructure v1.2.0 // indirect - github.com/mitchellh/mapstructure v1.5.0 // indirect - github.com/mitchellh/reflectwalk v1.0.2 // indirect + github.com/mattn/go-runewidth v0.0.19 // indirect github.com/muesli/termenv v0.16.0 // indirect - github.com/oklog/ulid v1.3.1 // indirect + github.com/oklog/ulid/v2 v2.1.1 // indirect github.com/pelletier/go-toml/v2 v2.2.4 // indirect - github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/rivo/uniseg v0.4.7 // indirect - github.com/rogpeppe/go-internal v1.13.1 // indirect - github.com/sagikazarmark/locafero v0.9.0 // indirect - github.com/shopspring/decimal v1.3.1 // indirect - github.com/sourcegraph/conc v0.3.0 // indirect - github.com/spf13/afero v1.14.0 // indirect - github.com/spf13/cast v1.8.0 // indirect + github.com/sagikazarmark/locafero v0.11.0 // indirect + github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect + github.com/spf13/afero v1.15.0 // indirect + github.com/spf13/cast v1.10.0 // indirect github.com/subosito/gotenv v1.6.0 // indirect - github.com/toqueteos/webbrowser v1.2.0 // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect - go.mongodb.org/mongo-driver v1.17.3 // indirect - go.uber.org/multierr v1.11.0 // indirect - golang.org/x/crypto v0.32.0 // indirect - golang.org/x/mod v0.18.0 // indirect - golang.org/x/sync v0.14.0 // indirect - golang.org/x/sys v0.34.0 // indirect - golang.org/x/text v0.25.0 // indirect - golang.org/x/tools v0.22.0 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect + go.yaml.in/yaml/v3 v3.0.4 // indirect + golang.org/x/net v0.55.0 // indirect + golang.org/x/sync v0.21.0 // indirect + golang.org/x/sys v0.46.0 // indirect + golang.org/x/text v0.37.0 // indirect ) - -tool github.com/go-swagger/go-swagger/cmd/swagger diff --git a/go.sum b/go.sum index 5751606f5..19bc15efa 100644 --- a/go.sum +++ b/go.sum @@ -1,16 +1,7 @@ dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA= -github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= -github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= -github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= -github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0= -github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= -github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA= -github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM= github.com/adrg/xdg v0.5.3 h1:xRnxJXne7+oWDatRhR1JLnvuccuIeCoBu2rtuLqQB78= github.com/adrg/xdg v0.5.3/go.mod h1:nlTsY+NNiCBGCK2tpm09vRqfVzrc2fLmXGpBLF0zlTQ= -github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= -github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= github.com/aymanbagabas/go-udiff v0.2.0 h1:TK0fH4MteXUDspT88n8CKzvK0X9O2xu9yQjWpi6yML8= @@ -27,200 +18,141 @@ github.com/charmbracelet/x/exp/golden v0.0.0-20240806155701-69247e0abc2a h1:G99k github.com/charmbracelet/x/exp/golden v0.0.0-20240806155701-69247e0abc2a/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U= github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ= github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg= +github.com/clipperhouse/stringish v0.1.1 h1:+NSqMOr3GR6k1FdRhhnXrLfztGzuG+VuFDfatpWHKCs= +github.com/clipperhouse/stringish v0.1.1/go.mod h1:v/WhFtE1q0ovMta2+m+UbpZ+2/HEXNWYXQgCt4hdOzA= +github.com/clipperhouse/uax29/v2 v2.3.0 h1:SNdx9DVUqMoBuBoW3iLOj4FQv3dN5mDtuqwuhIGpJy4= +github.com/clipperhouse/uax29/v2 v2.3.0/go.mod h1:Wn1g7MK6OoeDT0vL+Q0SQLDz/KpfsVRgg6W7ihQeh4g= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= -github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= -github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= -github.com/go-openapi/analysis v0.23.0 h1:aGday7OWupfMs+LbmLZG4k0MYXIANxcuBTYUC03zFCU= -github.com/go-openapi/analysis v0.23.0/go.mod h1:9mz9ZWaSlV8TvjQHLl2mUW2PbZtemkE8yA5v22ohupo= -github.com/go-openapi/errors v0.22.1 h1:kslMRRnK7NCb/CvR1q1VWuEQCEIsBGn5GgKD9e+HYhU= -github.com/go-openapi/errors v0.22.1/go.mod h1:+n/5UdIqdVnLIJ6Q9Se8HNGUXYaY6CN8ImWzfi/Gzp0= -github.com/go-openapi/inflect v0.21.0 h1:FoBjBTQEcbg2cJUWX6uwL9OyIW8eqc9k4KhN4lfbeYk= -github.com/go-openapi/inflect v0.21.0/go.mod h1:INezMuUu7SJQc2AyR3WO0DqqYUJSj8Kb4hBd7WtjlAw= -github.com/go-openapi/jsonpointer v0.21.1 h1:whnzv/pNXtK2FbX/W9yJfRmE2gsmkfahjMKB0fZvcic= -github.com/go-openapi/jsonpointer v0.21.1/go.mod h1:50I1STOfbY1ycR8jGz8DaMeLCdXiI6aDteEdRNNzpdk= -github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ= -github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4= -github.com/go-openapi/loads v0.22.0 h1:ECPGd4jX1U6NApCGG1We+uEozOAvXvJSF4nnwHZ8Aco= -github.com/go-openapi/loads v0.22.0/go.mod h1:yLsaTCS92mnSAZX5WWoxszLj0u+Ojl+Zs5Stn1oF+rs= -github.com/go-openapi/runtime v0.28.0 h1:gpPPmWSNGo214l6n8hzdXYhPuJcGtziTOgUpvsFWGIQ= -github.com/go-openapi/runtime v0.28.0/go.mod h1:QN7OzcS+XuYmkQLw05akXk0jRH/eZ3kb18+1KwW9gyc= -github.com/go-openapi/spec v0.21.0 h1:LTVzPc3p/RzRnkQqLRndbAzjY0d0BCL72A6j3CdL9ZY= -github.com/go-openapi/spec v0.21.0/go.mod h1:78u6VdPw81XU44qEWGhtr982gJ5BWg2c0I5XwVMotYk= -github.com/go-openapi/strfmt v0.23.0 h1:nlUS6BCqcnAk0pyhi9Y+kdDVZdZMHfEKQiS4HaMgO/c= -github.com/go-openapi/strfmt v0.23.0/go.mod h1:NrtIpfKtWIygRkKVsxh7XQMDQW5HKQl6S5ik2elW+K4= -github.com/go-openapi/swag v0.23.1 h1:lpsStH0n2ittzTnbaSloVZLuB5+fvSY/+hnagBjSNZU= -github.com/go-openapi/swag v0.23.1/go.mod h1:STZs8TbRvEQQKUA+JZNAm3EWlgaOBGpyFDqQnDHMef0= -github.com/go-openapi/validate v0.24.0 h1:LdfDKwNbpB6Vn40xhTdNZAnfLECL81w+VX3BumrGD58= -github.com/go-openapi/validate v0.24.0/go.mod h1:iyeX1sEufmv3nPbBdX3ieNviWnOZaJ1+zquzJEf2BAQ= -github.com/go-swagger/go-swagger v0.31.0 h1:H8eOYQnY2u7vNKWDNykv2xJP3pBhRG/R+SOCAmKrLlc= -github.com/go-swagger/go-swagger v0.31.0/go.mod h1:WSigRRWEig8zV6t6Sm8Y+EmUjlzA/HoaZJ5edupq7po= -github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss= -github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/go-openapi/analysis v0.25.2 h1:I0vy4n3alz+DHTiN1PRhCb7QZxkK6g5YmswZKv2TKuw= +github.com/go-openapi/analysis v0.25.2/go.mod h1:Uhs1t/2XR10EnwONYILGEzw8gcfGIG5Xk5K2AxnhqDo= +github.com/go-openapi/errors v0.22.8 h1:oP7sW7TWc3wFFjrzzj0nI83H2qMBkNjNfSd+XRejk/I= +github.com/go-openapi/errors v0.22.8/go.mod h1:BuUoHcYrU6E7V9gfj1I5wLQqgtIHnup/alXZ8KdgQ0w= +github.com/go-openapi/jsonpointer v0.23.1 h1:1HBACs7XIwR2RcmItfdSFlALhGbe6S92p0ry4d1GWg4= +github.com/go-openapi/jsonpointer v0.23.1/go.mod h1:iWRmZTrGn7XwYhtPt/fvdSFj1OfNBngqRT2UG3BxSqY= +github.com/go-openapi/jsonreference v0.21.6 h1:NZ5nGfnaM1n4I43Xjm1e5/M2GjOwQwndQz22uhxwD+Y= +github.com/go-openapi/jsonreference v0.21.6/go.mod h1:xzbgtQ3ZbWxvET3AxdzCJlJt6vkovbf+IfSPJjD0tUY= +github.com/go-openapi/loads v0.24.0 h1:4LLorXRPTzIN9V6ngMUZbAscsBOUBk3Oa8cClu/bFrQ= +github.com/go-openapi/loads v0.24.0/go.mod h1:xQMgX+hw5xRAhGrcDXxeMw78IFqUpIzhleu3HqPhyF4= +github.com/go-openapi/runtime v0.32.4 h1:8ElGj/3goG0itt0nBPP6Cm57ehcYyuHoI3O20nxgvkw= +github.com/go-openapi/runtime v0.32.4/go.mod h1:Bz6keOZw1NX4T6f+m42OoT1MBPDt6Re13dbccHyGH/4= +github.com/go-openapi/spec v0.22.6 h1:Tyy1pLaNCM8GBCFLoGYLonjJi6zykqyLCjXLc19ZPic= +github.com/go-openapi/spec v0.22.6/go.mod h1:HZvTHat+iH0PALQRWhrqIHtU/PEqxqd89fu0MxGlMeM= +github.com/go-openapi/strfmt v0.26.3 h1:rzmslHarJgBbf2qfGge+X3htclQfmXqBZMm0Too0HhU= +github.com/go-openapi/strfmt v0.26.3/go.mod h1:a5nsUw0oRpQzZeOwx8bi6cKbzFZslpbCKt1LEot+KnQ= +github.com/go-openapi/swag v0.26.1 h1:l5sVEyVpwj+DDYeZyo7wQI/Ebn/mKYIyGB/pFwAfGoQ= +github.com/go-openapi/swag v0.26.1/go.mod h1:yNY38BbIVthxbkDtq1UHBCGasBqjakW3lCR6ANzdBEw= +github.com/go-openapi/swag/cmdutils v0.26.1 h1:f2iE1ijYaJ3nuu5PaEMx3zpEhzhZFgivCJObWEObLIQ= +github.com/go-openapi/swag/cmdutils v0.26.1/go.mod h1:Sm1MVFMkF6guJJ+pQqHnQA3N0j9qALV3NxzDSv6bETM= +github.com/go-openapi/swag/conv v0.26.1 h1:slr5FVkg9Wc3Y5zcwenD8Sd/PQ94b2I/QJI7N7KTBpg= +github.com/go-openapi/swag/conv v0.26.1/go.mod h1:mvQXgPptZk9GTrFgGwWvT4q+dN+zQej9JfmGwnipz1A= +github.com/go-openapi/swag/fileutils v0.26.1 h1:K1XCM2CGhfNsc6YDt6v7Q5+1e59rftYWdcu/isZhvFw= +github.com/go-openapi/swag/fileutils v0.26.1/go.mod h1:mYUgxQAKX4ShS3qvvySx+/9yrlUnDhjiD1CalaQl8lQ= +github.com/go-openapi/swag/jsonname v0.26.1 h1:VReupaV6WxlAsCn0e4DUfgV6bPmINnPpyJDLqSfNPcE= +github.com/go-openapi/swag/jsonname v0.26.1/go.mod h1:OvdW6BoWoj33pTfi7x9vFrgmT+fk7aw0BRwvCE0YOuc= +github.com/go-openapi/swag/jsonutils v0.26.1 h1:2hdBfFkHg+7Wrz2VsCbeyR6hzkRDs7AztnMR2u84yOY= +github.com/go-openapi/swag/jsonutils v0.26.1/go.mod h1:U+RMJH3wa+6BRiphuRtIyI8fW9HPFqFQ4sHk2oRx0UQ= +github.com/go-openapi/swag/jsonutils/fixtures_test v0.26.1 h1:1CD7NiLLb/TXl3tOnFYU4b+mNfb5rtgHkaA+q7RMYYQ= +github.com/go-openapi/swag/jsonutils/fixtures_test v0.26.1/go.mod h1:ZWafc8nMdYzTE3uYY6W86f0n46+IF0g4uUyRhJw/kXc= +github.com/go-openapi/swag/loading v0.26.1 h1:E9K4wqXeROlhjFQ13K9zMz6ojFGXIggGe+ad1odrK9w= +github.com/go-openapi/swag/loading v0.26.1/go.mod h1:3qvRIlWzWdq1HvmldwmuJ2ohpcAryN6xVt2OTKd0/7E= +github.com/go-openapi/swag/mangling v0.26.1 h1:gpYI4WuPKFJJVjV5cDLGlDVJhFIxYjQc7yN5eEb4CqM= +github.com/go-openapi/swag/mangling v0.26.1/go.mod h1:POETDH01hqAdASXfw7ISEd9bCOE6xBHOt8NHmGZRmYM= +github.com/go-openapi/swag/netutils v0.26.1 h1:BNctoc39WTAUMxyAs355fExOPzMZtPbZ0ZZ1Am2FR5M= +github.com/go-openapi/swag/netutils v0.26.1/go.mod h1:y02vByhZhQPAVwOX+0KipXFZ/hUbk6G/Enhf5rGaOkQ= +github.com/go-openapi/swag/stringutils v0.26.1 h1:f88uYyTso7TnHrKM/bUBsQ5e2wKf37cpgo6pvbzd9yU= +github.com/go-openapi/swag/stringutils v0.26.1/go.mod h1:Sc6d3bU8fgk5AyZR8/8jEQ+Is/Ald+TD/IIggPN8UJk= +github.com/go-openapi/swag/typeutils v0.26.1 h1:yg42FgMzRR6PVQ3M3qHz1s+Y6/P4HoJ3cBarXa3OVnU= +github.com/go-openapi/swag/typeutils v0.26.1/go.mod h1:VfnV+oUtSP2vCSCn2aJgnr8OevUYemyIzzS1VOzS10o= +github.com/go-openapi/swag/yamlutils v0.26.1 h1:0TSLK+lXs9vfIhAWzBeI/lOzEnIoot6WTCO1aAeWFTk= +github.com/go-openapi/swag/yamlutils v0.26.1/go.mod h1:7W5b7PRX9MxwL7TjeG7H8HkyBGRsIDRObhyMWFgBI2M= +github.com/go-openapi/testify/enable/yaml/v2 v2.5.1 h1:q9NtHwK4qHF7yZziBPvZyv7zWAIk8ok88Gh2mR6Jpc8= +github.com/go-openapi/testify/enable/yaml/v2 v2.5.1/go.mod h1:JW0MXIotCYps/XsgJnG3a8Q7rE5xAiBwoOD5OfaIQBk= +github.com/go-openapi/testify/v2 v2.5.1 h1:TMdhCaw8fUNraVSf3Omoob1dO/AzBfhtFAPW0an6sBo= +github.com/go-openapi/testify/v2 v2.5.1/go.mod h1:SgsVHtfooshd0tublTtJ50FPKhujf47YRqauXXOUxfw= +github.com/go-openapi/validate v0.26.0 h1:dxWzQ3F+vb1SajqUxHjwb5T4mTpSHmdrtv5Bi7+ZNhw= +github.com/go-openapi/validate v0.26.0/go.mod h1:b4o00uq7fJeJA+wWhVFCJpKTctzeFwzZImGGmHsl2JA= +github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro= +github.com/go-viper/mapstructure/v2 v2.5.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= -github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyEE= -github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w= -github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= -github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU= -github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= -github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= -github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/itchyny/gojq v0.12.17 h1:8av8eGduDb5+rvEdaOO+zQUjA04MS0m3Ps8HiD+fceg= -github.com/itchyny/gojq v0.12.17/go.mod h1:WBrEMkgAfAGO1LUcGOckBl5O726KPp+OlkKug0I/FEY= -github.com/itchyny/timefmt-go v0.1.6 h1:ia3s54iciXDdzWzwaVKXZPbiXzxxnv1SPGFfM/myJ5Q= -github.com/itchyny/timefmt-go v0.1.6/go.mod h1:RRDZYC5s9ErkjQvTvvU7keJjxUYzIISJGxm9/mAERQg= -github.com/jessevdk/go-flags v1.5.0 h1:1jKYvbxEjfUl0fmqTCOfonvskHHXMjBySTLW4y9LFvc= -github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= -github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= -github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/itchyny/gojq v0.12.19 h1:ttXA0XCLEMoaLOz5lSeFOZ6u6Q3QxmG46vfgI4O0DEs= +github.com/itchyny/gojq v0.12.19/go.mod h1:5galtVPDywX8SPSOrqjGxkBeDhSxEW1gSxoy7tn1iZY= +github.com/itchyny/timefmt-go v0.1.8 h1:1YEo1JvfXeAHKdjelbYr/uCuhkybaHCeTkH8Bo791OI= +github.com/itchyny/timefmt-go v0.1.8/go.mod h1:5E46Q+zj7vbTgWY8o5YkMeYb4I6GeWLFnetPy5oBrAI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= -github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4= -github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU= -github.com/matryer/is v1.4.1 h1:55ehd8zaGABKLXQUe2awZ99BD/PTc2ls+KV/dXphgEQ= -github.com/matryer/is v1.4.1/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= -github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= -github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= -github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= -github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= -github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= -github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= -github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/mattn/go-runewidth v0.0.19 h1:v++JhqYnZuu5jSKrk9RbgF5v4CGUjqRfBm05byFGLdw= +github.com/mattn/go-runewidth v0.0.19/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs= github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc= github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk= -github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/oklog/ulid/v2 v2.1.1 h1:suPZ4ARWLOJLegGFiZZ1dFAkqzhMjL3J1TzI+5wHz8s= +github.com/oklog/ulid/v2 v2.1.1/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ= +github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o= github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= -github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= -github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= -github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sagikazarmark/locafero v0.9.0 h1:GbgQGNtTrEmddYDSAH9QLRyfAHY12md+8YFTqyMTC9k= -github.com/sagikazarmark/locafero v0.9.0/go.mod h1:UBUyz37V+EdMS3hDF3QWIiVr/2dPrx49OMO0Bn0hJqk= -github.com/sanity-io/litter v1.5.8 h1:uM/2lKrWdGbRXDrIq08Lh9XtVYoeGtcQxk9rtQ7+rYg= -github.com/sanity-io/litter v1.5.8/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U= -github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= -github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= -github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= -github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= -github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= -github.com/spf13/afero v1.14.0 h1:9tH6MapGnn/j0eb0yIXiLjERO8RB6xIVZRDCX7PtqWA= -github.com/spf13/afero v1.14.0/go.mod h1:acJQ8t0ohCGuMN3O+Pv0V0hgMxNYDlvdk+VTfyZmbYo= -github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cast v1.8.0 h1:gEN9K4b8Xws4EX0+a0reLmhq8moKn7ntRlQYgjPeCDk= -github.com/spf13/cast v1.8.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= -github.com/spf13/cobra v1.10.1 h1:lJeBwCfmrnXthfAupyUTzJ/J4Nc1RsHC/mSRU2dll/s= -github.com/spf13/cobra v1.10.1/go.mod h1:7SmJGaTHFVBY0jW4NXGluQoLvhqFQM+6XSKD+P4XaB0= -github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY= +github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc= +github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik= +github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 h1:+jumHNA0Wrelhe64i8F6HNlS8pkoyMv5sreGx2Ry5Rw= +github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8/go.mod h1:3n1Cwaq1E1/1lhQhtRK2ts/ZwZEhjcQeJQ1RuC6Q/8U= +github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I= +github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg= +github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY= +github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= +github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU= +github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4= -github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v0.0.0-20161117074351-18a02ba4a312/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= +github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU= +github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= -github.com/toqueteos/webbrowser v1.2.0 h1:tVP/gpK69Fx+qMJKsLE7TD8LuGWPnEV71wBN9rrstGQ= -github.com/toqueteos/webbrowser v1.2.0/go.mod h1:XWoZq4cyp9WeUeak7w7LXRUQf1F1ATJMir8RTqb4ayM= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -go.mongodb.org/mongo-driver v1.17.3 h1:TQyXhnsWfWtgAhMtOgtYHMTkZIfBTpMTsMnd9ZBeHxQ= -go.mongodb.org/mongo-driver v1.17.3/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ= -go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= -go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.yaml.in/yaml/v4 v4.0.0-rc.2 h1:/FrI8D64VSr4HtGIlUtlFMGsm7H7pWTbj6vOLVZcA6s= -go.yaml.in/yaml/v4 v4.0.0-rc.2/go.mod h1:aZqd9kCMsGL7AuUv/m/PvWLdg5sjJsZ4oHDEnfPPfY0= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= -golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc= -golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= -golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ= -golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0= -golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ= -golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= +go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= +go.yaml.in/yaml/v4 v4.0.0-rc.6 h1:1h7H1ohdUh93/FyE4YaDa1Zh64K6VVbjF4K6WUxMtH4= +go.yaml.in/yaml/v4 v4.0.0-rc.6/go.mod h1:aZqd9kCMsGL7AuUv/m/PvWLdg5sjJsZ4oHDEnfPPfY0= +golang.org/x/exp v0.0.0-20260611194520-c48552f49976 h1:X8Hz2ImujgbmetVuW+w2YkyZChE3cBpZi2P158rTG9M= +golang.org/x/exp v0.0.0-20260611194520-c48552f49976/go.mod h1:vnf4pv9iKZXY58sQE1L86zmNWJ4159e1RkcWiLCkeEY= +golang.org/x/net v0.55.0 h1:bcvxaJn3e1U6InsFWt1JUq1aSjnRxLzT2rtD2KfkDF8= +golang.org/x/net v0.55.0/go.mod h1:L5U2KuzuOe1lY7Z+aWVIKK6qEeJXnXV9yzGA+WCHJww= +golang.org/x/sync v0.21.0 h1:HLII4xRRTtCRkxYp4HNFF0Js/Og6q2i++KXbg0gHCwM= +golang.org/x/sync v0.21.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA= -golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= -golang.org/x/term v0.33.0 h1:NuFncQrRcaRvVmgRkvM3j/F00gWIAlcmlB8ACEKmGIg= -golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= -golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA= -golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/sys v0.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw= +golang.org/x/sys v0.46.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/term v0.44.0 h1:0rLvDRCtNj0gZkyIXhCyOb2OAzEhLVqc4B+hrsBhrmc= +golang.org/x/term v0.44.0/go.mod h1:7ze4MdzUzLXpSAoFP1H0bOI9aXDqveSvatT5vKcFh2Y= +golang.org/x/text v0.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc= +golang.org/x/text v0.37.0/go.mod h1:a5sjxXGs9hsn/AJVwuElvCAo9v8QYLzvavO5z2PiM38= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/internal/buildwatch/stream_test.go b/internal/buildwatch/stream_test.go deleted file mode 100644 index c61ed6d27..000000000 --- a/internal/buildwatch/stream_test.go +++ /dev/null @@ -1,92 +0,0 @@ -package buildwatch - -import ( - "bytes" - "context" - "testing" - "time" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -// TestStreamLogsDumpCompletedBuild verifies that StreamLogs (dump mode) consumes -// all events from a completed build and returns nil when the stream closes naturally. -func TestStreamLogsDumpCompletedBuild(t *testing.T) { - body := "id:1\ndata:{\"event\":\"status\",\"data\":{\"status\":\"started\",\"time\":1}}\n\n" + - "id:2\ndata:{\"event\":\"status\",\"data\":{\"status\":\"succeeded\",\"time\":2}}\n\n" - - client := &fakeClient{ - statuses: []string{"succeeded"}, - streamBodies: []string{body}, - } - - var out bytes.Buffer - err := StreamLogs( - context.Background(), - client, - "org", "proj", "env", "comp", "pipeline", "job", "42", - Options{ - LogWriter: &out, - DisableInterruptHandler: true, - }, - ) - require.NoError(t, err) - // The stream had two events; human output should mention build status lines. - assert.Contains(t, out.String(), "[build]") -} - -// TestStreamLogsDumpIdleTimeout verifies that StreamLogs (dump mode) returns -// after the idle timeout fires, without blocking indefinitely on an open stream. -func TestStreamLogsDumpIdleTimeout(t *testing.T) { - // An empty stream body will block in a real connection, but our fakeClient - // returns a closed reader immediately. This tests the normal "no events" path. - client := &fakeClient{ - statuses: []string{"started"}, - streamBodies: []string{""}, - } - - var out bytes.Buffer - start := time.Now() - err := StreamLogs( - context.Background(), - client, - "org", "proj", "env", "comp", "pipeline", "job", "42", - Options{ - LogWriter: &out, - DisableInterruptHandler: true, - }, - ) - elapsed := time.Since(start) - require.NoError(t, err) - // Should complete quickly (stream closed immediately by fake client). - assert.Less(t, elapsed, 5*time.Second) -} - -// TestStreamLogsWatchDelegatesToWatch verifies that StreamLogs in watch mode -// behaves like Watch (returns error codes for failed builds, etc.). -func TestStreamLogsWatchDelegatesToWatch(t *testing.T) { - client := &fakeClient{ - statuses: []string{"started", "failed"}, - streamBodies: []string{""}, - } - - var out bytes.Buffer - err := StreamLogs( - context.Background(), - client, - "org", "proj", "env", "comp", "pipeline", "job", "42", - Options{ - Watch: true, - LogWriter: &out, - PollInterval: 10 * time.Millisecond, - DisableInterruptHandler: true, - }, - ) - // Watch mode should return ExitError for a failed build. - var exitErr *ExitError - require.ErrorAs(t, err, &exitErr) - assert.Equal(t, exitCodeFailed, exitErr.ExitCode()) - // AbortBuild should NOT be called in read-only watch mode. - assert.Equal(t, 0, client.abortCalls) -} diff --git a/internal/buildwatch/watch.go b/internal/buildwatch/watch.go index 8233618f0..6f07c7bc7 100644 --- a/internal/buildwatch/watch.go +++ b/internal/buildwatch/watch.go @@ -17,7 +17,7 @@ import ( "golang.org/x/term" - "github.com/cycloidio/cycloid-cli/client/models" + "github.com/cycloidio/cycloid-cli/gen/models" ) const ( @@ -40,7 +40,7 @@ const ( OutputRaw ) -// Client is the minimal middleware surface required for watch (implemented by middleware.Middleware). +// Client is the minimal middleware surface required for watch (implemented by apiclient.Middleware). type Client interface { GetBuild(org, project, env, component, pipeline, job, buildID string) (*models.Build, *http.Response, error) AbortBuild(org, project, env, component, pipeline, job, buildID string) (*http.Response, error) diff --git a/internal/buildwatch/watch_test.go b/internal/buildwatch/watch_test.go deleted file mode 100644 index 2dce600a7..000000000 --- a/internal/buildwatch/watch_test.go +++ /dev/null @@ -1,300 +0,0 @@ -package buildwatch - -import ( - "context" - "errors" - "io" - "net/http" - "strings" - "sync" - "testing" - "time" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/cycloidio/cycloid-cli/client/models" -) - -type fakeClient struct { - mu sync.Mutex - - statuses []string - getBuildCalls int - getBuildErr error - - abortCalls int - abortErr error - - streamBodies []string - openErr error - openCalls int -} - -func (f *fakeClient) GetBuild(_, _, _, _, _, _, _ string) (*models.Build, *http.Response, error) { - f.mu.Lock() - defer f.mu.Unlock() - - if f.getBuildErr != nil { - return nil, nil, f.getBuildErr - } - if len(f.statuses) == 0 { - return nil, nil, errors.New("no status configured") - } - - idx := f.getBuildCalls - if idx >= len(f.statuses) { - idx = len(f.statuses) - 1 - } - f.getBuildCalls++ - - status := f.statuses[idx] - return &models.Build{Status: &status}, nil, nil -} - -func (f *fakeClient) AbortBuild(_, _, _, _, _, _, _ string) (*http.Response, error) { - f.mu.Lock() - defer f.mu.Unlock() - f.abortCalls++ - return nil, f.abortErr -} - -func (f *fakeClient) OpenBuildEventsStream(_ context.Context, _, _, _, _, _, _, _ string) (io.ReadCloser, *http.Response, error) { - f.mu.Lock() - defer f.mu.Unlock() - - if f.openErr != nil { - return nil, nil, f.openErr - } - - idx := f.openCalls - if idx >= len(f.streamBodies) { - idx = len(f.streamBodies) - 1 - } - f.openCalls++ - - if len(f.streamBodies) == 0 { - return io.NopCloser(strings.NewReader("")), nil, nil - } - - return io.NopCloser(strings.NewReader(f.streamBodies[idx])), nil, nil -} - -func TestWatchSucceeded(t *testing.T) { - t.Parallel() - - client := &fakeClient{ - statuses: []string{"pending", "started", "succeeded"}, - streamBodies: []string{"data: first line\n\ndata: second line\n\n"}, - } - - var out strings.Builder - err := Watch( - context.Background(), - client, - "org", - "project", - "env", - "component", - "pipeline", - "job", - "42", - Options{ - LogWriter: &out, - PollInterval: time.Millisecond, - ReconnectDelay: 50 * time.Millisecond, - Output: OutputRaw, - DisableInterruptHandler: true, - }, - ) - require.NoError(t, err) - assert.Contains(t, out.String(), "first line") - assert.Contains(t, out.String(), "second line") -} - -func TestWatchAborted(t *testing.T) { - t.Parallel() - - client := &fakeClient{ - statuses: []string{"aborted"}, - } - - err := Watch( - context.Background(), - client, - "org", - "project", - "env", - "component", - "pipeline", - "job", - "42", - Options{ - PollInterval: time.Millisecond, - ReconnectDelay: 50 * time.Millisecond, - DisableInterruptHandler: true, - }, - ) - require.Error(t, err) - - var codedErr *ExitError - require.ErrorAs(t, err, &codedErr) - assert.Equal(t, exitCodeAborted, codedErr.ExitCode()) -} - -func TestWatchFailed(t *testing.T) { - t.Parallel() - - client := &fakeClient{ - statuses: []string{"failed"}, - } - - err := Watch( - context.Background(), - client, - "org", - "project", - "env", - "component", - "pipeline", - "job", - "42", - Options{ - PollInterval: time.Millisecond, - ReconnectDelay: 50 * time.Millisecond, - DisableInterruptHandler: true, - }, - ) - require.Error(t, err) - - var codedErr *ExitError - require.ErrorAs(t, err, &codedErr) - assert.Equal(t, exitCodeFailed, codedErr.ExitCode()) -} - -func TestWatchTimeoutWithCancel(t *testing.T) { - t.Parallel() - - client := &fakeClient{ - statuses: []string{"pending"}, - } - - err := Watch( - context.Background(), - client, - "org", - "project", - "env", - "component", - "pipeline", - "job", - "42", - Options{ - Timeout: 5 * time.Millisecond, - CancelOnTimeout: true, - PollInterval: time.Millisecond, - ReconnectDelay: 50 * time.Millisecond, - DisableInterruptHandler: true, - }, - ) - require.Error(t, err) - - var codedErr *ExitError - require.ErrorAs(t, err, &codedErr) - assert.Equal(t, exitCodeTimeout, codedErr.ExitCode()) - assert.Equal(t, 1, client.abortCalls) -} - -func TestConsumeBuildEventsTracksLastEventID(t *testing.T) { - t.Parallel() - - stream := strings.NewReader("id: 10\ndata: one\n\ndata: two\n\nid: 11\ndata: three\n\n") - var out strings.Builder - - rawOpts := consumeOpts{format: lineFormatRaw} - lastID, err := consumeBuildEvents(context.Background(), stream, &out, "", rawOpts) - require.NoError(t, err) - assert.Equal(t, "11", lastID) - assert.Equal(t, "one\ntwo\nthree\n", out.String()) -} - -func TestFormatHumanBuildEventSample(t *testing.T) { - t.Parallel() - - opts := consumeOpts{ - format: lineFormatHuman, - verbose: false, - theme: StreamTheme{}, - stripLogANSI: true, - } - - statusStarted := `{"data":{"status":"started","time":1774994819},"event":"status","version":"1.0","event_id":"0"}` - out, ok := formatHumanBuildEvent(statusStarted, opts) - require.True(t, ok) - assert.Equal(t, "[build] status: started\n", out) - - logOut := `{"data":{"time":1774994823,"origin":{"id":"69b7cd6b","source":"stdout"},"payload":"hello world\r\n"},"event":"log","version":"5.1","event_id":"16"}` - out, ok = formatHumanBuildEvent(logOut, opts) - require.True(t, ok) - assert.Contains(t, out, "[stdout]") - assert.Contains(t, out, "hello world") - - startTask := `{"data":{"time":1774994823,"origin":{"id":"69b7cd6b"}},"event":"start-task","version":"5.0","event_id":"15"}` - out, ok = formatHumanBuildEvent(startTask, opts) - require.True(t, ok) - assert.Equal(t, "[task] 69b7cd6b: started\n", out) - - finishTask := `{"data":{"time":1774994823,"exit_status":0,"origin":{"id":"69b7cd6b"}},"event":"finish-task","version":"4.0","event_id":"17"}` - out, ok = formatHumanBuildEvent(finishTask, opts) - require.True(t, ok) - assert.Equal(t, "[task] 69b7cd6b: finished (exit 0)\n", out) - - imageCheck := `{"data":{"time":1},"event":"image-check","version":"1.1","event_id":"2"}` - _, ok = formatHumanBuildEvent(imageCheck, opts) - assert.False(t, ok) - - opts.verbose = true - out, ok = formatHumanBuildEvent(imageCheck, opts) - require.True(t, ok) - assert.Contains(t, out, "[res]") - assert.Contains(t, out, "image-check") -} - -func TestFormatHumanBuildEventRawPassthroughInvalidJSON(t *testing.T) { - t.Parallel() - - opts := consumeOpts{format: lineFormatHuman, theme: StreamTheme{}} - out, ok := formatHumanBuildEvent("not-json", opts) - require.True(t, ok) - assert.Equal(t, "not-json\n", out) -} - -func TestFormatHumanBuildEventLogPreservesBlankLines(t *testing.T) { - t.Parallel() - - opts := consumeOpts{ - format: lineFormatHuman, - theme: StreamTheme{}, - stripLogANSI: true, - } - - // Blank lines within a payload are preserved as bare newlines so - // meaningful output separators (e.g. ls column groups) are not lost. - multi := `{"data":{"origin":{"source":"stdout"},"payload":"hello\n\n\nworld\n"},"event":"log","version":"1.0"}` - out, ok := formatHumanBuildEvent(multi, opts) - require.True(t, ok) - assert.Contains(t, out, "[stdout] hello") - assert.Contains(t, out, "[stdout] world") - assert.NotContains(t, out, "[stdout] \n") // blank lines must not get the [stdout] prefix - assert.Equal(t, 2, strings.Count(out, "[stdout]")) - assert.Greater(t, strings.Count(out, "\n"), 2) // blank lines are present as bare newlines - - // Fully-whitespace payloads are suppressed entirely. - emptyPayload := `{"data":{"origin":{"source":"stdout"},"payload":"\n"},"event":"log","version":"1.0"}` - _, ok = formatHumanBuildEvent(emptyPayload, opts) - assert.False(t, ok) - - onlySpaces := `{"data":{"origin":{"source":"stderr"},"payload":" \n\t\n"},"event":"log","version":"1.0"}` - _, ok = formatHumanBuildEvent(onlySpaces, opts) - assert.False(t, ok) -} diff --git a/internal/custommodels/stacks.go b/internal/custommodels/stacks.go index 6c5b5c4e6..48c84a69f 100644 --- a/internal/custommodels/stacks.go +++ b/internal/custommodels/stacks.go @@ -1,6 +1,6 @@ package custommodels -import "github.com/cycloidio/cycloid-cli/client/models" +import "github.com/cycloidio/cycloid-cli/gen/models" type Blueprint struct { // Added use cases for blueprint make it more usable output diff --git a/internal/cyargs/api_key.go b/internal/cyargs/api_key.go index 99d7e2b7c..36bf47e4b 100644 --- a/internal/cyargs/api_key.go +++ b/internal/cyargs/api_key.go @@ -6,8 +6,8 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" ) func AddAPIKeyDescriptionFlag(cmd *cobra.Command) string { @@ -55,14 +55,14 @@ func CompleteAPIKeyCanonical(cmd *cobra.Command, args []string, toComplete strin } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) APIKeys, _, err := m.ListAPIKeys(org) if err != nil { return cobra.AppendActiveHelp(nil, "failed to list API Keys: "+err.Error()), cobra.ShellCompDirectiveNoFileComp } - var APIKeysComp = make([]cobra.Completion, len(APIKeys)) + APIKeysComp := make([]cobra.Completion, len(APIKeys)) for index, apiKey := range APIKeys { if apiKey.Canonical != nil && strings.HasPrefix(*apiKey.Canonical, toComplete) { APIKeysComp[index] = cobra.CompletionWithDesc(*apiKey.Canonical, fmt.Sprintf("%s from %s: %s", *apiKey.Name, *apiKey.Owner.Username, apiKey.Description)) diff --git a/internal/cyargs/cloud_accounts.go b/internal/cyargs/cloud_accounts.go index 55d4f84d2..3e4a31192 100644 --- a/internal/cyargs/cloud_accounts.go +++ b/internal/cyargs/cloud_accounts.go @@ -5,8 +5,8 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" ) // CloudAccountFlag is the canonical flag name for cloud-account targeting, @@ -63,7 +63,7 @@ func CompleteCloudAccount(cmd *cobra.Command, args []string, toComplete string) } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) accounts, _, err := m.ListCloudAccounts(org) if err != nil { return cobra.AppendActiveHelp(nil, "failed to list cloud accounts: "+err.Error()), diff --git a/internal/cyargs/common.go b/internal/cyargs/common.go index f62b57629..e1b0555d2 100644 --- a/internal/cyargs/common.go +++ b/internal/cyargs/common.go @@ -9,8 +9,8 @@ import ( "github.com/spf13/cobra" "github.com/spf13/viper" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" ) var ( @@ -133,7 +133,7 @@ func CompleteProject(cmd *cobra.Command, args []string, toComplete string) ([]co } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) projects, _, err := m.ListProjects(org) if err != nil { @@ -141,7 +141,7 @@ func CompleteProject(cmd *cobra.Command, args []string, toComplete string) ([]co cobra.ShellCompDirectiveNoFileComp } - var canonicals = make([]cobra.Completion, len(projects)) + canonicals := make([]cobra.Completion, len(projects)) for index, project := range projects { if project.Canonical != nil && strings.HasPrefix(*project.Canonical, toComplete) { canonicals[index] = cobra.CompletionWithDesc(*project.Canonical, *project.Name) @@ -191,7 +191,7 @@ func AddEnvFlag(cmd *cobra.Command) { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) envs, _, err := m.ListProjectEnvs(org, project) if err != nil { @@ -199,7 +199,7 @@ func AddEnvFlag(cmd *cobra.Command) { cobra.ShellCompDirectiveNoFileComp } - var canonicals = make([]cobra.Completion, len(envs)) + canonicals := make([]cobra.Completion, len(envs)) for index, env := range envs { if env.Canonical != nil && strings.HasPrefix(*env.Canonical, toComplete) { canonicals[index] = cobra.CompletionWithDesc(*env.Canonical, env.Name) @@ -255,7 +255,7 @@ func AddComponentFlag(cmd *cobra.Command) { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) components, _, err := m.ListComponents(org, project, env) if err != nil { @@ -263,7 +263,7 @@ func AddComponentFlag(cmd *cobra.Command) { cobra.ShellCompDirectiveNoFileComp } - var canonicals = make([]string, len(components)) + canonicals := make([]string, len(components)) for index, component := range components { if component.Canonical != nil && strings.HasPrefix(*component.Canonical, toComplete) { canonicals[index] = cobra.CompletionWithDesc(*component.Canonical, *component.Name) @@ -398,7 +398,7 @@ func AddOwnerFlag(cmd *cobra.Command) string { cmd.Flags().String(flagName, "", "canonical of a user to set as owner, will be the user attached to the current api key if empty.") cmd.RegisterFlagCompletionFunc(flagName, func(cmd *cobra.Command, args []string, toComplete string) ([]cobra.Completion, cobra.ShellCompDirective) { api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) org, err := GetOrg(cmd) if err != nil { @@ -412,7 +412,7 @@ func AddOwnerFlag(cmd *cobra.Command) string { cobra.ShellCompDirectiveNoFileComp } - var owners = make([]cobra.Completion, len(members)) + owners := make([]cobra.Completion, len(members)) for index, member := range members { if strings.HasPrefix(member.Username, toComplete) { owners[index] = cobra.CompletionWithDesc( @@ -452,23 +452,26 @@ func GetDescription(cmd *cobra.Command) (string, error) { func AddDeleteFlags(cmd *cobra.Command) { cmd.Flags().Bool("force", false, "shorthand for --skip-hooks --ignore-config-files-err") - cmd.Flags().Bool("skip-hooks", false, "skip component on_delete hooks (sets skip_hooks=true)") + cmd.Flags().Bool("skip-hooks", false, "skip component on_delete hooks (sets skip_hooks=true)") cmd.Flags().Bool("ignore-config-files-err", false, "ignore possible errors on config repository update (sets ignore_config_files_err=true)") } func GetDeleteFlags(cmd *cobra.Command) (force, skipHooks, ignoreConfigFilesErr bool, err error) { if force, err = cmd.Flags().GetBool("force"); err != nil { - return + return force, skipHooks, ignoreConfigFilesErr, err } if skipHooks, err = cmd.Flags().GetBool("skip-hooks"); err != nil { - return + return force, skipHooks, ignoreConfigFilesErr, err } ignoreConfigFilesErr, err = cmd.Flags().GetBool("ignore-config-files-err") - return + return force, skipHooks, ignoreConfigFilesErr, err } func GetOrg(cmd *cobra.Command) (string, error) { - org := v.GetString("org") + // The --org flag is bound to the global viper instance in root.go, so we + // use viper.GetString instead of the package-level v.GetString to always + // read from the current global instance (important after viper.Reset in tests). + org := viper.GetString("org") if org == "" { return "", fmt.Errorf("org is not set, use --org flag or CY_ORG env var, current value: %q", org) } diff --git a/internal/cyargs/common_test.go b/internal/cyargs/common_test.go deleted file mode 100644 index 7373f9c66..000000000 --- a/internal/cyargs/common_test.go +++ /dev/null @@ -1,89 +0,0 @@ -package cyargs_test - -import ( - "os" - "strings" - "testing" - - "github.com/sanity-io/litter" - "github.com/spf13/cobra" - "github.com/spf13/viper" - "github.com/stretchr/testify/assert" - - "github.com/cycloidio/cycloid-cli/internal/cyargs" -) - -var ( - org = "myOrg" - project = "myProject" - env = "myEnv" - component = "myComponent" - v = viper.GetViper() -) - -func parseArgFunc(t *testing.T, cmd *cobra.Command, args []string) { - t.Logf("Input args: %v", args) - t.Logf("cmd persistent flags: %s", litter.Sdump(cmd.PersistentFlags())) - if !cmd.HasPersistentFlags() { - t.Fatal("cmd does not have the org persistent flag") - } - - err := cmd.ParseFlags(args) - if err != nil { - t.Errorf("Failed to parse flags '%v' with cmd: %v", args, err) - } - - orgArg, projectArg, envArg, componentArg, err := cyargs.GetCyContext(cmd) - if err != nil { - t.Fatal("failed to parse args for cy context:", err) - } - - assert.Equal(t, org, orgArg) - assert.Equal(t, project, projectArg) - assert.Equal(t, env, envArg) - assert.Equal(t, component, componentArg) -} - -func TestCyContext(t *testing.T) { - // This test does not work as intended, remove or fix later - t.Skip() - - // Add the same viper setup that our root cmd - v.SetEnvPrefix("CY") - v.SetEnvKeyReplacer(strings.NewReplacer("-", "_")) - v.AutomaticEnv() - - // Add the org flag that is normally declared in the root org - cmd := cobra.Command{} - cmd.PersistentFlags().String("org", "", "Specify the org to use. override CY_ORG env var. Required for all Org scoped endpoint.") - v.BindPFlag("org", cmd.PersistentFlags().Lookup("org")) - cyargs.AddCyContext(&cmd) - - t.Run("WithFullFlag", func(t *testing.T) { - parseArgFunc(t, &cmd, []string{ - "--org", org, - "--project", project, - "--env", env, - "--component", component, - }, - ) - }) - - t.Run("WithShortFlag", func(t *testing.T) { - parseArgFunc(t, &cmd, []string{ - "--org", org, - "-p", project, - "-e", env, - "-c", component, - }, - ) - }) - - t.Run("WithEnvVar", func(t *testing.T) { - os.Setenv("CY_ORG", org) - os.Setenv("CY_PROJECT", project) - os.Setenv("CY_ENV", env) - os.Setenv("CY_COMPONENT", component) - parseArgFunc(t, &cmd, []string{}) - }) -} diff --git a/internal/cyargs/component.go b/internal/cyargs/component.go index e91017a75..b04f8a0de 100644 --- a/internal/cyargs/component.go +++ b/internal/cyargs/component.go @@ -6,8 +6,8 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" ) func AddComponentDescriptionFlag(cmd *cobra.Command) { @@ -80,7 +80,7 @@ func CompleteUseCase(cmd *cobra.Command, args []string, toComplete string) ([]st } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) // Try to get the stack use cases using the provided flags // If none are provided yet, this will use default version diff --git a/internal/cyargs/config_catalog_repositories.go b/internal/cyargs/config_catalog_repositories.go index 0ec5353e7..7da9d0f72 100644 --- a/internal/cyargs/config_catalog_repositories.go +++ b/internal/cyargs/config_catalog_repositories.go @@ -6,9 +6,9 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" + "github.com/cycloidio/cycloid-cli/gen/models" ) func AddCatalogRepositoryFlag(cmd *cobra.Command) string { @@ -51,7 +51,7 @@ func CompleteCatalogRepository(cmd *cobra.Command, args []string, toComplete str } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) stacks, _, err := m.ListCatalogRepositories(org) if err != nil { @@ -59,7 +59,7 @@ func CompleteCatalogRepository(cmd *cobra.Command, args []string, toComplete str cobra.ShellCompDirectiveNoFileComp } - var catalogRepositories = make([]cobra.Completion, len(stacks)) + catalogRepositories := make([]cobra.Completion, len(stacks)) for index, catalogRepository := range stacks { if catalogRepository.Canonical != nil { catalogRepositories[index] = cobra.CompletionWithDesc(*catalogRepository.Canonical, *catalogRepository.Name+" - branch: "+catalogRepository.Branch) @@ -86,7 +86,7 @@ func AddConfigRepoCanonicalFlag(cmd *cobra.Command) string { func CompleteConfigRepository(cmd *cobra.Command, args []string, toComplete string) ([]cobra.Completion, cobra.ShellCompDirective) { api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) org, err := GetOrg(cmd) if err != nil { @@ -98,7 +98,7 @@ func CompleteConfigRepository(cmd *cobra.Command, args []string, toComplete stri return cobra.AppendActiveHelp(nil, "failed to list config repositories for completion in org '"+org+"': "+err.Error()), cobra.ShellCompDirectiveError } - var configRepositories = make([]cobra.Completion, len(stacks)) + configRepositories := make([]cobra.Completion, len(stacks)) for index, configRepository := range stacks { if configRepository.Canonical != nil { configRepositories[index] = cobra.CompletionWithDesc(*configRepository.Canonical, *configRepository.Name+" - branch: "+configRepository.Branch) @@ -121,7 +121,7 @@ func GetConfigRepository(cmd *cobra.Command) (string, error) { func GetDefaultConfigRepository(cmd *cobra.Command) (string, error) { api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) org, err := GetOrg(cmd) if err != nil { diff --git a/internal/cyargs/credentials.go b/internal/cyargs/credentials.go index acacb5c9d..cc3356dbb 100644 --- a/internal/cyargs/credentials.go +++ b/internal/cyargs/credentials.go @@ -5,8 +5,8 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" ) func AddCredentialDescriptionPersistentFlag(cmd *cobra.Command) string { @@ -46,7 +46,7 @@ func CompleteCredentialCanonical(cmd *cobra.Command, args []string, toComplete s } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) creds, _, err := m.ListCredentials(org, "") if err != nil { @@ -54,7 +54,7 @@ func CompleteCredentialCanonical(cmd *cobra.Command, args []string, toComplete s cobra.ShellCompDirectiveNoFileComp } - var completions = make([]cobra.Completion, len(creds)) + completions := make([]cobra.Completion, len(creds)) for index, cred := range creds { if cred.Canonical != nil && strings.HasPrefix(*cred.Canonical, toComplete) { completions[index] = cobra.CompletionWithDesc(*cred.Canonical, *cred.Name+": "+cred.Description) @@ -89,7 +89,7 @@ func CompleteCredentialPath(cmd *cobra.Command, args []string, toComplete string } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) creds, _, err := m.ListCredentials(org, "") if err != nil { @@ -97,7 +97,7 @@ func CompleteCredentialPath(cmd *cobra.Command, args []string, toComplete string cobra.ShellCompDirectiveNoFileComp } - var completions = make([]cobra.Completion, len(creds)) + completions := make([]cobra.Completion, len(creds)) for index, cred := range creds { if cred.Path != nil && strings.HasPrefix(*cred.Path, toComplete) { completions[index] = cobra.CompletionWithDesc(*cred.Path, *cred.Name+": "+cred.Description) @@ -132,7 +132,7 @@ func CompleteCredentialName(cmd *cobra.Command, args []string, toComplete string } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) creds, _, err := m.ListCredentials(org, "") if err != nil { @@ -140,7 +140,7 @@ func CompleteCredentialName(cmd *cobra.Command, args []string, toComplete string cobra.ShellCompDirectiveNoFileComp } - var completions = make([]cobra.Completion, len(creds)) + completions := make([]cobra.Completion, len(creds)) for index, cred := range creds { if cred.Name != nil && strings.HasPrefix(*cred.Name, toComplete) { completions[index] = cobra.CompletionWithDesc(*cred.Name, *cred.Canonical+": "+cred.Description) @@ -295,7 +295,7 @@ func CompleteCredentialType(_ *cobra.Command, _ []string, toComplete string) ([] "swift", } - var comps = make([]cobra.Completion, len(credTypes)) + comps := make([]cobra.Completion, len(credTypes)) for index, credType := range credTypes { if strings.HasPrefix(credType, toComplete) { comps[index] = credType diff --git a/internal/cyargs/environment_types.go b/internal/cyargs/environment_types.go index 33fa9092c..c2ee29a24 100644 --- a/internal/cyargs/environment_types.go +++ b/internal/cyargs/environment_types.go @@ -5,8 +5,8 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" ) func AddEnvironmentTypeNameFlag(cmd *cobra.Command) string { @@ -27,7 +27,7 @@ func CompleteEnvironmentTypeCanonical(cmd *cobra.Command, args []string, toCompl } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) types, _, err := m.ListEnvironmentTypes(org) if err != nil { return cobra.AppendActiveHelp(nil, "failed to list environment types: "+err.Error()), diff --git a/internal/cyargs/environments.go b/internal/cyargs/environments.go index 8dc765e20..ea297ae46 100644 --- a/internal/cyargs/environments.go +++ b/internal/cyargs/environments.go @@ -8,10 +8,10 @@ import ( "github.com/spf13/cobra" "gopkg.in/yaml.v3" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" - "github.com/cycloidio/cycloid-cli/internal/ptr" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" + "github.com/cycloidio/cycloid-cli/gen/models" + "github.com/cycloidio/cycloid-cli/utils/ptr" ) func AddEnvironmentTypeFlag(cmd *cobra.Command) string { @@ -33,7 +33,7 @@ func CompleteEnvironmentType(cmd *cobra.Command, args []string, toComplete strin } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) types, _, err := m.ListEnvironmentTypes(org) if err != nil { return cobra.AppendActiveHelp(nil, "failed to list environment types: "+err.Error()), @@ -72,7 +72,7 @@ func CompleteCloudAccountCanonical(cmd *cobra.Command, args []string, toComplete } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) accounts, _, err := m.ListCloudAccounts(org) if err != nil { return cobra.AppendActiveHelp(nil, "failed to list cloud accounts: "+err.Error()), diff --git a/internal/cyargs/licence.go b/internal/cyargs/licence.go index 8b34084af..a7c94e735 100644 --- a/internal/cyargs/licence.go +++ b/internal/cyargs/licence.go @@ -8,7 +8,7 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" + "github.com/cycloidio/cycloid-cli/cmd/common" ) func AddLicenceKeyFlag(cmd *cobra.Command) string { diff --git a/internal/cyargs/members.go b/internal/cyargs/members.go index 58e03b81d..df48ae4d8 100644 --- a/internal/cyargs/members.go +++ b/internal/cyargs/members.go @@ -7,8 +7,8 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" ) // AddMemberIDFlag registers --id for member get/delete/update commands. @@ -56,7 +56,7 @@ func CompleteMemberID(cmd *cobra.Command, args []string, toComplete string) ([]c } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) members, _, err := m.ListMembers(org) if err != nil { @@ -88,7 +88,7 @@ func CompleteMemberEmail(cmd *cobra.Command, args []string, toComplete string) ( } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) members, _, err := m.ListMembers(org) if err != nil { diff --git a/internal/cyargs/organizations.go b/internal/cyargs/organizations.go index 89fe3b70a..8103605e4 100644 --- a/internal/cyargs/organizations.go +++ b/internal/cyargs/organizations.go @@ -10,9 +10,9 @@ import ( "github.com/spf13/cobra" "go.yaml.in/yaml/v4" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" + "github.com/cycloidio/cycloid-cli/gen/models" ) func AddOrgNameFlag(cmd *cobra.Command) string { @@ -27,7 +27,7 @@ func GetOrgName(cmd *cobra.Command) (string, error) { func CompleteOrg(cmd *cobra.Command, args []string, toComplete string) ([]cobra.Completion, cobra.ShellCompDirective) { api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) org, err := GetOrg(cmd) if err != nil { @@ -93,7 +93,7 @@ func CompleteRoleCanonical(cmd *cobra.Command, args []string, toComplete string) } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) roles, _, err := m.ListRoles(org) if err != nil { @@ -141,7 +141,7 @@ func GetRoleRulesJSON(cmd *cobra.Command) ([]*models.NewRule, error) { return nil, err } - var rules = make([]*models.NewRule, len(rulesJSON)) + rules := make([]*models.NewRule, len(rulesJSON)) for i, ruleJSON := range rulesJSON { var rule models.NewRule err := json.Unmarshal([]byte(ruleJSON), &rule) @@ -161,7 +161,7 @@ func GetRoleRulesFiles(cmd *cobra.Command) ([]*models.NewRule, error) { return nil, err } - var rules = []*models.NewRule{} + rules := []*models.NewRule{} for _, ruleFile := range rulesFiles { var content []byte if ruleFile == "-" && common.DetectStdinInput() { diff --git a/internal/cyargs/pipelines_jobs_build.go b/internal/cyargs/pipelines_jobs_build.go index f8dbc5d9f..8314578bf 100644 --- a/internal/cyargs/pipelines_jobs_build.go +++ b/internal/cyargs/pipelines_jobs_build.go @@ -8,22 +8,20 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" + "github.com/cycloidio/cycloid-cli/gen/models" ) -var ( - validPipelineStatuses = []string{ - "aborted", - "errored", - "failed", - "paused", - "pending", - "started", - "succeeded", - } -) +var validPipelineStatuses = []string{ + "aborted", + "errored", + "failed", + "paused", + "pending", + "started", + "succeeded", +} func AddPipelineStatuses(cmd *cobra.Command) string { flagName := "statuses" @@ -68,14 +66,14 @@ func AddPipeline(cmd *cobra.Command) string { env, _ := GetEnv(cmd) api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) pipelines, _, err := m.GetEnvPipelines(org, project, env) if err != nil { return cobra.AppendActiveHelp(nil, "failed to fetch pipeline list for completion in org '"+org+"': "+err.Error()), cobra.ShellCompDirectiveNoFileComp } - var names = make([]cobra.Completion, len(pipelines)) + names := make([]cobra.Completion, len(pipelines)) for index, pipeline := range pipelines { if pipeline.Name != nil && strings.HasPrefix(*pipeline.Name, toComplete) { names[index] = cobra.CompletionWithDesc(*pipeline.Name, @@ -103,7 +101,7 @@ func GetPipeline(cmd *cobra.Command) (string, error) { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) pipelines, _, err := m.GetEnvPipelines(org, project, environment) if err != nil { @@ -159,7 +157,7 @@ func AddPipelineJob(cmd *cobra.Command) string { pipeline, _ := GetPipeline(cmd) api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) jobs, _, err := m.GetJobs(org, project, env, component, pipeline) if err != nil { return cobra.AppendActiveHelp(nil, fmt.Sprintf( @@ -215,7 +213,7 @@ func AddPipelineBuildID(cmd *cobra.Command) string { job, _ := GetPipelineJob(cmd) api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) builds, _, err := m.GetBuilds(org, project, env, component, pipeline, job) if err != nil { diff --git a/internal/cyargs/plugins.go b/internal/cyargs/plugins.go index 7412d8301..3aa79c8f2 100644 --- a/internal/cyargs/plugins.go +++ b/internal/cyargs/plugins.go @@ -9,8 +9,8 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" ) // --------------------------------------------------------------------------- @@ -148,7 +148,7 @@ func CompletePluginInstallID(cmd *cobra.Command, args []string, toComplete strin return cobra.AppendActiveHelp(nil, "missing org: "+err.Error()), cobra.ShellCompDirectiveNoFileComp } - m := middleware.NewMiddleware(common.NewAPI()) + m := apiclient.NewMiddleware(common.NewAPI()) plugins, _, err := m.ListPlugins(org) if err != nil { return cobra.AppendActiveHelp(nil, "failed to list plugins: "+err.Error()), cobra.ShellCompDirectiveNoFileComp @@ -178,7 +178,7 @@ func CompletePluginInstallID(cmd *cobra.Command, args []string, toComplete strin // ResolvePluginInstallID resolves a numeric ID string or name to a uint32 plugin install ID. // The install ID lives at Plugin.Install.ID (not Plugin.ID which is the registry plugin ID). -func ResolvePluginInstallID(org, nameOrID string, m middleware.Middleware) (uint32, error) { +func ResolvePluginInstallID(org, nameOrID string, m apiclient.Middleware) (uint32, error) { if id, err := strconv.ParseUint(nameOrID, 10, 32); err == nil { return uint32(id), nil } @@ -209,7 +209,7 @@ func CompletePluginManagerID(cmd *cobra.Command, args []string, toComplete strin return cobra.AppendActiveHelp(nil, "missing org: "+err.Error()), cobra.ShellCompDirectiveNoFileComp } - m := middleware.NewMiddleware(common.NewAPI()) + m := apiclient.NewMiddleware(common.NewAPI()) managers, _, err := m.ListPluginManagers(org) if err != nil { return cobra.AppendActiveHelp(nil, "failed to list plugin managers: "+err.Error()), cobra.ShellCompDirectiveNoFileComp @@ -232,7 +232,7 @@ func CompletePluginManagerID(cmd *cobra.Command, args []string, toComplete strin } // ResolvePluginManagerID resolves a numeric ID, name, or URL to a plugin manager ID. -func ResolvePluginManagerID(org, nameOrID string, m middleware.Middleware) (uint32, error) { +func ResolvePluginManagerID(org, nameOrID string, m apiclient.Middleware) (uint32, error) { if id, err := strconv.ParseUint(nameOrID, 10, 32); err == nil { return uint32(id), nil } @@ -264,7 +264,7 @@ func CompletePluginRegistryID(cmd *cobra.Command, args []string, toComplete stri return cobra.AppendActiveHelp(nil, "missing org: "+err.Error()), cobra.ShellCompDirectiveNoFileComp } - m := middleware.NewMiddleware(common.NewAPI()) + m := apiclient.NewMiddleware(common.NewAPI()) registries, _, err := m.ListPluginRegistries(org) if err != nil { return cobra.AppendActiveHelp(nil, "failed to list plugin registries: "+err.Error()), cobra.ShellCompDirectiveNoFileComp @@ -297,7 +297,7 @@ func CompletePluginRegistryID(cmd *cobra.Command, args []string, toComplete stri // ResolvePluginRegistryID resolves a numeric ID, name, or URL to a plugin registry ID. // URL matching is tried when the value starts with "http". -func ResolvePluginRegistryID(org, nameOrID string, m middleware.Middleware) (uint32, error) { +func ResolvePluginRegistryID(org, nameOrID string, m apiclient.Middleware) (uint32, error) { if id, err := strconv.ParseUint(nameOrID, 10, 32); err == nil { return uint32(id), nil } @@ -335,7 +335,7 @@ func CompletePluginIDFromRegistryFlag(cmd *cobra.Command, args []string, toCompl if err != nil { return cobra.AppendActiveHelp(nil, "missing org: "+err.Error()), cobra.ShellCompDirectiveNoFileComp } - m := middleware.NewMiddleware(common.NewAPI()) + m := apiclient.NewMiddleware(common.NewAPI()) registryID, err := ResolvePluginRegistryID(org, registryStr, m) if err != nil { return cobra.AppendActiveHelp(nil, "failed to resolve registry: "+err.Error()), cobra.ShellCompDirectiveNoFileComp @@ -369,7 +369,7 @@ func CompletePluginVersionID(cmd *cobra.Command, args []string, toComplete strin if err != nil { return cobra.AppendActiveHelp(nil, "missing org: "+err.Error()), cobra.ShellCompDirectiveNoFileComp } - m := middleware.NewMiddleware(common.NewAPI()) + m := apiclient.NewMiddleware(common.NewAPI()) registryID, err := ResolvePluginRegistryID(org, registryStr, m) if err != nil { return cobra.AppendActiveHelp(nil, "failed to resolve registry: "+err.Error()), cobra.ShellCompDirectiveNoFileComp @@ -408,7 +408,7 @@ func CompleteRegistryPluginID(cmd *cobra.Command, args []string, toComplete stri return cobra.AppendActiveHelp(nil, "missing org: "+err.Error()), cobra.ShellCompDirectiveNoFileComp } - m := middleware.NewMiddleware(common.NewAPI()) + m := apiclient.NewMiddleware(common.NewAPI()) registryID, err := ResolvePluginRegistryID(org, args[0], m) if err != nil { return cobra.AppendActiveHelp(nil, "failed to resolve registry: "+err.Error()), cobra.ShellCompDirectiveNoFileComp @@ -435,7 +435,7 @@ func CompleteRegistryPluginID(cmd *cobra.Command, args []string, toComplete stri } // ResolveRegistryPluginID resolves a numeric ID or name to a plugin ID within a registry. -func ResolveRegistryPluginID(org string, registryID uint32, nameOrID string, m middleware.Middleware) (uint32, error) { +func ResolveRegistryPluginID(org string, registryID uint32, nameOrID string, m apiclient.Middleware) (uint32, error) { if id, err := strconv.ParseUint(nameOrID, 10, 32); err == nil { return uint32(id), nil } diff --git a/internal/cyargs/stackforms_input.go b/internal/cyargs/stackforms_input.go index 297aa9102..ca3d981d4 100644 --- a/internal/cyargs/stackforms_input.go +++ b/internal/cyargs/stackforms_input.go @@ -4,23 +4,20 @@ import ( "encoding/json" "fmt" "io" - "log" + "log/slog" "os" "slices" "strconv" "strings" "dario.cat/mergo" - "github.com/pkg/errors" "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" + "github.com/cycloidio/cycloid-cli/cmd/common" + "github.com/cycloidio/cycloid-cli/gen/models" ) -var ( - StackformsEnvVarName = "CY_STACKFORMS_VARS" -) +var StackformsEnvVarName = "CY_STACKFORMS_VARS" func AddStackFormsInputFlags(cmd *cobra.Command) { cmd.Flags().StringArrayP("json-file", "f", []string{}, "path to a JSON file containing Stackform input. Can be '-' to read from stdin. This flag can be set multiple times.") @@ -58,7 +55,7 @@ func GetStackformsVars(cmd *cobra.Command, defaults models.FormVariables) (model closeErr := tempFile.Close() rmErr := os.Remove(tempFile.Name()) if closeErr != nil || rmErr != nil { - log.Fatalf("failed to purge temp file with stdin content: %s: %s", closeErr, rmErr) + slog.Error("failed to purge temp file with stdin content", slog.Any("close_err", closeErr), slog.Any("rm_err", rmErr)) } }() @@ -81,7 +78,7 @@ func GetStackformsVars(cmd *cobra.Command, defaults models.FormVariables) (model } jsonFromEnv, ok := os.LookupEnv(StackformsEnvVarName) - var varsFromEnv = make(models.FormVariables) + varsFromEnv := make(models.FormVariables) if ok { decoder := json.NewDecoder(strings.NewReader(jsonFromEnv)) err := decoder.Decode(&varsFromEnv) @@ -101,7 +98,7 @@ func GetStackformsVars(cmd *cobra.Command, defaults models.FormVariables) (model } if output == nil { - return nil, errors.New("invalid user input: stackforms vars must not be empty.") + return nil, fmt.Errorf("invalid user input: stackforms vars must not be empty") } return output, nil @@ -110,7 +107,7 @@ func GetStackformsVars(cmd *cobra.Command, defaults models.FormVariables) (model // MergeStackformsVars will parse and merge all variables inputs in the following order of // precedence: // file < jsonString < keyValueField -func MergeStackformsVars(defaults models.FormVariables, envVars models.FormVariables, jsonFiles, jsonStrings []string, keyValueField map[string]string) (models.FormVariables, error) { +func MergeStackformsVars(defaults, envVars models.FormVariables, jsonFiles, jsonStrings []string, keyValueField map[string]string) (models.FormVariables, error) { if defaults == nil { defaults = make(models.FormVariables) } @@ -152,7 +149,7 @@ func MergeStackformsVars(defaults models.FormVariables, envVars models.FormVaria // MergeJSONFileVars will read and merge the Stackforms vars from the `json-file` arg func MergeJSONFileVars(jsonFiles []string) (models.FormVariables, error) { - var output = make(models.FormVariables) + output := make(models.FormVariables) for _, filename := range jsonFiles { var decoder *json.Decoder @@ -165,7 +162,7 @@ func MergeJSONFileVars(jsonFiles []string) (models.FormVariables, error) { decoder = json.NewDecoder(reader) for { - var extractedVars = make(models.FormVariables) + extractedVars := make(models.FormVariables) err := decoder.Decode(&extractedVars) if err == io.EOF { break @@ -185,13 +182,13 @@ func MergeJSONFileVars(jsonFiles []string) (models.FormVariables, error) { // MergeJSONVars expect an array of valid JSON string as stackforms input and return a models.FormVariables func MergeJSONVars(jsonVars []string) (models.FormVariables, error) { - var output = make(models.FormVariables) + output := make(models.FormVariables) for _, jsonString := range jsonVars { if jsonString == "" { continue } - var extractedVars = make(models.FormVariables) + extractedVars := make(models.FormVariables) err := json.Unmarshal([]byte(jsonString), &extractedVars) if err != nil { @@ -208,13 +205,13 @@ func MergeJSONVars(jsonVars []string) (models.FormVariables, error) { // UpdateFormVar will take a Stackform variable ref in the format section.group.var // and update its value. The value is passed as string but can be any valid 'JSON' type. -func UpdateFormVar(field string, value string, vars models.FormVariables) error { +func UpdateFormVar(field, value string, vars models.FormVariables) error { keys := strings.Split(field, ".") if len(keys) != 3 { - return errors.New("key=val update failed, you can only update a value using `section.group.var=value` syntax") + return fmt.Errorf("key=val update failed, you can only update a value using `section.group.var=value` syntax") } - var section, group, key = keys[0], keys[1], keys[2] + section, group, key := keys[0], keys[1], keys[2] if vars == nil { vars = models.FormVariables{section: {group: {key: nil}}} @@ -240,7 +237,7 @@ func UpdateFormVar(field string, value string, vars models.FormVariables) error var data any err := json.Unmarshal([]byte(trimmedValue), &data) if err != nil { - return errors.Wrapf(err, "invalid JSON value in key=val update with value %q", trimmedValue) + return fmt.Errorf("invalid JSON value in key=val update with value %q: %w", trimmedValue, err) } vars[section][group][key] = data diff --git a/internal/cyargs/stackforms_input_test.go b/internal/cyargs/stackforms_input_test.go deleted file mode 100644 index 0c3511fb6..000000000 --- a/internal/cyargs/stackforms_input_test.go +++ /dev/null @@ -1,215 +0,0 @@ -package cyargs_test - -import ( - "encoding/json" - "os" - "testing" - - "github.com/spf13/cobra" - "github.com/stretchr/testify/assert" - - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/internal/cyargs" -) - -func TestGetStackformsVars(t *testing.T) { - // vars - anyArray := []any{"string", 1, 1.1, true, []string{"hello"}, map[string]string{"hello": "world"}} - anyMap := map[string]any{ - "string": "string", - "int": 1, - "float": 1.1, - "bool": true, - "array": anyArray, - "map": map[string]any{ - "hello": "world", - }, - } - expected := models.FormVariables{ - "section": { - "group": { - "string": "string", - "int": 1, - "float": 1.1, - "bool": true, - "array": anyArray, - "map": anyMap, - }, - }, - } - expectedJSON, err := json.Marshal(expected) - if err != nil { - t.Errorf("failed setup for test, failed to encode expected value '%v' to json: %s", expected, err) - } - - t.Run("VarsStdin", func(t *testing.T) { - cmd := &cobra.Command{} - cyargs.AddStackFormsInputFlags(cmd) - - tempFile, err := os.CreateTemp("", "json-test") - if err != nil { - t.Errorf("failed to setup test, cannot create temp file: %s", err) - } - defer os.Remove(tempFile.Name()) - - _, err = tempFile.Write(expectedJSON) - if err != nil { - t.Errorf("failed to setup test, cannot write to test file %s: %s", tempFile.Name(), err) - } - - _, err = tempFile.Seek(0, 0) - if err != nil { - t.Errorf("failed to setup test, cannot change offset in file reader: %s", err) - } - - oldStdin := os.Stdin - defer func() { os.Stdin = oldStdin }() - - os.Stdin = tempFile - - cmd.ParseFlags([]string{ - "--json-file", "-", - }) - - var defaults = make(models.FormVariables) - output, err := cyargs.GetStackformsVars(cmd, defaults) - if err != nil { - t.Errorf("stackform var parsing failed: %s", err) - } - - gotJSON, err := json.Marshal(output) - if err != nil { - t.Errorf("failed to serialize json output '%v': %s", &output, err) - } - assert.Equal(t, string(expectedJSON), string(gotJSON), "should be equal") - }) - - t.Run("EmptyDefaultsEmptyVars", func(t *testing.T) { - cmd := &cobra.Command{} - cyargs.AddStackFormsInputFlags(cmd) - - var defaults = make(models.FormVariables) - output, err := cyargs.GetStackformsVars(cmd, defaults) - if err != nil { - t.Errorf("Empty default should work: %s", err) - } - - assert.Equal(t, defaults, output, "should be empty") - }) - - t.Run("EnvVar", func(t *testing.T) { - cmd := &cobra.Command{} - cyargs.AddStackFormsInputFlags(cmd) - - os.Setenv(cyargs.StackformsEnvVarName, string(expectedJSON)) - defer os.Unsetenv(cyargs.StackformsEnvVarName) - var defaults = make(models.FormVariables) - output, err := cyargs.GetStackformsVars(cmd, defaults) - if err != nil { - t.Errorf("Empty default should work: %s", err) - } - - gotJSON, err := json.Marshal(output) - if err != nil { - t.Errorf("failed to serialize json output '%v': %s", &output, err) - } - assert.Equal(t, expectedJSON, gotJSON, "should be equal") - }) - - t.Run("VarsJSON", func(t *testing.T) { - cmd := &cobra.Command{} - cyargs.AddStackFormsInputFlags(cmd) - - cmd.ParseFlags([]string{ - "--json-vars", string(expectedJSON), - }) - - var defaults = make(models.FormVariables) - output, err := cyargs.GetStackformsVars(cmd, defaults) - if err != nil { - t.Errorf("Empty default should work: %s", err) - } - - gotJSON, err := json.Marshal(output) - if err != nil { - t.Errorf("failed to serialize json output '%v': %s", &output, err) - } - assert.Equal(t, string(expectedJSON), string(gotJSON), "should be equal") - }) - - t.Run("VarsFile", func(t *testing.T) { - cmd := &cobra.Command{} - cyargs.AddStackFormsInputFlags(cmd) - - tempFile, err := os.CreateTemp("", "json-test") - if err != nil { - t.Errorf("failed to setup test, cannot create temp file: %s", err) - } - defer os.Remove(tempFile.Name()) - - _, err = tempFile.Write(expectedJSON) - if err != nil { - t.Errorf("failed to setup test, cannot write to test file %s: %s", tempFile.Name(), err) - } - - cmd.ParseFlags([]string{ - "--json-file", tempFile.Name(), - }) - - var defaults = make(models.FormVariables) - output, err := cyargs.GetStackformsVars(cmd, defaults) - if err != nil { - t.Errorf("Empty default should work: %s", err) - } - - gotJSON, err := json.Marshal(output) - if err != nil { - t.Errorf("failed to serialize json output '%v': %s", &output, err) - } - assert.Equal(t, string(expectedJSON), string(gotJSON), "should be equal") - }) - - t.Run("VarFlag", func(t *testing.T) { - cmd := &cobra.Command{} - cyargs.AddStackFormsInputFlags(cmd) - - cmd.ParseFlags([]string{ - "--var", `types.string.double_quote="1"`, - "--var", `types.string.single_quote='1'`, - "--var", `types.float.no_quote=1`, - "--var", `types.boolean.no_quote=true`, - "--var", `types.array.no_quote=["string", "hello_there"]`, - "--var", `types.map.no_quote={"string": "hello_there"}`, - }) - - var defaults = make(models.FormVariables) - parsedVars, err := cyargs.GetStackformsVars(cmd, defaults) - if err != nil { - t.Errorf("Empty default should work: %s", err) - } - - value, ok := parsedVars["types"]["string"]["double_quote"].(string) - assert.True(t, ok, "type cast to string should be okay") - assert.Equal(t, "1", value, "the output should be a string 1 with no quotes") - - value, ok = parsedVars["types"]["string"]["single_quote"].(string) - assert.True(t, ok, "type cast to string should be okay") - assert.Equal(t, "1", value, "the output should be a string 1 with no quotes") - - valueFloat, ok := parsedVars["types"]["float"]["no_quote"].(float64) - assert.True(t, ok, "type cast to float should be okay") - assert.Equal(t, 1.0, valueFloat, "the output should be a float") - - valueBool, ok := parsedVars["types"]["boolean"]["no_quote"].(bool) - assert.True(t, ok, "type cast to boolean should be okay") - assert.Equal(t, true, valueBool, "the output should be a bool") - - valueArray, ok := parsedVars["types"]["array"]["no_quote"] - assert.True(t, ok, "type cast to array should be okay") - assert.Equal(t, []any{"string", "hello_there"}, valueArray, "the output should be a array") - - valueMap, ok := parsedVars["types"]["map"]["no_quote"] - assert.True(t, ok, "type cast to map should be okay") - assert.Equal(t, map[string]any{"string": "hello_there"}, valueMap, "the output should be a map") - }) -} diff --git a/internal/cyargs/stacks.go b/internal/cyargs/stacks.go index 54579c295..81a52b89c 100644 --- a/internal/cyargs/stacks.go +++ b/internal/cyargs/stacks.go @@ -6,9 +6,9 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" - "github.com/cycloidio/cycloid-cli/internal/ptr" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" + "github.com/cycloidio/cycloid-cli/utils/ptr" ) func ValidateForms(cmd *cobra.Command, args []string, toComplete string) ([]cobra.Completion, cobra.ShellCompDirective) { @@ -24,7 +24,7 @@ func AddStackRefFlag(cmd *cobra.Command) string { func CompleteStackRef(cmd *cobra.Command, args []string, toComplete string) ([]cobra.Completion, cobra.ShellCompDirective) { api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) org, err := GetOrg(cmd) if err != nil { @@ -38,7 +38,7 @@ func CompleteStackRef(cmd *cobra.Command, args []string, toComplete string) ([]c cobra.ShellCompDirectiveNoFileComp } - var stackRefs = make([]string, len(stacks)) + stackRefs := make([]string, len(stacks)) for index, stack := range stacks { if stack.Ref != nil && strings.HasPrefix(*stack.Ref, toComplete) { desc := *stack.Name @@ -91,7 +91,7 @@ func CompleteBlueprint(cmd *cobra.Command, args []string, toComplete string) ([] } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) blueprints, _, err := m.ListBlueprints(org) if err != nil { @@ -99,7 +99,7 @@ func CompleteBlueprint(cmd *cobra.Command, args []string, toComplete string) ([] cobra.ShellCompDirectiveNoFileComp } - var completions = make([]cobra.Completion, len(blueprints)) + completions := make([]cobra.Completion, len(blueprints)) for index, blueprint := range blueprints { if blueprint.Ref != nil && strings.HasPrefix(*blueprint.Ref, toComplete) { completions[index] = cobra.CompletionWithDesc(*blueprint.Ref, *blueprint.Name+" - "+blueprint.Description) @@ -194,11 +194,11 @@ func GetStackVersionFlags(cmd *cobra.Command) (tag, branch, hash string, err err // 4. Bare value — calls m.ListStackVersions to resolve; requires a non-empty stackRef. // Precedence: tag > branch > commit-hash-prefix (min 7 chars). // Collision (same name matches both tag and branch) → error with disambiguation hint. -func ResolveStackVersionArg(cmd *cobra.Command, m middleware.Middleware, org, stackRef string) (tag, branch, hash string, err error) { +func ResolveStackVersionArg(cmd *cobra.Command, m apiclient.Middleware, org, stackRef string) (tag, branch, hash string, err error) { // Legacy flags take priority; Cobra already emits the deprecation notice. tag, branch, hash, err = GetStackVersionFlags(cmd) if err != nil || tag != "" || branch != "" || hash != "" { - return + return tag, branch, hash, err } v, err := cmd.Flags().GetString("stack-version") @@ -285,7 +285,7 @@ func CompleteStackVersionUnified(cmd *cobra.Command, args []string, toComplete s } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) versions, _, err := m.ListStackVersions(org, stackRef) if err != nil { @@ -347,7 +347,7 @@ func resolveStackRefForCompletion(cmd *cobra.Command, org string) string { } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) currentComponent, _, errGet := m.GetComponent(org, project, env, component) if errGet == nil && currentComponent.ServiceCatalog != nil && currentComponent.ServiceCatalog.Ref != nil { return *currentComponent.ServiceCatalog.Ref @@ -355,7 +355,7 @@ func resolveStackRefForCompletion(cmd *cobra.Command, org string) string { return "" } -func versionDesc(ver *middleware.StackVersion) string { +func versionDesc(ver *apiclient.StackVersion) string { desc := "" if ver.CommitHash != nil { desc = shortHash(*ver.CommitHash) @@ -390,7 +390,7 @@ func CompleteCatalogRepoCommitHash(cmd *cobra.Command, args []string, toComplete } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) versions, _, err := m.ListStackVersions(org, stackRef) if err != nil { @@ -433,7 +433,7 @@ func CompleteStackVersionTag(cmd *cobra.Command, args []string, toComplete strin } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) versions, _, err := m.ListStackVersions(org, stackRef) if err != nil { @@ -465,7 +465,7 @@ func CompleteStackVersionBranch(cmd *cobra.Command, args []string, toComplete st } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) versions, _, err := m.ListStackVersions(org, stackRef) if err != nil { diff --git a/internal/cyargs/stacks_test.go b/internal/cyargs/stacks_test.go deleted file mode 100644 index 09cdae514..000000000 --- a/internal/cyargs/stacks_test.go +++ /dev/null @@ -1,183 +0,0 @@ -package cyargs_test - -import ( - "net/http" - "testing" - - "github.com/spf13/cobra" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" - "github.com/cycloidio/cycloid-cli/internal/cyargs" - "github.com/cycloidio/cycloid-cli/internal/ptr" -) - -// stubMiddleware implements only ListStackVersions; all other methods panic. -type stubMiddleware struct { - middleware.Middleware - versions []*middleware.StackVersion - err error -} - -func (s *stubMiddleware) ListStackVersions(org, ref string, _ ...middleware.LHSFilter) ([]*middleware.StackVersion, *http.Response, error) { - return s.versions, nil, s.err -} - -func newCmd() *cobra.Command { - cmd := &cobra.Command{} - cyargs.AddStackVersionFlags(cmd) - return cmd -} - -func makeVersion(name, vType, commitHash string, isLatest bool) *middleware.StackVersion { - return &middleware.StackVersion{ - Name: ptr.Ptr(name), - Type: ptr.Ptr(vType), - CommitHash: ptr.Ptr(commitHash), - IsLatest: ptr.Ptr(isLatest), - } -} - -func TestResolveStackVersionArg(t *testing.T) { - tagVersion := makeVersion("v1.0.0", "tag", "aabbccdd1234567", true) - branchVersion := makeVersion("main", "branch", "deadbeef1234567", false) - ambigTag := makeVersion("release", "tag", "1111111111111111", false) - ambigBranch := makeVersion("release", "branch", "2222222222222222", false) - - canned := []*middleware.StackVersion{tagVersion, branchVersion, ambigTag, ambigBranch} - - m := &stubMiddleware{versions: canned} - const org = "myorg" - const stackRef = "myorg:mystack" - - cases := []struct { - name string - args []string - wantTag string - wantBranch string - wantHash string - wantErr string - }{ - { - name: "empty returns empty triple", - args: nil, - wantTag: "", wantBranch: "", wantHash: "", - }, - { - name: "tag prefix resolved client-side", - args: []string{"--stack-version", "tag:v1.0.0"}, - wantTag: "v1.0.0", - }, - { - name: "branch prefix resolved client-side", - args: []string{"--stack-version", "branch:main"}, - wantBranch: "main", - }, - { - name: "sha prefix resolved client-side", - args: []string{"--stack-version", "sha:deadbeef"}, - wantHash: "deadbeef", - }, - { - name: "commit prefix alias resolved client-side", - args: []string{"--stack-version", "commit:deadbeef"}, - wantHash: "deadbeef", - }, - { - name: "bare value resolves to tag (tag wins over branch)", - args: []string{"--stack-version", "v1.0.0"}, - wantTag: "v1.0.0", - }, - { - name: "bare value resolves to branch when no tag matches", - args: []string{"--stack-version", "main"}, - wantBranch: "main", - }, - { - name: "bare short hash resolves to commit", - args: []string{"--stack-version", "aabbccd"}, - wantHash: "aabbccdd1234567", - }, - { - name: "collision between tag and branch errors with hint", - args: []string{"--stack-version", "release"}, - wantErr: "ambiguous version", - }, - { - name: "unknown bare value returns not-found error", - args: []string{"--stack-version", "nonexistent"}, - wantErr: "not found", - }, - { - name: "short hash under 7 chars is not matched as commit", - args: []string{"--stack-version", "aabbcc"}, - wantErr: "not found", - }, - } - - for _, tc := range cases { - t.Run(tc.name, func(t *testing.T) { - cmd := newCmd() - if tc.args != nil { - require.NoError(t, cmd.ParseFlags(tc.args)) - } - - tag, branch, hash, err := cyargs.ResolveStackVersionArg(cmd, m, org, stackRef) - - if tc.wantErr != "" { - require.Error(t, err) - assert.Contains(t, err.Error(), tc.wantErr) - return - } - - require.NoError(t, err) - assert.Equal(t, tc.wantTag, tag) - assert.Equal(t, tc.wantBranch, branch) - assert.Equal(t, tc.wantHash, hash) - }) - } - - t.Run("legacy --stack-tag bypasses resolution", func(t *testing.T) { - noCallMiddleware := &stubMiddleware{} // panics if ListStackVersions called - cmd := newCmd() - require.NoError(t, cmd.ParseFlags([]string{"--stack-tag", "v2.0.0"})) - - tag, branch, hash, err := cyargs.ResolveStackVersionArg(cmd, noCallMiddleware, org, stackRef) - require.NoError(t, err) - assert.Equal(t, "v2.0.0", tag) - assert.Empty(t, branch) - assert.Empty(t, hash) - }) - - t.Run("legacy --stack-branch bypasses resolution", func(t *testing.T) { - noCallMiddleware := &stubMiddleware{} - cmd := newCmd() - require.NoError(t, cmd.ParseFlags([]string{"--stack-branch", "dev"})) - - tag, branch, hash, err := cyargs.ResolveStackVersionArg(cmd, noCallMiddleware, org, stackRef) - require.NoError(t, err) - assert.Empty(t, tag) - assert.Equal(t, "dev", branch) - assert.Empty(t, hash) - }) - - t.Run("tag prefix with no API call (noCallMiddleware should not panic)", func(t *testing.T) { - noCallMiddleware := &stubMiddleware{} - cmd := newCmd() - require.NoError(t, cmd.ParseFlags([]string{"--stack-version", "tag:v1.0.0"})) - - tag, _, _, err := cyargs.ResolveStackVersionArg(cmd, noCallMiddleware, org, stackRef) - require.NoError(t, err) - assert.Equal(t, "v1.0.0", tag) - }) - - t.Run("bare value without stackRef returns helpful error", func(t *testing.T) { - cmd := newCmd() - require.NoError(t, cmd.ParseFlags([]string{"--stack-version", "main"})) - - _, _, _, err := cyargs.ResolveStackVersionArg(cmd, m, org, "") - require.Error(t, err) - assert.Contains(t, err.Error(), "stack reference") - }) -} diff --git a/internal/cyargs/teams.go b/internal/cyargs/teams.go index a7aac2fd7..df2b956fa 100644 --- a/internal/cyargs/teams.go +++ b/internal/cyargs/teams.go @@ -8,10 +8,10 @@ import ( "github.com/spf13/cobra" - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" - "github.com/cycloidio/cycloid-cli/internal/ptr" + "github.com/cycloidio/cycloid-cli/cmd/apiclient" + "github.com/cycloidio/cycloid-cli/cmd/common" + "github.com/cycloidio/cycloid-cli/gen/models" + "github.com/cycloidio/cycloid-cli/utils/ptr" ) const ( @@ -46,7 +46,7 @@ func CompleteTeam(cmd *cobra.Command, args []string, toComplete string) ([]cobra orderBy, _ := GetTeamOrderBy(cmd) api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) teams, _, err := m.ListTeams(org, &name, createdAt, &memberID, orderBy) if err != nil { @@ -91,7 +91,7 @@ func TeamMembersCompletionHelper(cmd *cobra.Command) ([]*models.MemberTeam, erro } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) teams, _, err := m.ListTeamMembers(org, team) if err != nil { @@ -277,17 +277,17 @@ func AddTeamOrderBy(cmd *cobra.Command) string { return teamOrderByFlagName } -func GetTeamOrderBy(cmd *cobra.Command) (*middleware.TeamOrderByParam, error) { +func GetTeamOrderBy(cmd *cobra.Command) (*apiclient.TeamOrderByParam, error) { orderByStr, err := cmd.Flags().GetString(teamOrderByFlagName) if err != nil { - return &middleware.Ascending, err + return &apiclient.Ascending, err } switch orderByStr { case "desc", "descending": - return &middleware.Descending, nil + return &apiclient.Descending, nil default: - return &middleware.Ascending, nil + return &apiclient.Ascending, nil } } @@ -304,7 +304,7 @@ func CompleteTeamOwnerCanonical(cmd *cobra.Command, args []string, toComplete st } api := common.NewAPI() - m := middleware.NewMiddleware(api) + m := apiclient.NewMiddleware(api) users, _, err := m.ListMembers(org) if err != nil { diff --git a/internal/cyout/errors.go b/internal/cyout/errors.go index e5ac1223b..015c36678 100644 --- a/internal/cyout/errors.go +++ b/internal/cyout/errors.go @@ -9,10 +9,10 @@ import ( "github.com/spf13/cobra" "github.com/spf13/pflag" - "github.com/cycloidio/cycloid-cli/client/models" + "github.com/cycloidio/cycloid-cli/gen/models" ) -// apiErrorInfo is satisfied by *middleware.APIResponseError. +// apiErrorInfo is satisfied by *apiclient.APIResponseError. // Defined locally to avoid importing cmd/cycloid/middleware from internal/. type apiErrorInfo interface { error diff --git a/internal/cyout/errors_test.go b/internal/cyout/errors_test.go deleted file mode 100644 index 46ee004ce..000000000 --- a/internal/cyout/errors_test.go +++ /dev/null @@ -1,166 +0,0 @@ -package cyout - -import ( - "bytes" - "errors" - "testing" - - "github.com/spf13/cobra" - "github.com/stretchr/testify/assert" - - "github.com/cycloidio/cycloid-cli/client/models" -) - -// fakeAPIError implements apiErrorInfo + apiErrorPayloader for tests. -type fakeAPIError struct { - statusCode int - method string - path string - reqBody []byte - respBody []byte - payload *models.ErrorPayload -} - -func (e *fakeAPIError) Error() string { return "fake api error" } -func (e *fakeAPIError) HTTPStatusCode() int { return e.statusCode } -func (e *fakeAPIError) HTTPRequestMethod() string { return e.method } -func (e *fakeAPIError) HTTPRequestPath() string { return e.path } -func (e *fakeAPIError) HTTPRequestBody() []byte { return e.reqBody } -func (e *fakeAPIError) HTTPResponseBody() []byte { return e.respBody } -func (e *fakeAPIError) GetPayload() *models.ErrorPayload { return e.payload } - -func ptrString(s string) *string { return &s } - -func newTestCmd() *cobra.Command { - cmd := &cobra.Command{Use: "test"} - var buf bytes.Buffer - cmd.SetErr(&buf) - return cmd -} - -func captureError(cmd *cobra.Command, err error) string { - var buf bytes.Buffer - cmd.SetErr(&buf) - printError(cmd, err) - return buf.String() -} - -func TestPrintError_LocalError(t *testing.T) { - cmd := newTestCmd() - out := captureError(cmd, errors.New("missing flag: --project")) - // Local error: only command hint (no "API Error" line), main.go handles the Error: line - assert.NotContains(t, out, "API Error") -} - -func TestPrintError_APIErrorWithPayload(t *testing.T) { - cmd := newTestCmd() - err := &fakeAPIError{ - statusCode: 422, - method: "GET", - path: "/organizations", - respBody: []byte(`{"errors":[{"code":"Invalid","message":"This endpoint cannot be used with API Key"}]}`), - payload: &models.ErrorPayload{ - Errors: []*models.ErrorDetailsItem{ - {Code: ptrString("Invalid"), Message: ptrString("This endpoint cannot be used with API Key")}, - }, - }, - } - out := captureError(cmd, err) - assert.Contains(t, out, "API Error 422") - assert.Contains(t, out, "GET") - assert.Contains(t, out, "/organizations") - assert.Contains(t, out, "Invalid") - assert.Contains(t, out, "This endpoint cannot be used with API Key") -} - -func TestPrintError_APIErrorMultipleErrors(t *testing.T) { - cmd := newTestCmd() - err := &fakeAPIError{ - statusCode: 422, - method: "POST", - path: "/organizations/myorg/projects", - payload: &models.ErrorPayload{ - Errors: []*models.ErrorDetailsItem{ - {Code: ptrString("RequiredField"), Message: ptrString("name: must not be empty")}, - {Code: ptrString("InvalidType"), Message: ptrString("color: must be a valid hex color")}, - }, - }, - } - out := captureError(cmd, err) - assert.Contains(t, out, "RequiredField") - assert.Contains(t, out, "name: must not be empty") - assert.Contains(t, out, "InvalidType") - assert.Contains(t, out, "color: must be a valid hex color") -} - -func TestPrintError_APIErrorWithDetails(t *testing.T) { - cmd := newTestCmd() - err := &fakeAPIError{ - statusCode: 422, - method: "POST", - path: "/organizations/myorg/projects", - payload: &models.ErrorPayload{ - Errors: []*models.ErrorDetailsItem{ - { - Code: ptrString("InvalidValue"), - Message: ptrString("invalid color"), - Details: []string{"accepted values are #RRGGBB hex codes"}, - }, - }, - }, - } - out := captureError(cmd, err) - assert.Contains(t, out, "invalid color") - assert.Contains(t, out, "accepted values are #RRGGBB hex codes") -} - -func TestPrintError_APIErrorWithRequestBody(t *testing.T) { - cmd := newTestCmd() - err := &fakeAPIError{ - statusCode: 422, - method: "POST", - path: "/organizations/myorg/credentials", - reqBody: []byte(`{"name":"my-cred","ssh_key":"[REDACTED]"}`), - payload: &models.ErrorPayload{ - Errors: []*models.ErrorDetailsItem{ - {Code: ptrString("InvalidField"), Message: ptrString("unsupported type")}, - }, - }, - } - out := captureError(cmd, err) - assert.Contains(t, out, "Body:") - assert.Contains(t, out, "my-cred") - assert.Contains(t, out, "[REDACTED]") -} - -func TestPrintError_APIErrorRawBodyFallback(t *testing.T) { - // No structured payload — falls back to raw response body - cmd := newTestCmd() - err := &fakeAPIError{ - statusCode: 503, - method: "GET", - path: "/health", - respBody: []byte("Service Unavailable"), - } - out := captureError(cmd, err) - assert.Contains(t, out, "API Error 503") - assert.Contains(t, out, "Service Unavailable") -} - -func TestPrintError_APIErrorWithRequestID(t *testing.T) { - cmd := newTestCmd() - err := &fakeAPIError{ - statusCode: 500, - method: "GET", - path: "/organizations", - payload: &models.ErrorPayload{ - RequestID: "550e8400-e29b-41d4-a716-446655440000", - Errors: []*models.ErrorDetailsItem{ - {Code: ptrString("InternalError"), Message: ptrString("unexpected failure")}, - }, - }, - } - out := captureError(cmd, err) - assert.Contains(t, out, "Request-ID") - assert.Contains(t, out, "550e8400-e29b-41d4-a716-446655440000") -} diff --git a/internal/ptr/ptr.go b/internal/ptr/ptr.go deleted file mode 100644 index 238b6776e..000000000 --- a/internal/ptr/ptr.go +++ /dev/null @@ -1,13 +0,0 @@ -package ptr - -// Ptr returns a pointer address of given value -func Ptr[V any](v V) *V { return &v } - -// Value returns a value of given pointer -func Value[V any](v *V) V { - if v == nil { - var noop V - return noop - } - return *v -} diff --git a/internal/testcfg/config.go b/internal/testcfg/config.go deleted file mode 100644 index f54e537b0..000000000 --- a/internal/testcfg/config.go +++ /dev/null @@ -1,384 +0,0 @@ -package testcfg - -import ( - "errors" - "fmt" - "log" - "os" - "strconv" - "strings" - "time" - - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" - "github.com/cycloidio/cycloid-cli/internal/ptr" -) - -type Config struct { - APIKey string - APIUrl string - Org string - // GitCredential models.Credential - ConfigRepo *models.ConfigRepository - CatalogRepo *models.ServiceCatalogSource - CatalogRepoVersionStacks *middleware.StackVersion - Middleware middleware.Middleware - // Common project to use for tests that require one - Project *models.Project - // Common environment to use for tests that require one - Environment *models.Environment - // Common component to use for tests that require one - Component *models.Component - // Slice containing all functions to exec for cleaning common test resources - cleanupFuncs []func() -} - -func NewConfig(testName string) (*Config, error) { - if len(testName) < 1 { - return nil, fmt.Errorf("testName argument must not be empty") - } - - var ( - localGitSSHKey = strings.Join([]string{ - "-----BEGIN OPENSSH PRIVATE KEY-----", - "b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW", - "QyNTUxOQAAACD8O9mhkl5CAiD0NLeQcoPf1duYHImQlTjOXcCOgHmC+AAAAJjCF9jzwhfY", - "8wAAAAtzc2gtZWQyNTUxOQAAACD8O9mhkl5CAiD0NLeQcoPf1duYHImQlTjOXcCOgHmC+A", - "AAAEC0ryBZ1uJQ2drmjsO+WpsC2E/5SWheJD/r8+Q4LghWxfw72aGSXkICIPQ0t5Byg9/V", - "25gciZCVOM5dwI6AeYL4AAAAE2N5Y2xvaWRAZXhhbXBsZS5jb20BAg==", - "-----END OPENSSH PRIVATE KEY-----", - }, "\n") - localGitCredential = "local-git" - dockerIPAM = EnvDefault("DOCKER_IPAM", "192.168.10") - configRepoName = "cli-test-config" - configRepository = "cli-test-config" - configRepoURL = fmt.Sprintf("git@%s.7:/git-server/repos/backend-test-config-repo.git", dockerIPAM) - configRepoBranch = "master" - isDefault = true - gitCred = "github" - catalogRepo = "cli-test-stacks" - catalogRepoName = "CLI test catalog" - catalogRepoURL = "https://github.com/cycloidio/cycloid-cli-test-catalog.git" - catalogRepoBranch = "stacks" - defaultStackCanonical = "stack-e2e-stackforms" - defaultStackUseCase = "default" - ) - - var config = &Config{} - config.ConfigRepo = &models.ConfigRepository{ - Name: &configRepoName, - Canonical: &configRepository, - URL: &configRepoURL, - Branch: configRepoBranch, - CredentialCanonical: gitCred, - Default: &isDefault, - } - config.CatalogRepo = &models.ServiceCatalogSource{ - Name: &catalogRepoName, - Canonical: &catalogRepo, - URL: &catalogRepoURL, - Branch: catalogRepoBranch, - CredentialCanonical: gitCred, - } - - provisionAPI, _ := strconv.ParseBool(EnvDefault("CY_TEST_PROVISION_API", "1")) - config.APIUrl = EnvDefault("CY_TEST_API_URL", "http://"+dockerIPAM+".10:3001") - config.Org = EnvDefault("CY_TEST_ROOT_ORG", "cycloid") - licence, ok := os.LookupEnv("API_LICENCE_KEY") - if !ok && provisionAPI { - return config, fmt.Errorf("licence required for provisionning, set it with API_LICENCE_KEY") - } - - // If we provision the api, we will try to login first - if !provisionAPI { - apiKey, ok := os.LookupEnv("CY_TEST_API_KEY") - if !ok { - return config, fmt.Errorf("api key not set in CY_TEST_API_KEY env var") - } - config.APIKey = apiKey - } - - api := common.NewAPI( - common.WithURL(config.APIUrl), - common.WithInsecure(true), - common.WithToken(config.APIKey), - ) - m := middleware.NewMiddleware(api) - config.Middleware = m - - var ( - username = "administrator" - fullName = "administrator" - email = "admin@cycloid.io" - password = "cycloidadmin" - apiKeyCanonical = "admin-" + testName - ) - - if provisionAPI { - // try to login, is successful, console is initialized - init, _, err := m.InitFirstOrg(config.Org, username, fullName, email, password, licence, &apiKeyCanonical) - if err != nil { - return nil, fmt.Errorf("failed to init console: %w", err) - } - - config.APIKey = *init.APIKey - api.Config.Token = *init.APIKey - - // Write the API for the User, we'll look up a better way later - root, err := FindRepoRoot() - if err != nil { - return nil, err - } - - apiKeyEnvFile := strings.Join([]string{ - "CY_API_KEY=" + config.APIKey, - "CY_API_URL=" + config.APIUrl, - "CY_ORG=" + config.Org, - }, "\n") - err = os.WriteFile(root+"/.api_key", []byte(apiKeyEnvFile), 0666) - if err != nil { - return nil, err - } - } - - _, _, err := m.CreateCredential(config.Org, localGitCredential, "ssh", - &models.CredentialRaw{SSHKey: localGitSSHKey}, "", localGitCredential, "", - ) - var apiErr *middleware.APIResponseError - if errors.As(err, &apiErr) { - if apiErr.StatusCode != 409 { - return config, fmt.Errorf("failed to init config repo credential: %w", err) - } - } - - currentConfigRepo, _, err := m.CreateConfigRepository(config.Org, - *config.ConfigRepo.Canonical, *config.ConfigRepo.Canonical, *config.ConfigRepo.URL, - config.ConfigRepo.Branch, localGitCredential, *config.ConfigRepo.Default, - ) - if errors.As(err, &apiErr) { - var getErr error - currentConfigRepo, _, getErr = m.GetConfigRepository(config.Org, configRepository) - if apiErr.StatusCode != 409 || getErr != nil { - return config, fmt.Errorf("failed to setup config repo: %w%w", err, getErr) - } - } - - config.ConfigRepo = currentConfigRepo - - _, _, err = m.CreateCatalogRepository(config.Org, *config.CatalogRepo.Canonical, - *config.CatalogRepo.URL, config.CatalogRepo.Branch, "", "local", "", - ) - if errors.As(err, &apiErr) { - if apiErr.StatusCode != 409 { - return config, fmt.Errorf("failed to setup catalog repo: %w", err) - } - } - - _, _, err = m.RefreshCatalogRepository(config.Org, *config.CatalogRepo.Canonical) - if err != nil { - return config, fmt.Errorf("failed to refresh catalog repo: %w", err) - } - - stackRef := config.Org + ":" + defaultStackCanonical - stackVersions, _, err := m.ListStackVersions(config.Org, stackRef) - if err != nil { - return config, fmt.Errorf("failed to list stack versions: %w", err) - } - - for _, v := range stackVersions { - if ptr.Value(v.Name) == catalogRepoBranch { - config.CatalogRepoVersionStacks = v - break - } - } - if config.CatalogRepoVersionStacks == nil { - return config, fmt.Errorf("failed to find latest catalog repo version after refresh") - } - - project, err := config.NewTestProject("common") - if err != nil { - return config, err - } - config.Project = project - - environment, err := config.NewTestEnv("common", *project.Canonical) - if err != nil { - return config, err - } - config.Environment = environment - - component, err := config.NewTestComponent( - *project.Canonical, *environment.Canonical, "common", stackRef, defaultStackUseCase, "", "", ptr.Value(config.CatalogRepoVersionStacks.CommitHash), nil, - ) - if err != nil { - return config, err - } - config.Component = component - - stackConfig, _, err := m.GetComponentStackConfig(config.Org, *project.Canonical, *environment.Canonical, *component.Canonical, defaultStackUseCase, "", "", ptr.Value(config.CatalogRepoVersionStacks.CommitHash)) - if err != nil { - return config, err - } - - vars, err := common.FormUseCaseToFormVars(stackConfig, defaultStackUseCase) - if err != nil { - return config, err - } - common.UpdateMapField("types.tests.string", RandomCanonical("common"), vars) - - return config, nil -} - -// NewTestProject will create a project with a random canonical derived from identifier -// and return the project, the function to defer for its deletion and error. -// The func will always be returned so even if err != nil, defer the func. -func (config *Config) NewTestProject(identifier string) (*models.Project, error) { - var ( - project = RandomCanonical(identifier) - description = "Testing project " + identifier - configRepository = *config.ConfigRepo.Canonical - owner = "" - team = "" - color = "default" - icon = "inventory" - ) - - m := config.Middleware - - out, _, err := m.CreateProject(config.Org, project, project, description, configRepository, owner, team, color, icon) - if err != nil { - return nil, fmt.Errorf("failed to setup test project: %w", err) - } - - config.AppendCleanup(func() { - _, err := m.DeleteProject(config.Org, project, middleware.DeleteOptions{}) - if err != nil { - log.Fatalf("cannot cleanup projet %q for test %q: %v", project, identifier, err) - return - } - }) - - return out, nil -} - -// setupTestProject will create an env with a random canonical derived from identifier -// and return the env, the function to defer for its deletion and error. -// The func will always be returned so even if err != nil, defer the func. -func (config *Config) NewTestEnv(identifier, project string) (*models.Environment, error) { - var ( - env = RandomCanonical(identifier) - envType = "production" - ) - - m := config.Middleware - - body := &models.NewEnvironment{ - Canonical: env, - Name: ptr.Ptr(env), - Type: ptr.Ptr(envType), - } - out, _, err := m.CreateOrgEnv(config.Org, body) - if err != nil { - return nil, fmt.Errorf("failed to setup test environment: %w", err) - } - - if project != "" { - if _, err := m.LinkEnvToProject(config.Org, project, env); err != nil { - return nil, fmt.Errorf("failed to link test environment to project: %w", err) - } - } - - config.AppendCleanup(func() { - if project != "" { - _, _ = m.UnlinkEnvFromProject(config.Org, project, env, middleware.DeleteOptions{}) - } - _, err := m.DeleteOrgEnv(config.Org, env) - if err != nil { - log.Fatalf("cannot cleanup env %q for test %q: %v", env, identifier, err) - return - } - }) - - return out, nil -} - -// setupTestProject will create an component with a random canonical derived from identifier -// and return the component, the function to defer for its deletion and error. -// The func will always be returned so even if err != nil, defer the func. -func (config *Config) NewTestComponent(project, env, identifier, stackRef, useCase, versionTag, versionBranch, versionCommitHash string, inputs models.FormVariables) (*models.Component, error) { - m := config.Middleware - component := RandomCanonical(identifier) - - // Workaround for BE-1344: RefreshCatalogRepository is async — the DB is updated - // immediately but the backend git fetch may not be complete when we try to create a - // component. On a 404 GitObject error, trigger another refresh and retry. - const maxAttempts = 5 - var outComponent *models.Component - var err error - for attempt := range maxAttempts { - if attempt > 0 { - time.Sleep(5 * time.Second) - // Nudge backend to complete git fetch before retrying - _, _, _ = m.RefreshCatalogRepository(config.Org, *config.CatalogRepo.Canonical) - } - outComponent, _, err = m.CreateOrUpdateComponent(config.Org, project, env, - component, "", component, stackRef, versionTag, versionBranch, - versionCommitHash, useCase, "", inputs) - if err == nil { - break - } - var apiErr *middleware.APIResponseError - if !errors.As(err, &apiErr) || apiErr.StatusCode != 404 || - !strings.Contains(err.Error(), "GitObject") { - return nil, err // non-transient error, fail immediately - } - log.Printf("NewTestComponent: attempt %d/%d: transient GitObject error (BE-1344), retrying: %v", - attempt+1, maxAttempts, err) - } - if err != nil { - return nil, err - } - - config.AppendCleanup(func() { - if _, err := m.DeleteComponent(config.Org, project, env, component, middleware.DeleteOptions{}); err != nil { - log.Printf("failed to cleanup component for test %q: %v", identifier, err) - } - }) - - return outComponent, nil -} - -func (config *Config) AppendCleanup(f ...func()) { - config.cleanupFuncs = append(config.cleanupFuncs, f...) -} - -func (config *Config) Cleanup() { - if config == nil { - return - } - - for _, f := range config.cleanupFuncs { - defer f() - } -} - -// NewTestChildOrg is a helper function that create a suborg for a -// specific test and return a function to defer() for its deletion. -func (config *Config) NewTestChildOrg(parent, child string) (func(), error) { - m := config.Middleware - deferFunc := func() { - _, err := m.DeleteOrganization(child) - if err != nil { - log.Fatalf("Failed to delete org %q: %v", child, err) - return - } - } - - _, _, err := m.CreateOrganizationChild(parent, child, nil) - if err != nil { - return deferFunc, fmt.Errorf("failed to create child org %q: %v", child, err) - } - - return deferFunc, nil -} diff --git a/internal/testcfg/helpers.go b/internal/testcfg/helpers.go deleted file mode 100644 index 027e69bfb..000000000 --- a/internal/testcfg/helpers.go +++ /dev/null @@ -1,45 +0,0 @@ -package testcfg - -import ( - "fmt" - "math/rand" - "os" - "path/filepath" - "strings" -) - -func RandomCanonical(baseName string) string { - var size = 4 - var letterRunes = []rune("abcdefghijklmnopqrstuvwxyz") - - b := make([]rune, size) - for i := range b { - b[i] = letterRunes[rand.Intn(len(letterRunes))] - } - return strings.ToLower(baseName) + "-" + string(b) -} - -func EnvDefault(envVar, defaultValue string) string { - if value, ok := os.LookupEnv(envVar); ok { - return value - } - - return defaultValue -} - -func FindRepoRoot() (string, error) { - path := ".git" - for i := 0; true; i++ { - if pwd, err := os.Getwd(); pwd == "/" || err != nil { - return "", fmt.Errorf("failed to find project root we reached /") - } - - testPath := strings.Repeat("../", i) + path - _, err := os.Stat(testPath) - if err == nil { - return filepath.Join(filepath.Dir(testPath)), nil - } - } - - return "", fmt.Errorf("failed for some reason") -} diff --git a/interpolator/formatters/interface.go b/interpolator/formatters/interface.go index c95bcf201..81f3ff1dd 100644 --- a/interpolator/formatters/interface.go +++ b/interpolator/formatters/interface.go @@ -12,12 +12,10 @@ const ( YAMLFormat AvailableFormat = "yaml" ) -var ( - AvailableFormats = [...]AvailableFormat{ - YAMLFormat, - JSONFormat, - } -) +var AvailableFormats = [...]AvailableFormat{ + YAMLFormat, + JSONFormat, +} type Formatter interface { Format(data []any) (string, error) diff --git a/interpolator/formatters/interface_test.go b/interpolator/formatters/interface_test.go deleted file mode 100644 index 873596568..000000000 --- a/interpolator/formatters/interface_test.go +++ /dev/null @@ -1,126 +0,0 @@ -package formatters_test - -import ( - "testing" - - "github.com/stretchr/testify/assert" - - "github.com/cycloidio/cycloid-cli/interpolator/formatters" -) - -func TestFormatter(t *testing.T) { - complexData := []any{map[string]map[string]map[string]map[string]any{ - "one": { - "two": { - "three": { - "array": []string{"one", "two"}, - "map": map[string]string{ - "hello": "world", - }, - "int": 1, - "string": "hello_world", - "string_with_spaces": "hello world", - "string_with_newlines": "---\none\ntwo\nthree\n", - }, - }, - }, - }} - - tcs := []struct { - name string - params map[string][]string - data []any - expect string - allowErr bool - }{ - { - "UseJSONFormatterOk", - map[string][]string{ - "output": {"json"}, - "json_compact": {}, - }, - []any{map[string]string{"hello": "world"}}, - `{"hello":"world"}`, - false, - }, - { - "UseJSONFormatterComplex", - map[string][]string{ - "output": {"json"}, - "json_compact": {}, - }, - complexData, - `{"one":{"two":{"three":{"array":["one","two"],"int":1,"map":{"hello":"world"},"string":"hello_world","string_with_newlines":"---\none\ntwo\nthree\n","string_with_spaces":"hello world"}}}}`, - false, - }, - { - "JSONIndentOk", - map[string][]string{ - "output": {"json"}, - "indent_size": {"2"}, - }, - []any{map[string]string{"hello": "world"}}, - `{ - "hello": "world" -}`, - false, - }, - { - "UseYAMLFormatterOk", - map[string][]string{ - "output": {"yaml"}, - }, - []any{map[string]string{"hello": "world"}}, - "hello: world\n", - false, - }, - { - "UseYAMLFormatterComplex", - map[string][]string{ - "output": {"yaml"}, - "indent_size": {"2"}, - }, - complexData, - `one: - two: - three: - array: - - one - - two - int: 1 - map: - hello: world - string: hello_world - string_with_newlines: | - --- - one - two - three - string_with_spaces: hello world -`, - false, - }, - { - "YAMLIndentSettingsOk", - map[string][]string{ - "output": {"yaml"}, - "indent_size": {"6"}, - }, - []any{map[string]map[string]string{"one": {"two": "hello_world"}}}, - "one:\n two: hello_world\n", - false, - }, - } - - for _, tc := range tcs { - t.Run(tc.name, func(t *testing.T) { - formatter := formatters.New(tc.params) - got, err := formatter.Format(tc.data) - if err != nil && !tc.allowErr { - assert.NoError(t, err, "formatting should not fail") - } - - assert.Equal(t, tc.expect, got, "output strings should match") - }) - } -} diff --git a/interpolator/formatters/json/json_formatter.go b/interpolator/formatters/json/json_formatter.go index 55a1971e9..7499a2b4b 100644 --- a/interpolator/formatters/json/json_formatter.go +++ b/interpolator/formatters/json/json_formatter.go @@ -20,14 +20,14 @@ type JSONFormatter struct { // New will parse params and return a JSONFormatter func New(params map[string][]string) *JSONFormatter { - var f = &JSONFormatter{ + f := &JSONFormatter{ indentSize: 2, escape: false, compact: false, } for option, valueArray := range params { - var value = "" + value := "" if len(valueArray) > 0 { value = valueArray[0] } diff --git a/interpolator/formatters/json/json_formatter_test.go b/interpolator/formatters/json/json_formatter_test.go deleted file mode 100644 index 110672271..000000000 --- a/interpolator/formatters/json/json_formatter_test.go +++ /dev/null @@ -1,93 +0,0 @@ -package jsonformatter - -import ( - "strconv" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestJSONFormatterOptions(t *testing.T) { - tcs := []struct { - name string - params map[string][]string - expect *JSONFormatter - }{ - { - "DefaultsOk", - map[string][]string{}, - &JSONFormatter{indentSize: 2, escape: false, compact: false}, - }, - { - "GoodIndentOk", - map[string][]string{ - "output": {"json"}, - "indent_size": {"4"}, - }, - &JSONFormatter{indentSize: 4, escape: false, compact: false}, - }, - { - "BadIndentShouldDefault", - map[string][]string{ - "output": {"json"}, - "indent_size": {"-15"}, - }, - &JSONFormatter{indentSize: 2, escape: false, compact: false}, - }, - { - "EscapeOnlyOk", - map[string][]string{ - "output": {"json"}, - "json_escape": {}, - }, - &JSONFormatter{indentSize: 2, escape: true, compact: false}, - }, - { - "EscapeTrueOk", - map[string][]string{ - "json_escape": {}, - }, - &JSONFormatter{indentSize: 2, escape: true, compact: false}, - }, - { - "EscapeFalseOk", - map[string][]string{ - "json_escape": {"false"}, - }, - &JSONFormatter{indentSize: 2, escape: false, compact: false}, - }, - { - "CompactOnlyOk", - map[string][]string{ - "json_compact": {}, - }, - &JSONFormatter{indentSize: 2, escape: false, compact: true}, - }, - { - "CompactFalseOk", - map[string][]string{ - "json_compact": {"false"}, - }, - &JSONFormatter{indentSize: 2, escape: false, compact: false}, - }, - } - - for _, tc := range tcs { - t.Run(tc.name, func(t *testing.T) { - got := New(tc.params) - assert.Equal(t, tc.expect, got, "Values must match, setup:", tc.params) - }) - } -} - -func TestJSONEscape(t *testing.T) { - formatter := New(map[string][]string{"json_escape": {}}) - got, err := formatter.Format([]any{map[string]string{"hello": "world"}}) - assert.NoError(t, err, "formatting should not fail") - assert.Equal(t, `"{\"hello\":\"world\"}"`, got, "output should be equal") - - // Unquote should work - unquoted, err := strconv.Unquote(got) - assert.NoError(t, err, "unquote should work") - assert.Equal(t, `{"hello":"world"}`, unquoted) -} diff --git a/interpolator/formatters/yaml/yaml_formatter.go b/interpolator/formatters/yaml/yaml_formatter.go index e5bd9f1b9..b6f6121fd 100644 --- a/interpolator/formatters/yaml/yaml_formatter.go +++ b/interpolator/formatters/yaml/yaml_formatter.go @@ -16,7 +16,7 @@ type YAMLFormatter struct { // New will parse params and return a YAMLFormatter func New(params map[string][]string) *YAMLFormatter { - var f = &YAMLFormatter{ + f := &YAMLFormatter{ indentSize: 2, } diff --git a/interpolator/formatters/yaml/yaml_formatter_options_test.go b/interpolator/formatters/yaml/yaml_formatter_options_test.go deleted file mode 100644 index 71060cdbf..000000000 --- a/interpolator/formatters/yaml/yaml_formatter_options_test.go +++ /dev/null @@ -1,44 +0,0 @@ -package yamlformatter - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestYAMLFormatterOptions(t *testing.T) { - tcs := []struct { - name string - params map[string][]string - expect *YAMLFormatter - }{ - { - "DefaultsOk", - map[string][]string{}, - &YAMLFormatter{indentSize: 2}, - }, - { - "GoodIndentOk", - map[string][]string{ - "output": {"yaml"}, - "indent_size": {"4"}, - }, - &YAMLFormatter{indentSize: 4}, - }, - { - "BadIndentShouldDefault", - map[string][]string{ - "output": {"yaml"}, - "indent_size": {"-15"}, - }, - &YAMLFormatter{indentSize: 2}, - }, - } - - for _, tc := range tcs { - t.Run(tc.name, func(t *testing.T) { - got := New(tc.params) - assert.Equal(t, tc.expect, got, "Values must match") - }) - } -} diff --git a/interpolator/formatters/yaml/yaml_formatter_test.go b/interpolator/formatters/yaml/yaml_formatter_test.go deleted file mode 100644 index 655cb3e95..000000000 --- a/interpolator/formatters/yaml/yaml_formatter_test.go +++ /dev/null @@ -1,132 +0,0 @@ -package yamlformatter_test - -import ( - "net/url" - "testing" - - "github.com/stretchr/testify/assert" - - "github.com/cycloidio/cycloid-cli/interpolator/formatters" - "github.com/cycloidio/cycloid-cli/interpolator/resolvers/mockresolver" - "github.com/cycloidio/cycloid-cli/interpolator/resources" -) - -func TestYAMLFormatting(t *testing.T) { - mo := mockresolver.NewMockResolverWithDefault() - - tcs := []struct { - name string - ref *resources.Reference - expect string - }{ - { - "TestSimpleStringOk", - &resources.Reference{ - Path: "/simple/string", - Params: url.Values{"output": {"yaml"}}, - }, - "simple", - }, - { - "TestSimpleNumOk", - &resources.Reference{ - Path: "/simple/num", - Params: url.Values{"output": {"yaml"}}, - }, - "1\n", - }, - { - "TestSimpleBoolOk", - &resources.Reference{ - Path: "/simple/bool", - Params: url.Values{"output": {"yaml"}}, - }, - "true\n", - }, - { - "TestSimpleObjectOk", - &resources.Reference{ - Path: "/simple/object", - Params: url.Values{"output": {"yaml"}}, - }, - "str: simple\nnum: 1\nboolean: true\n", - }, - { - "TestListStringOk", - &resources.Reference{ - Path: "/list/string", - Params: url.Values{"output": {"yaml"}}, - }, - "- one\n- two\n- three\n", - }, - { - "TestListNumOk", - &resources.Reference{ - Path: "/list/num", - Params: url.Values{"output": {"yaml"}}, - }, - "- 1\n- 2\n- 3\n", - }, - { - "TestListBoolOk", - &resources.Reference{ - Path: "/list/bool", - Params: url.Values{"output": {"yaml"}}, - }, - "- true\n- false\n- true\n", - }, - { - "TestListObjectOk", - &resources.Reference{ - Path: "/list/object", - Params: url.Values{"output": {"yaml"}}, - }, - `- str: one - num: 1 - boolean: true -- str: two - num: 2 - boolean: false -- str: three - num: 3 - boolean: true -`, - }, - { - "TestBigObjectIndentedOk", - &resources.Reference{ - Path: "/simple/bigObject", - Params: url.Values{ - "output": {"yaml"}, - "indent_size": {"4"}, - }, - }, - `obj: - str: simple - num: 3 - boolean: false -list: - - hello - - world -listObj: - - str: one - num: 1 - boolean: true - - str: two - num: 2 - boolean: false - - str: three - num: 3 - boolean: true -`, - }, - } - for _, tc := range tcs { - data, err := mo.Resolve(tc.ref) - assert.NoError(t, err, "the resolution should not fail, check mockresolver") - yamlFormatter := formatters.New(tc.ref.Params) - result, err := yamlFormatter.Format(data) - assert.NoError(t, err, "Formatting should not fail") - assert.Equal(t, tc.expect, result, "result should match expectation") - } -} diff --git a/interpolator/parsers/fileparser_test.go b/interpolator/parsers/fileparser_test.go deleted file mode 100644 index 34d16d09e..000000000 --- a/interpolator/parsers/fileparser_test.go +++ /dev/null @@ -1,58 +0,0 @@ -package parsers_test - -import ( - "testing" - - "github.com/cycloidio/cycloid-cli/interpolator/parsers" - "github.com/cycloidio/cycloid-cli/interpolator/resolvers" - "github.com/cycloidio/cycloid-cli/interpolator/resolvers/mockresolver" -) - -func TestFileParserOk(t *testing.T) { -} - -func TestReplaceFile(t *testing.T) { - mock := mockresolver.NewMockResolverWithDefault() - - type args struct { - resolver resolvers.ResourceResolver - file string - } - tests := []struct { - name string - args args - want string - wantErr bool - }{ - { - "simpleInterpolationOk", - args{ - resolver: mock, - file: `ssh: cy://simple/string`, - }, - "ssh: simple", - false, - }, - { - "simpleInterpolationNotOk", - args{ - resolver: mock, - file: `ssh: cy://doesnot/exists`, - }, - `ssh: cy://doesnot/exists`, - true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := parsers.ReplaceFile(tt.args.resolver, tt.args.file) - if (err != nil) != tt.wantErr { - t.Errorf("ReplaceFile() error = %v, wantErr %v", err, tt.wantErr) - return - } - if got != tt.want { - t.Errorf("ReplaceFile() = %v, want %v", got, tt.want) - } - }) - } -} diff --git a/interpolator/resolvers/httpresolver/httpresolver.go b/interpolator/resolvers/httpresolver/httpresolver.go index 181eb2216..5d90aabbc 100644 --- a/interpolator/resolvers/httpresolver/httpresolver.go +++ b/interpolator/resolvers/httpresolver/httpresolver.go @@ -8,7 +8,7 @@ import ( "strings" "time" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" + "github.com/cycloidio/cycloid-cli/cmd/common" "github.com/cycloidio/cycloid-cli/interpolator/resolvers" "github.com/cycloidio/cycloid-cli/interpolator/resources" ) @@ -80,7 +80,7 @@ func (r HTTPResolver) Resolve(ref *resources.Reference) ([]any, error) { return data, nil default: - var details = make([]string, len(apiResponse.Errors)) + details := make([]string, len(apiResponse.Errors)) for index, apiErr := range apiResponse.Errors { details[index] = apiErr.String() } diff --git a/interpolator/resolvers/query_test.go b/interpolator/resolvers/query_test.go deleted file mode 100644 index 0277f478c..000000000 --- a/interpolator/resolvers/query_test.go +++ /dev/null @@ -1,43 +0,0 @@ -package resolvers - -import ( - "reflect" - "testing" -) - -func TestQuery(t *testing.T) { - type args struct { - params map[string][]string - data any - } - tests := []struct { - name string - args args - want []any - wantErr bool - }{ - { - "NullResultShouldErr", - args{ - params: map[string][]string{ - "key": {".does.not.exists"}, - }, - data: nil, - }, - nil, - true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := Query(tt.args.params, tt.args.data) - if (err != nil) != tt.wantErr { - t.Errorf("Query() error = %v, wantErr %v", err, tt.wantErr) - return - } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("Query() = %v, want %v", got, tt.want) - } - }) - } -} diff --git a/interpolator/resources/reference_test.go b/interpolator/resources/reference_test.go deleted file mode 100644 index 19cf36d8f..000000000 --- a/interpolator/resources/reference_test.go +++ /dev/null @@ -1,71 +0,0 @@ -package resources_test - -import ( - "fmt" - "reflect" - "testing" - - "github.com/spf13/viper" - - "github.com/cycloidio/cycloid-cli/interpolator/resources" -) - -func TestParseURI(t *testing.T) { - org := "myOrg" - project := "myProject" - env := "myEnv" - component := "myComponent" - tests := []struct { - name string - uri string - want *resources.Reference - wantErr bool - }{ - { - "simple_credentials", - "cy://org/some_org/cred/some_cred?format=json", - &resources.Reference{ - Path: "/organizations/some_org/credentials/some_cred?format=json", - Params: map[string][]string{ - "format": {"json"}, - }, - }, - false, - }, - { - "expand", - "cy://org/org/project/project/env/env/component/component", - &resources.Reference{ - Path: "/organizations/org/projects/project/environments/env/components/component", - Params: map[string][]string{}, - }, - false, - }, - { - "expandAndVars", - "cy://org/{org}/project/{project}/env/{env}/component/{component}", - &resources.Reference{ - Path: fmt.Sprintf("/organizations/%s/projects/%s/environments/%s/components/%s", org, project, env, component), - Params: map[string][]string{}, - }, - false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - viper.Set("org", org) - viper.Set("project", project) - viper.Set("env", env) - viper.Set("component", component) - got, err := resources.NewResourceReference(tt.uri) - if (err != nil) != tt.wantErr { - t.Errorf("\nhave: %v\nwant: %v", err, tt.wantErr) - return - } - - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("\nhave: %v\nwant: %v", got, tt.want) - } - }) - } -} diff --git a/interpolator/transformers/transformers.go b/interpolator/transformers/transformers.go index e1af9d114..257cd7ee5 100644 --- a/interpolator/transformers/transformers.go +++ b/interpolator/transformers/transformers.go @@ -8,17 +8,15 @@ import ( type Transformer func(input string, options []string) (string, error) -var ( - AvailableTransformers = map[string]Transformer{ - "indent": Indent, - "nindent": NIndent, - "base64": Base64, - "base64encode": Base64, - } -) +var AvailableTransformers = map[string]Transformer{ + "indent": Indent, + "nindent": NIndent, + "base64": Base64, + "base64encode": Base64, +} func Transform(input string, params map[string][]string) (string, error) { - var out = input + out := input var err error for param, options := range params { if ts, ok := AvailableTransformers[param]; ok { @@ -34,7 +32,7 @@ func Transform(input string, params map[string][]string) (string, error) { func Indent(input string, options []string) (string, error) { var out string - var pad = 0 + pad := 0 if len(options) >= 1 { pad, _ = strconv.Atoi(options[0]) } diff --git a/main.go b/main.go index b71bbc852..d9d508c78 100644 --- a/main.go +++ b/main.go @@ -5,17 +5,11 @@ import ( "fmt" "os" - "github.com/spf13/cobra" "github.com/spf13/viper" "github.com/cycloidio/cycloid-cli/cmd" ) -var ( - // Used for flags. - rootCmd *cobra.Command -) - type exitCoder interface { ExitCode() int } @@ -24,8 +18,10 @@ func inRed(msg string) string { return fmt.Sprintf("\033[1;31m%s\033[0m", msg) } -// Execute runs the CLI root command. -func Execute() { +func main() { + rootCmd := cmd.NewRootCommand() + viper.BindPFlag("api-url", rootCmd.PersistentFlags().Lookup("api-url")) + if err := rootCmd.Execute(); err != nil { rootCmd.PrintErrln(inRed("Error:"), err.Error()) var codedErr exitCoder @@ -35,10 +31,3 @@ func Execute() { os.Exit(1) } } - -func main() { - rootCmd = cmd.NewRootCommand() - viper.BindPFlag("api-url", rootCmd.PersistentFlags().Lookup("api-url")) - - Execute() -} diff --git a/pkg/testcfg/bootstrap.go b/pkg/testcfg/bootstrap.go deleted file mode 100644 index 61f25928a..000000000 --- a/pkg/testcfg/bootstrap.go +++ /dev/null @@ -1,86 +0,0 @@ -package testcfg - -// CLI bootstrap provisioning for be-reset / TestMain. -// -// Validated manually and via e2e (PR #441): `cy beta bootstrap-first-org` works -// against staging. testcfg still calls middleware.InitFirstOrg directly because -// in-process CLI bootstrap left viper/CY_API_KEY state that broke some middleware -// tests (403 Need to refresh token). Re-enable by swapping the provision block -// in config.go when we want testcfg to exercise the cobra path again. -// -// Uncomment bootstrapFirstOrgCLI and use it from NewConfig provisionAPI block: -// -// init, err := bootstrapFirstOrgCLI(bootstrapFirstOrgParams{ -// APIURL: config.APIUrl, -// Org: config.Org, -// Username: username, -// FullName: fullName, -// Email: email, -// Password: password, -// Licence: licence, -// APIKeyCanonical: apiKeyCanonical, -// }) -// if err != nil { -// return nil, fmt.Errorf("failed to init console: %w", err) -// } -// config.APIKey = *init.APIKey -// api.Config.Token = *init.APIKey -// -// /* -// -// import ( -// "bytes" -// "encoding/json" -// "fmt" -// -// "github.com/cycloidio/cycloid-cli/cmd" -// "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" -// ) -// -// type bootstrapFirstOrgParams struct { -// APIURL string -// Org string -// Username string -// FullName string -// Email string -// Password string -// Licence string -// APIKeyCanonical string -// } -// -// func bootstrapFirstOrgCLI(params bootstrapFirstOrgParams) (*middleware.FirstOrgData, error) { -// rootCmd := cmd.NewRootCommand() -// -// stdout := new(bytes.Buffer) -// stderr := new(bytes.Buffer) -// rootCmd.SetOut(stdout) -// rootCmd.SetErr(stderr) -// rootCmd.SetArgs([]string{ -// "--api-url", params.APIURL, -// "--output", "json", -// "--org", params.Org, -// "beta", "bootstrap-first-org", -// "--username", params.Username, -// "--full-name", params.FullName, -// "--email", params.Email, -// "--password", params.Password, -// "--licence", params.Licence, -// "--api-key-canonical", params.APIKeyCanonical, -// }) -// -// if err := rootCmd.Execute(); err != nil { -// return nil, fmt.Errorf("bootstrap-first-org CLI failed: %w (stderr: %s)", err, stderr.String()) -// } -// -// var result middleware.FirstOrgData -// if err := json.Unmarshal(stdout.Bytes(), &result); err != nil { -// return nil, fmt.Errorf("failed to decode bootstrap-first-org JSON output: %w (stdout: %s)", err, stdout.String()) -// } -// if result.APIKey == nil || *result.APIKey == "" { -// return nil, fmt.Errorf("bootstrap-first-org succeeded but APIKey is missing in output") -// } -// -// return &result, nil -// } -// -// */ diff --git a/pkg/testcfg/config.go b/pkg/testcfg/config.go deleted file mode 100644 index 4bf42ff55..000000000 --- a/pkg/testcfg/config.go +++ /dev/null @@ -1,393 +0,0 @@ -package testcfg - -import ( - "errors" - "fmt" - "log" - "os" - "strconv" - "strings" - "time" - - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/common" - "github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware" - "github.com/cycloidio/cycloid-cli/internal/ptr" -) - -type Config struct { - APIKey string - APIUrl string - Org string - // GitCredential models.Credential - ConfigRepo *models.ConfigRepository - CatalogRepo *models.ServiceCatalogSource - CatalogRepoVersionStacks *middleware.StackVersion - Middleware middleware.Middleware - // Common project to use for tests that require one - Project *models.Project - // Common environment to use for tests that require one - Environment *models.Environment - // Common component to use for tests that require one - Component *models.Component - // Slice containing all functions to exec for cleaning common test resources - cleanupFuncs []func() -} - -func NewConfig(testName string) (*Config, error) { - if len(testName) < 1 { - return nil, fmt.Errorf("testName argument must not be empty") - } - - var ( - localGitSSHKey = strings.Join([]string{ - "-----BEGIN OPENSSH PRIVATE KEY-----", - "b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW", - "QyNTUxOQAAACD8O9mhkl5CAiD0NLeQcoPf1duYHImQlTjOXcCOgHmC+AAAAJjCF9jzwhfY", - "8wAAAAtzc2gtZWQyNTUxOQAAACD8O9mhkl5CAiD0NLeQcoPf1duYHImQlTjOXcCOgHmC+A", - "AAAEC0ryBZ1uJQ2drmjsO+WpsC2E/5SWheJD/r8+Q4LghWxfw72aGSXkICIPQ0t5Byg9/V", - "25gciZCVOM5dwI6AeYL4AAAAE2N5Y2xvaWRAZXhhbXBsZS5jb20BAg==", - "-----END OPENSSH PRIVATE KEY-----", - }, "\n") - localGitCredential = "local-git" - configRepoName = "cli-test-config" - configRepository = "cli-test-config" - configRepoURL = "git@git-server:/git-server/repos/backend-test-config-repo.git" - configRepoBranch = "master" - isDefault = true - gitCred = "github" - catalogRepo = "cli-test-stacks" - catalogRepoName = "CLI test catalog" - catalogRepoURL = "https://github.com/cycloidio/cycloid-cli-test-catalog.git" - catalogRepoBranch = "stacks" - defaultStackCanonical = "stack-e2e-stackforms" - defaultStackUseCase = "default" - ) - - var config = &Config{} - config.ConfigRepo = &models.ConfigRepository{ - Name: &configRepoName, - Canonical: &configRepository, - URL: &configRepoURL, - Branch: configRepoBranch, - CredentialCanonical: gitCred, - Default: &isDefault, - } - config.CatalogRepo = &models.ServiceCatalogSource{ - Name: &catalogRepoName, - Canonical: &catalogRepo, - URL: &catalogRepoURL, - Branch: catalogRepoBranch, - CredentialCanonical: gitCred, - } - - provisionAPI, _ := strconv.ParseBool(EnvDefault("CY_TEST_PROVISION_API", "1")) - config.APIUrl = EnvDefault("CY_TEST_API_URL", "http://localhost:3001") - config.Org = EnvDefault("CY_TEST_ROOT_ORG", "cycloid") - licence, ok := os.LookupEnv("API_LICENCE_KEY") - if !ok && provisionAPI { - return config, fmt.Errorf("licence required for provisionning, set it with API_LICENCE_KEY") - } - - // If we provision the api, we will try to login first - if !provisionAPI { - apiKey, ok := os.LookupEnv("CY_TEST_API_KEY") - if !ok { - return config, fmt.Errorf("api key not set in CY_TEST_API_KEY env var") - } - config.APIKey = apiKey - } - - api := common.NewAPI( - common.WithURL(config.APIUrl), - common.WithInsecure(true), - common.WithToken(config.APIKey), - ) - m := middleware.NewMiddleware(api) - config.Middleware = m - - var ( - username = "administrator" - fullName = "administrator" - email = "admin@cycloid.io" - password = "cycloidadmin" - apiKeyCanonical = "admin-" + testName - ) - - if provisionAPI { - // try to login, is successful, console is initialized - init, _, err := m.InitFirstOrg(config.Org, username, fullName, email, password, licence, &apiKeyCanonical) - if err != nil { - return nil, fmt.Errorf("failed to init console: %w", err) - } - - config.APIKey = *init.APIKey - api.Config.Token = *init.APIKey - - // Write .api_key only when CY_TEST_WRITE_API_KEY_FILE is not "0". - // Default is "1" (enabled) so cycloid-cli dev flow is unchanged. - // Set to "0" when consuming from a different repo to avoid scribbling - // into that repo's working tree. - writeFile, _ := strconv.ParseBool(EnvDefault("CY_TEST_WRITE_API_KEY_FILE", "1")) - if writeFile { - root, err := FindRepoRoot() - if err != nil { - return nil, err - } - apiKeyEnvFile := strings.Join([]string{ - "CY_API_KEY=" + config.APIKey, - "CY_API_URL=" + config.APIUrl, - "CY_ORG=" + config.Org, - }, "\n") - err = os.WriteFile(root+"/.api_key", []byte(apiKeyEnvFile), 0666) - if err != nil { - return nil, err - } - } - } - - _, _, err := m.CreateCredential(config.Org, localGitCredential, "ssh", - &models.CredentialRaw{SSHKey: localGitSSHKey}, "", localGitCredential, "", - ) - var apiErr *middleware.APIResponseError - if errors.As(err, &apiErr) { - if apiErr.StatusCode != 409 { - return config, fmt.Errorf("failed to init config repo credential: %w", err) - } - } - - currentConfigRepo, _, err := m.CreateConfigRepository(config.Org, - *config.ConfigRepo.Canonical, *config.ConfigRepo.Canonical, *config.ConfigRepo.URL, - config.ConfigRepo.Branch, localGitCredential, *config.ConfigRepo.Default, - ) - if errors.As(err, &apiErr) { - var getErr error - currentConfigRepo, _, getErr = m.GetConfigRepository(config.Org, configRepository) - if apiErr.StatusCode != 409 || getErr != nil { - return config, fmt.Errorf("failed to setup config repo: %w%w", err, getErr) - } - } - - config.ConfigRepo = currentConfigRepo - - _, _, err = m.CreateCatalogRepository(config.Org, *config.CatalogRepo.Canonical, - *config.CatalogRepo.URL, config.CatalogRepo.Branch, "", "local", "", - ) - if errors.As(err, &apiErr) { - if apiErr.StatusCode != 409 { - return config, fmt.Errorf("failed to setup catalog repo: %w", err) - } - } - - _, _, err = m.RefreshCatalogRepository(config.Org, *config.CatalogRepo.Canonical) - if err != nil { - return config, fmt.Errorf("failed to refresh catalog repo: %w", err) - } - - stackRef := config.Org + ":" + defaultStackCanonical - stackVersions, _, err := m.ListStackVersions(config.Org, stackRef) - if err != nil { - return config, fmt.Errorf("failed to list stack versions: %w", err) - } - - for _, v := range stackVersions { - if ptr.Value(v.Name) == catalogRepoBranch { - config.CatalogRepoVersionStacks = v - break - } - } - if config.CatalogRepoVersionStacks == nil { - return config, fmt.Errorf("failed to find latest catalog repo version after refresh") - } - - project, err := config.NewTestProject("common") - if err != nil { - return config, err - } - config.Project = project - - environment, err := config.NewTestEnv("common", *project.Canonical) - if err != nil { - // Non-fatal: tests that require env/component fixtures will skip themselves. - // This allows tests that only need org+middleware (e.g. plugin manager) to run - // even when the staging API rejects environment creation. - log.Printf("testcfg: warning: env fixture skipped (%v) — tests needing env will skip", err) - return config, nil - } - config.Environment = environment - - component, err := config.NewTestComponent( - *project.Canonical, *environment.Canonical, "common", stackRef, defaultStackUseCase, "", "", ptr.Value(config.CatalogRepoVersionStacks.CommitHash), nil, - ) - if err != nil { - log.Printf("testcfg: warning: component fixture skipped (%v) — tests needing component will skip", err) - return config, nil - } - config.Component = component - - stackConfig, _, err := m.GetComponentStackConfig(config.Org, *project.Canonical, *environment.Canonical, *component.Canonical, defaultStackUseCase, "", "", ptr.Value(config.CatalogRepoVersionStacks.CommitHash)) - if err != nil { - return config, err - } - - vars, err := common.FormUseCaseToFormVars(stackConfig, defaultStackUseCase) - if err != nil { - return config, err - } - common.UpdateMapField("types.tests.string", RandomCanonical("common"), vars) - - return config, nil -} - -// NewTestProject will create a project with a random canonical derived from identifier -// and return the project, the function to defer for its deletion and error. -// The func will always be returned so even if err != nil, defer the func. -func (config *Config) NewTestProject(identifier string) (*models.Project, error) { - var ( - project = RandomCanonical(identifier) - description = "Testing project " + identifier - configRepository = *config.ConfigRepo.Canonical - owner = "" - team = "" - color = "default" - icon = "inventory" - ) - - m := config.Middleware - - out, _, err := m.CreateProject(config.Org, project, project, description, configRepository, owner, team, color, icon) - if err != nil { - return nil, fmt.Errorf("failed to setup test project: %w", err) - } - - config.AppendCleanup(func() { - _, err := m.DeleteProject(config.Org, project, middleware.DeleteOptions{}) - if err != nil { - log.Fatalf("cannot cleanup projet %q for test %q: %v", project, identifier, err) - return - } - }) - - return out, nil -} - -// setupTestProject will create an env with a random canonical derived from identifier -// and return the env, the function to defer for its deletion and error. -// The func will always be returned so even if err != nil, defer the func. -func (config *Config) NewTestEnv(identifier, project string) (*models.Environment, error) { - var ( - env = RandomCanonical(identifier) - envType = "production" - ) - - m := config.Middleware - - body := &models.NewEnvironment{ - Canonical: env, - Name: ptr.Ptr(env), - Type: ptr.Ptr(envType), - } - out, _, err := m.CreateOrgEnv(config.Org, body) - if err != nil { - return nil, fmt.Errorf("failed to setup test environment: %w", err) - } - - if project != "" { - if _, err := m.LinkEnvToProject(config.Org, project, env); err != nil { - return nil, fmt.Errorf("failed to link test environment to project: %w", err) - } - } - - config.AppendCleanup(func() { - if project != "" { - _, _ = m.UnlinkEnvFromProject(config.Org, project, env, middleware.DeleteOptions{}) - } - _, err := m.DeleteOrgEnv(config.Org, env) - if err != nil { - log.Fatalf("cannot cleanup env %q for test %q: %v", env, identifier, err) - return - } - }) - - return out, nil -} - -// setupTestProject will create an component with a random canonical derived from identifier -// and return the component, the function to defer for its deletion and error. -// The func will always be returned so even if err != nil, defer the func. -func (config *Config) NewTestComponent(project, env, identifier, stackRef, useCase, versionTag, versionBranch, versionCommitHash string, inputs models.FormVariables) (*models.Component, error) { - m := config.Middleware - component := RandomCanonical(identifier) - - // Workaround for BE-1344: RefreshCatalogRepository is async — the DB is updated - // immediately but the backend git fetch may not be complete when we try to create a - // component. On a 404 GitObject error, trigger another refresh and retry. - const maxAttempts = 5 - var outComponent *models.Component - var err error - for attempt := range maxAttempts { - if attempt > 0 { - time.Sleep(5 * time.Second) - // Nudge backend to complete git fetch before retrying - _, _, _ = m.RefreshCatalogRepository(config.Org, *config.CatalogRepo.Canonical) - } - outComponent, _, err = m.CreateOrUpdateComponent(config.Org, project, env, - component, "", component, stackRef, versionTag, versionBranch, - versionCommitHash, useCase, "", inputs) - if err == nil { - break - } - var apiErr *middleware.APIResponseError - if !errors.As(err, &apiErr) || apiErr.StatusCode != 404 || - !strings.Contains(err.Error(), "GitObject") { - return nil, err // non-transient error, fail immediately - } - log.Printf("NewTestComponent: attempt %d/%d: transient GitObject error (BE-1344), retrying: %v", - attempt+1, maxAttempts, err) - } - if err != nil { - return nil, err - } - - config.AppendCleanup(func() { - if _, err := m.DeleteComponent(config.Org, project, env, component, middleware.DeleteOptions{}); err != nil { - log.Printf("failed to cleanup component for test %q: %v", identifier, err) - } - }) - - return outComponent, nil -} - -func (config *Config) AppendCleanup(f ...func()) { - config.cleanupFuncs = append(config.cleanupFuncs, f...) -} - -func (config *Config) Cleanup() { - if config == nil { - return - } - - for _, f := range config.cleanupFuncs { - defer f() - } -} - -// NewTestChildOrg is a helper function that create a suborg for a -// specific test and return a function to defer() for its deletion. -func (config *Config) NewTestChildOrg(parent, child string) (func(), error) { - m := config.Middleware - deferFunc := func() { - _, err := m.DeleteOrganization(child) - if err != nil { - log.Fatalf("Failed to delete org %q: %v", child, err) - return - } - } - - _, _, err := m.CreateOrganizationChild(parent, child, nil) - if err != nil { - return deferFunc, fmt.Errorf("failed to create child org %q: %v", child, err) - } - - return deferFunc, nil -} diff --git a/pkg/testcfg/helpers.go b/pkg/testcfg/helpers.go deleted file mode 100644 index 027e69bfb..000000000 --- a/pkg/testcfg/helpers.go +++ /dev/null @@ -1,45 +0,0 @@ -package testcfg - -import ( - "fmt" - "math/rand" - "os" - "path/filepath" - "strings" -) - -func RandomCanonical(baseName string) string { - var size = 4 - var letterRunes = []rune("abcdefghijklmnopqrstuvwxyz") - - b := make([]rune, size) - for i := range b { - b[i] = letterRunes[rand.Intn(len(letterRunes))] - } - return strings.ToLower(baseName) + "-" + string(b) -} - -func EnvDefault(envVar, defaultValue string) string { - if value, ok := os.LookupEnv(envVar); ok { - return value - } - - return defaultValue -} - -func FindRepoRoot() (string, error) { - path := ".git" - for i := 0; true; i++ { - if pwd, err := os.Getwd(); pwd == "/" || err != nil { - return "", fmt.Errorf("failed to find project root we reached /") - } - - testPath := strings.Repeat("../", i) + path - _, err := os.Stat(testPath) - if err == nil { - return filepath.Join(filepath.Dir(testPath)), nil - } - } - - return "", fmt.Errorf("failed for some reason") -} diff --git a/pkg/testcfg/plugins.go b/pkg/testcfg/plugins.go deleted file mode 100644 index dd82faff8..000000000 --- a/pkg/testcfg/plugins.go +++ /dev/null @@ -1,130 +0,0 @@ -package testcfg - -import ( - "fmt" - "log" - "strings" - "testing" - "time" - - "github.com/cycloidio/cycloid-cli/client/models" -) - -// NewTestPluginRegistry creates a plugin registry for testing and registers cleanup. -// If a registry with the same URL already exists it is returned as-is (no cleanup -// registered for it, since we don't own it). -func (config *Config) NewTestPluginRegistry(t *testing.T, name, url string) (*models.PluginRegistry, error) { - t.Helper() - m := config.Middleware - out, _, err := m.CreatePluginRegistry(config.Org, name, url) - if err != nil { - // 409 Conflict → registry with this URL already exists; find and return it. - if strings.Contains(err.Error(), "409") || strings.Contains(err.Error(), "already exists") { - regs, _, listErr := m.ListPluginRegistries(config.Org) - if listErr != nil { - return nil, fmt.Errorf("create failed (%v) and list fallback failed: %w", err, listErr) - } - for _, r := range regs { - if r.URL != nil && string(*r.URL) == url { - return r, nil - } - } - return nil, fmt.Errorf("registry with url %q not found after 409: %w", url, err) - } - return nil, err - } - config.AppendCleanup(func() { - if _, delErr := m.DeletePluginRegistry(config.Org, *out.ID); delErr != nil { - log.Printf("failed to cleanup plugin registry %q: %v", name, delErr) - } - }) - return out, nil -} - -// NewTestPluginInRegistry creates a plugin inside the given registry and registers cleanup. -func (config *Config) NewTestPluginInRegistry(t *testing.T, registryID uint32, name string) (*models.Plugin, error) { - t.Helper() - m := config.Middleware - out, _, err := m.CreateRegistryPlugin(config.Org, registryID, name) - if err != nil { - return nil, err - } - config.AppendCleanup(func() { - if _, err := m.DeleteRegistryPlugin(config.Org, registryID, *out.ID); err != nil { - log.Printf("failed to cleanup registry plugin %q: %v", name, err) - } - }) - return out, nil -} - -// NewTestPluginVersion publishes a plugin version, waits for it to reach "success" -// status (indicating the plugin-registry has validated the image), and registers cleanup. -func (config *Config) NewTestPluginVersion(t *testing.T, registryID, pluginID uint32, dockerImage string) (*models.PluginVersion, error) { - t.Helper() - m := config.Middleware - out, _, err := m.CreatePluginVersion(config.Org, registryID, pluginID, dockerImage) - if err != nil { - return nil, err - } - config.AppendCleanup(func() { - if _, delErr := m.DeletePluginVersion(config.Org, registryID, pluginID, *out.ID); delErr != nil { - log.Printf("failed to cleanup plugin version %d: %v", *out.ID, delErr) - } - }) - - // The plugin-registry validates the image asynchronously. Poll until success. - deadline := time.Now().Add(60 * time.Second) - for time.Now().Before(deadline) { - ver, _, pollErr := m.GetPluginVersion(config.Org, registryID, pluginID, *out.ID) - if pollErr == nil && ver.Status != nil { - switch *ver.Status { - case "success": - return ver, nil - case "failed": - return nil, fmt.Errorf("plugin version %d validation failed", *out.ID) - } - } - time.Sleep(3 * time.Second) - } - return nil, fmt.Errorf("plugin version %d did not reach success within 60s", *out.ID) -} - -// AcceptPluginManager finds and accepts the auto-registered test-plugin-manager. -// The plugin-manager service in compose.yml auto-registers itself as "test-plugin-manager" -// on startup, but retries if the org doesn't exist yet. This helper polls until it -// appears (up to 90s) then accepts it. -func (config *Config) AcceptPluginManager(t *testing.T) (*models.PluginManager, error) { - t.Helper() - m := config.Middleware - deadline := time.Now().Add(90 * time.Second) - for { - managers, _, listErr := m.ListPluginManagers(config.Org) - if listErr == nil { - for _, mgr := range managers { - if mgr.Name != nil && *mgr.Name == "test-plugin-manager" { - // "invite_accepted" is what the API returns once accepted. - // Either form means already done. - if mgr.InviteStatus != nil && - (*mgr.InviteStatus == "accepted" || *mgr.InviteStatus == "invite_accepted") { - return mgr, nil - } - out, _, acceptErr := m.UpdatePluginManager(config.Org, *mgr.ID, "accepted") - if acceptErr != nil { - // Already accepted by a concurrent call — treat as success. - if strings.Contains(acceptErr.Error(), "only pending") { - return mgr, nil - } - return nil, acceptErr - } - return out, nil - } - } - } - // Any error (including JSON decode of numeric status on first registration) - // means the manager is not ready yet — keep polling. - if time.Now().After(deadline) { - return nil, fmt.Errorf("test-plugin-manager did not register within 90s") - } - time.Sleep(5 * time.Second) - } -} diff --git a/printer/factory/factory_test.go b/printer/factory/factory_test.go deleted file mode 100644 index e7cd31e19..000000000 --- a/printer/factory/factory_test.go +++ /dev/null @@ -1,34 +0,0 @@ -package factory - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/cycloidio/cycloid-cli/printer" - "github.com/cycloidio/cycloid-cli/printer/json" - "github.com/cycloidio/cycloid-cli/printer/yaml" -) - -func TestGetPrinter(t *testing.T) { - t.Run("SuccessYAML", func(t *testing.T) { - p, err := GetPrinter("yaml") - require.NoError(t, err) - assert.Implements(t, (*printer.Printer)(nil), p) - assert.IsType(t, yaml.YAML{}, p) - }) - t.Run("SuccessJSON", func(t *testing.T) { - p, err := GetPrinter("json") - require.NoError(t, err) - assert.Implements(t, (*printer.Printer)(nil), p) - assert.IsType(t, json.JSON{}, p) - }) - t.Run("FieldExtractor", func(t *testing.T) { - // Unknown output values fall through to the field extractor, not an error - p, err := GetPrinter("not a printer") - require.NoError(t, err) - assert.NotNil(t, p) - assert.Implements(t, (*printer.Printer)(nil), p) - }) -} diff --git a/printer/http_error_test.go b/printer/http_error_test.go deleted file mode 100644 index d886c8f5b..000000000 --- a/printer/http_error_test.go +++ /dev/null @@ -1,31 +0,0 @@ -package printer_test - -import ( - "testing" - - "github.com/stretchr/testify/assert" - - "github.com/cycloidio/cycloid-cli/printer" -) - -func TestFirstNLinesFromBytes(t *testing.T) { - t.Run("FewerThanN", func(t *testing.T) { - got := printer.FirstNLinesFromBytes([]byte("a\nb"), 10) - assert.Equal(t, "a\nb", got) - }) - t.Run("ExactlyN", func(t *testing.T) { - got := printer.FirstNLinesFromBytes([]byte("1\n2\n3"), 3) - assert.Equal(t, "1\n2\n3", got) - }) - t.Run("TruncatesAfterN", func(t *testing.T) { - got := printer.FirstNLinesFromBytes([]byte("1\n2\n3\n4\n5"), 3) - assert.Equal(t, "1\n2\n3", got) - }) - t.Run("ZeroN", func(t *testing.T) { - assert.Equal(t, "", printer.FirstNLinesFromBytes([]byte("a\nb"), 0)) - }) - t.Run("TrailingSpaceTrimmed", func(t *testing.T) { - got := printer.FirstNLinesFromBytes([]byte("x\ny\n \n"), 10) - assert.Equal(t, "x\ny", got) - }) -} diff --git a/printer/json/printer.go b/printer/json/printer.go index fd2a11ded..05a08e434 100644 --- a/printer/json/printer.go +++ b/printer/json/printer.go @@ -2,11 +2,10 @@ package json import ( "encoding/json" - stderrors "errors" + "errors" + "fmt" "io" - "github.com/pkg/errors" - "github.com/cycloidio/cycloid-cli/printer" ) @@ -21,10 +20,10 @@ func (j JSON) Print(obj interface{}, opts printer.Options, w io.Writer) error { if err != nil { asErr, ok := obj.(error) if !ok { - return errors.Wrap(err, "unable to marshal object") + return fmt.Errorf("unable to marshal object: %w", err) } var httpErr printer.ErrHTTPResponse - if stderrors.As(asErr, &httpErr) { + if errors.As(asErr, &httpErr) { diag := struct { CLIMarshalError string `json:"cli_marshal_error"` HTTPStatus int `json:"http_status"` @@ -42,22 +41,22 @@ func (j JSON) Print(obj interface{}, opts printer.Options, w io.Writer) error { } payload, err = json.MarshalIndent(diag, "", " ") if err != nil { - return errors.Wrap(err, "unable to marshal object") + return fmt.Errorf("unable to marshal object: %w", err) } payload = append(payload, '\n') if _, werr := w.Write(payload); werr != nil { - return errors.Wrap(werr, "unable to write JSON in the writer") + return fmt.Errorf("unable to write JSON in the writer: %w", werr) } return nil } - return errors.Wrap(err, "unable to marshal object") + return fmt.Errorf("unable to marshal object: %w", err) } // Add a newline to avoid ugly console output for user payload = append(payload, '\n') if _, err = w.Write(payload); err != nil { - return errors.Wrap(err, "unable to write JSON in the writer") + return fmt.Errorf("unable to write JSON in the writer: %w", err) } return nil } diff --git a/printer/json/printer_test.go b/printer/json/printer_test.go deleted file mode 100644 index ebf9803fe..000000000 --- a/printer/json/printer_test.go +++ /dev/null @@ -1,103 +0,0 @@ -package json - -import ( - "bytes" - "encoding/json" - "fmt" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/cycloidio/cycloid-cli/printer" -) - -func TestJSONPrinter(t *testing.T) { - - t.Run("Success", func(t *testing.T) { - var ( - j JSON - b bytes.Buffer - obj = struct { - A string `json:"a"` - B string `json:"b"` - C []string `json:"c"` - }{ - A: "value a", - B: "value b", - C: []string{"abc", "def"}, - } - ) - exp := `{ - "a": "value a", - "b": "value b", - "c": [ - "abc", - "def" - ] -} -` - - err := j.Print(obj, printer.Options{}, &b) - require.NoError(t, err) - assert.Equal(t, exp, b.String()) - - }) - -} - -// failMarshalHTTPError implements printer.ErrHTTPResponse and fails JSON marshaling. -type failMarshalHTTPError struct { - code int - body []byte -} - -func (e *failMarshalHTTPError) Error() string { return "fail-marshal" } - -func (e *failMarshalHTTPError) HTTPStatusCode() int { return e.code } - -func (e *failMarshalHTTPError) HTTPResponseBody() []byte { return e.body } - -func (e *failMarshalHTTPError) MarshalJSON() ([]byte, error) { - return nil, fmt.Errorf("marshal intentionally failed") -} - -type failMarshalHTTPErrorWithPath struct { - failMarshalHTTPError - path string -} - -func (e *failMarshalHTTPErrorWithPath) HTTPRequestPath() string { return e.path } - -func TestJSONPrinter_MarshalFallbackErrHTTPResponse(t *testing.T) { - t.Run("DiagnosticJSON", func(t *testing.T) { - body := []byte("a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl") - var j JSON - var b bytes.Buffer - err := j.Print(&failMarshalHTTPError{code: 422, body: body}, printer.Options{}, &b) - require.NoError(t, err) - - var out map[string]any - require.NoError(t, json.Unmarshal(b.Bytes(), &out)) - assert.EqualValues(t, 422, out["http_status"]) - assert.Contains(t, out["cli_marshal_error"].(string), "marshal intentionally failed") - preview := out["api_response_preview"].(string) - assert.Contains(t, preview, "a") - assert.NotContains(t, preview, "k") - _, hasPath := out["request_path"] - assert.False(t, hasPath) - }) - - t.Run("IncludesRequestPath", func(t *testing.T) { - var j JSON - var b bytes.Buffer - err := j.Print(&failMarshalHTTPErrorWithPath{ - failMarshalHTTPError: failMarshalHTTPError{code: 500, body: []byte("x")}, - path: "/organizations/o/projects/p", - }, printer.Options{}, &b) - require.NoError(t, err) - var out map[string]any - require.NoError(t, json.Unmarshal(b.Bytes(), &out)) - assert.Equal(t, "/organizations/o/projects/p", out["request_path"]) - }) -} diff --git a/printer/printer.go b/printer/printer.go index dac1303b1..1f09e2fc3 100644 --- a/printer/printer.go +++ b/printer/printer.go @@ -1,9 +1,8 @@ package printer import ( + "fmt" "io" - - "github.com/pkg/errors" ) // Printer is an interface that knows how to print runtime objects @@ -21,14 +20,14 @@ func SmartPrint(p Printer, obj interface{}, err error, errStr string, opt Option if err != nil { // print the result on the standard output if perr := p.Print(err, opt, w); perr != nil { - return errors.Wrap(perr, "unable to print result") + return fmt.Errorf("unable to print result: %w", perr) } - return errors.Wrap(err, errStr) + return fmt.Errorf("%s: %w", errStr, err) } // print the result on the standard output if perr := p.Print(obj, opt, w); perr != nil { - return errors.Wrap(perr, "unable to print result") + return fmt.Errorf("unable to print result: %w", perr) } return nil } diff --git a/printer/table/printer.go b/printer/table/printer.go index 76e4d421e..afb41dd28 100644 --- a/printer/table/printer.go +++ b/printer/table/printer.go @@ -15,8 +15,8 @@ import ( libtable "github.com/charmbracelet/lipgloss/table" "golang.org/x/term" - "github.com/cycloidio/cycloid-cli/client/models" "github.com/cycloidio/cycloid-cli/printer" + "github.com/cycloidio/cycloid-cli/gen/models" ) // Table is the default printer, rendering structured data as a terminal table. diff --git a/printer/table/printer_test.go b/printer/table/printer_test.go deleted file mode 100644 index 702106443..000000000 --- a/printer/table/printer_test.go +++ /dev/null @@ -1,460 +0,0 @@ -package table - -import ( - "bytes" - "reflect" - "strings" - "testing" - "time" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/cycloidio/cycloid-cli/client/models" - "github.com/cycloidio/cycloid-cli/printer" -) - -func int64Ptr(i int64) *int64 { - return &i -} - -func TestTablePrinter(t *testing.T) { - - t.Run("Success", func(t *testing.T) { - var ( - tab Table - b bytes.Buffer - obj = struct { - A string `json:"a"` - B string `json:"b"` - C []string `json:"c"` - }{ - A: "value a", - B: "value b", - C: []string{"abc", "def"}, - } - ) - - err := tab.Print(&obj, printer.Options{}, &b) - require.NoError(t, err) - out := b.String() - assert.Contains(t, out, "A") - assert.Contains(t, out, "B") - assert.Contains(t, out, "C") - assert.Contains(t, out, "value a") - assert.Contains(t, out, "value b") - assert.Contains(t, out, "abc, def") - }) - t.Run("SuccessTimestamp", func(t *testing.T) { - now := time.Now() - exptNow := now.Format(time.RFC3339) - var ( - tab Table - b bytes.Buffer - obj = struct { - A *int64 `json:"a"` - }{ - A: int64Ptr(now.Unix()), - } - ) - - err := tab.Print(&obj, printer.Options{}, &b) - require.NoError(t, err) - assert.Contains(t, b.String(), exptNow) - }) - t.Run("SuccessAvoidNestedStruct", func(t *testing.T) { - var ( - tab Table - b bytes.Buffer - obj = struct { - A *struct{} - }{ - A: &struct{}{}, - } - ) - - err := tab.Print(&obj, printer.Options{}, &b) - require.NoError(t, err) - // Nested struct field is skipped by headersFromStruct → no data columns. - // Since there are no data columns, headers is empty → no output. - assert.Empty(t, b.String()) - }) - t.Run("SuccessSlicePtr", func(t *testing.T) { - var ( - tab Table - b bytes.Buffer - obj = struct { - A []*struct{} - }{ - A: []*struct{}{ - {}, - {}, - }, - } - ) - - err := tab.Print(&obj, printer.Options{}, &b) - require.NoError(t, err) - out := b.String() - assert.Contains(t, out, "A") - assert.Contains(t, out, "2") - }) -} - -func TestTablePrinter_StringSlice(t *testing.T) { - t.Run("DefaultColumnName", func(t *testing.T) { - var ( - tab Table - b bytes.Buffer - ) - err := tab.Print([]string{"foo", "bar"}, printer.Options{}, &b) - require.NoError(t, err) - out := b.String() - assert.Contains(t, out, "Value", "default column header should be 'Value'") - assert.Contains(t, out, "foo") - assert.Contains(t, out, "bar") - }) - - t.Run("CustomColumnName", func(t *testing.T) { - var ( - tab Table - b bytes.Buffer - ) - err := tab.Print([]string{"proj-one", "proj-two"}, printer.Options{Columns: []string{"Canonical"}}, &b) - require.NoError(t, err) - out := b.String() - assert.Contains(t, out, "Canonical", "column header should be 'Canonical'") - assert.Contains(t, out, "proj-one") - assert.Contains(t, out, "proj-two") - }) - - t.Run("EmptySlice", func(t *testing.T) { - var ( - tab Table - b bytes.Buffer - ) - err := tab.Print([]string{}, printer.Options{}, &b) - require.NoError(t, err) - assert.Empty(t, b.String(), "empty slice should produce no output") - }) -} - -// apiErrNilPayload mimics *middleware.APIResponseError with no parsed JSON error payload (e.g. HTML body). -type apiErrNilPayload struct { - StatusCode int -} - -func (*apiErrNilPayload) GetPayload() *models.ErrorPayload { - return nil -} - -func TestTablePrinter_APIErrorNilPayloadDoesNotPanic(t *testing.T) { - var ( - tab Table - b bytes.Buffer - ) - err := tab.Print(&apiErrNilPayload{StatusCode: 404}, printer.Options{}, &b) - require.NoError(t, err) - assert.NotEmpty(t, b.String()) -} - -func TestTablePrinter_BorderOption(t *testing.T) { - t.Run("DefaultNoBorder", func(t *testing.T) { - type row struct{ Name string } - obj := []row{{"alice"}} - var b bytes.Buffer - err := (&Table{}).Print(obj, printer.Options{}, &b) - require.NoError(t, err) - out := b.String() - assert.NotContains(t, out, "╭", "default should not have rounded corner") - assert.NotContains(t, out, "╮", "default should not have rounded corner") - }) - - t.Run("BorderMode", func(t *testing.T) { - type row struct{ Name string } - obj := []row{{"alice"}} - var b bytes.Buffer - tab := Table{opts: printer.TableOptions{Border: true}} - err := tab.Print(obj, printer.Options{}, &b) - require.NoError(t, err) - out := b.String() - assert.Contains(t, out, "╭", "border mode should have rounded top-left corner") - assert.Contains(t, out, "╰", "border mode should have rounded bottom-left corner") - assert.Contains(t, out, "│", "border mode should have vertical separators") - }) -} - -// --------------------------------------------------------------------------- -// Nil / panic-safety tests -// --------------------------------------------------------------------------- - -func TestTablePrinter_NilSafety(t *testing.T) { - t.Run("NilInterface", func(t *testing.T) { - var b bytes.Buffer - err := (&Table{}).Print(nil, printer.Options{}, &b) - require.NoError(t, err) - assert.Empty(t, b.String()) - }) - - t.Run("TypedNilPointer", func(t *testing.T) { - type item struct{ Name string } - var p *item // typed nil - var b bytes.Buffer - err := (&Table{}).Print(p, printer.Options{}, &b) - require.NoError(t, err) - assert.Empty(t, b.String()) - }) - - t.Run("SliceOfAllNilPointers", func(t *testing.T) { - type item struct{ Name string } - objs := []*item{nil, nil, nil} - var b bytes.Buffer - err := (&Table{}).Print(objs, printer.Options{}, &b) - require.NoError(t, err) - // All nil → no headers discoverable → no output - assert.Empty(t, b.String()) - }) - - t.Run("SliceWithMixedNilPointers", func(t *testing.T) { - type item struct{ Name string } - objs := []*item{nil, {Name: "alice"}, nil} - var b bytes.Buffer - err := (&Table{}).Print(objs, printer.Options{}, &b) - require.NoError(t, err) - out := b.String() - assert.Contains(t, out, "Name") - assert.Contains(t, out, "alice") - }) - - t.Run("SliceOfNilInterfaces", func(t *testing.T) { - objs := []interface{}{nil, nil} - var b bytes.Buffer - err := (&Table{}).Print(objs, printer.Options{}, &b) - require.NoError(t, err) - }) - - t.Run("SliceWithMixedNilInterfaces", func(t *testing.T) { - type item struct{ Name string } - objs := []interface{}{nil, &item{Name: "bob"}, nil} - var b bytes.Buffer - err := (&Table{}).Print(objs, printer.Options{}, &b) - require.NoError(t, err) - assert.Contains(t, b.String(), "bob") - }) - - t.Run("EmptyStruct", func(t *testing.T) { - obj := &struct{}{} - var b bytes.Buffer - err := (&Table{}).Print(obj, printer.Options{}, &b) - require.NoError(t, err) - assert.Empty(t, b.String()) - }) - - t.Run("StructAllNilFields", func(t *testing.T) { - type item struct { - Name *string - Count *int64 - Nested *struct{ X string } - } - obj := &item{} - var b bytes.Buffer - err := (&Table{}).Print(obj, printer.Options{}, &b) - require.NoError(t, err) - // Name and Count are ptr-to-scalar (shown), Nested is ptr-to-struct (hidden) - out := b.String() - assert.Contains(t, out, "Name") - assert.Contains(t, out, "Count") - }) - - t.Run("NilSliceField", func(t *testing.T) { - type item struct { - Name string - Tags []string - } - obj := &item{Name: "test", Tags: nil} - var b bytes.Buffer - err := (&Table{}).Print(obj, printer.Options{}, &b) - require.NoError(t, err) - assert.Contains(t, b.String(), "test") - }) - - t.Run("NilMapField", func(t *testing.T) { - type item struct { - Name string - Config map[string]string - } - obj := &item{Name: "test", Config: nil} - var b bytes.Buffer - err := (&Table{}).Print(obj, printer.Options{}, &b) - require.NoError(t, err) - assert.Contains(t, b.String(), "test") - }) - - t.Run("PopulatedMapField", func(t *testing.T) { - type item struct { - Name string - Config map[string]string - } - obj := &item{Name: "test", Config: map[string]string{"a": "1", "b": "2"}} - var b bytes.Buffer - err := (&Table{}).Print(obj, printer.Options{}, &b) - require.NoError(t, err) - out := b.String() - assert.Contains(t, out, "test") - assert.Contains(t, out, "{2 entries}") - }) - - t.Run("NonStructScalarValue", func(t *testing.T) { - // Passing a bare string should return an error, not panic - var b bytes.Buffer - err := (&Table{}).Print("just a string", printer.Options{}, &b) - assert.Error(t, err, "bare string should return error") - }) - - t.Run("NonStructIntValue", func(t *testing.T) { - var b bytes.Buffer - err := (&Table{}).Print(42, printer.Options{}, &b) - assert.Error(t, err, "bare int should return error") - }) - - t.Run("DotNotationOnNilNestedField", func(t *testing.T) { - type Owner struct{ Username string } - type item struct { - Name string - Owner *Owner - } - obj := &item{Name: "test", Owner: nil} - var b bytes.Buffer - tab := NewWithOptions(printer.TableOptions{Columns: []string{"Name", "Owner.Username"}}) - err := tab.Print(obj, printer.Options{}, &b) - require.NoError(t, err) - assert.Contains(t, b.String(), "test") - }) - - t.Run("DotNotationOnNilNestedInSlice", func(t *testing.T) { - type Owner struct{ Username string } - type item struct { - Name string - Owner *Owner - } - objs := []*item{ - {Name: "alice", Owner: &Owner{Username: "alice_u"}}, - {Name: "bob", Owner: nil}, - } - var b bytes.Buffer - tab := NewWithOptions(printer.TableOptions{Columns: []string{"Name", "Owner.Username"}}) - err := tab.Print(objs, printer.Options{}, &b) - require.NoError(t, err) - out := b.String() - assert.Contains(t, out, "alice_u") - assert.Contains(t, out, "bob") - }) - - t.Run("TransformReturnsNilMap", func(t *testing.T) { - type item struct{ Name string } - obj := &item{Name: "test"} - var b bytes.Buffer - err := (&Table{}).Print(obj, printer.Options{ - Transform: func(interface{}) map[string]string { return nil }, - }, &b) - require.NoError(t, err) - // nil map → empty headers → no output - assert.Empty(t, b.String()) - }) - - t.Run("ExpandColumnsNilSliceElement", func(t *testing.T) { - type item struct{ Name string } - objs := []*item{nil} - result := expandColumns(objs, []string{"Name"}) - assert.Equal(t, []string{"Name"}, result, "should return curated cols when all nil") - }) -} - -func TestRenderValue(t *testing.T) { - t.Run("Struct", func(t *testing.T) { - type inner struct { - A string - B int - } - v := reflect.ValueOf(inner{"x", 1}) - result := renderValue(v) - assert.Equal(t, "{record 2 fields}", result) - }) - - t.Run("PtrToStruct", func(t *testing.T) { - type inner struct { - A string - B int - C bool - } - val := inner{} - v := reflect.ValueOf(&val) - result := renderValue(v) - assert.Equal(t, "{record 3 fields}", result) - }) - - t.Run("Int", func(t *testing.T) { - v := reflect.ValueOf(int(42)) - assert.Equal(t, "42", renderValue(v)) - }) - - t.Run("Int32", func(t *testing.T) { - v := reflect.ValueOf(int32(7)) - assert.Equal(t, "7", renderValue(v)) - }) - - t.Run("Float32", func(t *testing.T) { - v := reflect.ValueOf(float32(3.14)) - result := renderValue(v) - assert.Contains(t, result, "3.14") - }) - - t.Run("Float64", func(t *testing.T) { - v := reflect.ValueOf(float64(2.718)) - result := renderValue(v) - assert.Contains(t, result, "2.718") - }) -} - -func TestEstimateWidth(t *testing.T) { - headers := []string{"Name", "Status"} - rows := [][]string{{"alice", "active"}} - - withoutBorder := estimateWidth(headers, rows, false) - withBorder := estimateWidth(headers, rows, true) - - // Border adds numCols+1 = 3 chars - assert.Equal(t, withoutBorder+3, withBorder, "border mode should add numCols+1 chars") -} - -func TestExpandColumns(t *testing.T) { - type full struct { - Canonical string - Name string - Extra1 string - Extra2 string - } - obj := []full{{"c1", "n1", "e1", "e2"}} - curated := []string{"Canonical", "Name"} - - expanded := expandColumns(obj, curated) - - assert.Equal(t, []string{"Canonical", "Name"}, expanded[:2], "curated cols should come first") - assert.Len(t, expanded, 4, "should include all 4 fields") - assert.Contains(t, expanded, "Extra1") - assert.Contains(t, expanded, "Extra2") -} - -func TestFitToWidth_ProtectedCount(t *testing.T) { - headers := []string{"Canonical", "Name", "Extra1", "Extra2"} - rows := [][]string{ - {"c1", "n1", strings.Repeat("x", 30), strings.Repeat("y", 30)}, - } - - // protectedCount=2 protects Canonical+Name; Extra1 and Extra2 can be dropped - fitted, _ := fitToWidth(headers, rows, "", 40, 2, false, false) - - // Canonical and Name must survive - assert.Contains(t, fitted, "Canonical") - assert.Contains(t, fitted, "Name") -} diff --git a/printer/yaml/printer.go b/printer/yaml/printer.go index c2584cf67..e71869ffa 100644 --- a/printer/yaml/printer.go +++ b/printer/yaml/printer.go @@ -1,9 +1,9 @@ package yaml import ( + "fmt" "io" - "github.com/pkg/errors" "gopkg.in/yaml.v3" "github.com/cycloidio/cycloid-cli/printer" @@ -16,10 +16,10 @@ type YAML struct{} func (y YAML) Print(obj interface{}, opts printer.Options, w io.Writer) error { yml, err := yaml.Marshal(obj) if err != nil { - return errors.Wrap(err, "unable to marshal object") + return fmt.Errorf("unable to marshal object: %w", err) } if _, err = w.Write(yml); err != nil { - return errors.Wrap(err, "unable to write YAML in the writer") + return fmt.Errorf("unable to write YAML in the writer: %w", err) } return nil } diff --git a/printer/yaml/printer_test.go b/printer/yaml/printer_test.go deleted file mode 100644 index 4d25fd393..000000000 --- a/printer/yaml/printer_test.go +++ /dev/null @@ -1,42 +0,0 @@ -package yaml - -import ( - "bytes" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/cycloidio/cycloid-cli/printer" -) - -func TestYAMLPrinter(t *testing.T) { - - t.Run("Success", func(t *testing.T) { - var ( - y YAML - b bytes.Buffer - obj = struct { - A string `json:"a"` - B string `json:"b"` - C []string `json:"c"` - }{ - A: "value a", - B: "value b", - C: []string{"abc", "def"}, - } - ) - - exp := `a: value a -b: value b -c: - - abc - - def -` - err := y.Print(obj, printer.Options{}, &b) - require.NoError(t, err) - assert.Equal(t, b.String(), exp) - - }) - -} diff --git a/test.json b/test.json deleted file mode 100644 index 3130770d7..000000000 --- a/test.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "file3": "tuti" -} diff --git a/internal/utils/utils.go b/utils/coalesce.go similarity index 70% rename from internal/utils/utils.go rename to utils/coalesce.go index 14668efef..637508e55 100644 --- a/internal/utils/utils.go +++ b/utils/coalesce.go @@ -1,6 +1,6 @@ package utils -// Coalesce will return the first non-empty value +// Coalesce returns the first non-nil pointer value func Coalesce[T any](values ...*T) *T { for _, v := range values { if v != nil { @@ -11,6 +11,7 @@ func Coalesce[T any](values ...*T) *T { return nil } +// CoalesceNonZero returns the first non-zero value func CoalesceNonZero[T comparable](values ...T) T { var zero T for _, v := range values { @@ -21,6 +22,7 @@ func CoalesceNonZero[T comparable](values ...T) T { return zero } +// CoalesceNonZeroPtr returns a pointer to the first non-zero value, or nil func CoalesceNonZeroPtr[T comparable](values ...T) *T { var zero T for _, v := range values { diff --git a/utils/doc.go b/utils/doc.go new file mode 100644 index 000000000..eb45934a0 --- /dev/null +++ b/utils/doc.go @@ -0,0 +1,6 @@ +// Package utils stores basic components which are reused +// for all the entities of the domain. They don't hold any +// value for themselves, only when they are composed into +// another struct. For example the Timestamps or the +// Canonical. +package utils diff --git a/utils/ptr/ptr.go b/utils/ptr/ptr.go new file mode 100644 index 000000000..6f2d20bfa --- /dev/null +++ b/utils/ptr/ptr.go @@ -0,0 +1,30 @@ +package ptr + +import "github.com/go-openapi/strfmt" + +// Email returns the address of a literal strfmt.Email +func Email(s string) *strfmt.Email { e := strfmt.Email(s); return &e } + +// Ptr returns a pointer address of given value +func Ptr[V any](v V) *V { return &v } + +// Value returns a value of given pointer +func Value[V any](v *V) V { + if v == nil { + var noop V + return noop + } + return *v +} + +// PtrOrNil returns a pointer to the value or nil if it's an empty value. +// Can be used as a quick check if a struct is empty. +// Careful! Default values like boolean false and integer 0 are treated as empty values. +// For them too the function will return nil. +func PtrOrNil[V comparable](v V) *V { + var empty V + if v == empty { + return nil + } + return &v +}