55 type WorkloadManagerOptions ,
66} from "./types.js" ;
77import type { EnvironmentType , MachinePreset , PlacementTag } from "@trigger.dev/core/v3" ;
8+ import { PlacementTagProcessor } from "@trigger.dev/core/v3/serverOnly" ;
89import { env } from "../env.js" ;
910import { type K8sApi , createK8sApi , type k8s } from "../clients/kubernetes.js" ;
1011import { getRunnerId } from "../util.js" ;
@@ -13,18 +14,18 @@ type ResourceQuantities = {
1314 [ K in "cpu" | "memory" | "ephemeral-storage" ] ?: string ;
1415} ;
1516
16- interface PlacementConfig {
17- enabled : boolean ;
18- prefix : string ;
19- }
20-
2117export class KubernetesWorkloadManager implements WorkloadManager {
2218 private readonly logger = new SimpleStructuredLogger ( "kubernetes-workload-provider" ) ;
2319 private k8s : K8sApi ;
2420 private namespace = env . KUBERNETES_NAMESPACE ;
21+ private placementTagProcessor : PlacementTagProcessor ;
2522
2623 constructor ( private opts : WorkloadManagerOptions ) {
2724 this . k8s = createK8sApi ( ) ;
25+ this . placementTagProcessor = new PlacementTagProcessor ( {
26+ enabled : env . PLACEMENT_TAGS_ENABLED ,
27+ prefix : env . PLACEMENT_TAGS_PREFIX ,
28+ } ) ;
2829
2930 if ( opts . workloadApiDomain ) {
3031 this . logger . warn ( "[KubernetesWorkloadManager] ⚠️ Custom workload API domain" , {
@@ -33,56 +34,21 @@ export class KubernetesWorkloadManager implements WorkloadManager {
3334 }
3435 }
3536
36- private get placementConfig ( ) : PlacementConfig {
37- return {
38- enabled : env . PLACEMENT_TAGS_ENABLED ,
39- prefix : env . PLACEMENT_TAGS_PREFIX ,
40- } ;
41- }
42-
4337 private addPlacementTags (
4438 podSpec : Omit < k8s . V1PodSpec , "containers" > ,
4539 placementTags ?: PlacementTag [ ]
4640 ) : Omit < k8s . V1PodSpec , "containers" > {
47- if ( ! this . placementConfig . enabled || ! placementTags || placementTags . length === 0 ) {
48- return podSpec ;
49- }
50-
51- const nodeSelector : Record < string , string > = { ...podSpec . nodeSelector } ;
52-
53- // Convert placement tags to nodeSelector labels
54- for ( const tag of placementTags ) {
55- const labelKey = `${ this . placementConfig . prefix } /${ tag . key } ` ;
56-
57- // Print warnings (if any)
58- this . printTagWarnings ( tag ) ;
59-
60- // For now we only support single values via nodeSelector
61- nodeSelector [ labelKey ] = tag . values ?. [ 0 ] ?? "" ;
62- }
41+ const nodeSelector = this . placementTagProcessor . convertToNodeSelector (
42+ placementTags ,
43+ podSpec . nodeSelector
44+ ) ;
6345
6446 return {
6547 ...podSpec ,
6648 nodeSelector,
6749 } ;
6850 }
6951
70- private printTagWarnings ( tag : PlacementTag ) {
71- if ( ! tag . values || tag . values . length === 0 ) {
72- // No values provided
73- this . logger . warn (
74- "[KubernetesWorkloadManager] Placement tag has no values, using empty string" ,
75- tag
76- ) ;
77- } else if ( tag . values . length > 1 ) {
78- // Multiple values provided
79- this . logger . warn (
80- "[KubernetesWorkloadManager] Placement tag has multiple values, only using first one" ,
81- tag
82- ) ;
83- }
84- }
85-
8652 async create ( opts : WorkloadManagerCreateOptions ) {
8753 this . logger . log ( "[KubernetesWorkloadManager] Creating container" , { opts } ) ;
8854
0 commit comments