├── .gitignore ├── CONTRIBUTING ├── LICENSE ├── README.md ├── bundle ├── README.md ├── build-bundle.sh ├── m2_settings.xml └── pom.xml ├── checkstyle.xml ├── checkstyleJavaHeader └── image ├── base ├── Dockerfile.template ├── devshell │ ├── authorized_keys.sh │ ├── bashrc.google │ └── startup.sh ├── gcloud_docker_auth.sh ├── gitconfig ├── onrun.sh ├── sshd_config └── third_party │ └── jpetazzo │ └── dind │ ├── LICENSE │ ├── README.third_party │ └── wrapdocker ├── build.sh ├── install.sh ├── master_images ├── Dockerfile.template ├── jenkins │ ├── README.md │ ├── config.xml │ ├── healthChecks.xml │ └── jenkins-upgrade-version ├── nginx.conf ├── startup-scripts │ ├── jenkins.sh │ └── setup-slaves.sh.template └── supervisord.conf └── slave_images ├── jenkins-slave-go └── Dockerfile.template └── jenkins-slave-java └── Dockerfile.template /.gitignore: -------------------------------------------------------------------------------- 1 | .classpath 2 | .project 3 | bundle/target/ 4 | image/master_images/google-jenkins.war 5 | image/tmp_build_dir/ 6 | 7 | -------------------------------------------------------------------------------- /CONTRIBUTING: -------------------------------------------------------------------------------- 1 | # How to contribute # 2 | 3 | We'd love to accept your patches and contributions to this project. There are 4 | a just a few small guidelines you need to follow. 5 | 6 | 7 | ## Contributor License Agreement ## 8 | 9 | Contributions to any Google project must be accompanied by a Contributor 10 | License Agreement. This is not a copyright **assignment**, it simply gives 11 | Google permission to use and redistribute your contributions as part of the 12 | project. 13 | 14 | * If you are an individual writing original source code and you're sure you 15 | own the intellectual property, then you'll need to sign an [individual 16 | CLA][]. 17 | 18 | * If you work for a company that wants to allow you to contribute your work, 19 | then you'll need to sign a [corporate CLA][]. 20 | 21 | You generally only need to submit a CLA once, so if you've already submitted 22 | one (even if it was for a different project), you probably don't need to do it 23 | again. 24 | 25 | [individual CLA]: https://developers.google.com/open-source/cla/individual 26 | [corporate CLA]: https://developers.google.com/open-source/cla/corporate 27 | 28 | 29 | ## Submitting a patch ## 30 | 31 | 1. It's generally best to start by opening a new issue describing the bug or 32 | feature you're intending to fix. Even if you think it's relatively minor, 33 | it's helpful to know what people are working on. Mention in the initial 34 | issue that you are planning to work on that bug or feature so that it can 35 | be assigned to you. 36 | 37 | 1. Follow the normal process of [forking][] the project, and setup a new 38 | branch to work in. It's important that each group of changes be done in 39 | separate branches in order to ensure that a pull request only includes the 40 | commits related to that bug or feature. 41 | 42 | 1. Any significant changes should almost always be accompanied by tests. The 43 | project already has good test coverage, so look at some of the existing 44 | tests if you're unsure how to go about it. 45 | 46 | 1. All contributions must be licensed Apache 2.0 and all files must have 47 | a copy of the boilerplate licence comment (can be copied from an existing 48 | file. Files should be formatted according to Google's [java style guide][]. 49 | 50 | 1. Do your best to have [well-formed commit messages][] for each change. 51 | This provides consistency throughout the project, and ensures that commit 52 | messages are able to be formatted properly by various git tools. 53 | 54 | 1. Finally, push the commits to your fork and submit a [pull request][]. 55 | 56 | [forking]: https://help.github.com/articles/fork-a-repo 57 | [java style guide]: http://google-styleguide.googlecode.com/svn/trunk/javaguide.html 58 | [well-formed commit messages]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html 59 | [pull request]: https://help.github.com/articles/creating-a-pull-request -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This package provides a Docker image running Jenkins behind NGINX. It is designed to be deployed to Google Managed VMs using the provided app.yaml configuration file, but could also be deployed to any other platform that supports Docker images. 2 | 3 | In its setup, Jenkins is started inside a container, listening to a local port. NGINX is running in front of Jenkins to allow flexibility in creating our health check end point and passing authentication headers. 4 | 5 | The reverse-proxy-auth plugin is used by Jenkins to trust the authentication headers passed by NGINX, which receives them from the underlying platform (expected: Google App Engine). 6 | 7 | For convenience, $JENKINS_HOME is seeded with content of the /jenkins directory. Users can add plugins and initial configurations as needed. 8 | 9 | This image starts a Jenkins instance with several bundled plugins. In particular, the Google Cloud Backup plugin provides automatic backup and restore functionality. The default configuration when launched to Google Managed VMs will create backup files using Google Cloud Storage. This allows the Jenkins master to retain state despite intentional or accidental restarts of the VM. 10 | 11 | This image is packaged with a usage-reporting plugin. By default, the plugin is disabled and does not send any usage reports. Users who choose to opt in to usage reporting may do so by passing the --report_usage flag to the install script. 12 | 13 | You must have an existing Google Cloud Project to deploy to that has billing 14 | setup, and you must have these APIs enabled in your project: 15 | - Google Compute Engine 16 | - Google Cloud Storage 17 | 18 | If you want to deploy from the source code, run: 19 | 20 | (in the /bundle directory) 21 | ./build-bundle.sh 22 | (in the /image directory) 23 | ./install.sh --project --build_from_src 24 | 25 | If you want to deploy using the pre-built Docker image instead of from the source 26 | code, run: 27 | 28 | (in the /image directory) 29 | ./install.sh --project 30 | 31 | To see more command line options, run: 32 | 33 | (in the /image directory) 34 | ./insall.sh --help 35 | 36 | If you want to build and push the testing version of Docker image, run: 37 | 38 | (in the /bundle directory) 39 | ./build.sh 40 | 41 | (in the image directory) 42 | ./build.sh testing --push_image 43 | 44 | However, you must have write permission to the GCR repo where these images are stored in order to do so. 45 | -------------------------------------------------------------------------------- /bundle/README.md: -------------------------------------------------------------------------------- 1 | This package produces a Jenkins WAR file bundled with several useful plugins. The resulting WAR file is used by the Dockerfile found in the /image directory. 2 | -------------------------------------------------------------------------------- /bundle/build-bundle.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2015 Google Inc. All rights reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | mvn -s m2_settings.xml clean verify 18 | cp target/google-jenkins-war-0.1-SNAPSHOT.war ../image/master_images/google-jenkins.war 19 | -------------------------------------------------------------------------------- /bundle/m2_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | org.jenkins-ci.tools 5 | 6 | 7 | 8 | 9 | 10 | jenkins 11 | 12 | true 13 | 14 | 15 | 16 | repo.jenkins-ci.org 17 | http://repo.jenkins-ci.org/public/ 18 | 19 | 20 | 21 | 22 | repo.jenkins-ci.org 23 | http://repo.jenkins-ci.org/public/ 24 | 25 | 26 | 27 | 28 | 29 | 30 | repo.jenkins-ci.org 31 | http://repo.jenkins-ci.org/public/ 32 | m.g.o-public 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /bundle/pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 4.0.0 6 | com.google.jenkins 7 | google-jenkins-war 8 | 9 | 0.1-SNAPSHOT 10 | war 11 | 12 | Google Jenkins WAR 13 | 14 | 15 | org.jenkins-ci.main 16 | jenkins-war 17 | 1.645 18 | war 19 | 20 | 21 | 22 | 23 | 24 | 25 | org.apache.maven.plugins 26 | maven-dependency-plugin 27 | 28 | 29 | generate-sources 30 | 31 | copy 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | com.sonyericsson.hudson.plugins.rebuild 41 | rebuild 42 | 1.25 43 | hpi 44 | 45 | 46 | 47 | org.jvnet.hudson.plugins 48 | analysis-core 49 | 1.71 50 | hpi 51 | 52 | 53 | org.jvnet.hudson.plugins 54 | checkstyle 55 | 3.44 56 | hpi 57 | 58 | 59 | org.jvnet.hudson.plugins 60 | findbugs 61 | 4.63 62 | hpi 63 | 64 | 65 | 66 | org.jenkins-ci.plugins 67 | ant 68 | 1.2 69 | hpi 70 | 71 | 72 | org.jenkins-ci.plugins 73 | branch-api 74 | 1.0 75 | hpi 76 | 77 | 78 | org.jenkins-ci.plugins 79 | build-pipeline-plugin 80 | 1.4.9 81 | hpi 82 | 83 | 84 | org.jenkins-ci.plugins 85 | cloudbees-folder 86 | 5.1 87 | hpi 88 | 89 | 90 | org.jenkins-ci.plugins 91 | cobertura 92 | 1.9.7 93 | hpi 94 | 95 | 96 | org.jenkins-ci.plugins 97 | conditional-buildstep 98 | 1.3.3 99 | hpi 100 | 101 | 102 | org.jenkins-ci.plugins 103 | credentials 104 | 1.24 105 | hpi 106 | 107 | 108 | org.jenkins-ci.plugins 109 | dashboard-view 110 | 2.9.7 111 | hpi 112 | 113 | 114 | org.jenkins-ci.plugins 115 | git 116 | 2.4.1 117 | hpi 118 | 119 | 120 | org.jenkins-ci.plugins 121 | git-client 122 | 1.19.1 123 | hpi 124 | 125 | ${project.build.directory}/plugins 126 | 127 | 128 | 129 | org.jenkins-ci.plugins 130 | htmlpublisher 131 | 1.10 132 | hpi 133 | 134 | 135 | org.jenkins-ci.plugins 136 | javadoc 137 | 1.3 138 | hpi 139 | 140 | 141 | org.jenkins-ci.plugins 142 | jquery 143 | 1.11.2-0 144 | hpi 145 | 146 | 147 | org.jenkins-ci.plugins 148 | ldap 149 | 1.11 150 | hpi 151 | 152 | 153 | org.jenkins-ci.plugins 154 | mailer 155 | 1.16 156 | hpi 157 | 158 | 159 | org.jenkins-ci.plugins 160 | mapdb-api 161 | 1.0.6.0 162 | hpi 163 | 164 | 165 | org.jenkins-ci.plugins 166 | matrix-auth 167 | 1.2 168 | hpi 169 | 170 | 171 | org.jenkins-ci.plugins 172 | matrix-project 173 | 1.6 174 | hpi 175 | 176 | 177 | 178 | org.jenkins-ci.main 179 | maven-plugin 180 | 2.12.1 181 | hpi 182 | 183 | 184 | org.jenkins-ci.plugins 185 | mercurial 186 | 1.54 187 | hpi 188 | 189 | 190 | org.jenkins-ci.plugins 191 | multiple-scms 192 | 0.5 193 | hpi 194 | 195 | 196 | org.jenkins-ci.plugins 197 | oauth-credentials 198 | 0.3 199 | hpi 200 | 201 | 202 | org.jenkins-ci.plugins 203 | parameterized-trigger 204 | 2.30 205 | hpi 206 | 207 | 208 | org.jenkins-ci.plugins 209 | promoted-builds 210 | 2.24.1 211 | hpi 212 | 213 | 214 | org.jenkins-ci.plugins 215 | reverse-proxy-auth-plugin 216 | 1.4.0 217 | hpi 218 | 219 | 220 | org.jenkins-ci.plugins 221 | run-condition 222 | 1.0 223 | hpi 224 | 225 | 226 | org.jenkins-ci.plugins 227 | scm-api 228 | 1.0 229 | hpi 230 | 231 | 232 | org.jenkins-ci.plugins 233 | ssh-credentials 234 | 1.11 235 | hpi 236 | 237 | 238 | org.jenkins-ci.plugins 239 | subversion 240 | 2.5.7 241 | hpi 242 | 243 | 244 | org.jenkins-ci.plugins 245 | token-macro 246 | 1.12 247 | hpi 248 | 249 | 250 | org.jenkins-ci.plugins 251 | throttle-concurrents 252 | 1.8.4 253 | hpi 254 | 255 | 256 | org.jenkins-ci.plugins.workflow 257 | workflow-step-api 258 | 1.13 259 | hpi 260 | 261 | 262 | org.jenkins-ci.plugins 263 | yaml-project 264 | 0.1-beta-7 265 | hpi 266 | 267 | 268 | 269 | org.jenkins-ci.plugins 270 | google-analytics-usage-reporter 271 | 0.4 272 | hpi 273 | 274 | 275 | org.jenkins-ci.plugins 276 | google-cloud-backup 277 | 0.6 278 | hpi 279 | 280 | 281 | org.jenkins-ci.plugins 282 | google-cloud-health-check 283 | 0.3 284 | hpi 285 | 286 | 287 | org.jenkins-ci.plugins 288 | google-git-notes-publisher 289 | 0.3 290 | hpi 291 | 292 | 293 | org.jenkins-ci.plugins 294 | google-metadata-plugin 295 | 0.2 296 | hpi 297 | 298 | 299 | org.jenkins-ci.plugins 300 | google-oauth-plugin 301 | 0.4 302 | hpi 303 | 304 | 305 | org.jenkins-ci.plugins 306 | google-source-plugin 307 | 0.1 308 | hpi 309 | 310 | 311 | org.jenkins-ci.plugins 312 | google-storage-plugin 313 | 0.9 314 | hpi 315 | 316 | 317 | ${project.build.directory}/plugins 318 | true 319 | 320 | 321 | 322 | 323 | org.apache.maven.plugins 324 | maven-war-plugin 325 | 2.6 326 | 327 | 328 | 329 | Main 330 | 331 | 332 | 333 | 334 | ${project.build.directory}/plugins 335 | 336 | WEB-INF/plugins 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | -------------------------------------------------------------------------------- /checkstyle.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 9 | 10 | 12 | 13 | 14 | 15 | 16 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 30 | 31 | 32 | 33 | 35 | 36 | 37 | 38 | 39 | 40 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 87 | 88 | 89 | 90 | 92 | 93 | 94 | 95 | 96 | 101 | 102 | 103 | 104 | 105 | 107 | 108 | 109 | 110 | 111 | 112 | 114 | 115 | 116 | 117 | 118 | 119 | 121 | 122 | 123 | 124 | 125 | 127 | 128 | 129 | 130 | 131 | 133 | 134 | 135 | 136 | 137 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 153 | 154 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 173 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 202 | 204 | 205 | 206 | 207 | 208 | 213 | 214 | 215 | 220 | 221 | 222 | 223 | 228 | 229 | 230 | 234 | 241 | 242 | 243 | 244 | 245 | 248 | 249 | 250 | 251 | 252 | 255 | 257 | 258 | 259 | 260 | 261 | 262 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 274 | 275 | 276 | 277 | 282 | 283 | 284 | -------------------------------------------------------------------------------- /checkstyleJavaHeader: -------------------------------------------------------------------------------- 1 | ^/\*$ 2 | ^ \* Copyright 201(3|4|5) Google Inc\. All Rights Reserved\.$ 3 | ^ \*$ 4 | ^ \* Licensed under the Apache License, Version 2\.0 \(the \"License\"\);$ 5 | ^ \* you may not use this file except in compliance with the License\.$ 6 | ^ \* You may obtain a copy of the License at$ 7 | ^ \*$ 8 | ^ \* http://www\.apache\.org/licenses/LICENSE-2\.0$ 9 | ^ \*$ 10 | ^ \* Unless required by applicable law or agreed to in writing, software$ 11 | ^ \* distributed under the License is distributed on an \"AS IS\" BASIS,$ 12 | ^ \* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied\.$ 13 | ^ \* See the License for the specific language governing permissions and$ 14 | ^ \* limitations under the License\.$ 15 | ^ \*/ 16 | -------------------------------------------------------------------------------- /image/base/Dockerfile.template: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2015 Google Inc. All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | FROM debian:jessie 17 | 18 | ENV DEBIAN_FRONTEND noninteractive 19 | ENV MAVEN_VERSION 3.2.2 20 | ENV GRADLE_VERSION 2.3 21 | # Set an environment variable to configure which container server to use. 22 | # We use the Google Container Registry: 23 | # https://cloud.google.com/tools/container-registry/. 24 | ENV GCLOUD_CONTAINER_SERVER gcr.io 25 | # Eagerly run this authorization script upon startup. 26 | ENV ONRUN $ONRUN "/google/scripts/gcloud_docker_auth.sh" 27 | 28 | # Install common packages 29 | RUN apt-get update && apt-get upgrade -y && \ 30 | apt-get install -y -qq --no-install-recommends \ 31 | apparmor \ 32 | apt-transport-https \ 33 | ca-certificates-java \ 34 | cron \ 35 | curl \ 36 | rsyslog \ 37 | emacs-nox \ 38 | gcc \ 39 | git \ 40 | initramfs-tools \ 41 | iptables \ 42 | jq \ 43 | less \ 44 | locales \ 45 | lxc \ 46 | make \ 47 | man-db \ 48 | manpages \ 49 | mercurial \ 50 | mysql-client \ 51 | nano \ 52 | nginx \ 53 | openjdk-7-jre-headless \ 54 | openssh-server \ 55 | python \ 56 | python3 \ 57 | python-dev \ 58 | python-setuptools \ 59 | sudo \ 60 | supervisor \ 61 | symlinks \ 62 | unzip \ 63 | vim \ 64 | wget \ 65 | zip && \ 66 | apt-get clean && \ 67 | easy_install -U pip && pip install -U crcmod 68 | 69 | # Install a UTF-8 locale by default. 70 | RUN echo "en_US.UTF-8 UTF-8" >/etc/locale.gen && \ 71 | locale-gen && \ 72 | update-locale LANG=en_US.UTF-8 73 | 74 | # Install Docker. 75 | RUN echo deb https://get.docker.io/ubuntu docker main \ 76 | > /etc/apt/sources.list.d/docker.list 77 | RUN apt-key adv \ 78 | --keyserver hkp://keyserver.ubuntu.com:80 \ 79 | --recv-keys 36A1D7869245C8950F966E92D8576A8BA88D21E9 80 | RUN apt-get update && \ 81 | apt-get install -y --no-install-recommends \ 82 | lxc-docker-1.9.1 && \ 83 | apt-get clean 84 | 85 | # Add jpetazzo's magic wrapper. 86 | # This has been modified to start docker using 'service', 87 | # which means setting DOCKER_DAEMON_ARGS does nothing. 88 | # Instead, you can set DOCKER_SETTINGS_FILE to change 89 | # /etc/default/docker prior to starting the docker service. 90 | ADD third_party/jpetazzo/dind/wrapdocker /google/scripts/wrapdocker.sh 91 | RUN chmod +x /google/scripts/wrapdocker.sh 92 | 93 | # Must be excluded from aufs. 94 | VOLUME /var/lib/docker 95 | 96 | # Make the docker daemon log to a file, so we can realistically use the shell. 97 | ENV LOG file 98 | 99 | ENV DOCKER_HOST unix:///var/run/docker.sock 100 | 101 | # Add our onrun utility, which allows commands to be run on startup 102 | # by adding them to the ONRUN environment variable. For example: 103 | # ENV ONRUN $ONRUN "echo running my command" 104 | ADD onrun.sh /google/scripts/onrun.sh 105 | RUN chmod +x /google/scripts/onrun.sh 106 | 107 | # Now run the wrapdocker script on startup. 108 | ENV ONRUN $ONRUN "/google/scripts/wrapdocker.sh" 109 | 110 | # Configure sshd to be used for Devshell connections. 111 | RUN rm -fv /etc/ssh/ssh_host_* 112 | RUN mkdir /var/run/sshd 113 | ADD sshd_config /etc/ssh/ 114 | 115 | # Add devshell startup logic. 116 | ADD devshell/startup.sh /google/devshell/startup.sh 117 | ADD devshell/authorized_keys.sh /google/devshell/authorized_keys.sh 118 | ADD devshell/bashrc.google /google/devshell/bashrc.google 119 | RUN chmod -R 644 /google/devshell/bashrc.google 120 | RUN mkdir /google/devshell/bashrc.google.d 121 | ENV ONRUN $ONRUN "/google/devshell/startup.sh" 122 | 123 | # Git credential helpers for source.developers.google.com and Gerrit. 124 | ADD gitconfig /etc/gitconfig 125 | RUN chmod -R 644 /etc/gitconfig 126 | 127 | # Make it so the user does not need to type in their password for sudo 128 | RUN echo "%sudo ALL=NOPASSWD: ALL" >> /etc/sudoers 129 | 130 | # Start the cron daemon. 131 | ENV ONRUN $ONRUN "cron" 132 | 133 | # Add cron job to run "gcloud preview docker --authorize_only" every 5 minutes. 134 | ADD gcloud_docker_auth.sh /google/scripts/gcloud_docker_auth.sh 135 | RUN chmod +x /google/scripts/gcloud_docker_auth.sh 136 | RUN (crontab -l 2>/dev/null; \ 137 | echo '*/5 * * * * /google/scripts/gcloud_docker_auth.sh') \ 138 | | crontab 139 | 140 | # Install the Google Cloud SDK. 141 | RUN wget https://dl.google.com/dl/cloudsdk/release/google-cloud-sdk.zip && \ 142 | unzip google-cloud-sdk.zip -d /google/ && \ 143 | rm google-cloud-sdk.zip 144 | ENV CLOUD_SDK /google/google-cloud-sdk 145 | RUN $CLOUD_SDK/install.sh \ 146 | --usage-reporting=true \ 147 | --rc-path=/etc/bash.bashrc \ 148 | --bash-completion=true \ 149 | --path-update=true \ 150 | --disable-installation-options 151 | ENV PATH $CLOUD_SDK/bin:$PATH 152 | 153 | # Install the gcloud preview app support and Managed VMs. 154 | RUN yes | \ 155 | gcloud components update \ 156 | core \ 157 | gcloud 158 | 159 | # Install the Java 7 JDK. 160 | RUN apt-get update && \ 161 | apt-get install -y --no-install-recommends \ 162 | openjdk-7-jdk && \ 163 | apt-get clean 164 | 165 | # Install Maven $MAVEN_VERSION 166 | RUN wget http://archive.apache.org/dist/maven/binaries/apache-maven-$MAVEN_VERSION-bin.zip && \ 167 | unzip apache-maven-$MAVEN_VERSION-bin.zip && \ 168 | rm apache-maven-$MAVEN_VERSION-bin.zip 169 | ENV PATH /apache-maven-$MAVEN_VERSION/bin:$PATH 170 | 171 | # Install Gradle $GRADLE_VERSION 172 | RUN wget http://services.gradle.org/distributions/gradle-$GRADLE_VERSION-bin.zip && \ 173 | unzip gradle-$GRADLE_VERSION-bin.zip && \ 174 | rm gradle-$GRADLE_VERSION-bin.zip 175 | ENV PATH /gradle-$GRADLE_VERSION/bin:$PATH 176 | 177 | ENTRYPOINT ["/bin/bash", "/google/scripts/onrun.sh"] 178 | -------------------------------------------------------------------------------- /image/base/devshell/authorized_keys.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Copyright 2015 Google Inc. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # 17 | # Dumps the list of public keys authorized to authenticate with Devshell 18 | # containers for the current user. Used with sshd_config's AuthorizedKeysCommand 19 | # option. 20 | # 21 | 22 | set -o errexit 23 | set -o nounset 24 | set -o pipefail 25 | 26 | wget -q \ 27 | --header 'Metadata-Flavor:Google' -O - \ 28 | http://metadata.google.internal/computeMetadata/v1/instance/attributes/google-devshell-ssh-keys \ 29 | | sed 's/^[^:]*://' # The metadata is in GCE format, lstrip the user name. 30 | -------------------------------------------------------------------------------- /image/base/devshell/bashrc.google: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2015 Google Inc. All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | # Avoid sourcing bashrc.google more than once for a session as some of 18 | # the commands below are not reentrant. 19 | if [[ -n "${GOOGLE_BASHRC_SOURCED}" ]]; then 20 | return 21 | fi 22 | GOOGLE_BASHRC_SOURCED=1 23 | 24 | for FILE in /google/devshell/bashrc.google.d/*; do 25 | if [ -f "$FILE" ]; then 26 | source "$FILE" 27 | fi 28 | done 29 | 30 | CLOUD_SDK="/google/google-cloud-sdk" 31 | 32 | # The next line updates PATH for the Google Cloud SDK. 33 | source "$CLOUD_SDK/path.bash.inc" 34 | 35 | # The next line enables bash completion for gcloud. 36 | source "$CLOUD_SDK/completion.bash.inc" 37 | 38 | # Assigns a unique per current session configuration location for Cloud SDK 39 | # tools to isolate independent Developer Shell session from each other. 40 | export CLOUDSDK_CONFIG=$(mktemp -d) 41 | trap "rm -rf ${CLOUDSDK_CONFIG}" EXIT 42 | 43 | # Make sure to still create the default configuration settings directory since 44 | # "gcloud auth login" wants to store the credentials there but forgets to 45 | # create it itself when CLOUDSDK_CONFIG is set. Since Devshell is 46 | # authenticated by default, "gcloud auth login" should not be generally needed 47 | # but in case it is used we do want to have it working. 48 | # 49 | mkdir -p $HOME/.config/gcloud 50 | 51 | # Sets the default Cloud SDK session project from Developer Shell environment. 52 | gcloud config set project "${DEVSHELL_PROJECT_ID:-}" 53 | 54 | # Returns the current Cloud SDK project extracted from the configuration area. 55 | # Could parse it from "gcloud config list" output, but invoking gcloud on 56 | # each prompt is impractically slow currently. Use custom Python for now. 57 | get_current_gcloud_project_id () { 58 | python <> "${BASHRC_PATH}" 64 | fi 65 | 66 | # Disables GCE credential lookup as there is no metadata server to communicate 67 | # with in Devshell sessions. Updating the configuration file directly rather 68 | # than invoking gcloud since this is much faster. 69 | logger -p local0.info "Updating gcloud installation scope config" 70 | echo -ne '[core]\ncheck_gce_metadata = False\n' >>/google/google-cloud-sdk/properties 71 | 72 | # Propagate container PATH environment to the user's. 73 | echo "export PATH=$PATH" >/google/devshell/bashrc.google.d/env.sh 74 | 75 | if [[ ! -f /etc/ssh/ssh_host_rsa_key || ! -f /etc/ssh/ssh_host_dsa_key ]]; then 76 | # If SSH host keys are missing, generates a new set of keys. 77 | # Skips the key generation if the keys are present - e.g. if the VM host 78 | # keys have been mapped into the container. 79 | logger -p local0.info "Generating new set of host SSH keys" 80 | dpkg-reconfigure openssh-server 81 | else 82 | logger -p local0.info "Host SSH keys exist, skipping the generation" 83 | fi 84 | 85 | # Finally, start ssdh in the background. 86 | /usr/sbin/sshd ${DEVSHELL_SSH_ARGS} \ 87 | -p "${DEVSHELL_SSH_PORT}" \ 88 | -o AuthorizedKeysCommand="${AUTHORIZED_KEYS_COMMAND}" \ 89 | -o AuthorizedKeysCommandUser=root 90 | -------------------------------------------------------------------------------- /image/base/gcloud_docker_auth.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Copyright 2015 Google Inc. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # 17 | # Updates .dockercfg with credentials to ${GCLOUD_CONTAINER_SERVER}. 18 | # 19 | 20 | set -o errexit 21 | set -o nounset 22 | set -o pipefail 23 | 24 | # Only authorize if we have credentials. 25 | if gcloud auth print-access-token &> /dev/null; then 26 | gcloud docker --authorize-only --server="${GCLOUD_CONTAINER_SERVER}" 27 | fi 28 | 29 | -------------------------------------------------------------------------------- /image/base/gitconfig: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2015 Google Inc. All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | [core] 17 | repositoryformatversion = 0 18 | filemode = true 19 | bare = false 20 | logallrefupdates = true 21 | [credential "https://source.developers.google.com"] 22 | helper = gcloud.sh 23 | -------------------------------------------------------------------------------- /image/base/onrun.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Copyright 2015 Google Inc. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # 17 | # Runs commands defined in the variable ONRUN, which is intepreted as 18 | # an array of strings. We expect ONRUN to be declared in this fashion: 19 | # 20 | # declare -x ONRUN="\"echo first\" \"echo second\"" 21 | # 22 | # In a Dockerfile, a list of ENV declarations will 23 | # construct such an ONRUN variable; for example: 24 | # 25 | # ENV ONRUN "echo first" 26 | # ENV ONRUN $ONRUN "echo second" 27 | # 28 | # This produces the equivalent declaration. 29 | # 30 | # Each quote-delimited command will be executed in order. 31 | # 32 | # Last, any arguments to this script are executed in bash. 33 | # 34 | 35 | set -o errexit 36 | set -o nounset 37 | set -o pipefail 38 | 39 | /usr/sbin/rsyslogd 40 | 41 | # Convert the the ONRUN variable into an array. 42 | eval COMMANDS=(${ONRUN:-}) 43 | NUM_COMMANDS=${#COMMANDS[@]} 44 | 45 | # Put each command into this temporary file and execute it. 46 | TEMP=$(mktemp).sh 47 | trap "rm -rf ${TEMP}" EXIT 48 | for (( I=0; I<${NUM_COMMANDS}; I++ )); do 49 | COMMAND="${COMMANDS[$I]}" 50 | logger -p local0.info "Executing ONRUN command ${COMMAND}" 51 | echo "${COMMAND}" > $TEMP 52 | chmod +x $TEMP 53 | if ! $TEMP; then 54 | logger -p local0.info \ 55 | "ONRUN command $((I+1)) of ${NUM_COMMANDS} failed: ${COMMAND}" 56 | exit 1 57 | else 58 | logger -p local0.info \ 59 | "ONRUN command $((I+1)) of ${NUM_COMMANDS} succeeded: ${COMMAND}" 60 | fi 61 | done 62 | 63 | # Even though we have an EXIT trap set, clean up eagerly. 64 | rm -rf ${TEMP} 65 | 66 | # Now run whatever arguments we were given. Spawn a child process rather 67 | # than 'exec' to make sure bash stays PID 1 to reap zombie children. 68 | # TODO(aalexand): This may be insufficient to correctly handle docker stopping 69 | # a container as bash won't propagate SIGTERM down. Should we run a better 70 | # init-like something? See 71 | # https://blog.phusion.nl/2015/01/20/docker-and-the-pid-1-zombie-reaping-problem/ 72 | /bin/bash -c "$*" 73 | -------------------------------------------------------------------------------- /image/base/sshd_config: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2015 Google Inc. All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | # Package generated configuration file 17 | # See the sshd_config(5) manpage for details 18 | # 19 | 20 | # What ports, IPs and protocols we listen for 21 | Port 22 22 | # Use these options to restrict which interfaces/protocols sshd will bind to 23 | #ListenAddress :: 24 | #ListenAddress 0.0.0.0 25 | Protocol 2 26 | # HostKeys for protocol version 2 27 | HostKey /etc/ssh/ssh_host_rsa_key 28 | HostKey /etc/ssh/ssh_host_dsa_key 29 | #Privilege Separation is turned on for security 30 | UsePrivilegeSeparation yes 31 | 32 | # Lifetime and size of ephemeral version 1 server key 33 | KeyRegenerationInterval 3600 34 | ServerKeyBits 768 35 | 36 | # Logging 37 | SyslogFacility AUTH 38 | LogLevel INFO 39 | 40 | # Authentication: 41 | LoginGraceTime 120 42 | PermitRootLogin yes 43 | StrictModes yes 44 | 45 | RSAAuthentication yes 46 | PubkeyAuthentication yes 47 | #AuthorizedKeysFile %h/.ssh/authorized_keys 48 | 49 | # Don't read the user's ~/.rhosts and ~/.shosts files 50 | IgnoreRhosts yes 51 | # For this to work you will also need host keys in /etc/ssh_known_hosts 52 | RhostsRSAAuthentication no 53 | # similar for protocol version 2 54 | HostbasedAuthentication no 55 | # Uncomment if you don't trust ~/.ssh/known_hosts for RhostsRSAAuthentication 56 | #IgnoreUserKnownHosts yes 57 | 58 | # To enable empty passwords, change to yes (NOT RECOMMENDED) 59 | PermitEmptyPasswords no 60 | 61 | # Change to yes to enable challenge-response passwords (beware issues with 62 | # some PAM modules and threads) 63 | ChallengeResponseAuthentication no 64 | 65 | # Change to no to disable tunnelled clear text passwords 66 | PasswordAuthentication no 67 | 68 | # Kerberos options 69 | #KerberosAuthentication no 70 | #KerberosGetAFSToken no 71 | #KerberosOrLocalPasswd yes 72 | #KerberosTicketCleanup yes 73 | 74 | # GSSAPI options 75 | #GSSAPIAuthentication no 76 | #GSSAPICleanupCredentials yes 77 | 78 | X11Forwarding yes 79 | X11DisplayOffset 10 80 | PrintMotd no 81 | PrintLastLog yes 82 | TCPKeepAlive yes 83 | #UseLogin no 84 | 85 | #MaxStartups 10:30:60 86 | #Banner /etc/issue.net 87 | 88 | # Allow client to pass locale environment variables 89 | AcceptEnv LANG LC_* 90 | 91 | Subsystem sftp /usr/lib/openssh/sftp-server 92 | 93 | # Set this to 'yes' to enable PAM authentication, account processing, 94 | # and session processing. If this is enabled, PAM authentication will 95 | # be allowed through the ChallengeResponseAuthentication and 96 | # PasswordAuthentication. Depending on your PAM configuration, 97 | # PAM authentication via ChallengeResponseAuthentication may bypass 98 | # the setting of "PermitRootLogin without-password". 99 | # If you just want the PAM account and session checks to run without 100 | # PAM authentication, then enable this but set PasswordAuthentication 101 | # and ChallengeResponseAuthentication to 'no'. 102 | UsePAM yes 103 | 104 | # Make sure to include "hmac-md5" MAC format. 105 | MACs hmac-md5,umac-64-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha1-etm@openssh.com,umac-64@openssh.com,umac-128@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-sha1 106 | -------------------------------------------------------------------------------- /image/base/third_party/jpetazzo/dind/LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /image/base/third_party/jpetazzo/dind/README.third_party: -------------------------------------------------------------------------------- 1 | URL: https://raw.githubusercontent.com/jpetazzo/dind/977fcab64737b1c79bf81543a318884b3ac314ad/wrapdocker 2 | Version: 977fcab64737b1c79bf81543a318884b3ac314ad 3 | License: Apache 2.0 4 | License File: LICENSE 5 | 6 | Description: 7 | The wrapdocker script handles the necessary prep work for a Docker container to run Docker. 8 | 9 | Local Modifications: 10 | Added ensure_loopback_device prior to starting docker, to ensure at least four loopback devices exist. Inspired by https://github.com/jpetazzo/dind/issues/19#issuecomment-48859883. 11 | 12 | Start docker using "service docker start" rather than explicitly calling docker. This allows users to use the standard service interface for things like checking the status of the service, restarting it, or stopping it. 13 | -------------------------------------------------------------------------------- /image/base/third_party/jpetazzo/dind/wrapdocker: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # First, make sure that cgroups are mounted correctly. 4 | CGROUP=/sys/fs/cgroup 5 | : {LOG:=stdio} 6 | 7 | [ -d $CGROUP ] || 8 | mkdir $CGROUP 9 | 10 | mountpoint -q $CGROUP || 11 | mount -n -t tmpfs -o uid=0,gid=0,mode=0755 cgroup $CGROUP || { 12 | echo "Could not make a tmpfs mount. Did you use --privileged?" 13 | exit 1 14 | } 15 | 16 | if [ -d /sys/kernel/security ] && ! mountpoint -q /sys/kernel/security 17 | then 18 | mount -t securityfs none /sys/kernel/security || { 19 | echo "Could not mount /sys/kernel/security." 20 | echo "AppArmor detection and --privileged mode might break." 21 | } 22 | fi 23 | 24 | # Mount the cgroup hierarchies exactly as they are in the parent system. 25 | for SUBSYS in $(cut -d: -f2 /proc/1/cgroup) 26 | do 27 | [ -d $CGROUP/$SUBSYS ] || mkdir $CGROUP/$SUBSYS 28 | mountpoint -q $CGROUP/$SUBSYS || 29 | mount -n -t cgroup -o $SUBSYS cgroup $CGROUP/$SUBSYS 30 | 31 | # The two following sections address a bug which manifests itself 32 | # by a cryptic "lxc-start: no ns_cgroup option specified" when 33 | # trying to start containers withina container. 34 | # The bug seems to appear when the cgroup hierarchies are not 35 | # mounted on the exact same directories in the host, and in the 36 | # container. 37 | 38 | # Named, control-less cgroups are mounted with "-o name=foo" 39 | # (and appear as such under /proc//cgroup) but are usually 40 | # mounted on a directory named "foo" (without the "name=" prefix). 41 | # Systemd and OpenRC (and possibly others) both create such a 42 | # cgroup. To avoid the aforementioned bug, we symlink "foo" to 43 | # "name=foo". This shouldn't have any adverse effect. 44 | echo $SUBSYS | grep -q ^name= && { 45 | NAME=$(echo $SUBSYS | sed s/^name=//) 46 | ln -s $SUBSYS $CGROUP/$NAME 47 | } 48 | 49 | # Likewise, on at least one system, it has been reported that 50 | # systemd would mount the CPU and CPU accounting controllers 51 | # (respectively "cpu" and "cpuacct") with "-o cpuacct,cpu" 52 | # but on a directory called "cpu,cpuacct" (note the inversion 53 | # in the order of the groups). This tries to work around it. 54 | [ $SUBSYS = cpuacct,cpu ] && ln -s $SUBSYS $CGROUP/cpu,cpuacct 55 | done 56 | 57 | # Note: as I write those lines, the LXC userland tools cannot setup 58 | # a "sub-container" properly if the "devices" cgroup is not in its 59 | # own hierarchy. Let's detect this and issue a warning. 60 | grep -q :devices: /proc/1/cgroup || 61 | echo "WARNING: the 'devices' cgroup should be in its own hierarchy." 62 | grep -qw devices /proc/1/cgroup || 63 | echo "WARNING: it looks like the 'devices' cgroup is not mounted." 64 | 65 | # Now, close extraneous file descriptors. 66 | pushd /proc/self/fd >/dev/null 67 | for FD in * 68 | do 69 | case "$FD" in 70 | # Keep stdin/stdout/stderr 71 | [012]) 72 | ;; 73 | # Nuke everything else 74 | *) 75 | eval exec "$FD>&-" 76 | ;; 77 | esac 78 | done 79 | popd >/dev/null 80 | 81 | # Ensure we have at least 4 loopback devices. 82 | function ensure_loopback_device() { 83 | DEVICE_NUMBER="$1" 84 | DEVICE_NAME="/dev/loop$DEVICE_NUMBER" 85 | if [ -b "$DEVICE_NAME" ]; then 86 | return 0 87 | fi 88 | 89 | if ! mknod -m660 "$DEVICE_NAME" b 7 "$DEVICE_NUMBER"; then 90 | echo "Failed to create $DEVICE_NAME." 91 | return 1 92 | fi 93 | 94 | return 0 95 | } 96 | 97 | LOOP_A=$(losetup -f) 98 | LOOP_A=${LOOP_A#/dev/loop} 99 | LOOP_B=$(expr $LOOP_A + 1) 100 | LOOP_C=$(expr $LOOP_B + 1) 101 | LOOP_D=$(expr $LOOP_C + 1) 102 | 103 | ensure_loopback_device $LOOP_A 104 | ensure_loopback_device $LOOP_B 105 | ensure_loopback_device $LOOP_C 106 | ensure_loopback_device $LOOP_D 107 | 108 | # If a pidfile is still around (for example after a container restart), 109 | # delete it so that docker can start. 110 | rm -rf /var/run/docker.pid 111 | 112 | # If we were given a docker settings file, copy it to /etc/default/docker. 113 | if [ -n "$DOCKER_SETTINGS_FILE" ] && [ -f "$DOCKER_SETTINGS_FILE" ]; then 114 | cp "$DOCKER_SETTINGS_FILE" /etc/default/docker 115 | fi 116 | 117 | # Last, start the docker service and wait for the daemon to become available. 118 | service docker start &> /dev/null 119 | 120 | (( timeout = 60 + SECONDS )) 121 | until docker info >/dev/null 2>&1 122 | do 123 | if (( SECONDS >= timeout )); then 124 | echo 'Timed out trying to connect to internal docker host.' >&2 125 | break 126 | fi 127 | sleep 1 128 | done 129 | -------------------------------------------------------------------------------- /image/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | # This script builds the Docker image locally, tags it "testing", 3 | # and pushes it to the container registry. 4 | 5 | set -e 6 | 7 | function showUsage() { 8 | local shell_name=`basename $0` 9 | cat << EOF 10 | Usage: $shell_name [--project PROJECT] [--push_image] 11 | testing: build testing version Docker images, and tag them as 12 | gcr.io/developer_tools_bundle/:testing 13 | local_version: build local version of the image, and tag them as 14 | tagged as gcr.io/${TARGET}/:local_version. 15 | So this requires --project parameter to be provided 16 | --project PROJECT: only needed when local_version is specified. 17 | This is the GCP project that you want to deploy to. 18 | --push_image: push the images to gcr.io 19 | 20 | If on your machine docker must be run as root user, you will be prompted for 21 | root password by 'sudo docker ...'. 22 | 23 | You may not be able to push testing|stable version of the images if you don't have 24 | permission to the gcr.io/developer_tools_bundle repo. 25 | EOF 26 | } 27 | 28 | function parseArguments() { 29 | if [[ $# -lt 1 ]]; then 30 | showUsage $0 31 | exit 32 | fi 33 | if [[ $1 == "testing" || $1 == "local_version" ]]; then 34 | BUILD_TYPE=$1 35 | else 36 | showUsage $0 37 | exit 38 | fi 39 | shift 1 40 | PUSH_IMG=false 41 | while [[ -n "$1" ]]; do 42 | case $1 in 43 | --project) 44 | if [[ -n "$2" && ${2:0:1} != "-" ]]; then 45 | TARGET_PROJECT=$2 && shift 46 | fi 47 | ;; 48 | --push_image) 49 | PUSH_IMG=true 50 | ;; 51 | *) 52 | echo "Unknown argument: $1" 53 | showUsage $0 54 | exit 1 55 | ;; 56 | esac 57 | shift 58 | done 59 | if [[ $BUILD_TYPE == "local_version" ]]; then 60 | if [[ -z $TARGET_PROJECT ]]; then 61 | echo "--project parameter is missing" 62 | showUsage $0 63 | exit 64 | fi 65 | fi 66 | } 67 | 68 | BUILD_DIR=tmp_build_dir 69 | 70 | function createShellFormat() { 71 | local result="" 72 | while [[ -n "$1" ]]; do 73 | local tmp=`expr "$1" : '\(.*=\)'` 74 | result=${result}\\\$${tmp::-1}, 75 | shift 76 | done 77 | echo $result 78 | } 79 | 80 | function createDockerfileFromTemplate() { 81 | local src_dir=$1 82 | local build_dir_name=${BUILD_DIR}/$2 83 | shift 2 84 | local vars="$@" 85 | local vars_shell_format=`createShellFormat $vars` 86 | 87 | mkdir -p ${build_dir_name} 88 | rm -rf ${build_dir_name}/* 89 | cp -r ${src_dir}/* ${build_dir_name} 90 | if [[ -z "$vars_shell_format" ]]; then 91 | # We have to specify some vars in SHELL_FORMAT otherwise envsubst will 92 | # replace all environment variables in the target file, which is not what we 93 | # want. 94 | vars_shell_format=\\\$_NO_VARS_TO_REPLACE_ 95 | fi 96 | echo "vars_shell_format = $vars_shell_format" 97 | /bin/bash -c "$vars envsubst $vars_shell_format < ${build_dir_name}/Dockerfile.template > ${build_dir_name}/Dockerfile" 98 | rm ${build_dir_name}/Dockerfile.template 99 | } 100 | 101 | function createSlaveSetupScriptFromTemplate() { 102 | local build_dir_name=${BUILD_DIR}/$1 103 | shift 1 104 | local vars="$@" 105 | local vars_shell_format=`createShellFormat $vars` 106 | if [[ -z "$vars_shell_format" ]]; then 107 | # We have to specify some vars in SHELL_FORMAT otherwise envsubst will 108 | # replace all environment variables in the target file, which is not what we 109 | # want. 110 | vars_shell_format=\\\$_NO_VARS_TO_REPLACE_ 111 | fi 112 | 113 | echo "vars_shell_format = $vars_shell_format" 114 | local setup_slave_shell=${build_dir_name}/startup-scripts/setup-slaves.sh 115 | /bin/bash -c "$vars envsubst $vars_shell_format < ${setup_slave_shell}.template > ${setup_slave_shell}" 116 | rm ${setup_slave_shell}.template 117 | } 118 | 119 | function buildDockerImage() { 120 | local build_dir_name=${BUILD_DIR}/$1 121 | local local_image=$2 122 | local remote_image=$3 123 | if groups $USER | grep &>/dev/null '\bdocker\b'; then 124 | docker build -t $local_image $build_dir_name 125 | docker tag -f $local_image $remote_image 126 | else 127 | sudo docker build -t $local_image $build_dir_name 128 | sudo docker tag -f $local_image $remote_image 129 | fi 130 | } 131 | 132 | function pushDockerImage() { 133 | local remote_image=$1 134 | gcloud docker --authorize-only 135 | if groups $USER | grep &>/dev/null '\bdocker\b'; then 136 | docker push $remote_image 137 | else 138 | sudo docker push $remote_image 139 | fi 140 | } 141 | 142 | parseArguments $@ 143 | NESTED_IMAGE_TAG="$(date -u +%Y-%m-%d-%H-%M)" 144 | LOCAL_IMG=google/jenkins-base:${NESTED_IMAGE_TAG} 145 | 146 | echo 147 | echo "==========================================================" 148 | echo Building $BUILD_TYPE base image now 149 | echo "==========================================================" 150 | case $BUILD_TYPE in 151 | testing) 152 | REMOTE_IMG=gcr.io/developer_tools_bundle/jenkins-base:${NESTED_IMAGE_TAG} 153 | ENV_VARS="" 154 | ;; 155 | local_version) 156 | REMOTE_IMG=gcr.io/${TARGET_PROJECT}/jenkins-base:${NESTED_IMAGE_TAG} 157 | ENV_VARS="" 158 | ;; 159 | esac 160 | echo "Creating Dockerfile from template ..." 161 | createDockerfileFromTemplate base base_$BUILD_TYPE $ENV_VARS 162 | echo "Building Docker images now ..." 163 | buildDockerImage base_$BUILD_TYPE $LOCAL_IMG $REMOTE_IMG 164 | if [[ $PUSH_IMG == true ]]; then 165 | echo "Pushing $REMOTE_IMG now ..." 166 | pushDockerImage $REMOTE_IMG 167 | fi 168 | 169 | echo 170 | echo "==========================================================" 171 | echo Build $BUILD_TYPE slave images now 172 | echo "==========================================================" 173 | # Need to build slave images before master images, because master images 174 | # contains script that need to know what slaves are available. 175 | SDC="" 176 | for slave_dir in `find slave_images -maxdepth 1 -type d -name "jenkins-slave-*"`; 177 | do 178 | SLAVE_NAME=`basename $slave_dir` 179 | if [[ -z $SDC ]]; then 180 | SDC=$SLAVE_NAME 181 | else 182 | SDC=${SDC},${SLAVE_NAME} 183 | fi 184 | LOCAL_IMG=google/${SLAVE_NAME}:${NESTED_IMAGE_TAG} 185 | case $BUILD_TYPE in 186 | testing) 187 | REMOTE_IMG=gcr.io/developer_tools_bundle/${SLAVE_NAME}:${NESTED_IMAGE_TAG} 188 | ENV_VARS="_BASE_IMG_=gcr.io/developer_tools_bundle/jenkins-base:${NESTED_IMAGE_TAG}" 189 | ;; 190 | local_version) 191 | REMOTE_IMG=gcr.io/${TARGET_PROJECT}/${SLAVE_NAME}:${NESTED_IMAGE_TAG} 192 | ENV_VARS="_BASE_IMG_=gcr.io/${TARGET_PROJECT}/jenkins-base:${NESTED_IMAGE_TAG}" 193 | ;; 194 | esac 195 | echo "Creating $SLAVE_NAME Dockerfile from template ..." 196 | createDockerfileFromTemplate slave_images/${SLAVE_NAME} ${SLAVE_NAME}_$BUILD_TYPE $ENV_VARS 197 | echo "Building Docker images now ..." 198 | buildDockerImage ${SLAVE_NAME}_$BUILD_TYPE $LOCAL_IMG $REMOTE_IMG 199 | if [[ $PUSH_IMG == true ]]; then 200 | echo "Pushing $REMOTE_IMG now ..." 201 | pushDockerImage $REMOTE_IMG 202 | fi 203 | done 204 | SLAVE_IMG_PREFIX=${REMOTE_IMG%/*} 205 | SLAVE_IMG_LABEL=":"${REMOTE_IMG##*:} 206 | 207 | echo 208 | echo "==========================================================" 209 | echo Build $BUILD_TYPE master images now 210 | echo "==========================================================" 211 | case $BUILD_TYPE in 212 | testing) 213 | LOCAL_IMG=google/jenkins-appengine:testing 214 | REMOTE_IMG=gcr.io/developer_tools_bundle/jenkins:testing 215 | ENV_VARS="_BASE_IMG_=gcr.io/developer_tools_bundle/jenkins-base:${NESTED_IMAGE_TAG}" 216 | ;; 217 | local_version) 218 | LOCAL_IMG=google/jenkins-appengine:local_version 219 | REMOTE_IMG=gcr.io/${TARGET_PROJECT}/jenkins:local_version 220 | ENV_VARS="_BASE_IMG_=gcr.io/${TARGET_PROJECT}/jenkins-base:${NESTED_IMAGE_TAG}" 221 | ;; 222 | esac 223 | echo "Creating master Dockerfile from template ..." 224 | createDockerfileFromTemplate master_images master_$BUILD_TYPE $ENV_VARS 225 | ENV_VARS="_SDC_=$SDC _SLAVE_IMG_PREFIX_=${SLAVE_IMG_PREFIX} _SLAVE_IMG_LABEL_=${SLAVE_IMG_LABEL}" 226 | createSlaveSetupScriptFromTemplate master_$BUILD_TYPE $ENV_VARS 227 | echo "Building Docker images now ..." 228 | buildDockerImage master_$BUILD_TYPE $LOCAL_IMG $REMOTE_IMG 229 | if [[ $PUSH_IMG == true ]]; then 230 | echo "Pushing $REMOTE_IMG now ..." 231 | pushDockerImage $REMOTE_IMG 232 | fi 233 | -------------------------------------------------------------------------------- /image/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | # Copyright 2015 Google Inc. All rights reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -e 18 | 19 | function showUsage() { 20 | local shell_name=`basename $0` 21 | cat << EOF 22 | Usage: $shell_name [--project PROJECT] [--cpu CPU] [--memory MEMORY] [--disk DISK] 23 | [--build_from_src] [--use_test_img] [--on_conflict_restore_from_backup] 24 | --project PROJECT 25 | Sets the Google Cloud project you want to deploy to. PROJECT is the id 26 | of the project. If this option is not provided, default to the current 27 | project in gcloud config. 28 | --cpu CPU 29 | The number of CPUs to use. Minium CPU is 1, default is 4. 30 | --memory MEMORY 31 | Memory in GB. Minimum is 4(GB), default is 8(GB). 32 | --disk DISK 33 | Both memory size and disk sizes are in GB. Minimum is 200(GB), default is 200(GB) 34 | --build_from_src 35 | Build the image from your local source code. The default value is false so it 36 | will use a pre-built image 'gcr.io/developer_tools_bundle/jenkins'. 37 | If on your machine docker must be run as root user, you will be prompted for 38 | root password by 'sudo docker ...'. 39 | --use_test_img 40 | Deploy using the test version Google pre-built Docker image. 41 | --report_usage 42 | Enable anonymized usage reports. Jenkins usage information will be sent to 43 | Google via the Google Usage Reporting plugin. This is a project-wide setting. 44 | --on_conflict_restore_from_backup 45 | On Jenkins restart after upgrade, backup changes will overwrite disk changes if you use this flag. 46 | This means, pre-installed Jenkins settings/plugins may not work. 47 | Regular jenkins restart(non upgrades) will still favour backup changes 48 | so user configurations are not lost. This is a project-wide setting and will default to false. 49 | Omit cpu/memory/disk/on_conflict_restore_from_backup options to use default value. 50 | 51 | Example: $shell_name --project my_project_id --cpu 3 --memory 6 52 | EOF 53 | exit 54 | } 55 | 56 | function verifyAgainstMinimum() { 57 | local minimum=$1 58 | local default=$2 59 | local var=$3 60 | if [[ -z $var ]]; then 61 | printf "$default" 62 | elif (( $(echo "$var < $minimum" | bc -l) )); then 63 | printf "$minimum" 64 | else 65 | printf "$var" 66 | fi 67 | } 68 | 69 | DEPLOY_FLAVOR=stable 70 | function parseArguments() { 71 | SHOW_USAGE=false 72 | RESTORE_FROM_BACKUP=false 73 | SEND_USAGE_REPORTS=false 74 | 75 | while [[ -n "$1" ]]; do 76 | case $1 in 77 | --project) 78 | if [[ $2 != "" && ${2:0:1} != "-" ]]; then 79 | TARGET_PROJECT=$2 && shift 80 | fi 81 | ;; 82 | --cpu) 83 | if [[ $2 != "" && ${2:0:1} != "-" ]]; then 84 | JENKINS_CPU=$2 && shift 85 | fi 86 | ;; 87 | --memory) 88 | if [[ $2 != "" && ${2:0:1} != "-" ]]; then 89 | JENKINS_MEMORY=$2 && shift 90 | fi 91 | ;; 92 | --disk) 93 | if [[ $2 != "" && ${2:0:1} != "-" ]]; then 94 | JENKINS_DISK=$2 && shift 95 | fi 96 | ;; 97 | --build_from_src) 98 | BUILD_FROM_SRC=true 99 | DEPLOY_FLAVOR=local_version 100 | ;; 101 | --use_test_img) 102 | USE_TEST_IMG=true 103 | DEPLOY_FLAVOR=testing 104 | ;; 105 | --report_usage) 106 | SEND_USAGE_REPORTS=true 107 | ;; 108 | --on_conflict_restore_from_backup) 109 | RESTORE_FROM_BACKUP=true 110 | ;; 111 | -h|--help|*) 112 | SHOW_USAGE=true 113 | break 114 | ;; 115 | esac 116 | shift 117 | done 118 | if [[ $SHOW_USAGE = true ]]; then 119 | showUsage $0 120 | exit 121 | else 122 | JENKINS_CPU=$(verifyAgainstMinimum 1 4 $JENKINS_CPU) 123 | JENKINS_MEMORY=$(verifyAgainstMinimum 4 8 $JENKINS_MEMORY) 124 | JENKINS_DISK=$(verifyAgainstMinimum 200 200 $JENKINS_DISK) 125 | fi 126 | } 127 | 128 | function defaultModuleExists() { 129 | local project=$1 130 | local count=$(gcloud --quiet preview app modules list default --project $project 2>&1 \ 131 | | grep -o "^default" | wc -l) 132 | if [[ $count -gt 0 ]]; then 133 | return 0 134 | else 135 | return 1 136 | fi 137 | } 138 | 139 | function deployDefaultModule() { 140 | local target_project=$1 141 | local tmp_dir=$(mktemp -d --tmpdir=$(pwd)) 142 | echo 143 | echo "Default module doesn't exist, deploying default module now..." 144 | cat > ${tmp_dir}/app.yaml < ${tmp_dir}/hello.html < 158 | 159 | Sample Hello-World Page. 160 | 161 | 162 | Hello, World! 163 | 164 | 165 | EOF 166 | local status=1 167 | gcloud --quiet preview app deploy --project $target_project \ 168 | $tmp_dir/app.yaml --version v1 169 | [[ $? ]] && succeeded=0 || echo "Failed to deploy default module to $target_project" 170 | rm -rf $tmp_dir 171 | return $succeeded 172 | } 173 | 174 | function networkExists() { 175 | local project=$1 176 | local network=$2 177 | gcloud --quiet compute networks list $network --project $project --format yaml \ 178 | | grep "^name:\s*$network$" > /dev/null 2>&1 179 | return $? 180 | } 181 | 182 | function createAppDotYaml() { 183 | local tmp_dir=$1 184 | local jenkins_cpu=$2 185 | local jenkins_memory=$3 186 | local jenkins_disk=$4 187 | cat > ${tmp_dir}/app.yaml</dev/null '\bdocker\b'; then 248 | docker build -t $img . && docker tag -f $img $img_upload \ 249 | && gcloud --quiet docker push $img_upload 250 | else 251 | sudo docker build -t $img . && sudo docker tag -f $img $img_upload \ 252 | && gcloud --quiet docker push $img_upload 253 | fi 254 | } 255 | 256 | function createDockerfile() { 257 | local tmp_dir=$1 258 | local img=$2 259 | cat > ${tmp_dir}/Dockerfile < 2 | 3 | 4 | 2 5 | NORMAL 6 | true 7 | 9 | 10 | 11 | 12 | 13 | false 14 | 15 | uid={0} 16 | 15 17 | X-AppEngine-User-Email 18 | X-Forwarded-Groups 19 | | 20 | 21 | 22 | 23 | 24 | 25 | All 26 | false 27 | false 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /image/master_images/jenkins/healthChecks.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | basic 6 | 7 | basic 8 | 9 | 10 | 1 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | com.google.jenkins.plugins.health.HealthZone 19 | 20 | -------------------------------------------------------------------------------- /image/master_images/jenkins/jenkins-upgrade-version: -------------------------------------------------------------------------------- 1 | 1 2 | -------------------------------------------------------------------------------- /image/master_images/nginx.conf: -------------------------------------------------------------------------------- 1 | error_log /var/log/nginx.log; 2 | pid /var/log/nginx.pid; 3 | 4 | events { 5 | worker_connections 1024; # increase if you have lots of clients 6 | accept_mutex off; # "on" if nginx worker_processes > 1 7 | } 8 | 9 | http { 10 | server { 11 | listen 8080 default_server; 12 | 13 | # Reverse proxy setup for Jenkins, based on 14 | # https://wiki.jenkins-ci.org/display/JENKINS/Jenkins+behind+an+NGinX+reverse+proxy 15 | location / { 16 | # This assumes that Jenkins is started on port 5000 locally. 17 | # Either inside a Docker container or just a regular JVM. 18 | # Rewrites health check URL to access the health check plugin. 19 | rewrite ^/_ah/health /health/zone/basic/api/json; 20 | proxy_pass http://127.0.0.1:5000; 21 | proxy_set_header Host $host; 22 | proxy_set_header X-Real-IP $remote_addr; 23 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 24 | proxy_set_header Authorization $http_authorization; 25 | proxy_set_header X-Forwarded-User $http_authorization; 26 | proxy_set_header X-Forwarded-Server $host; 27 | proxy_set_header X-Forwarded-Proto https; 28 | proxy_pass_header Authorization; 29 | proxy_connect_timeout 150; 30 | proxy_send_timeout 100; 31 | proxy_read_timeout 100; 32 | proxy_buffers 4 32k; 33 | proxy_redirect http://$host https://$host; 34 | proxy_redirect http://127.0.0.1:5000 https://$host; 35 | client_max_body_size 8m; 36 | client_body_buffer_size 128k; 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /image/master_images/startup-scripts/jenkins.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2015 Google Inc. All rights reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | mkdir -p /var/log/app_engine/custom_logs 18 | export JENKINS_HOME=/jenkins 19 | 20 | function chown_cat() { 21 | cat > $1 22 | chown root:root $1 23 | chmod 777 $1 24 | } 25 | 26 | APP_BUCKET=$(curl -f http://metadata/computeMetadata/v1beta1/instance/attributes/gae_app_bucket || true) 27 | MODULE=$(curl -f http://metadata/computeMetadata/v1beta1/instance/attributes/gae_backend_name -f || true) 28 | VERSION=$(curl -f http://metadata/computeMetadata/v1beta1/instance/attributes/gae_backend_version || true) 29 | PROJECT_NUM=$(curl -f http://metadata/computeMetadata/v1beta1/project/numeric-project-id || false) 30 | METRICS_OPTIN=$(curl -f http://metadata/computeMetadata/v1beta1/project/attributes/google_report_usage || false) 31 | ANALYTICS_ID=$(curl -f http://metadata/computeMetadata/v1beta1/project/attributes/google_report_analytics_id || false) 32 | PROJECT_ID=$(curl -f http://metadata/computeMetadata/v1beta1/project/project-id || true) 33 | RESTORE_FROM_BACKUP=$(curl -f http://metadata/computeMetadata/v1beta1/project/attributes/restore_from_backup || false) 34 | 35 | if [[ -n "$PROJECT_NUM" ]]; then 36 | HASHED_PROJECT_NUM=$(echo -n "$PROJECT_NUM" | sha1sum | awk '{print $1}') 37 | else 38 | HASHED_PROJECT_NUM="" 39 | fi 40 | 41 | if [[ -n "$CONFIG_BUCKET" ]]; then 42 | BUCKET=$CONFIG_BUCKET 43 | else 44 | BUCKET=vm-containers.${APP_BUCKET#vm-config.}/jenkins-backup/$MODULE/$VERSION 45 | fi 46 | 47 | chown_cat $JENKINS_HOME/google-cloud-backup.xml < 49 | 50 | true 51 | true 52 | $RESTORE_FROM_BACKUP 53 | 1 54 | 3 55 | 56 | $BUCKET 57 | 58 | 59 | BACKUP_XML 60 | 61 | chown_cat $JENKINS_HOME/google-analytics-usage-reporter.xml < 63 | 64 | $METRICS_OPTIN 65 | $HASHED_PROJECT_NUM 66 | $ANALYTICS_ID 67 | 68 | USAGE_REPORT_XML 69 | 70 | chown_cat $JENKINS_HOME/jenkins.model.JenkinsLocationConfiguration.xml << LOCATION_CONFIG_XML 71 | 72 | 73 | address not configured yet <nobody@nowhere> 74 | https://jenkins-dot-${PROJECT_ID}.appspot.com 75 | 76 | LOCATION_CONFIG_XML 77 | 78 | java -jar jenkins.war --httpPort=5000 --logfile=/var/log/app_engine/custom_logs/jenkins.log 79 | -------------------------------------------------------------------------------- /image/master_images/startup-scripts/setup-slaves.sh.template: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2015 Google Inc. All rights reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | 18 | MASTER=$(hostname) 19 | #Jenkins Master port 20 | JMPORT=${JMPORT:-5000} 21 | SLAVE_JAR=slave.jar 22 | CLI_JAR=jenkins-cli.jar 23 | RETRY=1200 24 | SLEEP=5 #seconds 25 | SUCCESS="" 26 | echo "Downloading Jenkins CLI jar ..." 27 | for TRY in $(seq 1 $RETRY); do 28 | curl -O http://$MASTER:$JMPORT/jnlpJars/$CLI_JAR|| true 29 | # Verify that a jar file, not the "Please wait for Jenkins to be up" page 30 | # was downloaded. This should also cover the case that no file was downloaded. 31 | if zip -T $CLI_JAR; then 32 | SUCCESS=true 33 | break; 34 | fi 35 | echo "Jenkins may not be up and running yet, waiting..." 1>&2 36 | sleep $SLEEP 37 | done 38 | 39 | if [ -z "$SUCCESS" ]; then 40 | echo "[ERROR] Jenkins isn't up after $RETRY attempts." 1>&2 41 | exit -1 42 | fi 43 | 44 | echo "Removing old slaves ..." 45 | java -jar jenkins-cli.jar -s "http://$MASTER:$JMPORT" \ 46 | groovy = < 53 | null != node.assignedLabels.find { label -> 54 | label.name =~ "^docker-slave-[^:/]+" 55 | } 56 | } 57 | 58 | // Then remove all of them 59 | sdcNodes.each { sdcNode -> 60 | println "removing node " + sdcNode 61 | jenkins.removeNode(sdcNode) 62 | } 63 | REMOVE_OLD_SDC 64 | 65 | SDC=$_SDC_ 66 | for AN_SDC in ${SDC//,/ } 67 | do 68 | SLAVE_NAME=$AN_SDC 69 | IMAGE_NAME=${_SLAVE_IMG_PREFIX_}/${SLAVE_NAME}${_SLAVE_IMG_LABEL_} 70 | echo "pull slave image $IMAGE_NAME ..." 71 | gcloud docker pull $IMAGE_NAME 72 | echo "Spin up slave container $SLAVE_NAME with label $SLAVE_NAME" 73 | java -jar jenkins-cli.jar -s "http://$MASTER:$JMPORT" \ 74 | create-node $SLAVE_NAME < 76 | $SLAVE_NAME 77 | 78 | /var/jenkins/ 79 | 1 80 | NORMAL 81 | 82 | 84 | 85 | 86 | 87 | 88 | CONFIG_XML_SLAVE 89 | 90 | java -jar jenkins-cli.jar -s "http://$MASTER:$JMPORT" online-node $SLAVE_NAME 91 | 92 | cat > slave-startup-$SLAVE_NAME.sh <&2 107 | sleep $SLEEP 108 | done 109 | 110 | export JNLP_SUCCESS="" 111 | export JNLP_FILE=slave-agent.jnlp 112 | echo "Downloading Jenkins Slave-Agent JNLP file ..." 113 | for TRY in \$(seq 1 $RETRY); do 114 | curl --retry $RETRY --retry-delay $SLEEP \ 115 | -O http://\$PARENT_IP:$JMPORT/computer/$SLAVE_NAME/\$JNLP_FILE 116 | # Verify that a jnlp file, not the "Please wait for Jenkins to be up" page 117 | # was downloaded. This should also cover the case that no file was downloaded. 118 | if head -1 \$JNLP_FILE | grep -q "^&2 123 | sleep $SLEEP 124 | done 125 | 126 | # The slaves stay up until the host VM is torn down, 127 | # so ensure things stay up. This allows us to reconnect 128 | # slaves if the master has a temporary issue or is told 129 | # by the user to restart. 130 | while true 131 | do 132 | # Stagger the connections 133 | java -jar $SLAVE_JAR -jnlpUrl file:///\$JNLP_FILE 134 | sleep 10 135 | 136 | done 137 | EOF 138 | 139 | SLAVE_TMP_DIR=/container-tmp/$SLAVE_NAME 140 | mkdir -p $SLAVE_TMP_DIR 141 | chmod 777 $SLAVE_TMP_DIR 142 | 143 | echo "spin up SLAVE container $SLAVE_NAME ..." 144 | nohup docker run --rm -i --privileged --name="$SLAVE_NAME" \ 145 | -v $SLAVE_TMP_DIR/docker:/var/lib/docker \ 146 | -v $SLAVE_TMP_DIR/slave-home:/var/jenkins \ 147 | $IMAGE_NAME /bin/bash < slave-startup-$SLAVE_NAME.sh & 148 | done 149 | -------------------------------------------------------------------------------- /image/master_images/supervisord.conf: -------------------------------------------------------------------------------- 1 | [supervisord] 2 | nodaemon=true 3 | logfile=/var/log/app_engine/custom_logs/supervisord.log 4 | childlogdir=/var/log/app_engine/custom_logs/ 5 | 6 | [program:nginx] 7 | command=/bin/bash -c "/etc/init.d/nginx restart" 8 | 9 | [program:jenkins] 10 | command=/startup-scripts/jenkins.sh 11 | 12 | [program:setup-slaves] 13 | command=/startup-scripts/setup-slaves.sh 14 | 15 | 16 | -------------------------------------------------------------------------------- /image/slave_images/jenkins-slave-go/Dockerfile.template: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2015 Google Inc. All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | FROM $_BASE_IMG_ 18 | 19 | RUN apt-get update && apt-get install -y --no-install-recommends golang-go && apt-get clean 20 | 21 | ENV GOPATH /gopath 22 | ENV PATH $GOPATH/bin:$PATH 23 | 24 | # Pull down all the common app engine dependencies 25 | RUN go get google.golang.org/appengine 26 | 27 | # This is needed to translate Go test output into xUnit as the canonical test result format 28 | RUN go get bitbucket.org/tebeka/go2xunit 29 | -------------------------------------------------------------------------------- /image/slave_images/jenkins-slave-java/Dockerfile.template: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2015 Google Inc. All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | FROM $_BASE_IMG_ 18 | --------------------------------------------------------------------------------