├── .gitattributes ├── .gitignore ├── .travis.yml ├── LICENSE ├── Makefile ├── README.md ├── base ├── Dockerfile.txt ├── download.json └── generate.sh ├── hub ├── Dockerfile.txt ├── entry_point.sh ├── generate.sh └── generate_config ├── nodeBase ├── Dockerfile.txt ├── entry_point.sh ├── functions.sh └── generate.sh ├── nodeChrome ├── Dockerfile.txt ├── chrome_launcher.sh ├── config.json └── generate.sh ├── nodeFirefox ├── Dockerfile.txt ├── config.json └── generate.sh ├── nodePhantomjs ├── Dockerfile.txt ├── config.json ├── deps │ └── phantomjs-2.1.1-linux-x86_64.tar.bz2 └── generate.sh ├── sa-test.sh ├── standaloneChrome ├── Dockerfile.txt ├── entry_point.sh └── generate.sh ├── standaloneFirefox ├── Dockerfile.txt ├── entry_point.sh └── generate.sh ├── standalonePhantomjs ├── Dockerfile.txt ├── entry_point.sh └── generate.sh ├── test.sh ├── test ├── Dockerfile ├── generate.sh ├── pom.xml ├── settings.xml └── src │ └── test │ ├── java │ └── SimpleTest.java │ └── resources │ ├── GridSuite.xml │ └── StandaloneSuite.xml └── travis-deploy-to-docker-registry.sh /.gitattributes: -------------------------------------------------------------------------------- 1 | # Normalize all text files with LF when stored but 2 | # convert to the OS's native line endings on checkout 3 | * text 4 | *.tar.bz2 binary 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | base/Dockerfile 2 | hub/Dockerfile 3 | nodeBase/Dockerfile 4 | nodeChrome/Dockerfile 5 | nodeFirefox/Dockerfile 6 | nodePhantomjs/Dockerfile 7 | standalonePhantomjs/Dockerfile 8 | standaloneChrome/Dockerfile 9 | standaloneFirefox/Dockerfile 10 | .m2 11 | target 12 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | language: c 3 | services: 4 | - docker 5 | cache: 6 | directories: 7 | - $TRAVIS_BUILD_DIR/test/.m2 8 | script: 9 | - docker version 10 | - VERSION=develop make ci 11 | after_success: 12 | - VERSION=develop sh -e travis-deploy-to-docker-registry.sh 13 | notifications: 14 | irc: 15 | channels: 16 | - "irc.freenode.org#selion" 17 | on_success: always 18 | on_failure: always 19 | use_notice: true 20 | webhooks: 21 | urls: 22 | - https://webhooks.gitter.im/e/a8fc34e427360ced7ebf 23 | on_success: change 24 | on_failure: always 25 | on_start: never 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | 3 | Version 2.0, January 2004 4 | 5 | http://www.apache.org/licenses/ 6 | 7 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 8 | 9 | 1. Definitions. 10 | 11 | "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 12 | 9 of this document. 13 | 14 | "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or 17 | are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct 18 | or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership 19 | of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. 20 | 21 | "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. 22 | 23 | "Source" form shall mean the preferred form for making modifications, including but not limited to software source 24 | code, documentation source, and configuration files. 25 | 26 | "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including 27 | but not limited to compiled object code, generated documentation, and conversions to other media types. 28 | 29 | "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as 30 | indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix 31 | below). 32 | 33 | "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work 34 | and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an 35 | original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain 36 | separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. 37 | 38 | "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or 39 | additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the 40 | Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. 41 | For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent 42 | to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source 43 | code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of 44 | discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in 45 | writing by the copyright owner as "Not a Contribution." 46 | 47 | "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been 48 | received by Licensor and subsequently incorporated within the Work. 49 | 50 | 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to 51 | You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, 52 | prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such 53 | Derivative Works in Source or Object form. 54 | 55 | 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You 56 | a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent 57 | license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license 58 | applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution 59 | (s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You 60 | institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that 61 | the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then 62 | any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is 63 | filed. 64 | 65 | 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with 66 | or without modifications, and in Source or Object form, provided that You meet the following conditions: 67 | 68 | You must give any other recipients of the Work or Derivative Works a copy of this License; and 69 | You must cause any modified files to carry prominent notices stating that You changed the files; and 70 | You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and 71 | attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the 72 | Derivative Works; and 73 | If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute 74 | must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices 75 | that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text 76 | file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the 77 | Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices 78 | normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. 79 | You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to 80 | the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the 81 | License. 82 | 83 | You may add Your own copyright statement to Your modifications and may provide additional or different license terms 84 | and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a 85 | whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in 86 | this License. 87 | 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for 88 | inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any 89 | additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any 90 | separate license agreement you may have executed with Licensor regarding such Contributions. 91 | 92 | 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product 93 | names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and 94 | reproducing the content of the NOTICE file. 95 | 96 | 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and 97 | each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 98 | express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, 99 | MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness 100 | of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this 101 | License. 102 | 103 | 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, 104 | or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in 105 | writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or 106 | consequential damages of any character arising as a result of this License or out of the use or inability to use the 107 | Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or 108 | any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such 109 | damages. 110 | 111 | 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may 112 | choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations 113 | and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own 114 | behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, 115 | defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor 116 | by reason of your accepting any such warranty or additional liability. 117 | 118 | END OF TERMS AND CONDITIONS 119 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | NAME := selion 2 | VERSION := $(or $(VERSION),$(VERSION),'develop') 3 | PLATFORM := $(shell uname -s) 4 | SELION_GRID_VERSION := $(or $(SELION_GRID_VERSION), $(SELION_GRID_VERSION), '2.0.0-SNAPSHOT') 5 | REPO := $(or $(REPO), $(REPO), 'snapshots') 6 | SELENIUM_VERSION := $(or $(SELENIUM_VERSION), $(SELENIUM_VERSION), '3.0') 7 | SELENIUM_FIX := $(or $(SELENIUM_FIX), $(SELENIUM_FIX), '1') 8 | BUILD_ARGS := $(BUILD_ARGS) 9 | 10 | all: hub chrome firefox phantomjs standalone_phantomjs standalone_firefox standalone_chrome 11 | 12 | build: all 13 | 14 | ci: build test 15 | 16 | generate_all: \ 17 | generate_base \ 18 | generate_hub \ 19 | generate_nodebase \ 20 | generate_chrome \ 21 | generate_firefox \ 22 | generate_phantomjs \ 23 | generate_standalone_phantomjs \ 24 | generate_standalone_firefox \ 25 | generate_standalone_chrome 26 | 27 | generate_base: 28 | @echo "Generating sources for $(NAME)/base:$(VERSION) ..." 29 | cd ./base && ./generate.sh $(SELENIUM_VERSION) $(SELENIUM_FIX) $(REPO) $(SELION_GRID_VERSION) 30 | 31 | base: generate_base 32 | @echo "Building $(NAME)/base:$(VERSION) ..." 33 | cd ./base && docker build $(BUILD_ARGS) -t $(NAME)/base:$(VERSION) . 34 | 35 | generate_hub: 36 | @echo "Generating sources for $(NAME)/hub:$(VERSION) ..." 37 | cd ./hub && ./generate.sh $(VERSION) 38 | 39 | hub: base generate_hub 40 | @echo "Building $(NAME)/hub:$(VERSION) ..." 41 | cd ./hub && docker build $(BUILD_ARGS) -t $(NAME)/hub:$(VERSION) . 42 | 43 | generate_nodebase: 44 | @echo "Generating sources for $(NAME)/node-base:$(VERSION) ..." 45 | cd ./nodeBase && ./generate.sh $(VERSION) 46 | 47 | nodebase: base generate_nodebase 48 | @echo "Building $(NAME)/node-base:$(VERSION) ..." 49 | cd ./nodeBase && docker build $(BUILD_ARGS) -t $(NAME)/node-base:$(VERSION) . 50 | 51 | generate_chrome: 52 | @echo "Generating sources for $(NAME)/node-chrome:$(VERSION) ..." 53 | cd ./nodeChrome && ./generate.sh $(VERSION) 54 | 55 | chrome: nodebase generate_chrome 56 | @echo "Building $(NAME)/node-chrome:$(VERSION) ..." 57 | cd ./nodeChrome && docker build $(BUILD_ARGS) -t $(NAME)/node-chrome:$(VERSION) . 58 | 59 | generate_standalone_chrome: 60 | @echo "Generating sources for $(NAME)/standalone-chrome:$(VERSION) ..." 61 | cd ./standaloneChrome && ./generate.sh $(VERSION) 62 | 63 | standalone_chrome: generate_standalone_chrome chrome 64 | @echo "Building $(NAME)/standalone-chrome:$(VERSION) ..." 65 | cd ./standaloneChrome && docker build $(BUILD_ARGS) -t $(NAME)/standalone-chrome:$(VERSION) . 66 | 67 | generate_firefox: 68 | @echo "Generating sources for $(NAME)/node-firefox:$(VERSION) ..." 69 | cd ./nodeFirefox && ./generate.sh $(VERSION) 70 | 71 | firefox: nodebase generate_firefox 72 | @echo "Building $(NAME)/node-firefox:$(VERSION) ..." 73 | cd ./nodeFirefox && docker build $(BUILD_ARGS) -t $(NAME)/node-firefox:$(VERSION) . 74 | 75 | generate_standalone_firefox: 76 | @echo "Generating sources for $(NAME)/standalone-firefox:$(VERSION) ..." 77 | cd ./standaloneFirefox && ./generate.sh $(VERSION) 78 | 79 | standalone_firefox: generate_standalone_firefox firefox 80 | @echo "Building $(NAME)/standalone-firefox:$(VERSION) ..." 81 | cd ./standaloneFirefox && docker build $(BUILD_ARGS) -t $(NAME)/standalone-firefox:$(VERSION) . 82 | 83 | generate_phantomjs: 84 | @echo "Generating sources for $(NAME)/node-phantomjs:$(VERSION) ..." 85 | cd ./nodePhantomjs && ./generate.sh $(VERSION) 86 | 87 | phantomjs: nodebase generate_phantomjs 88 | @echo "Building $(NAME)/node-phantomjs:$(VERSION) ..." 89 | cd ./nodePhantomjs && docker build $(BUILD_ARGS) -t $(NAME)/node-phantomjs:$(VERSION) . 90 | 91 | generate_standalone_phantomjs: 92 | @echo "Generating sources for $(NAME)/standalone-phantomjs:$(VERSION) ..." 93 | cd ./standalonePhantomjs && ./generate.sh $(VERSION) 94 | 95 | standalone_phantomjs: generate_standalone_phantomjs phantomjs 96 | @echo "Building $(NAME)/standalone-phantomjs:$(VERSION) ..." 97 | cd ./standalonePhantomjs && docker build $(BUILD_ARGS) -t $(NAME)/standalone-phantomjs:$(VERSION) . 98 | 99 | tag_latest: 100 | @echo "Tagging $(VERSION) as latest ..." 101 | docker tag $(NAME)/base:$(VERSION) $(NAME)/base:latest 102 | docker tag $(NAME)/hub:$(VERSION) $(NAME)/hub:latest 103 | docker tag $(NAME)/node-base:$(VERSION) $(NAME)/node-base:latest 104 | docker tag $(NAME)/node-chrome:$(VERSION) $(NAME)/node-chrome:latest 105 | docker tag $(NAME)/node-firefox:$(VERSION) $(NAME)/node-firefox:latest 106 | docker tag $(NAME)/node-phantomjs:$(VERSION) $(NAME)/node-phantomjs:latest 107 | docker tag $(NAME)/standalone-chrome:$(VERSION) $(NAME)/standalone-chrome:latest 108 | docker tag $(NAME)/standalone-firefox:$(VERSION) $(NAME)/standalone-firefox:latest 109 | docker tag $(NAME)/standalone-phantomjs:$(VERSION) $(NAME)/standalone-phantomjs:latest 110 | 111 | release: tag_latest deploy 112 | @echo "*** Don't forget to create a tag. git tag v$(VERSION) && git push origin v$(VERSION)" 113 | 114 | deploy: 115 | @echo "Deploying to docker registry ..." 116 | @if ! docker images $(NAME)/base | awk '{ print $$2 }' | grep -q -F $(VERSION); then echo "$(NAME)/base version $(VERSION) is not yet built. Please run 'make build'"; false; fi 117 | @if ! docker images $(NAME)/hub | awk '{ print $$2 }' | grep -q -F $(VERSION); then echo "$(NAME)/hub version $(VERSION) is not yet built. Please run 'make build'"; false; fi 118 | @if ! docker images $(NAME)/node-base | awk '{ print $$2 }' | grep -q -F $(VERSION); then echo "$(NAME)/node-base version $(VERSION) is not yet built. Please run 'make build'"; false; fi 119 | @if ! docker images $(NAME)/node-chrome | awk '{ print $$2 }' | grep -q -F $(VERSION); then echo "$(NAME)/node-chrome version $(VERSION) is not yet built. Please run 'make build'"; false; fi 120 | @if ! docker images $(NAME)/node-firefox | awk '{ print $$2 }' | grep -q -F $(VERSION); then echo "$(NAME)/node-firefox version $(VERSION) is not yet built. Please run 'make build'"; false; fi 121 | @if ! docker images $(NAME)/node-phantomjs | awk '{ print $$2 }' | grep -q -F $(VERSION); then echo "$(NAME)/node-phantomjs version $(VERSION) is not yet built. Please run 'make build'"; false; fi 122 | @if ! docker images $(NAME)/standalone-chrome | awk '{ print $$2 }' | grep -q -F $(VERSION); then echo "$(NAME)/standalone-chrome version $(VERSION) is not yet built. Please run 'make build'"; false; fi 123 | @if ! docker images $(NAME)/standalone-firefox | awk '{ print $$2 }' | grep -q -F $(VERSION); then echo "$(NAME)/standalone-firefox version $(VERSION) is not yet built. Please run 'make build'"; false; fi 124 | @if ! docker images $(NAME)/standalone-phantomjs | awk '{ print $$2 }' | grep -q -F $(VERSION); then echo "$(NAME)/standalone-phantomjs version $(VERSION) is not yet built. Please run 'make build'"; false; fi 125 | docker push $(NAME)/base:$(VERSION) 126 | docker push $(NAME)/hub:$(VERSION) 127 | docker push $(NAME)/node-base:$(VERSION) 128 | docker push $(NAME)/node-chrome:$(VERSION) 129 | docker push $(NAME)/node-firefox:$(VERSION) 130 | docker push $(NAME)/node-phantomjs:$(VERSION) 131 | docker push $(NAME)/standalone-chrome:$(VERSION) 132 | docker push $(NAME)/standalone-firefox:$(VERSION) 133 | docker push $(NAME)/standalone-phantomjs:$(VERSION) 134 | 135 | generate_test: 136 | @echo "Setting up test dependencies ..." 137 | cd ./test && ./generate.sh $(SELION_GRID_VERSION) 138 | 139 | test: generate_test 140 | @echo "Running tests ..." 141 | VERSION=$(VERSION) SELION_VERSION=$(SELION_GRID_VERSION) ./test.sh 142 | VERSION=$(VERSION) SELION_VERSION=$(SELION_GRID_VERSION) ./sa-test.sh 143 | 144 | clean: 145 | @echo "Cleaning up generated Dockerfiles ..." 146 | @if [ -f base/Dockerfile ]; then rm base/Dockerfile; fi 147 | @if [ -f hub/Dockerfile ]; then rm hub/Dockerfile; fi 148 | @if [ -f nodeBase/Dockerfile ]; then rm nodeBase/Dockerfile; fi 149 | @if [ -f nodeChrome/Dockerfile ]; then rm nodeChrome/Dockerfile; fi 150 | @if [ -f nodeFirefox/Dockerfile ]; then rm nodeFirefox/Dockerfile; fi 151 | @if [ -f nodePhantomjs/Dockerfile ]; then rm nodePhantomjs/Dockerfile; fi 152 | @if [ -f standaloneChrome/Dockerfile ]; then rm standaloneChrome/Dockerfile; fi 153 | @if [ -f standaloneFirefox/Dockerfile ]; then rm standaloneFirefox/Dockerfile; fi 154 | @if [ -f standalonePhantomjs/Dockerfile ]; then rm standalonePhantomjs/Dockerfile; fi 155 | @echo "Cleaning up test dependencies ..." 156 | @if [ -d test/.m2 ]; then rm -rf test/.m2; fi 157 | @if [ -d test/target ]; then rm -rf test/target; fi 158 | @echo "Removing all exited $(NAME) $(VERSION) containers ..." 159 | @if [ `docker ps -a | grep $(NAME) | grep Exit | grep $(VERSION) | awk '{print $$1}' | wc -l | sed -e 's/^[ \t]*//'` -ne 0 ]; then\ 160 | docker rm `docker ps -a | grep Exit | grep $(NAME) | grep $(VERSION) | awk '{print $$1}'`;\ 161 | fi 162 | @echo "Removing all $(NAME) $(VERSION) images ..." 163 | @if [ `docker images | grep $(NAME) | grep $(VERSION) | awk '{print $$3}' | wc -l | sed -e 's/^[ \t]*//'` -ne 0 ]; then\ 164 | docker rmi -f `docker images | grep $(NAME) | grep $(VERSION) | awk '{print $$3}'`;\ 165 | fi 166 | 167 | .PHONY: \ 168 | all \ 169 | base \ 170 | build \ 171 | chrome \ 172 | ci \ 173 | firefox \ 174 | phantomjs \ 175 | hub \ 176 | nodebase \ 177 | release \ 178 | standalone_chrome \ 179 | standalone_firefox \ 180 | standalone_phantomjs \ 181 | tag_latest \ 182 | test 183 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # docker-selion 2 | 3 | ## Docker images for SeLion (grid) server Hub and Node configurations with Chrome and Firefox. 4 | 5 | [![Build Status](https://travis-ci.org/paypal/docker-selion.svg?branch=develop)](https://travis-ci.org/paypal/docker-selion) 6 | [![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/paypal/SeLion?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 7 | 8 | Find us on [Gitter](https://gitter.im/paypal/SeLion) 9 | 10 | These images build on the Selenium docker images here https://github.com/SeleniumHQ/docker-selenium 11 | 12 | Images included here: 13 | - __selion/base__: Base image which includes Java runtime, Selenium + SeLion JAR files 14 | - __selion/hub__: Image for running a Selion Grid Hub 15 | - __selion/node-base__: Base image for the SeLion node images 16 | - __selion/node-chrome__: SeLion node with Chrome installed, needs to be connected to a SeLion Grid Hub 17 | - __selion/node-firefox__: SeLion node with Firefox installed, needs to be connected to a SeLion Grid Hub 18 | - __selion/node-phantomjs__: SeLion node with Phantomjs installed, needs to be connected to a SeLion Grid Hub 19 | - __selion/standalone-chrome__: SeLion standalone with Chrome installed 20 | - __selion/standalone-firefox__: SeLion standalone with Firefox installed 21 | - __selion/standalone-phantomjs__: SeLion standalone with Phantomjs installed 22 | 23 | ## Running the images 24 | 25 | When executing docker run for an image with chrome browser please add volume mount `-v /dev/shm:/dev/shm` to use the host's shared memory. 26 | 27 | ``` bash 28 | $ docker run -d -p 4444:4444 -v /dev/shm:/dev/shm selion/node_chrome:1.1.0 29 | ``` 30 | 31 | This is a workaround to node-chrome crash in docker container issue: https://code.google.com/p/chromium/issues/detail?id=519952 32 | 33 | ### Selion Grid Hub 34 | 35 | ``` bash 36 | $ docker run -d -p 4444:4444 --name selion-hub selion/hub:1.1.0 37 | ``` 38 | 39 | ### SELION_OPTS options 40 | 41 | You can pass `SELION_OPTS` variable with additional commandline parameters for starting a hub or a node. So to run a SeLion sauce hub. 42 | 43 | ### Selion Grid Sauce Hub 44 | 45 | ``` bash 46 | $ docker run -d -p 4444:4444 -e SELION_OPTS="-type sauce" --name selion-hub selion/hub:1.1.0 47 | ``` 48 | 49 | ### Chrome and Firefox Grid Nodes 50 | 51 | ``` bash 52 | $ docker run -d --link selion-hub:hub selion/node-chrome:1.1.0 53 | $ docker run -d --link selion-hub:hub selion/node-firefox:1.1.0 54 | ``` 55 | 56 | ### Java Environment Options 57 | 58 | You can pass JAVA_OPTS environment variable to selenium java processes. 59 | 60 | ``` bash 61 | $ docker run -d -p 4444:4444 -e JAVA_OPTS=-Xmx512m --name selion-hub selion/hub:1.1.0 62 | ``` 63 | 64 | ## Building the images 65 | 66 | Ensure you have the `ubuntu:15.04` base image downloaded, this step is _optional_ since Docker takes care of downloading the parent base image automatically. 67 | 68 | ``` bash 69 | $ docker pull ubuntu:15.04 70 | ``` 71 | 72 | Clone the repo and from the project directory root you can build everything by running: 73 | 74 | ``` bash 75 | $ VERSION=local make build 76 | ``` 77 | 78 | _Note: Omitting_ `VERSION=local` _will build the images with the develop version number thus overwriting the images downloaded from [Docker Hub](https://registry.hub.docker.com/)._ 79 | 80 | ## Using the images 81 | 82 | ##### Example: Spawn a container for testing in Chrome: 83 | 84 | ``` bash 85 | $ docker run -d --name selion-hub -p 4444:4444 selion/hub:1.1.0 86 | $ CH=$(docker run --rm --name=ch \ 87 | --link selion-hub:hub -v /e2e/uploads:/e2e/uploads \ 88 | selion/node-chrome:1.1.0) 89 | ``` 90 | 91 | _Note:_ `-v /e2e/uploads:/e2e/uploads` _is optional in case you are testing browser uploads on your web app you will probably need to share a directory for this._ 92 | 93 | ##### Example: Spawn a container for testing in Firefox: 94 | 95 | This command line is the same as for Chrome. Remember that the Selenium running container is able to launch either Chrome or Firefox, the idea around having 2 separate containers, one for each browser is for convenience plus avoiding certain `:focus` issues your web app may encounter during end-to-end test automation. 96 | 97 | ``` bash 98 | $ docker run -d --name selion-hub -p 4444:4444 selion/hub:1.1.0 99 | $ FF=$(docker run --rm --name=fx \ 100 | --link selion-hub:hub -v /e2e/uploads:/e2e/uploads \ 101 | selion/node-firefox:1.1.0) 102 | ``` 103 | 104 | _Note: Since a Docker container is not meant to preserve state and spawning a new one takes less than 3 seconds you will likely want to remove containers after each end-to-end test with_ `--rm` _command. You need to think of your Docker containers as single processes, not as running virtual machines, in case you are familiar with [Vagrant](https://www.vagrantup.com/)._ 105 | 106 | 107 | ### Troubleshooting 108 | 109 | All output is sent to stdout so it can be inspected by running: 110 | ``` bash 111 | $ docker logs -f 112 | ``` 113 | 114 | License 115 | ------- 116 | [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) 117 | -------------------------------------------------------------------------------- /base/Dockerfile.txt: -------------------------------------------------------------------------------- 1 | FROM ubuntu:15.04 2 | MAINTAINER Selion 3 | 4 | # Builds on docker selenium (https://github.com/SeleniumHQ/docker-selenium) which we customize for SeLion. 5 | # This is copy of selenium base. Inheriting FROM selenium base didn't allow over-riding some 6 | # choices already made in selenium base. 7 | 8 | # This Docker is just a base for the other SeLion docker images. 9 | 10 | # TODOs: 11 | # Selenium using openjdk (openjdk-8-jre-headless) 12 | # Consider this base instead https://github.com/phusion/baseimage-docker 13 | 14 | #============================== 15 | # Customize sources for apt-get 16 | #============================== 17 | RUN echo "deb http://archive.ubuntu.com/ubuntu vivid main universe\n" > /etc/apt/sources.list \ 18 | && echo "deb http://archive.ubuntu.com/ubuntu vivid-updates main universe\n" >> /etc/apt/sources.list 19 | 20 | #============================== 21 | # Miscellaneous packages 22 | # Includes minimal runtime used for executing non GUI Java programs 23 | #============================== 24 | RUN apt-get update -qqy \ 25 | && apt-get -qqy --no-install-recommends install \ 26 | ca-certificates \ 27 | openjdk-8-jre-headless \ 28 | sudo \ 29 | unzip \ 30 | wget \ 31 | && rm -rf /var/lib/apt/lists/* \ 32 | && sed -i 's/securerandom\.source=file:\/dev\/random/securerandom\.source=file:\/dev\/urandom/' ./usr/lib/jvm/java-8-openjdk-amd64/jre/lib/security/java.security 33 | 34 | # The Selenium server version (Keep in sync with Selion server) 35 | ENV SELENIUM_VERSION=%SELENIUM_VERSION% 36 | ENV SELENIUM_FIX=%SELENIUM_FIX% 37 | 38 | # Selenium base was already using /opt 39 | ENV SELION_HOME /opt/selion 40 | 41 | ENV SEL_SERVER https://selenium-release.storage.googleapis.com 42 | ENV REDIRECT_URL https://oss.sonatype.org/service/local/artifact/maven/content 43 | ENV REPO=%REPO% 44 | ENV SELION_GRID_VERSION=%SELION_GRID_VERSION% 45 | 46 | #============================= 47 | # Add selion + selenium server 48 | #============================= 49 | RUN mkdir -p ${SELION_HOME} \ 50 | && wget --no-verbose "$REDIRECT_URL?r=$REPO&g=com.paypal.selion&a=SeLion-Grid&c=jar-with-dependencies&v=$SELION_GRID_VERSION" -O $SELION_HOME/SeLion-Grid.jar \ 51 | && wget --no-verbose $SEL_SERVER/$SELENIUM_VERSION/selenium-server-standalone-$SELENIUM_VERSION.$SELENIUM_FIX.jar -O $SELION_HOME/selenium-server-standalone.jar 52 | 53 | #======================================== 54 | # Add normal user with passwordless sudo 55 | #======================================== 56 | RUN sudo useradd seluser --shell /bin/bash --create-home \ 57 | && sudo usermod -a -G sudo seluser \ 58 | && echo 'ALL ALL = (ALL) NOPASSWD: ALL' >> /etc/sudoers \ 59 | && echo 'seluser:secret' | chpasswd 60 | 61 | #===================================================================== 62 | # Add an empty SeLion download.json. The dependencies will be in place 63 | #===================================================================== 64 | # Empty file to suppress downloads 65 | COPY download.json $SELION_HOME/config/download.json 66 | -------------------------------------------------------------------------------- /base/download.json: -------------------------------------------------------------------------------- 1 | [] 2 | -------------------------------------------------------------------------------- /base/generate.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | SELENIUM_VERSION=$1 4 | SELENIUM_FIX=$2 5 | REPO=$3 6 | SELION_GRID_VERSION=$4 7 | 8 | cat ./Dockerfile.txt > ./Dockerfile 9 | 10 | # The Selenium server version (Keep in sync with SeLion server) 11 | sed -i.bkp -e "s/%SELENIUM_VERSION%/$SELENIUM_VERSION/g" ./Dockerfile 12 | sed -i.bkp -e "s/%SELENIUM_FIX%/$SELENIUM_FIX/g" ./Dockerfile 13 | # Where to pull the SeLion-Grid artifact from REPO = 'snapshots' || REPO = 'releases' 14 | sed -i.bkp -e "s/%REPO%/$REPO/g" ./Dockerfile 15 | # SeLion-Grid artifact version 16 | sed -i.bkp -e "s/%SELION_GRID_VERSION%/$SELION_GRID_VERSION/g" ./Dockerfile 17 | 18 | rm -f ./Dockerfile.bkp 19 | -------------------------------------------------------------------------------- /hub/Dockerfile.txt: -------------------------------------------------------------------------------- 1 | MAINTAINER Selion 2 | 3 | EXPOSE 4444 4 | 5 | # SeLion hub Configuration 6 | ENV GRID_NEW_SESSION_WAIT_TIMEOUT 600000 7 | ENV GRID_JETTY_MAX_THREADS 1000 8 | ENV GRID_NODE_POLLING 5000 9 | ENV GRID_CLEAN_UP_CYCLE 5000 10 | ENV GRID_TIMEOUT 180 11 | ENV GRID_BROWSER_TIMEOUT 120 12 | ENV GRID_MAX_SESSION 5 13 | ENV GRID_UNREGISTER_IF_STILL_DOWN_AFTER 30000 14 | # SeLion specific 15 | ENV SELGRID_UNIQUE_SESSION_COUNT 50 16 | ENV SELGRID_NODE_RECYCLE_THREAD_TIMEOUT 1200 17 | 18 | COPY generate_config $SELION_HOME/generate_config 19 | RUN chmod 755 $SELION_HOME/generate_config 20 | 21 | COPY entry_point.sh $SELION_HOME/entry_point.sh 22 | 23 | RUN chown -R seluser $SELION_HOME 24 | RUN chmod 755 $SELION_HOME/entry_point.sh 25 | 26 | USER seluser 27 | 28 | CMD $SELION_HOME/entry_point.sh 29 | -------------------------------------------------------------------------------- /hub/entry_point.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Assumptions: 4 | # Selion grid files in $SELION_HOME 5 | # $SELION_HOME defined in env 6 | # JAVA available on PATH 7 | 8 | CONF=$SELION_HOME/config/hubConfig.json 9 | 10 | $SELION_HOME/generate_config >$CONF 11 | 12 | echo "starting selenium hub with configuration:" 13 | cat $CONF 14 | 15 | function shutdown { 16 | echo "shutting down hub.." 17 | kill -s SIGTERM $NODE_PID 18 | wait $NODE_PID 19 | echo "shutdown complete" 20 | } 21 | 22 | if [ ! -z "$SELION_OPTS" ]; then 23 | echo "appending SeLion options: ${SELION_OPTS}" 24 | fi 25 | 26 | cd $SELION_HOME && java -DselionHome=$SELION_HOME ${JAVA_OPTS} \ 27 | -classpath $SELION_HOME/selenium-server-standalone.jar:$SELION_HOME/SeLion-Grid.jar \ 28 | -jar $SELION_HOME/SeLion-Grid.jar \ 29 | -role hub \ 30 | -hubConfig $CONF \ 31 | -continuousRestart false\ 32 | -uniqueSessionCount $SELGRID_UNIQUE_SESSION_COUNT \ 33 | -nodeRecycleThreadWaitTimeout $SELGRID_NODE_RECYCLE_THREAD_TIMEOUT \ 34 | ${SELION_OPTS} & 35 | NODE_PID=$! 36 | 37 | trap shutdown SIGTERM SIGINT 38 | wait $NODE_PID 39 | -------------------------------------------------------------------------------- /hub/generate.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | VERSION=$1 3 | 4 | echo FROM selion/base:$VERSION > ./Dockerfile 5 | cat ./Dockerfile.txt >> ./Dockerfile 6 | -------------------------------------------------------------------------------- /hub/generate_config: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo " 4 | { 5 | \"servlets\": [ 6 | \"com.paypal.selion.grid.servlets.LoginServlet\", 7 | \"com.paypal.selion.grid.servlets.ListAllNodes\", 8 | \"com.paypal.selion.grid.servlets.GridStatistics\", 9 | \"com.paypal.selion.grid.servlets.GridAutoUpgradeDelegateServlet\", 10 | \"com.paypal.selion.grid.servlets.GridForceRestartDelegateServlet\", 11 | \"com.paypal.selion.grid.servlets.PasswordChangeServlet\", 12 | \"com.paypal.selion.grid.servlets.TransferServlet\" 13 | ], 14 | \"withoutServlets\": [ 15 | \"org.openqa.grid.web.servlet.LifecycleServlet\", 16 | \"org.openqa.grid.web.servlet.Grid1HeartbeatServlet\" 17 | ], 18 | \"host\": null, 19 | \"port\": 4444, 20 | \"prioritizer\": null, 21 | \"capabilityMatcher\": \"com.paypal.selion.grid.matchers.MobileCapabilityMatcher\", 22 | \"throwOnCapabilityNotPresent\": true, 23 | \"newSessionWaitTimeout\": $GRID_NEW_SESSION_WAIT_TIMEOUT, 24 | \"jettyMaxThreads\": $GRID_JETTY_MAX_THREADS, 25 | \"nodePolling\": $GRID_NODE_POLLING, 26 | \"cleanUpCycle\": $GRID_CLEAN_UP_CYCLE, 27 | \"timeout\": $GRID_TIMEOUT, 28 | \"browserTimeout\": $GRID_BROWSER_TIMEOUT, 29 | \"maxSession\": $GRID_MAX_SESSION, 30 | \"unregisterIfStillDownAfter\": $GRID_UNREGISTER_IF_STILL_DOWN_AFTER 31 | }" 32 | -------------------------------------------------------------------------------- /nodeBase/Dockerfile.txt: -------------------------------------------------------------------------------- 1 | MAINTAINER Selion 2 | 3 | ENV DEBIAN_FRONTEND noninteractive 4 | ENV DEBCONF_NONINTERACTIVE_SEEN true 5 | 6 | #=================== 7 | # Timezone settings 8 | # Possible alternative: https://github.com/docker/docker/issues/3359#issuecomment-32150214 9 | #=================== 10 | ENV TZ "US/Pacific" 11 | RUN echo "US/Pacific" | sudo tee /etc/timezone \ 12 | && dpkg-reconfigure --frontend noninteractive tzdata 13 | 14 | USER root 15 | 16 | #============== 17 | # Xvfb 18 | #============== 19 | RUN apt-get clean \ 20 | && apt-get update -qqy \ 21 | && apt-get -qqy install \ 22 | xvfb \ 23 | && rm -rf /var/lib/apt/lists/* 24 | 25 | #============================== 26 | # Scripts to run Selion Node 27 | #============================== 28 | COPY \ 29 | entry_point.sh \ 30 | functions.sh \ 31 | $SELION_HOME/ 32 | RUN chmod +x $SELION_HOME/entry_point.sh 33 | 34 | #============================ 35 | # Some configuration options 36 | #============================ 37 | ENV SCREEN_WIDTH 1360 38 | ENV SCREEN_HEIGHT 1020 39 | ENV SCREEN_DEPTH 24 40 | ENV DISPLAY :99.0 41 | 42 | RUN chown -R seluser $SELION_HOME 43 | 44 | USER seluser 45 | 46 | CMD $SELION_HOME/entry_point.sh 47 | -------------------------------------------------------------------------------- /nodeBase/entry_point.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | export GEOMETRY="$SCREEN_WIDTH""x""$SCREEN_HEIGHT""x""$SCREEN_DEPTH" 3 | 4 | if [ ! -e $SELION_HOME/config.json ]; then 5 | echo No SeLion Node configuration file, the node-base image is not intended to be run directly. 1>&2 6 | exit 1 7 | fi 8 | 9 | if [ -z "$HUB_PORT_4444_TCP_ADDR" ]; then 10 | echo Not linked with a running Hub container 1>&2 11 | exit 1 12 | fi 13 | 14 | function shutdown { 15 | kill -s SIGTERM $NODE_PID 16 | wait $NODE_PID 17 | } 18 | 19 | REMOTE_HOST_PARAM="" 20 | if [ ! -z "$REMOTE_HOST" ]; then 21 | echo "REMOTE_HOST variable is set, appending -remoteHost" 22 | REMOTE_HOST_PARAM="-remoteHost $REMOTE_HOST" 23 | fi 24 | 25 | if [ ! -z "$SELION_OPTS" ]; then 26 | echo "appending SeLion options: ${SELION_OPTS}" 27 | fi 28 | 29 | # TODO: Look into http://www.seleniumhq.org/docs/05_selenium_rc.jsp#browser-side-logs 30 | 31 | cd $SELION_HOME && xvfb-run --server-args="$DISPLAY -screen 0 $GEOMETRY -ac +extension RANDR" \ 32 | java -DselionHome=$SELION_HOME -jar $SELION_HOME/SeLion-Grid.jar \ 33 | ${JAVA_OPTS} \ 34 | -role node \ 35 | -hub http://$HUB_PORT_4444_TCP_ADDR:$HUB_PORT_4444_TCP_PORT/grid/register \ 36 | -continuousRestart false \ 37 | ${REMOTE_HOST_PARAM} \ 38 | -nodeConfig $SELION_HOME/config.json \ 39 | ${SELION_OPTS} & 40 | NODE_PID=$! 41 | 42 | trap shutdown SIGTERM SIGINT 43 | wait $NODE_PID 44 | -------------------------------------------------------------------------------- /nodeBase/functions.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # https://github.com/SeleniumHQ/docker-selenium/issues/184 4 | function get_server_num() { 5 | echo $(echo $DISPLAY | sed -r -e 's/([^:]+)?:([0-9]+)(\.[0-9]+)?/\2/') 6 | } 7 | -------------------------------------------------------------------------------- /nodeBase/generate.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | VERSION=$1 3 | 4 | echo FROM selion/base:$VERSION > ./Dockerfile 5 | cat ./Dockerfile.txt >> ./Dockerfile 6 | -------------------------------------------------------------------------------- /nodeChrome/Dockerfile.txt: -------------------------------------------------------------------------------- 1 | MAINTAINER Selion 2 | 3 | USER root 4 | 5 | #============================================ 6 | # Google Chrome 7 | #============================================ 8 | # can specify versions by CHROME_VERSION; 9 | # e.g. google-chrome-stable=53.0.2785.101-1 10 | # google-chrome-beta=53.0.2785.92-1 11 | # google-chrome-unstable=54.0.2840.14-1 12 | # latest (equivalent to google-chrome-stable) 13 | # google-chrome-beta (pull latest beta) 14 | #============================================ 15 | ARG CHROME_VERSION="google-chrome-stable" 16 | RUN wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - \ 17 | && echo "deb http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google-chrome.list \ 18 | && apt-get update -qqy \ 19 | && apt-get -qqy install \ 20 | ${CHROME_VERSION:-google-chrome-stable} \ 21 | && rm /etc/apt/sources.list.d/google-chrome.list \ 22 | && rm -rf /var/lib/apt/lists/* /var/cache/apt/* 23 | 24 | #================== 25 | # Chrome webdriver 26 | #================== 27 | ENV CHROME_DRIVER_VERSION 2.25 28 | RUN wget --no-verbose -O /tmp/chromedriver_linux64.zip https://chromedriver.storage.googleapis.com/$CHROME_DRIVER_VERSION/chromedriver_linux64.zip \ 29 | && rm -rf $SELION_HOME/chromedriver \ 30 | && unzip /tmp/chromedriver_linux64.zip -d $SELION_HOME \ 31 | && rm /tmp/chromedriver_linux64.zip 32 | 33 | #======================== 34 | # Selenium Configuration 35 | #======================== 36 | COPY config.json $SELION_HOME/config.json 37 | 38 | #================================= 39 | # Chrome Launch Script Modication 40 | #================================= 41 | COPY chrome_launcher.sh /opt/google/chrome/google-chrome 42 | RUN chmod +x /opt/google/chrome/google-chrome 43 | 44 | RUN chown -R seluser $SELION_HOME 45 | 46 | USER seluser 47 | -------------------------------------------------------------------------------- /nodeChrome/chrome_launcher.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Copyright (c) 2011 The Chromium Authors. All rights reserved. 4 | # Use of this source code is governed by a BSD-style license that can be 5 | # found in the LICENSE file. 6 | 7 | # Let the wrapped binary know that it has been run through the wrapper. 8 | export CHROME_WRAPPER="`readlink -f "$0"`" 9 | 10 | HERE="`dirname "$CHROME_WRAPPER"`" 11 | 12 | # Check if the CPU supports SSE2. If not, try to pop up a dialog to explain the 13 | # problem and exit. Otherwise the browser will just crash with a SIGILL. 14 | # http://crbug.com/348761 15 | grep ^flags /proc/cpuinfo|grep -qs sse2 16 | if [ $? != 0 ]; then 17 | SSE2_DEPRECATION_MSG="This computer can no longer run Google Chrome because \ 18 | its hardware is no longer supported." 19 | if which zenity &> /dev/null; then 20 | zenity --warning --text="$SSE2_DEPRECATION_MSG" 21 | elif which gmessage &> /dev/null; then 22 | gmessage "$SSE2_DEPRECATION_MSG" 23 | elif which xmessage &> /dev/null; then 24 | xmessage "$SSE2_DEPRECATION_MSG" 25 | else 26 | echo "$SSE2_DEPRECATION_MSG" 1>&2 27 | fi 28 | exit 1 29 | fi 30 | 31 | # We include some xdg utilities next to the binary, and we want to prefer them 32 | # over the system versions when we know the system versions are very old. We 33 | # detect whether the system xdg utilities are sufficiently new to be likely to 34 | # work for us by looking for xdg-settings. If we find it, we leave $PATH alone, 35 | # so that the system xdg utilities (including any distro patches) will be used. 36 | if ! which xdg-settings &> /dev/null; then 37 | # Old xdg utilities. Prepend $HERE to $PATH to use ours instead. 38 | export PATH="$HERE:$PATH" 39 | else 40 | # Use system xdg utilities. But first create mimeapps.list if it doesn't 41 | # exist; some systems have bugs in xdg-mime that make it fail without it. 42 | xdg_app_dir="${XDG_DATA_HOME:-$HOME/.local/share/applications}" 43 | mkdir -p "$xdg_app_dir" 44 | [ -f "$xdg_app_dir/mimeapps.list" ] || touch "$xdg_app_dir/mimeapps.list" 45 | fi 46 | 47 | # Always use our versions of ffmpeg libs. 48 | # This also makes RPMs find the compatibly-named library symlinks. 49 | if [[ -n "$LD_LIBRARY_PATH" ]]; then 50 | LD_LIBRARY_PATH="$HERE:$HERE/lib:$LD_LIBRARY_PATH" 51 | else 52 | LD_LIBRARY_PATH="$HERE:$HERE/lib" 53 | fi 54 | export LD_LIBRARY_PATH 55 | 56 | export CHROME_VERSION_EXTRA="stable" 57 | 58 | # We don't want bug-buddy intercepting our crashes. http://crbug.com/24120 59 | export GNOME_DISABLE_CRASH_DIALOG=SET_BY_GOOGLE_CHROME 60 | 61 | # Automagically migrate user data directory. 62 | # TODO(phajdan.jr): Remove along with migration code in the browser for M33. 63 | if [[ -n "" ]]; then 64 | if [[ ! -d "" ]]; then 65 | "$HERE/chrome" "--migrate-data-dir-for-sxs=" \ 66 | --enable-logging=stderr --log-level=0 67 | fi 68 | fi 69 | 70 | # Make sure that the profile directory specified in the environment, if any, 71 | # overrides the default. 72 | if [[ -n "$CHROME_USER_DATA_DIR" ]]; then 73 | PROFILE_DIRECTORY_FLAG="--user-data-dir=$CHROME_USER_DATA_DIR" 74 | fi 75 | 76 | # Sanitize std{in,out,err} because they'll be shared with untrusted child 77 | # processes (http://crbug.com/376567). 78 | exec < /dev/null 79 | exec > >(exec cat) 80 | exec 2> >(exec cat >&2) 81 | 82 | # Note: exec -a below is a bashism. 83 | # DOCKER SELENIUM NOTE: Strait copy of script installed by Chrome with the exception of adding 84 | # the --no-sandbox flag here. 85 | exec -a "$0" "$HERE/chrome" --no-sandbox "$PROFILE_DIRECTORY_FLAG" \ 86 | "$@" 87 | exec -a "$0" /etc/alternatives/google-chrome --no-sandbox "$@" 88 | -------------------------------------------------------------------------------- /nodeChrome/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "capabilities": [ 3 | { 4 | "browserName": "chrome", 5 | "maxInstances": 1, 6 | "acceptSslCerts": true, 7 | "javascriptEnabled": true, 8 | "takesScreenshot": true 9 | } 10 | ], 11 | "servlets": [ 12 | "com.paypal.selion.node.servlets.LogServlet", 13 | "com.paypal.selion.node.servlets.NodeForceRestartServlet" 14 | ], 15 | "cleanUpCycle": 30000, 16 | "timeout": 120, 17 | "registerCycle": 5000, 18 | "proxy": "com.paypal.selion.proxy.SeLionRemoteProxy", 19 | "maxSession": 1, 20 | "port": 5555, 21 | "register": true 22 | } 23 | -------------------------------------------------------------------------------- /nodeChrome/generate.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | VERSION=$1 3 | 4 | echo FROM selion/node-base:$VERSION > ./Dockerfile 5 | cat ./Dockerfile.txt >> ./Dockerfile 6 | -------------------------------------------------------------------------------- /nodeFirefox/Dockerfile.txt: -------------------------------------------------------------------------------- 1 | MAINTAINER Selion 2 | 3 | USER root 4 | 5 | #========= 6 | # Firefox 7 | #========= 8 | RUN apt-get update -qqy \ 9 | && apt-get -qqy --no-install-recommends install \ 10 | firefox \ 11 | && rm -rf /var/lib/apt/lists/* 12 | 13 | #======================== 14 | # Selenium Configuration 15 | #======================== 16 | COPY config.json $SELION_HOME/config.json 17 | 18 | RUN chown -R seluser $SELION_HOME 19 | USER seluser 20 | -------------------------------------------------------------------------------- /nodeFirefox/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "capabilities": [ 3 | { 4 | "browserName": "firefox", 5 | "maxInstances": 1, 6 | "acceptSslCerts": true, 7 | "javascriptEnabled": true, 8 | "takesScreenshot": true, 9 | "marionette": false 10 | } 11 | ], 12 | "servlets": [ 13 | "com.paypal.selion.node.servlets.LogServlet", 14 | "com.paypal.selion.node.servlets.NodeForceRestartServlet" 15 | ], 16 | "cleanUpCycle": 30000, 17 | "timeout": 120, 18 | "registerCycle": 5000, 19 | "proxy": "com.paypal.selion.proxy.SeLionRemoteProxy", 20 | "maxSession": 1, 21 | "port": 5555, 22 | "register": true 23 | } 24 | -------------------------------------------------------------------------------- /nodeFirefox/generate.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | VERSION=$1 3 | 4 | echo FROM selion/node-base:$VERSION > ./Dockerfile 5 | cat ./Dockerfile.txt >> ./Dockerfile 6 | -------------------------------------------------------------------------------- /nodePhantomjs/Dockerfile.txt: -------------------------------------------------------------------------------- 1 | MAINTAINER Selion 2 | 3 | ENV PJS_VERSION 2.1.1 4 | 5 | USER root 6 | 7 | #============== 8 | # PhantomJS 9 | #============== 10 | RUN apt-get update -y 11 | RUN apt-get install bzip2 libfreetype6 libfontconfig1 -y 12 | COPY deps/* / 13 | RUN tar -xvjf phantomjs-$PJS_VERSION-linux-x86_64.tar.bz2 && rm phantomjs-$PJS_VERSION-linux-x86_64.tar.bz2 14 | RUN mv /phantomjs-$PJS_VERSION-linux-x86_64 /usr/local/phantomjs-$PJS_VERSION-linux-x86_64 15 | RUN ln -s /usr/local/phantomjs-$PJS_VERSION-linux-x86_64/bin/phantomjs $SELION_HOME/phantomjs 16 | 17 | #======================== 18 | # Selenium Configuration 19 | #======================== 20 | COPY config.json $SELION_HOME/config.json 21 | 22 | RUN chown -R seluser $SELION_HOME 23 | USER seluser 24 | -------------------------------------------------------------------------------- /nodePhantomjs/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "capabilities": [ 3 | { 4 | "browserName": "phantomjs", 5 | "maxInstances": 1, 6 | "acceptSslCerts": true, 7 | "javascriptEnabled": true, 8 | "takesScreenshot": true 9 | } 10 | ], 11 | "servlets": [ 12 | "com.paypal.selion.node.servlets.LogServlet", 13 | "com.paypal.selion.node.servlets.NodeForceRestartServlet" 14 | ], 15 | "cleanUpCycle": 30000, 16 | "timeout": 120, 17 | "registerCycle": 5000, 18 | "proxy": "com.paypal.selion.proxy.SeLionRemoteProxy", 19 | "maxSession": 1, 20 | "port": 5555, 21 | "register": true 22 | } 23 | -------------------------------------------------------------------------------- /nodePhantomjs/deps/phantomjs-2.1.1-linux-x86_64.tar.bz2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paypal/docker-selion/f264f954b1c400c570899438fb5d9ac7d022e378/nodePhantomjs/deps/phantomjs-2.1.1-linux-x86_64.tar.bz2 -------------------------------------------------------------------------------- /nodePhantomjs/generate.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | VERSION=$1 3 | 4 | echo FROM selion/node-base:$VERSION > ./Dockerfile 5 | cat ./Dockerfile.txt >> ./Dockerfile 6 | -------------------------------------------------------------------------------- /sa-test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | VERSION=${VERSION-develop} 3 | SELION_VERSION=${SELION_VERSION} 4 | 5 | function build_test_container { 6 | echo Building test container image 7 | docker build -t selion/smoketest:$VERSION ./test 8 | } 9 | 10 | function teardown { 11 | echo Tearing down Selion standalone-$BROWSER container 12 | docker stop $SA_NAME 13 | docker rm $SA_NAME 14 | echo Removing the test container 15 | docker rm $TEST_CONTAINER 16 | } 17 | 18 | function test_standalone { 19 | BROWSER=$1 20 | echo Starting Selion standalone-$BROWSER container 21 | 22 | SA=$(docker run -d selion/standalone-$BROWSER:$VERSION) 23 | sleep 2 24 | SA_NAME=$(docker inspect -f '{{ .Name }}' $SA | sed s:/::) 25 | 26 | echo Running test container... 27 | docker run -it -v /dev/shm:/dev/shm --link $SA_NAME:hub \ 28 | -e BROWSER=$BROWSER \ 29 | -e TEST_SUITE=StandaloneSuite.xml \ 30 | -e SELION_VERSION=$SELION_VERSION \ 31 | selion/smoketest:$VERSION 32 | 33 | STATUS=$? 34 | TEST_CONTAINER=$(docker ps -aq | head -1) 35 | 36 | if [ ! $STATUS == 0 ]; then 37 | echo Failed 38 | teardown 39 | exit 1 40 | fi 41 | teardown 42 | } 43 | 44 | #------------- 45 | # main 46 | #------------- 47 | build_test_container 48 | 49 | test_standalone firefox 50 | test_standalone chrome 51 | test_standalone phantomjs 52 | -------------------------------------------------------------------------------- /standaloneChrome/Dockerfile.txt: -------------------------------------------------------------------------------- 1 | MAINTAINER Selion 2 | 3 | USER root 4 | 5 | #==================================== 6 | # Scripts to run Standalone 7 | #==================================== 8 | COPY entry_point.sh $SELION_HOME/entry_point.sh 9 | RUN chmod +x $SELION_HOME/entry_point.sh 10 | 11 | #========================================== 12 | # Don't need this file from the base image 13 | #========================================== 14 | RUN rm $SELION_HOME/config.json 15 | 16 | USER seluser 17 | 18 | EXPOSE 4444 19 | -------------------------------------------------------------------------------- /standaloneChrome/entry_point.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | source $SELION_HOME/functions.sh 4 | 5 | export GEOMETRY="$SCREEN_WIDTH""x""$SCREEN_HEIGHT""x""$SCREEN_DEPTH" 6 | 7 | function shutdown { 8 | kill -s SIGTERM $NODE_PID 9 | wait $NODE_PID 10 | } 11 | 12 | if [ ! -z "$SELION_OPTS" ]; then 13 | echo "appending SeLion options: ${SELION_OPTS}" 14 | fi 15 | 16 | SERVERNUM=$(get_server_num) 17 | cd $SELION_HOME && xvfb-run -n $SERVERNUM --server-args="-screen 0 $GEOMETRY -ac +extension RANDR" \ 18 | java -DselionHome=$SELION_HOME -jar $SELION_HOME/SeLion-Grid.jar \ 19 | ${JAVA_OPTS} \ 20 | -continuousRestart false \ 21 | ${SELION_OPTS} & 22 | NODE_PID=$! 23 | 24 | trap shutdown SIGTERM SIGINT 25 | wait $NODE_PID 26 | -------------------------------------------------------------------------------- /standaloneChrome/generate.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | VERSION=$1 3 | 4 | echo FROM selion/node-chrome:$VERSION > ./Dockerfile 5 | cat ./Dockerfile.txt >> ./Dockerfile 6 | -------------------------------------------------------------------------------- /standaloneFirefox/Dockerfile.txt: -------------------------------------------------------------------------------- 1 | MAINTAINER Selion 2 | 3 | USER root 4 | 5 | #==================================== 6 | # Scripts to run Standalone 7 | #==================================== 8 | COPY entry_point.sh $SELION_HOME/entry_point.sh 9 | RUN chmod +x $SELION_HOME/entry_point.sh 10 | 11 | #========================================== 12 | # Don't need this file from the base image 13 | #========================================== 14 | RUN rm $SELION_HOME/config.json 15 | 16 | USER seluser 17 | 18 | EXPOSE 4444 19 | -------------------------------------------------------------------------------- /standaloneFirefox/entry_point.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | source $SELION_HOME/functions.sh 4 | 5 | export GEOMETRY="$SCREEN_WIDTH""x""$SCREEN_HEIGHT""x""$SCREEN_DEPTH" 6 | 7 | function shutdown { 8 | kill -s SIGTERM $NODE_PID 9 | wait $NODE_PID 10 | } 11 | 12 | if [ ! -z "$SELION_OPTS" ]; then 13 | echo "appending SeLion options: ${SELION_OPTS}" 14 | fi 15 | 16 | SERVERNUM=$(get_server_num) 17 | cd $SELION_HOME && xvfb-run -n $SERVERNUM --server-args="-screen 0 $GEOMETRY -ac +extension RANDR" \ 18 | java -Dwebdriver.firefox.marionette=false -DselionHome=$SELION_HOME -jar $SELION_HOME/SeLion-Grid.jar \ 19 | ${JAVA_OPTS} \ 20 | -continuousRestart false \ 21 | ${SELION_OPTS} & 22 | NODE_PID=$! 23 | 24 | trap shutdown SIGTERM SIGINT 25 | wait $NODE_PID 26 | -------------------------------------------------------------------------------- /standaloneFirefox/generate.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | VERSION=$1 3 | 4 | echo FROM selion/node-firefox:$VERSION > ./Dockerfile 5 | cat ./Dockerfile.txt >> ./Dockerfile 6 | -------------------------------------------------------------------------------- /standalonePhantomjs/Dockerfile.txt: -------------------------------------------------------------------------------- 1 | MAINTAINER Selion 2 | 3 | USER root 4 | 5 | #==================================== 6 | # Scripts to run Standalone 7 | #==================================== 8 | COPY entry_point.sh $SELION_HOME/entry_point.sh 9 | RUN chmod +x $SELION_HOME/entry_point.sh 10 | 11 | #========================================== 12 | # Don't need this file from the base image 13 | #========================================== 14 | RUN rm $SELION_HOME/config.json 15 | 16 | USER seluser 17 | 18 | EXPOSE 4444 19 | -------------------------------------------------------------------------------- /standalonePhantomjs/entry_point.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | source $SELION_HOME/functions.sh 4 | 5 | export GEOMETRY="$SCREEN_WIDTH""x""$SCREEN_HEIGHT""x""$SCREEN_DEPTH" 6 | 7 | function shutdown { 8 | kill -s SIGTERM $NODE_PID 9 | wait $NODE_PID 10 | } 11 | 12 | if [ ! -z "$SELION_OPTS" ]; then 13 | echo "appending SeLion options: ${SELION_OPTS}" 14 | fi 15 | 16 | SERVERNUM=$(get_server_num) 17 | cd $SELION_HOME && xvfb-run -n $SERVERNUM --server-args="-screen 0 $GEOMETRY -ac +extension RANDR" \ 18 | java -DselionHome=$SELION_HOME -jar $SELION_HOME/SeLion-Grid.jar \ 19 | ${JAVA_OPTS} \ 20 | -continuousRestart false \ 21 | ${SELION_OPTS} & 22 | NODE_PID=$! 23 | 24 | trap shutdown SIGTERM SIGINT 25 | wait $NODE_PID 26 | -------------------------------------------------------------------------------- /standalonePhantomjs/generate.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | VERSION=$1 3 | 4 | echo FROM selion/node-phantomjs:$VERSION > ./Dockerfile 5 | cat ./Dockerfile.txt >> ./Dockerfile 6 | -------------------------------------------------------------------------------- /test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | VERSION=${VERSION-develop} 3 | SELION_VERSION=${SELION_VERSION} 4 | 5 | function build_test_container { 6 | echo Building test container image 7 | docker build -t selion/smoketest:$VERSION ./test 8 | } 9 | 10 | function startup { 11 | echo 'Starting Selion Hub Container ...' 12 | HUB=$(docker run -d selion/hub:$VERSION) 13 | HUB_NAME=$(docker inspect -f '{{ .Name }}' $HUB | sed s:/::) 14 | echo 'Waiting for Hub to come online ...' 15 | docker logs -f $HUB & 16 | sleep 2 17 | 18 | echo 'Starting Selion Chrome node ...' 19 | NODE_CHROME=$(docker run -d --link $HUB_NAME:hub -v /dev/shm:/dev/shm selion/node-chrome:$VERSION) 20 | echo 'Starting Selion Firefox node ...' 21 | NODE_FIREFOX=$(docker run -d --link $HUB_NAME:hub selion/node-firefox:$VERSION) 22 | echo 'Starting Selion Phantomjs node ...' 23 | NODE_PHANTOMJS=$(docker run -d --link $HUB_NAME:hub selion/node-phantomjs:$VERSION) 24 | docker logs -f $NODE_CHROME & 25 | docker logs -f $NODE_FIREFOX & 26 | docker logs -f $NODE_PHANTOMJS & 27 | echo 'Waiting for nodes to register and come online ...' 28 | sleep 3 29 | } 30 | 31 | function teardown { 32 | echo Removing the test container 33 | docker rm $TEST_CONTAINER 34 | 35 | echo Tearing down Selion Chrome Node container 36 | docker stop $NODE_CHROME 37 | docker rm $NODE_CHROME 38 | 39 | echo Tearing down Selion Firefox Node container 40 | docker stop $NODE_FIREFOX 41 | docker rm $NODE_FIREFOX 42 | 43 | echo Tearing down Selion Phantomjs Node container 44 | docker stop $NODE_PHANTOMJS 45 | docker rm $NODE_PHANTOMJS 46 | 47 | echo Tearing down Selion Hub container 48 | docker stop $HUB 49 | docker rm $HUB 50 | } 51 | 52 | function test_nodes { 53 | BROWSER=$1 54 | 55 | echo Running Node tests ... 56 | docker run -it --link $HUB_NAME:hub \ 57 | -e TEST_SUITE=GridSuite.xml \ 58 | -e SELION_VERSION=$SELION_VERSION \ 59 | selion/smoketest:$VERSION 60 | 61 | STATUS=$? 62 | TEST_CONTAINER=$(docker ps -aq | head -1) 63 | 64 | if [ ! $STATUS == 0 ]; then 65 | echo Failed 66 | teardown 67 | exit 1 68 | fi 69 | } 70 | 71 | #------------- 72 | # main 73 | #------------- 74 | 75 | build_test_container 76 | startup 77 | test_nodes 78 | teardown 79 | -------------------------------------------------------------------------------- /test/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM maven:3.3.9-jdk-8-alpine 2 | MAINTAINER Selion 3 | 4 | ADD . /usr/src/app 5 | WORKDIR /usr/src/app 6 | RUN rm Dockerfile 7 | 8 | CMD mvn -B -q -s settings.xml test \ 9 | -Dselion.version=$SELION_VERSION \ 10 | -DSELION_BROWSER=$BROWSER \ 11 | -DsuiteXmlFile=$TEST_SUITE \ 12 | -DSELION_SELENIUM_HOST=$HUB_PORT_4444_TCP_ADDR 13 | -------------------------------------------------------------------------------- /test/generate.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | docker run -it --rm \ 3 | -v "$PWD":/usr/src/mymaven \ 4 | -w /usr/src/mymaven maven:3.3.9-jdk-8-alpine \ 5 | mvn -DskipTests -Dselion.version=$1 -B -q -s settings.xml clean package 6 | -------------------------------------------------------------------------------- /test/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | com.paypal.selion.docker 5 | smoke-test 6 | develop 7 | smoke-test 8 | jar 9 | 10 | 11 | 12 | 13 | com.paypal.selion 14 | SeLion-Project-BOM 15 | ${selion.version} 16 | pom 17 | import 18 | 19 | 20 | 21 | 22 | 23 | 24 | com.paypal.selion 25 | SeLion 26 | ${selion.version} 27 | test 28 | 29 | 30 | 31 | 32 | 33 | 34 | org.apache.maven.plugins 35 | maven-surefire-plugin 36 | 2.19.1 37 | 38 | 39 | src/test/resources/${suiteXmlFile} 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /test/settings.xml: -------------------------------------------------------------------------------- 1 | 2 | .m2/ 3 | 4 | 5 | 6 | sonatype 7 | 8 | 9 | sonatype-nexus-snapshots 10 | https://oss.sonatype.org/content/repositories/snapshots 11 | 12 | 13 | 14 | 15 | 16 | 17 | sonatype 18 | 19 | 20 | -------------------------------------------------------------------------------- /test/src/test/java/SimpleTest.java: -------------------------------------------------------------------------------- 1 | import com.paypal.selion.annotations.WebTest; 2 | import com.paypal.selion.platform.grid.Grid; 3 | 4 | import org.testng.annotations.Test; 5 | 6 | import static org.testng.Assert.assertTrue; 7 | 8 | public class SimpleTest { 9 | @Test 10 | @WebTest(additionalCapabilities="marionette:false") 11 | public void openWikipedia () { 12 | Grid.driver().get("http://www.wikipedia.org"); 13 | assertTrue(Grid.driver().getTitle().contains("Wikipedia")); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /test/src/test/resources/GridSuite.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /test/src/test/resources/StandaloneSuite.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /travis-deploy-to-docker-registry.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ################################################# 3 | # Deploys resulting containers to docker registry 4 | ################################################# 5 | 6 | DOCKER_USERNAME=${DOCKER_USERNAME-foo} 7 | DOCKER_PASSWORD=${DOCKER_PASSWORD-bar} 8 | 9 | # Deploy only if the following conditions are satisfied 10 | # 1. The build is for the project paypal/docker-selion, not on the fork 11 | # 3. The build is not on a pull request 12 | # 4. The build is on the develop branch 13 | if [ "$TRAVIS_REPO_SLUG" = "paypal/docker-selion" ] && [ "$TRAVIS_PULL_REQUEST" = "false" ] && [ "$TRAVIS_BRANCH" = "develop" ]; then 14 | echo "Deploying to Docker registry...\n" 15 | # verify that we are on develop branch, otherwise exit with error code 16 | git checkout develop 17 | output=$(git rev-parse --abbrev-ref HEAD) 18 | if [ "$output" = "develop" ]; then 19 | docker login -u "$DOCKER_USERNAME" -p "$DOCKER_PASSWORD" -e "$DOCKER_EMAIL" 20 | if [ $? -ne 0 ]; then 21 | echo "Failed to authenticate with Docker registry." 22 | exit 1 23 | fi 24 | VERSION="$VERSION" make dev_release 25 | else 26 | echo "Not on the develop branch." 27 | exit 1 28 | fi 29 | else 30 | echo "Deployment selection criteria not met." 31 | fi 32 | --------------------------------------------------------------------------------