/* * Copyright 2013-2026, Seqera Labs * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package recreationaltech.plugin.model import groovy.transform.CompileStatic import groovy.transform.EqualsAndHashCode import groovy.transform.PackageScope import groovy.transform.ToString /** * Model K8s pod options such as environment variables, * secret and config-maps * * @author Paolo Di Tommaso */ @CompileStatic @ToString(includeNames = true) @EqualsAndHashCode(includeFields = true) class PodOptions { private String imagePullPolicy private String imagePullSecret private Collection envVars private Collection mountConfigMaps private Collection mountCsiEphemerals private Collection mountEmptyDirs private Collection mountSecrets private Collection mountClaims private Collection mountHostPaths private Map labels = [:] private Map annotations = [:] private PodNodeSelector nodeSelector private Map affinity private PodSecurityContext securityContext private boolean automountServiceAccountToken private String priorityClassName private List tolerations private Boolean privileged private String schedulerName private Integer ttlSecondsAfterFinished private String runtimeClassName PodOptions( List options=null ) { int size = options ? options.size() : 0 envVars = new HashSet<>(size) mountConfigMaps = new HashSet<>(size) mountCsiEphemerals = new HashSet<>(size) mountEmptyDirs = new HashSet<>(size) mountSecrets = new HashSet<>(size) mountClaims = new HashSet<>(size) mountHostPaths = new HashSet<>(10) automountServiceAccountToken = true tolerations = new ArrayList(size) init(options) } @PackageScope void init(List options) { if( !options ) return for( Map entry : options ) { create(entry) } } @PackageScope void create(Map entry) { if( entry.env && entry.value ) { envVars << PodEnv.value(entry.env, entry.value) } else if( entry.env && entry.fieldPath ) { envVars << PodEnv.fieldPath(entry.env, entry.fieldPath) } else if( entry.env && entry.secret ) { envVars << PodEnv.secret(entry.env, entry.secret) } else if( entry.env && entry.config ) { envVars << PodEnv.config(entry.env, entry.config) } else if( entry.mountPath && entry.secret ) { mountSecrets << new PodMountSecret(entry) } else if( entry.mountPath && entry.config ) { mountConfigMaps << new PodMountConfig(entry) } else if( entry.mountPath && entry.csi ) { mountCsiEphemerals << new PodMountCsiEphemeral(entry) } else if( entry.mountPath && entry.emptyDir != null ) { mountEmptyDirs << new PodMountEmptyDir(entry) } else if( entry.mountPath && entry.volumeClaim ) { mountClaims << new PodVolumeClaim(entry) } else if( entry.mountPath && entry.hostPath instanceof CharSequence ) { mountHostPaths << new PodHostMount(entry.hostPath, entry.mountPath) } else if( entry.pullPolicy || entry.imagePullPolicy ) { this.imagePullPolicy = entry.pullPolicy ?: entry.imagePullPolicy as String } else if( entry.imagePullSecret || entry.imagePullSecrets ) { this.imagePullSecret = entry.imagePullSecret ?: entry.imagePullSecrets } else if( entry.label && entry.value ) { this.labels.put(entry.label as String, entry.value as String) } else if( entry.runAsUser != null ) { this.securityContext = new PodSecurityContext(entry.runAsUser) } else if( entry.securityContext instanceof Map ) { this.securityContext = new PodSecurityContext(entry.securityContext as Map) } else if( entry.nodeSelector ) { this.nodeSelector = new PodNodeSelector(entry.nodeSelector) } else if( entry.affinity instanceof Map ) { this.affinity = entry.affinity as Map } else if( entry.annotation && entry.value ) { this.annotations.put(entry.annotation as String, entry.value as String) } else if( entry.automountServiceAccountToken instanceof Boolean ) { this.automountServiceAccountToken = entry.automountServiceAccountToken as Boolean } else if( entry.priorityClassName ) { this.priorityClassName = entry.priorityClassName } else if( entry.toleration instanceof Map ) { tolerations << (entry.toleration as Map) } else if( entry.privileged instanceof Boolean ) { this.privileged = entry.privileged as Boolean } else if( entry.schedulerName ) { this.schedulerName = entry.schedulerName } else if( entry.ttlSecondsAfterFinished instanceof Integer ) { this.ttlSecondsAfterFinished = entry.ttlSecondsAfterFinished as Integer } else if( entry.runtimeClassName ) { this.runtimeClassName = entry.runtimeClassName } else throw new IllegalArgumentException("Unknown pod options: $entry") } Collection getEnvVars() { envVars } Collection getMountConfigMaps() { mountConfigMaps } Collection getMountCsiEphemerals() { mountCsiEphemerals } Collection getMountEmptyDirs() { mountEmptyDirs } Collection getMountSecrets() { mountSecrets } Collection getMountHostPaths() { mountHostPaths } Collection getVolumeClaims() { mountClaims } Map getLabels() { labels } Map getAnnotations() { annotations } PodNodeSelector getNodeSelector() { nodeSelector } PodOptions setNodeSelector( PodNodeSelector sel ) { nodeSelector = sel return this } Map getAffinity() { affinity } PodSecurityContext getSecurityContext() { securityContext } PodOptions setSecurityContext( PodSecurityContext ctx ) { this.securityContext = ctx return this } String getImagePullSecret() { imagePullSecret } PodOptions setImagePullSecret( String secret ) { this.imagePullSecret = secret return this } String getImagePullPolicy() { imagePullPolicy } PodOptions setImagePullPolicy( String policy ) { this.imagePullPolicy = policy return this } boolean getAutomountServiceAccountToken() { automountServiceAccountToken } PodOptions setAutomountServiceAccountToken( boolean mount ) { this.automountServiceAccountToken = mount return this } String getPriorityClassName() { priorityClassName } String getSchedulerName() { schedulerName } List getTolerations() { tolerations } Boolean getPrivileged() { privileged } Integer getTtlSecondsAfterFinished() { ttlSecondsAfterFinished } String getRuntimeClassName() { runtimeClassName } PodOptions plus( PodOptions other ) { def result = new PodOptions() // env vars result.envVars.addAll(envVars) result.envVars.addAll( other.envVars ) // config maps result.mountConfigMaps.addAll( mountConfigMaps ) result.mountConfigMaps.addAll( other.mountConfigMaps ) // csi ephemeral volumes result.mountCsiEphemerals.addAll( mountCsiEphemerals ) result.mountCsiEphemerals.addAll( other.mountCsiEphemerals ) // empty dirs result.mountEmptyDirs.addAll( mountEmptyDirs ) result.mountEmptyDirs.addAll( other.mountEmptyDirs ) // host paths result.mountHostPaths.addAll( mountHostPaths ) result.mountHostPaths.addAll( other.mountHostPaths ) // secrets result.mountSecrets.addAll( mountSecrets ) result.mountSecrets.addAll( other.mountSecrets ) // volume claims result.volumeClaims.addAll( volumeClaims ) result.volumeClaims.addAll( other.volumeClaims ) // sec context result.securityContext = other.securityContext ?: this.securityContext // node selector result.nodeSelector = other.nodeSelector ?: this.nodeSelector // affinity result.affinity = other.affinity ?: this.affinity // pull policy result.imagePullPolicy = other.imagePullPolicy ?: this.imagePullPolicy // image secret result.imagePullSecret = other.imagePullSecret ?: this.imagePullSecret // labels result.labels.putAll(labels) result.labels.putAll(other.labels) // annotations result.annotations.putAll(annotations) result.annotations.putAll(other.annotations) // automount service account token result.automountServiceAccountToken = other.automountServiceAccountToken & this.automountServiceAccountToken // priority class name result.priorityClassName = other.priorityClassName ?: this.priorityClassName // tolerations result.tolerations = other.tolerations ?: this.tolerations // privileged execution result.privileged = other.privileged!=null ? other.privileged : this.privileged // scheduler name result.schedulerName = other.schedulerName ?: this.schedulerName // ttl seconds after finished (job) result.ttlSecondsAfterFinished = other.ttlSecondsAfterFinished!=null ? other.ttlSecondsAfterFinished : this.ttlSecondsAfterFinished // runtime class name result.runtimeClassName = other.runtimeClassName ?: this.runtimeClassName return result } }