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
4 changes: 0 additions & 4 deletions cmd/hyperfleet-api/server/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,6 @@ func (s *apiServer) routes() *mux.Router {
apiV1Router.HandleFunc("/openapi.html", openapiHandler.GetOpenAPIUI).Methods(http.MethodGet)
apiV1Router.HandleFunc("/openapi", openapiHandler.GetOpenAPI).Methods(http.MethodGet)

// /api/hyperfleet/v1/compatibility
compatibilityHandler := handlers.NewCompatibilityHandler()
apiV1Router.HandleFunc("/compatibility", compatibilityHandler.Get).Methods(http.MethodGet)

registerApiMiddleware(apiV1Router)

// Auto-discovered routes (no manual editing needed)
Expand Down
111 changes: 57 additions & 54 deletions openapi/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ info:
version: 1.0.0
contact:
name: HyperFleet Team
license:
name: Apache 2.0
url: https://www.apache.org/licenses/LICENSE-2.0
description: |-
HyperFleet API provides simple CRUD operations for managing cluster resources and their status history.

Expand All @@ -29,6 +32,8 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/ClusterList'
'400':
description: The server could not understand the request due to invalid syntax.
default:
description: An unexpected error response.
content:
Expand All @@ -52,6 +57,8 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/Cluster'
'400':
description: The server could not understand the request due to invalid syntax.
default:
description: An unexpected error response.
content:
Expand Down Expand Up @@ -82,6 +89,8 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/Cluster'
'400':
description: The server could not understand the request due to invalid syntax.
default:
description: An unexpected error response.
content:
Expand Down Expand Up @@ -112,6 +121,8 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/NodePoolList'
'400':
description: The server could not understand the request due to invalid syntax.
default:
description: An unexpected error response.
content:
Expand All @@ -136,6 +147,8 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/NodePoolCreateResponse'
'400':
description: The server could not understand the request due to invalid syntax.
default:
description: An unexpected error response.
content:
Expand Down Expand Up @@ -173,47 +186,15 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/NodePool'
'400':
description: The server could not understand the request due to invalid syntax.
default:
description: An unexpected error response.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/api/hyperfleet/v1/clusters/{cluster_id}/nodepools/{nodepool_id}/statuses:
get:
operationId: getNodePoolsStatuses
summary: List all adapter statuses for nodepools
description: Returns adapter status reports for this nodepool
parameters:
- name: cluster_id
in: path
required: true
description: Cluster ID
schema:
type: string
- name: nodepool_id
in: path
required: true
schema:
type: string
- $ref: '#/components/parameters/QueryParams.page'
- $ref: '#/components/parameters/QueryParams.pageSize'
- $ref: '#/components/parameters/QueryParams.orderBy'
- $ref: '#/components/parameters/QueryParams.order'
- $ref: '#/components/parameters/SearchParams'
responses:
'200':
description: The request has succeeded.
content:
application/json:
schema:
$ref: '#/components/schemas/AdapterStatusList'
default:
description: An unexpected error response.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
post:
operationId: postNodePoolStatuses
summary: Create or update adapter status
Expand Down Expand Up @@ -254,18 +235,22 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/AdapterStatusCreateRequest'
/api/hyperfleet/v1/clusters/{cluster_id}/statuses:
get:
operationId: getClusterStatuses
summary: List all adapter statuses for cluster
description: Returns adapter status reports for this cluster
operationId: getNodePoolsStatuses
summary: List all adapter statuses for nodepools
description: Returns adapter status reports for this nodepool
parameters:
- name: cluster_id
in: path
required: true
description: Cluster ID
schema:
type: string
- name: nodepool_id
in: path
required: true
schema:
type: string
- $ref: '#/components/parameters/QueryParams.page'
- $ref: '#/components/parameters/QueryParams.pageSize'
- $ref: '#/components/parameters/QueryParams.orderBy'
Expand All @@ -278,8 +263,15 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/AdapterStatusList'
'404':
description: The server cannot find the requested resource.
'400':
description: The server could not understand the request due to invalid syntax.
default:
description: An unexpected error response.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/api/hyperfleet/v1/clusters/{cluster_id}/statuses:
post:
operationId: postClusterStatuses
summary: Create or update adapter status
Expand Down Expand Up @@ -315,11 +307,17 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/AdapterStatusCreateRequest'
/api/hyperfleet/v1/compatibility:
get:
operationId: getCompatibility
description: Returns the list of all nodepools
operationId: getClusterStatuses
summary: List all adapter statuses for cluster
description: Returns adapter status reports for this cluster
parameters:
- name: cluster_id
in: path
required: true
description: Cluster ID
schema:
type: string
- $ref: '#/components/parameters/QueryParams.page'
- $ref: '#/components/parameters/QueryParams.pageSize'
- $ref: '#/components/parameters/QueryParams.orderBy'
Expand All @@ -329,11 +327,13 @@ paths:
'200':
description: The request has succeeded.
content:
text/plain:
application/json:
schema:
type: string
security:
- BearerAuth: []
$ref: '#/components/schemas/AdapterStatusList'
'400':
description: The server could not understand the request due to invalid syntax.
'404':
description: The server cannot find the requested resource.
/api/hyperfleet/v1/nodepools:
get:
operationId: getNodePools
Expand All @@ -352,13 +352,20 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/NodePoolList'
'400':
description: The server could not understand the request due to invalid syntax.
default:
description: An unexpected error response.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
components:
securitySchemes:
BearerAuth:
type: http
scheme: bearer

parameters:
QueryParams.order:
name: order
Expand Down Expand Up @@ -702,7 +709,7 @@ components:
default: Cluster
name:
type: string
minLength: 1
minLength: 3
maxLength: 63
pattern: ^[a-z0-9-]+$
description: Cluster name (unique)
Expand Down Expand Up @@ -1194,11 +1201,7 @@ components:
- Ready
- Failed
description: Phase of a resource (Cluster or NodePool)
securitySchemes:
BearerAuth:
type: http
scheme: bearer
servers:
- url: http://localhost:8000
description: Development
- url: https://api.hyperfleet.redhat.com
description: Production
variables: {}
3 changes: 0 additions & 3 deletions pkg/api/cluster_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,6 @@ func (c *Cluster) BeforeCreate(tx *gorm.DB) error {
c.ID = NewID()
c.CreatedTime = now
c.UpdatedTime = now
if c.Kind == "" {
c.Kind = "Cluster"
}
if c.Generation == 0 {
c.Generation = 1
}
Expand Down
10 changes: 6 additions & 4 deletions pkg/api/cluster_types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,14 @@ func TestCluster_BeforeCreate_IDGeneration(t *testing.T) {
Expect(len(cluster.ID)).To(BeNumerically(">", 0))
}

// TestCluster_BeforeCreate_KindDefault tests Kind default value
func TestCluster_BeforeCreate_KindDefault(t *testing.T) {
// TestCluster_BeforeCreate_KindPreservation tests Kind is preserved (not auto-set)
func TestCluster_BeforeCreate_KindPreservation(t *testing.T) {
RegisterTestingT(t)

// Test default Kind
// Kind must be set before BeforeCreate (by handler validation)
cluster := &Cluster{
Name: "test-cluster",
Kind: "Cluster",
}

err := cluster.BeforeCreate(nil)
Expand Down Expand Up @@ -189,14 +190,15 @@ func TestCluster_BeforeCreate_Complete(t *testing.T) {

cluster := &Cluster{
Name: "test-cluster",
Kind: "Cluster", // Kind must be set before BeforeCreate
}

err := cluster.BeforeCreate(nil)
Expect(err).To(BeNil())

// Verify all defaults
Expect(cluster.ID).ToNot(BeEmpty())
Expect(cluster.Kind).To(Equal("Cluster"))
Expect(cluster.Kind).To(Equal("Cluster")) // Kind is preserved, not auto-set
Expect(cluster.Generation).To(Equal(int32(1)))
Expect(cluster.StatusPhase).To(Equal("NotReady"))
Expect(cluster.Href).To(Equal("/api/hyperfleet/v1/clusters/" + cluster.ID))
Expand Down
3 changes: 0 additions & 3 deletions pkg/api/node_pool_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,6 @@ func (np *NodePool) BeforeCreate(tx *gorm.DB) error {
np.ID = NewID()
np.CreatedTime = now
np.UpdatedTime = now
if np.Kind == "" {
np.Kind = "NodePool"
}
if np.OwnerKind == "" {
np.OwnerKind = "Cluster"
}
Expand Down
10 changes: 6 additions & 4 deletions pkg/api/node_pool_types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,14 +68,15 @@ func TestNodePool_BeforeCreate_IDGeneration(t *testing.T) {
Expect(len(nodepool.ID)).To(BeNumerically(">", 0))
}

// TestNodePool_BeforeCreate_KindDefault tests Kind default value
func TestNodePool_BeforeCreate_KindDefault(t *testing.T) {
// TestNodePool_BeforeCreate_KindPreservation tests Kind is preserved (not auto-set)
func TestNodePool_BeforeCreate_KindPreservation(t *testing.T) {
RegisterTestingT(t)

// Test default Kind
// Kind must be set before BeforeCreate (by handler validation)
nodepool := &NodePool{
Name: "test-nodepool",
OwnerID: "cluster-123",
Kind: "NodePool",
}

err := nodepool.BeforeCreate(nil)
Expand Down Expand Up @@ -230,14 +231,15 @@ func TestNodePool_BeforeCreate_Complete(t *testing.T) {
nodepool := &NodePool{
Name: "test-nodepool",
OwnerID: "cluster-complete",
Kind: "NodePool", // Kind must be set before BeforeCreate
}

err := nodepool.BeforeCreate(nil)
Expect(err).To(BeNil())

// Verify all defaults
Expect(nodepool.ID).ToNot(BeEmpty())
Expect(nodepool.Kind).To(Equal("NodePool"))
Expect(nodepool.Kind).To(Equal("NodePool")) // Kind is preserved, not auto-set
Expect(nodepool.OwnerKind).To(Equal("Cluster"))
Expect(nodepool.StatusPhase).To(Equal("NotReady"))
Expect(nodepool.Href).To(Equal("/api/hyperfleet/v1/clusters/cluster-complete/nodepools/" + nodepool.ID))
Expand Down
1 change: 0 additions & 1 deletion pkg/api/openapi_embed.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,3 @@ var openapiFS embed.FS
func GetOpenAPISpec() ([]byte, error) {
return fs.ReadFile(openapiFS, "openapi/api/openapi.yaml")
}

4 changes: 2 additions & 2 deletions pkg/api/presenters/adapter_status_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ func TestConvertAdapterStatus_ConditionStatusConversion(t *testing.T) {
RegisterTestingT(t)

testCases := []struct {
openapiStatus openapi.ConditionStatus
openapiStatus openapi.ConditionStatus
expectedDomain api.ConditionStatus
}{
{openapi.TRUE, api.ConditionTrue},
Expand Down Expand Up @@ -361,7 +361,7 @@ func TestPresentAdapterStatus_ConditionStatusConversion(t *testing.T) {
RegisterTestingT(t)

testCases := []struct {
domainStatus api.ConditionStatus
domainStatus api.ConditionStatus
expectedOpenAPI openapi.ConditionStatus
}{
{api.ConditionTrue, openapi.TRUE},
Expand Down
1 change: 0 additions & 1 deletion pkg/auth/auth_middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"fmt"
"net/http"


"github.com/openshift-hyperfleet/hyperfleet-api/pkg/errors"
)

Expand Down
12 changes: 6 additions & 6 deletions pkg/dao/mocks/generic.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ import (
var _ dao.GenericDao = &genericDaoMock{}

type genericDaoMock struct {
preload string
orderBy string
joins string
group string
wheres []dao.Where
model interface{}
preload string
orderBy string
joins string
group string
wheres []dao.Where
model interface{}
}

func NewGenericDao() *genericDaoMock {
Expand Down
2 changes: 2 additions & 0 deletions pkg/handlers/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ func (h clusterHandler) Create(w http.ResponseWriter, r *http.Request) {
&req,
[]validate{
validateEmpty(&req, "Id", "id"),
validateName(&req, "Name", "name", 3, 63),
validateKind(&req, "Kind", "kind", "Cluster"),
},
func() (interface{}, *errors.ServiceError) {
ctx := r.Context()
Expand Down
Loading