diff --git a/main.tsp b/main.tsp index 5980b87..f4a537d 100644 --- a/main.tsp +++ b/main.tsp @@ -20,7 +20,7 @@ using OpenAPI; * */ @service(#{ title: "HyperFleet API" }) -@info(#{ version: "1.0.3", contact: #{ name: "HyperFleet Team" }, license: #{ name: "Apache 2.0" ,url: "https://www.apache.org/licenses/LICENSE-2.0"} }) +@info(#{ version: "1.0.4", contact: #{ name: "HyperFleet Team" }, license: #{ name: "Apache 2.0" ,url: "https://www.apache.org/licenses/LICENSE-2.0"} }) @server("https://hyperfleet.redhat.com", "Production") @route("/api/hyperfleet/v1") namespace HyperFleet; diff --git a/models-core/cluster/example_cluster.tsp b/models-core/cluster/example_cluster.tsp index 674a92d..b7034ee 100644 --- a/models-core/cluster/example_cluster.tsp +++ b/models-core/cluster/example_cluster.tsp @@ -1,5 +1,6 @@ import "../../aliases-core.tsp"; import "../../models/clusters/model.tsp"; +import "../../models/common/model.tsp"; const exampleCluster: Cluster = #{ kind: "Cluster", @@ -12,26 +13,42 @@ const exampleCluster: Cluster = #{ updated_time: "2021-01-01T00:00:00Z", generation: 1, status: #{ - phase: ResourcePhase.Ready, - last_transition_time: "2021-01-01T00:00:00Z", - observed_generation: 1, - last_updated_time: "2021-01-01T00:00:00Z", conditions: #[ #{ - type: "ValidationSuccessful", - status: ConditionStatus.True, - reason: "All validations passed", - message: "All 30 validation tests passed", + type: ConditionType.Ready, + status: ResourceConditionStatus.True, + reason: ExampleReadyReason, + message: ExampleReadyMessage, observed_generation: 1, created_time: "2021-01-01T10:00:00Z", last_updated_time: "2021-01-01T10:00:00Z", last_transition_time: "2021-01-01T10:00:00Z", }, #{ - type: "DNSSuccessful", - status: ConditionStatus.True, - reason: "DNS configured", - message: "DNS records created for custom.domain.com", + type: ConditionType.Available, + status: ResourceConditionStatus.True, + reason: ExampleAvailableReason, + message: ExampleAvailableMessage, + observed_generation: 1, + created_time: "2021-01-01T10:00:00Z", + last_updated_time: "2021-01-01T10:00:00Z", + last_transition_time: "2021-01-01T10:00:00Z", + }, + #{ + type: "Adapter1Successful", + status: ResourceConditionStatus.True, + reason: ExampleAdapter1AvaliableReason, + message: ExampleAdapter1AvaliableMessage, + observed_generation: 1, + created_time: "2021-01-01T10:00:00Z", + last_updated_time: "2021-01-01T10:00:00Z", + last_transition_time: "2021-01-01T10:00:00Z", + }, + #{ + type: "Adapter2Successful", + status: ResourceConditionStatus.True, + reason: ExampleAdapter2AvaliableReason, + message: ExampleAdapter2AvaliableMessage, observed_generation: 1, created_time: "2021-01-01T10:01:00Z", last_updated_time: "2021-01-01T10:01:00Z", diff --git a/models-core/nodepool/example_nodepool.tsp b/models-core/nodepool/example_nodepool.tsp index f7f175f..349a518 100644 --- a/models-core/nodepool/example_nodepool.tsp +++ b/models-core/nodepool/example_nodepool.tsp @@ -1,5 +1,6 @@ import "../../aliases-core.tsp"; import "../../models/nodepools/model.tsp"; +import "../../models/common/model.tsp"; const exampleNodePool: NodePool = #{ kind: "NodePool", @@ -19,26 +20,42 @@ const exampleNodePool: NodePool = #{ href: "https://api.hyperfleet.com/v1/clusters/cluster-123", }, status: #{ - phase: ResourcePhase.Ready, - last_transition_time: "2021-01-01T10:00:00Z", - observed_generation: 1, - last_updated_time: "2021-01-01T10:02:00Z", conditions: #[ #{ - type: "ValidationSuccessful", - status: ConditionStatus.True, - reason: "All validations passed", - message: "NodePool validation passed", + type: ConditionType.Ready, + status: ResourceConditionStatus.True, + reason: ExampleReadyReason, + message: ExampleReadyMessage, observed_generation: 1, created_time: "2021-01-01T10:00:00Z", last_updated_time: "2021-01-01T10:00:00Z", last_transition_time: "2021-01-01T10:00:00Z", }, #{ - type: "NodePoolSuccessful", - status: ConditionStatus.True, - reason: "NodePool provisioned successfully", - message: "NodePool has been scaled to desired count", + type: ConditionType.Available, + status: ResourceConditionStatus.True, + reason: ExampleAvailableReason, + message: ExampleAvailableMessage, + observed_generation: 1, + created_time: "2021-01-01T10:00:00Z", + last_updated_time: "2021-01-01T10:00:00Z", + last_transition_time: "2021-01-01T10:00:00Z", + }, + #{ + type: "Adapter1Successful", + status: ResourceConditionStatus.True, + reason: ExampleAdapter1AvaliableReason, + message: ExampleAdapter1AvaliableMessage, + observed_generation: 1, + created_time: "2021-01-01T10:00:00Z", + last_updated_time: "2021-01-01T10:00:00Z", + last_transition_time: "2021-01-01T10:00:00Z", + }, + #{ + type: "Adapter2Successful", + status: ResourceConditionStatus.True, + reason: ExampleAdapter2AvaliableReason, + message: ExampleAdapter2AvaliableMessage, observed_generation: 1, created_time: "2021-01-01T10:01:00Z", last_updated_time: "2021-01-01T10:01:00Z", diff --git a/models-gcp/cluster/example_cluster.tsp b/models-gcp/cluster/example_cluster.tsp index a0e0116..a732e36 100644 --- a/models-gcp/cluster/example_cluster.tsp +++ b/models-gcp/cluster/example_cluster.tsp @@ -1,5 +1,6 @@ import "../../aliases-gcp.tsp"; import "../../models/clusters/model.tsp"; +import "../../models/common/model.tsp"; const exampleCluster: Cluster = #{ kind: "Cluster", @@ -34,26 +35,42 @@ const exampleCluster: Cluster = #{ updated_time: "2021-01-01T00:00:00Z", generation: 1, status: #{ - phase: ResourcePhase.Ready, - last_transition_time: "2021-01-01T00:00:00Z", - observed_generation: 1, - last_updated_time: "2021-01-01T00:00:00Z", conditions: #[ #{ - type: "ValidationSuccessful", - status: ConditionStatus.True, - reason: "All validations passed", - message: "All 30 validation tests passed", + type: ConditionType.Ready, + status: ResourceConditionStatus.True, + reason: ExampleReadyReason, + message: ExampleReadyMessage, observed_generation: 1, created_time: "2021-01-01T10:00:00Z", last_updated_time: "2021-01-01T10:00:00Z", last_transition_time: "2021-01-01T10:00:00Z", }, #{ - type: "DNSSuccessful", - status: ConditionStatus.True, - reason: "DNS configured", - message: "DNS records created for custom.domain.com", + type: ConditionType.Available, + status: ResourceConditionStatus.True, + reason: ExampleAvailableReason, + message: ExampleAvailableMessage, + observed_generation: 1, + created_time: "2021-01-01T10:00:00Z", + last_updated_time: "2021-01-01T10:00:00Z", + last_transition_time: "2021-01-01T10:00:00Z", + }, + #{ + type: "Adapter1Successful", + status: ResourceConditionStatus.True, + reason: ExampleAdapter1AvaliableReason, + message: ExampleAdapter1AvaliableMessage, + observed_generation: 1, + created_time: "2021-01-01T10:00:00Z", + last_updated_time: "2021-01-01T10:00:00Z", + last_transition_time: "2021-01-01T10:00:00Z", + }, + #{ + type: "Adapter2Successful", + status: ResourceConditionStatus.True, + reason: ExampleAdapter2AvaliableReason, + message: ExampleAdapter2AvaliableMessage, observed_generation: 1, created_time: "2021-01-01T10:01:00Z", last_updated_time: "2021-01-01T10:01:00Z", @@ -63,4 +80,4 @@ const exampleCluster: Cluster = #{ }, created_by: "user-123@example.com", updated_by: "user-123@example.com", -}; \ No newline at end of file +}; diff --git a/models-gcp/nodepool/example_nodepool.tsp b/models-gcp/nodepool/example_nodepool.tsp index 05b633e..3f158fc 100644 --- a/models-gcp/nodepool/example_nodepool.tsp +++ b/models-gcp/nodepool/example_nodepool.tsp @@ -41,14 +41,30 @@ const exampleNodePool: NodePool = #{ href: "https://api.hyperfleet.com/v1/clusters/cluster-123", }, status: #{ - phase: ResourcePhase.Ready, - last_transition_time: "2021-01-01T10:00:00Z", - observed_generation: 1, - last_updated_time: "2021-01-01T10:02:00Z", conditions: #[ + #{ + type: ConditionType.Ready, + status: ResourceConditionStatus.True, + reason: "ResourceReady", + message: "All conditions successful for current spec generation", + observed_generation: 1, + created_time: "2021-01-01T10:00:00Z", + last_updated_time: "2021-01-01T10:00:00Z", + last_transition_time: "2021-01-01T10:00:00Z", + }, + #{ + type: ConditionType.Available, + status: ResourceConditionStatus.True, + reason: "ResourceAvailable", + message: "All conditions successful for observed_generation", + observed_generation: 1, + created_time: "2021-01-01T10:00:00Z", + last_updated_time: "2021-01-01T10:00:00Z", + last_transition_time: "2021-01-01T10:00:00Z", + }, #{ type: "ValidationSuccessful", - status: ConditionStatus.True, + status: ResourceConditionStatus.True, reason: "All validations passed", message: "NodePool validation passed", observed_generation: 1, @@ -58,7 +74,7 @@ const exampleNodePool: NodePool = #{ }, #{ type: "NodePoolSuccessful", - status: ConditionStatus.True, + status: ResourceConditionStatus.True, reason: "NodePool provisioned successfully", message: "NodePool has 3 nodes running", observed_generation: 1, diff --git a/models/clusters/model.tsp b/models/clusters/model.tsp index f83d65b..56975d0 100644 --- a/models/clusters/model.tsp +++ b/models/clusters/model.tsp @@ -22,32 +22,20 @@ model ClusterBase { * This object is computed by the service and CANNOT be modified directly. * It is aggregated from condition updates posted to `/clusters/{id}/statuses`. * - * Provides quick overview of all reported conditions and aggregated phase. + * Provides quick overview of all reported conditions. */ model ClusterStatus { - phase: ResourcePhase; /** - * When cluster last transitioned (used by Sentinel for backoff) - * Updated when conditions are reported if the phase changes + * List of status conditions for the cluster. + * + * **Mandatory conditions**: + * - `type: "Ready"`: Whether all adapters report successfully at the current generation. + * - `type: "Available"`: Aggregated adapter result for a common observed_generation. + * + * These conditions are present immediately upon resource creation. */ - @format("date-time") last_transition_time: string; - - /** - * Last generation processed - * Updated when conditions are reported. - * This will be the lowest value of each condition's observed_generation values - * The phase value is based on this generation - */ - observed_generation: int32; - - /** Time of the last update - * Updated when conditions are reported. - * Computed as min(conditions[].last_updated_time) to detect stale adapters. - * Uses earliest (not latest) timestamp to ensure Sentinel can detect if any adapter has stopped reporting. - */ - @format("date-time") last_updated_time: string; - + @minItems(2) conditions: ResourceCondition[]; } diff --git a/models/common/model.tsp b/models/common/model.tsp index 6dd70aa..d9356f2 100644 --- a/models/common/model.tsp +++ b/models/common/model.tsp @@ -10,15 +10,6 @@ alias KindClusterStatus = "ClusterStatus"; alias KindNodePoolStatus = "NodePoolStatus"; alias KindNodePool = "NodePool"; -/** - * Phase of a resource (Cluster or NodePool) - */ -enum ResourcePhase { - NotReady, - Ready, - Failed, -} - model ID { /** Resource identifier */ id?: Identifier; @@ -140,7 +131,7 @@ enum OrderDirection { model SearchParams { /** Filter results using TSL (Tree Search Language) query syntax. - * Examples: `status.phase='NotReady'`, `name in ('c1','c2')`, `labels.region='us-east'` */ + * Examples: `status.conditions.Ready='True'`, `name in ('c1','c2')`, `labels.region='us-east'` */ @query search?: string; } @@ -167,3 +158,91 @@ model List { total: int32; items: T[]; } + +union ConditionType { + string, + Available: "Available", + Ready: "Ready" +} + +/** + * Base condition fields shared by all condition types + */ +model ConditionBase { + /** + * Condition type + */ + type: string; + + /** + * Machine-readable reason code + */ + reason?: string; + + /** + * Human-readable message + */ + message?: string; + + /** + * When this condition last transitioned status (API-managed) + * Only updated when status changes (True/False), not when reason/message changes + */ + @format("date-time") last_transition_time: string; +} + +/** + * Status value for adapter conditions + */ +enum AdapterConditionStatus { + True: "True", + False: "False", + Unknown, +} + +/** + * Condition in Cluster/NodePool status + * Used for semantic condition types: "ValidationSuccessful", "DNSSuccessful", "NodePoolSuccessful", etc. + * Includes observed_generation and last_updated_time to track adapter-specific state + */ +model ResourceCondition { + ...ConditionBase; + + status: ResourceConditionStatus; + + /** + * Generation of the spec that this condition reflects + */ + observed_generation: int32; + + /** + * When this condition was first created (API-managed) + */ + @format("date-time") created_time: string; + + /** + * When the corresponding adapter last reported (API-managed) + * Updated every time the adapter POSTs, even if condition status hasn't changed + * Copied from AdapterStatus.last_report_time + */ + @format("date-time") last_updated_time: string; +} + + const ExampleAvailableReason: string = "All adapters reported Available True for the same generation"; + const ExampleAvailableMessage: string = "All adapters reported Available True for the same generation"; + const ExampleReadyReason: string = "All adapters reported Ready True for the current generation"; + const ExampleReadyMessage: string = "All adapters reported Ready True for the current generation"; + const ExampleAdapter1: string = "adapter1"; + const ExampleAdapter2: string = "adapter2"; + const ExampleAdapter1AppliedReason: string = "Validation job applied"; + const ExampleAdapter1AppliedMessage: string = "Adapter1 validation job applied successfully"; + const ExampleAdapter1HealthReason: string = "All adapter1 operations completed successfully"; + const ExampleAdapter1HealthMessage: string = "All adapter1 runtime operations completed successfully"; + const ExampleAdapter1AvaliableReason: string = "This adapter1 is available"; + const ExampleAdapter1AvaliableMessage: string = "This adapter1 is available"; + const ExampleAdapter2AppliedReason: string = "Validation job applied"; + const ExampleAdapter2AppliedMessage: string = "Adapter2 validation job applied successfully"; + const ExampleAdapter2HealthReason: string = "All adapter2 operations completed successfully"; + const ExampleAdapter2HealthMessage: string = "All adapter2 runtime operations completed successfully"; + const ExampleAdapter2AvaliableReason: string = "This adapter2 is available"; + const ExampleAdapter2AvaliableMessage: string = "This adapter2 is available"; diff --git a/models/nodepools/model.tsp b/models/nodepools/model.tsp index c15f72a..45a9b83 100644 --- a/models/nodepools/model.tsp +++ b/models/nodepools/model.tsp @@ -22,29 +22,17 @@ model NodePoolBase { * This object is computed by the service and CANNOT be modified directly. */ model NodePoolStatus { - phase: ResourcePhase; /** - * Last generation processed - * Updated when conditions are reported. - * This will be the lowest value of each condition's observed_generation values - * The phase value is based on this generation + * List of status conditions for the nodepool. + * + * **Mandatory conditions**: + * - `type: "Ready"`: Whether all adapters report successfully at the current generation. + * - `type: "Available"`: Aggregated adapter result for a common observed_generation. + * + * These conditions are present immediately upon resource creation. */ - @minValue(1) - observed_generation: int32; - - /** - * When NodePool last transitioned (used by Sentinel for backoff) - */ - @format("date-time") last_transition_time: string; - - /** Time of the last update - * Updated when conditions are reported. - * Computed as min(conditions[].last_updated_time) to detect stale adapters. - * Uses earliest (not latest) timestamp to ensure Sentinel can detect if any adapter has stopped reporting. - */ - @format("date-time") last_updated_time: string; - + @minItems(2) conditions: ResourceCondition[]; } diff --git a/models/statuses/example_adapter_status.tsp b/models/statuses/example_adapter_status.tsp index d4e5e3c..5e47d72 100644 --- a/models/statuses/example_adapter_status.tsp +++ b/models/statuses/example_adapter_status.tsp @@ -1,29 +1,30 @@ import "../../models/statuses/model.tsp"; +import "../../models/common/model.tsp"; // Example AdapterStatus for validator adapter const exampleAdapterStatus: AdapterStatus = (#{ - adapter: "validator", + adapter: ExampleAdapter1, observed_generation: 1, conditions: #[ #{ - type: "Available", - status: ConditionStatus.True, - reason: "All validations passed", - message: "All 30 validation tests passed", + type: ConditionType.Available, + status: AdapterConditionStatus.True, + reason: ExampleAdapter1AvaliableReason, + message: ExampleAdapter1AvaliableMessage, last_transition_time: "2021-01-01T10:00:00Z", }, #{ type: "Applied", - status: ConditionStatus.True, - reason: "Validation job applied", - message: "Validation job applied successfully", + status: AdapterConditionStatus.True, + reason: ExampleAdapter1AppliedReason, + message: ExampleAdapter1AppliedMessage, last_transition_time: "2021-01-01T10:00:00Z", }, #{ type: "Health", - status: ConditionStatus.True, - reason: "All adapter operations completed successfully", - message: "All adapter runtime operations completed successfully", + status: AdapterConditionStatus.True, + reason: ExampleAdapter1HealthReason, + message: ExampleAdapter1HealthMessage, last_transition_time: "2021-01-01T10:00:00Z", } ], @@ -53,22 +54,22 @@ const exampleAdapterStatusCreateRequest: AdapterStatusCreateRequest = (#{ observed_time: "2021-01-01T10:00:00Z", conditions: #[ #{ - type: "Available", - status: ConditionStatus.True, - reason: "All validations passed", - message: "All 30 validation tests passed", + type: ConditionType.Available, + status: AdapterConditionStatus.True, + reason: ExampleAdapter1AvaliableReason, + message: ExampleAdapter1AvaliableMessage, }, #{ type: "Applied", - status: ConditionStatus.True, - reason: "Validation job applied", - message: "Validation job applied successfully", + status: AdapterConditionStatus.True, + reason: ExampleAdapter1AppliedReason, + message: ExampleAdapter1AppliedMessage, }, #{ type: "Health", - status: ConditionStatus.True, - reason: "All adapter operations completed successfully", - message: "All adapter runtime operations completed successfully", + status: AdapterConditionStatus.True, + reason: ExampleAdapter1HealthReason, + message: ExampleAdapter1HealthMessage, } ], metadata: #{ @@ -96,14 +97,14 @@ const exampleAdapterStatusList: AdapterStatusList = (#{ total: 2, items: #[ #{ - adapter: "validator", + adapter: ExampleAdapter1, observed_generation: 1, conditions: #[ #{ - type: "Available", - status: ConditionStatus.True, - reason: "All validations passed", - message: "All 30 validation tests passed", + type: ConditionType.Available, + status: AdapterConditionStatus.True, + reason: ExampleAdapter1AvaliableReason, + message: ExampleAdapter1AvaliableMessage, last_transition_time: "2021-01-01T10:00:00Z", }, ], @@ -115,14 +116,14 @@ const exampleAdapterStatusList: AdapterStatusList = (#{ last_report_time: "2021-01-01T10:02:00Z", }, #{ - adapter: "dns", + adapter: ExampleAdapter2, observed_generation: 1, conditions: #[ #{ - type: "Available", - status: ConditionStatus.True, - reason: "DNS configured", - message: "DNS records created", + type: ConditionType.Available, + status: AdapterConditionStatus.True, + reason: ExampleAdapter2AvaliableReason, + message: ExampleAdapter2AvaliableMessage, last_transition_time: "2021-01-01T10:01:00Z", }, ], diff --git a/models/statuses/model.tsp b/models/statuses/model.tsp index 61a387c..d95061b 100644 --- a/models/statuses/model.tsp +++ b/models/statuses/model.tsp @@ -2,40 +2,11 @@ import "../common/model.tsp"; import "./example_adapter_status.tsp"; /** - * Status value for conditions + * Status value for resource conditions */ -enum ConditionStatus { +enum ResourceConditionStatus { True: "True", False: "False", - Unknown, -} - -/** - * Base condition fields shared by all condition types - */ -model ConditionBase { - /** - * Condition type - */ - type: string; - - status: ConditionStatus; - - /** - * Machine-readable reason code - */ - reason?: string; - - /** - * Human-readable message - */ - message?: string; - - /** - * When this condition last transitioned status (API-managed) - * Only updated when status changes (True/False/Unknown), not when reason/message changes - */ - @format("date-time") last_transition_time: string; } /** @@ -46,41 +17,18 @@ model ConditionBase { */ model AdapterCondition { ...ConditionBase; - // No additional fields - inherits all fields from ConditionBase -} -/** - * Condition in Cluster/NodePool status - * Used for semantic condition types: "ValidationSuccessful", "DNSSuccessful", "NodePoolSuccessful", etc. - * Includes observed_generation and last_updated_time to track adapter-specific state - */ -model ResourceCondition { - ...ConditionBase; - /** - * Generation of the spec that this condition reflects - */ - observed_generation: int32; - - /** - * When this condition was first created (API-managed) - */ - @format("date-time") created_time: string; - - /** - * When the corresponding adapter last reported (API-managed) - * Updated every time the adapter POSTs, even if condition status hasn't changed - * Copied from AdapterStatus.last_report_time - */ - @format("date-time") last_updated_time: string; + status: AdapterConditionStatus; } + /** * Condition data for create/update requests (from adapters) * observed_generation and observed_time are now at AdapterStatusCreateRequest level */ model ConditionRequest { type: string; - status: ConditionStatus; + status: AdapterConditionStatus; reason?: string; message?: string; } diff --git a/schemas/core/openapi.yaml b/schemas/core/openapi.yaml index 28168b6..46f47e7 100644 --- a/schemas/core/openapi.yaml +++ b/schemas/core/openapi.yaml @@ -1,7 +1,7 @@ openapi: 3.0.0 info: title: HyperFleet API - version: 1.0.3 + version: 1.0.4 contact: name: HyperFleet Team license: @@ -49,8 +49,8 @@ paths: Create a new cluster resource. **Note**: The `status` object in the response is read-only and computed by the service. - It is NOT part of the request body. Initially, status.phase will be "NotReady" and - status.conditions will be empty until status conditions are POSTed. + It is NOT part of the request body. Initially, + status.conditions will include mandatory "Available" and "Ready" conditions. parameters: [] responses: '201': @@ -419,7 +419,7 @@ components: required: false description: |- Filter results using TSL (Tree Search Language) query syntax. - Examples: `status.phase='NotReady'`, `name in ('c1','c2')`, `labels.region='us-east'` + Examples: `status.conditions.Ready='True'`, `name in ('c1','c2')`, `labels.region='us-east'` schema: type: string explode: false @@ -428,14 +428,12 @@ components: type: object required: - type - - status - last_transition_time + - status properties: type: type: string description: Condition type - status: - $ref: '#/components/schemas/ConditionStatus' reason: type: string description: Machine-readable reason code @@ -447,12 +445,21 @@ components: format: date-time description: |- When this condition last transitioned status (API-managed) - Only updated when status changes (True/False/Unknown), not when reason/message changes + Only updated when status changes (True/False), not when reason/message changes + status: + $ref: '#/components/schemas/AdapterConditionStatus' description: |- Condition in AdapterStatus Used for standard Kubernetes condition types: "Available", "Applied", "Health" Note: observed_generation is at AdapterStatus level, not per-condition, since all conditions in one AdapterStatus share the same observed generation + AdapterConditionStatus: + type: string + enum: + - 'True' + - 'False' + - Unknown + description: Status value for adapter conditions AdapterStatus: type: object required: @@ -514,23 +521,23 @@ components: AdapterStatus represents the complete status report from an adapter Contains multiple conditions, job metadata, and adapter-specific data example: - adapter: validator + adapter: adapter1 observed_generation: 1 conditions: - type: Available status: 'True' - reason: All validations passed - message: All 30 validation tests passed + reason: This adapter1 is available + message: This adapter1 is available last_transition_time: '2021-01-01T10:00:00Z' - type: Applied status: 'True' reason: Validation job applied - message: Validation job applied successfully + message: Adapter1 validation job applied successfully last_transition_time: '2021-01-01T10:00:00Z' - type: Health status: 'True' - reason: All adapter operations completed successfully - message: All adapter runtime operations completed successfully + reason: All adapter1 operations completed successfully + message: All adapter1 runtime operations completed successfully last_transition_time: '2021-01-01T10:00:00Z' metadata: job_name: validator-job-abc123 @@ -602,16 +609,16 @@ components: conditions: - type: Available status: 'True' - reason: All validations passed - message: All 30 validation tests passed + reason: This adapter1 is available + message: This adapter1 is available - type: Applied status: 'True' reason: Validation job applied - message: Validation job applied successfully + message: Adapter1 validation job applied successfully - type: Health status: 'True' - reason: All adapter operations completed successfully - message: All adapter runtime operations completed successfully + reason: All adapter1 operations completed successfully + message: All adapter1 runtime operations completed successfully metadata: job_name: validator-job-abc123 job_namespace: hyperfleet-system @@ -655,26 +662,26 @@ components: size: 2 total: 2 items: - - adapter: validator + - adapter: adapter1 observed_generation: 1 conditions: - type: Available status: 'True' - reason: All validations passed - message: All 30 validation tests passed + reason: This adapter1 is available + message: This adapter1 is available last_transition_time: '2021-01-01T10:00:00Z' metadata: job_name: validator-job-abc123 duration: 2m created_time: '2021-01-01T10:00:00Z' last_report_time: '2021-01-01T10:02:00Z' - - adapter: dns + - adapter: adapter2 observed_generation: 1 conditions: - type: Available status: 'True' - reason: DNS configured - message: DNS records created + reason: This adapter2 is available + message: This adapter2 is available last_transition_time: '2021-01-01T10:01:00Z' created_time: '2021-01-01T10:01:00Z' last_report_time: '2021-01-01T10:01:30Z' @@ -758,23 +765,35 @@ components: updated_time: '2021-01-01T00:00:00Z' generation: 1 status: - phase: Ready - last_transition_time: '2021-01-01T00:00:00Z' - observed_generation: 1 - last_updated_time: '2021-01-01T00:00:00Z' conditions: - - type: ValidationSuccessful + - type: Ready + status: 'True' + reason: All adapters reported Ready True for the current generation + message: All adapters reported Ready True for the current generation + observed_generation: 1 + created_time: '2021-01-01T10:00:00Z' + last_updated_time: '2021-01-01T10:00:00Z' + last_transition_time: '2021-01-01T10:00:00Z' + - type: Available + status: 'True' + reason: All adapters reported Available True for the same generation + message: All adapters reported Available True for the same generation + observed_generation: 1 + created_time: '2021-01-01T10:00:00Z' + last_updated_time: '2021-01-01T10:00:00Z' + last_transition_time: '2021-01-01T10:00:00Z' + - type: Adapter1Successful status: 'True' - reason: All validations passed - message: All 30 validation tests passed + reason: This adapter1 is available + message: This adapter1 is available observed_generation: 1 created_time: '2021-01-01T10:00:00Z' last_updated_time: '2021-01-01T10:00:00Z' last_transition_time: '2021-01-01T10:00:00Z' - - type: DNSSuccessful + - type: Adapter2Successful status: 'True' - reason: DNS configured - message: DNS records created for custom.domain.com + reason: This adapter2 is available + message: This adapter2 is available observed_generation: 1 created_time: '2021-01-01T10:01:00Z' last_updated_time: '2021-01-01T10:01:00Z' @@ -849,47 +868,28 @@ components: ClusterStatus: type: object required: - - phase - - last_transition_time - - observed_generation - - last_updated_time - conditions properties: - phase: - $ref: '#/components/schemas/ResourcePhase' - last_transition_time: - type: string - format: date-time - description: |- - When cluster last transitioned (used by Sentinel for backoff) - Updated when conditions are reported if the phase changes - observed_generation: - type: integer - format: int32 - description: |- - Last generation processed - Updated when conditions are reported. - This will be the lowest value of each condition's observed_generation values - The phase value is based on this generation - last_updated_time: - type: string - format: date-time - description: |- - Time of the last update - Updated when conditions are reported. - Computed as min(conditions[].last_updated_time) to detect stale adapters. - Uses earliest (not latest) timestamp to ensure Sentinel can detect if any adapter has stopped reporting. conditions: type: array items: $ref: '#/components/schemas/ResourceCondition' + minItems: 2 + description: |- + List of status conditions for the cluster. + + **Mandatory conditions**: + - `type: "Ready"`: Whether all adapters report successfully at the current generation. + - `type: "Available"`: Aggregated adapter result for a common observed_generation. + + These conditions are present immediately upon resource creation. description: |- Cluster status computed from all status conditions. This object is computed by the service and CANNOT be modified directly. It is aggregated from condition updates posted to `/clusters/{id}/statuses`. - Provides quick overview of all reported conditions and aggregated phase. + Provides quick overview of all reported conditions. ConditionRequest: type: object required: @@ -899,7 +899,7 @@ components: type: type: string status: - $ref: '#/components/schemas/ConditionStatus' + $ref: '#/components/schemas/AdapterConditionStatus' reason: type: string message: @@ -907,13 +907,6 @@ components: description: |- Condition data for create/update requests (from adapters) observed_generation and observed_time are now at AdapterStatusCreateRequest level - ConditionStatus: - type: string - enum: - - 'True' - - 'False' - - Unknown - description: Status value for conditions Error: type: object required: @@ -1037,23 +1030,35 @@ components: kind: Cluster href: https://api.hyperfleet.com/v1/clusters/cluster-123 status: - phase: Ready - last_transition_time: '2021-01-01T10:00:00Z' - observed_generation: 1 - last_updated_time: '2021-01-01T10:02:00Z' conditions: - - type: ValidationSuccessful + - type: Ready + status: 'True' + reason: All adapters reported Ready True for the current generation + message: All adapters reported Ready True for the current generation + observed_generation: 1 + created_time: '2021-01-01T10:00:00Z' + last_updated_time: '2021-01-01T10:00:00Z' + last_transition_time: '2021-01-01T10:00:00Z' + - type: Available status: 'True' - reason: All validations passed - message: NodePool validation passed + reason: All adapters reported Available True for the same generation + message: All adapters reported Available True for the same generation observed_generation: 1 created_time: '2021-01-01T10:00:00Z' last_updated_time: '2021-01-01T10:00:00Z' last_transition_time: '2021-01-01T10:00:00Z' - - type: NodePoolSuccessful + - type: Adapter1Successful status: 'True' - reason: NodePool provisioned successfully - message: NodePool has been scaled to desired count + reason: This adapter1 is available + message: This adapter1 is available + observed_generation: 1 + created_time: '2021-01-01T10:00:00Z' + last_updated_time: '2021-01-01T10:00:00Z' + last_transition_time: '2021-01-01T10:00:00Z' + - type: Adapter2Successful + status: 'True' + reason: This adapter2 is available + message: This adapter2 is available observed_generation: 1 created_time: '2021-01-01T10:01:00Z' last_updated_time: '2021-01-01T10:01:00Z' @@ -1181,39 +1186,21 @@ components: NodePoolStatus: type: object required: - - phase - - observed_generation - - last_transition_time - - last_updated_time - conditions properties: - phase: - $ref: '#/components/schemas/ResourcePhase' - observed_generation: - type: integer - format: int32 - minimum: 1 - description: |- - Last generation processed - Updated when conditions are reported. - This will be the lowest value of each condition's observed_generation values - The phase value is based on this generation - last_transition_time: - type: string - format: date-time - description: When NodePool last transitioned (used by Sentinel for backoff) - last_updated_time: - type: string - format: date-time - description: |- - Time of the last update - Updated when conditions are reported. - Computed as min(conditions[].last_updated_time) to detect stale adapters. - Uses earliest (not latest) timestamp to ensure Sentinel can detect if any adapter has stopped reporting. conditions: type: array items: $ref: '#/components/schemas/ResourceCondition' + minItems: 2 + description: |- + List of status conditions for the nodepool. + + **Mandatory conditions**: + - `type: "Ready"`: Whether all adapters report successfully at the current generation. + - `type: "Available"`: Aggregated adapter result for a common observed_generation. + + These conditions are present immediately upon resource creation. description: |- NodePool status computed from all status conditions. @@ -1239,8 +1226,8 @@ components: type: object required: - type - - status - last_transition_time + - status - observed_generation - created_time - last_updated_time @@ -1248,8 +1235,6 @@ components: type: type: string description: Condition type - status: - $ref: '#/components/schemas/ConditionStatus' reason: type: string description: Machine-readable reason code @@ -1261,7 +1246,9 @@ components: format: date-time description: |- When this condition last transitioned status (API-managed) - Only updated when status changes (True/False/Unknown), not when reason/message changes + Only updated when status changes (True/False), not when reason/message changes + status: + $ref: '#/components/schemas/ResourceConditionStatus' observed_generation: type: integer format: int32 @@ -1281,13 +1268,12 @@ components: Condition in Cluster/NodePool status Used for semantic condition types: "ValidationSuccessful", "DNSSuccessful", "NodePoolSuccessful", etc. Includes observed_generation and last_updated_time to track adapter-specific state - ResourcePhase: + ResourceConditionStatus: type: string enum: - - NotReady - - Ready - - Failed - description: Phase of a resource (Cluster or NodePool) + - 'True' + - 'False' + description: Status value for resource conditions ValidationError: type: object required: diff --git a/schemas/gcp/openapi.yaml b/schemas/gcp/openapi.yaml index 478faff..5c513f8 100644 --- a/schemas/gcp/openapi.yaml +++ b/schemas/gcp/openapi.yaml @@ -1,7 +1,7 @@ openapi: 3.0.0 info: title: HyperFleet API - version: 1.0.3 + version: 1.0.4 contact: name: HyperFleet Team license: @@ -49,8 +49,8 @@ paths: Create a new cluster resource. **Note**: The `status` object in the response is read-only and computed by the service. - It is NOT part of the request body. Initially, status.phase will be "NotReady" and - status.conditions will be empty until status conditions are POSTed. + It is NOT part of the request body. Initially, + status.conditions will include mandatory "Available" and "Ready" conditions. parameters: [] responses: '201': @@ -342,7 +342,7 @@ components: required: false description: |- Filter results using TSL (Tree Search Language) query syntax. - Examples: `status.phase='NotReady'`, `name in ('c1','c2')`, `labels.region='us-east'` + Examples: `status.conditions.Ready='True'`, `name in ('c1','c2')`, `labels.region='us-east'` schema: type: string explode: false @@ -362,14 +362,12 @@ components: type: object required: - type - - status - last_transition_time + - status properties: type: type: string description: Condition type - status: - $ref: '#/components/schemas/ConditionStatus' reason: type: string description: Machine-readable reason code @@ -381,12 +379,21 @@ components: format: date-time description: |- When this condition last transitioned status (API-managed) - Only updated when status changes (True/False/Unknown), not when reason/message changes + Only updated when status changes (True/False), not when reason/message changes + status: + $ref: '#/components/schemas/AdapterConditionStatus' description: |- Condition in AdapterStatus Used for standard Kubernetes condition types: "Available", "Applied", "Health" Note: observed_generation is at AdapterStatus level, not per-condition, since all conditions in one AdapterStatus share the same observed generation + AdapterConditionStatus: + type: string + enum: + - 'True' + - 'False' + - Unknown + description: Status value for adapter conditions AdapterStatus: type: object required: @@ -448,23 +455,23 @@ components: AdapterStatus represents the complete status report from an adapter Contains multiple conditions, job metadata, and adapter-specific data example: - adapter: validator + adapter: adapter1 observed_generation: 1 conditions: - type: Available status: 'True' - reason: All validations passed - message: All 30 validation tests passed + reason: This adapter1 is available + message: This adapter1 is available last_transition_time: '2021-01-01T10:00:00Z' - type: Applied status: 'True' reason: Validation job applied - message: Validation job applied successfully + message: Adapter1 validation job applied successfully last_transition_time: '2021-01-01T10:00:00Z' - type: Health status: 'True' - reason: All adapter operations completed successfully - message: All adapter runtime operations completed successfully + reason: All adapter1 operations completed successfully + message: All adapter1 runtime operations completed successfully last_transition_time: '2021-01-01T10:00:00Z' metadata: job_name: validator-job-abc123 @@ -511,26 +518,26 @@ components: size: 2 total: 2 items: - - adapter: validator + - adapter: adapter1 observed_generation: 1 conditions: - type: Available status: 'True' - reason: All validations passed - message: All 30 validation tests passed + reason: This adapter1 is available + message: This adapter1 is available last_transition_time: '2021-01-01T10:00:00Z' metadata: job_name: validator-job-abc123 duration: 2m created_time: '2021-01-01T10:00:00Z' last_report_time: '2021-01-01T10:02:00Z' - - adapter: dns + - adapter: adapter2 observed_generation: 1 conditions: - type: Available status: 'True' - reason: DNS configured - message: DNS records created + reason: This adapter2 is available + message: This adapter2 is available last_transition_time: '2021-01-01T10:01:00Z' created_time: '2021-01-01T10:01:00Z' last_report_time: '2021-01-01T10:01:30Z' @@ -656,23 +663,35 @@ components: updated_time: '2021-01-01T00:00:00Z' generation: 1 status: - phase: Ready - last_transition_time: '2021-01-01T00:00:00Z' - observed_generation: 1 - last_updated_time: '2021-01-01T00:00:00Z' conditions: - - type: ValidationSuccessful + - type: Ready status: 'True' - reason: All validations passed - message: All 30 validation tests passed + reason: All adapters reported Ready True for the current generation + message: All adapters reported Ready True for the current generation + observed_generation: 1 + created_time: '2021-01-01T10:00:00Z' + last_updated_time: '2021-01-01T10:00:00Z' + last_transition_time: '2021-01-01T10:00:00Z' + - type: Available + status: 'True' + reason: All adapters reported Available True for the same generation + message: All adapters reported Available True for the same generation observed_generation: 1 created_time: '2021-01-01T10:00:00Z' last_updated_time: '2021-01-01T10:00:00Z' last_transition_time: '2021-01-01T10:00:00Z' - - type: DNSSuccessful + - type: Adapter1Successful status: 'True' - reason: DNS configured - message: DNS records created for custom.domain.com + reason: This adapter1 is available + message: This adapter1 is available + observed_generation: 1 + created_time: '2021-01-01T10:00:00Z' + last_updated_time: '2021-01-01T10:00:00Z' + last_transition_time: '2021-01-01T10:00:00Z' + - type: Adapter2Successful + status: 'True' + reason: This adapter2 is available + message: This adapter2 is available observed_generation: 1 created_time: '2021-01-01T10:01:00Z' last_updated_time: '2021-01-01T10:01:00Z' @@ -807,54 +826,28 @@ components: ClusterStatus: type: object required: - - phase - - last_transition_time - - observed_generation - - last_updated_time - conditions properties: - phase: - $ref: '#/components/schemas/ResourcePhase' - last_transition_time: - type: string - format: date-time - description: |- - When cluster last transitioned (used by Sentinel for backoff) - Updated when conditions are reported if the phase changes - observed_generation: - type: integer - format: int32 - description: |- - Last generation processed - Updated when conditions are reported. - This will be the lowest value of each condition's observed_generation values - The phase value is based on this generation - last_updated_time: - type: string - format: date-time - description: |- - Time of the last update - Updated when conditions are reported. - Computed as min(conditions[].last_updated_time) to detect stale adapters. - Uses earliest (not latest) timestamp to ensure Sentinel can detect if any adapter has stopped reporting. conditions: type: array items: $ref: '#/components/schemas/ResourceCondition' + minItems: 2 + description: |- + List of status conditions for the cluster. + + **Mandatory conditions**: + - `type: "Ready"`: Whether all adapters report successfully at the current generation. + - `type: "Available"`: Aggregated adapter result for a common observed_generation. + + These conditions are present immediately upon resource creation. description: |- Cluster status computed from all status conditions. This object is computed by the service and CANNOT be modified directly. It is aggregated from condition updates posted to `/clusters/{id}/statuses`. - Provides quick overview of all reported conditions and aggregated phase. - ConditionStatus: - type: string - enum: - - 'True' - - 'False' - - Unknown - description: Status value for conditions + Provides quick overview of all reported conditions. DNSSpec: type: object properties: @@ -1013,11 +1006,23 @@ components: kind: Cluster href: https://api.hyperfleet.com/v1/clusters/cluster-123 status: - phase: Ready - last_transition_time: '2021-01-01T10:00:00Z' - observed_generation: 1 - last_updated_time: '2021-01-01T10:02:00Z' conditions: + - type: Ready + status: 'True' + reason: ResourceReady + message: All conditions successful for current spec generation + observed_generation: 1 + created_time: '2021-01-01T10:00:00Z' + last_updated_time: '2021-01-01T10:00:00Z' + last_transition_time: '2021-01-01T10:00:00Z' + - type: Available + status: 'True' + reason: ResourceAvailable + message: All conditions successful for observed_generation + observed_generation: 1 + created_time: '2021-01-01T10:00:00Z' + last_updated_time: '2021-01-01T10:00:00Z' + last_transition_time: '2021-01-01T10:00:00Z' - type: ValidationSuccessful status: 'True' reason: All validations passed @@ -1226,39 +1231,21 @@ components: NodePoolStatus: type: object required: - - phase - - observed_generation - - last_transition_time - - last_updated_time - conditions properties: - phase: - $ref: '#/components/schemas/ResourcePhase' - observed_generation: - type: integer - format: int32 - minimum: 1 - description: |- - Last generation processed - Updated when conditions are reported. - This will be the lowest value of each condition's observed_generation values - The phase value is based on this generation - last_transition_time: - type: string - format: date-time - description: When NodePool last transitioned (used by Sentinel for backoff) - last_updated_time: - type: string - format: date-time - description: |- - Time of the last update - Updated when conditions are reported. - Computed as min(conditions[].last_updated_time) to detect stale adapters. - Uses earliest (not latest) timestamp to ensure Sentinel can detect if any adapter has stopped reporting. conditions: type: array items: $ref: '#/components/schemas/ResourceCondition' + minItems: 2 + description: |- + List of status conditions for the nodepool. + + **Mandatory conditions**: + - `type: "Ready"`: Whether all adapters report successfully at the current generation. + - `type: "Available"`: Aggregated adapter result for a common observed_generation. + + These conditions are present immediately upon resource creation. description: |- NodePool status computed from all status conditions. @@ -1291,8 +1278,8 @@ components: type: object required: - type - - status - last_transition_time + - status - observed_generation - created_time - last_updated_time @@ -1300,8 +1287,6 @@ components: type: type: string description: Condition type - status: - $ref: '#/components/schemas/ConditionStatus' reason: type: string description: Machine-readable reason code @@ -1313,7 +1298,9 @@ components: format: date-time description: |- When this condition last transitioned status (API-managed) - Only updated when status changes (True/False/Unknown), not when reason/message changes + Only updated when status changes (True/False), not when reason/message changes + status: + $ref: '#/components/schemas/ResourceConditionStatus' observed_generation: type: integer format: int32 @@ -1333,13 +1320,12 @@ components: Condition in Cluster/NodePool status Used for semantic condition types: "ValidationSuccessful", "DNSSuccessful", "NodePoolSuccessful", etc. Includes observed_generation and last_updated_time to track adapter-specific state - ResourcePhase: + ResourceConditionStatus: type: string enum: - - NotReady - - Ready - - Failed - description: Phase of a resource (Cluster or NodePool) + - 'True' + - 'False' + description: Status value for resource conditions TaintSpec: type: object required: diff --git a/schemas/gcp/swagger.yaml b/schemas/gcp/swagger.yaml index 0d44baa..c57a25b 100644 --- a/schemas/gcp/swagger.yaml +++ b/schemas/gcp/swagger.yaml @@ -16,7 +16,7 @@ info: name: Apache 2.0 url: 'https://www.apache.org/licenses/LICENSE-2.0' title: HyperFleet API - version: 1.0.3 + version: 1.0.4 host: hyperfleet.redhat.com basePath: / schemes: @@ -31,7 +31,7 @@ paths: - description: >- Filter results using TSL (Tree Search Language) query syntax. - Examples: `status.phase='NotReady'`, `name in ('c1','c2')`, + Examples: `status.conditions.Ready='True'`, `name in ('c1','c2')`, `labels.region='us-east'` in: query name: search @@ -110,10 +110,10 @@ paths: **Note**: The `status` object in the response is read-only and computed by the service. - It is NOT part of the request body. Initially, status.phase will be - "NotReady" and + It is NOT part of the request body. Initially, - status.conditions will be empty until status conditions are POSTed. + status.conditions will include mandatory "Available" and "Ready" + conditions. operationId: postCluster summary: Create cluster '/api/hyperfleet/v1/clusters/{cluster_id}': @@ -125,7 +125,7 @@ paths: - description: >- Filter results using TSL (Tree Search Language) query syntax. - Examples: `status.phase='NotReady'`, `name in ('c1','c2')`, + Examples: `status.conditions.Ready='True'`, `name in ('c1','c2')`, `labels.region='us-east'` in: query name: search @@ -164,7 +164,7 @@ paths: - description: >- Filter results using TSL (Tree Search Language) query syntax. - Examples: `status.phase='NotReady'`, `name in ('c1','c2')`, + Examples: `status.conditions.Ready='True'`, `name in ('c1','c2')`, `labels.region='us-east'` in: query name: search @@ -295,7 +295,7 @@ paths: - description: >- Filter results using TSL (Tree Search Language) query syntax. - Examples: `status.phase='NotReady'`, `name in ('c1','c2')`, + Examples: `status.conditions.Ready='True'`, `name in ('c1','c2')`, `labels.region='us-east'` in: query name: search @@ -352,7 +352,7 @@ paths: - description: >- Filter results using TSL (Tree Search Language) query syntax. - Examples: `status.phase='NotReady'`, `name in ('c1','c2')`, + Examples: `status.conditions.Ready='True'`, `name in ('c1','c2')`, `labels.region='us-east'` in: query name: search @@ -405,7 +405,7 @@ paths: - description: >- Filter results using TSL (Tree Search Language) query syntax. - Examples: `status.phase='NotReady'`, `name in ('c1','c2')`, + Examples: `status.conditions.Ready='True'`, `name in ('c1','c2')`, `labels.region='us-east'` in: query name: search @@ -479,8 +479,8 @@ definitions: description: >- When this condition last transitioned status (API-managed) - Only updated when status changes (True/False/Unknown), not when - reason/message changes + Only updated when status changes (True/False), not when reason/message + changes format: date-time type: string message: @@ -490,35 +490,42 @@ definitions: description: Machine-readable reason code type: string status: - $ref: '#/definitions/ConditionStatus' + $ref: '#/definitions/AdapterConditionStatus' type: description: Condition type type: string required: - type - - status - last_transition_time + - status type: object + AdapterConditionStatus: + description: Status value for adapter conditions + enum: + - 'True' + - 'False' + - Unknown + type: string AdapterStatus: description: |- AdapterStatus represents the complete status report from an adapter Contains multiple conditions, job metadata, and adapter-specific data example: - adapter: validator + adapter: adapter1 conditions: - last_transition_time: '2021-01-01T10:00:00Z' - message: All 30 validation tests passed - reason: All validations passed + message: This adapter1 is available + reason: This adapter1 is available status: 'True' type: Available - last_transition_time: '2021-01-01T10:00:00Z' - message: Validation job applied successfully + message: Adapter1 validation job applied successfully reason: Validation job applied status: 'True' type: Applied - last_transition_time: '2021-01-01T10:00:00Z' - message: All adapter runtime operations completed successfully - reason: All adapter operations completed successfully + message: All adapter1 runtime operations completed successfully + reason: All adapter1 operations completed successfully status: 'True' type: Health created_time: '2021-01-01T10:00:00Z' @@ -599,11 +606,11 @@ definitions: description: List of adapter statuses with pagination metadata example: items: - - adapter: validator + - adapter: adapter1 conditions: - last_transition_time: '2021-01-01T10:00:00Z' - message: All 30 validation tests passed - reason: All validations passed + message: This adapter1 is available + reason: This adapter1 is available status: 'True' type: Available created_time: '2021-01-01T10:00:00Z' @@ -612,11 +619,11 @@ definitions: duration: 2m job_name: validator-job-abc123 observed_generation: 1 - - adapter: dns + - adapter: adapter2 conditions: - last_transition_time: '2021-01-01T10:01:00Z' - message: DNS records created - reason: DNS configured + message: This adapter2 is available + reason: This adapter2 is available status: 'True' type: Available created_time: '2021-01-01T10:01:00Z' @@ -723,23 +730,35 @@ definitions: - created_time: '2021-01-01T10:00:00Z' last_transition_time: '2021-01-01T10:00:00Z' last_updated_time: '2021-01-01T10:00:00Z' - message: All 30 validation tests passed + message: All adapters reported Ready True for the current generation observed_generation: 1 - reason: All validations passed + reason: All adapters reported Ready True for the current generation status: 'True' - type: ValidationSuccessful + type: Ready + - created_time: '2021-01-01T10:00:00Z' + last_transition_time: '2021-01-01T10:00:00Z' + last_updated_time: '2021-01-01T10:00:00Z' + message: All adapters reported Available True for the same generation + observed_generation: 1 + reason: All adapters reported Available True for the same generation + status: 'True' + type: Available + - created_time: '2021-01-01T10:00:00Z' + last_transition_time: '2021-01-01T10:00:00Z' + last_updated_time: '2021-01-01T10:00:00Z' + message: This adapter1 is available + observed_generation: 1 + reason: This adapter1 is available + status: 'True' + type: Adapter1Successful - created_time: '2021-01-01T10:01:00Z' last_transition_time: '2021-01-01T10:01:00Z' last_updated_time: '2021-01-01T10:01:00Z' - message: DNS records created for custom.domain.com + message: This adapter2 is available observed_generation: 1 - reason: DNS configured + reason: This adapter2 is available status: 'True' - type: DNSSuccessful - last_transition_time: '2021-01-01T00:00:00Z' - last_updated_time: '2021-01-01T00:00:00Z' - observed_generation: 1 - phase: Ready + type: Adapter2Successful updated_by: user-123@example.com updated_time: '2021-01-01T00:00:00Z' properties: @@ -932,59 +951,30 @@ definitions: `/clusters/{id}/statuses`. - Provides quick overview of all reported conditions and aggregated phase. + Provides quick overview of all reported conditions. properties: conditions: - items: - $ref: '#/definitions/ResourceCondition' - type: array - last_transition_time: - description: |- - When cluster last transitioned (used by Sentinel for backoff) - Updated when conditions are reported if the phase changes - format: date-time - type: string - last_updated_time: description: >- - Time of the last update + List of status conditions for the cluster. - Updated when conditions are reported. - Computed as min(conditions[].last_updated_time) to detect stale - adapters. + **Mandatory conditions**: - Uses earliest (not latest) timestamp to ensure Sentinel can detect if - any adapter has stopped reporting. - format: date-time - type: string - observed_generation: - description: >- - Last generation processed + - `type: "Ready"`: Whether all adapters report successfully at the + current generation. - Updated when conditions are reported. + - `type: "Available"`: Aggregated adapter result for a common + observed_generation. - This will be the lowest value of each condition's observed_generation - values - The phase value is based on this generation - format: int32 - type: integer - phase: - $ref: '#/definitions/ResourcePhase' + These conditions are present immediately upon resource creation. + items: + $ref: '#/definitions/ResourceCondition' + minItems: 2 + type: array required: - - phase - - last_transition_time - - observed_generation - - last_updated_time - conditions type: object - ConditionStatus: - description: Status value for conditions - enum: - - 'True' - - 'False' - - Unknown - type: string DNSSpec: properties: baseDomain: @@ -1087,6 +1077,22 @@ definitions: type: gcp status: conditions: + - created_time: '2021-01-01T10:00:00Z' + last_transition_time: '2021-01-01T10:00:00Z' + last_updated_time: '2021-01-01T10:00:00Z' + message: All conditions successful for current spec generation + observed_generation: 1 + reason: ResourceReady + status: 'True' + type: Ready + - created_time: '2021-01-01T10:00:00Z' + last_transition_time: '2021-01-01T10:00:00Z' + last_updated_time: '2021-01-01T10:00:00Z' + message: All conditions successful for observed_generation + observed_generation: 1 + reason: ResourceAvailable + status: 'True' + type: Available - created_time: '2021-01-01T10:00:00Z' last_transition_time: '2021-01-01T10:00:00Z' last_updated_time: '2021-01-01T10:00:00Z' @@ -1103,10 +1109,6 @@ definitions: reason: NodePool provisioned successfully status: 'True' type: NodePoolSuccessful - last_transition_time: '2021-01-01T10:00:00Z' - last_updated_time: '2021-01-01T10:02:00Z' - observed_generation: 1 - phase: Ready updated_by: user-123@example.com updated_time: '2021-01-01T00:00:00Z' properties: @@ -1364,46 +1366,25 @@ definitions: This object is computed by the service and CANNOT be modified directly. properties: conditions: - items: - $ref: '#/definitions/ResourceCondition' - type: array - last_transition_time: - description: When NodePool last transitioned (used by Sentinel for backoff) - format: date-time - type: string - last_updated_time: description: >- - Time of the last update + List of status conditions for the nodepool. - Updated when conditions are reported. - Computed as min(conditions[].last_updated_time) to detect stale - adapters. + **Mandatory conditions**: - Uses earliest (not latest) timestamp to ensure Sentinel can detect if - any adapter has stopped reporting. - format: date-time - type: string - observed_generation: - description: >- - Last generation processed + - `type: "Ready"`: Whether all adapters report successfully at the + current generation. - Updated when conditions are reported. + - `type: "Available"`: Aggregated adapter result for a common + observed_generation. - This will be the lowest value of each condition's observed_generation - values - The phase value is based on this generation - format: int32 - minimum: 1 - type: integer - phase: - $ref: '#/definitions/ResourcePhase' + These conditions are present immediately upon resource creation. + items: + $ref: '#/definitions/ResourceCondition' + minItems: 2 + type: array required: - - phase - - observed_generation - - last_transition_time - - last_updated_time - conditions type: object ObjectReference: @@ -1448,8 +1429,8 @@ definitions: description: >- When this condition last transitioned status (API-managed) - Only updated when status changes (True/False/Unknown), not when - reason/message changes + Only updated when status changes (True/False), not when reason/message + changes format: date-time type: string last_updated_time: @@ -1473,24 +1454,23 @@ definitions: description: Machine-readable reason code type: string status: - $ref: '#/definitions/ConditionStatus' + $ref: '#/definitions/ResourceConditionStatus' type: description: Condition type type: string required: - type - - status - last_transition_time + - status - observed_generation - created_time - last_updated_time type: object - ResourcePhase: - description: Phase of a resource (Cluster or NodePool) + ResourceConditionStatus: + description: Status value for resource conditions enum: - - NotReady - - Ready - - Failed + - 'True' + - 'False' type: string TaintSpec: properties: @@ -1579,7 +1559,7 @@ x-components: description: >- Filter results using TSL (Tree Search Language) query syntax. - Examples: `status.phase='NotReady'`, `name in ('c1','c2')`, + Examples: `status.conditions.Ready='True'`, `name in ('c1','c2')`, `labels.region='us-east'` in: query name: search diff --git a/services/clusters.tsp b/services/clusters.tsp index 0890b9e..11e011e 100644 --- a/services/clusters.tsp +++ b/services/clusters.tsp @@ -37,8 +37,8 @@ interface Clusters { * Create a new cluster resource. * * **Note**: The `status` object in the response is read-only and computed by the service. - * It is NOT part of the request body. Initially, status.phase will be "NotReady" and - * status.conditions will be empty until status conditions are POSTed. + * It is NOT part of the request body. Initially, + * status.conditions will include mandatory "Available" and "Ready" conditions. * */ @route("")