├── .github ├── ISSUE_TEMPLATE.md └── stale.yml ├── .gitignore ├── .grenrc.yml ├── .travis.yml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── docs ├── authentication.md ├── releasing.md └── usage.md ├── extension ├── LICENSE.txt ├── pom.xml └── src │ └── main │ └── resources │ └── META-INF │ └── plexus │ └── components.xml ├── plugin ├── LICENSE.txt ├── pom.xml └── src │ ├── it │ ├── advanced │ │ ├── backend │ │ │ ├── Dockerfile │ │ │ ├── pom.xml │ │ │ └── src │ │ │ │ └── main │ │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── spotify │ │ │ │ └── it │ │ │ │ └── backend │ │ │ │ └── Main.java │ │ ├── frontend │ │ │ ├── Dockerfile │ │ │ ├── pom.xml │ │ │ └── src │ │ │ │ ├── main │ │ │ │ └── java │ │ │ │ │ └── com │ │ │ │ │ └── spotify │ │ │ │ │ └── it │ │ │ │ │ └── frontend │ │ │ │ │ └── Main.java │ │ │ │ └── test │ │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── spotify │ │ │ │ └── it │ │ │ │ └── frontend │ │ │ │ └── MainIT.java │ │ ├── invoker.properties │ │ └── pom.xml │ ├── basic-lowercase-dockerfile │ │ ├── dockerfile │ │ ├── pom.xml │ │ └── verify.groovy │ ├── basic-with-build-args │ │ ├── Dockerfile │ │ ├── pom.xml │ │ └── verify.groovy │ ├── basic │ │ ├── Dockerfile │ │ ├── pom.xml │ │ └── verify.groovy │ ├── build-into-repository │ │ ├── Dockerfile │ │ ├── pom.xml │ │ └── verify.groovy │ ├── build-into-tag │ │ ├── Dockerfile │ │ ├── pom.xml │ │ └── verify.groovy │ ├── build-tag-version │ │ ├── Dockerfile │ │ ├── pom.xml │ │ └── verify.groovy │ ├── build-then-add-repository │ │ ├── Dockerfile │ │ ├── pom.xml │ │ └── verify.groovy │ ├── build-then-add-tag │ │ ├── Dockerfile │ │ ├── pom.xml │ │ └── verify.groovy │ ├── build-with-custom-dockerfile │ │ ├── context │ │ │ ├── resources │ │ │ │ └── foo.txt │ │ │ └── sub │ │ │ │ └── Dockerfile │ │ ├── pom.xml │ │ └── verify.groovy │ ├── illegal-custom-dockerfile-location │ │ ├── context │ │ │ └── foo.txt │ │ ├── invoker.properties │ │ ├── not-context │ │ │ └── Dockerfile │ │ ├── pom.xml │ │ └── verify.groovy │ ├── maven-settings-auth │ │ ├── Dockerfile │ │ ├── auth.properties │ │ ├── invoker.properties │ │ ├── pom.xml │ │ ├── settings-security.xml │ │ └── verify.groovy │ ├── missing-custom-dockerfile │ │ ├── invoker.properties │ │ ├── pom.xml │ │ └── verify.groovy │ ├── missing-dockerfile │ │ ├── invoker.properties │ │ ├── pom.xml │ │ └── verify.groovy │ ├── multi-module │ │ ├── a │ │ │ ├── Dockerfile │ │ │ └── pom.xml │ │ ├── b │ │ │ ├── Dockerfile │ │ │ └── pom.xml │ │ ├── pom.xml │ │ └── verify.groovy │ ├── settings.xml │ ├── skip │ │ ├── pom.xml │ │ └── verify.groovy │ └── writes-test-classpath │ │ ├── Dockerfile │ │ ├── pom.xml │ │ └── verify.groovy │ ├── main │ └── java │ │ └── com │ │ └── spotify │ │ └── plugin │ │ └── dockerfile │ │ ├── AbstractDockerMojo.java │ │ ├── BuildMojo.java │ │ ├── LoggingProgressHandler.java │ │ ├── MavenPomAuthSupplier.java │ │ ├── MavenRegistryAuthSupplier.java │ │ ├── PushMojo.java │ │ └── TagMojo.java │ └── test │ └── java │ └── com │ └── spotify │ └── plugin │ └── dockerfile │ └── TestRepoNameValidation.java ├── pom.xml └── travis-settings.xml /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | <!-- This form is for bug reports and feature requests ONLY! 2 | 3 | If you're looking for help check 4 | [Stack Overflow](https://stackoverflow.com/questions/tagged/spotify-dockerfile-maven) and the docs. 5 | --> 6 | 7 | **Is this a BUG REPORT or FEATURE REQUEST?**: 8 | 9 | ## Description 10 | 11 | [Add feature/bug description here] 12 | 13 | ## How to reproduce 14 | 15 | [Add steps on how to reproduce this issue] 16 | 17 | ## What do you expect 18 | 19 | [Describe what do you expect to happen] 20 | 21 | ## What happened instead 22 | 23 | [Describe the actual results] 24 | 25 | ## Software: 26 | 27 | - `docker version`: [Add the output of `docker version` here, both client and server] 28 | - Spotify's dockerfile-maven version: [Add dockerfile-maven version here] 29 | 30 | ## Full backtrace 31 | 32 | ```text 33 | [Paste full backtrace here] 34 | ``` 35 | 36 | -------------------------------------------------------------------------------- /.github/stale.yml: -------------------------------------------------------------------------------- 1 | daysUntilStale: 60 2 | daysUntilClose: 7 3 | exemptLabels: 4 | - pinned 5 | - security 6 | staleLabel: stale 7 | markComment: > 8 | This issue has been automatically marked as stale because it has not had 9 | recent activity. It will be closed if no further activity occurs. Thank you 10 | for your contributions. 11 | closeComment: false 12 | only: issues 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .* 2 | !.git* 3 | !.travis.yml 4 | target/ 5 | pom.xml.releaseBackup 6 | release.properties 7 | -------------------------------------------------------------------------------- /.grenrc.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dataSource: "prs" 3 | prefix: "" 4 | ignoreLabels: [] 5 | ignoreIssuesWith: [] 6 | onlyMilestones: false 7 | groupBy: false 8 | changelogFilename: "CHANGELOG.md" 9 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | 3 | jdk: 4 | - openjdk11 5 | - openjdk10 6 | - openjdk9 7 | - openjdk8 8 | 9 | sudo: required 10 | 11 | services: 12 | - docker 13 | 14 | install: true # This runs the "true" command in the install phase; thus skipping install 15 | script: 16 | - | 17 | if [[ "$TRAVIS_BRANCH" == master && "$TRAVIS_PULL_REQUEST" == false && "$TRAVIS_JDK_VERSION" == "openjdk8" ]] 18 | then mvn deploy -s travis-settings.xml 19 | else mvn verify 20 | fi 21 | 22 | cache: 23 | directories: 24 | - $HOME/.m2/repository/ 25 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## v1.4.13 (October 15 2019) 4 | - [**closed**] #308 Extend repository validation by allowing port number. [#309](https://github.com/spotify/dockerfile-maven/pull/309) 5 | - [**closed**] doc [#318](https://github.com/spotify/dockerfile-maven/pull/318) 6 | 7 | ## v1.4.12 (July 29 2019) 8 | - [**closed**] Upgrade docker-client dep from 8.14.5 to 8.16.0 [#307](https://github.com/spotify/dockerfile-maven/pull/307) 9 | 10 | ## v1.4.11 (July 29 2019) 11 | - [**closed**] Validation of docker repository names [#275](https://github.com/spotify/dockerfile-maven/pull/275) 12 | - [**closed**] Update docker-client version to 8.14.5 [#280](https://github.com/spotify/dockerfile-maven/pull/280) 13 | 14 | ## 1.4.10 (released January 15 2019) 15 | - Add support for --squash experimental build option ([248][]) 16 | - Add support for specifying a custom Dockerfile location ([89][]) 17 | 18 | [248]: https://github.com/spotify/dockerfile-maven/pull/248 19 | [89]: https://github.com/spotify/dockerfile-maven/pull/89 20 | 21 | ## 1.4.9 (released October 25 2018) 22 | - Upgrade docker-client dep from 8.14.2 to 8.14.3 to fix spotify/docker-client#1100 23 | 24 | ## 1.4.8 (released October 23 2018) 25 | - Upgrade docker-client dep from 8.14.0 to 8.14.2 26 | - Upgrade com.sparkjava:spark-core to fix CVE-2018-9159 27 | - Improve documentation on referencing build artifacts 28 | 29 | ## 1.4.7 (released October 8 2018) 30 | - Fix an ExceptionInInitializerError when plugin is used on Java 11 ([230][]) 31 | - change source/target version for compiler from 1.7 to 1.8. This means that 32 | the plugin will only run on Java 8 and above. ([231]) 33 | 34 | [230]: https://github.com/spotify/dockerfile-maven/pull/230 35 | [231]: https://github.com/spotify/dockerfile-maven/pull/231 36 | 37 | ## 1.4.6 (released October 5 2018) 38 | 39 | - Support for Java 9 and 10 40 | 41 | ## 1.3.6 (released September 13 2017) 42 | 43 | - Add support for using maven settings.xml file to provide docker authorization ([65][]) 44 | 45 | [65]: https://github.com/spotify/dockerfile-maven/pull/65 46 | 47 | ## 1.3.3 (released July 11 2017) 48 | 49 | - Add support for supplying build-args (`ARG` in Dockerfile) in pom.xml with 50 | `<buildArgs>` [41][] 51 | 52 | - Allow disabling of Google Container Registry credential checks with 53 | `-Ddockerfile.googleContainerRegistryEnabled` or 54 | `<googleContainerRegistryEnabled>false</googleContainerRegistryEnabled>`([43][]) 55 | 56 | 57 | [41]: https://github.com/spotify/dockerfile-maven/pull/41 58 | [43]: https://github.com/spotify/dockerfile-maven/pull/43 59 | 60 | 61 | ## 1.3.2 (released July 10 2017) 62 | 63 | - Upgrade to docker-client 8.8.0 ([38][]) 64 | 65 | - Improved fix for NullPointerException in LoggingProgressHandler ([36][]) 66 | 67 | [36]: https://github.com/spotify/dockerfile-maven/pull/36 68 | [38]: https://github.com/spotify/dockerfile-maven/pull/38 69 | 70 | 71 | ## 1.3.1 (released June 30 2017) 72 | 73 | - Fix NullPointerException in LoggingProgressHandler ([30][]) 74 | 75 | [30]: https://github.com/spotify/dockerfile-maven/pull/30 76 | 77 | 78 | ## 1.3.0 (released June 5 2017) 79 | 80 | - Support for authentication to Google Container Registry ([13][], [17][]) 81 | 82 | [13]: https://github.com/spotify/dockerfile-maven/pull/13 83 | [17]: https://github.com/spotify/dockerfile-maven/pull/17 84 | 85 | ## Earlier releases 86 | 87 | Please check the [list of commits on Github][commits]. 88 | 89 | [commits]: https://github.com/spotify/dockerfile-maven/commits/master 90 | -------------------------------------------------------------------------------- /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. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Dockerfile Maven 2 | 3 | [](https://travis-ci.com/spotify/dockerfile-maven) 4 | [](https://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.spotify%22%20dockerfile-maven) 5 | [](LICENSE) 6 | 7 | ## Status: mature 8 | 9 | **At this point, we're not developing or accepting new features or even fixing non-critical bugs.** 10 | 11 | This Maven plugin integrates Maven with Docker. 12 | 13 | The design goals are: 14 | 15 | - Don't do anything fancy. `Dockerfile`s are how you build 16 | Docker projects; that's what this plugin uses. They are 17 | mandatory. 18 | - Make the Docker build process integrate with the Maven build 19 | process. If you bind the default phases, when you type `mvn 20 | package`, you get a Docker image. When you type `mvn deploy`, 21 | your image gets pushed. 22 | - Make the goals remember what you are doing. You can type `mvn 23 | dockerfile:build` and later `mvn dockerfile:tag` and later `mvn 24 | dockerfile:push` without problems. This also eliminates the need 25 | for something like `mvn dockerfile:build -DalsoPush`; instead you 26 | can just say `mvn dockerfile:build dockerfile:push`. 27 | - Integrate with the Maven build reactor. You can depend on the 28 | Docker image of one project in another project, and Maven will 29 | build the projects in the correct order. This is useful when you 30 | want to run integration tests involving multiple services. 31 | 32 | This project adheres to the [Open Code of Conduct][code-of-conduct]. 33 | By participating, you are expected to honor this code. 34 | 35 | See the [changelog for a list of releases][changelog] 36 | 37 | [code-of-conduct]: https://github.com/spotify/code-of-conduct/blob/master/code-of-conduct.md 38 | [changelog]: CHANGELOG.md 39 | 40 | ## Set-up 41 | 42 | This plugin requires Java 7 or later and Apache Maven 3 or later (dockerfile-maven-plugin <=1.4.6 needs 43 | Maven >= 3, and for other cases, Maven >= 3.5.2). To run the integration tests or to use the plugin in practice, a working 44 | Docker set-up is needed. 45 | 46 | ## Example 47 | 48 | For more examples, see the [integration test](./plugin/src/it) directory. 49 | 50 | In particular, the [advanced](./plugin/src/it/advanced) test showcases a 51 | full service consisting of two micro-services that are integration 52 | tested using `helios-testing`. 53 | 54 | This configures the actual plugin to build your image with `mvn 55 | package` and push it with `mvn deploy`. Of course you can also say 56 | `mvn dockerfile:build` explicitly. 57 | 58 | ```xml 59 | <plugin> 60 | <groupId>com.spotify</groupId> 61 | <artifactId>dockerfile-maven-plugin</artifactId> 62 | <version>${dockerfile-maven-version}</version> 63 | <executions> 64 | <execution> 65 | <id>default</id> 66 | <goals> 67 | <goal>build</goal> 68 | <goal>push</goal> 69 | </goals> 70 | </execution> 71 | </executions> 72 | <configuration> 73 | <repository>spotify/foobar</repository> 74 | <tag>${project.version}</tag> 75 | <buildArgs> 76 | <JAR_FILE>${project.build.finalName}.jar</JAR_FILE> 77 | </buildArgs> 78 | </configuration> 79 | </plugin> 80 | ``` 81 | 82 | A corresponding `Dockerfile` could look like: 83 | 84 | ``` 85 | FROM openjdk:8-jre 86 | MAINTAINER David Flemström <dflemstr@spotify.com> 87 | 88 | ENTRYPOINT ["/usr/bin/java", "-jar", "/usr/share/myservice/myservice.jar"] 89 | 90 | # Add Maven dependencies (not shaded into the artifact; Docker-cached) 91 | ADD target/lib /usr/share/myservice/lib 92 | # Add the service itself 93 | ARG JAR_FILE 94 | ADD target/${JAR_FILE} /usr/share/myservice/myservice.jar 95 | ``` 96 | 97 | **Important note** 98 | 99 | The most Maven-ish way to reference the build artifact would probably 100 | be to use the `project.build.directory` variable for referencing the 101 | 'target'-directory. However, this results in an absolute path, which 102 | is not supported by the ADD command in the Dockerfile. Any such source 103 | must be inside the *context* of the Docker build and therefor must be 104 | referenced by a *relative path*. See https://github.com/spotify/dockerfile-maven/issues/101 105 | 106 | *Do **not** use `${project.build.directory}` as a way to reference your 107 | build directory.* 108 | 109 | ## What does it give me? 110 | 111 | There are many advantages to using this plugin for your builds. 112 | 113 | ### Faster build times 114 | 115 | This plugin lets you leverage Docker cache more consistently, vastly 116 | speeding up your builds by letting you cache Maven dependencies in 117 | your image. It also encourages avoiding the `maven-shade-plugin`, 118 | which also greatly speeds up builds. 119 | 120 | ### Consistent build lifecycle 121 | 122 | You no longer have to say something like: 123 | 124 | mvn package 125 | mvn dockerfile:build 126 | mvn verify 127 | mvn dockerfile:push 128 | mvn deploy 129 | 130 | Instead, it is simply enough to say: 131 | 132 | mvn deploy 133 | 134 | With the basic configuration, this will make sure that the image is 135 | built and pushed at the correct times. 136 | 137 | ### Depend on Docker images of other services 138 | 139 | You can depend on the Docker information of another project, because 140 | this plugin attaches project metadata when it builds Docker images. 141 | Simply add this information to any project: 142 | 143 | ```xml 144 | <dependency> 145 | <groupId>com.spotify</groupId> 146 | <artifactId>foobar</artifactId> 147 | <version>1.0-SNAPSHOT</version> 148 | <type>docker-info</type> 149 | </dependency> 150 | ``` 151 | 152 | Now, you can read information about the Docker image of the project 153 | that you depended on: 154 | 155 | ```java 156 | String imageName = getResource("META-INF/docker/com.spotify/foobar/image-name"); 157 | ``` 158 | 159 | This is great for an integration test where you want the latest 160 | version of another project's Docker image. 161 | 162 | Note that you have to register a Maven extension in your POM (or a 163 | parent POM) in order for the `docker-info` type to be supported: 164 | 165 | ```xml 166 | <build> 167 | <extensions> 168 | <extension> 169 | <groupId>com.spotify</groupId> 170 | <artifactId>dockerfile-maven-extension</artifactId> 171 | <version>${version}</version> 172 | </extension> 173 | </extensions> 174 | </build> 175 | ``` 176 | 177 | ## Use other Docker tools that rely on Dockerfiles 178 | 179 | Your project(s) look like so: 180 | 181 | ``` 182 | a/ 183 | Dockerfile 184 | pom.xml 185 | b/ 186 | Dockerfile 187 | pom.xml 188 | ``` 189 | 190 | You can now use these projects with Fig or docker-compose or some 191 | other system that works with Dockerfiles. For example, a 192 | `docker-compose.yml` might look like: 193 | 194 | ```yaml 195 | service-a: 196 | build: a/ 197 | ports: 198 | - '80' 199 | 200 | service-b: 201 | build: b/ 202 | links: 203 | - service-a 204 | ``` 205 | 206 | Now, `docker-compose up` and `docker-compose build` will work as 207 | expected. 208 | 209 | ## Usage 210 | 211 | See [usage docs](https://github.com/spotify/dockerfile-maven/blob/master/docs/usage.md). 212 | 213 | ## Authentication 214 | 215 | See [authentication docs](https://github.com/spotify/dockerfile-maven/blob/master/docs/authentication.md). 216 | 217 | ## Releasing 218 | 219 | To cut the Maven release: 220 | 221 | ``` 222 | mvn clean [-B -Dinvoker.skip -DskipTests -Darguments='-Dinvoker.skip -DskipTests'] \ 223 | -Dgpg.keyname=<key ID used for signing artifacts> \ 224 | release:clean release:prepare release:perform 225 | ``` 226 | 227 | We use [`gren`](https://github.com/github-tools/github-release-notes#installation) to create Releases in Github: 228 | 229 | ``` 230 | gren release 231 | ``` -------------------------------------------------------------------------------- /docs/authentication.md: -------------------------------------------------------------------------------- 1 | # Authentication 2 | 3 | ## Authentication and private Docker registry support 4 | 5 | Since version 1.3.0, the plugin will automatically use any configuration in 6 | your `~/.dockercfg` or `~/.docker/config.json` file when pulling, pushing, or 7 | building images to private registries. 8 | 9 | Additionally the plugin will enable support for Google Container Registry if it 10 | is able to successfully load [Google's "Application Default Credentials"][ADC]. 11 | The plugin will also load Google credentials from the file pointed to by the 12 | environment variable `DOCKER_GOOGLE_CREDENTIALS` if it is defined. Since GCR 13 | authentication requires retrieving short-lived access codes for the given 14 | credentials, support for this registry is baked into the underlying 15 | docker-client rather than having to first populate the docker config file 16 | before running the plugin. 17 | 18 | [ADC]: https://developers.google.com/identity/protocols/application-default-credentials 19 | 20 | GCR users may need to initialize their Application Default Credentials via `gcloud`. 21 | Depending on where the plugin will run, they may wish to use [their Google 22 | identity][app-def-login] by running the following command 23 | 24 | gcloud auth application-default login 25 | 26 | or [create a service account][service-acct] instead. 27 | 28 | [app-def-login]: https://cloud.google.com/sdk/gcloud/reference/auth/application-default/login 29 | [service-acct]: https://cloud.google.com/docs/authentication/getting-started#creating_a_service_account 30 | 31 | ## Authenticating with maven settings.xml 32 | 33 | Since version 1.3.6, you can authenticate using your maven settings.xml instead 34 | of docker configuration. Just add configuration similar to: 35 | 36 | ```xml 37 | <configuration> 38 | <repository>docker-repo.example.com:8080/organization/image</repository> 39 | <tag>latest</tag> 40 | <useMavenSettingsForAuth>true</useMavenSettingsForAuth> 41 | </configuration> 42 | ``` 43 | 44 | You can also use `-Ddockerfile.useMavenSettingsForAuth=true` on the command line. 45 | 46 | Then, in your maven settings file, add configuration for the server: 47 | 48 | ```xml 49 | <servers> 50 | <server> 51 | <id>docker-repo.example.com:8080</id> 52 | <username>me</username> 53 | <password>mypassword</password> 54 | </server> 55 | </servers> 56 | ``` 57 | 58 | exactly as you would for any other server configuration. 59 | 60 | Since version 1.4.3, using an encrypted password in the Maven settings file is supported. For more 61 | information about encrypting server passwords in `settings.xml`, 62 | [read the documentation here](https://maven.apache.org/guides/mini/guide-encryption.html). 63 | 64 | ## Authenticating with maven pom.xml 65 | 66 | Since version 1.3.XX, you can authenticate using config from the pom itself. 67 | Just add configuration similar to: 68 | 69 | ```xml 70 | <plugin> 71 | <groupId>com.spotify</groupId> 72 | <artifactId>dockerfile-maven-plugin</artifactId> 73 | <version>${version}</version> 74 | <configuration> 75 | <username>repoUserName</username> 76 | <password>repoPassword</password> 77 | <repository>${docker.image.prefix}/${project.artifactId}</repository> 78 | <buildArgs> 79 | <JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE> 80 | </buildArgs> 81 | </configuration> 82 | </plugin> 83 | ``` 84 | or simpler, 85 | ```xml 86 | <plugin> 87 | <groupId>com.spotify</groupId> 88 | <artifactId>dockerfile-maven-plugin</artifactId> 89 | <version>${version}</version> 90 | <configuration> 91 | <repository>${docker.image.prefix}/${project.artifactId}</repository> 92 | <buildArgs> 93 | <JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE> 94 | </buildArgs> 95 | </configuration> 96 | </plugin> 97 | ``` 98 | 99 | with this command line call 100 | 101 | mvn goal -Ddockerfile.username=... -Ddockerfile.password=... 102 | 103 | -------------------------------------------------------------------------------- /docs/releasing.md: -------------------------------------------------------------------------------- 1 | # Releasing 2 | 3 | ``` 4 | mvn -P release -Dgpg.keyname=<key-ID> release:clean release:prepare release:perform --batch-mode 5 | ``` 6 | -------------------------------------------------------------------------------- /docs/usage.md: -------------------------------------------------------------------------------- 1 | # Usage 2 | 3 | ## Maven Goals 4 | 5 | Goals available for this plugin: 6 | 7 | | Goal | Description | Default Phase | 8 | | ---- | -------------- | ------------- | 9 | | `dockerfile:build` | Builds a Docker image from a Dockerfile. | package | 10 | | `dockerfile:tag` | Tags a Docker image. | package | 11 | | `dockerfile:push` | Pushes a Docker image to a repository. | deploy | 12 | 13 | ### Skip Docker Goals Bound to Maven Phases 14 | 15 | You can pass options to maven to disable the docker goals. 16 | 17 | | Maven Option | What Does it Do? | Default Value | 18 | | ------------- | -------------------------- | ------------- | 19 | | `dockerfile.skip` | Disables the entire dockerfile plugin; all goals become no-ops. | false | 20 | | `dockerfile.build.skip` | Disables the build goal; it becomes a no-op. | false | 21 | | `dockerfile.tag.skip` | Disables the tag goal; it becomes a no-op. | false | 22 | | `dockerfile.push.skip` | Disables the push goal; it becomes a no-op. | false | 23 | 24 | For example, to skip the entire dockerfile plugin: 25 | ``` 26 | mvn clean package -Ddockerfile.skip 27 | ``` 28 | 29 | ## Configuration 30 | 31 | ### Build Phase 32 | 33 | | Maven Option | What Does it Do? | Required | Default Value | 34 | | ------------- | -------------------------- | -------- | ------------- | 35 | | `dockerfile.contextDirectory` | Directory containing the Dockerfile to build. | yes | none | 36 | | `dockerfile.repository` | The repository to name the built image | no | none | 37 | | `dockerfile.tag` | The tag to apply when building the Dockerfile, which is appended to the repository. | no | latest | 38 | | `dockerfile.build.pullNewerImage` | Updates base images automatically. | no | true | 39 | | `dockerfile.build.noCache` | Do not use cache when building the image. | no | false | 40 | | `dockerfile.build.cacheFrom` | Docker image used as cache-from. Pulled in advance if not exist locally or `pullNewerImage` is `false` | no | none | 41 | | `dockerfile.buildArgs` | Custom build arguments. | no | none | 42 | | `dockerfile.build.squash` | Squash newly built layers into a single new layer (experimental API 1.25+). | no | false | 43 | -------------------------------------------------------------------------------- /extension/LICENSE.txt: -------------------------------------------------------------------------------- 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. 202 | -------------------------------------------------------------------------------- /extension/pom.xml: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 3 | <modelVersion>4.0.0</modelVersion> 4 | 5 | <parent> 6 | <artifactId>dockerfile-maven</artifactId> 7 | <groupId>com.spotify</groupId> 8 | <version>1.4.14-SNAPSHOT</version> 9 | </parent> 10 | 11 | <artifactId>dockerfile-maven-extension</artifactId> 12 | 13 | <name>Dockerfile Maven Extension</name> 14 | <description>Adds support for docker-info dependencies in Maven</description> 15 | 16 | </project> 17 | -------------------------------------------------------------------------------- /extension/src/main/resources/META-INF/plexus/components.xml: -------------------------------------------------------------------------------- 1 | <!-- 2 | -/-/- 3 | Dockerfile Maven Extension 4 | %% 5 | Copyright (C) 2015 - 2016 Spotify AB 6 | %% 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | -\-\- 19 | --> 20 | <component-set> 21 | <components> 22 | <component> 23 | <role>org.apache.maven.artifact.handler.ArtifactHandler</role> 24 | <role-hint>docker-info</role-hint> 25 | <implementation>org.apache.maven.artifact.handler.DefaultArtifactHandler</implementation> 26 | <configuration> 27 | <classifier>docker-info</classifier> 28 | <extension>jar</extension> 29 | <type>docker-info</type> 30 | <packaging>jar</packaging> 31 | <language>java</language> 32 | <addedToClasspath>true</addedToClasspath> 33 | <includesDependencies>false</includesDependencies> 34 | </configuration> 35 | </component> 36 | </components> 37 | </component-set> 38 | -------------------------------------------------------------------------------- /plugin/LICENSE.txt: -------------------------------------------------------------------------------- 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. 202 | -------------------------------------------------------------------------------- /plugin/pom.xml: -------------------------------------------------------------------------------- 1 | <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 2 | 3 | <modelVersion>4.0.0</modelVersion> 4 | 5 | <parent> 6 | <groupId>com.spotify</groupId> 7 | <artifactId>dockerfile-maven</artifactId> 8 | <version>1.4.14-SNAPSHOT</version> 9 | </parent> 10 | 11 | <artifactId>dockerfile-maven-plugin</artifactId> 12 | <packaging>maven-plugin</packaging> 13 | 14 | <name>Dockerfile Maven Plugin</name> 15 | <description>Adds support for building Dockerfiles in Maven</description> 16 | 17 | <properties> 18 | <docker-client.version>8.16.0</docker-client.version> 19 | </properties> 20 | 21 | <dependencyManagement> 22 | <dependencies> 23 | <dependency> 24 | <groupId>com.google.code.findbugs</groupId> 25 | <artifactId>jsr305</artifactId> 26 | <version>2.0.1</version> 27 | </dependency> 28 | <dependency> 29 | <groupId>org.apache.commons</groupId> 30 | <artifactId>commons-compress</artifactId> 31 | <version>1.19</version> 32 | </dependency> 33 | <dependency> 34 | <groupId>org.codehaus.plexus</groupId> 35 | <artifactId>plexus-interpolation</artifactId> 36 | <version>1.24</version> 37 | </dependency> 38 | </dependencies> 39 | </dependencyManagement> 40 | 41 | <dependencies> 42 | <dependency> 43 | <groupId>com.spotify</groupId> 44 | <artifactId>docker-client</artifactId> 45 | <classifier>shaded</classifier> 46 | <version>${docker-client.version}</version> 47 | </dependency> 48 | <dependency> 49 | <groupId>com.google.auth</groupId> 50 | <artifactId>google-auth-library-oauth2-http</artifactId> 51 | <version>0.6.0</version> 52 | </dependency> 53 | <dependency> 54 | <groupId>com.google.guava</groupId> 55 | <artifactId>guava</artifactId> 56 | <version>23.6.1-jre</version> 57 | </dependency> 58 | <dependency> 59 | <groupId>com.spotify</groupId> 60 | <artifactId>dockerfile-maven-extension</artifactId> 61 | <version>1.4.14-SNAPSHOT</version> 62 | </dependency> 63 | 64 | <dependency> 65 | <groupId>org.apache.maven</groupId> 66 | <artifactId>maven-plugin-api</artifactId> 67 | <version>3.5.4</version> 68 | </dependency> 69 | <dependency> 70 | <groupId>org.apache.maven</groupId> 71 | <artifactId>maven-core</artifactId> 72 | <version>3.5.4</version> 73 | </dependency> 74 | 75 | <dependency> 76 | <groupId>org.apache.maven</groupId> 77 | <artifactId>maven-archiver</artifactId> 78 | <version>3.2.0</version> 79 | </dependency> 80 | 81 | <dependency> 82 | <groupId>org.sonatype.plexus</groupId> 83 | <artifactId>plexus-sec-dispatcher</artifactId> 84 | <version>1.4</version> 85 | </dependency> 86 | 87 | <dependency> 88 | <groupId>com.google.code.gson</groupId> 89 | <artifactId>gson</artifactId> 90 | <version>2.8.0</version> 91 | </dependency> 92 | 93 | <dependency> 94 | <groupId>org.apache.maven.plugin-tools</groupId> 95 | <artifactId>maven-plugin-annotations</artifactId> 96 | <version>3.5.2</version> 97 | <scope>provided</scope> 98 | </dependency> 99 | 100 | <dependency> 101 | <groupId>junit</groupId> 102 | <artifactId>junit</artifactId> 103 | <version>4.12</version> 104 | <scope>test</scope> 105 | </dependency> 106 | </dependencies> 107 | 108 | <build> 109 | <plugins> 110 | <plugin> 111 | <artifactId>maven-checkstyle-plugin</artifactId> 112 | </plugin> 113 | <plugin> 114 | <artifactId>maven-enforcer-plugin</artifactId> 115 | </plugin> 116 | <plugin> 117 | <artifactId>maven-failsafe-plugin</artifactId> 118 | </plugin> 119 | <plugin> 120 | <artifactId>maven-compiler-plugin</artifactId> 121 | <version>3.1</version> 122 | <configuration> 123 | <source>1.8</source> 124 | <target>1.8</target> 125 | </configuration> 126 | </plugin> 127 | <plugin> 128 | <groupId>org.apache.maven.plugins</groupId> 129 | <artifactId>maven-plugin-plugin</artifactId> 130 | <version>3.5.2</version> 131 | <configuration> 132 | <goalPrefix>dockerfile</goalPrefix> 133 | <skipErrorNoDescriptorsFound>true</skipErrorNoDescriptorsFound> 134 | </configuration> 135 | <executions> 136 | <execution> 137 | <id>mojo-descriptor</id> 138 | <goals> 139 | <goal>descriptor</goal> 140 | </goals> 141 | </execution> 142 | <execution> 143 | <id>help-goal</id> 144 | <goals> 145 | <goal>helpmojo</goal> 146 | </goals> 147 | </execution> 148 | </executions> 149 | </plugin> 150 | <plugin> 151 | <groupId>org.apache.maven.plugins</groupId> 152 | <artifactId>maven-invoker-plugin</artifactId> 153 | <version>1.9</version> 154 | <dependencies> 155 | <dependency> 156 | <groupId>com.spotify</groupId> 157 | <artifactId>docker-client</artifactId> 158 | <version>${docker-client.version}</version> 159 | </dependency> 160 | </dependencies> 161 | <configuration> 162 | <cloneProjectsTo>${project.build.directory}/it</cloneProjectsTo> 163 | <pomIncludes> 164 | <pomInclude>*/pom.xml</pomInclude> 165 | </pomIncludes> 166 | <postBuildHookScript>verify</postBuildHookScript> 167 | <localRepositoryPath>${project.build.directory}/local-repo</localRepositoryPath> 168 | <settingsFile>src/it/settings.xml</settingsFile> 169 | <streamLogs>true</streamLogs> 170 | <goals> 171 | <goal>clean</goal> 172 | <goal>verify</goal> 173 | </goals> 174 | </configuration> 175 | <executions> 176 | <execution> 177 | <id>integration-test</id> 178 | <goals> 179 | <goal>install</goal> 180 | <goal>integration-test</goal> 181 | <goal>verify</goal> 182 | </goals> 183 | </execution> 184 | </executions> 185 | </plugin> 186 | </plugins> 187 | </build> 188 | </project> 189 | -------------------------------------------------------------------------------- /plugin/src/it/advanced/backend/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM java 2 | MAINTAINER David Flemström <dflemstr@spotify.com> 3 | ENTRYPOINT ["/usr/bin/java", "-jar", "/usr/share/backend/backend.jar"] 4 | 5 | ADD target/lib /usr/share/backend/lib 6 | ADD target/backend.jar /usr/share/backend/backend.jar 7 | -------------------------------------------------------------------------------- /plugin/src/it/advanced/backend/pom.xml: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <!-- 3 | -/-/- 4 | Dockerfile Maven Plugin 5 | %% 6 | Copyright (C) 2015 - 2016 Spotify AB 7 | %% 8 | Licensed under the Apache License, Version 2.0 (the "License"); 9 | you may not use this file except in compliance with the License. 10 | You may obtain a copy of the License at 11 | 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | Unless required by applicable law or agreed to in writing, software 15 | distributed under the License is distributed on an "AS IS" BASIS, 16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | See the License for the specific language governing permissions and 18 | limitations under the License. 19 | -\-\- 20 | --> 21 | 22 | <project xmlns="http://maven.apache.org/POM/4.0.0" 23 | xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 24 | xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 25 | <modelVersion>4.0.0</modelVersion> 26 | 27 | <parent> 28 | <groupId>com.spotify.it</groupId> 29 | <artifactId>advanced</artifactId> 30 | <version>1.0-SNAPSHOT</version> 31 | </parent> 32 | 33 | <artifactId>backend</artifactId> 34 | 35 | <description>The backend service</description> 36 | 37 | <properties> 38 | <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 39 | </properties> 40 | 41 | <dependencies> 42 | <dependency> 43 | <groupId>com.sparkjava</groupId> 44 | <artifactId>spark-core</artifactId> 45 | <version>2.8.0</version> 46 | </dependency> 47 | </dependencies> 48 | 49 | <build> 50 | <finalName>backend</finalName> 51 | <plugins> 52 | <!-- Use Java 8 --> 53 | <plugin> 54 | <artifactId>maven-compiler-plugin</artifactId> 55 | <configuration> 56 | <source>1.8</source> 57 | <target>1.8</target> 58 | </configuration> 59 | </plugin> 60 | <!-- Set up JAR manifest --> 61 | <plugin> 62 | <artifactId>maven-jar-plugin</artifactId> 63 | <configuration> 64 | <archive> 65 | <manifest> 66 | <addClasspath>true</addClasspath> 67 | <classpathPrefix>lib/</classpathPrefix> 68 | <mainClass>com.spotify.it.backend.Main</mainClass> 69 | </manifest> 70 | </archive> 71 | </configuration> 72 | </plugin> 73 | <!-- Copy Maven dependencies into target/lib/ --> 74 | <plugin> 75 | <artifactId>maven-dependency-plugin</artifactId> 76 | <executions> 77 | <execution> 78 | <phase>initialize</phase> 79 | <goals> 80 | <goal>copy-dependencies</goal> 81 | </goals> 82 | <configuration> 83 | <overWriteReleases>false</overWriteReleases> 84 | <includeScope>runtime</includeScope> 85 | <outputDirectory>${project.build.directory}/lib</outputDirectory> 86 | </configuration> 87 | </execution> 88 | </executions> 89 | </plugin> 90 | <!-- Build Docker image --> 91 | <plugin> 92 | <groupId>@project.groupId@</groupId> 93 | <artifactId>@project.artifactId@</artifactId> 94 | <version>@project.version@</version> 95 | <executions> 96 | <execution> 97 | <id>default</id> 98 | <goals> 99 | <goal>build</goal> 100 | </goals> 101 | <configuration> 102 | <repository>spotify/dockerfile-advanced-backend</repository> 103 | </configuration> 104 | </execution> 105 | </executions> 106 | </plugin> 107 | </plugins> 108 | </build> 109 | </project> 110 | -------------------------------------------------------------------------------- /plugin/src/it/advanced/backend/src/main/java/com/spotify/it/backend/Main.java: -------------------------------------------------------------------------------- 1 | /*- 2 | * -\-\- 3 | * Dockerfile Maven Plugin 4 | * -- 5 | * Copyright (C) 2016 Spotify AB 6 | * -- 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * -/-/- 19 | */ 20 | 21 | package com.spotify.it.backend; 22 | 23 | import spark.Spark; 24 | 25 | public class Main { 26 | 27 | public static void main(String[] args) { 28 | Spark.port(1337); 29 | Spark.get("/api/version", (req, res) -> "v1.0"); 30 | Spark.get("/api/lowercase/:message", (req, res) -> req.params("message").toLowerCase()); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /plugin/src/it/advanced/frontend/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM java 2 | MAINTAINER David Flemström <dflemstr@spotify.com> 3 | ENTRYPOINT ["/usr/bin/java", "-jar", "/usr/share/frontend/frontend.jar"] 4 | 5 | ADD target/lib /usr/share/frontend/lib 6 | ADD target/frontend.jar /usr/share/frontend/frontend.jar 7 | -------------------------------------------------------------------------------- /plugin/src/it/advanced/frontend/pom.xml: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <!-- 3 | -/-/- 4 | Dockerfile Maven Plugin 5 | %% 6 | Copyright (C) 2015 - 2016 Spotify AB 7 | %% 8 | Licensed under the Apache License, Version 2.0 (the "License"); 9 | you may not use this file except in compliance with the License. 10 | You may obtain a copy of the License at 11 | 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | Unless required by applicable law or agreed to in writing, software 15 | distributed under the License is distributed on an "AS IS" BASIS, 16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | See the License for the specific language governing permissions and 18 | limitations under the License. 19 | -\-\- 20 | --> 21 | 22 | <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 23 | xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 24 | <modelVersion>4.0.0</modelVersion> 25 | 26 | <parent> 27 | <groupId>com.spotify.it</groupId> 28 | <artifactId>advanced</artifactId> 29 | <version>1.0-SNAPSHOT</version> 30 | </parent> 31 | 32 | <artifactId>frontend</artifactId> 33 | 34 | <description>The second module</description> 35 | 36 | <properties> 37 | <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 38 | </properties> 39 | 40 | <dependencies> 41 | <dependency> 42 | <groupId>com.sparkjava</groupId> 43 | <artifactId>spark-core</artifactId> 44 | <version>2.8.0</version> 45 | </dependency> 46 | <dependency> 47 | <groupId>com.google.guava</groupId> 48 | <artifactId>guava</artifactId> 49 | <version>19.0</version> 50 | </dependency> 51 | 52 | <dependency> 53 | <groupId>com.spotify.it</groupId> 54 | <artifactId>backend</artifactId> 55 | <version>1.0-SNAPSHOT</version> 56 | <type>docker-info</type> 57 | <scope>test</scope> 58 | </dependency> 59 | <dependency> 60 | <groupId>junit</groupId> 61 | <artifactId>junit</artifactId> 62 | <version>4.12</version> 63 | <scope>test</scope> 64 | </dependency> 65 | <dependency> 66 | <groupId>org.hamcrest</groupId> 67 | <artifactId>hamcrest-core</artifactId> 68 | <version>1.3</version> 69 | <scope>test</scope> 70 | </dependency> 71 | <dependency> 72 | <groupId>org.hamcrest</groupId> 73 | <artifactId>hamcrest-library</artifactId> 74 | <version>1.3</version> 75 | <scope>test</scope> 76 | </dependency> 77 | <dependency> 78 | <groupId>com.spotify</groupId> 79 | <artifactId>helios-testing</artifactId> 80 | <version>0.9.71</version> 81 | <scope>test</scope> 82 | </dependency> 83 | <dependency> 84 | <groupId>org.testcontainers</groupId> 85 | <artifactId>testcontainers</artifactId> 86 | <version>1.9.1</version> 87 | <scope>test</scope> 88 | </dependency> 89 | </dependencies> 90 | 91 | <build> 92 | <finalName>frontend</finalName> 93 | <plugins> 94 | <!-- Use Java 8 --> 95 | <plugin> 96 | <artifactId>maven-compiler-plugin</artifactId> 97 | <configuration> 98 | <source>1.8</source> 99 | <target>1.8</target> 100 | </configuration> 101 | </plugin> 102 | <!-- Set up JAR manifest --> 103 | <plugin> 104 | <artifactId>maven-jar-plugin</artifactId> 105 | <configuration> 106 | <archive> 107 | <manifest> 108 | <addClasspath>true</addClasspath> 109 | <classpathPrefix>lib/</classpathPrefix> 110 | <mainClass>com.spotify.it.frontend.Main</mainClass> 111 | </manifest> 112 | </archive> 113 | </configuration> 114 | </plugin> 115 | <!-- Copy Maven dependencies into target/lib/ --> 116 | <plugin> 117 | <artifactId>maven-dependency-plugin</artifactId> 118 | <executions> 119 | <execution> 120 | <phase>initialize</phase> 121 | <goals> 122 | <goal>copy-dependencies</goal> 123 | </goals> 124 | <configuration> 125 | <overWriteReleases>false</overWriteReleases> 126 | <includeScope>runtime</includeScope> 127 | <outputDirectory>${project.build.directory}/lib</outputDirectory> 128 | </configuration> 129 | </execution> 130 | </executions> 131 | </plugin> 132 | <!-- Build Docker image --> 133 | <plugin> 134 | <groupId>@project.groupId@</groupId> 135 | <artifactId>@project.artifactId@</artifactId> 136 | <version>@project.version@</version> 137 | <executions> 138 | <execution> 139 | <id>default</id> 140 | <goals> 141 | <goal>build</goal> 142 | </goals> 143 | <configuration> 144 | <repository>spotify/dockerfile-advanced-frontend</repository> 145 | </configuration> 146 | </execution> 147 | </executions> 148 | </plugin> 149 | <plugin> 150 | <artifactId>maven-failsafe-plugin</artifactId> 151 | <executions> 152 | <execution> 153 | <goals> 154 | <goal>integration-test</goal> 155 | <goal>verify</goal> 156 | </goals> 157 | </execution> 158 | </executions> 159 | </plugin> 160 | </plugins> 161 | </build> 162 | </project> 163 | -------------------------------------------------------------------------------- /plugin/src/it/advanced/frontend/src/main/java/com/spotify/it/frontend/Main.java: -------------------------------------------------------------------------------- 1 | /*- 2 | * -\-\- 3 | * Dockerfile Maven Plugin 4 | * -- 5 | * Copyright (C) 2016 Spotify AB 6 | * -- 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * -/-/- 19 | */ 20 | 21 | package com.spotify.it.frontend; 22 | 23 | import com.google.common.io.CharStreams; 24 | 25 | import java.io.InputStream; 26 | import java.io.InputStreamReader; 27 | import java.math.BigInteger; 28 | import java.net.URI; 29 | import java.nio.charset.StandardCharsets; 30 | import java.security.SecureRandom; 31 | import java.util.Random; 32 | 33 | import spark.Spark; 34 | 35 | public class Main { 36 | 37 | public static void main(String[] args) { 38 | if (args.length < 1) { 39 | System.err.println("Needs backend URL as command-line argument"); 40 | System.exit(1); 41 | return; 42 | } 43 | 44 | URI backendUri = URI.create(args[0]); 45 | 46 | Random random = new SecureRandom(); 47 | 48 | Spark.port(1338); 49 | Spark.get("/", (req, res) -> { 50 | String uppercase = new BigInteger(130, random).toString(32).toUpperCase(); 51 | 52 | String version; 53 | try (InputStream versionStream = backendUri.resolve("/api/version").toURL().openStream()) { 54 | version = 55 | CharStreams.toString(new InputStreamReader(versionStream, StandardCharsets.UTF_8)); 56 | } 57 | 58 | String lowercase; 59 | try (InputStream lowercaseStream = 60 | backendUri.resolve("/api/lowercase/" + uppercase).toURL().openStream()) { 61 | lowercase = 62 | CharStreams.toString(new InputStreamReader(lowercaseStream, StandardCharsets.UTF_8)); 63 | } 64 | 65 | return "<!DOCTYPE html><html>" 66 | + "<head><title>frontend</title></head>" 67 | + "<body>" 68 | + "<p>Backend version: " + version + "</p>" 69 | + "<p>Lower case of " + uppercase + " is according to backend " + lowercase + "</p>" 70 | + "</body></html>"; 71 | }); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /plugin/src/it/advanced/frontend/src/test/java/com/spotify/it/frontend/MainIT.java: -------------------------------------------------------------------------------- 1 | /*- 2 | * -\-\- 3 | * Dockerfile Maven Plugin 4 | * -- 5 | * Copyright (C) 2016 Spotify AB 6 | * -- 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * -/-/- 19 | */ 20 | 21 | package com.spotify.it.frontend; 22 | 23 | import static org.hamcrest.MatcherAssert.assertThat; 24 | import static org.hamcrest.Matchers.containsString; 25 | import static org.hamcrest.Matchers.describedAs; 26 | import static org.hamcrest.Matchers.is; 27 | 28 | import com.google.common.base.Charsets; 29 | import com.google.common.io.CharStreams; 30 | import com.google.common.io.Files; 31 | import com.google.common.io.Resources; 32 | import java.io.File; 33 | import java.io.IOException; 34 | import java.io.InputStream; 35 | import java.io.InputStreamReader; 36 | import java.net.URI; 37 | import java.nio.charset.StandardCharsets; 38 | import java.util.regex.Matcher; 39 | import java.util.regex.Pattern; 40 | import org.junit.Before; 41 | import org.junit.Rule; 42 | import org.junit.Test; 43 | import org.slf4j.Logger; 44 | import org.slf4j.LoggerFactory; 45 | import org.testcontainers.containers.GenericContainer; 46 | import org.testcontainers.containers.Network; 47 | import org.testcontainers.containers.output.Slf4jLogConsumer; 48 | import org.testcontainers.containers.wait.strategy.Wait; 49 | 50 | public class MainIT { 51 | private static final Logger log = LoggerFactory.getLogger(MainIT.class); 52 | 53 | private static final int BACKEND_PORT = 1337; 54 | private static final int FRONTEND_PORT = 1338; 55 | 56 | /** 57 | * Create a Network that both containers are attached to. When the containers are setup, they have 58 | * .withNetworkAliases("foo") set, which allows the other container to refer to http://foo/ when 59 | * one container needs to talk to another. 60 | * 61 | * This is needed because container.getContainerIpAddress() is only for use for a test 62 | * to communicate with a container, not container-to-container communication - 63 | * getContainerIpAddress() will return "localhost" typically 64 | */ 65 | @Rule public final Network network = Network.newNetwork(); 66 | 67 | @Rule 68 | public final GenericContainer backendJob = createBackend(network); 69 | 70 | @Rule 71 | public final GenericContainer frontendJob = createFrontend(network); 72 | 73 | private GenericContainer createBackend(final Network network) { 74 | final String image; 75 | try { 76 | image = Resources.toString( 77 | Resources.getResource("META-INF/docker/com.spotify.it/backend/image-name"), 78 | Charsets.UTF_8).trim(); 79 | } catch (IOException e) { 80 | throw new RuntimeException(e); 81 | } 82 | 83 | final GenericContainer container = new GenericContainer(image) 84 | .withExposedPorts(BACKEND_PORT) 85 | .withNetwork(network) 86 | .withNetworkAliases("backend") 87 | .waitingFor(Wait.forHttp("/api/version")); 88 | 89 | // start early, since frontend needs to know the port of backend 90 | container.start(); 91 | 92 | return container; 93 | } 94 | 95 | private GenericContainer createFrontend(final Network network) { 96 | final String image; 97 | try { 98 | image = Files.readFirstLine(new File("target/docker/image-name"), Charsets.UTF_8); 99 | } catch (IOException e) { 100 | throw new RuntimeException(e); 101 | } 102 | 103 | return new GenericContainer(image) 104 | .withExposedPorts(1338) 105 | .withCommand("http://backend:" + BACKEND_PORT) 106 | .withNetwork(network) 107 | .withNetworkAliases("frontend"); 108 | } 109 | 110 | private URI frontend; 111 | private URI backend; 112 | 113 | @Before 114 | public void setUp() { 115 | backend = httpUri(backendJob, BACKEND_PORT); 116 | frontend = httpUri(frontendJob, FRONTEND_PORT); 117 | 118 | backendJob.followOutput(new Slf4jLogConsumer( 119 | LoggerFactory.getLogger(MainIT.class.getName() + ".backend"))); 120 | 121 | frontendJob.followOutput(new Slf4jLogConsumer( 122 | LoggerFactory.getLogger(MainIT.class.getName() + ".frontend"))); 123 | } 124 | 125 | private URI httpUri(GenericContainer container, int portNumber) { 126 | return URI.create("http://" + container.getContainerIpAddress() 127 | + ":" + container.getMappedPort(portNumber)); 128 | } 129 | 130 | @Test 131 | public void testVersion() throws Exception { 132 | String version = requestString(backend.resolve("/api/version")); 133 | String homepage = requestString(frontend.resolve("/")); 134 | 135 | assertThat(homepage, containsString("Backend version: " + version)); 136 | } 137 | 138 | @Test 139 | public void testLowercase() throws Exception { 140 | String homepage; 141 | homepage = requestString(frontend.resolve("/")); 142 | Pattern pattern = Pattern.compile("Lower case of ([^ <]+) is according to backend ([^ <]+)"); 143 | 144 | Matcher matcher = pattern.matcher(homepage); 145 | assertThat(matcher.find(), describedAs("the pattern was found", is(true))); 146 | assertThat(matcher.group(2), is(matcher.group(1).toLowerCase())); 147 | } 148 | 149 | private String requestString(URI uri) throws IOException { 150 | try (InputStream is = uri.toURL().openStream()) { 151 | return CharStreams.toString(new InputStreamReader(is, StandardCharsets.UTF_8)); 152 | } 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /plugin/src/it/advanced/invoker.properties: -------------------------------------------------------------------------------- 1 | ### 2 | # -/-/- 3 | # Dockerfile Maven Plugin 4 | # %% 5 | # Copyright (C) 2015 - 2016 Spotify AB 6 | # %% 7 | # Licensed under the Apache License, Version 2.0 (the "License"); 8 | # you may not use this file except in compliance with the License. 9 | # You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distributed on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | # -\-\- 19 | ### 20 | 21 | # Only run this test for Java 8+ 22 | invoker.java.version=1.8+ -------------------------------------------------------------------------------- /plugin/src/it/advanced/pom.xml: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <!-- 3 | -/-/- 4 | Dockerfile Maven Plugin 5 | %% 6 | Copyright (C) 2015 - 2016 Spotify AB 7 | %% 8 | Licensed under the Apache License, Version 2.0 (the "License"); 9 | you may not use this file except in compliance with the License. 10 | You may obtain a copy of the License at 11 | 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | Unless required by applicable law or agreed to in writing, software 15 | distributed under the License is distributed on an "AS IS" BASIS, 16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | See the License for the specific language governing permissions and 18 | limitations under the License. 19 | -\-\- 20 | --> 21 | 22 | <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 23 | xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 24 | <modelVersion>4.0.0</modelVersion> 25 | 26 | <groupId>com.spotify.it</groupId> 27 | <artifactId>advanced</artifactId> 28 | <version>1.0-SNAPSHOT</version> 29 | <packaging>pom</packaging> 30 | 31 | <description>This project is an advanced example, simulating a real use-case</description> 32 | 33 | <modules> 34 | <module>backend</module> 35 | <module>frontend</module> 36 | </modules> 37 | 38 | <build> 39 | <extensions> 40 | <extension> 41 | <groupId>@project.groupId@</groupId> 42 | <artifactId>dockerfile-maven-extension</artifactId> 43 | <version>@project.version@</version> 44 | </extension> 45 | </extensions> 46 | </build> 47 | </project> 48 | -------------------------------------------------------------------------------- /plugin/src/it/basic-lowercase-dockerfile/dockerfile: -------------------------------------------------------------------------------- 1 | FROM scratch 2 | MAINTAINER David Flemström <dflemstr@spotify.com> -------------------------------------------------------------------------------- /plugin/src/it/basic-lowercase-dockerfile/pom.xml: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <!-- 3 | -/-/- 4 | Dockerfile Maven Plugin 5 | %% 6 | Copyright (C) 2015 - 2016 Spotify AB 7 | %% 8 | Licensed under the Apache License, Version 2.0 (the "License"); 9 | you may not use this file except in compliance with the License. 10 | You may obtain a copy of the License at 11 | 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | Unless required by applicable law or agreed to in writing, software 15 | distributed under the License is distributed on an "AS IS" BASIS, 16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | See the License for the specific language governing permissions and 18 | limitations under the License. 19 | -\-\- 20 | --> 21 | 22 | <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 23 | xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 24 | <modelVersion>4.0.0</modelVersion> 25 | 26 | <groupId>com.spotify.it</groupId> 27 | <artifactId>basic-lowercase-dockerfile</artifactId> 28 | <version>1.0-SNAPSHOT</version> 29 | 30 | <description>A simple IT verifying the basic use case.</description> 31 | 32 | <properties> 33 | <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 34 | </properties> 35 | 36 | <build> 37 | <plugins> 38 | <plugin> 39 | <groupId>@project.groupId@</groupId> 40 | <artifactId>@project.artifactId@</artifactId> 41 | <version>@project.version@</version> 42 | <executions> 43 | <execution> 44 | <id>default</id> 45 | <goals> 46 | <goal>build</goal> 47 | </goals> 48 | </execution> 49 | </executions> 50 | </plugin> 51 | </plugins> 52 | </build> 53 | </project> 54 | -------------------------------------------------------------------------------- /plugin/src/it/basic-lowercase-dockerfile/verify.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * -/-/- 3 | * Dockerfile Maven Plugin 4 | * %% 5 | * Copyright (C) 2015 - 2016 Spotify AB 6 | * %% 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * -\-\- 19 | */ 20 | File imageIdFile = new File(basedir, "target/docker/image-id") 21 | assert imageIdFile.isFile() 22 | -------------------------------------------------------------------------------- /plugin/src/it/basic-with-build-args/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM hello-world 2 | MAINTAINER David Flemström <dflemstr@spotify.com> 3 | 4 | ARG IMAGE_VERSION 5 | 6 | LABEL version=${IMAGE_VERSION} 7 | -------------------------------------------------------------------------------- /plugin/src/it/basic-with-build-args/pom.xml: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <!-- 3 | -/-/- 4 | Dockerfile Maven Plugin 5 | %% 6 | Copyright (C) 2015 - 2016 Spotify AB 7 | %% 8 | Licensed under the Apache License, Version 2.0 (the "License"); 9 | you may not use this file except in compliance with the License. 10 | You may obtain a copy of the License at 11 | 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | Unless required by applicable law or agreed to in writing, software 15 | distributed under the License is distributed on an "AS IS" BASIS, 16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | See the License for the specific language governing permissions and 18 | limitations under the License. 19 | -\-\- 20 | --> 21 | 22 | <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 23 | xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 24 | <modelVersion>4.0.0</modelVersion> 25 | 26 | <groupId>com.spotify.it</groupId> 27 | <artifactId>basic-with-build-args</artifactId> 28 | <version>1.0-SNAPSHOT</version> 29 | 30 | <description>A simple IT verifying a basic use case with build arguments.</description> 31 | 32 | <properties> 33 | <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 34 | </properties> 35 | 36 | <build> 37 | <plugins> 38 | <plugin> 39 | <groupId>@project.groupId@</groupId> 40 | <artifactId>@project.artifactId@</artifactId> 41 | <version>@project.version@</version> 42 | <executions> 43 | <execution> 44 | <id>default</id> 45 | <goals> 46 | <goal>build</goal> 47 | </goals> 48 | </execution> 49 | </executions> 50 | <configuration> 51 | <buildArgs> 52 | <IMAGE_VERSION>0.0.1</IMAGE_VERSION> 53 | </buildArgs> 54 | </configuration> 55 | </plugin> 56 | </plugins> 57 | </build> 58 | </project> 59 | -------------------------------------------------------------------------------- /plugin/src/it/basic-with-build-args/verify.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * -/-/- 3 | * Dockerfile Maven Plugin 4 | * %% 5 | * Copyright (C) 2015 - 2016 Spotify AB 6 | * %% 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * -\-\- 19 | */ 20 | import com.spotify.docker.client.DefaultDockerClient 21 | 22 | File imageIdFile = new File(basedir, "target/docker/image-id") 23 | String imageId = imageIdFile.text.replaceAll("\\s", "") 24 | 25 | DefaultDockerClient dockerClient = DefaultDockerClient.fromEnv().build() 26 | imageInfo = dockerClient.inspectImage(imageId) 27 | 28 | assert imageInfo.config().labels().get("version") == "0.0.1" 29 | -------------------------------------------------------------------------------- /plugin/src/it/basic/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM scratch 2 | MAINTAINER David Flemström <dflemstr@spotify.com> -------------------------------------------------------------------------------- /plugin/src/it/basic/pom.xml: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <!-- 3 | -/-/- 4 | Dockerfile Maven Plugin 5 | %% 6 | Copyright (C) 2015 - 2016 Spotify AB 7 | %% 8 | Licensed under the Apache License, Version 2.0 (the "License"); 9 | you may not use this file except in compliance with the License. 10 | You may obtain a copy of the License at 11 | 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | Unless required by applicable law or agreed to in writing, software 15 | distributed under the License is distributed on an "AS IS" BASIS, 16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | See the License for the specific language governing permissions and 18 | limitations under the License. 19 | -\-\- 20 | --> 21 | 22 | <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 23 | xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 24 | <modelVersion>4.0.0</modelVersion> 25 | 26 | <groupId>com.spotify.it</groupId> 27 | <artifactId>basic</artifactId> 28 | <version>1.0-SNAPSHOT</version> 29 | 30 | <description>A simple IT verifying the basic use case.</description> 31 | 32 | <properties> 33 | <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 34 | </properties> 35 | 36 | <build> 37 | <plugins> 38 | <plugin> 39 | <groupId>@project.groupId@</groupId> 40 | <artifactId>@project.artifactId@</artifactId> 41 | <version>@project.version@</version> 42 | <executions> 43 | <execution> 44 | <id>default</id> 45 | <goals> 46 | <goal>build</goal> 47 | </goals> 48 | </execution> 49 | </executions> 50 | </plugin> 51 | </plugins> 52 | </build> 53 | </project> 54 | -------------------------------------------------------------------------------- /plugin/src/it/basic/verify.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * -/-/- 3 | * Dockerfile Maven Plugin 4 | * %% 5 | * Copyright (C) 2015 - 2016 Spotify AB 6 | * %% 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * -\-\- 19 | */ 20 | File imageIdFile = new File(basedir, "target/docker/image-id") 21 | assert imageIdFile.isFile() 22 | -------------------------------------------------------------------------------- /plugin/src/it/build-into-repository/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM scratch 2 | MAINTAINER David Flemström <dflemstr@spotify.com> -------------------------------------------------------------------------------- /plugin/src/it/build-into-repository/pom.xml: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <!-- 3 | -/-/- 4 | Dockerfile Maven Plugin 5 | %% 6 | Copyright (C) 2015 - 2016 Spotify AB 7 | %% 8 | Licensed under the Apache License, Version 2.0 (the "License"); 9 | you may not use this file except in compliance with the License. 10 | You may obtain a copy of the License at 11 | 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | Unless required by applicable law or agreed to in writing, software 15 | distributed under the License is distributed on an "AS IS" BASIS, 16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | See the License for the specific language governing permissions and 18 | limitations under the License. 19 | -\-\- 20 | --> 21 | 22 | <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 23 | xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 24 | <modelVersion>4.0.0</modelVersion> 25 | 26 | <groupId>com.spotify.it</groupId> 27 | <artifactId>built-into-repository</artifactId> 28 | <version>1.0-SNAPSHOT</version> 29 | 30 | <description>The Dockerfile is immediately put into a repository</description> 31 | 32 | <properties> 33 | <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 34 | </properties> 35 | 36 | <build> 37 | <plugins> 38 | <plugin> 39 | <groupId>@project.groupId@</groupId> 40 | <artifactId>@project.artifactId@</artifactId> 41 | <version>@project.version@</version> 42 | <executions> 43 | <execution> 44 | <id>default</id> 45 | <goals> 46 | <goal>build</goal> 47 | </goals> 48 | <configuration> 49 | <repository>test/build-into-repository</repository> 50 | </configuration> 51 | </execution> 52 | </executions> 53 | </plugin> 54 | </plugins> 55 | </build> 56 | </project> 57 | -------------------------------------------------------------------------------- /plugin/src/it/build-into-repository/verify.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * -/-/- 3 | * Dockerfile Maven Plugin 4 | * %% 5 | * Copyright (C) 2015 - 2016 Spotify AB 6 | * %% 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * -\-\- 19 | */ 20 | File imageIdFile = new File(basedir, "target/docker/image-id") 21 | assert imageIdFile.isFile() 22 | 23 | File repositoryFile = new File(basedir, "target/docker/repository") 24 | assert repositoryFile.text == "test/build-into-repository\n" 25 | 26 | File tagFile = new File(basedir, "target/docker/tag") 27 | assert tagFile.text == "latest\n" 28 | 29 | File imageNameFile = new File(basedir, "target/docker/image-name") 30 | assert imageNameFile.text == "test/build-into-repository:latest\n" 31 | -------------------------------------------------------------------------------- /plugin/src/it/build-into-tag/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM scratch 2 | MAINTAINER David Flemström <dflemstr@spotify.com> -------------------------------------------------------------------------------- /plugin/src/it/build-into-tag/pom.xml: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <!-- 3 | -/-/- 4 | Dockerfile Maven Plugin 5 | %% 6 | Copyright (C) 2015 - 2016 Spotify AB 7 | %% 8 | Licensed under the Apache License, Version 2.0 (the "License"); 9 | you may not use this file except in compliance with the License. 10 | You may obtain a copy of the License at 11 | 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | Unless required by applicable law or agreed to in writing, software 15 | distributed under the License is distributed on an "AS IS" BASIS, 16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | See the License for the specific language governing permissions and 18 | limitations under the License. 19 | -\-\- 20 | --> 21 | 22 | <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 23 | xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 24 | <modelVersion>4.0.0</modelVersion> 25 | 26 | <groupId>com.spotify.it</groupId> 27 | <artifactId>build-into-tag</artifactId> 28 | <version>1.0-SNAPSHOT</version> 29 | 30 | <description>The Dockerfile is built into a repository with a custom tag</description> 31 | 32 | <properties> 33 | <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 34 | </properties> 35 | 36 | <build> 37 | <plugins> 38 | <plugin> 39 | <groupId>@project.groupId@</groupId> 40 | <artifactId>@project.artifactId@</artifactId> 41 | <version>@project.version@</version> 42 | <executions> 43 | <execution> 44 | <id>default</id> 45 | <goals> 46 | <goal>build</goal> 47 | </goals> 48 | <configuration> 49 | <repository>test/build-into-tag</repository> 50 | <tag>unstable</tag> 51 | </configuration> 52 | </execution> 53 | </executions> 54 | </plugin> 55 | </plugins> 56 | </build> 57 | </project> 58 | -------------------------------------------------------------------------------- /plugin/src/it/build-into-tag/verify.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * -/-/- 3 | * Dockerfile Maven Plugin 4 | * %% 5 | * Copyright (C) 2015 - 2016 Spotify AB 6 | * %% 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * -\-\- 19 | */ 20 | File imageIdFile = new File(basedir, "target/docker/image-id") 21 | assert imageIdFile.isFile() 22 | 23 | File repositoryFile = new File(basedir, "target/docker/repository") 24 | assert repositoryFile.text == "test/build-into-tag\n" 25 | 26 | File tagFile = new File(basedir, "target/docker/tag") 27 | assert tagFile.text == "unstable\n" 28 | 29 | File imageNameFile = new File(basedir, "target/docker/image-name") 30 | assert imageNameFile.text == "test/build-into-tag:unstable\n" 31 | -------------------------------------------------------------------------------- /plugin/src/it/build-tag-version/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM scratch 2 | MAINTAINER David Flemström <dflemstr@spotify.com> -------------------------------------------------------------------------------- /plugin/src/it/build-tag-version/pom.xml: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <!-- 3 | -/-/- 4 | Dockerfile Maven Plugin 5 | %% 6 | Copyright (C) 2015 - 2016 Spotify AB 7 | %% 8 | Licensed under the Apache License, Version 2.0 (the "License"); 9 | you may not use this file except in compliance with the License. 10 | You may obtain a copy of the License at 11 | 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | Unless required by applicable law or agreed to in writing, software 15 | distributed under the License is distributed on an "AS IS" BASIS, 16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | See the License for the specific language governing permissions and 18 | limitations under the License. 19 | -\-\- 20 | --> 21 | 22 | <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 23 | xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 24 | <modelVersion>4.0.0</modelVersion> 25 | 26 | <groupId>com.spotify.it</groupId> 27 | <artifactId>build-tag-version</artifactId> 28 | <version>1.2.3-SNAPSHOT</version> 29 | 30 | <description>The Dockerfile is built, and later tagged with the project version.</description> 31 | 32 | <properties> 33 | <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 34 | </properties> 35 | 36 | <build> 37 | <plugins> 38 | <plugin> 39 | <groupId>@project.groupId@</groupId> 40 | <artifactId>@project.artifactId@</artifactId> 41 | <version>@project.version@</version> 42 | <executions> 43 | <execution> 44 | <id>build</id> 45 | <goals> 46 | <goal>build</goal> 47 | </goals> 48 | </execution> 49 | <execution> 50 | <id>tag</id> 51 | <goals> 52 | <goal>tag</goal> 53 | </goals> 54 | <configuration> 55 | <repository>test/build-tag-version</repository> 56 | <tag>${project.version}</tag> 57 | </configuration> 58 | </execution> 59 | </executions> 60 | </plugin> 61 | </plugins> 62 | </build> 63 | </project> 64 | -------------------------------------------------------------------------------- /plugin/src/it/build-tag-version/verify.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * -/-/- 3 | * Dockerfile Maven Plugin 4 | * %% 5 | * Copyright (C) 2015 - 2016 Spotify AB 6 | * %% 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * -\-\- 19 | */ 20 | File imageIdFile = new File(basedir, "target/docker/image-id") 21 | assert imageIdFile.isFile() 22 | 23 | File repositoryFile = new File(basedir, "target/docker/repository") 24 | assert repositoryFile.text == "test/build-tag-version\n" 25 | 26 | File tagFile = new File(basedir, "target/docker/tag") 27 | assert tagFile.text == "1.2.3-SNAPSHOT\n" 28 | 29 | File imageNameFile = new File(basedir, "target/docker/image-name") 30 | assert imageNameFile.text == "test/build-tag-version:1.2.3-SNAPSHOT\n" 31 | -------------------------------------------------------------------------------- /plugin/src/it/build-then-add-repository/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM scratch 2 | MAINTAINER David Flemström <dflemstr@spotify.com> -------------------------------------------------------------------------------- /plugin/src/it/build-then-add-repository/pom.xml: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <!-- 3 | -/-/- 4 | Dockerfile Maven Plugin 5 | %% 6 | Copyright (C) 2015 - 2016 Spotify AB 7 | %% 8 | Licensed under the Apache License, Version 2.0 (the "License"); 9 | you may not use this file except in compliance with the License. 10 | You may obtain a copy of the License at 11 | 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | Unless required by applicable law or agreed to in writing, software 15 | distributed under the License is distributed on an "AS IS" BASIS, 16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | See the License for the specific language governing permissions and 18 | limitations under the License. 19 | -\-\- 20 | --> 21 | 22 | <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 23 | xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 24 | <modelVersion>4.0.0</modelVersion> 25 | 26 | <groupId>com.spotify.it</groupId> 27 | <artifactId>build-then-add-repository</artifactId> 28 | <version>1.0-SNAPSHOT</version> 29 | 30 | <description>The Dockerfile is built, and later put into a repository</description> 31 | 32 | <properties> 33 | <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 34 | </properties> 35 | 36 | <build> 37 | <plugins> 38 | <plugin> 39 | <groupId>@project.groupId@</groupId> 40 | <artifactId>@project.artifactId@</artifactId> 41 | <version>@project.version@</version> 42 | <executions> 43 | <execution> 44 | <id>build</id> 45 | <goals> 46 | <goal>build</goal> 47 | </goals> 48 | </execution> 49 | <execution> 50 | <id>tag</id> 51 | <goals> 52 | <goal>tag</goal> 53 | </goals> 54 | <configuration> 55 | <repository>test/build-then-add-repository</repository> 56 | </configuration> 57 | </execution> 58 | </executions> 59 | </plugin> 60 | </plugins> 61 | </build> 62 | </project> 63 | -------------------------------------------------------------------------------- /plugin/src/it/build-then-add-repository/verify.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * -/-/- 3 | * Dockerfile Maven Plugin 4 | * %% 5 | * Copyright (C) 2015 - 2016 Spotify AB 6 | * %% 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * -\-\- 19 | */ 20 | File imageIdFile = new File(basedir, "target/docker/image-id") 21 | assert imageIdFile.isFile() 22 | 23 | File repositoryFile = new File(basedir, "target/docker/repository") 24 | assert repositoryFile.text == "test/build-then-add-repository\n" 25 | 26 | File tagFile = new File(basedir, "target/docker/tag") 27 | assert tagFile.text == "latest\n" 28 | 29 | File imageNameFile = new File(basedir, "target/docker/image-name") 30 | assert imageNameFile.text == "test/build-then-add-repository:latest\n" 31 | -------------------------------------------------------------------------------- /plugin/src/it/build-then-add-tag/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM scratch 2 | MAINTAINER David Flemström <dflemstr@spotify.com> -------------------------------------------------------------------------------- /plugin/src/it/build-then-add-tag/pom.xml: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <!-- 3 | -/-/- 4 | Dockerfile Maven Plugin 5 | %% 6 | Copyright (C) 2015 - 2016 Spotify AB 7 | %% 8 | Licensed under the Apache License, Version 2.0 (the "License"); 9 | you may not use this file except in compliance with the License. 10 | You may obtain a copy of the License at 11 | 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | Unless required by applicable law or agreed to in writing, software 15 | distributed under the License is distributed on an "AS IS" BASIS, 16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | See the License for the specific language governing permissions and 18 | limitations under the License. 19 | -\-\- 20 | --> 21 | 22 | <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 23 | xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 24 | <modelVersion>4.0.0</modelVersion> 25 | 26 | <groupId>com.spotify.it</groupId> 27 | <artifactId>build-then-add-tag</artifactId> 28 | <version>1.0-SNAPSHOT</version> 29 | 30 | <description>The Dockerfile is built, and later put into a repository with a tag.</description> 31 | 32 | <properties> 33 | <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 34 | </properties> 35 | 36 | <build> 37 | <plugins> 38 | <plugin> 39 | <groupId>@project.groupId@</groupId> 40 | <artifactId>@project.artifactId@</artifactId> 41 | <version>@project.version@</version> 42 | <executions> 43 | <execution> 44 | <id>build</id> 45 | <goals> 46 | <goal>build</goal> 47 | </goals> 48 | </execution> 49 | <execution> 50 | <id>tag</id> 51 | <goals> 52 | <goal>tag</goal> 53 | </goals> 54 | <configuration> 55 | <repository>test/build-then-add-tag</repository> 56 | <tag>unstable</tag> 57 | </configuration> 58 | </execution> 59 | </executions> 60 | </plugin> 61 | </plugins> 62 | </build> 63 | </project> 64 | -------------------------------------------------------------------------------- /plugin/src/it/build-then-add-tag/verify.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * -/-/- 3 | * Dockerfile Maven Plugin 4 | * %% 5 | * Copyright (C) 2015 - 2016 Spotify AB 6 | * %% 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * -\-\- 19 | */ 20 | File imageIdFile = new File(basedir, "target/docker/image-id") 21 | assert imageIdFile.isFile() 22 | 23 | File repositoryFile = new File(basedir, "target/docker/repository") 24 | assert repositoryFile.text == "test/build-then-add-tag\n" 25 | 26 | File tagFile = new File(basedir, "target/docker/tag") 27 | assert tagFile.text == "unstable\n" 28 | 29 | File imageNameFile = new File(basedir, "target/docker/image-name") 30 | assert imageNameFile.text == "test/build-then-add-tag:unstable\n" 31 | -------------------------------------------------------------------------------- /plugin/src/it/build-with-custom-dockerfile/context/resources/foo.txt: -------------------------------------------------------------------------------- 1 | bar -------------------------------------------------------------------------------- /plugin/src/it/build-with-custom-dockerfile/context/sub/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM scratch 2 | ADD resources/foo.txt /foo.txt 3 | MAINTAINER David Flemström <dflemstr@spotify.com> -------------------------------------------------------------------------------- /plugin/src/it/build-with-custom-dockerfile/pom.xml: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <!-- 3 | -/-/- 4 | Dockerfile Maven Plugin 5 | %% 6 | Copyright (C) 2015 - 2016 Spotify AB 7 | %% 8 | Licensed under the Apache License, Version 2.0 (the "License"); 9 | you may not use this file except in compliance with the License. 10 | You may obtain a copy of the License at 11 | 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | Unless required by applicable law or agreed to in writing, software 15 | distributed under the License is distributed on an "AS IS" BASIS, 16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | See the License for the specific language governing permissions and 18 | limitations under the License. 19 | -\-\- 20 | --> 21 | 22 | <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 23 | xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 24 | <modelVersion>4.0.0</modelVersion> 25 | 26 | <groupId>com.spotify.it</groupId> 27 | <artifactId>build-with-custom-dockerfile</artifactId> 28 | <version>1.0-SNAPSHOT</version> 29 | 30 | <description>The Dockerfile is manually specified by the user</description> 31 | 32 | <properties> 33 | <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 34 | </properties> 35 | 36 | <build> 37 | <plugins> 38 | <plugin> 39 | <groupId>@project.groupId@</groupId> 40 | <artifactId>@project.artifactId@</artifactId> 41 | <version>@project.version@</version> 42 | <executions> 43 | <execution> 44 | <id>default</id> 45 | <goals> 46 | <goal>build</goal> 47 | </goals> 48 | <configuration> 49 | <repository>test/build-with-custom-dockerfile</repository> 50 | <contextDirectory>context</contextDirectory> 51 | <dockerfile>context/sub/Dockerfile</dockerfile> 52 | </configuration> 53 | </execution> 54 | </executions> 55 | </plugin> 56 | </plugins> 57 | </build> 58 | </project> 59 | -------------------------------------------------------------------------------- /plugin/src/it/build-with-custom-dockerfile/verify.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * -/-/- 3 | * Dockerfile Maven Plugin 4 | * %% 5 | * Copyright (C) 2015 - 2016 Spotify AB 6 | * %% 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * -\-\- 19 | */ 20 | File imageIdFile = new File(basedir, "target/docker/image-id") 21 | assert imageIdFile.isFile() 22 | 23 | File repositoryFile = new File(basedir, "target/docker/repository") 24 | assert repositoryFile.text == "test/build-with-custom-dockerfile\n" 25 | 26 | File tagFile = new File(basedir, "target/docker/tag") 27 | assert tagFile.text == "latest\n" 28 | 29 | File imageNameFile = new File(basedir, "target/docker/image-name") 30 | assert imageNameFile.text == "test/build-with-custom-dockerfile:latest\n" 31 | -------------------------------------------------------------------------------- /plugin/src/it/illegal-custom-dockerfile-location/context/foo.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spotify/dockerfile-maven/986f960cb82085d2f666acd6c2682672d47f5bb0/plugin/src/it/illegal-custom-dockerfile-location/context/foo.txt -------------------------------------------------------------------------------- /plugin/src/it/illegal-custom-dockerfile-location/invoker.properties: -------------------------------------------------------------------------------- 1 | ### 2 | # -/-/- 3 | # Dockerfile Maven Plugin 4 | # %% 5 | # Copyright (C) 2015 - 2016 Spotify AB 6 | # %% 7 | # Licensed under the Apache License, Version 2.0 (the "License"); 8 | # you may not use this file except in compliance with the License. 9 | # You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distributed on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | # -\-\- 19 | ### 20 | invoker.buildResult=failure 21 | -------------------------------------------------------------------------------- /plugin/src/it/illegal-custom-dockerfile-location/not-context/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM scratch 2 | MAINTAINER David Flemström <dflemstr@spotify.com> -------------------------------------------------------------------------------- /plugin/src/it/illegal-custom-dockerfile-location/pom.xml: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <!-- 3 | -/-/- 4 | Dockerfile Maven Plugin 5 | %% 6 | Copyright (C) 2015 - 2016 Spotify AB 7 | %% 8 | Licensed under the Apache License, Version 2.0 (the "License"); 9 | you may not use this file except in compliance with the License. 10 | You may obtain a copy of the License at 11 | 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | Unless required by applicable law or agreed to in writing, software 15 | distributed under the License is distributed on an "AS IS" BASIS, 16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | See the License for the specific language governing permissions and 18 | limitations under the License. 19 | -\-\- 20 | --> 21 | 22 | <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 23 | xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 24 | <modelVersion>4.0.0</modelVersion> 25 | 26 | <groupId>com.spotify.it</groupId> 27 | <artifactId>illegal-custom-dockerfile-location</artifactId> 28 | <version>1.0-SNAPSHOT</version> 29 | 30 | <description> 31 | A simple IT verifying it fails gracefully when a user defined dockerfile is not 32 | located inside of the context directory. 33 | </description> 34 | 35 | <properties> 36 | <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 37 | </properties> 38 | 39 | <build> 40 | <plugins> 41 | <plugin> 42 | <groupId>@project.groupId@</groupId> 43 | <artifactId>@project.artifactId@</artifactId> 44 | <version>@project.version@</version> 45 | <executions> 46 | <execution> 47 | <id>default</id> 48 | <goals> 49 | <goal>build</goal> 50 | </goals> 51 | <configuration> 52 | <contextDirectory>context</contextDirectory> 53 | <dockerfile>not-context/Dockerfile</dockerfile> 54 | </configuration> 55 | </execution> 56 | </executions> 57 | </plugin> 58 | </plugins> 59 | </build> 60 | </project> 61 | -------------------------------------------------------------------------------- /plugin/src/it/illegal-custom-dockerfile-location/verify.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * -/-/- 3 | * Dockerfile Maven Plugin 4 | * %% 5 | * Copyright (C) 2015 - 2016 Spotify AB 6 | * %% 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * -\-\- 19 | */ 20 | String buildLog = new File("${basedir}/build.log").getText("UTF-8") 21 | assert buildLog.contains("is not a child of the context directory") 22 | -------------------------------------------------------------------------------- /plugin/src/it/maven-settings-auth/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM scratch 2 | MAINTAINER David Flemström <dflemstr@spotify.com> -------------------------------------------------------------------------------- /plugin/src/it/maven-settings-auth/auth.properties: -------------------------------------------------------------------------------- 1 | # This system property overrides the path used for the settings-security.xml file. 2 | settings.security=settings-security.xml -------------------------------------------------------------------------------- /plugin/src/it/maven-settings-auth/invoker.properties: -------------------------------------------------------------------------------- 1 | ### 2 | # -/-/- 3 | # Dockerfile Maven Plugin 4 | # %% 5 | # Copyright (C) 2015 - 2018 Spotify AB 6 | # %% 7 | # Licensed under the Apache License, Version 2.0 (the "License"); 8 | # you may not use this file except in compliance with the License. 9 | # You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distributed on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | # -\-\- 19 | ### 20 | 21 | # The build will fail as we're pushing to a nonexistent Docker registry. 22 | invoker.buildResult=failure 23 | 24 | # Enable debug logging so that we can assert that the Maven server password was successfully 25 | # decrypted. 26 | invoker.debug=true 27 | 28 | # The deploy phase runs the dockerfile:push goal. 29 | invoker.goals=deploy 30 | 31 | # Overrides the path to settings-security.xml, which contains an encrypted master password. 32 | # See https://maven.apache.org/guides/mini/guide-encryption.html for more details. 33 | invoker.systemPropertiesFile=auth.properties -------------------------------------------------------------------------------- /plugin/src/it/maven-settings-auth/pom.xml: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <!-- 3 | -/-/- 4 | Dockerfile Maven Plugin 5 | %% 6 | Copyright (C) 2015 - 2018 Spotify AB 7 | %% 8 | Licensed under the Apache License, Version 2.0 (the "License"); 9 | you may not use this file except in compliance with the License. 10 | You may obtain a copy of the License at 11 | 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | Unless required by applicable law or agreed to in writing, software 15 | distributed under the License is distributed on an "AS IS" BASIS, 16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | See the License for the specific language governing permissions and 18 | limitations under the License. 19 | -\-\- 20 | --> 21 | 22 | <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 23 | xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 24 | <modelVersion>4.0.0</modelVersion> 25 | 26 | <groupId>com.spotify.it</groupId> 27 | <artifactId>maven-settings-auth</artifactId> 28 | <version>1.0-SNAPSHOT</version> 29 | 30 | <description>Tests Docker registry authentication using an encrypted password in the Maven 31 | settings.xml file. 32 | </description> 33 | 34 | <properties> 35 | <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 36 | <maven.deploy.skip>true</maven.deploy.skip> 37 | </properties> 38 | 39 | <build> 40 | <plugins> 41 | <plugin> 42 | <groupId>@project.groupId@</groupId> 43 | <artifactId>@project.artifactId@</artifactId> 44 | <version>@project.version@</version> 45 | <executions> 46 | <execution> 47 | <id>default</id> 48 | <goals> 49 | <goal>build</goal> 50 | <goal>push</goal> 51 | </goals> 52 | </execution> 53 | </executions> 54 | <configuration> 55 | <repository>example.com/test/build</repository> 56 | <useMavenSettingsForAuth>true</useMavenSettingsForAuth> 57 | <googleContainerRegistryEnabled>false</googleContainerRegistryEnabled> 58 | </configuration> 59 | </plugin> 60 | </plugins> 61 | </build> 62 | </project> 63 | -------------------------------------------------------------------------------- /plugin/src/it/maven-settings-auth/settings-security.xml: -------------------------------------------------------------------------------- 1 | <!-- 2 | Contains the encrypted master password used to encrypt/decrypt server passwords in the 3 | Maven settings.xml file. 4 | 5 | See https://maven.apache.org/guides/mini/guide-encryption.html for more details. 6 | --> 7 | <settingsSecurity> 8 | <master>{fPB6uDF2BxcH5tT+mSXLWpd1tNw+TABncl/cf+uQQbw=}</master> 9 | </settingsSecurity> -------------------------------------------------------------------------------- /plugin/src/it/maven-settings-auth/verify.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * -/-/- 3 | * Dockerfile Maven Plugin 4 | * %% 5 | * Copyright (C) 2015 - 2018 Spotify AB 6 | * %% 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * -\-\- 19 | */ 20 | 21 | // Asserts that Maven server password decryption was successful. 22 | String buildLog = new File("${basedir}/build.log").getText("UTF-8") 23 | assert buildLog.contains("[DEBUG] Successfully decrypted Maven server password") -------------------------------------------------------------------------------- /plugin/src/it/missing-custom-dockerfile/invoker.properties: -------------------------------------------------------------------------------- 1 | ### 2 | # -/-/- 3 | # Dockerfile Maven Plugin 4 | # %% 5 | # Copyright (C) 2015 - 2016 Spotify AB 6 | # %% 7 | # Licensed under the Apache License, Version 2.0 (the "License"); 8 | # you may not use this file except in compliance with the License. 9 | # You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distributed on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | # -\-\- 19 | ### 20 | invoker.buildResult=failure 21 | -------------------------------------------------------------------------------- /plugin/src/it/missing-custom-dockerfile/pom.xml: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <!-- 3 | -/-/- 4 | Dockerfile Maven Plugin 5 | %% 6 | Copyright (C) 2015 - 2016 Spotify AB 7 | %% 8 | Licensed under the Apache License, Version 2.0 (the "License"); 9 | you may not use this file except in compliance with the License. 10 | You may obtain a copy of the License at 11 | 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | Unless required by applicable law or agreed to in writing, software 15 | distributed under the License is distributed on an "AS IS" BASIS, 16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | See the License for the specific language governing permissions and 18 | limitations under the License. 19 | -\-\- 20 | --> 21 | 22 | <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 23 | xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 24 | <modelVersion>4.0.0</modelVersion> 25 | 26 | <groupId>com.spotify.it</groupId> 27 | <artifactId>missing-custom-dockerfile</artifactId> 28 | <version>1.0-SNAPSHOT</version> 29 | 30 | <description>A simple IT verifying it fails gracefully when a user defined dockerfile is not found.</description> 31 | 32 | <properties> 33 | <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 34 | </properties> 35 | 36 | <build> 37 | <plugins> 38 | <plugin> 39 | <groupId>@project.groupId@</groupId> 40 | <artifactId>@project.artifactId@</artifactId> 41 | <version>@project.version@</version> 42 | <executions> 43 | <execution> 44 | <id>default</id> 45 | <goals> 46 | <goal>build</goal> 47 | </goals> 48 | <configuration> 49 | <dockerfile>Custom</dockerfile> 50 | </configuration> 51 | </execution> 52 | </executions> 53 | </plugin> 54 | </plugins> 55 | </build> 56 | </project> 57 | -------------------------------------------------------------------------------- /plugin/src/it/missing-custom-dockerfile/verify.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * -/-/- 3 | * Dockerfile Maven Plugin 4 | * %% 5 | * Copyright (C) 2015 - 2016 Spotify AB 6 | * %% 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * -\-\- 19 | */ 20 | String buildLog = new File("${basedir}/build.log").getText("UTF-8") 21 | assert buildLog.contains("Missing Dockerfile at") 22 | -------------------------------------------------------------------------------- /plugin/src/it/missing-dockerfile/invoker.properties: -------------------------------------------------------------------------------- 1 | ### 2 | # -/-/- 3 | # Dockerfile Maven Plugin 4 | # %% 5 | # Copyright (C) 2015 - 2016 Spotify AB 6 | # %% 7 | # Licensed under the Apache License, Version 2.0 (the "License"); 8 | # you may not use this file except in compliance with the License. 9 | # You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distributed on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | # -\-\- 19 | ### 20 | invoker.buildResult=failure 21 | -------------------------------------------------------------------------------- /plugin/src/it/missing-dockerfile/pom.xml: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <!-- 3 | -/-/- 4 | Dockerfile Maven Plugin 5 | %% 6 | Copyright (C) 2015 - 2016 Spotify AB 7 | %% 8 | Licensed under the Apache License, Version 2.0 (the "License"); 9 | you may not use this file except in compliance with the License. 10 | You may obtain a copy of the License at 11 | 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | Unless required by applicable law or agreed to in writing, software 15 | distributed under the License is distributed on an "AS IS" BASIS, 16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | See the License for the specific language governing permissions and 18 | limitations under the License. 19 | -\-\- 20 | --> 21 | 22 | <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 23 | xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 24 | <modelVersion>4.0.0</modelVersion> 25 | 26 | <groupId>com.spotify.it</groupId> 27 | <artifactId>missing-dockerfile</artifactId> 28 | <version>1.0-SNAPSHOT</version> 29 | 30 | <description>A simple IT verifying it fails gracefully when the dockerfile is not found.</description> 31 | 32 | <properties> 33 | <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 34 | </properties> 35 | 36 | <build> 37 | <plugins> 38 | <plugin> 39 | <groupId>@project.groupId@</groupId> 40 | <artifactId>@project.artifactId@</artifactId> 41 | <version>@project.version@</version> 42 | <executions> 43 | <execution> 44 | <id>default</id> 45 | <goals> 46 | <goal>build</goal> 47 | </goals> 48 | </execution> 49 | </executions> 50 | </plugin> 51 | </plugins> 52 | </build> 53 | </project> 54 | -------------------------------------------------------------------------------- /plugin/src/it/missing-dockerfile/verify.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * -/-/- 3 | * Dockerfile Maven Plugin 4 | * %% 5 | * Copyright (C) 2015 - 2016 Spotify AB 6 | * %% 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * -\-\- 19 | */ 20 | String buildLog = new File("${basedir}/build.log").getText("UTF-8") 21 | assert buildLog.contains("Missing Dockerfile in context directory") 22 | -------------------------------------------------------------------------------- /plugin/src/it/multi-module/a/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM scratch 2 | MAINTAINER David Flemström <dflemstr@spotify.com> -------------------------------------------------------------------------------- /plugin/src/it/multi-module/a/pom.xml: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <!-- 3 | -/-/- 4 | Dockerfile Maven Plugin 5 | %% 6 | Copyright (C) 2015 - 2016 Spotify AB 7 | %% 8 | Licensed under the Apache License, Version 2.0 (the "License"); 9 | you may not use this file except in compliance with the License. 10 | You may obtain a copy of the License at 11 | 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | Unless required by applicable law or agreed to in writing, software 15 | distributed under the License is distributed on an "AS IS" BASIS, 16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | See the License for the specific language governing permissions and 18 | limitations under the License. 19 | -\-\- 20 | --> 21 | 22 | <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 23 | xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 24 | <modelVersion>4.0.0</modelVersion> 25 | 26 | <parent> 27 | <groupId>com.spotify.it</groupId> 28 | <artifactId>multi-module</artifactId> 29 | <version>1.0-SNAPSHOT</version> 30 | </parent> 31 | 32 | <artifactId>a</artifactId> 33 | 34 | <description>The first module</description> 35 | 36 | <properties> 37 | <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 38 | </properties> 39 | 40 | <build> 41 | <plugins> 42 | <plugin> 43 | <groupId>@project.groupId@</groupId> 44 | <artifactId>@project.artifactId@</artifactId> 45 | <version>@project.version@</version> 46 | <executions> 47 | <execution> 48 | <id>default</id> 49 | <goals> 50 | <goal>build</goal> 51 | </goals> 52 | <configuration> 53 | <repository>test/multi-module-a</repository> 54 | <tag>unstable</tag> 55 | </configuration> 56 | </execution> 57 | </executions> 58 | </plugin> 59 | </plugins> 60 | </build> 61 | </project> 62 | -------------------------------------------------------------------------------- /plugin/src/it/multi-module/b/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM scratch 2 | MAINTAINER David Flemström <dflemstr@spotify.com> -------------------------------------------------------------------------------- /plugin/src/it/multi-module/b/pom.xml: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <!-- 3 | -/-/- 4 | Dockerfile Maven Plugin 5 | %% 6 | Copyright (C) 2015 - 2016 Spotify AB 7 | %% 8 | Licensed under the Apache License, Version 2.0 (the "License"); 9 | you may not use this file except in compliance with the License. 10 | You may obtain a copy of the License at 11 | 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | Unless required by applicable law or agreed to in writing, software 15 | distributed under the License is distributed on an "AS IS" BASIS, 16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | See the License for the specific language governing permissions and 18 | limitations under the License. 19 | -\-\- 20 | --> 21 | 22 | <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 23 | xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 24 | <modelVersion>4.0.0</modelVersion> 25 | 26 | <parent> 27 | <groupId>com.spotify.it</groupId> 28 | <artifactId>multi-module</artifactId> 29 | <version>1.0-SNAPSHOT</version> 30 | </parent> 31 | 32 | <artifactId>b</artifactId> 33 | 34 | <description>The second module</description> 35 | 36 | <properties> 37 | <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 38 | </properties> 39 | 40 | <dependencies> 41 | <dependency> 42 | <groupId>com.spotify.it</groupId> 43 | <artifactId>a</artifactId> 44 | <version>1.0-SNAPSHOT</version> 45 | <type>docker-info</type> 46 | </dependency> 47 | </dependencies> 48 | 49 | <build> 50 | <plugins> 51 | <plugin> 52 | <artifactId>maven-dependency-plugin</artifactId> 53 | <executions> 54 | <execution> 55 | <goals> 56 | <goal>unpack-dependencies</goal> 57 | </goals> 58 | <configuration> 59 | <classifier>docker-info</classifier> 60 | <outputDirectory>${project.build.directory}/docker-info-deps</outputDirectory> 61 | </configuration> 62 | </execution> 63 | </executions> 64 | </plugin> 65 | </plugins> 66 | </build> 67 | </project> 68 | -------------------------------------------------------------------------------- /plugin/src/it/multi-module/pom.xml: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <!-- 3 | -/-/- 4 | Dockerfile Maven Plugin 5 | %% 6 | Copyright (C) 2015 - 2016 Spotify AB 7 | %% 8 | Licensed under the Apache License, Version 2.0 (the "License"); 9 | you may not use this file except in compliance with the License. 10 | You may obtain a copy of the License at 11 | 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | Unless required by applicable law or agreed to in writing, software 15 | distributed under the License is distributed on an "AS IS" BASIS, 16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | See the License for the specific language governing permissions and 18 | limitations under the License. 19 | -\-\- 20 | --> 21 | 22 | <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 23 | xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 24 | <modelVersion>4.0.0</modelVersion> 25 | 26 | <groupId>com.spotify.it</groupId> 27 | <artifactId>multi-module</artifactId> 28 | <version>1.0-SNAPSHOT</version> 29 | <packaging>pom</packaging> 30 | 31 | <description>This project has two modules that depend on each other.</description> 32 | 33 | <modules> 34 | <module>a</module> 35 | <module>b</module> 36 | </modules> 37 | 38 | <build> 39 | <extensions> 40 | <extension> 41 | <groupId>@project.groupId@</groupId> 42 | <artifactId>dockerfile-maven-extension</artifactId> 43 | <version>@project.version@</version> 44 | </extension> 45 | </extensions> 46 | </build> 47 | </project> 48 | -------------------------------------------------------------------------------- /plugin/src/it/multi-module/verify.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * -/-/- 3 | * Dockerfile Maven Plugin 4 | * %% 5 | * Copyright (C) 2015 - 2016 Spotify AB 6 | * %% 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * -\-\- 19 | */ 20 | File imageIdFile = new File(basedir, "b/target/docker-info-deps/META-INF/docker/com.spotify.it/a/image-id") 21 | assert imageIdFile.isFile() 22 | 23 | File repositoryFile = new File(basedir, "b/target/docker-info-deps/META-INF/docker/com.spotify.it/a/repository") 24 | assert repositoryFile.text == "test/multi-module-a\n" 25 | 26 | File tagFile = new File(basedir, "b/target/docker-info-deps/META-INF/docker/com.spotify.it/a/tag") 27 | assert tagFile.text == "unstable\n" 28 | 29 | File imageNameFile = new File(basedir, "b/target/docker-info-deps/META-INF/docker/com.spotify.it/a/image-name") 30 | assert imageNameFile.text == "test/multi-module-a:unstable\n" 31 | -------------------------------------------------------------------------------- /plugin/src/it/settings.xml: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <!-- 3 | -/-/- 4 | Dockerfile Maven Plugin 5 | %% 6 | Copyright (C) 2015 - 2016 Spotify AB 7 | %% 8 | Licensed under the Apache License, Version 2.0 (the "License"); 9 | you may not use this file except in compliance with the License. 10 | You may obtain a copy of the License at 11 | 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | Unless required by applicable law or agreed to in writing, software 15 | distributed under the License is distributed on an "AS IS" BASIS, 16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | See the License for the specific language governing permissions and 18 | limitations under the License. 19 | -\-\- 20 | --> 21 | 22 | 23 | <settings> 24 | <profiles> 25 | <profile> 26 | <id>it-repo</id> 27 | <activation> 28 | <activeByDefault>true</activeByDefault> 29 | </activation> 30 | <repositories> 31 | <repository> 32 | <id>local.central</id> 33 | <url>@localRepositoryUrl@</url> 34 | <releases> 35 | <enabled>true</enabled> 36 | </releases> 37 | <snapshots> 38 | <enabled>true</enabled> 39 | </snapshots> 40 | </repository> 41 | </repositories> 42 | <pluginRepositories> 43 | <pluginRepository> 44 | <id>local.central</id> 45 | <url>@localRepositoryUrl@</url> 46 | <releases> 47 | <enabled>true</enabled> 48 | </releases> 49 | <snapshots> 50 | <enabled>true</enabled> 51 | </snapshots> 52 | </pluginRepository> 53 | </pluginRepositories> 54 | </profile> 55 | </profiles> 56 | 57 | <servers> 58 | <!-- Nonexistent Docker registry server used for testing authentication. --> 59 | <server> 60 | <username>testuser</username> 61 | <password>{oZT21IwPcEkHpuwQX3oZdg/NZHHOL69SDb5vJXxxixU=}</password> 62 | <id>example.com</id> 63 | </server> 64 | </servers> 65 | </settings> 66 | -------------------------------------------------------------------------------- /plugin/src/it/skip/pom.xml: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <!-- 3 | -/-/- 4 | Dockerfile Maven Plugin 5 | %% 6 | Copyright (C) 2015 - 2016 Spotify AB 7 | %% 8 | Licensed under the Apache License, Version 2.0 (the "License"); 9 | you may not use this file except in compliance with the License. 10 | You may obtain a copy of the License at 11 | 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | Unless required by applicable law or agreed to in writing, software 15 | distributed under the License is distributed on an "AS IS" BASIS, 16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | See the License for the specific language governing permissions and 18 | limitations under the License. 19 | -\-\- 20 | --> 21 | 22 | <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 23 | xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 24 | <modelVersion>4.0.0</modelVersion> 25 | 26 | <groupId>com.spotify.it</groupId> 27 | <artifactId>skip</artifactId> 28 | <version>1.0-SNAPSHOT</version> 29 | 30 | <description>The skip flag should disable the build goal</description> 31 | 32 | <properties> 33 | <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 34 | </properties> 35 | 36 | <build> 37 | <plugins> 38 | <plugin> 39 | <groupId>@project.groupId@</groupId> 40 | <artifactId>@project.artifactId@</artifactId> 41 | <version>@project.version@</version> 42 | <executions> 43 | <execution> 44 | <id>default</id> 45 | <goals> 46 | <goal>build</goal> 47 | </goals> 48 | </execution> 49 | </executions> 50 | <configuration> 51 | <skip>true</skip> 52 | </configuration> 53 | </plugin> 54 | </plugins> 55 | </build> 56 | </project> 57 | -------------------------------------------------------------------------------- /plugin/src/it/skip/verify.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * -/-/- 3 | * Dockerfile Maven Plugin 4 | * %% 5 | * Copyright (C) 2015 - 2016 Spotify AB 6 | * %% 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * -\-\- 19 | */ 20 | File imageIdFile = new File(basedir, "target/docker/image-id") 21 | assert !imageIdFile.exists() 22 | -------------------------------------------------------------------------------- /plugin/src/it/writes-test-classpath/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM scratch 2 | MAINTAINER David Flemström <dflemstr@spotify.com> -------------------------------------------------------------------------------- /plugin/src/it/writes-test-classpath/pom.xml: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <!-- 3 | -/-/- 4 | Dockerfile Maven Plugin 5 | %% 6 | Copyright (C) 2015 - 2016 Spotify AB 7 | %% 8 | Licensed under the Apache License, Version 2.0 (the "License"); 9 | you may not use this file except in compliance with the License. 10 | You may obtain a copy of the License at 11 | 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | Unless required by applicable law or agreed to in writing, software 15 | distributed under the License is distributed on an "AS IS" BASIS, 16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | See the License for the specific language governing permissions and 18 | limitations under the License. 19 | -\-\- 20 | --> 21 | 22 | <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 23 | xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 24 | <modelVersion>4.0.0</modelVersion> 25 | 26 | <groupId>com.spotify.it</groupId> 27 | <artifactId>writes-test-classpath</artifactId> 28 | <version>1.0-SNAPSHOT</version> 29 | 30 | <description>A simple IT verifying the basic use case.</description> 31 | 32 | <properties> 33 | <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 34 | </properties> 35 | 36 | <build> 37 | <plugins> 38 | <plugin> 39 | <groupId>@project.groupId@</groupId> 40 | <artifactId>@project.artifactId@</artifactId> 41 | <version>@project.version@</version> 42 | <executions> 43 | <execution> 44 | <id>default</id> 45 | <goals> 46 | <goal>build</goal> 47 | </goals> 48 | </execution> 49 | </executions> 50 | </plugin> 51 | </plugins> 52 | </build> 53 | </project> 54 | -------------------------------------------------------------------------------- /plugin/src/it/writes-test-classpath/verify.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * -/-/- 3 | * Dockerfile Maven Plugin 4 | * %% 5 | * Copyright (C) 2015 - 2016 Spotify AB 6 | * %% 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * -\-\- 19 | */ 20 | File imageIdFile = new File(basedir, "target/test-classes/META-INF/docker/com.spotify.it/writes-test-classpath/image-id") 21 | assert imageIdFile.isFile() 22 | -------------------------------------------------------------------------------- /plugin/src/main/java/com/spotify/plugin/dockerfile/AbstractDockerMojo.java: -------------------------------------------------------------------------------- 1 | /*- 2 | * -\-\- 3 | * Dockerfile Maven Plugin 4 | * -- 5 | * Copyright (C) 2016 Spotify AB 6 | * -- 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * -/-/- 19 | */ 20 | 21 | package com.spotify.plugin.dockerfile; 22 | 23 | import com.google.auth.oauth2.GoogleCredentials; 24 | import com.google.common.base.Charsets; 25 | import com.google.common.base.Preconditions; 26 | import com.google.common.io.Files; 27 | import com.spotify.docker.client.DefaultDockerClient; 28 | import com.spotify.docker.client.DockerClient; 29 | import com.spotify.docker.client.DockerConfigReader; 30 | import com.spotify.docker.client.auth.ConfigFileRegistryAuthSupplier; 31 | import com.spotify.docker.client.auth.MultiRegistryAuthSupplier; 32 | import com.spotify.docker.client.auth.RegistryAuthSupplier; 33 | import com.spotify.docker.client.auth.gcr.ContainerRegistryAuthSupplier; 34 | import com.spotify.docker.client.exceptions.DockerCertificateException; 35 | import java.io.File; 36 | import java.io.FileInputStream; 37 | import java.io.IOException; 38 | import java.text.MessageFormat; 39 | import java.util.ArrayList; 40 | import java.util.List; 41 | import java.util.Objects; 42 | import javax.annotation.Nonnull; 43 | import javax.annotation.Nullable; 44 | import org.apache.maven.archiver.MavenArchiveConfiguration; 45 | import org.apache.maven.archiver.MavenArchiver; 46 | import org.apache.maven.execution.MavenSession; 47 | import org.apache.maven.plugin.AbstractMojo; 48 | import org.apache.maven.plugin.MojoExecutionException; 49 | import org.apache.maven.plugin.MojoFailureException; 50 | import org.apache.maven.plugin.logging.Log; 51 | import org.apache.maven.plugins.annotations.Component; 52 | import org.apache.maven.plugins.annotations.Parameter; 53 | import org.apache.maven.project.MavenProject; 54 | import org.apache.maven.project.MavenProjectHelper; 55 | import org.apache.maven.settings.crypto.SettingsDecrypter; 56 | import org.codehaus.plexus.archiver.Archiver; 57 | import org.codehaus.plexus.archiver.jar.JarArchiver; 58 | 59 | public abstract class AbstractDockerMojo extends AbstractMojo { 60 | 61 | protected enum Metadata { 62 | IMAGE_ID("image ID", "image-id"), 63 | REPOSITORY("repository", "repository"), 64 | TAG("tag", "tag"), 65 | IMAGE_NAME("image name", "image-name"); 66 | 67 | private final String friendlyName; 68 | private final String fileName; 69 | 70 | Metadata(String friendlyName, String fileName) { 71 | this.friendlyName = friendlyName; 72 | this.fileName = fileName; 73 | } 74 | 75 | public String getFriendlyName() { 76 | return friendlyName; 77 | } 78 | 79 | public String getFileName() { 80 | return fileName; 81 | } 82 | } 83 | 84 | /** 85 | * Directory containing the generated Docker info JAR. 86 | */ 87 | @Parameter(defaultValue = "${project.build.directory}", 88 | property = "dockerfile.outputDirectory", 89 | required = true) 90 | private File buildDirectory; 91 | 92 | /** 93 | * Directory where various Docker-related metadata fragments will be stored. 94 | */ 95 | @Parameter(defaultValue = "${project.build.directory}/docker", 96 | property = "dockerfile.dockerInfoDirectory", required = true) 97 | protected File dockerInfoDirectory; 98 | 99 | /** 100 | * Path to docker config file, if the default is not acceptable. 101 | */ 102 | @Parameter(property = "dockerfile.dockerConfigFile") 103 | protected File dockerConfigFile; 104 | 105 | /** 106 | * A maven server id, in order to use maven settings to supply server auth. 107 | */ 108 | @Parameter(defaultValue = "false", property = "dockerfile.useMavenSettingsForAuth") 109 | protected boolean useMavenSettingsForAuth; 110 | 111 | /** 112 | * Whether to connect to Docker Daemon using HTTP proxy, if set. 113 | */ 114 | @Parameter(defaultValue = "true", property = "dockerfile.useProxy") 115 | protected boolean useProxy; 116 | 117 | /** 118 | * Directory where test metadata will be written during build. 119 | */ 120 | @Parameter(defaultValue = "${project.build.testOutputDirectory}", 121 | property = "dockerfile.testOutputDirectory", 122 | required = true) 123 | protected File testOutputDirectory; 124 | 125 | @Parameter(defaultValue = "300000" /* 5 minutes */, 126 | property = "dockerfile.readTimeoutMillis", 127 | required = true) 128 | protected long readTimeoutMillis; 129 | 130 | @Parameter(defaultValue = "300000" /* 5 minutes */, 131 | property = "dockerfile.connectTimeoutMillis", 132 | required = true) 133 | protected long connectTimeoutMillis; 134 | 135 | /** 136 | * Certain Docker operations can fail due to mysterious Docker daemon conditions. Sometimes it 137 | * might be worth it to just retry operations until they succeed. This parameter controls how 138 | * many times operations should be retried before they fail. By default, an extra attempt (so up 139 | * to two attempts) is made before failing. 140 | */ 141 | @Parameter(defaultValue = "1", property = "dockerfile.retryCount") 142 | protected int retryCount; 143 | 144 | @Parameter(property = "dockerfile.username") 145 | protected String username; 146 | 147 | @Parameter(property = "dockerfile.password") 148 | protected String password; 149 | 150 | /** 151 | * Whether to output a verbose log when performing various operations. 152 | */ 153 | @Parameter(defaultValue = "false", property = "dockerfile.verbose") 154 | protected boolean verbose; 155 | 156 | /** 157 | * Disables the entire dockerfile plugin; all goals become no-ops. 158 | */ 159 | @Parameter(defaultValue = "false", property = "dockerfile.skip") 160 | protected boolean skip; 161 | 162 | /** 163 | * Whether to write image information into the test output directory, so that docker information 164 | * is available on the CLASSPATH for integration tests. 165 | */ 166 | @Parameter(defaultValue = "true", property = "dockerfile.writeTestMetadata") 167 | protected boolean writeTestMetadata; 168 | 169 | /** 170 | * Require the jar plugin to build a new Docker info JAR even if none of the contents appear to 171 | * have changed. By default, this plugin looks to see if the output jar exists and inputs have 172 | * not changed. If these conditions are true, the plugin skips creation of the jar. This does 173 | * not work when other plugins, like the maven-shade-plugin, are configured to post-process the 174 | * jar. This plugin can not detect the post-processing, and so leaves the post-processed jar in 175 | * place. This can lead to failures when those plugins do not expect to find their own output as 176 | * an input. Set this parameter to <tt>true</tt> to avoid these problems by forcing this plugin 177 | * to recreate the jar every time. 178 | */ 179 | @Parameter(defaultValue = "false", property = "dockerfile.forceCreation") 180 | private boolean forceCreation; 181 | 182 | /** 183 | * Name of the generated Docker info JAR. 184 | */ 185 | @Parameter(defaultValue = "${project.build.finalName}", property = "dockerfile.finalName") 186 | private String finalName; 187 | 188 | /** 189 | * Classifier to use when attaching the Docker info JAR. If empty or absent, the JAR will become 190 | * the main artifact of the project. 191 | */ 192 | @Parameter(defaultValue = "docker-info", property = "dockerfile.classifier") 193 | protected String classifier; 194 | 195 | /** 196 | * Skip creation of the Docker info JAR. 197 | */ 198 | @Parameter(defaultValue = "false", property = "dockerfile.skipDockerInfo") 199 | protected boolean skipDockerInfo; 200 | 201 | /** 202 | * The Maven project. 203 | */ 204 | @Parameter(defaultValue = "${project}", readonly = true, required = true) 205 | protected MavenProject project; 206 | 207 | /** 208 | * The current Maven session. 209 | */ 210 | @Parameter(defaultValue = "${session}", readonly = true, required = true) 211 | private MavenSession session; 212 | 213 | /** 214 | * The archive configuration to use for the Docker info JAR. This can be used to embed additional 215 | * information in the JAR. 216 | */ 217 | @Parameter 218 | private MavenArchiveConfiguration archive = new MavenArchiveConfiguration(); 219 | 220 | /** 221 | * The JAR archiver. 222 | */ 223 | @Component(role = Archiver.class, hint = "jar") 224 | private JarArchiver jarArchiver; 225 | 226 | /** 227 | * Allows disabling of Google Container Registry authentication support. The support is enabled by 228 | * default, and should be a no-op (and fail fast) in most non-GCR environments, but this behavior 229 | * can be explicitly disabled with this property if needed. 230 | */ 231 | @Parameter(defaultValue = "true", property = "dockerfile.googleContainerRegistryEnabled") 232 | private boolean googleContainerRegistryEnabled; 233 | 234 | /** 235 | * The Maven project helper. 236 | */ 237 | @Component 238 | private MavenProjectHelper projectHelper; 239 | 240 | /** 241 | * The settings decrypter. 242 | */ 243 | @Component 244 | private SettingsDecrypter settingsDecrypter; 245 | 246 | protected abstract void execute(DockerClient dockerClient) 247 | throws MojoExecutionException, MojoFailureException; 248 | 249 | @Override 250 | public void execute() throws MojoExecutionException, MojoFailureException { 251 | if (skip) { 252 | getLog().info("Skipping execution because 'dockerfile.skip' is set"); 253 | } else { 254 | tryExecute(this.retryCount + 1); // We want to try at least one time 255 | } 256 | } 257 | 258 | private void tryExecute(int attempts) throws MojoFailureException, MojoExecutionException { 259 | Preconditions.checkArgument(attempts > 0, "attempts must not be negative"); 260 | 261 | MojoExecutionException exception = null; 262 | 263 | for (int attempt = 0; attempt < attempts; attempt++) { 264 | try { 265 | execute(openDockerClient()); 266 | return; // Not "break;" since we don't want to "throw exception;" 267 | } catch (MojoExecutionException e) { 268 | // Don't catch MojoFailureException, since that exception means "permanent failure" 269 | exception = e; 270 | 271 | final int attemptsLeft = attempts - attempt - 1; 272 | if (attemptsLeft > 0) { 273 | final String warningMessage = 274 | MessageFormat.format("An attempt failed, will retry {0} more times", attemptsLeft); 275 | getLog().warn(warningMessage, e); 276 | } 277 | } 278 | } 279 | 280 | throw exception; 281 | } 282 | 283 | protected void writeMetadata(Log log) throws MojoExecutionException { 284 | writeTestMetadata(); 285 | if (skipDockerInfo) { 286 | return; 287 | } 288 | final File jarFile = buildDockerInfoJar(log); 289 | attachJar(jarFile); 290 | } 291 | 292 | protected void writeMetadata(@Nonnull Metadata metadata, @Nonnull String value) 293 | throws MojoExecutionException { 294 | final File metadataFile = ensureMetadataFile(metadata); 295 | 296 | final String oldValue = readMetadata(metadata); 297 | if (Objects.equals(oldValue, value)) { 298 | return; 299 | } 300 | 301 | try { 302 | Files.write(value + "\n", metadataFile, Charsets.UTF_8); 303 | } catch (IOException e) { 304 | final String message = 305 | MessageFormat.format("Could not write {0} file at {1}", metadata.getFriendlyName(), 306 | metadataFile); 307 | throw new MojoExecutionException(message, e); 308 | } 309 | } 310 | 311 | private void writeTestMetadata() throws MojoExecutionException { 312 | if (writeTestMetadata && dockerInfoDirectory.exists()) { 313 | final File testMetadataDir = new File(testOutputDirectory, getMetaSubdir()); 314 | 315 | if (!testMetadataDir.isDirectory()) { 316 | if (!testMetadataDir.mkdirs()) { 317 | throw new MojoExecutionException("Could not create metadata output directory"); 318 | } 319 | } 320 | 321 | for (String name : dockerInfoDirectory.list()) { 322 | final File sourceFile = new File(dockerInfoDirectory, name); 323 | final File targetFile = new File(testMetadataDir, name); 324 | try { 325 | Files.copy(sourceFile, targetFile); 326 | } catch (IOException e) { 327 | throw new MojoExecutionException("Could not copy files", e); 328 | } 329 | } 330 | } 331 | } 332 | 333 | private String getMetaSubdir() { 334 | return String.format("META-INF/docker/%s/%s/", project.getGroupId(), project.getArtifactId()); 335 | } 336 | 337 | void attachJar(@Nonnull File jarFile) { 338 | if (classifier != null) { 339 | projectHelper.attachArtifact(project, "docker-info", classifier, jarFile); 340 | } else { 341 | project.getArtifact().setFile(jarFile); 342 | } 343 | } 344 | 345 | @Nonnull 346 | protected File buildDockerInfoJar(@Nonnull Log log) throws MojoExecutionException { 347 | final File jarFile = getJarFile(buildDirectory, finalName, classifier); 348 | 349 | final MavenArchiver archiver = new MavenArchiver(); 350 | archiver.setArchiver(jarArchiver); 351 | archiver.setOutputFile(jarFile); 352 | 353 | archive.setForced(forceCreation); 354 | 355 | if (dockerInfoDirectory.exists()) { 356 | final String prefix = getMetaSubdir(); 357 | archiver.getArchiver().addDirectory(dockerInfoDirectory, prefix); 358 | } else { 359 | log.warn("Docker info directory not created - Docker info JAR will be empty"); 360 | } 361 | 362 | try { 363 | archiver.createArchive(session, project, archive); 364 | } catch (Exception e) { 365 | throw new MojoExecutionException("Could not build Docker info JAR", e); 366 | } 367 | 368 | return jarFile; 369 | } 370 | 371 | @Nonnull 372 | private static File getJarFile(@Nonnull File basedir, @Nonnull String finalName, 373 | @Nullable String classifier) { 374 | if (classifier == null) { 375 | classifier = ""; 376 | } else { 377 | classifier = classifier.trim(); 378 | } 379 | 380 | if (classifier.length() > 0 && !classifier.startsWith("-")) { 381 | classifier = "-" + classifier; 382 | } 383 | 384 | return new File(basedir, finalName + classifier + ".jar"); 385 | } 386 | 387 | @Nonnull 388 | protected File ensureDockerInfoDirectory() throws MojoExecutionException { 389 | if (!dockerInfoDirectory.exists()) { 390 | if (!dockerInfoDirectory.mkdirs()) { 391 | throw new MojoExecutionException( 392 | MessageFormat 393 | .format("Could not create Docker info directory {0}", dockerInfoDirectory)); 394 | } 395 | } 396 | return dockerInfoDirectory; 397 | } 398 | 399 | @Nonnull 400 | protected File ensureMetadataFile(@Nonnull Metadata metadata) throws MojoExecutionException { 401 | return new File(ensureDockerInfoDirectory(), metadata.getFileName()); 402 | } 403 | 404 | protected void writeImageInfo(String repository, String tag) throws MojoExecutionException { 405 | writeMetadata(Metadata.REPOSITORY, repository); 406 | writeMetadata(Metadata.TAG, tag); 407 | writeMetadata(Metadata.IMAGE_NAME, formatImageName(repository, tag)); 408 | } 409 | 410 | @Nullable 411 | protected String readMetadata(@Nonnull Metadata metadata) throws MojoExecutionException { 412 | final File metadataFile = ensureMetadataFile(metadata); 413 | 414 | if (!metadataFile.exists()) { 415 | return null; 416 | } 417 | 418 | try { 419 | return Files.readFirstLine(metadataFile, Charsets.UTF_8); 420 | } catch (IOException e) { 421 | final String message = 422 | MessageFormat.format("Could not read {0} file at {1}", metadata.getFileName(), 423 | metadataFile); 424 | throw new MojoExecutionException(message, e); 425 | } 426 | } 427 | 428 | @Nonnull 429 | protected static String formatImageName(@Nonnull String repository, @Nonnull String tag) { 430 | return repository + ":" + tag; 431 | } 432 | 433 | @Nonnull 434 | private DockerClient openDockerClient() throws MojoExecutionException { 435 | final RegistryAuthSupplier authSupplier = createRegistryAuthSupplier(); 436 | 437 | try { 438 | return DefaultDockerClient.fromEnv() 439 | .readTimeoutMillis(readTimeoutMillis) 440 | .connectTimeoutMillis(connectTimeoutMillis) 441 | .registryAuthSupplier(authSupplier) 442 | .useProxy(useProxy) 443 | .build(); 444 | } catch (DockerCertificateException e) { 445 | throw new MojoExecutionException("Could not load Docker certificates", e); 446 | } 447 | } 448 | 449 | @Nonnull 450 | private RegistryAuthSupplier createRegistryAuthSupplier() { 451 | final List<RegistryAuthSupplier> suppliers = new ArrayList<>(); 452 | 453 | if (useMavenSettingsForAuth) { 454 | suppliers.add(new MavenRegistryAuthSupplier(session.getSettings(), settingsDecrypter)); 455 | } 456 | 457 | if (dockerConfigFile == null || "".equals(dockerConfigFile.getName())) { 458 | suppliers.add(new ConfigFileRegistryAuthSupplier()); 459 | } else { 460 | suppliers.add( 461 | new ConfigFileRegistryAuthSupplier( 462 | new DockerConfigReader(), 463 | dockerConfigFile.toPath() 464 | ) 465 | ); 466 | } 467 | if (googleContainerRegistryEnabled) { 468 | try { 469 | final RegistryAuthSupplier googleSupplier = googleContainerRegistryAuthSupplier(); 470 | if (googleSupplier != null) { 471 | suppliers.add(0, googleSupplier); 472 | } 473 | } catch (IOException ex) { 474 | getLog().info("Ignoring exception while loading Google credentials", ex); 475 | } 476 | } else { 477 | getLog().info("Google Container Registry support is disabled"); 478 | } 479 | 480 | MavenPomAuthSupplier pomSupplier = new MavenPomAuthSupplier(this.username, this.password); 481 | if (pomSupplier.hasUserName()) { 482 | suppliers.add(pomSupplier); 483 | } 484 | 485 | return new MultiRegistryAuthSupplier(suppliers); 486 | } 487 | 488 | /** 489 | * Attempt to load a GCR compatible RegistryAuthSupplier based on a few conditions: 490 | * <ol> 491 | * <li>First check to see if the environemnt variable DOCKER_GOOGLE_CREDENTIALS is set and points 492 | * to a readable file</li> 493 | * <li>Otherwise check if the Google Application Default Credentials can be loaded</li> 494 | * </ol> 495 | * Note that we use a special environment variable of our own in addition to any environment 496 | * variable that the ADC loading uses (GOOGLE_APPLICATION_CREDENTIALS) in case there is a need for 497 | * the user to use the latter env var for some other purpose in their build. 498 | * 499 | * @return a GCR RegistryAuthSupplier, or null 500 | * @throws IOException if an IOException occurs while loading the credentials 501 | */ 502 | @Nullable 503 | private RegistryAuthSupplier googleContainerRegistryAuthSupplier() throws IOException { 504 | GoogleCredentials credentials = null; 505 | 506 | final String googleCredentialsPath = System.getenv("DOCKER_GOOGLE_CREDENTIALS"); 507 | if (googleCredentialsPath != null) { 508 | final File file = new File(googleCredentialsPath); 509 | if (file.exists()) { 510 | try (FileInputStream inputStream = new FileInputStream(file)) { 511 | credentials = GoogleCredentials.fromStream(inputStream); 512 | getLog().info("Using Google credentials from file: " + file.getAbsolutePath()); 513 | } 514 | } 515 | } 516 | 517 | // use the ADC last 518 | if (credentials == null) { 519 | try { 520 | credentials = GoogleCredentials.getApplicationDefault(); 521 | getLog().info("Using Google application default credentials"); 522 | } catch (IOException ex) { 523 | // No GCP default credentials available 524 | getLog().debug("Failed to load Google application default credentials", ex); 525 | } 526 | } 527 | 528 | if (credentials == null) { 529 | return null; 530 | } 531 | 532 | return ContainerRegistryAuthSupplier.forCredentials(credentials).build(); 533 | } 534 | 535 | } 536 | -------------------------------------------------------------------------------- /plugin/src/main/java/com/spotify/plugin/dockerfile/BuildMojo.java: -------------------------------------------------------------------------------- 1 | /*- 2 | * -\-\- 3 | * Dockerfile Maven Plugin 4 | * -- 5 | * Copyright (C) 2016 Spotify AB 6 | * -- 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * -/-/- 19 | */ 20 | 21 | package com.spotify.plugin.dockerfile; 22 | 23 | import com.google.common.annotations.VisibleForTesting; 24 | import com.google.gson.Gson; 25 | import com.spotify.docker.client.DockerClient; 26 | import com.spotify.docker.client.exceptions.DockerException; 27 | import com.spotify.docker.client.exceptions.ImageNotFoundException; 28 | import java.io.File; 29 | import java.io.IOException; 30 | import java.io.UnsupportedEncodingException; 31 | import java.net.URLEncoder; 32 | import java.nio.file.Files; 33 | import java.nio.file.Path; 34 | import java.text.MessageFormat; 35 | import java.util.ArrayList; 36 | import java.util.List; 37 | import java.util.Map; 38 | import java.util.regex.Pattern; 39 | import javax.annotation.Nonnull; 40 | import javax.annotation.Nullable; 41 | import org.apache.maven.plugin.MojoExecutionException; 42 | import org.apache.maven.plugin.MojoFailureException; 43 | import org.apache.maven.plugin.logging.Log; 44 | import org.apache.maven.plugins.annotations.LifecyclePhase; 45 | import org.apache.maven.plugins.annotations.Mojo; 46 | import org.apache.maven.plugins.annotations.Parameter; 47 | 48 | @Mojo(name = "build", 49 | defaultPhase = LifecyclePhase.PACKAGE, 50 | requiresProject = true, 51 | threadSafe = true) 52 | public class BuildMojo extends AbstractDockerMojo { 53 | /** 54 | * Regex for a valid docker repository name. Used in validateRepository(). 55 | */ 56 | private static final String VALID_REPO_REGEX = "^([a-z0-9_.-])+(:[0-9]{1,5})?(\\/[a-z0-9_.-]+)*quot;; 57 | 58 | /** 59 | * Directory containing the the build context. This is typically the directory that contains 60 | * your Dockerfile. 61 | */ 62 | @Parameter(defaultValue = "${project.basedir}", 63 | property = "dockerfile.contextDirectory", 64 | required = true) 65 | private File contextDirectory; 66 | 67 | /** 68 | * Path to the Dockerfile to build. The specified file must reside withing the build context 69 | */ 70 | @Parameter(property = "dockerfile.dockerfile", required = false) 71 | private File dockerfile; 72 | 73 | /** 74 | * The repository to put the built image into when building the Dockerfile, for example 75 | * <tt>spotify/foo</tt>. You should also set the <tt>tag</tt> parameter, otherwise the tag 76 | * <tt>latest</tt> is used by default. If this is not specified, the <tt>tag</tt> goal needs to 77 | * be ran separately in order to tag the generated image with anything. 78 | */ 79 | @Parameter(property = "dockerfile.repository") 80 | private String repository; 81 | 82 | /** 83 | * The tag to apply when building the Dockerfile, which is appended to the repository. 84 | */ 85 | @Parameter(property = "dockerfile.tag", defaultValue = "latest") 86 | private String tag; 87 | 88 | /** 89 | * Disables the build goal; it becomes a no-op. 90 | */ 91 | @Parameter(property = "dockerfile.build.skip", defaultValue = "false") 92 | private boolean skipBuild; 93 | 94 | /** 95 | * Updates base images automatically. 96 | */ 97 | @Parameter(property = "dockerfile.build.pullNewerImage", defaultValue = "true") 98 | private boolean pullNewerImage; 99 | 100 | /** 101 | * Do not use cache when building the image. 102 | */ 103 | @Parameter(property = "dockerfile.build.noCache", defaultValue = "false") 104 | private boolean noCache; 105 | 106 | /** 107 | * Custom build arguments. 108 | */ 109 | @Parameter(property = "dockerfile.buildArgs") 110 | private Map<String,String> buildArgs; 111 | 112 | @Parameter(property = "dockerfile.build.cacheFrom") 113 | private List<String> cacheFrom; 114 | 115 | @Parameter(property = "dockerfile.build.squash", defaultValue = "false") 116 | private boolean squash; 117 | 118 | @Override 119 | public void execute(DockerClient dockerClient) 120 | throws MojoExecutionException, MojoFailureException { 121 | final Log log = getLog(); 122 | 123 | if (skipBuild) { 124 | log.info("Skipping execution because 'dockerfile.build.skip' is set"); 125 | return; 126 | } 127 | 128 | log.info("dockerfile: " + dockerfile); 129 | log.info("contextDirectory: " + contextDirectory); 130 | 131 | Path dockerfilePath = null; 132 | if (dockerfile != null) { 133 | dockerfilePath = dockerfile.toPath(); 134 | } 135 | final String imageId = buildImage( 136 | dockerClient, log, verbose, contextDirectory.toPath(), dockerfilePath, repository, tag, 137 | pullNewerImage, noCache, buildArgs, cacheFrom, squash); 138 | 139 | if (imageId == null) { 140 | log.warn("Docker build was successful, but no image was built"); 141 | } else { 142 | log.info(MessageFormat.format("Detected build of image with id {0}", imageId)); 143 | writeMetadata(Metadata.IMAGE_ID, imageId); 144 | } 145 | 146 | // Do this after the build so that other goals don't use the tag if it doesn't exist 147 | if (repository != null) { 148 | writeImageInfo(repository, tag); 149 | } 150 | 151 | writeMetadata(log); 152 | 153 | if (repository == null) { 154 | log.info(MessageFormat.format("Successfully built {0}", imageId)); 155 | } else { 156 | log.info(MessageFormat.format("Successfully built {0}", formatImageName(repository, tag))); 157 | } 158 | } 159 | 160 | @Nullable 161 | static String buildImage(@Nonnull DockerClient dockerClient, 162 | @Nonnull Log log, 163 | boolean verbose, 164 | @Nonnull Path contextDirectory, 165 | @Nullable Path dockerfile, 166 | @Nullable String repository, 167 | @Nonnull String tag, 168 | boolean pullNewerImage, 169 | boolean noCache, 170 | @Nullable Map<String,String> buildArgs, 171 | @Nullable List<String> cacheFrom, 172 | boolean squash) 173 | throws MojoExecutionException, MojoFailureException { 174 | 175 | log.info(MessageFormat.format("Building Docker context {0}", contextDirectory)); 176 | 177 | 178 | requireValidDockerFilePath(log, contextDirectory, dockerfile); 179 | 180 | final ArrayList<DockerClient.BuildParam> buildParameters = new ArrayList<>(); 181 | if (dockerfile != null) { 182 | buildParameters.add(DockerClient.BuildParam.dockerfile( 183 | contextDirectory.relativize(dockerfile))); 184 | } 185 | 186 | final LoggingProgressHandler progressHandler = new LoggingProgressHandler(log, verbose); 187 | if (pullNewerImage) { 188 | buildParameters.add(DockerClient.BuildParam.pullNewerImage()); 189 | } 190 | if (noCache) { 191 | buildParameters.add(DockerClient.BuildParam.noCache()); 192 | } 193 | 194 | if (buildArgs != null && !buildArgs.isEmpty()) { 195 | buildParameters.add(new DockerClient.BuildParam("buildargs", encodeBuildParam(buildArgs))); 196 | } 197 | 198 | if (cacheFrom != null) { 199 | final List<String> cacheFromExistLocally = new ArrayList<>(); 200 | for (String image : cacheFrom) { 201 | try { 202 | if (pullNewerImage || !imageExistLocally(dockerClient, image)) { 203 | dockerClient.pull(image); 204 | } 205 | log.info(MessageFormat.format("Build will use image {0} for cache-from", image)); 206 | cacheFromExistLocally.add(image); 207 | } catch (ImageNotFoundException e) { 208 | log.warn(MessageFormat.format( 209 | "Image {0} not found, build will not use it for cache-from", image)); 210 | } catch (DockerException | InterruptedException e) { 211 | throw new MojoExecutionException("Could not pull cache-from image", e); 212 | } 213 | } 214 | if (!cacheFromExistLocally.isEmpty()) { 215 | buildParameters.add(new DockerClient.BuildParam("cache-from", 216 | encodeBuildParam(cacheFromExistLocally))); 217 | } 218 | } 219 | 220 | if (squash) { 221 | buildParameters.add(new DockerClient.BuildParam("squash", encodeBuildParam(squash))); 222 | } 223 | 224 | final DockerClient.BuildParam[] buildParametersArray = 225 | buildParameters.toArray(new DockerClient.BuildParam[buildParameters.size()]); 226 | 227 | log.info(""); // Spacing around build progress 228 | try { 229 | if (repository != null) { 230 | if (!validateRepository(repository)) { 231 | throw new MojoFailureException( 232 | "Repo name \"" 233 | + repository 234 | + "\" must contain only lowercase, numbers, '-', '_' or '.'."); 235 | } 236 | 237 | final String name = formatImageName(repository, tag); 238 | log.info(MessageFormat.format("Image will be built as {0}", name)); 239 | log.info(""); // Spacing around build progress 240 | dockerClient.build(contextDirectory, name, progressHandler, buildParametersArray); 241 | } else { 242 | log.info("Image will be built without a name"); 243 | log.info(""); // Spacing around build progress 244 | dockerClient.build(contextDirectory, progressHandler, buildParametersArray); 245 | } 246 | } catch (DockerException | IOException | InterruptedException e) { 247 | throw new MojoExecutionException("Could not build image", e); 248 | } 249 | log.info(""); // Spacing around build progress 250 | 251 | return progressHandler.builtImageId(); 252 | } 253 | 254 | @VisibleForTesting 255 | static boolean validateRepository(@Nonnull String repository) { 256 | Pattern pattern = Pattern.compile(VALID_REPO_REGEX); 257 | return pattern.matcher(repository).matches(); 258 | } 259 | 260 | private static void requireValidDockerFilePath(@Nonnull Log log, 261 | @Nonnull Path contextDirectory, 262 | @Nullable Path dockerfile) 263 | throws MojoFailureException { 264 | 265 | log.info("Path(dockerfile): " + dockerfile); 266 | log.info("Path(contextDirectory): " + contextDirectory); 267 | 268 | if (dockerfile == null 269 | && !Files.exists(contextDirectory.resolve("Dockerfile")) 270 | && !Files.exists(contextDirectory.resolve("dockerfile"))) { 271 | // user did not override the default value 272 | log.error("Missing Dockerfile in context directory: " + contextDirectory); 273 | throw new MojoFailureException("Missing Dockerfile in context directory: " 274 | + contextDirectory); 275 | } 276 | 277 | if (dockerfile != null) { 278 | if (!Files.exists(dockerfile)) { 279 | log.error("Missing Dockerfile at " + dockerfile); 280 | throw new MojoFailureException("Missing Dockerfile at " + dockerfile); 281 | } 282 | if (!dockerfile.startsWith(contextDirectory)) { 283 | log.error("Dockerfile " + dockerfile + " is not a child of the context directory: " 284 | + contextDirectory); 285 | throw new MojoFailureException("Dockerfile " + dockerfile 286 | + " is not a child of the context directory: " + contextDirectory); 287 | } 288 | } 289 | } 290 | 291 | private static String encodeBuildParam(Object buildParam) throws MojoExecutionException { 292 | try { 293 | return URLEncoder.encode(new Gson().toJson(buildParam), "utf-8"); 294 | } catch (UnsupportedEncodingException e) { 295 | throw new MojoExecutionException("Could not build image", e); 296 | } 297 | } 298 | 299 | private static boolean imageExistLocally(DockerClient dockerClient, String image) 300 | throws DockerException, InterruptedException { 301 | try { 302 | dockerClient.inspectImage(image); 303 | return true; 304 | } catch (ImageNotFoundException e) { 305 | return false; 306 | } 307 | } 308 | 309 | } 310 | -------------------------------------------------------------------------------- /plugin/src/main/java/com/spotify/plugin/dockerfile/LoggingProgressHandler.java: -------------------------------------------------------------------------------- 1 | /*- 2 | * -\-\- 3 | * Dockerfile Maven Plugin 4 | * -- 5 | * Copyright (C) 2016 Spotify AB 6 | * -- 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * -/-/- 19 | */ 20 | 21 | package com.spotify.plugin.dockerfile; 22 | 23 | import com.google.common.base.Objects; 24 | import com.google.common.base.Splitter; 25 | import com.spotify.docker.client.ProgressHandler; 26 | import com.spotify.docker.client.exceptions.DockerException; 27 | import com.spotify.docker.client.messages.ProgressMessage; 28 | 29 | import java.text.MessageFormat; 30 | import java.util.HashMap; 31 | import java.util.Map; 32 | 33 | import javax.annotation.Nonnull; 34 | import javax.annotation.Nullable; 35 | 36 | import org.apache.maven.plugin.logging.Log; 37 | 38 | class LoggingProgressHandler implements ProgressHandler { 39 | 40 | private static final Splitter LINE_SPLITTER = Splitter.on('\n'); 41 | private final Log log; 42 | private final boolean verbose; 43 | private String builtImageId; 44 | private Map<String, String> imageStatuses = new HashMap<>(); 45 | 46 | LoggingProgressHandler(Log log, boolean verbose) { 47 | this.log = log; 48 | this.verbose = verbose; 49 | } 50 | 51 | public static LoggingProgressHandler forLog(Log log, boolean verbose) { 52 | return new LoggingProgressHandler(log, verbose); 53 | } 54 | 55 | @Nullable 56 | public String builtImageId() { 57 | return builtImageId; 58 | } 59 | 60 | @Override 61 | public void progress(ProgressMessage message) throws DockerException { 62 | if (message.error() != null) { 63 | handleError(message.error()); 64 | } else if (message.progressDetail() != null) { 65 | handleProgress(message.id(), message.status(), message.progress()); 66 | } else if ((message.status() != null) || (message.stream() != null)) { 67 | handleGeneric(message.stream(), message.status()); 68 | } 69 | 70 | String imageId = message.buildImageId(); 71 | if (imageId != null) { 72 | builtImageId = imageId; 73 | } 74 | } 75 | 76 | void handleGeneric(@Nullable String stream, @Nonnull String status) { 77 | final String value; 78 | if (stream != null) { 79 | value = trimNewline(stream); 80 | } else { 81 | value = status; 82 | } 83 | for (String line : LINE_SPLITTER.split(value)) { 84 | log.info(line); 85 | } 86 | } 87 | 88 | void handleProgress(@Nonnull String id, @Nonnull String status, @Nullable String progress) { 89 | if (verbose) { 90 | if (progress == null) { 91 | log.info(MessageFormat.format("Image {0}: {1}", id, status)); 92 | } else { 93 | log.info(MessageFormat.format("Image {0}: {1} {2}", id, status, progress)); 94 | } 95 | } else { 96 | if (!Objects.equal(imageStatuses.get(id), status)) { 97 | imageStatuses.put(id, status); 98 | log.info(MessageFormat.format("Image {0}: {1}", id, status)); 99 | } 100 | } 101 | } 102 | 103 | void handleError(@Nonnull String error) throws DockerException { 104 | log.error(error); 105 | throw new DockerException(error); 106 | } 107 | 108 | @Nonnull 109 | static String trimNewline(@Nonnull String string) { 110 | if (string.endsWith("\n")) { 111 | return string.substring(0, string.length() - 1); 112 | } else { 113 | return string; 114 | } 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /plugin/src/main/java/com/spotify/plugin/dockerfile/MavenPomAuthSupplier.java: -------------------------------------------------------------------------------- 1 | /*- 2 | * -\-\- 3 | * Dockerfile Maven Plugin 4 | * -- 5 | * Copyright (C) 2017 Spotify AB 6 | * -- 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * -/-/- 19 | */ 20 | 21 | package com.spotify.plugin.dockerfile; 22 | 23 | import com.spotify.docker.client.auth.RegistryAuthSupplier; 24 | import com.spotify.docker.client.messages.RegistryAuth; 25 | import com.spotify.docker.client.messages.RegistryConfigs; 26 | 27 | import java.util.HashMap; 28 | import java.util.Map; 29 | 30 | public class MavenPomAuthSupplier implements RegistryAuthSupplier { 31 | 32 | private String userName; 33 | private String password; 34 | 35 | public MavenPomAuthSupplier(String userName, String password) { 36 | this.userName = userName; 37 | this.password = password; 38 | } 39 | 40 | public boolean hasUserName() { 41 | return this.userName != null && !this.userName.equals(""); 42 | } 43 | 44 | @Override 45 | public RegistryAuth authFor(String server) { 46 | if (hasUserName()) { 47 | return RegistryAuth.builder() 48 | .username(this.userName) 49 | .password(this.password) 50 | .build(); 51 | } 52 | return null; 53 | } 54 | 55 | @Override 56 | public RegistryAuth authForSwarm() { 57 | return null; 58 | } 59 | 60 | @Override 61 | public RegistryConfigs authForBuild() { 62 | final Map<String, RegistryAuth> allConfigs = new HashMap<>(); 63 | if (hasUserName()) { 64 | allConfigs.put( 65 | "config", 66 | RegistryAuth.builder() 67 | .username(this.userName) 68 | .password(this.password) 69 | .build() 70 | ); 71 | } 72 | return RegistryConfigs.create(allConfigs); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /plugin/src/main/java/com/spotify/plugin/dockerfile/MavenRegistryAuthSupplier.java: -------------------------------------------------------------------------------- 1 | /*- 2 | * -\-\- 3 | * Dockerfile Maven Plugin 4 | * -- 5 | * Copyright (C) 2017 Spotify AB 6 | * -- 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * -/-/- 19 | */ 20 | 21 | package com.spotify.plugin.dockerfile; 22 | 23 | import com.spotify.docker.client.ImageRef; 24 | import com.spotify.docker.client.auth.RegistryAuthSupplier; 25 | import com.spotify.docker.client.exceptions.DockerException; 26 | import com.spotify.docker.client.messages.RegistryAuth; 27 | import com.spotify.docker.client.messages.RegistryConfigs; 28 | import java.util.HashMap; 29 | import java.util.Map; 30 | import org.apache.maven.settings.Server; 31 | import org.apache.maven.settings.Settings; 32 | import org.apache.maven.settings.building.SettingsProblem; 33 | import org.apache.maven.settings.crypto.DefaultSettingsDecryptionRequest; 34 | import org.apache.maven.settings.crypto.SettingsDecrypter; 35 | import org.apache.maven.settings.crypto.SettingsDecryptionRequest; 36 | import org.apache.maven.settings.crypto.SettingsDecryptionResult; 37 | import org.slf4j.Logger; 38 | import org.slf4j.LoggerFactory; 39 | 40 | public class MavenRegistryAuthSupplier implements RegistryAuthSupplier { 41 | 42 | private static final Logger log = LoggerFactory.getLogger(MavenRegistryAuthSupplier.class); 43 | 44 | private final Settings settings; 45 | private final SettingsDecrypter settingsDecrypter; 46 | 47 | public MavenRegistryAuthSupplier(final Settings settings, 48 | final SettingsDecrypter settingsDecrypter) { 49 | this.settings = settings; 50 | this.settingsDecrypter = settingsDecrypter; 51 | } 52 | 53 | @Override 54 | public RegistryAuth authFor(final String imageName) throws DockerException { 55 | final ImageRef ref = new ImageRef(imageName); 56 | Server server = settings.getServer(ref.getRegistryName()); 57 | if (server != null) { 58 | return createRegistryAuth(server); 59 | } 60 | log.warn("Did not find maven server configuration for docker server " + ref.getRegistryName()); 61 | return null; 62 | } 63 | 64 | @Override 65 | public RegistryAuth authForSwarm() throws DockerException { 66 | return null; 67 | } 68 | 69 | @Override 70 | public RegistryConfigs authForBuild() throws DockerException { 71 | final Map<String, RegistryAuth> allConfigs = new HashMap<>(); 72 | for (Server server : settings.getServers()) { 73 | allConfigs.put(server.getId(), createRegistryAuth(server)); 74 | } 75 | return RegistryConfigs.create(allConfigs); 76 | } 77 | 78 | private RegistryAuth createRegistryAuth(Server server) throws DockerException { 79 | SettingsDecryptionRequest decryptionRequest = new DefaultSettingsDecryptionRequest(server); 80 | SettingsDecryptionResult decryptionResult = settingsDecrypter.decrypt(decryptionRequest); 81 | 82 | if (decryptionResult.getProblems().isEmpty()) { 83 | log.debug("Successfully decrypted Maven server password"); 84 | } else { 85 | for (SettingsProblem problem : decryptionResult.getProblems()) { 86 | log.error("Settings problem for server {}: {}", server.getId(), problem); 87 | } 88 | 89 | throw new DockerException("Failed to decrypt Maven server password"); 90 | } 91 | 92 | return RegistryAuth.builder() 93 | .username(server.getUsername()) 94 | .password(decryptionResult.getServer().getPassword()) 95 | .build(); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /plugin/src/main/java/com/spotify/plugin/dockerfile/PushMojo.java: -------------------------------------------------------------------------------- 1 | /*- 2 | * -\-\- 3 | * Dockerfile Maven Plugin 4 | * -- 5 | * Copyright (C) 2016 Spotify AB 6 | * -- 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * -/-/- 19 | */ 20 | 21 | package com.spotify.plugin.dockerfile; 22 | 23 | import com.spotify.docker.client.DockerClient; 24 | import com.spotify.docker.client.exceptions.DockerException; 25 | 26 | import org.apache.maven.plugin.MojoExecutionException; 27 | import org.apache.maven.plugin.MojoFailureException; 28 | import org.apache.maven.plugin.logging.Log; 29 | import org.apache.maven.plugins.annotations.LifecyclePhase; 30 | import org.apache.maven.plugins.annotations.Mojo; 31 | import org.apache.maven.plugins.annotations.Parameter; 32 | 33 | @Mojo(name = "push", 34 | defaultPhase = LifecyclePhase.DEPLOY, 35 | requiresProject = true, 36 | threadSafe = true) 37 | public class PushMojo extends AbstractDockerMojo { 38 | 39 | /** 40 | * The repository to put the built image into, for example <tt>spotify/foo</tt>. You should also 41 | * set the <tt>tag</tt> parameter, otherwise the tag <tt>latest</tt> is used by default. 42 | */ 43 | @Parameter(property = "dockerfile.repository") 44 | private String repository; 45 | 46 | /** 47 | * The tag to apply to the built image. 48 | */ 49 | @Parameter(property = "dockerfile.tag") 50 | private String tag; 51 | 52 | /** 53 | * Disables the push goal; it becomes a no-op. 54 | */ 55 | @Parameter(property = "dockerfile.push.skip", defaultValue = "false") 56 | private boolean skipPush; 57 | 58 | @Override 59 | protected void execute(DockerClient dockerClient) 60 | throws MojoExecutionException, MojoFailureException { 61 | final Log log = getLog(); 62 | 63 | if (skipPush) { 64 | log.info("Skipping execution because 'dockerfile.push.skip' is set"); 65 | return; 66 | } 67 | 68 | if (repository == null) { 69 | repository = readMetadata(Metadata.REPOSITORY); 70 | } 71 | 72 | // Do this hoop jumping so that the override order is correct 73 | if (tag == null) { 74 | tag = readMetadata(Metadata.TAG); 75 | } 76 | if (tag == null) { 77 | tag = "latest"; 78 | } 79 | 80 | if (repository == null) { 81 | throw new MojoExecutionException( 82 | "Can't push image; image repository not known " 83 | + "(specify dockerfile.repository parameter, or run the tag goal before)"); 84 | } 85 | 86 | try { 87 | dockerClient 88 | .push(formatImageName(repository, tag), LoggingProgressHandler.forLog(log, verbose)); 89 | } catch (DockerException | InterruptedException e) { 90 | throw new MojoExecutionException("Could not push image", e); 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /plugin/src/main/java/com/spotify/plugin/dockerfile/TagMojo.java: -------------------------------------------------------------------------------- 1 | /*- 2 | * -\-\- 3 | * Dockerfile Maven Plugin 4 | * -- 5 | * Copyright (C) 2016 Spotify AB 6 | * -- 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * -/-/- 19 | */ 20 | 21 | package com.spotify.plugin.dockerfile; 22 | 23 | import com.spotify.docker.client.DockerClient; 24 | import com.spotify.docker.client.exceptions.DockerException; 25 | 26 | import java.text.MessageFormat; 27 | 28 | import org.apache.maven.plugin.MojoExecutionException; 29 | import org.apache.maven.plugin.MojoFailureException; 30 | import org.apache.maven.plugin.logging.Log; 31 | import org.apache.maven.plugins.annotations.LifecyclePhase; 32 | import org.apache.maven.plugins.annotations.Mojo; 33 | import org.apache.maven.plugins.annotations.Parameter; 34 | 35 | @Mojo(name = "tag", 36 | defaultPhase = LifecyclePhase.PACKAGE, 37 | requiresProject = true, 38 | threadSafe = true) 39 | public class TagMojo extends AbstractDockerMojo { 40 | 41 | /** 42 | * The repository to put the built image into, for example <tt>spotify/foo</tt>. You should also 43 | * set the <tt>tag</tt> parameter, otherwise the tag <tt>latest</tt> is used by default. 44 | */ 45 | @Parameter(property = "dockerfile.repository", required = true) 46 | private String repository; 47 | 48 | /** 49 | * The tag to apply to the built image. 50 | */ 51 | @Parameter(property = "dockerfile.tag", defaultValue = "latest", required = true) 52 | private String tag; 53 | 54 | /** 55 | * Whether to force re-assignment of an already assigned tag. 56 | */ 57 | @Parameter(property = "dockerfile.force", defaultValue = "true", required = true) 58 | private boolean force; 59 | 60 | /** 61 | * Disables the tag goal; it becomes a no-op. 62 | */ 63 | @Parameter(property = "dockerfile.tag.skip", defaultValue = "false") 64 | private boolean skipTag; 65 | 66 | @Override 67 | protected void execute(DockerClient dockerClient) 68 | throws MojoExecutionException, MojoFailureException { 69 | final Log log = getLog(); 70 | 71 | if (skipTag) { 72 | log.info("Skipping execution because 'dockerfile.tag.skip' is set"); 73 | return; 74 | } 75 | 76 | final String imageId = readMetadata(Metadata.IMAGE_ID); 77 | final String imageName = formatImageName(repository, tag); 78 | 79 | final String message = 80 | MessageFormat.format("Tagging image {0} as {1}", imageId, imageName); 81 | log.info(message); 82 | 83 | try { 84 | dockerClient.tag(imageId, imageName, force); 85 | } catch (DockerException | InterruptedException e) { 86 | throw new MojoExecutionException("Could not tag Docker image", e); 87 | } 88 | 89 | writeImageInfo(repository, tag); 90 | 91 | writeMetadata(log); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /plugin/src/test/java/com/spotify/plugin/dockerfile/TestRepoNameValidation.java: -------------------------------------------------------------------------------- 1 | /*- 2 | * -\-\- 3 | * Dockerfile Maven Plugin 4 | * -- 5 | * Copyright (C) 2019 Simon Woodward 6 | * -- 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * -/-/- 19 | */ 20 | 21 | package com.spotify.plugin.dockerfile; 22 | 23 | import static org.junit.Assert.assertFalse; 24 | import static org.junit.Assert.assertTrue; 25 | 26 | import org.apache.maven.plugin.MojoFailureException; 27 | import org.junit.Test; 28 | import org.junit.rules.ExpectedException; 29 | 30 | public class TestRepoNameValidation { 31 | public ExpectedException thrown = ExpectedException.none(); 32 | 33 | @Test 34 | public void testSuccess() throws MojoFailureException { 35 | assertTrue("All lower case should work", BuildMojo.validateRepository("alllowercase")); 36 | assertTrue("With numbers", BuildMojo.validateRepository("with000numbers")); 37 | assertTrue("Begin with numbers", BuildMojo.validateRepository("00withnumbers")); 38 | assertTrue("All numbers", BuildMojo.validateRepository("00757383")); 39 | assertTrue("End with numbers", BuildMojo.validateRepository("withnumbers34343")); 40 | assertTrue("With hyphens", BuildMojo.validateRepository("with-hyphens")); 41 | assertTrue("with underscores", BuildMojo.validateRepository("with_underscores")); 42 | assertTrue("With dots", BuildMojo.validateRepository("with.dots")); 43 | assertTrue("All underscores", BuildMojo.validateRepository("______")); 44 | assertTrue("All hyphens", BuildMojo.validateRepository("------")); 45 | assertTrue("All dots", BuildMojo.validateRepository("......")); 46 | assertTrue("Multipart", BuildMojo.validateRepository("example.com/okay./.path")); 47 | assertTrue("Start and end with dots", BuildMojo.validateRepository(".start.and.end.")); 48 | assertTrue("Start and end with hyphens", BuildMojo.validateRepository("-start-and-end-")); 49 | assertTrue("Start and end with underscores", BuildMojo.validateRepository("_start_and_end_")); 50 | assertTrue("May contain port", BuildMojo.validateRepository("example.com:443/okay./.path")); 51 | // Forward slash delimits the repo user from the repo name; strictly speaking, 52 | // you're allowed only one slash, somewhere in the middle. 53 | assertTrue("Multipart", BuildMojo.validateRepository("with/forwardslash")); 54 | assertTrue("Multi-multipart", BuildMojo.validateRepository("with/multiple/forwardslash")); 55 | } 56 | 57 | @Test 58 | public void testFailCases() { 59 | assertFalse("Mixed case didn't fail", BuildMojo.validateRepository("ddddddDddddd")); 60 | assertFalse("Symbols didn't fail", BuildMojo.validateRepository("ddddddDd+dddd")); 61 | assertFalse("Starting slash didn't fail", BuildMojo.validateRepository("/atstart")); 62 | assertFalse("Ending slash didn't fail", BuildMojo.validateRepository("atend/")); 63 | assertFalse("Only port", BuildMojo.validateRepository(":443")); 64 | assertFalse( 65 | "Port exceeding range", BuildMojo.validateRepository("example.com:100000/myproject")); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 2 | 3 | <modelVersion>4.0.0</modelVersion> 4 | 5 | <parent> 6 | <groupId>com.spotify</groupId> 7 | <artifactId>foss-root</artifactId> 8 | <version>6</version> 9 | </parent> 10 | 11 | <artifactId>dockerfile-maven</artifactId> 12 | <version>1.4.14-SNAPSHOT</version> 13 | <packaging>pom</packaging> 14 | 15 | <name>Dockerfile Maven Support</name> 16 | <description>A set of Maven tools for dealing with Dockerfiles</description> 17 | <url>https://github.com/spotify/dockerfile-maven</url> 18 | 19 | <modules> 20 | <module>extension</module> 21 | <module>plugin</module> 22 | </modules> 23 | 24 | <properties> 25 | <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 26 | </properties> 27 | 28 | <scm> 29 | <connection>scm:git:ssh://git@github.com/spotify/dockerfile-maven.git</connection> 30 | <developerConnection>scm:git:ssh://git@github.com/spotify/dockerfile-maven.git</developerConnection> 31 | <tag>HEAD</tag> 32 | <url>https://github.com/spotify/dockerfile-maven</url> 33 | </scm> 34 | 35 | <build> 36 | <pluginManagement> 37 | <plugins> 38 | <plugin> 39 | <artifactId>maven-checkstyle-plugin</artifactId> 40 | <configuration> 41 | <sourceDirectory>${project.build.sourceDirectory}</sourceDirectory> 42 | <testSourceDirectory>${project.build.testSourceDirectory}</testSourceDirectory> 43 | <includeTestSourceDirectory>true</includeTestSourceDirectory> 44 | <violationSeverity>warning</violationSeverity> 45 | </configuration> 46 | </plugin> 47 | </plugins> 48 | </pluginManagement> 49 | 50 | <plugins> 51 | <plugin> 52 | <artifactId>maven-deploy-plugin</artifactId> 53 | <version>2.8.2</version> 54 | <configuration> 55 | <updateReleaseInfo>true</updateReleaseInfo> 56 | </configuration> 57 | </plugin> 58 | </plugins> 59 | </build> 60 | 61 | <developers> 62 | <developer> 63 | <id>dflemstr</id> 64 | <email>dflemstr@spotify.com</email> 65 | <name>David Flemström</name> 66 | </developer> 67 | <developer> 68 | <id>davidxia</id> 69 | <email>dxia@spotify.com</email> 70 | <name>David Xia</name> 71 | </developer> 72 | <developer> 73 | <id>mattnworb</id> 74 | <email>mattbrown@spotify.com</email> 75 | <name>Matt Brown</name> 76 | </developer> 77 | </developers> 78 | 79 | </project> 80 | -------------------------------------------------------------------------------- /travis-settings.xml: -------------------------------------------------------------------------------- 1 | <settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" 2 | xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 3 | xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 4 | http://maven.apache.org/xsd/settings-1.0.0.xsd"> 5 | 6 | <servers> 7 | <server> 8 | <id>ossrh</id> 9 | <username>${env.SONATYPE_USERNAME}</username> 10 | <password>${env.SONATYPE_PASSWORD}</password> 11 | </server> 12 | </servers> 13 | </settings> 14 | --------------------------------------------------------------------------------