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
12 changes: 12 additions & 0 deletions deploy/operator/internal/features/runtime/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*/

// Package runtime defines explicit feature gates controlled by the Dynamo
// runtime compatibility version.
//
// Runtime gates make rendered defaults stable across operator upgrades. A
// runtime version change is the trigger for adopting new defaults, while
// explicit user configuration remains authoritative.
package runtime
23 changes: 23 additions & 0 deletions deploy/operator/internal/features/runtime/gate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*/

package runtime

import "github.com/ai-dynamo/dynamo/deploy/operator/internal/runtimeversion"

// Gate controls a feature's rendered defaults by Dynamo runtime version.
type Gate struct {
Name string
MinRuntimeVersion runtimeversion.Version
}

// Enabled reports whether a known runtime version meets the feature threshold.
func (g Gate) Enabled(version *runtimeversion.Version) bool {
if version == nil {
return false
}

return version.Compare(g.MinRuntimeVersion) >= 0
}
67 changes: 67 additions & 0 deletions deploy/operator/internal/features/runtime/gate_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*/

package runtime

import (
"testing"

"github.com/ai-dynamo/dynamo/deploy/operator/internal/runtimeversion"
)

func TestGateEnabled(t *testing.T) {
t.Log("define a feature introduced by Dynamo runtime 1.4.0")
gate := Gate{
Name: "TestFeature",
MinRuntimeVersion: runtimeversion.Version{Major: 1, Minor: 4, Patch: 0},
}

t.Log("define versions below, at, and above the feature threshold")
tests := []struct {
name string
version *runtimeversion.Version
want bool
}{
{
name: "unknown runtime",
},
{
name: "older runtime",
version: &runtimeversion.Version{Major: 1, Minor: 3, Patch: 9},
},
{
name: "minimum supported runtime",
version: &runtimeversion.Version{Major: 1, Minor: 4, Patch: 0},
want: true,
},
{
name: "newer runtime",
version: &runtimeversion.Version{Major: 2, Minor: 0, Patch: 0},
want: true,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Log("evaluate the feature for the resolved runtime version")
got := gate.Enabled(tt.version)

t.Log("compare the gate decision")
if got != tt.want {
t.Fatalf("Enabled(%v) = %t, want %t", tt.version, got, tt.want)
}
})
}
}

func TestCanaryHealthChecksThreshold(t *testing.T) {
t.Log("inspect the central canary health-check feature gate")
got := CanaryHealthChecks.MinRuntimeVersion.String()

t.Log("verify canary health checks are introduced by runtime 1.4.0")
if got != "1.4.0" {
t.Fatalf("MinRuntimeVersion = %s, want 1.4.0", got)
}
}
17 changes: 17 additions & 0 deletions deploy/operator/internal/features/runtime/gates.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*/

package runtime

import "github.com/ai-dynamo/dynamo/deploy/operator/internal/runtimeversion"

var (
// CanaryHealthChecks gates the canary health-check rendering defaults
// introduced for Dynamo runtime 1.4.0.
CanaryHealthChecks = Gate{
Name: "CanaryHealthChecks",
MinRuntimeVersion: runtimeversion.Version{Major: 1, Minor: 4, Patch: 0},
}
)
12 changes: 12 additions & 0 deletions deploy/operator/internal/runtimeversion/runtimeversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
package runtimeversion

import (
"cmp"
"fmt"
"regexp"
"strings"
Expand All @@ -26,6 +27,17 @@ func (v Version) String() string {
return fmt.Sprintf("%d.%d.%d", v.Major, v.Minor, v.Patch)
}

// Compare returns -1, 0, or 1 when v's normalized compatibility core is less
// than, equal to, or greater than other. Image-tag prerelease and build
// suffixes are intentionally excluded by ParseImageVersion before comparison.
func (v Version) Compare(other Version) int {
return cmp.Or(
cmp.Compare(v.Major, other.Major),
cmp.Compare(v.Minor, other.Minor),
cmp.Compare(v.Patch, other.Patch),
)
}

// Parse returns the compatibility version represented by an explicit override.
func Parse(value string) (Version, error) {
version, err := semver.StrictNewVersion(value)
Expand Down
29 changes: 29 additions & 0 deletions deploy/operator/internal/runtimeversion/runtimeversion_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,35 @@ package runtimeversion

import "testing"

func TestVersionCompare(t *testing.T) {
t.Log("define the reference runtime compatibility core")
reference := Version{Major: 1, Minor: 4, Patch: 1}

t.Log("define comparisons below, equal to, and above the reference")
tests := []struct {
name string
version Version
want int
}{
{name: "below major", version: Version{Major: 0, Minor: 9, Patch: 9}, want: -1},
{name: "below minor", version: Version{Major: 1, Minor: 3, Patch: 9}, want: -1},
{name: "below patch", version: Version{Major: 1, Minor: 4, Patch: 0}, want: -1},
{name: "equal", version: Version{Major: 1, Minor: 4, Patch: 1}, want: 0},
{name: "above patch", version: Version{Major: 1, Minor: 4, Patch: 2}, want: 1},
{name: "above minor", version: Version{Major: 1, Minor: 5, Patch: 0}, want: 1},
{name: "above major", version: Version{Major: 2, Minor: 0, Patch: 0}, want: 1},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Log("compare the normalized runtime compatibility cores")
if got := tt.version.Compare(reference); got != tt.want {
t.Fatalf("%s.Compare(%s) = %d, want %d", tt.version, reference, got, tt.want)
}
})
}
}

func TestParse(t *testing.T) {
tests := []struct {
name string
Expand Down
Loading