···1818COPY loom/cmd/controller/main.go cmd/controller/main.go
1919COPY loom/api/ api/
2020COPY loom/internal/ internal/
2121-COPY loom/pkg/ pkg/
22212322# Build
2423# CGO is required for go-sqlite3
+21-8
api/v1alpha1/spindleset_types.go
···137137 Nixpkgs []string `json:"nixpkgs,omitempty"`
138138}
139139140140+// ResourceProfile defines a resource configuration for spindle jobs based on node labels.
141141+// Profiles are matched against workflow architecture and applied to job pods.
142142+type ResourceProfile struct {
143143+ // NodeSelector defines labels that must match for this profile to be used.
144144+ // Must include kubernetes.io/arch to match workflow architecture.
145145+ // Additional labels allow differentiation between node types (e.g., node-tier, instance-type).
146146+ // +kubebuilder:validation:Required
147147+ NodeSelector map[string]string `json:"nodeSelector"`
148148+149149+ // Resources defines the compute resource requirements for jobs using this profile.
150150+ // +kubebuilder:validation:Required
151151+ Resources corev1.ResourceRequirements `json:"resources"`
152152+}
153153+140154// SpindleTemplate defines the pod template configuration for spindle jobs.
141155// This is configured via ConfigMap and used internally by the engine.
142156type SpindleTemplate struct {
143143- // Resources defines the compute resource requirements for spindle jobs.
144144- Resources corev1.ResourceRequirements `json:"resources,omitempty"`
145145-146146- // NodeSelector is a selector which must be true for the pod to fit on a node.
147147- // For MVP, this is not exposed via ConfigMap.
148148- NodeSelector map[string]string `json:"nodeSelector,omitempty"`
157157+ // ResourceProfiles is an ordered list of resource configurations based on node labels.
158158+ // When creating a job, the first profile matching the workflow's architecture is selected.
159159+ // The profile's nodeSelector and resources are applied to the job pod.
160160+ // +optional
161161+ ResourceProfiles []ResourceProfile `json:"resourceProfiles,omitempty"`
149162150163 // Tolerations allows pods to schedule onto nodes with matching taints.
151151- // For MVP, this is not exposed via ConfigMap.
164164+ // +optional
152165 Tolerations []corev1.Toleration `json:"tolerations,omitempty"`
153166154167 // Affinity defines scheduling constraints for spindle job pods.
155155- // For MVP, this is not exposed via ConfigMap.
168168+ // +optional
156169 Affinity *corev1.Affinity `json:"affinity,omitempty"`
157170}
158171
+28-6
api/v1alpha1/zz_generated.deepcopy.go
···5454}
55555656// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
5757+func (in *ResourceProfile) DeepCopyInto(out *ResourceProfile) {
5858+ *out = *in
5959+ if in.NodeSelector != nil {
6060+ in, out := &in.NodeSelector, &out.NodeSelector
6161+ *out = make(map[string]string, len(*in))
6262+ for key, val := range *in {
6363+ (*out)[key] = val
6464+ }
6565+ }
6666+ in.Resources.DeepCopyInto(&out.Resources)
6767+}
6868+6969+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceProfile.
7070+func (in *ResourceProfile) DeepCopy() *ResourceProfile {
7171+ if in == nil {
7272+ return nil
7373+ }
7474+ out := new(ResourceProfile)
7575+ in.DeepCopyInto(out)
7676+ return out
7777+}
7878+7979+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
5780func (in *SpindleSet) DeepCopyInto(out *SpindleSet) {
5881 *out = *in
5982 out.TypeMeta = in.TypeMeta
···165188// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
166189func (in *SpindleTemplate) DeepCopyInto(out *SpindleTemplate) {
167190 *out = *in
168168- in.Resources.DeepCopyInto(&out.Resources)
169169- if in.NodeSelector != nil {
170170- in, out := &in.NodeSelector, &out.NodeSelector
171171- *out = make(map[string]string, len(*in))
172172- for key, val := range *in {
173173- (*out)[key] = val
191191+ if in.ResourceProfiles != nil {
192192+ in, out := &in.ResourceProfiles, &out.ResourceProfiles
193193+ *out = make([]ResourceProfile, len(*in))
194194+ for i := range *in {
195195+ (*in)[i].DeepCopyInto(&(*out)[i])
174196 }
175197 }
176198 if in.Tolerations != nil {
···198198 Set internally by the engine from ConfigMap configuration.
199199 properties:
200200 affinity:
201201- description: |-
202202- Affinity defines scheduling constraints for spindle job pods.
203203- For MVP, this is not exposed via ConfigMap.
201201+ description: Affinity defines scheduling constraints for spindle
202202+ job pods.
204203 properties:
205204 nodeAffinity:
206205 description: Describes node affinity scheduling rules for
···11181117 x-kubernetes-list-type: atomic
11191118 type: object
11201119 type: object
11211121- nodeSelector:
11221122- additionalProperties:
11231123- type: string
11201120+ resourceProfiles:
11241121 description: |-
11251125- NodeSelector is a selector which must be true for the pod to fit on a node.
11261126- For MVP, this is not exposed via ConfigMap.
11271127- type: object
11281128- resources:
11291129- description: Resources defines the compute resource requirements
11301130- for spindle jobs.
11311131- properties:
11321132- claims:
11331133- description: |-
11341134- Claims lists the names of resources, defined in spec.resourceClaims,
11351135- that are used by this container.
11221122+ ResourceProfiles is an ordered list of resource configurations based on node labels.
11231123+ When creating a job, the first profile matching the workflow's architecture is selected.
11241124+ The profile's nodeSelector and resources are applied to the job pod.
11251125+ items:
11261126+ description: |-
11271127+ ResourceProfile defines a resource configuration for spindle jobs based on node labels.
11281128+ Profiles are matched against workflow architecture and applied to job pods.
11291129+ properties:
11301130+ nodeSelector:
11311131+ additionalProperties:
11321132+ type: string
11331133+ description: |-
11341134+ NodeSelector defines labels that must match for this profile to be used.
11351135+ Must include kubernetes.io/arch to match workflow architecture.
11361136+ Additional labels allow differentiation between node types (e.g., node-tier, instance-type).
11371137+ type: object
11381138+ resources:
11391139+ description: Resources defines the compute resource requirements
11401140+ for jobs using this profile.
11411141+ properties:
11421142+ claims:
11431143+ description: |-
11441144+ Claims lists the names of resources, defined in spec.resourceClaims,
11451145+ that are used by this container.
1136114611371137- This is an alpha field and requires enabling the
11381138- DynamicResourceAllocation feature gate.
11471147+ This is an alpha field and requires enabling the
11481148+ DynamicResourceAllocation feature gate.
1139114911401140- This field is immutable. It can only be set for containers.
11411141- items:
11421142- description: ResourceClaim references one entry in PodSpec.ResourceClaims.
11431143- properties:
11441144- name:
11501150+ This field is immutable. It can only be set for containers.
11511151+ items:
11521152+ description: ResourceClaim references one entry in
11531153+ PodSpec.ResourceClaims.
11541154+ properties:
11551155+ name:
11561156+ description: |-
11571157+ Name must match the name of one entry in pod.spec.resourceClaims of
11581158+ the Pod where this field is used. It makes that resource available
11591159+ inside a container.
11601160+ type: string
11611161+ request:
11621162+ description: |-
11631163+ Request is the name chosen for a request in the referenced claim.
11641164+ If empty, everything from the claim is made available, otherwise
11651165+ only the result of this request.
11661166+ type: string
11671167+ required:
11681168+ - name
11691169+ type: object
11701170+ type: array
11711171+ x-kubernetes-list-map-keys:
11721172+ - name
11731173+ x-kubernetes-list-type: map
11741174+ limits:
11751175+ additionalProperties:
11761176+ anyOf:
11771177+ - type: integer
11781178+ - type: string
11791179+ pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
11801180+ x-kubernetes-int-or-string: true
11451181 description: |-
11461146- Name must match the name of one entry in pod.spec.resourceClaims of
11471147- the Pod where this field is used. It makes that resource available
11481148- inside a container.
11491149- type: string
11501150- request:
11821182+ Limits describes the maximum amount of compute resources allowed.
11831183+ More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
11841184+ type: object
11851185+ requests:
11861186+ additionalProperties:
11871187+ anyOf:
11881188+ - type: integer
11891189+ - type: string
11901190+ pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
11911191+ x-kubernetes-int-or-string: true
11511192 description: |-
11521152- Request is the name chosen for a request in the referenced claim.
11531153- If empty, everything from the claim is made available, otherwise
11541154- only the result of this request.
11551155- type: string
11561156- required:
11571157- - name
11931193+ Requests describes the minimum amount of compute resources required.
11941194+ If Requests is omitted for a container, it defaults to Limits if that is explicitly specified,
11951195+ otherwise to an implementation-defined value. Requests cannot exceed Limits.
11961196+ More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
11971197+ type: object
11581198 type: object
11591159- type: array
11601160- x-kubernetes-list-map-keys:
11611161- - name
11621162- x-kubernetes-list-type: map
11631163- limits:
11641164- additionalProperties:
11651165- anyOf:
11661166- - type: integer
11671167- - type: string
11681168- pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
11691169- x-kubernetes-int-or-string: true
11701170- description: |-
11711171- Limits describes the maximum amount of compute resources allowed.
11721172- More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
11731173- type: object
11741174- requests:
11751175- additionalProperties:
11761176- anyOf:
11771177- - type: integer
11781178- - type: string
11791179- pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
11801180- x-kubernetes-int-or-string: true
11811181- description: |-
11821182- Requests describes the minimum amount of compute resources required.
11831183- If Requests is omitted for a container, it defaults to Limits if that is explicitly specified,
11841184- otherwise to an implementation-defined value. Requests cannot exceed Limits.
11851185- More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
11861186- type: object
11871187- type: object
11991199+ required:
12001200+ - nodeSelector
12011201+ - resources
12021202+ type: object
12031203+ type: array
11881204 tolerations:
11891189- description: |-
11901190- Tolerations allows pods to schedule onto nodes with matching taints.
11911191- For MVP, this is not exposed via ConfigMap.
12051205+ description: Tolerations allows pods to schedule onto nodes with
12061206+ matching taints.
11921207 items:
11931208 description: |-
11941209 The pod this Toleration is attached to tolerates any taint that matches