diff --git a/.changie.yaml b/.changie.yaml deleted file mode 100644 index 1390a219..00000000 --- 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 4d7c894a..00000000 --- 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 77c1c547..00000000 --- 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 1ce57c64..d142b175 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 b43460fc..00000000 --- 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 3d62d069..00000000 --- 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 ea1e4389..00000000 --- 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 50890d6e..00000000 --- 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 57b6ddff..00000000 --- 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 c392ccd9..00000000 --- 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 d6c07f3f..00000000 --- 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 f33832ef..00000000 --- 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 f5e50dd1..00000000 --- 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 18d383ca..7201d8a7 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 e69de29b..00000000 diff --git a/changelog/releases/0.md b/changelog/releases/0.md deleted file mode 100644 index d79c95e6..00000000 --- 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 d7006679..00000000 --- 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 8d3630e9..00000000 --- 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 ffe52a60..00000000 --- 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 01348493..00000000 --- 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 263ed53d..00000000 --- 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 59eb0d27..00000000 --- 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 104dbcdf..00000000 --- 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 3e6bb3c3..00000000 --- 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 89ce861f..00000000 --- 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 ffe7c3a3..00000000 --- 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 83b2e2f0..00000000 --- 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 332c4fc5..00000000 --- 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 9bff5ecf..00000000 --- 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 9cfc64f4..00000000 --- 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 48224ff2..00000000 --- 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 e45332f1..00000000 --- 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 a3a92ee3..00000000 --- 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 14cf7dc1..00000000 --- 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 cf3b1022..00000000 --- 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 a1f43035..00000000 --- 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 8b957760..00000000 --- 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 440fa61a..00000000 --- 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 1f07e87b..00000000 --- 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 fbf58f94..00000000 --- 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 b7a186cc..00000000 --- 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 ca66b759..00000000 --- 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 a1cea1d3..00000000 --- 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 283279e6..00000000 --- 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 4f571ac6..00000000 --- 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 940ca127..00000000 --- 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 28fda0d6..00000000 --- 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 32cd533c..00000000 --- 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 b47a70f3..00000000 --- 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 10a110aa..00000000 --- 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 1bd43b9d..00000000 --- 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 0461e46b..00000000 --- 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 fb0b3d62..00000000 --- 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 e69de29b..00000000 diff --git a/client/models/infra_import.go b/client/models/infra_import.go deleted file mode 100644 index 9e16d521..00000000 --- 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 552e53e7..00000000 --- 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 8a13a9fe..00000000 --- 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 27ae47fe..00000000 --- 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 77b73aa6..00000000 --- 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 bb545150..00000000 --- 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 645095c3..00000000 --- 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 6dc4aa3d..00000000 --- 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 6b56ad7c..00000000 --- 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 ffad31c9..00000000 --- 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 26664992..5356c347 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 daf47382..217c0828 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 7406ca5c..034b9675 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 2fec5bf4..9abd8bc5 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 df0782e7..5e180417 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 b197e642..0ae0f847 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 5e4c099c..83769f9c 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 982d16a2..58a4eae8 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 d3480a3a..c49e5e7a 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 7b104667..215088d1 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 26388aa5..763b70e8 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 d3693279..a7b0b83f 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 61a6d196..c9222491 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 00000000..6f75222d --- /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 e00f50b6..39865b51 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 757b9928..45d22265 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 d4dfb493..2c6fafdb 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 66e39ee2..8210c376 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 e5240d6a..12a342d2 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 8696f2b9..a25d75b8 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 41976e5f..fdf3d4f7 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 c196d7c5..c4258671 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 c37cc07d..3fb99205 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 9a1410aa..e42bce9e 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 f1810b41..88cbdf44 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 4b35f970..7080e018 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 c7df5fc7..68d9a4c1 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 5a78b3f0..2c6b166b 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 8a8e9894..009ffcbd 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 b203f35b..0ccfaa1c 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 4a8e9f64..e9565f5c 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 b93115a7..52aab2ef 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 abc681f8..c0b07ca0 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 9dca5ac8..17a724b7 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 6fd229a1..0ec3db6f 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 63aad716..c503bd72 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 ed65b065..7c6217d9 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 eb99171a..1e929bc2 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 d059e098..f8e26c94 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 57c4bf83..68f4539a 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 56c7f613..614ce79d 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 93f9de67..af057e30 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 d2f751d4..2c1032e2 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 e2222b8d..194c5fa7 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 0bdb972f..17de9d3d 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 d5ee82be..133f289a 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 a787074d..e4f2fb77 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 c0891d15..813cc1ff 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 8b90bbaf..c6633053 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 f417627b..cf898f64 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 f3828bb7..6bcb9201 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 d22466d2..1c08071f 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 50d8ef35..6ecc9b2b 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 534d35c9..64cc1113 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 d0fad678..33120aa2 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 a544d7fc..1433d277 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 7d9a53fa..22d50b4e 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 b2b5d456..fba233b7 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 6defed5e..c5e477c6 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 33c7944f..5ea6a1ce 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 a01b719d..1fab2b5d 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 c2ae1370..83cb7ed2 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 a9532ea2..9331893f 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 7cc958f5..2ac83e64 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 224f57f8..575b51bb 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 bc4c8b7a..7509ceb2 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 32fd441b..eb9304d2 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 5cabe63e..e26b2bd3 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 259fe887..eda7d127 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 7362d4e7..eed27091 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 346790d6..a382e807 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 67693a6d..6d76b37d 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 37337507..841e6e4e 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 416a53f5..330363c7 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 f4043d17..c284c440 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 6bcf6d6d..f5eb5c90 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 443c3525..6409a205 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 8a2d0eb2..41904db5 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 6c2c2f9a..209e88b2 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 54bdcfb1..e92b4856 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 90dbca80..98166dd3 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 95986c8b..cd094943 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 f13e63e7..5b3399cf 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 8e8466e2..ca456a9b 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 84344315..a7b5efb6 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 e4709e70..5c1b6ab2 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 8e8e9214..5f50495f 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 bc457b7b..d42779b0 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 7b13ec1f..5b3b4fd6 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 91490593..0aec06ea 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 7d9e14f9..00000000 --- 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 b8d700e8..00000000 --- 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 d0606dd6..00000000 --- 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 8fa24446..00000000 --- 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 43a809d5..00000000 --- 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 02381dec..00000000 --- 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 d5f93dce..00000000 --- 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 d7d24ac2..00000000 --- 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 232c19b6..00000000 --- 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 0d993b55..00000000 --- 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 15014d48..00000000 --- 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 26b24008..00000000 --- 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 f6f633d7..00000000 --- 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 dfe69336..00000000 --- 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 8e1b1500..00000000 --- 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 14b3d030..00000000 --- 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 a95867db..00000000 --- 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 c2d3cea2..00000000 --- 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 53ac9e81..00000000 --- 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 d4baafe3..00000000 --- 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 c7c62a89..00000000 --- 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 bfe6329b..00000000 --- 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 26b0c569..00000000 --- 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 dc090b95..00000000 --- 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 f7fee075..00000000 --- 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 3e75f0ee..00000000 --- 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 91a74efa..00000000 --- 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 96407e86..00000000 --- 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 0ac9e6a0..00000000 --- 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 b6b488f5..00000000 --- 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 63da8fc5..00000000 --- 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 5eae453a..00000000 --- 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 febd05fa..00000000 --- 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 2dab496c..00000000 --- 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 f190c4ef..00000000 --- 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 17c15695..00000000 --- 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 11e20928..00000000 --- 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 777044c2..00000000 --- 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 5fc44361..00000000 --- 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 f6b9a667..00000000 --- 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 beca1235..00000000 --- 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 e6123340..00000000 --- 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 f3c79c01..00000000 --- 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 0bc92a8e..00000000 --- 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 81fe16d0..00000000 --- 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 2671d04d..00000000 --- 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 e04dc075..00000000 --- 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 9069d309..51b2b2bf 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 73011ddc..d45531ea 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 1403db27..35690797 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 8d520a95..486530a7 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 2742ccd1..de35cc0f 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 17eda129..1bdefd20 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 26974129..31941c8c 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 ecb94253..cc631692 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 512a260e..806e7bba 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 06760cb5..a5a5b519 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 db5a03ad..f9ff402e 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 e935de62..a7377f76 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 1b50b526..fcb4b4bd 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 cb937192..a44f1b6b 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 66b528fb..1485d99d 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 d99a4520..892e1e8b 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 88825be0..3dff54a1 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 0020b340..e73e0735 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 1cd6e9ae..17a9c31b 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 c678fea9..ce17be0b 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 4d0d3d3e..49cc539f 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 c2452ae3..c85a308f 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 09ddda18..f09819a5 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 36e9fbcd..2c28a2de 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 de592011..e38ced3c 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 6f82b2ad..e4acb948 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 adb9940d..3f772eb3 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 74bfe04e..f0129c3f 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 f3eae6b8..a1e7db6c 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 e2ac9381..4ae10b7f 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 61b1bd88..177ee0c8 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 c6ec1399..01aed67d 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 428369c8..ef8477fe 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 c4fd5c47..5695dcb6 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 29b25dd2..3e5d9fb3 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 72e7c9fe..fdf2a39b 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 35fe3bfa..033630c4 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 28e4bab8..0f25ffd1 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 0019ca9c..70668c9a 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 ef23cb0d..3667fb99 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 64c905a4..4853cd41 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 4e76931b..5fad2014 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 027202f4..9b6e1548 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 7e848c2d..fb28e740 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 3f4fd817..cff80752 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 11c3eb09..e448cb1c 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 2d1b19b0..9048c6fe 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 99a5248d..a1a6b3ec 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 3c15f6c7..a02abcea 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 b555a45d..c86511fb 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 a34cce29..15ddda46 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 021ecfa7..6618c2b8 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 2f453f1d..8a452cd0 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 0064561d..668c1969 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 eeaa7554..03f7b5c1 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 d902aa65..d8eb0949 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 1fb405ac..02a9a2bb 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 1e4ee43c..823d682e 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 7bf5b527..c8e7c8b1 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 5d181bcd..bb8545ee 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 ac6a7d9a..23093a79 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 abcfabc5..15744451 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 e1b256e1..65b4cf17 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 c4bdceb0..5fdcae4e 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 604e79dc..9213b00f 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 9aec5831..7aeeed94 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 672a810c..aed2021e 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 005e8e68..a2f79e9e 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 86ed86c0..a05ef34b 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 ab3e14f7..abdd8287 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 276527e0..3508e827 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 3d348069..6f7bd628 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 d6ee2bc5..e849148a 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 ede26d61..6046800b 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 2763b7cd..5bc9ebfc 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 1a7ba2b6..775ef14a 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 c324adcf..f0089553 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 39e9d20d..05f3a0d3 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 7b892501..91efc4a3 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 0bce7340..490ab2b6 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 f8a27482..76426b02 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 f2f7074e..496e6c63 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 3395fc62..64e42158 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 a92aeba1..fb40537a 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 0c289d6b..46e650d0 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 0cca0fcf..d09d85c4 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 896be864..6b486b97 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 c2e529bd..5b515ad3 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 dadc304f..a63e16d6 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 afae1681..81e10795 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 2276983c..38897e67 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 8be71558..69ed0e3f 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 d3a15dab..253f64c8 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 06b0c14d..6da976f6 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 3a75dbcd..76787132 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 2e787908..498fd665 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 e7b4de6f..f2d12bbd 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 64f3a6fa..736dff8b 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 1f49e854..236417ab 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 52447fd2..881e37d3 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 b919da74..f4ec193e 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 576db30f..004b6c4c 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 d14f0ea3..8896d01f 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 3b5c60a7..6a64b92e 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 bddabb83..337dbce8 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 cd765653..24b91c92 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 a779f592..8abe1fc0 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 bea5e130..97ed1e94 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 9a63514f..99a81b1a 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 b4c567c4..5c7b8a46 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 7a44ab4a..eba7a2ec 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 120e0006..2fe57378 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 faf0e681..72c0e3b9 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 b6025396..0dc33743 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 8ac46c9c..5634e340 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 d1297425..fecf5e65 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 021e9a91..537982af 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 04d6aaf4..ca6d064d 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 b722dca3..8e25806d 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 90a2d2ee..09e70b2e 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 424b9d3b..932773d4 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 e129dc80..0196d092 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 ce2ef1a8..1c1e4b9b 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 caca5e97..fa66b494 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 984484c2..cc46c62a 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 cffe5f9c..0015e906 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 057342be..27f5ce68 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 bc3b89d3..1a8237a9 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 3ff53bc9..a6aeb676 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 3121625f..10f149fb 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 800b7a85..b4c6f414 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 80795ae6..8eb9b736 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 0fe0d7e0..91a9f65a 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 b12559f2..8d965b64 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 fd5afd87..723aabb1 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 2350e00f..2382b122 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 920d254e..50d727fa 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 4e7f0c74..26c270c1 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 5119cd3c..f2bdd14e 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 702f1b5a..de22af27 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 e233ec96..7b712cae 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 8f401940..4fb5fa2d 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 c8532cfb..46a29aa7 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 57162eed..0e0eb4b1 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 f6c10c63..8b135349 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 44f5330b..d660b46f 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 062e9cbc..27514987 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 00000000..ab509a9b --- /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 9e728bf1..f1778581 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 2761cd03..7f92d7b3 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 e50e4818..ee8cfee2 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 9d68f61a..00000000 --- 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 e40e4bc7..99ca6f5b 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 f62e96a3..00000000 --- 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 25e4bc53..00000000 --- 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 f5c63fbe..00000000 --- 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 d9c7e130..00000000 --- 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 ccfbac60..00000000 --- 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 752156b0..00000000 --- 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 3a06ad29..00000000 --- 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 7a168c96..00000000 --- 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 46acbd1f..00000000 --- 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 6dc9de2d..00000000 --- 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 28380908..00000000 --- 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 28249a0c..00000000 --- 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 b095d354..00000000 --- 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 cd72b8b4..00000000 --- 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 28e2d82b..00000000 --- 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 cf495f9d..00000000 --- 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 3974c58f..00000000 --- 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 c479bbfd..00000000 --- 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 53dfb8c6..00000000 --- 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 aacefc0d..00000000 --- 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 921c6068..00000000 --- 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 d33d7b9d..00000000 --- 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 77ee35d9..00000000 --- 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 5df8df8f..00000000 --- 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 d789a68d..00000000 --- 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 2322e8c8..00000000 --- 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 5676834f..00000000 --- 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 35410889..00000000 --- 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 7563ca04..00000000 --- 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 00bed0b3..00000000 --- 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 d6f8345d..00000000 --- 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 faf8601e..00000000 --- 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 3c6382b7..00000000 --- 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 24c7a383..00000000 --- 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 e9438188..00000000 --- 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 66bc89c3..0e0684ea 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 0620a426..8ce59f00 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 0fb3f6d1..cf009312 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 cbae1c23..36b9c541 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 fb5828a0..efc5549d 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 fc37eada..4e942419 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 c2f85708..1a91151b 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 13eba48e..0d96f8d7 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 f188a7d0..5849756e 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 ae3ac169..aa8724d1 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 14d7b9d8..4fbc89c1 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 b3229f47..3108b392 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 7d5f75e5..2c5b7222 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 c481b628..c60d5958 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 0ae920c2..e1666b1d 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 dfb97956..65293674 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 cdfcca44..8031799e 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 016ddfa8..1d114363 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 8e636c1f..40377836 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 5554b164..b0681569 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 ca0fb567..89e6c182 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 f6538546..18f5508d 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 466da949..eeb7fd97 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 805ceeb7..b855628c 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 f34e8dae..a7e4f9ec 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 9b401bec..e1581c81 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 75f2d7be..d3d74506 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 fe3e7563..62e523e9 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 d5246a74..b2c63c5a 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 6e68fbe5..56b903f0 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 17a68fd4..d7601763 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 6e7f7716..436a391d 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 adcdc1eb..6ba04524 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 9db475f1..a4a823a4 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 80afc36e..49724a1f 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 3fe59219..b04b5b30 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 00000000..0e283611 --- /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 00000000..330fdb86 --- /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 00000000..657fee0d --- /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 33542aa8..b8be03a3 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 42ddfbda..4b6ad213 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 310fa170..fdeae7bc 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 17f03e83..7a4f83d8 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 31836678..415d109b 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 b4710de8..434f27d9 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 06771753..0724fa40 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 389ca354..ddc30615 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 374f0201..4796c769 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 6285e413..d82a3c1d 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 ed719b3c..c29aa647 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 1099cb10..f3ca6ff1 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 c17ab2c5..872f3f06 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 7ad40251..f4f4303d 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 f902444b..e1a2fbf1 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 32c56657..91443d49 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 b41b788d..c244c791 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 8d6345f2..442e3b6e 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 e581021c..4be43fba 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 983e811f..7ea875b2 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 9af0828f..089079fb 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 f6a6403a..cf9709df 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 10d3a018..ebe0e0a8 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 90c48f4d..c4efd84e 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 1300c8e8..911e824a 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 a327de4c..5798dd13 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 7c6f0ff3..dfe10d76 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 80af2fdd..ffccc011 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 feb76ea8..0d3cf93f 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 06a83008..248ad4d7 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 300aea1b..bde21044 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 482b56e0..f875fe69 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 9b9efc0a..51fe2718 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 93336fa3..928c50cc 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 2615f2ee..c20d37ae 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 6b0fc255..573f9189 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 21183507..0d281ab6 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 77e21e30..976f00df 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 d9c954e8..a75a898d 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 efb9d683..78a9245b 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 4699bbdc..1b21bbcf 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 1274e545..6f3aa058 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 3bb54c1e..968e7e4a 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 1b7eea17..98f7df47 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 18b77bf8..2f793ec9 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 d2309ef1..f6782f53 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 982d3629..37fe16bf 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 6413e6df..9b88878a 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 45724b04..63172dac 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 5eb3796e..5bae8fcf 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 3f47e528..8b7de124 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 87dc40b2..9861ebd2 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 8163c147..89bdfb64 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 570aaf1a..0a3e95af 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 040012e2..1431cedd 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 cc19980a..01f963f9 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 c1f9ba96..5b79d709 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 0143a338..b829651e 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 0d1e549c..f081c345 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 18dc9b54..e4698e6e 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 08da5376..da3f3468 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 904a5d3f..ba6bdd1c 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 d4456381..1841ab5c 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 b35e0602..917639ad 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 c52e4f9a..15806da7 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 6668238a..dadedd8d 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 68d2f067..af44337c 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 407c823a..75963104 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 dae8a694..7ed212f5 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 938d08c4..a0a13ea4 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 8ce09f90..88b4533c 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 a11f9bc2..25e65918 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 5dbef6e7..424d963a 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 e34972f5..2c05d243 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 b764b1b3..50c852ba 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 12f42348..d2c25599 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 9da231aa..47ea1e3c 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 81067103..15ff4f85 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 6d131203..e3d4c10e 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 31c70ad2..a69191b8 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 cfb3ec99..a94f2e6c 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 056c3b2e..6bdd650b 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 64f99578..3b4ac120 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 0d2685ef..7ffa717a 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 9752a03f..6c4e76aa 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 c1261027..df47d9a8 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 f67311f2..d077854d 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 919b94d8..f5dd8844 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 dc14b640..7b031112 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 75af63d3..704823dd 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 110503b9..7a8b4516 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 ed9254f6..01d5e3b9 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 0a13ddf3..7c09a818 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 3491e213..4ae4adef 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 38d86be1..10f9bf8c 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 daae9c64..96756909 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 9761cbee..76045f21 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 b3e7f412..cbe49cfb 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 9c9936aa..29247024 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 2997dab6..6918a73e 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 a033e6ed..21fc5510 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 d5d688f6..113ab5b8 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 f4501844..2731e541 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 88eb2d6d..eb1e53d9 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 f1da8bec..154f954f 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 49607952..ffd3abdf 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 262b57e7..da057d66 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 fb89a001..f23cfaf3 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 51c48b9c..1be4f659 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 dbc8bbde..1c2f52fd 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 d1fc319c..5d973e05 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 3b050763..eeccfe25 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 0064b2b1..0f2c057f 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 3d042b3f..c83ec1ae 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 287a38ec..2a19dec9 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 893516c2..b0d4eaa5 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 e6d425ff..1cf5d455 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 18376147..a8408c9b 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 b46410f3..522d9f4b 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 73c2e231..57b6074e 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 b302dd63..5c131627 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 20a11489..a450aade 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 00000000..b2d350b0 --- /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 6e8411ff..ef0ede7b 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 81e9699e..f00b9f92 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 b4250f14..93b54260 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 0b54dbf2..28f1c1cc 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 bc63e46a..3ff1ef03 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 04e6a5ad..7b17a484 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 1c546114..f7679880 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 e5a561f6..96648055 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 1dcc0172..8fd9ada5 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 2e7e92b8..4b04beee 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 363ba0cc..52c79d36 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 98ccaf2d..138b54e2 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 1be51e32..cab9fde2 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 fadd3b76..e5cadde5 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 24c3e440..6e4fa275 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 3d684f6b..b8de0099 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 1646647f..78e065a6 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 288b2384..6aebe2ed 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 4312b4c0..0928abdf 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 5c787213..a027803c 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 b15d7126..5115780f 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 00000000..c049e8b3 --- /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 00000000..8997cf64 --- /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 00000000..16a1e028 --- /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 6a36449f..08c97311 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 2795ca7e..f17d6830 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 b012ce56..842798de 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 6daaf769..913f939e 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 00c88367..f22c9427 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 fecddfb6..d1737cc0 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 ebe791b2..530ea98b 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 efa9f94b..07c2fe59 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 57d86165..7a903501 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 52f9e491..2989f1c2 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 d3dfe06c..cbd37df8 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 ee9a9261..e12b0792 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 7e94be46..737e4e6e 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 63f292ef..d1935115 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 a0115e55..35a4c638 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 2d57e119..5a56c774 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 e4a1733e..37978936 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 c5c5b709..ffd1c6ad 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 0b344440..debe182a 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 eb13692f..f79924a0 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 89d7f7af..9af6eda8 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 4f394036..5601838a 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 f6766273..7d502c12 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 00000000..f2621869 --- /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 037dfd01..435212b5 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 ecde75da..1b851bdb 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 4a6a3354..f8e4bdfe 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 551ad60c..a9897f42 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 b4b5deda..8a7e038f 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 8c4b0791..66156f8e 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 74a2d925..90eb9142 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 3da79e88..d4d2c4f0 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 1cc80979..9091d275 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 b8409c8a..cbefcf62 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 a66aa040..ad2bf7f9 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 5f7e00e9..065bff8c 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 4ee4334e..3137b9bd 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 d768f9b7..41cb045d 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 a2aadf92..c89dae82 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 55bdbf48..8d2e10f2 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 cf9cc077..4ca30a84 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 11efdee7..ab97447f 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 2a89fb73..94fb001e 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 c1123904..958ffa09 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 8779d931..147f354d 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 2999c138..eaf423ad 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 8503f8ef..3f3da8f0 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 bfe2f083..8fb132f6 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 b5ab2ba0..658c3c43 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 49bdee97..f3727eab 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 f15c2e7d..55cab226 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 ef819a5c..37be488b 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 6b0c146f..9fb9f924 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 b220b4f8..30253e6b 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 0f657a68..ebe3011c 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 859309e7..c6fc3f4e 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 59e5fd30..88226a09 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 f62733e2..3ead2ab5 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 f9a9dc0d..5f14c3ea 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 ac47d70b..845db473 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 ec5b59cd..508adb9e 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 5b653fcb..62e6d506 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 7baf8d85..94f3e12f 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 b42d24a3..02377a3c 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 3bd4be59..dc65b1f4 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 8fdcb13c..10eae697 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 753c4d03..1d0e135e 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 6ef83586..bb4e6b35 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 b4cdc3e3..255d43e5 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 b5d092b7..8d2a6e3d 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 0cece71b..219d93b4 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 3c7f1ae5..c0e56fbc 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 a4e3802a..404d4c47 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 6ca80198..6048057f 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 1f4122fd..241692ff 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 00a9f209..961f2cdd 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 e8ea8589..d8a71173 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 2786ff5f..e7792ead 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 cbf664b8..7e3dcedc 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 25da74fb..5525bdc7 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 1b214452..2231d99d 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 1fd9c006..3c172667 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 8bea3cc1..084d578e 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 c581f6ef..956ee274 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 6bfafcea..c4ee5fcc 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 6f7139ea..4c7ac0a5 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 f0905035..d1507688 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 a40f3e76..5942d3c7 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 c9c3a84d..8b5aacab 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 b97a67b4..b6505f3e 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 992a74b1..854b8cf5 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 cb895aa4..7a0a4b10 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 47222ecc..54dcfce6 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 196ebe48..c2858b56 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 81098776..6acc249d 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 15e75e1c..a7839ef7 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 8ef6bdc5..822c2c51 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 74760da7..fa5fa772 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 1e9b82ec..0a78d636 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 8a814d09..9d43a0c2 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 2f61935b..ee235166 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 1f8e4779..c89c4699 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 7ac68b3e..3df6593b 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 5ccacc25..47c294b5 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 800baa55..acbbc807 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 8f580a77..e6ccbd1b 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 f2d08c7c..6b5700e0 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 5972305c..caaf65c8 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 65cc96c6..837c9a29 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 00000000..b94dcb6c --- /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 ce13f534..ab63ea82 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 f9ec374f..efeafa08 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 72a2537c..12684509 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 8b840b81..811dd0ae 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 0fc046d6..c888dc27 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 6cd12c94..970bed28 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 c3a90fe7..1e090334 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 371469e9..fff35e17 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 cdd121fb..ff2648c4 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 4df9fa9a..ffec8d83 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 336d71fd..938f13f8 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 e639077b..7427457d 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 d03e4ab0..f4229862 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 37f9c3f3..1be54ae3 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 f104688b..29a8724d 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 f62c9091..da552c64 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 286ab049..b4c5a18b 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 49edcc6a..56605a0c 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 92cfc6be..0c291716 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 79c07cdb..fe7c6ac7 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 5827ea9e..b7c247b0 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 233c9a44..272b8d68 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 83de50ee..dba14bbf 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 508683ed..75483a41 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 fa6037e5..a4c8e8f0 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 52c76f3e..fd69547e 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 ccff8e95..42fa4d92 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 c66e43fc..008b5c1b 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 b9293c90..e78590c3 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 f3b9b41f..020bc327 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 dbf082c2..5e30e38e 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 87aa3069..772e990b 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 5751606f..19bc15ef 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 c61ed6d2..00000000 --- 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 8233618f..6f07c7bc 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 2dce600a..00000000 --- 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 6c5b5c4e..48c84a69 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 99d7e2b7..36bf47e4 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 55d4f84d..3e4a3119 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 f62b5762..e1b0555d 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 7373f9c6..00000000 --- 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 e91017a7..b04f8a0d 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 0ec5353e..7da9d0f7 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 acacb5c9..cc3356db 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 33fa9092..c2ee29a2 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 8dc765e2..ea297ae4 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 8b34084a..a7c94e73 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 58e03b81..df48ae4d 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 89fe3b70..8103605e 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 f8dbc5d9..8314578b 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 7412d830..3aa79c8f 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 297aa910..ca3d981d 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 0c3511fb..00000000 --- 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 54579c29..81a52b89 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 09cdae51..00000000 --- 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 a7aac2fd..df2b956f 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 e5ac1223..015c3667 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 46ee004c..00000000 --- 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 238b6776..00000000 --- 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 f54e537b..00000000 --- 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 027e69bf..00000000 --- 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 c95bcf20..81f3ff1d 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 87359656..00000000 --- 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 55a1971e..7499a2b4 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 11067227..00000000 --- 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 e5bd9f1b..b6f6121f 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 71060cdb..00000000 --- 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 655cb3e9..00000000 --- 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 34d16d09..00000000 --- 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 181eb221..5d90aabb 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 0277f478..00000000 --- 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 19cf36d8..00000000 --- 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 e1af9d11..257cd7ee 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 b71bbc85..d9d508c7 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 61f25928..00000000 --- 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 4bf42ff5..00000000 --- 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 027e69bf..00000000 --- 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 dd82faff..00000000 --- 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 e7cd31e1..00000000 --- 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 d886c8f5..00000000 --- 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 fd2a11de..05a08e43 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 ebf9803f..00000000 --- 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 dac1303b..1f09e2fc 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 76e4d421..afb41dd2 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 70210644..00000000 --- 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 c2584cf6..e71869ff 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 4d25fd39..00000000 --- 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 3130770d..00000000 --- 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 14668efe..637508e5 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 00000000..eb45934a --- /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 00000000..6f2d20bf --- /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 +}