Skip to content

Commit b261e18

Browse files
authored
Merge pull request #196 from tremes/truncate-proposal-name
fix: truncate proposal name in label values to 63 chars
2 parents ea1046f + 5243949 commit b261e18

8 files changed

Lines changed: 75 additions & 5 deletions

File tree

controller/proposal/bare_pod_manager.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ func (m *BarePodManager) Claim(ctx context.Context, proposalName, step, _ string
7676
Name: podName,
7777
Namespace: m.Namespace,
7878
Labels: map[string]string{
79-
LabelProposal: proposalName,
79+
LabelProposal: truncateK8sName(proposalName),
8080
LabelStep: step,
8181
},
8282
},

controller/proposal/bare_pod_manager_test.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package proposal
22

33
import (
44
"context"
5+
"strings"
56
"testing"
67
"time"
78

@@ -80,6 +81,32 @@ func TestBarePodManager_Claim_UsesPerProposalSA(t *testing.T) {
8081
}
8182
}
8283

84+
func TestBarePodManager_Claim_TruncatesLongProposalNameInLabel(t *testing.T) {
85+
fc := newBarePodClient().Build()
86+
builder := &PodSpecBuilder{Image: "quay.io/test/sandbox:latest"}
87+
m := NewBarePodManager(fc, builder, "test-ns")
88+
m.SetStep(
89+
&agenticv1alpha1.Agent{Spec: agenticv1alpha1.AgentSpec{Model: "claude-opus-4-6"}},
90+
testLLMProvider(agenticv1alpha1.LLMProviderAnthropic),
91+
nil,
92+
defaultSandboxSA,
93+
)
94+
95+
longName := strings.Repeat("a", 80)
96+
name, err := m.Claim(context.Background(), longName, "analysis", "")
97+
if err != nil {
98+
t.Fatalf("Claim: %v", err)
99+
}
100+
101+
var pod corev1.Pod
102+
if err := fc.Get(context.Background(), types.NamespacedName{Name: name, Namespace: "test-ns"}, &pod); err != nil {
103+
t.Fatalf("pod not created: %v", err)
104+
}
105+
if len(pod.Labels[LabelProposal]) > 63 {
106+
t.Fatalf("proposal label length %d exceeds 63", len(pod.Labels[LabelProposal]))
107+
}
108+
}
109+
83110
func TestBarePodManager_Claim_AlreadyExists(t *testing.T) {
84111
existing := &corev1.Pod{}
85112
existing.Name = "ls-analysis-my-proposal"

controller/proposal/rbac.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ func rbacTargetNamespaces(proposal *agenticv1alpha1.Proposal, rbacResult *agenti
213213

214214
func truncateK8sName(name string) string {
215215
if len(name) > 63 {
216-
name = strings.TrimRight(name[:63], "-")
216+
name = strings.TrimRight(name[:63], "-._")
217217
}
218218
return name
219219
}
@@ -228,7 +228,7 @@ func clusterRoleName(proposalName string) string {
228228

229229
func rbacLabels(proposalName, component string) map[string]string {
230230
return map[string]string{
231-
LabelProposal: proposalName,
231+
LabelProposal: truncateK8sName(proposalName),
232232
LabelComponent: component,
233233
}
234234
}

controller/proposal/rbac_test.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,9 @@ func TestTruncateK8sName(t *testing.T) {
477477
{"exactly_63", strings.Repeat("a", 63), strings.Repeat("a", 63)},
478478
{"over_63", strings.Repeat("a", 70), strings.Repeat("a", 63)},
479479
{"trailing_dash_trimmed", strings.Repeat("a", 60) + "---" + strings.Repeat("b", 5), strings.Repeat("a", 60)},
480+
{"trailing_dot_trimmed", strings.Repeat("a", 60) + "..." + strings.Repeat("b", 5), strings.Repeat("a", 60)},
481+
{"trailing_underscore_trimmed", strings.Repeat("a", 60) + "___" + strings.Repeat("b", 5), strings.Repeat("a", 60)},
482+
{"trailing_mixed_trimmed", strings.Repeat("a", 58) + "-._.-" + strings.Repeat("b", 5), strings.Repeat("a", 58)},
480483
}
481484
for _, tt := range tests {
482485
t.Run(tt.name, func(t *testing.T) {
@@ -778,3 +781,14 @@ func TestRBACLabels(t *testing.T) {
778781
t.Fatalf("expected 2 labels, got %d", len(labels))
779782
}
780783
}
784+
785+
func TestRBACLabels_TruncatesLongProposalName(t *testing.T) {
786+
longName := strings.Repeat("a", 80)
787+
labels := rbacLabels(longName, "execution-rbac")
788+
if len(labels[LabelProposal]) > 63 {
789+
t.Fatalf("proposal label length %d exceeds 63", len(labels[LabelProposal]))
790+
}
791+
if labels[LabelProposal] != strings.Repeat("a", 63) {
792+
t.Errorf("proposal label = %q, want %q", labels[LabelProposal], strings.Repeat("a", 63))
793+
}
794+
}

controller/proposal/results.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ func proposalOwnerRef(proposal *agenticv1alpha1.Proposal) metav1.OwnerReference
3636

3737
func resultLabels(proposalName, step string) map[string]string {
3838
return map[string]string{
39-
LabelProposal: proposalName,
39+
LabelProposal: truncateK8sName(proposalName),
4040
LabelStep: step,
4141
}
4242
}

controller/proposal/results_test.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package proposal
22

33
import (
44
"context"
5+
"strings"
56
"testing"
67

78
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -11,6 +12,20 @@ import (
1112
agenticv1alpha1 "github.com/openshift/lightspeed-agentic-operator/api/v1alpha1"
1213
)
1314

15+
func TestResultLabels_TruncatesLongProposalName(t *testing.T) {
16+
longName := strings.Repeat("a", 80)
17+
labels := resultLabels(longName, "analysis")
18+
if len(labels[LabelProposal]) > 63 {
19+
t.Fatalf("proposal label length %d exceeds 63", len(labels[LabelProposal]))
20+
}
21+
if labels[LabelProposal] != strings.Repeat("a", 63) {
22+
t.Errorf("proposal label = %q, want %q", labels[LabelProposal], strings.Repeat("a", 63))
23+
}
24+
if labels[LabelStep] != "analysis" {
25+
t.Errorf("step label = %q, want analysis", labels[LabelStep])
26+
}
27+
}
28+
1429
func TestCreateIdempotent_StatusFieldsWritten(t *testing.T) {
1530
scheme := testScheme()
1631
fc := fake.NewClientBuilder().WithScheme(scheme).

controller/proposal/sandbox.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ func (m *SandboxManager) buildClaim(claimName, proposalName, step, templateName
8080
"name": claimName,
8181
"namespace": m.Namespace,
8282
"labels": map[string]any{
83-
LabelProposal: proposalName,
83+
LabelProposal: truncateK8sName(proposalName),
8484
LabelStep: step,
8585
},
8686
},

controller/proposal/sandbox_test.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,20 @@ func TestBuildClaim_Labels(t *testing.T) {
109109
}
110110
}
111111

112+
func TestBuildClaim_TruncatesLongProposalName(t *testing.T) {
113+
longName := strings.Repeat("a", 80)
114+
m := NewSandboxManager(nil, "ns", "")
115+
claim := m.buildClaim("c", longName, "execution", "tpl")
116+
117+
labels := claim.GetLabels()
118+
if len(labels[LabelProposal]) > 63 {
119+
t.Fatalf("proposal label length %d exceeds 63", len(labels[LabelProposal]))
120+
}
121+
if labels[LabelProposal] != strings.Repeat("a", 63) {
122+
t.Errorf("proposal label = %q, want %q", labels[LabelProposal], strings.Repeat("a", 63))
123+
}
124+
}
125+
112126
func TestBuildClaim_TemplateRef(t *testing.T) {
113127
m := NewSandboxManager(nil, "ns", "")
114128
claim := m.buildClaim("c", "p", "analysis", "my-template")

0 commit comments

Comments
 (0)