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
63 changes: 63 additions & 0 deletions internal/utils/pdrole/detect.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package pdrole

import (
appsv1 "k8s.io/api/apps/v1"
)

// GetDeploymentPDRole determines the P/D role of a deployment by checking
// pod template labels against the provided labelConfig.
//
// This is label-only detection, matching how the EPP's filter plugins work:
// the EPP's prefill-filter and decode-filter (and by-label) plugins route
// traffic based solely on pod labels, never deployment names.
//
// Returns RoleUnknown if the deployment has no matching label. Callers should
// use the PDDiscoveryResult.Disaggregated flag to interpret RoleUnknown:
// - If Disaggregated=false, skip detection entirely and treat all deployments as RoleBoth
// - If Disaggregated=true and RoleUnknown, the deployment has no P/D label set
func GetDeploymentPDRole(deploy *appsv1.Deployment, labelConfig PDRoleLabelConfig) PDRole {
if deploy == nil {
return RoleUnknown
}

return detectFromLabels(deploy, labelConfig)
}

// detectFromLabels checks pod template labels against the label config.
func detectFromLabels(deploy *appsv1.Deployment, config PDRoleLabelConfig) PDRole {
if config.LabelKey == "" {
return RoleUnknown
}

labels := deploy.Spec.Template.Labels
if labels == nil {
return RoleUnknown
}

value, exists := labels[config.LabelKey]
if !exists {
return RoleUnknown
}

return matchLabelValue(value, config)
}

// matchLabelValue matches a label value against the config's role value lists.
func matchLabelValue(value string, config PDRoleLabelConfig) PDRole {
for _, v := range config.PrefillValues {
if value == v {
return RolePrefill
}
}
for _, v := range config.DecodeValues {
if value == v {
return RoleDecode
}
}
for _, v := range config.BothValues {
if value == v {
return RoleBoth
}
}
return RoleUnknown
}
130 changes: 130 additions & 0 deletions internal/utils/pdrole/detect_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
package pdrole

import (
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"

appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

func makeDeployment(name string, labels map[string]string) *appsv1.Deployment {
return &appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: "default"},
Spec: appsv1.DeploymentSpec{
Template: corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{Labels: labels},
},
},
}
}

var _ = Describe("GetDeploymentPDRole", func() {
var defaultConfig PDRoleLabelConfig

BeforeEach(func() {
defaultConfig = DefaultPDRoleLabelConfig()
})

Context("with nil deployment", func() {
It("should return RoleUnknown", func() {
Expect(GetDeploymentPDRole(nil, defaultConfig)).To(Equal(RoleUnknown))
})
})

Context("with label-based detection", func() {
It("should detect prefill from label", func() {
deploy := makeDeployment("vllm-llama", map[string]string{DefaultRoleLabel: "prefill"})
Expect(GetDeploymentPDRole(deploy, defaultConfig)).To(Equal(RolePrefill))
})

It("should detect decode from label", func() {
deploy := makeDeployment("vllm-llama", map[string]string{DefaultRoleLabel: "decode"})
Expect(GetDeploymentPDRole(deploy, defaultConfig)).To(Equal(RoleDecode))
})

It("should detect both from label", func() {
deploy := makeDeployment("vllm-llama", map[string]string{DefaultRoleLabel: "both"})
Expect(GetDeploymentPDRole(deploy, defaultConfig)).To(Equal(RoleBoth))
})

It("should return unknown for unrecognized label value", func() {
deploy := makeDeployment("vllm-llama", map[string]string{DefaultRoleLabel: "invalid"})
Expect(GetDeploymentPDRole(deploy, defaultConfig)).To(Equal(RoleUnknown))
})
})

Context("without P/D label", func() {
It("should return unknown even if name contains prefill", func() {
deploy := makeDeployment("llama-prefill-a100", map[string]string{"app": "vllm"})
Expect(GetDeploymentPDRole(deploy, defaultConfig)).To(Equal(RoleUnknown))
})

It("should return unknown even if name contains decode", func() {
deploy := makeDeployment("llama-decode-h100", map[string]string{"app": "vllm"})
Expect(GetDeploymentPDRole(deploy, defaultConfig)).To(Equal(RoleUnknown))
})

It("should return unknown with no labels at all", func() {
deploy := makeDeployment("llama-prefill", nil)
Expect(GetDeploymentPDRole(deploy, defaultConfig)).To(Equal(RoleUnknown))
})

It("should return unknown with generic name and no P/D label", func() {
deploy := makeDeployment("vllm-llama", map[string]string{"app": "vllm"})
Expect(GetDeploymentPDRole(deploy, defaultConfig)).To(Equal(RoleUnknown))
})
})

Context("with custom label config", func() {
It("should detect prefill with custom label key and values", func() {
config := PDRoleLabelConfig{
LabelKey: "my.org/pd-role",
PrefillValues: []string{"p"},
DecodeValues: []string{"d"},
BothValues: []string{"pd"},
}
deploy := makeDeployment("vllm-llama", map[string]string{"my.org/pd-role": "p"})
Expect(GetDeploymentPDRole(deploy, config)).To(Equal(RolePrefill))
})

It("should detect decode with custom label key and values", func() {
config := PDRoleLabelConfig{
LabelKey: "my.org/pd-role",
PrefillValues: []string{"p"},
DecodeValues: []string{"d"},
BothValues: []string{"pd"},
}
deploy := makeDeployment("vllm-llama", map[string]string{"my.org/pd-role": "d"})
Expect(GetDeploymentPDRole(deploy, config)).To(Equal(RoleDecode))
})

It("should detect both with custom label key and values", func() {
config := PDRoleLabelConfig{
LabelKey: "my.org/pd-role",
PrefillValues: []string{"p"},
DecodeValues: []string{"d"},
BothValues: []string{"pd"},
}
deploy := makeDeployment("vllm-llama", map[string]string{"my.org/pd-role": "pd"})
Expect(GetDeploymentPDRole(deploy, config)).To(Equal(RoleBoth))
})

It("should return unknown when label key is empty", func() {
config := PDRoleLabelConfig{LabelKey: ""}
deploy := makeDeployment("vllm-llama", map[string]string{DefaultRoleLabel: "prefill"})
Expect(GetDeploymentPDRole(deploy, config)).To(Equal(RoleUnknown))
})
})
})

var _ = Describe("DefaultPDRoleLabelConfig", func() {
It("should return standard configuration", func() {
config := DefaultPDRoleLabelConfig()
Expect(config.LabelKey).To(Equal(DefaultRoleLabel))
Expect(config.PrefillValues).To(Equal([]string{"prefill"}))
Expect(config.DecodeValues).To(Equal([]string{"decode"}))
Expect(config.BothValues).To(Equal([]string{"both"}))
})
})
Loading