Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions .ai/checkpoints/catalog-instance-rehydrate.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

35 changes: 31 additions & 4 deletions .ai/specs/dcm-cli.spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ dependencies.
- Policy CRUD operations (create, list, get, update, delete)
- Service type read operations (list, get)
- Catalog item operations (create, list, get, delete)
- Catalog item instance operations (create, list, get, delete)
- Catalog item instance operations (create, list, get, delete, rehydrate)
- SP resource read operations (list, get) via Service Provider Resource Manager
- SP provider read operations (list, get) via Service Provider Manager
- Version display
Expand Down Expand Up @@ -795,8 +795,10 @@ Formatting).
#### Overview

Implement the `dcm catalog instance` command group with subcommands: `create`,
`list`, `get`, `delete`. Instances represent deployed catalog items. No update
operation is supported for instances in v1alpha1.
`list`, `get`, `delete`, `rehydrate`. Instances represent deployed catalog items.
No update operation is supported for instances in v1alpha1. The `rehydrate`
command triggers rehydration of an existing instance, generating a new resource
ID and delegating to the Placement Manager.

Out of scope: instance update/day-2 operations, instance status watching,
instance logs.
Expand All @@ -815,7 +817,9 @@ instance logs.
| REQ-CIN-080 | `dcm catalog instance delete` MUST display a success message in the format `Catalog item instance "<instanceId>" deleted successfully.` | MUST | |
| REQ-CIN-090 | All catalog instance commands MUST use the generated Catalog Manager client | MUST | |
| REQ-CIN-100 | `--from-file` MUST be required for `create` | MUST | |
| REQ-CIN-110 | Missing positional arguments for `get`, `delete` MUST result in a usage error (exit code 2) | MUST | |
| REQ-CIN-110 | Missing positional arguments for `get`, `delete`, `rehydrate` MUST result in a usage error (exit code 2) | MUST | |
| REQ-CIN-120 | `dcm catalog instance rehydrate` MUST accept an `INSTANCE_ID` positional argument and trigger rehydration of the instance | MUST | |
| REQ-CIN-130 | `dcm catalog instance rehydrate` MUST display the rehydrated instance in the configured output format | MUST | |

#### Table Output Columns

Expand Down Expand Up @@ -918,6 +922,29 @@ my-instance c3d4e5f6-a7b8-9012-cdef-123456789012 My App Instance my-catalog
- **And** the API returns a server-side error (e.g., 500 Internal Server Error or 409 Conflict) with RFC 7807 body
- **Then** the CLI MUST display the error in the configured output format and exit with code 1

##### AC-CIN-130: Rehydrate instance

- **Validates:** REQ-CIN-120, REQ-CIN-130
- **Given** an instance with ID `my-instance` exists
- **When** `dcm catalog instance rehydrate my-instance` is invoked
- **Then** a POST request MUST be sent to `/api/v1alpha1/catalog-item-instances/my-instance:rehydrate`
- **And** the rehydrated instance MUST be displayed in the configured output format

##### AC-CIN-140: Rehydrate without INSTANCE_ID

- **Validates:** REQ-CIN-110
- **Given** no positional argument is provided
- **When** `dcm catalog instance rehydrate` is invoked
- **Then** the CLI MUST exit with code 2 and display a usage error

##### AC-CIN-150: Rehydrate non-existent instance

- **Validates:** REQ-CIN-120, REQ-XC-ERR-010
- **Given** no instance with ID `nonexistent` exists
- **When** `dcm catalog instance rehydrate nonexistent` is invoked
- **Then** the API returns a 404 with RFC 7807 body
- **And** the CLI MUST display the error in the configured output format and exit with code 1

#### Dependencies

Depends on Topic 1 (CLI Framework), Topic 2 (Configuration), Topic 3 (Output
Expand Down
42 changes: 40 additions & 2 deletions .ai/test-plans/dcm-cli-unit.test-plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -870,6 +870,42 @@ test classes. Instead:
- **When:** `dcm catalog instance get my-instance` is executed with `--output table`
- **Then:** The table output includes columns: ID, UID, DISPLAY NAME, CATALOG ITEM, RESOURCE ID, CREATED

### TC-U150: Rehydrate instance

- **Requirement:** REQ-CIN-120, REQ-CIN-130
- **Acceptance Criteria:** AC-CIN-130
- **Type:** Unit
- **Given:** A mock server returning 200 with a rehydrated instance
- **When:** `dcm catalog instance rehydrate my-instance` is executed
- **Then:** A POST request is sent to `/api/v1alpha1/catalog-item-instances/my-instance:rehydrate` AND the rehydrated instance is displayed in the configured output format

### TC-U151: Rehydrate instance without INSTANCE_ID fails

- **Requirement:** REQ-CIN-110
- **Acceptance Criteria:** AC-CIN-140
- **Type:** Unit
- **Given:** No positional argument is provided
- **When:** `dcm catalog instance rehydrate` is executed
- **Then:** The CLI exits with code 2 and displays a usage error

### TC-U152: Rehydrate non-existent instance

- **Requirement:** REQ-CIN-120, REQ-XC-ERR-010
- **Acceptance Criteria:** AC-CIN-150, AC-XC-ERR-010
- **Type:** Unit
- **Given:** A mock server returning 404 with RFC 7807 body for instance ID `nonexistent`
- **When:** `dcm catalog instance rehydrate nonexistent` is executed
- **Then:** The CLI displays the error in the configured output format AND exits with code 1

### TC-U153: Rehydrate instance server error

- **Requirement:** REQ-CIN-120, REQ-XC-ERR-010
- **Acceptance Criteria:** AC-XC-ERR-010
- **Type:** Unit
- **Given:** A mock server returning 500 with RFC 7807 body
- **When:** `dcm catalog instance rehydrate my-instance` is executed
- **Then:** The CLI displays the error in the configured output format AND exits with code 1

---

## 9 · SP Resource Commands
Expand Down Expand Up @@ -1575,7 +1611,9 @@ dedicated test class or `Describe` block.
| REQ-CIN-080 | TC-U077 | Covered |
| REQ-CIN-090 | TC-U067 (via TC-U058, TC-U073, TC-U075, TC-U077) | Covered |
| REQ-CIN-100 | TC-U072 | Covered |
| REQ-CIN-110 | TC-U076, TC-U078 | Covered |
| REQ-CIN-110 | TC-U076, TC-U078, TC-U151 | Covered |
| REQ-CIN-120 | TC-U150, TC-U152, TC-U153 | Covered |
| REQ-CIN-130 | TC-U150 | Covered |
| REQ-SPR-010 | TC-U121, TC-U122, TC-U123 | Covered |
| REQ-SPR-020 | TC-U121 | Covered |
| REQ-SPR-030 | TC-U124 | Covered |
Expand Down Expand Up @@ -1624,7 +1662,7 @@ dedicated test class or `Describe` block.
| REQ-XC-TLS-070 | TC-U095, TC-U096 | Covered |
| REQ-XC-TLS-080 | TC-U090, TC-U097 | Covered |

**Total:** 113 test case IDs — 87 in behavioural test classes, 26 in the utility
**Total:** 117 test case IDs — 91 in behavioural test classes, 26 in the utility
index (tested transitively through higher-level behavioural tests).

---
Expand Down
12 changes: 7 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module github.com/dcm-project/cli
go 1.25.5

require (
github.com/dcm-project/catalog-manager v0.0.0-20260313160905-1ff110850088
github.com/dcm-project/catalog-manager v0.0.0-20260408124701-1315c44e39b9
github.com/dcm-project/policy-manager v0.0.0-20260310132113-15bd45617e87
github.com/dcm-project/service-provider-manager v0.0.0-20260324094657-8aad860d86d2
github.com/onsi/ginkgo/v2 v2.28.1
Expand All @@ -16,6 +16,7 @@ require (
require (
github.com/Masterminds/semver/v3 v3.4.0 // indirect
github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/fsnotify/fsnotify v1.9.0 // indirect
github.com/getkin/kin-openapi v0.134.0 // indirect
github.com/go-logr/logr v1.4.3 // indirect
Expand All @@ -30,23 +31,24 @@ require (
github.com/josharian/intern v1.0.0 // indirect
github.com/mailru/easyjson v0.9.1 // indirect
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
github.com/oapi-codegen/runtime v1.3.0 // indirect
github.com/oapi-codegen/runtime v1.3.1 // indirect
github.com/oasdiff/yaml v0.0.0-20260313112342-a3ea61cb4d4c // indirect
github.com/oasdiff/yaml3 v0.0.0-20260224194419-61cd415a242b // indirect
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
github.com/perimeterx/marshmallow v1.1.5 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // 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/spf13/pflag v1.0.10 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/woodsbury/decimal128 v1.4.0 // indirect
golang.org/x/mod v0.32.0 // indirect
golang.org/x/net v0.49.0 // indirect
golang.org/x/mod v0.33.0 // indirect
golang.org/x/net v0.50.0 // indirect
golang.org/x/sync v0.19.0 // indirect
golang.org/x/sys v0.42.0 // indirect
golang.org/x/text v0.34.0 // indirect
golang.org/x/tools v0.41.0 // indirect
golang.org/x/tools v0.42.0 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
)
27 changes: 14 additions & 13 deletions go.sum

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

41 changes: 41 additions & 0 deletions internal/commands/catalog_instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ func newCatalogInstanceCommand() *cobra.Command {
cmd.AddCommand(newCatalogInstanceListCommand())
cmd.AddCommand(newCatalogInstanceGetCommand())
cmd.AddCommand(newCatalogInstanceDeleteCommand())
cmd.AddCommand(newCatalogInstanceRehydrateCommand())

return cmd
}
Expand Down Expand Up @@ -215,6 +216,46 @@ func newCatalogInstanceGetCommand() *cobra.Command {
}
}

func newCatalogInstanceRehydrateCommand() *cobra.Command {
return &cobra.Command{
Use: "rehydrate INSTANCE_ID",
Short: "Rehydrate a catalog item instance",
Args: ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
cfg := config.FromCommand(cmd)
formatter, err := newFormatter(cmd, catalogInstanceTableDef, "catalog instance rehydrate")
if err != nil {
return err
}

client, err := newCatalogClient(cfg)
if err != nil {
return fmt.Errorf("creating catalog client: %w", err)
}

ctx, cancel := requestContext(cmd)
defer cancel()

resp, err := client.RehydrateCatalogItemInstance(ctx, args[0])
if err != nil {
return connectionError(err, cfg)
}
defer func() { _ = resp.Body.Close() }()

if resp.StatusCode != http.StatusOK {
return handleErrorResponse(resp, formatter)
}

var result map[string]any
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
return fmt.Errorf("parsing response: %w", err)
}

return formatter.FormatOne(result)
},
}
}

func newCatalogInstanceDeleteCommand() *cobra.Command {
return &cobra.Command{
Use: "delete INSTANCE_ID",
Expand Down
Loading