Skip to content

Commit 55c7f37

Browse files
Merge pull request #31 from mliptak0/HYPERFLEET-543
HYPERFLEET-543 - feat: add soft-delete endpoints for clusters and nodepools
2 parents 0f0a404 + ffcaec9 commit 55c7f37

16 files changed

Lines changed: 1377 additions & 38 deletions

File tree

CHANGELOG.md

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1717

1818
- Improved README.md structure to align with HyperFleet documentation standards
1919

20+
## [1.0.6] - 2026-04-13
21+
22+
### Added
23+
24+
- DELETE endpoint for clusters with soft-delete semantics (returns 202, sets `deleted_time`)
25+
- DELETE endpoint for nodepools with soft-delete semantics and cascade support
26+
- `deleted_time` and `deleted_by` optional fields to API metadata
27+
28+
### Changed
29+
30+
- Renamed `APICreatedResource` model to `APIMetadata` to reflect broader scope
31+
2032
## [1.0.2] - 2026-01-13
2133

2234
### Added
@@ -51,6 +63,7 @@ First official stable release of the HyperFleet API specification.
5163
- Interactive API documentation
5264

5365
<!-- Links -->
54-
[Unreleased]: https://github.com/openshift-hyperfleet/hyperfleet-api-spec/compare/v1.0.2...HEAD
66+
[Unreleased]: https://github.com/openshift-hyperfleet/hyperfleet-api-spec/compare/v1.0.6...HEAD
67+
[1.0.6]: https://github.com/openshift-hyperfleet/hyperfleet-api-spec/compare/v1.0.2...v1.0.6
5568
[1.0.2]: https://github.com/openshift-hyperfleet/hyperfleet-api-spec/compare/v1.0.0...v1.0.2
5669
[1.0.0]: https://github.com/openshift-hyperfleet/hyperfleet-api-spec/releases/tag/v1.0.0

CLAUDE.md

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,12 @@ npm run build:all # Generate all variants with Swagger
1313

1414
**Validation workflow:**
1515
```bash
16-
npm install # Install dependencies
17-
npm run build:core # Build and verify compilation
18-
npm run build:gcp # Build GCP variant
19-
ls -l schemas/*/openapi.yaml # Confirm outputs exist
16+
npm install # Install dependencies
17+
./build-schema.sh gcp # Build GCP OpenAPI 3.0
18+
./build-schema.sh gcp --swagger # Build GCP OpenAPI 2.0 (Swagger)
19+
./build-schema.sh core # Build core OpenAPI 3.0
20+
./build-schema.sh core --swagger # Build core OpenAPI 2.0 (Swagger)
21+
ls -l schemas/*/openapi.yaml # Confirm outputs exist
2022
```
2123

2224
## Key Concepts
@@ -98,7 +100,11 @@ services/
98100
- Commit `node_modules/` or build artifacts
99101

100102
**DO:**
101-
- Run `npm run build:all` before committing schema changes
103+
- Run builds in this order before committing schema changes:
104+
1. `./build-schema.sh gcp`
105+
2. `./build-schema.sh gcp --swagger`
106+
3. `./build-schema.sh core`
107+
4. `./build-schema.sh core --swagger`
102108
- Test both provider variants when modifying shared models
103109
- Keep TypeSpec files focused (one resource per service file)
104110
- Use semantic versioning for releases (see RELEASING.md)
@@ -187,8 +193,10 @@ Build: `npm run build:gcp`
187193
Before submitting changes:
188194

189195
- [ ] Dependencies installed: `npm install`
190-
- [ ] Core variant builds: `npm run build:core`
191-
- [ ] GCP variant builds: `npm run build:gcp`
196+
- [ ] GCP variant builds: `./build-schema.sh gcp`
197+
- [ ] GCP Swagger builds: `./build-schema.sh gcp --swagger`
198+
- [ ] Core variant builds: `./build-schema.sh core`
199+
- [ ] Core Swagger builds: `./build-schema.sh core --swagger`
192200
- [ ] Schema files generated: `ls schemas/*/openapi.yaml`
193201
- [ ] No TypeSpec compilation errors (check output)
194202
- [ ] Changes committed including schema updates

main.tsp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ using OpenAPI;
2020
*
2121
*/
2222
@service(#{ title: "HyperFleet API" })
23-
@info(#{ version: "1.0.5", contact: #{ name: "HyperFleet Team" }, license: #{ name: "Apache 2.0" ,url: "https://www.apache.org/licenses/LICENSE-2.0"} })
23+
@info(#{ version: "1.0.6", contact: #{ name: "HyperFleet Team" }, license: #{ name: "Apache 2.0" ,url: "https://www.apache.org/licenses/LICENSE-2.0"} })
2424
@server("https://hyperfleet.redhat.com", "Production")
2525
@route("/api/hyperfleet/v1")
2626
namespace HyperFleet;

models-core/cluster/example_cluster.tsp

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@ const exampleCluster: Cluster = #{
99
name: "cluster-123",
1010
labels: #{ environment: "production", team: "platform" },
1111
spec: #{},
12-
created_time: "2021-01-01T00:00:00Z",
13-
updated_time: "2021-01-01T00:00:00Z",
1412
generation: 1,
1513
status: #{
1614
conditions: #[
@@ -56,6 +54,68 @@ const exampleCluster: Cluster = #{
5654
},
5755
],
5856
},
57+
created_time: "2021-01-01T00:00:00Z",
58+
updated_time: "2021-01-01T10:02:00Z",
59+
created_by: "user-123@example.com",
60+
updated_by: "user-123@example.com",
61+
};
62+
63+
const exampleDeletedCluster: Cluster = #{
64+
kind: "Cluster",
65+
id: "019466a0-8f8e-7abc-9def-0123456789ab",
66+
href: "https://api.hyperfleet.com/v1/clusters/019466a0-8f8e-7abc-9def-0123456789ab",
67+
name: "cluster-123",
68+
labels: #{ environment: "production", team: "platform" },
69+
spec: #{},
70+
generation: 2,
71+
status: #{
72+
conditions: #[
73+
#{
74+
type: ConditionType.Ready,
75+
status: ResourceConditionStatus.True,
76+
reason: ExampleReadyReason,
77+
message: ExampleReadyMessage,
78+
observed_generation: 1,
79+
created_time: "2021-01-01T10:00:00Z",
80+
last_updated_time: "2021-01-01T10:00:00Z",
81+
last_transition_time: "2021-01-01T10:00:00Z",
82+
},
83+
#{
84+
type: ConditionType.Available,
85+
status: ResourceConditionStatus.True,
86+
reason: ExampleAvailableReason,
87+
message: ExampleAvailableMessage,
88+
observed_generation: 1,
89+
created_time: "2021-01-01T10:00:00Z",
90+
last_updated_time: "2021-01-01T10:00:00Z",
91+
last_transition_time: "2021-01-01T10:00:00Z",
92+
},
93+
#{
94+
type: "Adapter1Successful",
95+
status: ResourceConditionStatus.True,
96+
reason: ExampleAdapter1AvaliableReason,
97+
message: ExampleAdapter1AvaliableMessage,
98+
observed_generation: 1,
99+
created_time: "2021-01-01T10:00:00Z",
100+
last_updated_time: "2021-01-01T10:00:00Z",
101+
last_transition_time: "2021-01-01T10:00:00Z",
102+
},
103+
#{
104+
type: "Adapter2Successful",
105+
status: ResourceConditionStatus.True,
106+
reason: ExampleAdapter2AvaliableReason,
107+
message: ExampleAdapter2AvaliableMessage,
108+
observed_generation: 1,
109+
created_time: "2021-01-01T10:01:00Z",
110+
last_updated_time: "2021-01-01T10:01:00Z",
111+
last_transition_time: "2021-01-01T10:01:00Z",
112+
},
113+
],
114+
},
115+
created_time: "2021-01-01T00:00:00Z",
116+
updated_time: "2021-01-01T10:02:00Z",
117+
deleted_time: "2021-01-01T10:05:00Z",
59118
created_by: "user-123@example.com",
60119
updated_by: "user-123@example.com",
120+
deleted_by: "user-123@example.com",
61121
};

models-core/nodepool/example_nodepool.tsp

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,69 @@ const exampleNodePool: NodePool = #{
1010
labels: #{ environment: "production", pooltype: "worker" },
1111
spec: #{},
1212
generation: 1,
13+
owner_references: #{
14+
id: "019466a0-8f8e-7abc-9def-0123456789ab",
15+
kind: "Cluster",
16+
href: "https://api.hyperfleet.com/v1/clusters/019466a0-8f8e-7abc-9def-0123456789ab",
17+
},
18+
status: #{
19+
conditions: #[
20+
#{
21+
type: ConditionType.Ready,
22+
status: ResourceConditionStatus.True,
23+
reason: ExampleReadyReason,
24+
message: ExampleReadyMessage,
25+
observed_generation: 1,
26+
created_time: "2021-01-01T10:00:00Z",
27+
last_updated_time: "2021-01-01T10:00:00Z",
28+
last_transition_time: "2021-01-01T10:00:00Z",
29+
},
30+
#{
31+
type: ConditionType.Available,
32+
status: ResourceConditionStatus.True,
33+
reason: ExampleAvailableReason,
34+
message: ExampleAvailableMessage,
35+
observed_generation: 1,
36+
created_time: "2021-01-01T10:00:00Z",
37+
last_updated_time: "2021-01-01T10:00:00Z",
38+
last_transition_time: "2021-01-01T10:00:00Z",
39+
},
40+
#{
41+
type: "Adapter1Successful",
42+
status: ResourceConditionStatus.True,
43+
reason: ExampleAdapter1AvaliableReason,
44+
message: ExampleAdapter1AvaliableMessage,
45+
observed_generation: 1,
46+
created_time: "2021-01-01T10:00:00Z",
47+
last_updated_time: "2021-01-01T10:00:00Z",
48+
last_transition_time: "2021-01-01T10:00:00Z",
49+
},
50+
#{
51+
type: "Adapter2Successful",
52+
status: ResourceConditionStatus.True,
53+
reason: ExampleAdapter2AvaliableReason,
54+
message: ExampleAdapter2AvaliableMessage,
55+
observed_generation: 1,
56+
created_time: "2021-01-01T10:01:00Z",
57+
last_updated_time: "2021-01-01T10:01:00Z",
58+
last_transition_time: "2021-01-01T10:01:00Z",
59+
},
60+
],
61+
},
1362
created_time: "2021-01-01T00:00:00Z",
14-
updated_time: "2021-01-01T00:00:00Z",
63+
updated_time: "2021-01-01T10:02:00Z",
1564
created_by: "user-123@example.com",
1665
updated_by: "user-123@example.com",
66+
};
67+
68+
const exampleDeletedNodePool: NodePool = #{
69+
kind: "NodePool",
70+
id: "019466a1-2b3c-7def-8abc-456789abcdef",
71+
href: "https://api.hyperfleet.com/v1/nodepools/019466a1-2b3c-7def-8abc-456789abcdef",
72+
name: "worker-pool-1",
73+
labels: #{ environment: "production", pooltype: "worker" },
74+
spec: #{},
75+
generation: 2,
1776
owner_references: #{
1877
id: "019466a0-8f8e-7abc-9def-0123456789ab",
1978
kind: "Cluster",
@@ -63,4 +122,10 @@ const exampleNodePool: NodePool = #{
63122
},
64123
],
65124
},
125+
created_time: "2021-01-01T00:00:00Z",
126+
updated_time: "2021-01-01T10:02:00Z",
127+
deleted_time: "2021-01-01T10:05:00Z",
128+
created_by: "user-123@example.com",
129+
updated_by: "user-123@example.com",
130+
deleted_by: "user-123@example.com",
66131
};

models-gcp/cluster/example_cluster.tsp

Lines changed: 84 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,6 @@ const exampleCluster: Cluster = #{
3131
baseDomain: "example.com",
3232
},
3333
},
34-
created_time: "2021-01-01T00:00:00Z",
35-
updated_time: "2021-01-01T00:00:00Z",
3634
generation: 1,
3735
status: #{
3836
conditions: #[
@@ -78,6 +76,90 @@ const exampleCluster: Cluster = #{
7876
}
7977
],
8078
},
79+
created_time: "2021-01-01T00:00:00Z",
80+
updated_time: "2021-01-01T10:02:00Z",
81+
created_by: "user-123@example.com",
82+
updated_by: "user-123@example.com",
83+
};
84+
85+
const exampleDeletedCluster: Cluster = #{
86+
kind: "Cluster",
87+
id: "019466a0-8f8e-7abc-9def-0123456789ab",
88+
href: "https://api.hyperfleet.com/v1/clusters/019466a0-8f8e-7abc-9def-0123456789ab",
89+
name: "cluster-123",
90+
labels: #{ environment: "production", team: "platform" },
91+
spec: #{
92+
platform: #{
93+
type: "gcp",
94+
gcp: #{
95+
projectID: "project-123",
96+
region: "us-central1",
97+
zone: "us-central1-a",
98+
network: "network-123",
99+
subnet: "subnet-123",
100+
},
101+
},
102+
release: #{
103+
image: "registry.redhat.io/openshift4/ose-cluster-version-operator:v4.14.0",
104+
version: "4.14.0",
105+
},
106+
networking: #{
107+
clusterNetwork: #[ #{ cidr: "10.10.0.0/16", hostPrefix: 24 } ],
108+
serviceNetwork: #["10.96.0.0/12"],
109+
},
110+
dns: #{
111+
baseDomain: "example.com",
112+
},
113+
},
114+
generation: 2,
115+
status: #{
116+
conditions: #[
117+
#{
118+
type: ConditionType.Ready,
119+
status: ResourceConditionStatus.True,
120+
reason: ExampleReadyReason,
121+
message: ExampleReadyMessage,
122+
observed_generation: 1,
123+
created_time: "2021-01-01T10:00:00Z",
124+
last_updated_time: "2021-01-01T10:00:00Z",
125+
last_transition_time: "2021-01-01T10:00:00Z",
126+
},
127+
#{
128+
type: ConditionType.Available,
129+
status: ResourceConditionStatus.True,
130+
reason: ExampleAvailableReason,
131+
message: ExampleAvailableMessage,
132+
observed_generation: 1,
133+
created_time: "2021-01-01T10:00:00Z",
134+
last_updated_time: "2021-01-01T10:00:00Z",
135+
last_transition_time: "2021-01-01T10:00:00Z",
136+
},
137+
#{
138+
type: "Adapter1Successful",
139+
status: ResourceConditionStatus.True,
140+
reason: ExampleAdapter1AvaliableReason,
141+
message: ExampleAdapter1AvaliableMessage,
142+
observed_generation: 1,
143+
created_time: "2021-01-01T10:00:00Z",
144+
last_updated_time: "2021-01-01T10:00:00Z",
145+
last_transition_time: "2021-01-01T10:00:00Z",
146+
},
147+
#{
148+
type: "Adapter2Successful",
149+
status: ResourceConditionStatus.True,
150+
reason: ExampleAdapter2AvaliableReason,
151+
message: ExampleAdapter2AvaliableMessage,
152+
observed_generation: 1,
153+
created_time: "2021-01-01T10:01:00Z",
154+
last_updated_time: "2021-01-01T10:01:00Z",
155+
last_transition_time: "2021-01-01T10:01:00Z",
156+
}
157+
],
158+
},
159+
created_time: "2021-01-01T00:00:00Z",
160+
updated_time: "2021-01-01T10:02:00Z",
161+
deleted_time: "2021-01-01T10:05:00Z",
81162
created_by: "user-123@example.com",
82163
updated_by: "user-123@example.com",
164+
deleted_by: "user-123@example.com",
83165
};

0 commit comments

Comments
 (0)