Skip to content
Open
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
33 changes: 33 additions & 0 deletions deploy/operator/api/roundtrip_fuzz_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,28 @@ func dynamoFuzzerFuncs(_ runtimeserializer.CodecFactory) []any {
fuzzAlphaDGDRStatus,
fuzzBetaDGDRSpec,
fuzzBetaDGDRStatus,
// PlacementStatus (v1alpha1 + v1beta1): pick admissible values so the
// round-trip fuzzer exercises Placement without producing shapes the CRD
// schema rejects. State draws from the enum; Score draws either nil or a
// value inside the [0, 1] bounds enforced by the CRD.
func(p *v1beta1.PlacementStatus, c randfill.Continue) {
p.State = oneOf(c,
v1beta1.PlacementScoreStateReported,
v1beta1.PlacementScoreStatePartial,
v1beta1.PlacementScoreStateUnsupported,
v1beta1.PlacementScoreStateUnknown,
)
p.Score = oneOfPtr(c, 0.0, 0.25, 0.5, 0.75, 1.0)
},
func(p *v1alpha1.PlacementStatus, c randfill.Continue) {
p.State = oneOf(c,
v1alpha1.PlacementScoreStateReported,
v1alpha1.PlacementScoreStatePartial,
v1alpha1.PlacementScoreStateUnsupported,
v1alpha1.PlacementScoreStateUnknown,
)
p.Score = oneOfPtr(c, 0.0, 0.25, 0.5, 0.75, 1.0)
},
// v1beta1 Components: the listMapKey marker requires name
// to be non-empty and unique; MaxItems caps the length at 25.
// Enforce both so the input is admissible.
Expand Down Expand Up @@ -308,6 +330,17 @@ func oneOf[T any](c randfill.Continue, values ...T) T {
return values[c.Intn(len(values))]
}

// oneOfPtr returns nil roughly half the time; otherwise a pointer to one of
// values. Useful for optional API fields that must either be unset or draw
// from a constrained value set.
func oneOfPtr[T any](c randfill.Continue, values ...T) *T {
if c.Bool() {
return nil
}
v := oneOf(c, values...)
return &v
}

func fuzzJSONValue(c randfill.Continue, depth int) any {
if depth >= 2 {
switch c.Uint32() % 5 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,8 @@ DynamoGraphDeploymentStatus.components.scheduledReplicas
DynamoGraphDeploymentStatus.components.updatedReplicas
DynamoGraphDeploymentStatus.conditions
DynamoGraphDeploymentStatus.observedGeneration
DynamoGraphDeploymentStatus.placement.score
DynamoGraphDeploymentStatus.placement.state
DynamoGraphDeploymentStatus.restart.inProgress
DynamoGraphDeploymentStatus.restart.observedID
DynamoGraphDeploymentStatus.restart.phase
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,16 @@ func ConvertToSpecTopologyConstraint(src *v1beta1.SpecTopologyConstraint, dst *S
func ConvertFromDynamoGraphDeploymentStatus(src *DynamoGraphDeploymentStatus, dst *v1beta1.DynamoGraphDeploymentStatus) {
dst.ObservedGeneration = src.ObservedGeneration
dst.State = v1beta1.DGDState(src.State)
if src.Placement != nil {
dst.Placement = &v1beta1.PlacementStatus{
State: v1beta1.PlacementScoreState(src.Placement.State),
}
if src.Placement.Score != nil {
dst.Placement.Score = ptr.To(*src.Placement.Score)
}
} else {
dst.Placement = nil
}
if len(src.Conditions) > 0 {
dst.Conditions = make([]metav1.Condition, 0, len(src.Conditions))
for _, c := range src.Conditions {
Expand Down Expand Up @@ -677,6 +687,16 @@ func ConvertFromDynamoGraphDeploymentStatus(src *DynamoGraphDeploymentStatus, ds
func ConvertToDynamoGraphDeploymentStatus(src *v1beta1.DynamoGraphDeploymentStatus, dst *DynamoGraphDeploymentStatus) {
dst.ObservedGeneration = src.ObservedGeneration
dst.State = DGDState(src.State)
if src.Placement != nil {
dst.Placement = &PlacementStatus{
State: PlacementScoreState(src.Placement.State),
}
if src.Placement.Score != nil {
dst.Placement.Score = ptr.To(*src.Placement.Score)
}
} else {
dst.Placement = nil
}
if len(src.Conditions) > 0 {
dst.Conditions = make([]metav1.Condition, 0, len(src.Conditions))
for _, c := range src.Conditions {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -912,6 +912,10 @@ func TestDGD_RoundTrip_Status(t *testing.T) {
Status: v1beta1.DynamoGraphDeploymentStatus{
ObservedGeneration: 7,
State: v1beta1.DGDStateSuccessful,
Placement: &v1beta1.PlacementStatus{
Score: ptr.To(0.87),
State: v1beta1.PlacementScoreStateReported,
},
Conditions: []metav1.Condition{
{
Type: "Ready",
Expand Down
32 changes: 32 additions & 0 deletions deploy/operator/api/v1alpha1/dynamographdeployment_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,34 @@ const (
DGDStateFailed DGDState = "failed"
)

// PlacementScoreState describes whether placement score is available and how
// complete the reported score is for a graph deployment. See the v1beta1
// PlacementScoreState for the authoritative semantics of each value.
// +kubebuilder:validation:Enum=Reported;Partial;Unsupported;Unknown
type PlacementScoreState string

const (
PlacementScoreStateReported PlacementScoreState = "Reported"
PlacementScoreStatePartial PlacementScoreState = "Partial"
PlacementScoreStateUnsupported PlacementScoreState = "Unsupported"
PlacementScoreStateUnknown PlacementScoreState = "Unknown"
Comment thread
ashnamehrotra marked this conversation as resolved.
)

// PlacementStatus groups DGD-level scheduler placement fields under a single
// status object so future placement signals can be added without a schema
// break. See the v1beta1 PlacementStatus for the authoritative field docs.
type PlacementStatus struct {
// Score is the DGD-level scheduler placement score. Normalized to [0.0, 1.0]
// where higher is better and 1.0 is the best possible placement.
// +optional
// +kubebuilder:validation:Minimum=0
// +kubebuilder:validation:Maximum=1
Score *float64 `json:"score,omitempty"`
// State indicates placement score reporting state.
// +optional
State PlacementScoreState `json:"state,omitempty"`
}

// DynamoGraphDeploymentSpec defines the desired state of DynamoGraphDeployment.
// +kubebuilder:validation:XValidation:rule="oldSelf.hasValue() || !has(self.restart)",message="spec.restart must be unset on create; set spec.restart.id after creation to request a restart",optionalOldSelf=true
type DynamoGraphDeploymentSpec struct {
Expand Down Expand Up @@ -169,6 +197,10 @@ type DynamoGraphDeploymentStatus struct {
// Currently only supported for singl-node, non-Grove deployments (DCD/Deployment).
// +optional
RollingUpdate *RollingUpdateStatus `json:"rollingUpdate,omitempty"`
// Placement groups DGD-level scheduler placement signals (score, reporting
// state, and any future placement fields).
// +optional
Placement *PlacementStatus `json:"placement,omitempty"`
}

// ServiceCheckpointStatus contains checkpoint information for a single service.
Expand Down
25 changes: 25 additions & 0 deletions deploy/operator/api/v1alpha1/zz_generated.deepcopy.go

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

47 changes: 47 additions & 0 deletions deploy/operator/api/v1beta1/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,53 @@ const (
DGDStateFailed DGDState = "failed"
)

// PlacementScoreState describes whether placement score is available and how
// complete the reported score is for a graph deployment.
//
// Every backend must set this field after the first reconciliation:
// - Reported: a score is available for every scored placement unit.
// - Partial: a score is available for some but not all placement units.
// - Unsupported: the backend does not surface a placement score at all.
// - Unknown: the backend supports scores but the current value is
// indeterminate (e.g. read failure, not yet populated by the
// scheduler). When set, PlacementStatus.Score must be cleared.
//
// +kubebuilder:validation:Enum=Reported;Partial;Unsupported;Unknown
type PlacementScoreState string

const (
PlacementScoreStateReported PlacementScoreState = "Reported"
PlacementScoreStatePartial PlacementScoreState = "Partial"
PlacementScoreStateUnsupported PlacementScoreState = "Unsupported"
PlacementScoreStateUnknown PlacementScoreState = "Unknown"
)

// PlacementStatus groups DGD-level scheduler placement fields under a single
// status object so future placement signals (e.g. scheduler contract version,
// last-report timestamp, per-unit reports) can be added without a schema break.
//
// The score source is an open question in DEP #10064 (Grove mirror, typed Grove
// scheduler API, or unstructured provider). Until a source is selected and
// implemented, the DGD controller does not write this field; the schema and
// conversion are landed here so downstream consumers can rely on the shape.
type PlacementStatus struct {
// score is the DGD-level scheduler placement score aggregated from
// relevant scheduler placement units. Normalized to [0.0, 1.0] where higher
// is better and 1.0 represents the best possible placement. Aggregation
// uses the minimum across placement units so the value is a worst-placement
// signal for the graph. Scores are only comparable across DGDs that share
// the same scheduler scoring contract and version.
// +optional
// +kubebuilder:validation:Minimum=0
// +kubebuilder:validation:Maximum=1
Score *float64 `json:"score,omitempty"`

// state indicates placement score reporting state. See PlacementScoreState
// for the semantics of each value.
// +optional
State PlacementScoreState `json:"state,omitempty"`
}

// RestartPhase enumerates phases of a graph-level restart.
type RestartPhase string

Expand Down
5 changes: 5 additions & 0 deletions deploy/operator/api/v1beta1/dynamographdeployment_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,11 @@ type DynamoGraphDeploymentStatus struct {
// Currently only supported for single-node, non-Grove deployments (DCD/Deployment).
// +optional
RollingUpdate *RollingUpdateStatus `json:"rollingUpdate,omitempty"`

// placement groups DGD-level scheduler placement signals (score, reporting
// state, and any future placement fields).
// +optional
Placement *PlacementStatus `json:"placement,omitempty"`
}

// DGD Ready condition reasons used to classify Grove-backed not-ready
Expand Down
25 changes: 25 additions & 0 deletions deploy/operator/api/v1beta1/zz_generated.deepcopy.go

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

Original file line number Diff line number Diff line change
Expand Up @@ -11951,6 +11951,27 @@ spec:
description: ObservedGeneration is the most recent generation observed by the controller.
format: int64
type: integer
placement:
description: |-
Placement groups DGD-level scheduler placement signals (score, reporting
state, and any future placement fields).
properties:
score:
description: |-
Score is the DGD-level scheduler placement score. Normalized to [0.0, 1.0]
where higher is better and 1.0 is the best possible placement.
maximum: 1
minimum: 0
type: number
state:
description: State indicates placement score reporting state.
enum:
- Reported
- Partial
- Unsupported
- Unknown
type: string
type: object
restart:
description: Restart contains the status of the restart of the graph deployment.
properties:
Expand Down Expand Up @@ -21370,6 +21391,33 @@ spec:
description: observedGeneration is the most recent generation observed by the controller.
format: int64
type: integer
placement:
description: |-
placement groups DGD-level scheduler placement signals (score, reporting
state, and any future placement fields).
properties:
score:
description: |-
score is the DGD-level scheduler placement score aggregated from
relevant scheduler placement units. Normalized to [0.0, 1.0] where higher
is better and 1.0 represents the best possible placement. Aggregation
uses the minimum across placement units so the value is a worst-placement
signal for the graph. Scores are only comparable across DGDs that share
the same scheduler scoring contract and version.
maximum: 1
minimum: 0
type: number
state:
description: |-
state indicates placement score reporting state. See PlacementScoreState
for the semantics of each value.
enum:
- Reported
- Partial
- Unsupported
- Unknown
type: string
type: object
restart:
description: restart contains the status of a graph-level restart.
properties:
Expand Down
Loading
Loading