├── .gitignore
├── LICENSE
├── Makefile
├── README.md
├── bin
└── .gitkeep
├── resources
├── README.md
├── agentManagement
│ ├── AWSAgentBootstrap.groovy
│ └── AWSAgentDestroy.groovy
├── config
│ ├── configuration-as-code-plugin
│ │ └── jenkins.yaml
│ └── groovy
│ │ ├── auth.groovy
│ │ ├── baseURL.groovy
│ │ ├── credentials.groovy
│ │ ├── github.groovy
│ │ ├── globalEnvVars.groovy
│ │ ├── globalSharedLibrary.groovy
│ │ ├── securitySettings.groovy
│ │ ├── slack.groovy
│ │ ├── theme.groovy
│ │ ├── timezone.groovy
│ │ ├── triggerConfigurationAsCodePlugin.groovy
│ │ └── userPublicKeys.groovy
├── docker
│ ├── Dockerfile
│ ├── dsl
│ │ └── ConfigurationAndSeedingPipelineDSL.groovy
│ ├── init.groovy.d
│ │ └── init.groovy
│ ├── plugins.txt
│ └── scriptApproval.xml
├── helm
│ ├── Chart.yaml
│ ├── templates
│ │ ├── ingress.yaml
│ │ ├── secrets.yaml
│ │ ├── services.yaml
│ │ └── statefulsets.yaml
│ └── values.yaml
├── init
│ └── ConfigurationAndSeedingPipeline.groovy
├── jobDSL
│ ├── agentManagement.groovy
│ └── example.groovy
└── terraform
│ ├── Makefile
│ ├── README.md
│ ├── aws
│ ├── agent-network
│ │ ├── Makefile
│ │ ├── all.tf
│ │ ├── aws-agent-network.backend.config
│ │ ├── io.tf
│ │ └── terraform.tfvars
│ └── agent-vms
│ │ ├── Makefile
│ │ ├── all.tf
│ │ ├── aws-agent-vms.backend.config
│ │ ├── io.tf
│ │ ├── terraform.tfvars
│ │ └── user_data
│ │ └── docker.sh
│ └── config
└── vars
├── AWSAgentBootstrap.groovy
├── AWSAgentDestroy.groovy
└── printDockerVersion.groovy
/.gitignore:
--------------------------------------------------------------------------------
1 | *.swp
2 | resources/helm/secret-files
3 | .terraform
4 | bin/helm
5 | bin/kubectl
6 | bin/minikube
7 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 devtail
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | get-tools-linux: ARCH=linux
2 | get-tools-mac: ARCH=darwin
3 |
4 | .PHONY: help
5 |
6 | help: ## Prints help for targets with comments
7 | @grep -E '^[a-zA-Z0-9.\ _-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
8 |
9 | get-tools-linux get-tools-mac: ## Pull dep-less binaries (minikube, kubectl, helm) to local bin/
10 | # TODO: verify checksums ..
11 | curl -Lo bin/minikube https://storage.googleapis.com/minikube/releases/v1.0.0/minikube-$(ARCH)-amd64 && chmod +x bin/minikube
12 | curl -Lo bin/kubectl https://storage.googleapis.com/kubernetes-release/release/v1.14.0/bin/$(ARCH)/amd64/kubectl && chmod +x bin/kubectl
13 | curl -L https://storage.googleapis.com/kubernetes-helm/helm-v2.13.1-$(ARCH)-amd64.tar.gz | tar -xz -C bin/ && mv bin/$(ARCH)-amd64/helm bin/ && rm -r bin/$(ARCH)-amd64
14 |
15 | minikube-start: ## Start and prepare minikube with ingress addon
16 | bin/minikube start --extra-config=apiserver.service-node-port-range=80-32000
17 | bin/minikube addons enable ingress
18 | bin/helm init --history-max 100
19 |
20 | helm-deploy: ## Deploy jenkins to minikube
21 | bin/helm upgrade --wait --install jenkins resources/helm
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://quay.io/repository/devtail/jenkins-as-code)
2 |
3 | # jenkins-as-code
4 |
5 | **[Demo] Bootstrapping Jenkins:**
6 |
7 |
8 |
9 |
10 | This repository contains a Jenkins-as-Code approach.
11 | Everything is tested and running with Jenkins `2.204.1` on minikube `v1.0.0` (the .gif you above was done with an older version).
12 | The setup is based on docker, helm and git so it can be easily applied in different infrastructures.
13 | Plugins and minimum setup are pre-baked inside a docker image.
14 | A configuration and seeding pipeline provisions Jenkins with configuration code from a central git repository.
15 | Configuration includes: agents on demand (with terraform), slack, github, github-oauth, security settings, theming, ...
16 |
17 | ## Running locally
18 |
19 | The following files with your secrets have to be created to run this prototype:
20 |
21 | ```
22 | resources/helm/
23 | |-- secret-files
24 | |-- default-setup-password # pre-baked setup user password
25 | |-- default-setup-user # pre-baked setup user name
26 | |-- deploy-key-shared-library # private ssh deploy key
27 | |-- deploy-key-shared-library.pub # public ssh deploy key
28 | |-- github-ci-password # GitHub Jenkins user password
29 | |-- github-ci-token # GitHub Jenkins user access token
30 | |-- github-ci-user # GitHub Jenkins user name
31 | |-- github-oauth-client-id
32 | |-- github-oauth-client-secret
33 | |-- slack-token
34 | |-- ssh-agent-access-key # private ssh key for agent access
35 | |-- ssh-agent-access-key.pub # public ssh key for agent access
36 | `-- terraform-config # Terraform backend configs and secrets
37 | |-- aws-agent-network.backend.config
38 | |-- aws-agent-network.tfvars
39 | |-- aws-agent-vms.backend.config
40 | `-- aws-agent-vms.tfvars
41 | ```
42 |
43 | After you have placed your secret files you can run:
44 |
45 | ```
46 | make get-tools-(linux|mac)
47 | make minikube-start
48 | make deploy-helm
49 | ```
50 |
51 | This should open Jenkins on [http://192.168.99.100/](http://192.168.99.100/).
52 |
53 | ## On-Demand Agents
54 |
55 | The code base also supports on-demand agents with custom terraform bootstrapping/destroy pipelines.
56 | A demo can be found [here](resources/README.md)
57 |
58 | ## Detailed Explanations
59 |
60 | The following blog entries describe in more detail how this works:
61 |
62 | - [Jenkins-as-Code Part I | Initial Setup](https://fishi.devtail.io/weblog/2019/01/06/jenkins-as-code-part-1/)
63 | - [Jenkins-as-Code Part II | Configuration](https://fishi.devtail.io/weblog/2019/01/12/jenkins-as-code-part-2/)
64 | - [Jenkins-as-Code Part III | JobDSL](https://fishi.devtail.io/weblog/2019/02/09/jenkins-as-code-part-3/)
65 |
--------------------------------------------------------------------------------
/bin/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devtail/jenkins-as-code/5d5e977c709a59d047f767b7a04e528268f9ee7a/bin/.gitkeep
--------------------------------------------------------------------------------
/resources/README.md:
--------------------------------------------------------------------------------
1 | ## On-Demand Agents
2 |
3 | **[Demo] On-Demand Agents:**
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/resources/agentManagement/AWSAgentBootstrap.groovy:
--------------------------------------------------------------------------------
1 | @Library('devtail-ci-lib@master') _
2 |
3 | AWSAgentBootstrap(agentID: env.agentID)
4 |
--------------------------------------------------------------------------------
/resources/agentManagement/AWSAgentDestroy.groovy:
--------------------------------------------------------------------------------
1 | @Library('devtail-ci-lib@master') _
2 |
3 | AWSAgentDestroy(agentID: env.agentID)
4 |
--------------------------------------------------------------------------------
/resources/config/configuration-as-code-plugin/jenkins.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | jenkins:
3 | systemMessage: "Powered automagically by Groovy and Configuration-as-Code Plugin\n\n"
4 | numExecutors: 5
5 |
6 | crumbIssuer:
7 | standard:
8 | excludeClientIPFromCrumb: false
9 |
10 | remotingSecurity:
11 | enabled: true
12 |
13 | globalNodeProperties:
14 | - envVars:
15 | env:
16 | - key: "DEVTAIL_DEBUG"
17 | value: "True"
18 |
19 | authorizationStrategy:
20 | globalMatrix:
21 | grantedPermissions:
22 | - "Overall/Administer:devtail*Admin"
23 | - "Overall/Administer:admin"
24 |
25 | securityRealm:
26 | github:
27 | githubWebUri: "https://github.com"
28 | githubApiUri: "https://api.github.com"
29 | clientID: "${jenkins-tokens/github-oauth-client-id}"
30 | clientSecret: "${jenkins-tokens/github-oauth-client-secret}"
31 | oauthScopes: "read:org,user:email"
32 |
33 | nodes:
34 | - permanent:
35 | labelString: "docker"
36 | name: "docker-agent-1"
37 | nodeName: "docker-agent-1"
38 | numExecutors: 2
39 | remoteFS: "/home/ubuntu"
40 | launcher:
41 | setupSlaveLauncher:
42 | startScript: "java -jar /var/jenkins_home/war/WEB-INF/jenkins-cli.jar -s http://localhost:8080 -ssh -user admin -i /var/jenkins_home/jenkins-ssh-keys/ssh-agent-access-key build 'Admin/AWSAgentBootstrap' -p agentID='0' -s"
43 | stopScript: "java -jar /var/jenkins_home/war/WEB-INF/jenkins-cli.jar -s http://localhost:8080 -ssh -user admin -i /var/jenkins_home/jenkins-ssh-keys/ssh-agent-access-key build 'Admin/AWSAgentDestroy' -p agentID='0' -s"
44 | launcher:
45 | sSHLauncher:
46 | credentialsId: "ssh-agent-access-key"
47 | host: "18.195.157.53"
48 | workDir: "/home/ubuntu"
49 | sshHostKeyVerificationStrategy: "nonVerifyingKeyVerificationStrategy"
50 | retentionStrategy:
51 | demand:
52 | idleDelay: 1000
53 | inDemandDelay: 0
54 | - permanent:
55 | labelString: "docker"
56 | name: "docker-agent-2"
57 | nodeName: "docker-agent-2"
58 | numExecutors: 2
59 | remoteFS: "/home/ubuntu"
60 | launcher:
61 | setupSlaveLauncher:
62 | startScript: "java -jar /var/jenkins_home/war/WEB-INF/jenkins-cli.jar -s http://localhost:8080 -ssh -user admin -i /var/jenkins_home/jenkins-ssh-keys/ssh-agent-access-key build 'Admin/AWSAgentBootstrap' -p agentID='1' -s"
63 | stopScript: "java -jar /var/jenkins_home/war/WEB-INF/jenkins-cli.jar -s http://localhost:8080 -ssh -user admin -i /var/jenkins_home/jenkins-ssh-keys/ssh-agent-access-key build 'Admin/AWSAgentDestroy' -p agentID='1' -s"
64 | launcher:
65 | sSHLauncher:
66 | credentialsId: "ssh-agent-access-key"
67 | host: "3.122.182.67"
68 | workDir: "/home/ubuntu"
69 | sshHostKeyVerificationStrategy: "nonVerifyingKeyVerificationStrategy"
70 | retentionStrategy:
71 | demand:
72 | idleDelay: 1000
73 | inDemandDelay: 0
74 |
75 | security:
76 | globalJobDslSecurityConfiguration:
77 | useScriptSecurity: false
78 | sSHD:
79 | port: 6666
80 |
81 | credentials:
82 | system:
83 | domainCredentials:
84 | - credentials:
85 | #######
86 | # User Auth
87 | #######
88 | - usernamePassword:
89 | scope: "GLOBAL"
90 | id: "github-ci-user"
91 | description: "Github CI User Credentials"
92 | username: "${jenkins-basic-auth-credentials/github-ci-user}"
93 | password: "${jenkins-basic-auth-credentials/github-ci-password}"
94 | ########
95 | # Tokens
96 | ########
97 | - string:
98 | scope: "GLOBAL"
99 | id: "slack-token"
100 | description: "Slack Access Token"
101 | secret: "${jenkins-tokens/slack-token}"
102 | - string:
103 | scope: "GLOBAL"
104 | id: "github-ci-token"
105 | description: "Github CI User Token"
106 | secret: "${jenkins-tokens/github-ci-token}"
107 | - string:
108 | scope: "GLOBAL"
109 | id: "github-oauth-client-id"
110 | description: "Github OAuth Client ID"
111 | secret: "${jenkins-tokens/github-oauth-client-id}"
112 | - string:
113 | scope: "GLOBAL"
114 | id: "github-oauth-client-secret"
115 | description: "Github OAuth Client Secret"
116 | secret: "${jenkins-tokens/github-oauth-client-secret}"
117 | ########
118 | # SSH Keys
119 | ########
120 | - basicSSHUserPrivateKey:
121 | scope: "GLOBAL"
122 | id: "deploy-key-shared-library"
123 | username: "root"
124 | passphrase: ""
125 | description: "Deploy key for global shared library"
126 | privateKeySource:
127 | directEntry:
128 | privateKey: "${jenkins-ssh-keys/deploy-key-shared-library}"
129 | - basicSSHUserPrivateKey:
130 | scope: "GLOBAL"
131 | id: "ssh-agent-access-key"
132 | username: "ubuntu"
133 | passphrase: ""
134 | description: "SSH key to access agents"
135 | privateKeySource:
136 | directEntry:
137 | privateKey: "${jenkins-ssh-keys/ssh-agent-access-key}"
138 |
139 | unclassified:
140 | location:
141 | url: "http://192.168.99.100:30001/"
142 | adminAddress: "admin@devtail.io"
143 |
144 | globalLibraries:
145 | libraries:
146 | - name: "devtail-ci-lib"
147 | retriever:
148 | modernSCM:
149 | scm:
150 | git:
151 | remote: "git@github.com:devtail/jenkins-as-code.git"
152 | credentialsId: "deploy-key-shared-library"
153 |
154 | simple-theme-plugin:
155 | elements:
156 | - cssUrl:
157 | url: "https://fishi.devtail.io/content-images/jenkins-devtail-theme.css"
158 |
159 | slackNotifier:
160 | teamDomain: "devtail"
161 | baseUrl: "https://devtail.slack.com/services/hooks/jenkins-ci/"
162 | tokenCredentialId: "slack-token"
163 |
164 | githubpluginconfig:
165 | configs:
166 | - name: "Github"
167 | credentialsId: "github-ci-token"
168 | manageHooks: true
169 |
--------------------------------------------------------------------------------
/resources/config/groovy/auth.groovy:
--------------------------------------------------------------------------------
1 | #!groovy
2 |
3 | /*
4 | * This script configures Github OAuth access
5 | * in Jenkins. It uses a global authorization
6 | * Matrix strategy as authorization configurtion.
7 | * This script requires the Gibhub Authentication
8 | * plugin (github-oauth) to be installed. It is
9 | * tested with github-oauth:0.29
10 | */
11 |
12 | import hudson.security.SecurityRealm
13 | import org.jenkinsci.plugins.GithubSecurityRealm
14 | import jenkins.model.*
15 | import hudson.security.*
16 |
17 | // Setup OAUTH Realm
18 | String githubWebUri = GithubSecurityRealm.DEFAULT_WEB_URI
19 | String githubApiUri = GithubSecurityRealm.DEFAULT_API_URI
20 | String oauthScopes = 'read:org,user:email' //GithubSecurityRealm.DEFAULT_OAUTH_SCOPES
21 | String clientID = System.getenv()['GITHUB_OAUTH_CLIENT_ID'] // TODO: get from credential store
22 | String clientSecret = System.getenv()['GITHUB_OAUTH_CLIENT_SECRET'] // TODO: get from credential store
23 |
24 | SecurityRealm github_realm = new GithubSecurityRealm(githubWebUri, githubApiUri, clientID, clientSecret, oauthScopes)
25 | Jenkins.instance.setSecurityRealm(github_realm)
26 |
27 | // Create global authorization matrix
28 | def strategy = new GlobalMatrixAuthorizationStrategy()
29 |
30 | // Give admin access to fishi0x01 user
31 | strategy.add(Jenkins.ADMINISTER, "fishi0x01")
32 |
33 | // Give admin access to my_team_name
34 | strategy.add(Jenkins.ADMINISTER, "devtail*Admin")
35 |
36 | // wrap up
37 | Jenkins.instance.setAuthorizationStrategy(strategy)
38 | Jenkins.instance.save()
39 |
--------------------------------------------------------------------------------
/resources/config/groovy/baseURL.groovy:
--------------------------------------------------------------------------------
1 | #!groovy
2 |
3 | /*
4 | * This script configures the Jenkins base URL.
5 | */
6 |
7 | import jenkins.model.JenkinsLocationConfiguration
8 |
9 | JenkinsLocationConfiguration location = Jenkins.instance.getExtensionList('jenkins.model.JenkinsLocationConfiguration')[0]
10 | location.url = 'http://192.168.99.100:30001/' // minikube:jenkins-node-port
11 | location.save()
12 |
--------------------------------------------------------------------------------
/resources/config/groovy/credentials.groovy:
--------------------------------------------------------------------------------
1 | #!groovy
2 |
3 | /*
4 | * This script loads different kinds
5 | * of credentials from files into the
6 | * Jenkins credential store.
7 | *
8 | * https://gist.github.com/fishi0x01/7c2d29afbaa0f16126eb4d4b35942f76#file-credentials-groovy
9 | */
10 |
11 | import jenkins.model.*
12 | import com.cloudbees.plugins.credentials.*
13 | import com.cloudbees.plugins.credentials.common.*
14 | import com.cloudbees.plugins.credentials.domains.*
15 | import com.cloudbees.plugins.credentials.impl.*
16 | import com.cloudbees.jenkins.plugins.sshcredentials.impl.*
17 | import org.jenkinsci.plugins.plaincredentials.*
18 | import org.jenkinsci.plugins.plaincredentials.impl.*
19 | import hudson.util.Secret
20 |
21 | ///////////////////
22 | // Helper functions
23 | ///////////////////
24 | def getStore() {
25 | return Jenkins.instance.getExtensionList('com.cloudbees.plugins.credentials.SystemCredentialsProvider')[0].getStore()
26 | }
27 |
28 | def getContent(filePath) {
29 | return new File(filePath).text
30 | }
31 |
32 | // This function reads the contents of a key file and returns
33 | // a Jenkins SSH private key object with the given user as owner
34 | def getSSHKeyCredential(id, path, user) {
35 | return new BasicSSHUserPrivateKey(
36 | CredentialsScope.GLOBAL,
37 | id,
38 | user,
39 | new BasicSSHUserPrivateKey.DirectEntryPrivateKeySource(getContent(path)),
40 | "",
41 | "SSH key ${id}"
42 | )
43 | }
44 |
45 | // Get master credential store
46 | domain = Domain.global()
47 |
48 | //////////////////////////////
49 | // Add username/password pairs
50 | //////////////////////////////
51 | userPasswords = [
52 | [id: 'github-ci-user', description: 'GitHub CI User Credentials', userNameFile: '/var/jenkins_home/jenkins-basic-auth-credentials/github-ci-user', userPasswordFile: '/var/jenkins_home/jenkins-basic-auth-credentials/github-ci-password'],
53 | ]
54 |
55 | for(userPassword in userPasswords) {
56 | Credentials cred = (Credentials) new UsernamePasswordCredentialsImpl(CredentialsScope.GLOBAL, userPassword.id, userPassword.description, getContent(userPassword.userNameFile), getContent(userPassword.userPasswordFile))
57 | getStore().addCredentials(domain, cred)
58 | }
59 |
60 | /////////////
61 | // Add tokens
62 | /////////////
63 | secretTokens = [
64 | [id: 'slack-token', description: 'Slack Token', tokenFile: '/var/jenkins_home/jenkins-tokens/slack-token'],
65 | [id: 'github-ci-token', description: 'Github CI User Token', tokenFile: '/var/jenkins_home/jenkins-tokens/github-ci-token'],
66 | [id: 'github-oauth-client-id', description: 'Github OAuth Client ID', tokenFile: '/var/jenkins_home/jenkins-tokens/github-oauth-client-id'],
67 | [id: 'github-oauth-client-secret', description: 'Github OAuth Client Secret', tokenFile: '/var/jenkins_home/jenkins-tokens/github-oauth-client-secret'],
68 | ]
69 |
70 | for(secretToken in secretTokens) {
71 | Credentials token = (Credentials) new StringCredentialsImpl(CredentialsScope.GLOBAL, secretToken.id, secretToken.description, Secret.fromString(getContent(secretToken.tokenFile)))
72 | getStore().addCredentials(domain, token)
73 | }
74 |
75 | ///////////////
76 | // Add ssh keys
77 | ///////////////
78 | sshKeys = [
79 | [id: 'ssh-global-shared-library', path: '/var/jenkins_home/jenkins-ssh-keys/deploy-key-shared-library', user: 'root'],
80 | ]
81 |
82 | for(sshKey in sshKeys) {
83 | getStore().addCredentials(domain, getSSHKeyCredential(sshKey.id, sshKey.path, sshKey.user))
84 | }
85 |
--------------------------------------------------------------------------------
/resources/config/groovy/github.groovy:
--------------------------------------------------------------------------------
1 | #!groovy
2 |
3 | /*
4 | * This script configures the GitHub Plugin.
5 | * Requires the GitHub Plugin to be installed.
6 | * Tested with github:1.29.3
7 | */
8 |
9 | import jenkins.model.Jenkins
10 | import org.jenkinsci.plugins.github.config.GitHubPluginConfig
11 | import org.jenkinsci.plugins.github.config.GitHubServerConfig
12 |
13 | def githubConfig = new GitHubServerConfig("github-ci-token") // credential ID for our user token for the GitHub CI User
14 | githubConfig.setManageHooks(true)
15 | githubConfig.setName("GitHub")
16 | def github = Jenkins.instance.getExtensionList(GitHubPluginConfig.class)[0]
17 | github.setConfigs([
18 | githubConfig,
19 | ])
20 | github.save()
21 |
--------------------------------------------------------------------------------
/resources/config/groovy/globalEnvVars.groovy:
--------------------------------------------------------------------------------
1 | #!groovy
2 |
3 | /*
4 | * This script configures global environment variables in Jenkins
5 | */
6 |
7 | import jenkins.model.Jenkins
8 | import hudson.EnvVars;
9 | import hudson.slaves.EnvironmentVariablesNodeProperty;
10 | import hudson.slaves.NodeProperty;
11 | import hudson.slaves.NodePropertyDescriptor;
12 | import hudson.util.DescribableList;
13 |
14 | def createGlobalEnvironmentVariables(String key, String value){
15 |
16 | Jenkins instance = Jenkins.getInstance();
17 |
18 | DescribableList, NodePropertyDescriptor> globalNodeProperties = instance.getGlobalNodeProperties();
19 | List envVarsNodePropertyList = globalNodeProperties.getAll(EnvironmentVariablesNodeProperty.class);
20 |
21 | EnvironmentVariablesNodeProperty newEnvVarsNodeProperty = null;
22 | EnvVars envVars = null;
23 |
24 | if ( envVarsNodePropertyList == null || envVarsNodePropertyList.size() == 0 ) {
25 | newEnvVarsNodeProperty = new hudson.slaves.EnvironmentVariablesNodeProperty();
26 | globalNodeProperties.add(newEnvVarsNodeProperty);
27 | envVars = newEnvVarsNodeProperty.getEnvVars();
28 | } else {
29 | envVars = envVarsNodePropertyList.get(0).getEnvVars();
30 | }
31 | envVars.put(key, value)
32 | instance.save()
33 | }
34 |
35 | createGlobalEnvironmentVariables('DEBUG', 'True')
36 |
--------------------------------------------------------------------------------
/resources/config/groovy/globalSharedLibrary.groovy:
--------------------------------------------------------------------------------
1 | #!groovy
2 |
3 | /*
4 | * Configure pipeline shared libraries in the global Jenkins configuration.
5 | * This will safely compare configured libraries and only overwrite the global
6 | * shared library config if changes have been made.
7 | * workflow-cps-global-lib:2.12
8 | *
9 | * Source: https://github.com/thbkrkr/jks/blob/master/init.groovy.d/11-configure-pipeline-global-shared.groovy
10 | */
11 | import jenkins.model.Jenkins
12 | import jenkins.plugins.git.GitSCMSource
13 | import jenkins.plugins.git.traits.BranchDiscoveryTrait
14 | import org.jenkinsci.plugins.workflow.libs.GlobalLibraries
15 | import org.jenkinsci.plugins.workflow.libs.LibraryConfiguration
16 | import org.jenkinsci.plugins.workflow.libs.SCMSourceRetriever
17 |
18 | List libraries = [] as ArrayList
19 |
20 | def remote = 'git@github.com:devtail/jenkins-as-code.git'
21 | def credentialsId = 'deploy-key-shared-library'
22 |
23 | name = 'devtail-ci'
24 | defaultVersion = 'master'
25 |
26 | if (remote != null) {
27 |
28 | def scm = new GitSCMSource(remote)
29 | if (credentialsId != null) {
30 | scm.credentialsId = credentialsId
31 | }
32 |
33 | scm.traits = [new BranchDiscoveryTrait()]
34 | def retriever = new SCMSourceRetriever(scm)
35 |
36 | def library = new LibraryConfiguration(name, retriever)
37 | library.defaultVersion = defaultVersion
38 | library.implicit = false
39 | library.allowVersionOverride = true
40 | library.includeInChangesets = false
41 |
42 | libraries << library
43 |
44 | def global_settings = Jenkins.instance.getExtensionList(GlobalLibraries.class)[0]
45 | global_settings.libraries = libraries
46 | global_settings.save()
47 | println 'Configured Pipeline Global Shared Libraries:\n ' + global_settings.libraries.collect { it.name }.join('\n ')
48 | }
49 |
--------------------------------------------------------------------------------
/resources/config/groovy/securitySettings.groovy:
--------------------------------------------------------------------------------
1 | #!groovy
2 |
3 | /*
4 | * Configure general security settings.
5 | */
6 | import jenkins.model.Jenkins
7 | import hudson.security.csrf.DefaultCrumbIssuer
8 | import jenkins.security.s2m.AdminWhitelistRule
9 |
10 |
11 | // Disable Remote CLI
12 | Jenkins.instance.getDescriptor("jenkins.CLI").get().setEnabled(false)
13 |
14 | // CSRF Issuer
15 | if(Jenkins.instance.getCrumbIssuer() == null) {
16 | Jenkins.instance.setCrumbIssuer(new DefaultCrumbIssuer(true))
17 | }
18 |
19 | // agent to master security subsystem
20 | Jenkins.instance.getInjector().getInstance(AdminWhitelistRule.class).setMasterKillSwitch(false)
21 |
22 | // sshd settings
23 | def sshDesc = Jenkins.instance.getDescriptor("org.jenkinsci.main.modules.sshd.SSHD")
24 | sshDesc.setPort(6666)
25 | sshDesc.getActualPort()
26 | sshDesc.save()
27 |
28 | Jenkins.instance.save()
29 |
--------------------------------------------------------------------------------
/resources/config/groovy/slack.groovy:
--------------------------------------------------------------------------------
1 | #!groovy
2 |
3 | /*
4 | * This script configures the Jenkins Slack Plugin.
5 | * Requires the installation of the Slack Plugin.
6 | * Tested with slack:2.14
7 | */
8 |
9 | import jenkins.model.Jenkins
10 |
11 | def slack = Jenkins.instance.getExtensionList('jenkins.plugins.slack.SlackNotifier$DescriptorImpl')[0]
12 | slack.tokenCredentialId = 'slack-token'
13 | slack.teamDomain = 'devtail'
14 | slack.baseUrl = 'https://devtail.slack.com/services/hooks/jenkins-ci/'
15 | slack.save()
16 |
--------------------------------------------------------------------------------
/resources/config/groovy/theme.groovy:
--------------------------------------------------------------------------------
1 | #!groovy
2 |
3 | /*
4 | * This script configures the simple theme plugin.
5 | * Requires the simple theme plugin to be installed.
6 | * Tested with simple-theme-plugin:0.5.1
7 | *
8 | * Use http://afonsof.com/jenkins-material-theme/ to generate a new jenkins theme.
9 | * Place the theme at the userContent directory of Jenkins to be publicly available
10 | */
11 |
12 | import jenkins.model.Jenkins
13 | import org.jenkinsci.plugins.simpletheme.CssUrlThemeElement
14 |
15 |
16 | def themeDecorator = Jenkins.instance.getExtensionList(org.codefirst.SimpleThemeDecorator.class).first()
17 |
18 | themeDecorator.setElements([
19 | new CssUrlThemeElement('https://fishi.devtail.io/content-images/jenkins-devtail-theme.css')
20 | ])
21 |
22 | Jenkins.instance.save()
23 |
24 |
--------------------------------------------------------------------------------
/resources/config/groovy/timezone.groovy:
--------------------------------------------------------------------------------
1 | #! groovy
2 |
3 | /*
4 | * This script configures the timezone in Jenkins
5 | */
6 |
7 | System.setProperty('org.apache.commons.jelly.tags.fmt.timeZone', 'Europe/Berlin')
8 |
--------------------------------------------------------------------------------
/resources/config/groovy/triggerConfigurationAsCodePlugin.groovy:
--------------------------------------------------------------------------------
1 | #! groovy
2 |
3 | import jenkins.model.Jenkins
4 |
5 | // trigger configuration
6 | def jcacPlugin = Jenkins.instance.getExtensionList(io.jenkins.plugins.casc.ConfigurationAsCode.class).first()
7 | jcacPlugin.configure()
8 |
--------------------------------------------------------------------------------
/resources/config/groovy/userPublicKeys.groovy:
--------------------------------------------------------------------------------
1 | #! groovy
2 |
3 | def getFileContent(filePath) {
4 | return new File(filePath).text
5 | }
6 |
7 | def user = hudson.model.User.get('admin')
8 |
9 | def pubKey = new org.jenkinsci.main.modules.cli.auth.ssh.UserPropertyImpl(getFileContent('/var/jenkins_home/jenkins-ssh-keys/ssh-agent-access-key.pub'))
10 | user.addProperty(pubKey)
11 |
12 | user.save()
13 |
--------------------------------------------------------------------------------
/resources/docker/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM jenkins/jenkins:2.204.1
2 |
3 | ENV ARCH=linux_amd64 \
4 | VAULT_VERSION=1.3.1 \
5 | TERRAFORM_VERSION=0.12.18
6 |
7 | # Delay for CasC + disable install wizard
8 | ENV JAVA_OPTS="-Dio.jenkins.plugins.casc.ConfigurationAsCode.initialDelay=9000 -Djenkins.install.runSetupWizard=false -Dorg.jenkinsci.main.modules.sshd.SSHD.hostName=127.0.0.1"
9 |
10 | # JCasC Plugin pointer to config/secret values
11 | ENV SECRETS="/var/jenkins_home/"
12 |
13 | USER root
14 |
15 | # Install deps
16 | RUN apt-get update -y \
17 | && apt-get install -y build-essential rsync
18 |
19 | # Add Vault client
20 | RUN curl -sL https://releases.hashicorp.com/vault/${VAULT_VERSION}/vault_${VAULT_VERSION}_${ARCH}.zip -o /tmp/vault_${VAULT_VERSION}_${ARCH}.zip \
21 | && curl -sL https://releases.hashicorp.com/vault/${VAULT_VERSION}/vault_${VAULT_VERSION}_SHA256SUMS -o /tmp/vault_${VAULT_VERSION}_SHA256SUMS \
22 | && export CUR_DIR=$(pwd) \
23 | && cd /tmp \
24 | && sha256sum -c vault_${VAULT_VERSION}_SHA256SUMS 2>&1 | grep OK \
25 | && cd ${CUR_DIR}
26 |
27 | RUN unzip /tmp/vault_${VAULT_VERSION}_${ARCH}.zip -d /bin
28 | RUN rm -f /tmp/vault_${VAULT_VERSION}_${ARCH}.zip \
29 | && rm -f /tmp/vault_${VAULT_VERSION}_SHA256SUMS
30 |
31 | # Add Terraform client
32 | RUN curl -sL https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_${ARCH}.zip -o /tmp/terraform_${TERRAFORM_VERSION}_${ARCH}.zip \
33 | && curl -sL https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_SHA256SUMS -o /tmp/terraform_${TERRAFORM_VERSION}_SHA256SUMS \
34 | && export CUR_DIR=$(pwd) \
35 | && cd /tmp \
36 | && sha256sum -c terraform_${TERRAFORM_VERSION}_SHA256SUMS 2>&1 | grep OK \
37 | && cd ${CUR_DIR}
38 |
39 | RUN unzip /tmp/terraform_${TERRAFORM_VERSION}_${ARCH}.zip -d /bin
40 | RUN rm -f /tmp/terraform_${TERRAFORM_VERSION}_${ARCH}.zip \
41 | && rm -f /tmp/terraform_${TERRAFORM_VERSION}_SHA256SUMS
42 |
43 | USER jenkins
44 |
45 | # Add minimum jenkins setup
46 | ADD init.groovy.d /usr/share/jenkins/ref/init.groovy.d
47 | ADD dsl /usr/share/jenkins/ref/dsl
48 | COPY scriptApproval.xml /var/jenkins_home/scriptApproval.xml
49 |
50 | # Install plugins
51 | COPY plugins.txt /usr/share/jenkins/ref/plugins.txt
52 | RUN /usr/local/bin/install-plugins.sh < /usr/share/jenkins/ref/plugins.txt
53 |
54 |
--------------------------------------------------------------------------------
/resources/docker/dsl/ConfigurationAndSeedingPipelineDSL.groovy:
--------------------------------------------------------------------------------
1 | #!groovy
2 |
3 | folder('Admin') {
4 | description('Folder containing configuration and seed jobs')
5 | }
6 |
7 | pipelineJob("Admin/Configure") {
8 | parameters {
9 | gitParam('revision') {
10 | type('BRANCH_TAG')
11 | sortMode('ASCENDING_SMART')
12 | defaultValue('origin/master')
13 | }
14 | }
15 |
16 | triggers {
17 | githubPush()
18 | }
19 |
20 | logRotator {
21 | numToKeep(20)
22 | }
23 |
24 | definition {
25 | cpsScm {
26 | scm {
27 | git {
28 | remote {
29 | github("devtail/jenkins-as-code", "ssh")
30 | credentials("deploy-key-shared-library")
31 | }
32 |
33 | branch('$revision')
34 | }
35 | }
36 |
37 | scriptPath('resources/init/ConfigurationAndSeedingPipeline.groovy')
38 | }
39 | }
40 | }
41 |
42 |
--------------------------------------------------------------------------------
/resources/docker/init.groovy.d/init.groovy:
--------------------------------------------------------------------------------
1 | #!groovy
2 |
3 | /*
4 | * This script is designated for the init.groovy.d
5 | * directory to be executed at startup time of the
6 | * Jenkins instance. This script requires the jobDSL
7 | * Plugin. Tested with job-dsl:1.70
8 | */
9 |
10 | import javaposse.jobdsl.dsl.DslScriptLoader
11 | import javaposse.jobdsl.plugin.JenkinsJobManagement
12 | import jenkins.model.Jenkins
13 | import com.cloudbees.plugins.credentials.domains.Domain
14 | import com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey
15 | import com.cloudbees.plugins.credentials.CredentialsScope
16 | import hudson.security.FullControlOnceLoggedInAuthorizationStrategy
17 | import hudson.security.HudsonPrivateSecurityRealm
18 |
19 |
20 | // Add deploy key for the centrally shared pipeline and configuration repository
21 | def domain = Domain.global()
22 | def store = Jenkins.instance.getExtensionList('com.cloudbees.plugins.credentials.SystemCredentialsProvider')[0].getStore()
23 | def keyFileContents = new File("/var/jenkins_home/jenkins-ssh-keys/deploy-key-shared-library").text
24 | def privateKey = new BasicSSHUserPrivateKey(
25 | CredentialsScope.GLOBAL,
26 | "deploy-key-shared-library",
27 | "root",
28 | new BasicSSHUserPrivateKey.DirectEntryPrivateKeySource(keyFileContents),
29 | "",
30 | "SSH key for shared-library"
31 | )
32 | store.addCredentials(domain, privateKey)
33 |
34 | // Create the configuration pipeline from a jobDSL script
35 | def jobDslScript = new File('/var/jenkins_home/dsl/ConfigurationAndSeedingPipelineDSL.groovy')
36 | def workspace = new File('.')
37 | def jobManagement = new JenkinsJobManagement(System.out, [:], workspace)
38 | new DslScriptLoader(jobManagement).runScript(jobDslScript.text)
39 |
40 | // Disable Wizards
41 | if(Jenkins.instance.getSecurityRealm().getClass().getSimpleName() == 'None') {
42 | def instance = Jenkins.getInstance()
43 | def setupUser = new File("/var/jenkins_home/jenkins-basic-auth-credentials/default-setup-user").text.trim()
44 | def setupPass = new File("/var/jenkins_home/jenkins-basic-auth-credentials/default-setup-password").text.trim()
45 |
46 | def hudsonRealm = new HudsonPrivateSecurityRealm(false)
47 | instance.setSecurityRealm(hudsonRealm)
48 | def user = instance.getSecurityRealm().createAccount(setupUser, setupPass)
49 | user.save()
50 |
51 | def strategy = new FullControlOnceLoggedInAuthorizationStrategy()
52 | strategy.setAllowAnonymousRead(false)
53 | instance.setAuthorizationStrategy(strategy)
54 |
55 | instance.save()
56 |
57 | println("SetupWizard Disabled")
58 | }
59 |
--------------------------------------------------------------------------------
/resources/docker/plugins.txt:
--------------------------------------------------------------------------------
1 | jdk-tool
2 | command-launcher
3 | configuration-as-code
4 | configuration-as-code-support
5 | uno-choice
6 | github-oauth
7 | workflow-cps-global-lib
8 | slack
9 | github
10 | throttle-concurrents
11 | ansicolor
12 | mask-passwords
13 | build-user-vars-plugin
14 | git-parameter
15 | authorize-project
16 | job-dsl
17 | simple-theme-plugin
18 | build-name-setter
19 | cloudbees-folder
20 | conditional-buildstep
21 | credentials-binding
22 | credentials
23 | dashboard-view
24 | display-url-api
25 | docker-commons
26 | docker-workflow
27 | durable-task
28 | email-ext
29 | emailext-template
30 | embeddable-build-status
31 | external-monitor-job
32 | git-client
33 | git-server
34 | git
35 | github-api
36 | github-branch-source
37 | handlebars
38 | hashicorp-vault-plugin
39 | icon-shim
40 | jackson2-api
41 | javadoc
42 | jquery-detached
43 | jquery
44 | jsch
45 | junit
46 | mailer
47 | matrix-auth
48 | matrix-project
49 | maven-plugin
50 | momentjs
51 | pam-auth
52 | parameterized-trigger
53 | pipeline-build-step
54 | pipeline-github-lib
55 | pipeline-graph-analysis
56 | pipeline-input-step
57 | pipeline-milestone-step
58 | pipeline-model-api
59 | pipeline-model-declarative-agent
60 | pipeline-model-definition
61 | pipeline-model-extensions
62 | pipeline-rest-api
63 | pipeline-stage-step
64 | pipeline-stage-tags-metadata
65 | pipeline-stage-view
66 | pipeline-utility-steps
67 | plain-credentials
68 | resource-disposer
69 | role-strategy
70 | scm-api
71 | script-security
72 | ssh-credentials
73 | ssh-slaves
74 | slave-setup
75 | ssh
76 | structs
77 | timestamper
78 | token-macro
79 | workflow-aggregator
80 | workflow-api
81 | workflow-basic-steps
82 | workflow-cps
83 | workflow-durable-task-step
84 | workflow-job
85 | workflow-multibranch
86 | workflow-scm-step
87 | workflow-step-api
88 | workflow-support
89 | ws-cleanup
90 |
--------------------------------------------------------------------------------
/resources/docker/scriptApproval.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | field jenkins.plugins.slack.SlackNotifier$DescriptorImpl baseUrl
6 | field jenkins.plugins.slack.SlackNotifier$DescriptorImpl teamDomain
7 | field jenkins.plugins.slack.SlackNotifier$DescriptorImpl tokenCredentialId
8 | method com.cloudbees.plugins.credentials.CredentialsStore addCredentials com.cloudbees.plugins.credentials.domains.Domain com.cloudbees.plugins.credentials.Credentials
9 | method com.cloudbees.plugins.credentials.SystemCredentialsProvider getStore
10 | method groovy.lang.GroovyObject invokeMethod java.lang.String java.lang.Object
11 | method hudson.model.Descriptor load
12 | method hudson.model.Saveable save
13 | method hudson.slaves.EnvironmentVariablesNodeProperty getEnvVars
14 | method hudson.util.PersistedList getAll java.lang.Class
15 | method java.lang.Class isInstance java.lang.Object
16 | method jenkins.model.Jenkins addNode hudson.model.Node
17 | method jenkins.model.Jenkins getDescriptor java.lang.String
18 | method jenkins.model.Jenkins getExtensionList java.lang.Class
19 | method jenkins.model.Jenkins getExtensionList java.lang.String
20 | method jenkins.model.Jenkins getGlobalNodeProperties
21 | method jenkins.model.Jenkins setAuthorizationStrategy hudson.security.AuthorizationStrategy
22 | method jenkins.model.Jenkins setSecurityRealm hudson.security.SecurityRealm
23 | method jenkins.model.JenkinsLocationConfiguration setUrl java.lang.String
24 | method jenkins.plugins.git.GitSCMSource setCredentialsId java.lang.String
25 | method jenkins.plugins.git.GitSCMSource setTraits java.util.List
26 | method jenkins.scm.api.SCMSource setTraits java.util.List
27 | method org.codefirst.SimpleThemeDecorator setCssUrl java.lang.String
28 | method org.jenkinsci.main.modules.sshd.SSHD getActualPort
29 | method org.jenkinsci.main.modules.sshd.SSHD setPort int
30 | method org.jenkinsci.plugins.github.config.GitHubPluginConfig setConfigs java.util.List
31 | method org.jenkinsci.plugins.github.config.GitHubServerConfig setManageHooks boolean
32 | method org.jenkinsci.plugins.github.config.GitHubServerConfig setName java.lang.String
33 | method org.jenkinsci.plugins.matrixauth.AuthorizationContainer add hudson.security.Permission java.lang.String
34 | method org.jenkinsci.plugins.workflow.libs.GlobalLibraries getLibraries
35 | method org.jenkinsci.plugins.workflow.libs.GlobalLibraries setLibraries java.util.List
36 | method org.jenkinsci.plugins.workflow.libs.LibraryConfiguration getName
37 | method org.jenkinsci.plugins.workflow.libs.LibraryConfiguration setAllowVersionOverride boolean
38 | method org.jenkinsci.plugins.workflow.libs.LibraryConfiguration setDefaultVersion java.lang.String
39 | method org.jenkinsci.plugins.workflow.libs.LibraryConfiguration setImplicit boolean
40 | method org.jenkinsci.plugins.workflow.libs.LibraryConfiguration setIncludeInChangesets boolean
41 | method org.codefirst.SimpleThemeDecorator setElements java.util.List
42 | method jenkins.CLI get
43 | method jenkins.CLI setEnabled boolean
44 | method jenkins.model.Jenkins getCrumbIssuer
45 | method jenkins.model.Jenkins setCrumbIssuer hudson.security.csrf.CrumbIssuer
46 | method jenkins.model.Jenkins getInjector
47 | method com.google.inject.Injector getInstance java.lang.Class
48 | method jenkins.security.s2m.AdminWhitelistRule setMasterKillSwitch boolean
49 | method io.jenkins.plugins.casc.ConfigurationAsCode configure
50 | method hudson.model.User addProperty hudson.model.UserProperty
51 | new hudson.security.csrf.DefaultCrumbIssuer boolean
52 | new com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey com.cloudbees.plugins.credentials.CredentialsScope java.lang.String java.lang.String com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey$PrivateKeySource java.lang.String java.lang.String
53 | new com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey$DirectEntryPrivateKeySource java.lang.String
54 | new com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey$FileOnMasterPrivateKeySource java.lang.String
55 | new com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl com.cloudbees.plugins.credentials.CredentialsScope java.lang.String java.lang.String java.lang.String java.lang.String
56 | new hudson.plugins.sshslaves.SSHLauncher java.lang.String int com.cloudbees.plugins.credentials.common.StandardUsernameCredentials java.lang.String java.lang.String hudson.tools.JDKInstaller java.lang.String java.lang.String java.lang.Integer java.lang.Integer java.lang.Integer
57 | new hudson.plugins.sshslaves.SSHLauncher java.lang.String int java.lang.String java.lang.String java.lang.String java.lang.String java.lang.String java.lang.Integer java.lang.Integer java.lang.Integer hudson.plugins.sshslaves.verifiers.SshHostKeyVerificationStrategy
58 | new hudson.plugins.sshslaves.verifiers.NonVerifyingKeyVerificationStrategy
59 | new hudson.security.GlobalMatrixAuthorizationStrategy
60 | new hudson.slaves.DumbSlave java.lang.String java.lang.String java.lang.String java.lang.String hudson.model.Node$Mode java.lang.String hudson.slaves.ComputerLauncher hudson.slaves.RetentionStrategy java.util.List
61 | new hudson.slaves.EnvironmentVariablesNodeProperty hudson.slaves.EnvironmentVariablesNodeProperty$Entry[]
62 | new hudson.slaves.RetentionStrategy$Always
63 | new hudson.slaves.RetentionStrategy$Demand long long
64 | new java.io.File java.lang.String
65 | new java.util.LinkedList
66 | new jenkins.plugins.git.GitSCMSource java.lang.String
67 | new jenkins.plugins.git.traits.BranchDiscoveryTrait
68 | new org.jenkinsci.plugins.GithubSecurityRealm java.lang.String java.lang.String java.lang.String java.lang.String java.lang.String
69 | new org.jenkinsci.plugins.github.config.GitHubServerConfig java.lang.String
70 | new org.jenkinsci.plugins.plaincredentials.impl.StringCredentialsImpl com.cloudbees.plugins.credentials.CredentialsScope java.lang.String java.lang.String hudson.util.Secret
71 | new org.jenkinsci.plugins.slave_setup.SetupSlaveLauncher hudson.slaves.ComputerLauncher java.lang.String java.lang.String
72 | new org.jenkinsci.plugins.workflow.libs.LibraryConfiguration java.lang.String org.jenkinsci.plugins.workflow.libs.LibraryRetriever
73 | new org.jenkinsci.plugins.workflow.libs.SCMSourceRetriever jenkins.scm.api.SCMSource
74 | new org.jenkinsci.plugins.simpletheme.CssUrlThemeElement java.lang.String
75 | new org.jenkinsci.main.modules.cli.auth.ssh.UserPropertyImpl java.lang.String
76 | staticField com.cloudbees.plugins.credentials.CredentialsScope GLOBAL
77 | staticField hudson.model.Node$Mode EXCLUSIVE
78 | staticField jenkins.model.Jenkins ADMINISTER
79 | staticField org.jenkinsci.plugins.GithubSecurityRealm DEFAULT_API_URI
80 | staticField org.jenkinsci.plugins.GithubSecurityRealm DEFAULT_WEB_URI
81 | staticMethod com.cloudbees.plugins.credentials.domains.Domain global
82 | staticMethod hudson.model.PageDecorator all
83 | staticMethod hudson.model.User get java.lang.String boolean java.util.Map
84 | staticMethod hudson.plugins.sshslaves.SSHLauncher lookupSystemCredentials java.lang.String
85 | staticMethod hudson.util.Secret fromString java.lang.String
86 | staticMethod java.lang.System getenv
87 | staticMethod java.lang.System setProperty java.lang.String java.lang.String
88 | staticMethod jenkins.model.Jenkins getInstance
89 | staticMethod org.apache.commons.io.FileUtils copyDirectory java.io.File java.io.File
90 | staticMethod org.codehaus.groovy.runtime.DefaultGroovyMethods deleteDir java.io.File
91 | staticMethod org.codehaus.groovy.runtime.DefaultGroovyMethods getText java.io.File
92 | staticMethod org.codehaus.groovy.runtime.DefaultGroovyMethods leftShift java.io.File java.lang.Object
93 | staticMethod hudson.model.User get java.lang.String
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
--------------------------------------------------------------------------------
/resources/helm/Chart.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: "v1"
3 | name: "JenkinsAsCode"
4 | version: "0.0.1"
5 |
--------------------------------------------------------------------------------
/resources/helm/templates/ingress.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: extensions/v1beta1
2 | kind: Ingress
3 | metadata:
4 | name: jenkins
5 | namespace: default
6 | spec:
7 | rules:
8 | - http:
9 | paths:
10 | - backend:
11 | serviceName: jenkins
12 | servicePort: 80
13 | path: /
14 |
15 |
--------------------------------------------------------------------------------
/resources/helm/templates/secrets.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: v1
3 | kind: Secret
4 | metadata:
5 | name: jenkins-ssh-keys
6 | type: Opaque
7 | data:
8 | deploy-key-shared-library: {{ b64enc (.Files.Get "secret-files/deploy-key-shared-library") }}
9 | ssh-agent-access-key: {{ b64enc (.Files.Get "secret-files/ssh-agent-access-key") }}
10 | ssh-agent-access-key.pub: {{ b64enc (.Files.Get "secret-files/ssh-agent-access-key.pub") }}
11 |
12 | ---
13 | apiVersion: v1
14 | kind: Secret
15 | metadata:
16 | name: jenkins-basic-auth-credentials
17 | type: Opaque
18 | data:
19 | docker-registry-user: {{ b64enc (.Files.Get "secret-files/docker-registry-user") }}
20 | docker-registry-password: {{ b64enc (.Files.Get "secret-files/docker-registry-password") }}
21 | github-ci-user: {{ b64enc (.Files.Get "secret-files/github-ci-user") }}
22 | github-ci-password: {{ b64enc (.Files.Get "secret-files/github-ci-password") }}
23 | default-setup-user: {{ b64enc (.Files.Get "secret-files/default-setup-user") }}
24 | default-setup-password: {{ b64enc (.Files.Get "secret-files/default-setup-password") }}
25 |
26 | ---
27 | apiVersion: v1
28 | kind: Secret
29 | metadata:
30 | name: jenkins-tokens
31 | type: Opaque
32 | data:
33 | slack-token: {{ b64enc (.Files.Get "secret-files/slack-token") }}
34 | github-ci-token: {{ b64enc (.Files.Get "secret-files/github-ci-token") }}
35 | github-oauth-client-id: {{ b64enc (.Files.Get "secret-files/github-oauth-client-id") }}
36 | github-oauth-client-secret: {{ b64enc (.Files.Get "secret-files/github-oauth-client-secret") }}
37 |
38 | ---
39 | apiVersion: v1
40 | kind: Secret
41 | metadata:
42 | name: terraform-config
43 | type: Opaque
44 | data:
45 | {{- (.Files.Glob "secret-files/terraform-config/*").AsSecrets | nindent 2 }}
46 |
--------------------------------------------------------------------------------
/resources/helm/templates/services.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | kind: Service
3 | apiVersion: v1
4 | metadata:
5 | name: jenkins
6 | spec:
7 | selector:
8 | app: jenkins
9 | ports:
10 | - protocol: TCP
11 | port: 80
12 | targetPort: 8080
13 |
--------------------------------------------------------------------------------
/resources/helm/templates/statefulsets.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: apps/v1
3 | kind: StatefulSet
4 | metadata:
5 | name: jenkins
6 | spec:
7 | selector:
8 | matchLabels:
9 | app: jenkins
10 | serviceName: "jenkins"
11 | replicas: 1
12 | template:
13 | metadata:
14 | labels:
15 | app: jenkins
16 | spec:
17 | terminationGracePeriodSeconds: 10
18 | containers:
19 | - name: jenkins
20 | image: quay.io/devtail/jenkins-as-code:master
21 | imagePullPolicy: Always
22 | env:
23 | - name: DEPLOY_TS
24 | value: "{{ date "20060102150405" .Release.Time }}"
25 | - name: GITHUB_OAUTH_CLIENT_ID
26 | valueFrom:
27 | secretKeyRef:
28 | name: jenkins-tokens
29 | key: github-oauth-client-id
30 | - name: GITHUB_OAUTH_CLIENT_SECRET
31 | valueFrom:
32 | secretKeyRef:
33 | name: jenkins-tokens
34 | key: github-oauth-client-secret
35 | ports:
36 | - containerPort: 8080
37 | name: http
38 | volumeMounts:
39 | - name: jenkins-ssh-keys
40 | mountPath: /var/jenkins_home/jenkins-ssh-keys
41 | - name: jenkins-basic-auth-credentials
42 | mountPath: /var/jenkins_home/jenkins-basic-auth-credentials
43 | - name: jenkins-tokens
44 | mountPath: /var/jenkins_home/jenkins-tokens
45 | - name: terraform-config
46 | mountPath: /var/jenkins_home/agent-bootstrapping-terraform-config
47 | volumes:
48 | - name: jenkins-ssh-keys
49 | secret:
50 | secretName: jenkins-ssh-keys
51 | - name: jenkins-basic-auth-credentials
52 | secret:
53 | secretName: jenkins-basic-auth-credentials
54 | - name: jenkins-tokens
55 | secret:
56 | secretName: jenkins-tokens
57 | - name: terraform-config
58 | secret:
59 | secretName: terraform-config
60 |
--------------------------------------------------------------------------------
/resources/helm/values.yaml:
--------------------------------------------------------------------------------
1 | ---
2 |
--------------------------------------------------------------------------------
/resources/init/ConfigurationAndSeedingPipeline.groovy:
--------------------------------------------------------------------------------
1 | node('master') {
2 | stage('Checkout') {
3 | // Clean workspace and checkout shared library repository on the jenkins master
4 | cleanWs()
5 | checkout scm
6 | }
7 |
8 | stage('Configuration') {
9 | // set config file in master
10 | sh('cp /var/jenkins_home/workspace/Admin/Configure/resources/config/configuration-as-code-plugin/jenkins.yaml /var/jenkins_home/jenkins.yaml')
11 |
12 | // run configuration from config file
13 | load('resources/config/groovy/triggerConfigurationAsCodePlugin.groovy')
14 |
15 | // set public key for bootstrapping user
16 | load('resources/config/groovy/userPublicKeys.groovy')
17 |
18 | // set the timezone
19 | load('resources/config/groovy/timezone.groovy')
20 | }
21 |
22 | stage('Deploy Agent Networks') {
23 | ansiColor('xterm') {
24 | sh('ln -sfn /var/jenkins_home/agent-bootstrapping-terraform-config/aws-agent-network.backend.config resources/terraform/aws/agent-network/')
25 | sh('ln -sfn /var/jenkins_home/agent-bootstrapping-terraform-config/aws-agent-network.tfvars resources/terraform/aws/agent-network/terraform.tfvars')
26 | sh('cd resources/terraform/ && make deploy-agent-network')
27 | }
28 | }
29 |
30 | stage('Job Seeding') {
31 | jobDsl(targets: 'resources/jobDSL/*.groovy', sandbox: false)
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/resources/jobDSL/agentManagement.groovy:
--------------------------------------------------------------------------------
1 | pipelineJob("Admin/AWSAgentBootstrap") {
2 |
3 | parameters {
4 | stringParam('agentID', '', '')
5 | }
6 |
7 | logRotator {
8 | numToKeep(50)
9 | }
10 |
11 | throttleConcurrentBuilds {
12 | maxTotal(1)
13 | }
14 |
15 | definition {
16 | cpsScm {
17 | scm {
18 | git {
19 | remote {
20 | github("devtail/jenkins-as-code", "ssh")
21 | credentials("deploy-key-shared-library")
22 | }
23 |
24 | branch('master')
25 | }
26 | }
27 |
28 | scriptPath('resources/agentManagement/AWSAgentBootstrap.groovy')
29 | }
30 | }
31 | }
32 |
33 | pipelineJob("Admin/AWSAgentDestroy") {
34 |
35 | parameters {
36 | stringParam('agentID', '', '')
37 | }
38 |
39 | logRotator {
40 | numToKeep(50)
41 | }
42 |
43 | throttleConcurrentBuilds {
44 | maxTotal(1)
45 | }
46 |
47 | definition {
48 | cpsScm {
49 | scm {
50 | git {
51 | remote {
52 | github("devtail/jenkins-as-code", "ssh")
53 | credentials("deploy-key-shared-library")
54 | }
55 |
56 | branch('master')
57 | }
58 | }
59 |
60 | scriptPath('resources/agentManagement/AWSAgentDestroy.groovy')
61 | }
62 | }
63 | }
64 |
65 |
--------------------------------------------------------------------------------
/resources/jobDSL/example.groovy:
--------------------------------------------------------------------------------
1 | projects = [
2 | [name: "ServiceA"],
3 | [name: "ServiceB"],
4 | [name: "ServiceC"]
5 | ]
6 |
7 | for(project in projects) {
8 | folder("${project.name}")
9 |
10 | pipelineJob("${project.name}/build") {
11 |
12 | logRotator {
13 | numToKeep(50)
14 | }
15 |
16 | definition {
17 | cps {
18 | sandbox(true)
19 | script("""@Library('devtail-ci-lib@master') _
20 | printDockerVersion()
21 | """)
22 | }
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/resources/terraform/Makefile:
--------------------------------------------------------------------------------
1 | export AGENT_ID
2 |
3 | deploy-agent-network:
4 | $(MAKE) -C aws/agent-network deploy-agent-network
5 |
6 | bootstrap-agent-vm:
7 | $(MAKE) -C aws/agent-vms bootstrap-agent-vm
8 |
9 | destroy-agent-vm:
10 | $(MAKE) -C aws/agent-vms destroy-agent-vm
11 |
--------------------------------------------------------------------------------
/resources/terraform/README.md:
--------------------------------------------------------------------------------
1 | # Terraform for Agent Infrastructure
2 |
3 | ## Place variables/secrets in config/
4 |
5 | Secrets are not commited to Github ;-)
6 |
7 | Create `config/` dir with secrets/variables for terraform automation.
8 | Directory structure should in the end look like that:
9 |
10 | ```
11 | terraform/
12 | ├── aws
13 | │ ├── agent-network
14 | │ │ ├── all.tf
15 | │ │ ├── aws-agent-network.backend.config -> ../../config/aws-agent-network.backend.config
16 | │ │ ├── io.tf
17 | │ │ └── terraform.tfvars -> ../../config/aws-agent-network.tfvars
18 | │ └── agent-vms
19 | │ ├── all.tf
20 | │ ├── aws-agent-vms.backend.config -> ../../config/aws-agent-vms.backend.config
21 | │ ├── io.tf
22 | │ └── terraform.tfvars -> ../../config/aws-agent-vms.tfvars
23 | ├── config
24 | │ ├── aws-agent-network.backend.config
25 | │ ├── aws-agent-network.tfvars
26 | │ ├── aws-agent-vms.backend.config
27 | │ └── aws-agent-vms.tfvars
28 | ├── Makefile
29 | └── README.md
30 | ```
31 |
32 | ## Agent Network Infrastructure
33 |
34 | To initialize the state:
35 | ```
36 | cd aws/agent-network
37 | terraform init -backend-config aws-agent-network.backend.config
38 | ```
39 |
40 | To bootstrap the network:
41 | ```
42 | cd aws/agent-network
43 | terraform apply
44 | ```
45 |
46 | ## Agent VMs
47 |
48 | Bootstrap agent-1:
49 | ```
50 | cd aws/agent-vms
51 | terraform workspace select 0
52 | terraform apply
53 | ```
54 |
55 | Bootstrap agent-2:
56 | ```
57 | cd aws/agent-vms
58 | terraform workspace select 1
59 | terraform apply
60 | ```
61 |
--------------------------------------------------------------------------------
/resources/terraform/aws/agent-network/Makefile:
--------------------------------------------------------------------------------
1 | deploy-agent-network:
2 | terraform init -backend-config aws-agent-network.backend.config
3 | terraform apply -auto-approve
4 |
--------------------------------------------------------------------------------
/resources/terraform/aws/agent-network/all.tf:
--------------------------------------------------------------------------------
1 | provider "aws" {
2 | access_key = "${var.aws_access_key}"
3 | secret_key = "${var.aws_secret_key}"
4 | region = "${var.aws_region}"
5 | }
6 |
7 | terraform {
8 | backend "s3" {}
9 | }
10 |
11 | resource "aws_vpc" "agents" {
12 | cidr_block = "${var.agents_vpc_cidr}"
13 | }
14 |
15 | resource "aws_internet_gateway" "gw" {
16 | vpc_id = "${aws_vpc.agents.id}"
17 | }
18 |
19 | resource "aws_route_table" "agent-routing" {
20 | vpc_id = "${aws_vpc.agents.id}"
21 | }
22 |
23 | resource "aws_route" "internet" {
24 | route_table_id = "${aws_route_table.agent-routing.id}"
25 | destination_cidr_block = "0.0.0.0/0"
26 | gateway_id = "${aws_internet_gateway.gw.id}"
27 | }
28 |
29 | resource "aws_subnet" "agents" {
30 | vpc_id = "${aws_vpc.agents.id}"
31 | cidr_block = "${var.agents_subnet_cidr}"
32 | }
33 |
34 | resource "aws_main_route_table_association" "agent-routing" {
35 | vpc_id = "${aws_vpc.agents.id}"
36 | route_table_id = "${aws_route_table.agent-routing.id}"
37 | }
38 |
39 | resource "aws_security_group" "agents" {
40 | name = "agent_rules"
41 | description = "Agent Rules"
42 | vpc_id = "${aws_vpc.agents.id}"
43 | }
44 |
45 | resource "aws_security_group_rule" "allow-ssh" {
46 | type = "ingress"
47 | from_port = 22
48 | to_port = 22
49 | protocol = "tcp"
50 | cidr_blocks = ["0.0.0.0/0"]
51 |
52 | security_group_id = "${aws_security_group.agents.id}"
53 | }
54 |
55 | resource "aws_security_group_rule" "allow_all" {
56 | type = "egress"
57 | to_port = 0
58 | protocol = "-1"
59 | from_port = 0
60 | cidr_blocks = ["0.0.0.0/0"]
61 |
62 | security_group_id = "${aws_security_group.agents.id}"
63 | }
64 |
65 | resource "aws_key_pair" "agent-access" {
66 | key_name = "devtail-jenkins-agent-access"
67 | public_key = "${var.agent_access_public_key}"
68 | }
69 |
70 | data "aws_eip" "public-agent-ip" {
71 | count = "${length(keys(var.agent_config_map)) / var.num_agents}"
72 |
73 | filter {
74 | name = "tag:Name"
75 | values = ["${var.agent_config_map["${count.index}_name"]}"]
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/resources/terraform/aws/agent-network/aws-agent-network.backend.config:
--------------------------------------------------------------------------------
1 | ../../config/aws-agent-network.backend.config
--------------------------------------------------------------------------------
/resources/terraform/aws/agent-network/io.tf:
--------------------------------------------------------------------------------
1 | variable "aws_access_key" {}
2 | variable "aws_secret_key" {}
3 | variable "aws_region" {}
4 |
5 | variable "agents_vpc_cidr" {}
6 | variable "agents_subnet_cidr" {}
7 |
8 | variable "agent_access_public_key" {}
9 |
10 | variable "agent_config_map" { type = "map" }
11 | variable "num_agents" {}
12 |
13 | ### Output
14 | output "agents_subnet_id" {
15 | value = "${aws_subnet.agents.id}"
16 | }
17 |
18 | output "agent_access_key_name" {
19 | value = "${aws_key_pair.agent-access.key_name}"
20 | }
21 |
22 | output "agent_public_ip_ids" {
23 | value = "${data.aws_eip.public-agent-ip.*.id}"
24 | }
25 |
26 | output "agent_config_map" {
27 | value = "${var.agent_config_map}"
28 | }
29 |
30 | output "num_agents" {
31 | value = "${var.num_agents}"
32 | }
33 |
34 | output "agent_security_group_id" {
35 | value = "${aws_security_group.agents.id}"
36 | }
37 |
--------------------------------------------------------------------------------
/resources/terraform/aws/agent-network/terraform.tfvars:
--------------------------------------------------------------------------------
1 | ../../config/aws-agent-network.tfvars
--------------------------------------------------------------------------------
/resources/terraform/aws/agent-vms/Makefile:
--------------------------------------------------------------------------------
1 | get-workspace:
2 | terraform init -backend-config aws-agent-vms.backend.config
3 | terraform workspace new $(AGENT_ID) || true
4 | terraform workspace select $(AGENT_ID)
5 |
6 | bootstrap-agent-vm: get-workspace
7 | terraform apply -auto-approve
8 |
9 | destroy-agent-vm: get-workspace
10 | terraform destroy -auto-approve
11 |
12 |
--------------------------------------------------------------------------------
/resources/terraform/aws/agent-vms/all.tf:
--------------------------------------------------------------------------------
1 | provider "aws" {
2 | access_key = "${var.aws_access_key}"
3 | secret_key = "${var.aws_secret_key}"
4 | region = "${var.aws_region}"
5 | }
6 |
7 | terraform {
8 | backend "s3" {}
9 | }
10 |
11 | data "terraform_remote_state" "agent-network" {
12 | backend = "s3"
13 | config {
14 | bucket = "${var.remote_state_agent_network_s3_bucket}"
15 | key = "${var.remote_state_agent_network_s3_key}"
16 | region = "${var.remote_state_agent_network_region}"
17 | access_key = "${var.remote_state_agent_network_access_key}"
18 | secret_key = "${var.remote_state_agent_network_secret_key}"
19 | }
20 | }
21 |
22 | locals {
23 | agent_config_map = "${data.terraform_remote_state.agent-network.agent_config_map}"
24 | num_agents = "${data.terraform_remote_state.agent-network.num_agents}"
25 | }
26 |
27 | data "aws_ami" "ubuntu18-04" {
28 | most_recent = true
29 |
30 | filter {
31 | name = "name"
32 | values = ["ubuntu/images/hvm-ssd/ubuntu-bionic-18.04-amd64-server-*"]
33 | }
34 |
35 | filter {
36 | name = "virtualization-type"
37 | values = ["hvm"]
38 | }
39 |
40 | owners = ["099720109477"] # Canonical
41 | }
42 |
43 | resource "aws_instance" "agent" {
44 | ami = "${data.aws_ami.ubuntu18-04.id}"
45 | instance_type = "${local.agent_config_map["${terraform.workspace}_size"]}"
46 | subnet_id = "${data.terraform_remote_state.agent-network.agents_subnet_id}"
47 | key_name = "${data.terraform_remote_state.agent-network.agent_access_key_name}"
48 | user_data = "${file("user_data/docker.sh")}"
49 | vpc_security_group_ids = [
50 | "${data.terraform_remote_state.agent-network.agent_security_group_id}"
51 | ]
52 |
53 | tags = {
54 | Name = "${local.agent_config_map["${terraform.workspace}_name"]}"
55 | }
56 | }
57 |
58 | resource "aws_eip_association" "agent" {
59 | instance_id = "${aws_instance.agent.id}"
60 | allocation_id = "${data.terraform_remote_state.agent-network.agent_public_ip_ids[terraform.workspace]}"
61 | }
62 |
--------------------------------------------------------------------------------
/resources/terraform/aws/agent-vms/aws-agent-vms.backend.config:
--------------------------------------------------------------------------------
1 | ../../config/aws-agent-vms.backend.config
--------------------------------------------------------------------------------
/resources/terraform/aws/agent-vms/io.tf:
--------------------------------------------------------------------------------
1 | variable "aws_access_key" {}
2 | variable "aws_secret_key" {}
3 | variable "aws_region" {}
4 |
5 | variable "remote_state_agent_network_s3_bucket" {}
6 | variable "remote_state_agent_network_s3_key" {}
7 | variable "remote_state_agent_network_region" {}
8 | variable "remote_state_agent_network_access_key" {}
9 | variable "remote_state_agent_network_secret_key" {}
10 |
--------------------------------------------------------------------------------
/resources/terraform/aws/agent-vms/terraform.tfvars:
--------------------------------------------------------------------------------
1 | ../../config/aws-agent-vms.tfvars
--------------------------------------------------------------------------------
/resources/terraform/aws/agent-vms/user_data/docker.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | ## agent connectivity
4 | apt-get update -y
5 | apt-get install -y openjdk-8-jdk
6 |
7 | ## docker
8 | apt-get install -y \
9 | apt-transport-https \
10 | ca-certificates \
11 | curl \
12 | gnupg-agent \
13 | software-properties-common
14 |
15 | curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
16 |
17 | add-apt-repository \
18 | "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
19 | $(lsb_release -cs) \
20 | stable"
21 |
22 | apt-get update -y
23 | apt-get install -y docker-ce
24 |
25 | groupadd docker
26 | usermod -aG docker ubuntu
27 |
--------------------------------------------------------------------------------
/resources/terraform/config:
--------------------------------------------------------------------------------
1 | ../helm/secret-files/terraform-config
--------------------------------------------------------------------------------
/vars/AWSAgentBootstrap.groovy:
--------------------------------------------------------------------------------
1 | def call(Map config) {
2 | node('master') {
3 | stage('Checkout') {
4 | cleanWs()
5 | checkout scm
6 | }
7 |
8 | stage('Terraform') {
9 | ansiColor('xterm') {
10 | sh('ln -sfn /var/jenkins_home/agent-bootstrapping-terraform-config/aws-agent-vms.backend.config resources/terraform/aws/agent-vms/')
11 | sh('ln -sfn /var/jenkins_home/agent-bootstrapping-terraform-config/aws-agent-vms.tfvars resources/terraform/aws/agent-vms/terraform.tfvars')
12 | sh("cd resources/terraform/ && make bootstrap-agent-vm AGENT_ID=${config['agentID']}")
13 | }
14 |
15 | // Wait for cloud-init to bootstrap
16 | sh("sleep 120")
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/vars/AWSAgentDestroy.groovy:
--------------------------------------------------------------------------------
1 | def call(Map config) {
2 | node('master') {
3 | stage('Checkout') {
4 | cleanWs()
5 | checkout scm
6 | }
7 |
8 | stage('Terraform') {
9 | ansiColor('xterm') {
10 | sh('ln -sfn /var/jenkins_home/agent-bootstrapping-terraform-config/aws-agent-vms.backend.config resources/terraform/aws/agent-vms/')
11 | sh('ln -sfn /var/jenkins_home/agent-bootstrapping-terraform-config/aws-agent-vms.tfvars resources/terraform/aws/agent-vms/terraform.tfvars')
12 | sh("cd resources/terraform/ && make destroy-agent-vm AGENT_ID=${config['agentID']}")
13 | }
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/vars/printDockerVersion.groovy:
--------------------------------------------------------------------------------
1 | def call(Map config) {
2 | node('master') {
3 | stage('Hello') {
4 | echo('Hello World')
5 | }
6 | }
7 |
8 | node('docker') {
9 | stage('Version') {
10 | sh('sudo docker version')
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------