├── Jenkinsfile ├── README.md ├── config ├── credentials.ctmpl ├── credentials_V2.ctpl ├── kubernetes.ctmpl ├── scriptApproval.txt └── scriptApprovalExample.txt ├── entrypoint.sh ├── jenkins_config.hcl └── src ├── .DS_Store ├── credentials.groovy ├── kubernetes.groovy └── scriptApproval.groovy /Jenkinsfile: -------------------------------------------------------------------------------- 1 | node { 2 | stage('checkout') { 3 | 4 | sh ''' 5 | 6 | git clone ssh://git@your_scm_here/jenkins_config_as_code.git ${JENKINS_HOME}/jenkins_config 7 | mv ${JENKINS_HOME}/jenkins_config/*.groovy ${JENKINS_HOME}/init.groovy.d/ 8 | 9 | ''' 10 | } 11 | 12 | stage('run consul template'){ 13 | sh ''' 14 | consul-template \ 15 | -consul-addr "$CONSUL_ADDR" \ 16 | -vault-addr "$VAULT_ADDR" \ 17 | -config "jenkins_config.hcl" \ 18 | -once 19 | ''' 20 | } 21 | 22 | stage('update credentials') { 23 | load("/var/jenkins_home/init.groovy.d/credentials.groovy") 24 | } 25 | 26 | stage('update k8s') { 27 | load("/var/jenkins_home/init.groovy.d/kubernetes.groovy") 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Advanced Jenkins config as code setup with 4 steps 2 | 3 | Creating Jenkins configation as code and applying changes without downtime with Groovy, Java, Docker and Jenkins job. 4 | 5 | POC: 6 | 1) Being able to update any Jenkins master or slave immediately - no new image, no redeploy, no downtime 7 | 2) No manual changes through UI - everything is kept as a code, and as a result: 8 | 3) Jenkins current state and state of image + config is kept in sync 9 | 4) Any change could be tested immediatelly without vicious cycle: create a new image, deploy, test, and if fails - repeat! 10 | 5) Creating a configuration that could be applied for specific environment only(prod vs test/dev Jenkins), with inheritence of common config and custom per jenkins config 11 | 12 | #### Step 1: Write groovy to interact with Java API 13 | ``` 14 | import hudson.model.* 15 | import jenkins.model.* 16 | import com.cloudbees.plugins.credentials.CredentialsScope 17 | import com.cloudbees.plugins.credentials.domains.Domain 18 | import com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl 19 | 20 | def domain = Domain.global() 21 | def store = Jenkins.instance.getExtensionList('com.cloudbees.plugins.credentials.SystemCredentialsProvider')[0].getStore() 22 | 23 | def instance = System.getenv("JENKINS_INSTANCE_NAME").replaceAll('-','_') 24 | 25 | ConfigObject conf = new ConfigSlurper().parse(new File(System.getenv("JENKINS_HOME")+'/jenkins_config/credentials.txt').text) 26 | 27 | conf.common_credentials.each { key, credentials -> 28 | println("Adding common credential ${key}") 29 | store.addCredentials(domain, new UsernamePasswordCredentialsImpl(CredentialsScope.GLOBAL, key, credentials.description, credentials.username, credentials.password)) 30 | } 31 | 32 | 33 | conf."${instance}_credentials".each { key, credentials -> 34 | println("Adding ${instance} credential ${key}") 35 | store.addCredentials(domain, new UsernamePasswordCredentialsImpl(CredentialsScope.GLOBAL, key, credentials.description, credentials.username, credentials.password)) 36 | } 37 | 38 | println("Successfully configured credentials") 39 | 40 | ``` 41 | 42 | #### Step 2: Create config for the script 43 | 44 | ``` 45 | common_credentials { 46 | 47 | exclude{ 48 | tyrion-jenkins 49 | } 50 | 51 | data{ 52 | jenkins_service_user = [ 53 | username: 'jenkins_service_user', 54 | password: '{{with $secret := secret "secret/jenkins/jenkins_service_user" }}{{ $secret.Data.value }}{{end}}', 55 | description :'for automated jenkins jobs' 56 | ] 57 | 58 | slack = [ 59 | username: '{{with $secret := secret "secret/slack/user" }}{{ $secret.Data.value }}{{end}}', 60 | password: '{{with $secret := secret "secret/slack/pass" }}{{ $secret.Data.value }}{{end}}', 61 | description: 'slack credentials' 62 | ] 63 | } 64 | 65 | } 66 | 67 | custom_credentials { 68 | 69 | include{ 70 | john-snow-jenkins 71 | arya-jenkins 72 | sansa-jenkins 73 | } 74 | 75 | data{ 76 | artifactory = [ 77 | username: 'arti', 78 | password: '{{with $secret := secret "secret/jenkins/artifactory" }}{{ $secret.Data.artifactory_password }}{{end}}', 79 | description: 'Artifactory credentials' 80 | ] 81 | 82 | } 83 | 84 | } 85 | 86 | tyrion-jenkins_credentials { 87 | 88 | data{ 89 | nexus=[ 90 | 'username':'deployment', 91 | 'password':'{{with $secret := secret "secret/jenkins/nexus" }}{{ $secret.Data.nexus_password }}{{end}}', 92 | 'description':'Nexus credentials' 93 | ] 94 | 95 | } 96 | 97 | } 98 | ``` 99 | 100 | #### Step 3: Checkout config and script and inject secrets and other variables with consul-template in container: 101 | ``` 102 | #!/usr/bin/env bash 103 | 104 | git clone ssh://git@your_scm_here/jenkins_config_as_code.git ${JENKINS_HOME}/jenkins_config 105 | mv ${JENKINS_HOME}/jenkins_config/*.groovy ${JENKINS_HOME}/init.groovy.d/ 106 | 107 | consul-template \ 108 | -consul-addr "$CONSUL_ADDR" \ 109 | -vault-addr "$VAULT_ADDR" \ 110 | -config "jenkins_config.hcl" \ 111 | -once 112 | 113 | 114 | ``` 115 | 116 | 117 | #### Step 4: Update continuously with Jenkins job without downtime 118 | ``` 119 | node { 120 | stage('checkout') { 121 | 122 | sh ''' 123 | 124 | git clone ssh://git@your_scm_here/jenkins_config_as_code.git ${JENKINS_HOME}/jenkins_config 125 | mv ${JENKINS_HOME}/jenkins_config/*.groovy ${JENKINS_HOME}/init.groovy.d/ 126 | 127 | ''' 128 | } 129 | 130 | stage('run consul template'){ 131 | sh ''' 132 | consul-template \ 133 | -consul-addr "$CONSUL_ADDR" \ 134 | -vault-addr "$VAULT_ADDR" \ 135 | -config "jenkins_config.hcl" \ 136 | -once 137 | ''' 138 | } 139 | 140 | stage('update credentials') { 141 | load("/var/jenkins_home/init.groovy.d/credentials.groovy") 142 | } 143 | 144 | stage('update k8s') { 145 | load("/var/jenkins_home/init.groovy.d/kubernetes.groovy") 146 | } 147 | 148 | } 149 | 150 | 151 | ``` -------------------------------------------------------------------------------- /config/credentials.ctmpl: -------------------------------------------------------------------------------- 1 | common_credentials { 2 | jenkins_service_user = [ 3 | username: 'jenkins_service_user', 4 | password: '{{with $secret := secret "secret/jenkins/jenkins_service_user" }}{{ $secret.Data.value }}{{end}}', 5 | description :'for automated jenkins jobs' 6 | ] 7 | 8 | slack = [ 9 | username: '{{with $secret := secret "secret/slack/user" }}{{ $secret.Data.value }}{{end}}', 10 | password: '{{with $secret := secret "secret/slack/pass" }}{{ $secret.Data.value }}{{end}}', 11 | description: 'slack credentials' 12 | ] 13 | } 14 | 15 | kayan_jenkins_credentials { 16 | artifactory = [ 17 | username: 'arti', 18 | password: '{{with $secret := secret "secret/jenkins/artifactory" }}{{ $secret.Data.artifactory_password }}{{end}}', 19 | description: 'Artifactory credentials' 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /config/credentials_V2.ctpl: -------------------------------------------------------------------------------- 1 | common_credentials { 2 | exclude{ 3 | tyrion-jenkins 4 | } 5 | data{ 6 | jenkins_service_user = [ 7 | username: 'jenkins_service_user', 8 | password: '{{with $secret := secret "secret/jenkins/jenkins_service_user" }}{{ $secret.Data.value }}{{end}}', 9 | description :'for automated jenkins jobs' 10 | ] 11 | slack = [ 12 | username: '{{with $secret := secret "secret/slack/user" }}{{ $secret.Data.value }}{{end}}', 13 | password: '{{with $secret := secret "secret/slack/pass" }}{{ $secret.Data.value }}{{end}}', 14 | description: 'slack credentials' 15 | ] 16 | } 17 | } 18 | 19 | custom_credentials { 20 | include{ 21 | john-snow-jenkins 22 | arya-jenkins 23 | sansa-jenkins 24 | } 25 | data{ 26 | artifactory = [ 27 | username: 'arti', 28 | password: '{{with $secret := secret "secret/jenkins/artifactory" }}{{ $secret.Data.artifactory_password }}{{end}}', 29 | description: 'Artifactory credentials' 30 | ] 31 | } 32 | } 33 | 34 | tyrion-jenkins_credentials { 35 | data{ 36 | nexus=[ 37 | 'username':'deployment', 38 | 'password':'{{with $secret := secret "secret/jenkins/nexus" }}{{ $secret.Data.nexus_password }}{{end}}', 39 | 'description':'Nexus credentials' 40 | ] 41 | 42 | } 43 | } -------------------------------------------------------------------------------- /config/kubernetes.ctmpl: -------------------------------------------------------------------------------- 1 | 2 | kubernetes { 3 | name = 'Kubernetes' 4 | serverUrl = 'https://kingslanding.westeros.co.uk' 5 | skipTlsVerify = true 6 | namespace = 'kingslanding' 7 | jenkinsUrl = 'http://kingslanding-dev-jenkins.kingslanding.svc.cluster.local' 8 | credentialsId = 'VALYRIAN_STEEL_SECRET' 9 | containerCapStr = '500' 10 | retentionTimeout = 5 11 | connectTimeout = 0 12 | readTimeout = 0 13 | podTemplatesDefaults { 14 | instanceCap = 2147483647 15 | } 16 | containerTemplateDefaults { 17 | name = 'jnlp' 18 | alwaysPullImage= false 19 | ttyEnabled= true 20 | privileged= true 21 | workingDir= '/var/jenkins_home' 22 | args= '${computer.jnlpmac} ${computer.name} -jar-cache /var/jenkins_home/jars' 23 | resourceRequestCpu = '1000m' 24 | resourceLimitCpu = '2000m' 25 | resourceRequestMemory = '1Gi' 26 | resourceLimitMemory = '2Gi' 27 | command = '' 28 | } 29 | podTemplates = [ 30 | [ 31 | name: 'PARENT', 32 | idleMinutes: 0, 33 | nodeSelector: 'role=jenkins', 34 | nodeUsageMode: 'NORMAL', 35 | customWorkspaceVolumeEnabled: false, 36 | workspaceVolume: [ 37 | type: 'EmptyDirWorkspaceVolume', 38 | memory: false, 39 | ], 40 | volumes: [ 41 | [ 42 | type: 'HostPathVolume', 43 | mountPath: '/jenkins/.m2/repository', 44 | hostPath: '/jenkins/m2' 45 | ] 46 | ], 47 | keyValueEnvVar: [ 48 | [ 49 | key: 'VAULT_TOKEN_ARTIFACTORY', 50 | value: '{{with $secret := secret "secret/jenkins/artifactory" }}{{ $secret.Data.value }}{{end}}' 51 | ], 52 | [ key: 'VAULT_ADDR', 53 | value: '{{env "VAULT_ADDR"}}' 54 | ], 55 | [ key: 'CONSUL_ADDR', 56 | value: '{{env "CONSUL_ADDR"}}' 57 | ] 58 | ], 59 | podImagePullSecret: 'my-secret' 60 | ], 61 | [ 62 | name: 'Java', 63 | label: 'java_slave', 64 | inheritFrom: 'PARENT', 65 | containerTemplate : [ 66 | image: 'registry.host.domain/jenkins-slave-java', 67 | alwaysPullImage: true, 68 | resourceRequestCpu: '1000m', 69 | resourceRequestMemory: '1Gi', 70 | resourceLimitCpu: '2000m', 71 | resourceLimitMemory: '2Gi' 72 | ] 73 | 74 | ], 75 | [ 76 | name: 'Go', 77 | label: 'go_slave', 78 | inheritFrom: 'PARENT', 79 | containerTemplate : [ 80 | image: 'registry.host.domain/jenkins-slave-go', 81 | alwaysPullImage: true, 82 | resourceRequestCpu: '1000m', 83 | resourceRequestMemory: '1Gi', 84 | resourceLimitCpu: '2000m', 85 | resourceLimitMemory: '8Gi' 86 | ], 87 | volumes: [ 88 | [ 89 | type: 'HostPathVolume', 90 | mountPath: '/var/go/go_stuff', 91 | hostPath: '/go/go_stuff' 92 | ], 93 | [ 94 | type: 'HostPathVolume', 95 | mountPath: '/var/go/some_other_go_stuff', 96 | hostPath: '/go/some_other_go_stuff' 97 | ] 98 | ] 99 | 100 | ] 101 | 102 | ] 103 | } -------------------------------------------------------------------------------- /config/scriptApproval.txt: -------------------------------------------------------------------------------- 1 | scriptApproval{ 2 | approvedSignatures=[ 3 | 'method groovy.util.ConfigSlurper parse java.lang.String', 4 | 'staticMethod java.lang.System getenv', 5 | 'method org.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval approveSignature java.lang.String', 6 | 'staticMethod org.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval get', 7 | 8 | 'field jenkins.model.Jenkins clouds', 9 | 'new org.csanchez.jenkins.plugins.kubernetes.KubernetesCloud java.lang.String', 10 | 'method org.csanchez.jenkins.plugins.kubernetes.KubernetesCloud setContainerCapStr java.lang.String', 11 | 'method org.csanchez.jenkins.plugins.kubernetes.KubernetesCloud setServerUrl java.lang.String', 12 | 'method org.csanchez.jenkins.plugins.kubernetes.KubernetesCloud setSkipTlsVerify boolean', 13 | 'method org.csanchez.jenkins.plugins.kubernetes.KubernetesCloud setNamespace java.lang.String', 14 | 'method org.csanchez.jenkins.plugins.kubernetes.KubernetesCloud setJenkinsUrl java.lang.String', 15 | 'method org.csanchez.jenkins.plugins.kubernetes.KubernetesCloud setCredentialsId java.lang.String', 16 | 'method org.csanchez.jenkins.plugins.kubernetes.KubernetesCloud setRetentionTimeout int', 17 | 'method org.csanchez.jenkins.plugins.kubernetes.KubernetesCloud setConnectTimeout int', 18 | 'method org.csanchez.jenkins.plugins.kubernetes.KubernetesCloud setReadTimeout int', 19 | 'method org.csanchez.jenkins.plugins.kubernetes.KubernetesCloud setMaxRequestsPerHostStr java.lang.String', 20 | 'method org.csanchez.jenkins.plugins.kubernetes.KubernetesCloud getTemplates', 21 | 'method java.util.Collection clear', 22 | 'new org.csanchez.jenkins.plugins.kubernetes.PodTemplate', 23 | 'method org.csanchez.jenkins.plugins.kubernetes.PodTemplate setLabel java.lang.String', 24 | 'method org.csanchez.jenkins.plugins.kubernetes.PodTemplate setName java.lang.String', 25 | 'method org.csanchez.jenkins.plugins.kubernetes.PodTemplate setSlaveConnectTimeout int', 26 | 'method org.csanchez.jenkins.plugins.kubernetes.PodTemplate setNodeSelector java.lang.String', 27 | 'method org.csanchez.jenkins.plugins.kubernetes.PodTemplate setNodeUsageMode java.lang.String', 28 | 'new org.csanchez.jenkins.plugins.kubernetes.volumes.workspace.EmptyDirWorkspaceVolume java.lang.Boolean', 29 | 'method org.csanchez.jenkins.plugins.kubernetes.PodTemplate setWorkspaceVolume org.csanchez.jenkins.plugins.kubernetes.volumes.workspace.WorkspaceVolume', 30 | 'new org.csanchez.jenkins.plugins.kubernetes.volumes.HostPathVolume java.lang.String java.lang.String', 31 | 'method org.csanchez.jenkins.plugins.kubernetes.PodTemplate setVolumes java.util.List', 32 | 'new org.csanchez.jenkins.plugins.kubernetes.model.KeyValueEnvVar java.lang.String java.lang.String', 33 | 'new org.csanchez.jenkins.plugins.kubernetes.PodEnvVar java.lang.String java.lang.String', 34 | 'method org.csanchez.jenkins.plugins.kubernetes.PodTemplate setEnvVars java.util.List', 35 | 'method org.csanchez.jenkins.plugins.kubernetes.PodTemplate setInheritFrom java.lang.String', 36 | 'new org.csanchez.jenkins.plugins.kubernetes.ContainerTemplate java.lang.String java.lang.String', 37 | 'method org.csanchez.jenkins.plugins.kubernetes.ContainerTemplate setAlwaysPullImage boolean', 38 | 'method org.csanchez.jenkins.plugins.kubernetes.ContainerTemplate setPrivileged boolean', 39 | 'method org.csanchez.jenkins.plugins.kubernetes.ContainerTemplate setTtyEnabled boolean', 40 | 'method org.csanchez.jenkins.plugins.kubernetes.ContainerTemplate setWorkingDir java.lang.String', 41 | 'method org.csanchez.jenkins.plugins.kubernetes.ContainerTemplate setArgs java.lang.String', 42 | 'method org.csanchez.jenkins.plugins.kubernetes.ContainerTemplate setResourceRequestCpu java.lang.String', 43 | 'method org.csanchez.jenkins.plugins.kubernetes.ContainerTemplate setResourceLimitCpu java.lang.String', 44 | 'method org.csanchez.jenkins.plugins.kubernetes.ContainerTemplate setResourceRequestMemory java.lang.String', 45 | 'method org.csanchez.jenkins.plugins.kubernetes.ContainerTemplate setResourceLimitMemory java.lang.String', 46 | 'method org.csanchez.jenkins.plugins.kubernetes.ContainerTemplate setCommand java.lang.String', 47 | 'method org.csanchez.jenkins.plugins.kubernetes.PodTemplate setContainers java.util.List', 48 | 'new java.lang.Exception java.lang.String' 49 | 50 | ] 51 | } 52 | -------------------------------------------------------------------------------- /config/scriptApprovalExample.txt: -------------------------------------------------------------------------------- 1 | scriptApproval{ 2 | approvedSignatures=[ 3 | 'method groovy.util.ConfigSlurper parse java.lang.String', 4 | 'staticMethod java.lang.System getenv', 5 | 'method org.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval approveSignature java.lang.String', 6 | 'staticMethod org.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval get' 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | git clone ssh://git@your_scm_here/jenkins_config_as_code.git ${JENKINS_HOME}/jenkins_config 4 | mv ${JENKINS_HOME}/jenkins_config/*.groovy ${JENKINS_HOME}/init.groovy.d/ 5 | 6 | consul-template \ 7 | -consul-addr "$CONSUL_ADDR" \ 8 | -vault-addr "$VAULT_ADDR" \ 9 | -config "jenkins_config.hcl" \ 10 | -once 11 | 12 | -------------------------------------------------------------------------------- /jenkins_config.hcl: -------------------------------------------------------------------------------- 1 | max_stale = "10m" 2 | retry = "5s" 3 | log_level = "warn" 4 | 5 | vault { 6 | renew_token = true 7 | ssl { 8 | enabled = true 9 | verify = false 10 | } 11 | retry { 12 | enabled = true 13 | attempts = 0 14 | } 15 | } 16 | 17 | template { 18 | source = "/var/jenkins_home/jenkins_config/credentials.ctmpl" 19 | destination = "/var/jenkins_home/jenkins_config/credentials.txt" 20 | perms = 0600 21 | backup = true 22 | } 23 | 24 | template { 25 | source = "/var/jenkins_home/jenkins_config/kubernetes.ctmpl" 26 | destination = "/var/jenkins_home/jenkins_config/kubernetes.txt" 27 | perms = 0600 28 | backup = true 29 | } -------------------------------------------------------------------------------- /src/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kenych/jenkins_config_as_code/e9cb4c1f5014ce668337040f770897d39a255566/src/.DS_Store -------------------------------------------------------------------------------- /src/credentials.groovy: -------------------------------------------------------------------------------- 1 | import hudson.model.* 2 | import jenkins.model.* 3 | import com.cloudbees.plugins.credentials.CredentialsScope 4 | import com.cloudbees.plugins.credentials.domains.Domain 5 | import com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl 6 | 7 | def domain = Domain.global() 8 | def store = Jenkins.instance.getExtensionList('com.cloudbees.plugins.credentials.SystemCredentialsProvider')[0].getStore() 9 | 10 | def instance = System.getenv("JENKINS_INSTANCE_NAME").replaceAll('-','_') 11 | 12 | ConfigObject conf = new ConfigSlurper().parse(new File(System.getenv("JENKINS_HOME")+'/jenkins_config/credentials.txt').text) 13 | 14 | conf.common_credentials.each { key, credentials -> 15 | println("Adding common credential ${key}") 16 | store.addCredentials(domain, new UsernamePasswordCredentialsImpl(CredentialsScope.GLOBAL, key, credentials.description, credentials.username, credentials.password)) 17 | } 18 | 19 | 20 | conf."${instance}_credentials".each { key, credentials -> 21 | println("Adding ${instance} credential ${key}") 22 | store.addCredentials(domain, new UsernamePasswordCredentialsImpl(CredentialsScope.GLOBAL, key, credentials.description, credentials.username, credentials.password)) 23 | } 24 | 25 | println("Successfully configured credentials") -------------------------------------------------------------------------------- /src/kubernetes.groovy: -------------------------------------------------------------------------------- 1 | import hudson.model.* 2 | import jenkins.model.* 3 | import org.csanchez.jenkins.plugins.kubernetes.* 4 | import org.csanchez.jenkins.plugins.kubernetes.volumes.workspace.EmptyDirWorkspaceVolume 5 | import org.csanchez.jenkins.plugins.kubernetes.volumes.HostPathVolume 6 | 7 | //since kubernetes-1.0 8 | //import org.csanchez.jenkins.plugins.kubernetes.model.KeyValueEnvVar 9 | import org.csanchez.jenkins.plugins.kubernetes.PodEnvVar 10 | 11 | //change after testing 12 | ConfigObject conf = new ConfigSlurper().parse(new File(System.getenv("JENKINS_HOME") + '/jenkins_config/kubernetes.txt').text) 13 | 14 | def kc 15 | try { 16 | println("Configuring k8s") 17 | 18 | 19 | if (Jenkins.instance.clouds) { 20 | kc = Jenkins.instance.clouds.get(0) 21 | println "cloud found: ${Jenkins.instance.clouds}" 22 | } else { 23 | kc = new KubernetesCloud(conf.kubernetes.name) 24 | Jenkins.instance.clouds.add(kc) 25 | println "cloud added: ${Jenkins.instance.clouds}" 26 | } 27 | 28 | kc.setContainerCapStr(conf.kubernetes.containerCapStr) 29 | kc.setServerUrl(conf.kubernetes.serverUrl) 30 | kc.setSkipTlsVerify(conf.kubernetes.skipTlsVerify) 31 | kc.setNamespace(conf.kubernetes.namespace) 32 | kc.setJenkinsUrl(conf.kubernetes.jenkinsUrl) 33 | kc.setCredentialsId(conf.kubernetes.credentialsId) 34 | kc.setRetentionTimeout(conf.kubernetes.retentionTimeout) 35 | //since kubernetes-1.0 36 | // kc.setConnectTimeout(conf.kubernetes.connectTimeout) 37 | kc.setReadTimeout(conf.kubernetes.readTimeout) 38 | //since kubernetes-1.0 39 | // kc.setMaxRequestsPerHostStr(conf.kubernetes.maxRequestsPerHostStr) 40 | 41 | println "set templates" 42 | kc.templates.clear() 43 | 44 | conf.kubernetes.podTemplates.each { podTemplateConfig -> 45 | 46 | def podTemplate = new PodTemplate() 47 | podTemplate.setLabel(podTemplateConfig.label) 48 | podTemplate.setName(podTemplateConfig.name) 49 | 50 | if (podTemplateConfig.inheritFrom) podTemplate.setInheritFrom(podTemplateConfig.inheritFrom) 51 | if (podTemplateConfig.slaveConnectTimeout) podTemplate.setSlaveConnectTimeout(podTemplateConfig.slaveConnectTimeout) 52 | if (podTemplateConfig.idleMinutes) podTemplate.setIdleMinutes(podTemplateConfig.idleMinutes) 53 | if (podTemplateConfig.nodeSelector) podTemplate.setNodeSelector(podTemplateConfig.nodeSelector) 54 | // 55 | //since kubernetes-1.0 56 | // if (podTemplateConfig.nodeUsageMode) podTemplate.setNodeUsageMode(podTemplateConfig.nodeUsageMode) 57 | if (podTemplateConfig.customWorkspaceVolumeEnabled) podTemplate.setCustomWorkspaceVolumeEnabled(podTemplateConfig.customWorkspaceVolumeEnabled) 58 | 59 | if (podTemplateConfig.workspaceVolume) { 60 | if (podTemplateConfig.workspaceVolume.type == 'EmptyDirWorkspaceVolume') { 61 | podTemplate.setWorkspaceVolume(new EmptyDirWorkspaceVolume(podTemplateConfig.workspaceVolume.memory)) 62 | } 63 | } 64 | 65 | if (podTemplateConfig.volumes) { 66 | def volumes = [] 67 | podTemplateConfig.volumes.each { volume -> 68 | if (volume.type == 'HostPathVolume') { 69 | volumes << new HostPathVolume(volume.hostPath, volume.mountPath) 70 | 71 | } 72 | } 73 | podTemplate.setVolumes(volumes) 74 | } 75 | 76 | if (podTemplateConfig.keyValueEnvVar) { 77 | def envVars = [] 78 | podTemplateConfig.keyValueEnvVar.each { keyValueEnvVar -> 79 | 80 | //since kubernetes-1.0 81 | // envVars << new KeyValueEnvVar(keyValueEnvVar.key, keyValueEnvVar.value) 82 | envVars << new PodEnvVar(keyValueEnvVar.key, keyValueEnvVar.value) 83 | } 84 | podTemplate.setEnvVars(envVars) 85 | } 86 | 87 | 88 | if (podTemplateConfig.containerTemplate) { 89 | println "containerTemplate: ${podTemplateConfig.containerTemplate}" 90 | 91 | ContainerTemplate ct = new ContainerTemplate( 92 | podTemplateConfig.containerTemplate.name ?: conf.kubernetes.containerTemplateDefaults.name, 93 | podTemplateConfig.containerTemplate.image) 94 | 95 | ct.setAlwaysPullImage(podTemplateConfig.containerTemplate.alwaysPullImage ?: conf.kubernetes.containerTemplateDefaults.alwaysPullImage) 96 | ct.setPrivileged(podTemplateConfig.containerTemplate.privileged ?: conf.kubernetes.containerTemplateDefaults.privileged) 97 | ct.setTtyEnabled(podTemplateConfig.containerTemplate.ttyEnabled ?: conf.kubernetes.containerTemplateDefaults.ttyEnabled) 98 | ct.setWorkingDir(podTemplateConfig.containerTemplate.workingDir ?: conf.kubernetes.containerTemplateDefaults.workingDir) 99 | ct.setArgs(podTemplateConfig.containerTemplate.args ?: conf.kubernetes.containerTemplateDefaults.args) 100 | ct.setResourceRequestCpu(podTemplateConfig.containerTemplate.resourceRequestCpu ?: conf.kubernetes.containerTemplateDefaults.resourceRequestCpu) 101 | ct.setResourceLimitCpu(podTemplateConfig.containerTemplate.resourceLimitCpu ?: conf.kubernetes.containerTemplateDefaults.resourceLimitCpu) 102 | ct.setResourceRequestMemory(podTemplateConfig.containerTemplate.resourceRequestMemory ?: conf.kubernetes.containerTemplateDefaults.resourceRequestMemory) 103 | ct.setResourceLimitMemory(podTemplateConfig.containerTemplate.resourceLimitMemory ?: conf.kubernetes.containerTemplateDefaults.resourceLimitMemory) 104 | ct.setCommand(podTemplateConfig.containerTemplate.command ?: conf.kubernetes.containerTemplateDefaults.command) 105 | podTemplate.setContainers([ct]) 106 | } 107 | 108 | println "adding ${podTemplateConfig.name}" 109 | kc.templates << podTemplate 110 | 111 | } 112 | 113 | kc = null 114 | println("Configuring k8s completed") 115 | } 116 | finally { 117 | //if we don't null kc, jenkins will try to serialise k8s objects and that will fail, so we won't see actual error 118 | kc = null 119 | } 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | -------------------------------------------------------------------------------- /src/scriptApproval.groovy: -------------------------------------------------------------------------------- 1 | import org.jenkinsci.plugins.scriptsecurity.scripts.* 2 | 3 | ScriptApproval script = ScriptApproval.get() 4 | 5 | ConfigObject conf = new ConfigSlurper().parse(new File(System.getenv("JENKINS_HOME") + '/jenkins_config/scriptApproval.txt').text) 6 | 7 | conf.scriptApproval.approvedSignatures.each{ approvedSignature -> 8 | println("checking for new signature ${approvedSignature}") 9 | 10 | def found = script.approvedSignatures.find { it == approvedSignature } 11 | 12 | if (!found){ 13 | println("Approving signature ${approvedSignature}") 14 | script.approveSignature(approvedSignature) 15 | } 16 | 17 | } 18 | 19 | 20 | --------------------------------------------------------------------------------