├── .buildscript ├── deploy_snapshot.sh └── settings.xml ├── .gitignore ├── .travis.yml ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── clocker.bom ├── common ├── catalog │ ├── catalog.bom │ ├── common │ │ ├── ca.bom │ │ ├── common.bom │ │ ├── haproxy-template.bom │ │ └── haproxy.bom │ └── docker │ │ └── docker.bom ├── examples │ └── ca.yaml ├── pom.xml ├── resources │ ├── common │ │ └── certificate-functions.sh │ └── icons │ │ ├── centos.png │ │ ├── docker.png │ │ ├── haproxy.png │ │ └── openssl.png └── tests │ └── docker │ ├── common.tests.bom │ ├── docker.tests.bom │ └── tests.bom ├── feature ├── pom.xml └── src │ └── main │ └── feature │ └── feature.xml ├── kubernetes ├── catalog │ ├── catalog.bom │ └── kubernetes │ │ ├── kubernetes.bom │ │ ├── plugins.bom │ │ └── pods.bom ├── examples │ ├── kubernetes-minimal.yaml │ └── kubernetes.yaml ├── pom.xml ├── resources │ ├── icons │ │ ├── calico.png │ │ ├── flannel.png │ │ ├── kubernetes.png │ │ ├── openshift.png │ │ └── prometheus.png │ └── kubernetes │ │ ├── basic_auth.csv │ │ ├── kube-dns.yaml │ │ ├── kubernetes-dashboard.yaml │ │ ├── policy-controller.yaml │ │ └── prometheus.yaml └── tests │ └── kubernetes │ ├── kubernetes.tests.bom │ ├── tests.default.bom │ └── tests.no-shared-security-group.bom ├── pom.xml └── swarm ├── catalog ├── catalog.bom └── swarm │ └── swarm.bom ├── examples ├── custom-swarm.yaml ├── swarm-byon.yaml ├── swarm-minimal.yaml ├── swarm-using-external-resources.yaml └── swarm.yaml ├── pom.xml ├── resources └── icons │ └── swarm.png └── tests └── swarm ├── swarm.tests.bom ├── tests_with_shared_group.bom └── tests_without_shared_group.bom /.buildscript/deploy_snapshot.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Deploy jars to Sonatype's snapshot repo. 4 | # 5 | # Adapted from https://coderwall.com/p/9b_lfq and 6 | # http://benlimmer.com/2013/12/26/automatically-publish-javadoc-to-gh-pages-with-travis-ci/ 7 | 8 | SLUG="brooklyncentral/clocker" 9 | BRANCH="master" 10 | 11 | set -e 12 | 13 | if [ "$TRAVIS_REPO_SLUG" != "$SLUG" ]; then 14 | echo "Skipping snapshot deployment: wrong repository. Expected '$SLUG' but was '$TRAVIS_REPO_SLUG'." 15 | elif [ "$TRAVIS_PULL_REQUEST" != "false" ]; then 16 | echo "Skipping snapshot deployment: was pull request." 17 | elif [ "$TRAVIS_BRANCH" != "$BRANCH" ]; then 18 | echo "Skipping snapshot deployment: wrong branch. Expected '$BRANCH' but was '$TRAVIS_BRANCH'." 19 | else 20 | echo "Deploying snapshot..." 21 | mvn clean deploy --settings=".buildscript/settings.xml" -Dmaven.test.skip=true 22 | echo "Snapshot deployed!" 23 | fi 24 | -------------------------------------------------------------------------------- /.buildscript/settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | sonatype-nexus-snapshots 5 | ${env.CI_DEPLOY_USERNAME} 6 | ${env.CI_DEPLOY_PASSWORD} 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .classpath 2 | .project 3 | .settings 4 | eclipsebin 5 | 6 | bin 7 | gen 8 | out 9 | lib 10 | 11 | test-output 12 | 13 | target 14 | pom.xml.* 15 | release.properties 16 | 17 | .idea/* 18 | *.iml 19 | *.ipr 20 | *.iws 21 | classes 22 | 23 | *.log* 24 | obj 25 | *.swp 26 | .DS_Store 27 | *.swp 28 | 29 | .vagrant 30 | brooklyn-clocker/ 31 | external-resources/ 32 | 33 | .checkstyle 34 | 35 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # Copyright 2014-2015 by Cloudsoft Corporation Limited 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | sudo: false 16 | 17 | script: mvn clean install 18 | 19 | after_success: 20 | - .buildscript/deploy_snapshot.sh 21 | 22 | env: 23 | global: 24 | - secure: "NfjzLpDuRQozk7CXxiR+u9brsDn6j5CnAUwS0VGgVnGfR6p3TazemlhXCyDsYHzvc2CDm/R61lRe0KJ81ahUlDt6aQucjMfgRA1GOYJy9GuQQsIisr91bOrs3p1frsb0iYxqPU9Rp9uhhu6aG1Hk26hWu7uPR8wKlF0MX3v/QmY=" 25 | - secure: "L/iMDibl60hJX1Gax0n0mxNFbrIJ2Sg+KfagWEVpI0EgjF5VtwYkE+d0bTnC5jH/HpyDfA5SdnXMcSAyxcePJg2YHzk+bf2+55pc+os29dVSXRbL87bPJb9Rjl0IvxBOjREOXTLsA50ARnmrJElbAhYAdHJR0RaGhtRvQMiWpmA=" 26 | 27 | cache: 28 | directories: 29 | - $HOME/.m2 30 | notifications: 31 | email: 32 | - andrew.kennedy@cloudsoft.io 33 | - andrea.turli@cloudsoft.io 34 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Contributing to Clocker 2 | ==== 3 | 4 | Clocker is part of the [Brooklyn Central](https://github.com/brooklyncentral/) family of contributions to the [Apache Brooklyn](http://brooklyn.incubator.apache.org/) project, 5 | sponsored by [Cloudsoft](http://www.cloudsoftcorp.com/). 6 | 7 | All contributions are licensed under the [Apache 2.0](http://www.apache.org/licenses/LICENSE-2.0) license. Contributors should ensure they have permission from 8 | the owner or or own the copyright themselves, for any submission. 9 | 10 | Please read the [wiki](https://github.com/brooklyncentral/clocker/wiki) to find out more, or email us at [clocker@cloudsoft.io](mailto:clocker@cloudsoft.io). 11 | 12 | Thanks! 13 | 14 | _Andrew Kennedy_ [**@grkvlt**](http://github.com/grkvlt/) / [abstractvisitorpattern.co.uk](http://blog.abstractvisitorpattern.co.uk) 15 | 16 | ---- 17 | Copyright 2014-2015 by Cloudsoft Corporation and licensed under CC-BY-SA 4.0 18 | -------------------------------------------------------------------------------- /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 | [![Build Status](https://travis-ci.org/brooklyncentral/clocker.svg?branch=master)](https://travis-ci.org/brooklyncentral/clocker) 2 | 3 | # Clocker 4 | 5 | The current release is **2.0.0**, available in Maven Central. For more 6 | information, see the [official Clocker site](http://www.clocker.io/), including 7 | [documentation](http://www.clocker.io/docs/) and [tutorials](http://www.clocker.io/tutorials/). 8 | 9 | The development version is **2.1.0-SNAPSHOT**, available in the Sonatype Open-Source 10 | repository. To install this, follow the instructions below. 11 | 12 | ## Overview 13 | 14 | Clocker for [Apache Brooklyn](https://brooklyn.apache.org/) is a set of open 15 | source, Apache Licensed tools designed to make working with [Docker](https://www.docker.com/) 16 | containers as simple as a few clicks. Clocker contains [Brooklyn blueprints](http://brooklyn.apache.org/v/latest/start/blueprints.html) 17 | to enable deployment and management of [Docker Swarm](https://www.docker.com/products/docker-swarm) 18 | and [Kubernetes](http://kubernetes.io/) clusters. 19 | 20 | You will find the source code for the blueprints in this repository. 21 | 22 | * [Docker](./common/catalog/docker/) 23 | * [Swarm](./swarm/catalog/swarm/) 24 | * [Kubernetes](./kubernetes/catalog/kubernetes/) 25 | 26 | ## Getting Started 27 | 28 | ### Add Clocker to Brooklyn (Karaf Edition) 29 | 30 | Add catalog entries using the YAML below: 31 | 32 | ```YAML 33 | brooklyn.catalog: 34 | brooklyn.libraries: 35 | - "https://oss.sonatype.org/service/local/artifact/maven/redirect?r=snapshots&g=io.brooklyn.etcd&a=brooklyn-etcd&v=2.7.0-SNAPSHOT" 36 | - "https://oss.sonatype.org/service/local/artifact/maven/redirect?r=snapshots&g=io.brooklyn.clocker&a=clocker-common&v=2.1.0-SNAPSHOT" 37 | - "https://oss.sonatype.org/service/local/artifact/maven/redirect?r=snapshots&g=io.brooklyn.clocker&a=clocker-swarm&v=2.1.0-SNAPSHOT" 38 | - "https://oss.sonatype.org/service/local/artifact/maven/redirect?r=snapshots&g=io.brooklyn.clocker&a=clocker-kubernetes&v=2.1.0-SNAPSHOT" 39 | items: 40 | - classpath://io.brooklyn.clocker.swarm:swarm/catalog.bom 41 | - classpath://io.brooklyn.clocker.kubernetes:kubernetes/catalog.bom 42 | ``` 43 | 44 | ### Add Clocker to Brooklyn (Classic Edition) 45 | 46 | You must add the following JARs to `./lib/dropins`: 47 | 48 | * [brooklyn-etcd](https://oss.sonatype.org/service/local/artifact/maven/redirect?r=snapshots&g=io.brooklyn.etcd&a=brooklyn-etcd&v=2.7.0-SNAPSHOT) 49 | * [common](https://oss.sonatype.org/service/local/artifact/maven/redirect?r=snapshots&g=io.brooklyn.clocker&a=clocker-common&v=2.1.0-SNAPSHOT) 50 | * [swarm](https://oss.sonatype.org/service/local/artifact/maven/redirect?r=snapshots&g=io.brooklyn.clocker&a=clocker-swarm&v=2.1.0-SNAPSHOT) 51 | * [kubernetes](https://oss.sonatype.org/service/local/artifact/maven/redirect?r=snapshots&g=io.brooklyn.clocker&a=clocker-kubernetes&v=2.1.0-SNAPSHOT) 52 | 53 | Then add the catalog entries using the following YAML: 54 | 55 | ```YAML 56 | brooklyn.catalog: 57 | items: 58 | - classpath://swarm/catalog.bom 59 | - classpath://kubernetes/catalog.bom 60 | ``` 61 | 62 | ## Copyright 63 | 64 | The following icon images have been used, and their use here is believed to be 65 | acceptable under their licensing terms or fair use doctrine. The source URLs 66 | and other links given contain more details: 67 | 68 | - [`common/resources/icons/centos.png`](https://commons.wikimedia.org/wiki/File:Centos-logo-light.svg) Remixed version of freely available logo 69 | - [`common/resources/icons/docker.png`](https://www.docker.com/brand-guidelines) Icon taken from media kit 70 | - [`common/resources/icons/haproxy.png`](https://pbs.twimg.com/profile_images/737664607301566464/pmfqGAYU.jpg) Fair use of logo from Twitter account for open source project 71 | - [`common/resources/icons/openssl.png`](https://commons.wikimedia.org/wiki/File:OpenSSL_logo.png) Public domain image 72 | - [`swarm/resources/icons/swarm.png`](https://www.docker.com/sites/default/files/docker-swarm-hero2.png) Fair use of image from and also found in Docker media kit 73 | - [`kubernetes/resources/icons/calico.png`](https://github.com/projectcalico/calico/blob/master/images/favicon.png) APACHE 2.0 image 74 | - [`kubernetes/resources/icons/flannel.png`](https://github.com/coreos/flannel/blob/master/logos/flannel-horizontal-color.png) APACHE 2.0 image 75 | - [`kubernetes/resources/icons/kubernetes.png`](https://raw.githubusercontent.com/kubernetes/kubernetes/master/logo/logo.png) APACHE 2.0 image 76 | - [`kubernetes/resources/icons/prometheus.png`](https://github.com/prometheus/docs/blob/master/static/prometheus_logo.png) APACHE 2.0 image 77 | - [`kubernetes/resources/icons/openshift.png`](https://github.com/openshift/origin-web-console/blob/e7a0c0a8f703d5429f70b78223abb31856a66670/app/images/openshift-logo.svg) APACHE 2.0 image 78 | -------------------------------------------------------------------------------- /clocker.bom: -------------------------------------------------------------------------------- 1 | brooklyn.catalog: 2 | brooklyn.libraries: 3 | - "https://oss.sonatype.org/service/local/artifact/maven/redirect?r=snapshots&g=io.brooklyn.etcd&a=brooklyn-etcd&v=2.5.0-SNAPSHOT" 4 | - "https://oss.sonatype.org/service/local/artifact/maven/redirect?r=snapshots&g=io.brooklyn.clocker&a=clocker-common&v=2.1.0-SNAPSHOT" 5 | - "https://oss.sonatype.org/service/local/artifact/maven/redirect?r=snapshots&g=io.brooklyn.clocker&a=clocker-swarm&v=2.1.0-SNAPSHOT" 6 | - "https://oss.sonatype.org/service/local/artifact/maven/redirect?r=snapshots&g=io.brooklyn.clocker&a=clocker-kubernetes&v=2.1.0-SNAPSHOT" 7 | items: 8 | - classpath://io.brooklyn.clocker.swarm:swarm/catalog.bom 9 | - classpath://io.brooklyn.clocker.kubernetes:kubernetes/catalog.bom 10 | -------------------------------------------------------------------------------- /common/catalog/catalog.bom: -------------------------------------------------------------------------------- 1 | brooklyn.catalog: 2 | items: 3 | - classpath://common/common.bom 4 | - classpath://common/ca.bom 5 | - classpath://common/haproxy.bom 6 | - classpath://docker/docker.bom 7 | -------------------------------------------------------------------------------- /common/catalog/common/ca.bom: -------------------------------------------------------------------------------- 1 | brooklyn.catalog: 2 | version: "2.1.0-SNAPSHOT" # CLOCKER_VERSION 3 | publish: 4 | description: | 5 | An X.509 Certificate Authority tool using OpenSSL 6 | license_code: APACHE-2.0 7 | 8 | items: 9 | 10 | - id: ca-server 11 | name: "Certificate Authority Server" 12 | description: | 13 | An X.509 Certificate Authority tool with a simple REST API. 14 | 15 | Request creation of a certificate for a client with a POST request to 16 | '/generate/{nodeName}' with nodeName set to the IP address of the node. 17 | Download the CA certificate, client certificate and private key with GET 18 | requests to '/cert/{nodeName}/ca.pem' '/cert/{nodeName}/cert.pem' and 19 | '/cert/{nodeName}/key.pem' 20 | itemType: entity 21 | iconUrl: classpath://io.brooklyn.clocker.common:icons/openssl.png 22 | item: 23 | type: centos-software-process 24 | name: "authority" 25 | 26 | brooklyn.parameters: 27 | - name: ca.server.port 28 | label: "CA Server Port" 29 | description: | 30 | The external port the CA Server web service listens on 31 | type: integer 32 | default: 8080 33 | 34 | brooklyn.config: 35 | shell.env: 36 | COUNTRY: $brooklyn:config("country") 37 | STATE: $brooklyn:config("state") 38 | LOCALITY: $brooklyn:config("locality") 39 | ORGANIZATION_NAME: $brooklyn:config("organization.name") 40 | ORGANIZATION_UNIT: $brooklyn:config("organization.unit") 41 | COMMON_NAME: $brooklyn:config("common.name") 42 | EMAIL_ADDRESS: $brooklyn:config("email.address") 43 | CHALLENGE_PASSWORD: $brooklyn:config("challenge.password") 44 | OPTIONAL_COMPANY_NAME: $brooklyn:config("optional.company.name") 45 | CA_SERVER_PORT: $brooklyn:config("ca.server.port") 46 | INSTALL_DIR: $brooklyn:attributeWhenReady("install.dir") 47 | NODE_PATH: 48 | $brooklyn:formatString: 49 | - "%s/node_modules" 50 | - $brooklyn:attributeWhenReady("install.dir") 51 | 52 | install.command: | 53 | echo "[CLOCKER] Install OpenSSL" 54 | sudo yum install -y openssl 55 | 56 | echo "[CLOCKER] Install Node.js webapp prerequisites" 57 | curl --silent --location https://rpm.nodesource.com/setup_6.x | sudo bash - 58 | sudo yum install -y install nodejs 59 | npm config set prefix ${INSTALL_DIR} 60 | npm install express@4.13 61 | 62 | customize.command: | 63 | echo "[CLOCKER] Set up Bash OpenSSL scripts" 64 | cat > functions.sh <<-'EOF' 65 | function setup_structure() { 66 | sed -e "/copy_extensions/s/^# *//" -e "/^dir/c dir = $(pwd)" -e '/^#unique/s/#//' /etc/pki/tls/openssl.cnf > openssl.cnf 67 | mkdir certs crl newcerts private 68 | openssl rand -hex 16 > serial 69 | touch index.txt 70 | } 71 | 72 | function self_sign_ca_certificate () { 73 | echo "[CLOCKER] Generate a CA root certificate" 74 | openssl genrsa -out private/cakey.pem 2048 75 | openssl req -config openssl.cnf -new -key private/cakey.pem -days 1825 -out ca.csr <<-EOC 76 | ${COUNTRY:-.} 77 | ${STATE:-.} 78 | ${LOCALITY:-.} 79 | ${ORGANIZATION_NAME:-.} 80 | ${ORGANIZATION_UNIT:-.} 81 | ${COMMON_NAME:-'*'} 82 | ${EMAIL_ADDRESS:-.} 83 | ${CHALLENGE_PASSWORD:-.} 84 | ${OPTIONAL_COMPANY_NAME:-.} 85 | EOC 86 | yes | openssl ca -config openssl.cnf -selfsign -in ca.csr -out ca.pem -policy policy_anything -extensions v3_ca 87 | } 88 | 89 | function sign_cert () { 90 | csr_file=$1 91 | yes | openssl ca -config openssl.cnf -cert ca.pem -extensions usr_cert -policy policy_anything -in ${csr_file} 92 | } 93 | EOF 94 | 95 | 96 | cat > sign_cert.sh <<-'EOF' 97 | #!/usr/bin/env bash 98 | source functions.sh 99 | temp_request=$(mktemp) 100 | 101 | # cat all input to the temp request file 102 | cat > ${temp_request} 103 | 104 | sign_cert ${temp_request} || { 105 | res=$? 106 | echo Error signing certificate 107 | exit res 108 | } 109 | EOF 110 | chmod +x sign_cert.sh 111 | 112 | source functions.sh 113 | 114 | setup_structure 115 | 116 | echo "[CLOCKER] Set up Node.js web service" 117 | cat > webserver.js <<-EOF 118 | var http = require('http'); 119 | var fs = require('fs'); 120 | var express = require('express'); 121 | const spawn = require('child_process').spawn; 122 | 123 | const PORT=${CA_SERVER_PORT}; 124 | 125 | var server = express(); 126 | server.use('/cacert', express.static('cacert')); 127 | server.post("/sign", function(request, response) { 128 | console.log("POST received on " + request.url); 129 | var proc = spawn('./sign_cert.sh'); 130 | request.pipe(proc.stdin); 131 | proc.stdout.pipe(response); 132 | }); 133 | 134 | server.listen(PORT, function(req, res){ 135 | console.log("Server listening on port %s", PORT); 136 | }); 137 | EOF 138 | 139 | self_sign_ca_certificate 140 | mkdir cacert 141 | cp ca.pem cacert 142 | 143 | launch.command: | 144 | nohup node webserver.js > webserver.out 2> webserver.err & echo $! > ${PID_FILE} 145 | 146 | checkRunning.command: | 147 | ps -p $(cat ${PID_FILE}) 148 | 149 | stop.command: | 150 | kill -9 $(cat ${PID_FILE}) 151 | 152 | brooklyn.initializers: 153 | - type: org.apache.brooklyn.core.sensor.ssh.SshCommandSensor 154 | brooklyn.config: 155 | name: ca.cert 156 | description: | 157 | Present the CA certificate for the ca-server 158 | command: | 159 | [ -f ca.pem ] && cat ca.pem 160 | - type: org.apache.brooklyn.core.effector.ssh.SshCommandEffector 161 | brooklyn.config: 162 | name: generate 163 | description: | 164 | Generate public certificate and private key for a node 165 | parameters: 166 | nodeName: 167 | description: | 168 | IP address for the node 169 | command: | 170 | source functions.sh 171 | generate $(pwd) ${nodeName} 172 | - type: org.apache.brooklyn.core.effector.ssh.SshCommandEffector 173 | brooklyn.config: 174 | name: sign 175 | description: Take an X.509 Certificate Signing Request and return the signed certificate 176 | parameters: 177 | csr: 178 | description: Text of an X.509 Certificate Signing Request in PEM format 179 | command: | 180 | source functions.sh 181 | temp_request=$(mktemp) 182 | echo "$csr" >> ${temp_request} 183 | sign_cert ${temp_request} && rm -f ${temp_request} 184 | 185 | brooklyn.enrichers: 186 | - type: org.apache.brooklyn.enricher.stock.Transformer 187 | brooklyn.config: 188 | enricher.triggerSensors: 189 | - host.address 190 | enricher.targetSensor: $brooklyn:sensor("main.uri") 191 | enricher.targetValue: 192 | $brooklyn:formatString: 193 | - "http://%s:%d" 194 | - $brooklyn:attributeWhenReady("host.address") 195 | - $brooklyn:config("ca.server.port") 196 | -------------------------------------------------------------------------------- /common/catalog/common/common.bom: -------------------------------------------------------------------------------- 1 | brooklyn.catalog: 2 | version: "2.1.0-SNAPSHOT" # CLOCKER_VERSION 3 | publish: 4 | description: | 5 | Resources for common Apache Brooklyn entities 6 | license_code: APACHE-2.0 7 | 8 | items: 9 | - id: conditional-entity 10 | name: "Conditional Entity" 11 | description: | 12 | An entity that creates a child only if a configuration key is set 13 | itemType: entity 14 | item: 15 | type: org.apache.brooklyn.entity.stock.ConditionalEntity 16 | id: conditional-entity 17 | 18 | - id: child-software-process 19 | name: "Child Software Process" 20 | description: | 21 | A child entity that executes commands to run a process 22 | itemType: entity 23 | item: 24 | type: org.apache.brooklyn.entity.software.base.VanillaSoftwareProcess 25 | id: child-software-process 26 | 27 | - id: empty-software-process 28 | name: "Empty Software Process" 29 | description: | 30 | A startable entity to group child entities 31 | itemType: entity 32 | item: 33 | type: org.apache.brooklyn.entity.software.base.EmptySoftwareProcess 34 | id: empty-software-process 35 | 36 | - id: centos-software-process 37 | name: "CentOS Software Process" 38 | description: | 39 | An entity that executes commands to run a process 40 | 41 | Uses a CentOS 7.x Virtual Machine 42 | itemType: entity 43 | iconUrl: classpath://io.brooklyn.clocker.common:icons/centos.png 44 | item: 45 | type: org.apache.brooklyn.entity.software.base.VanillaSoftwareProcess 46 | id: centos-software-process 47 | brooklyn.config: 48 | dontRequireTtyForSudo: true 49 | provisioning.properties: 50 | osFamily: centos 51 | osVersionRegex: 7 52 | -------------------------------------------------------------------------------- /common/catalog/common/haproxy-template.bom: -------------------------------------------------------------------------------- 1 | brooklyn.catalog: 2 | items: 3 | - id: ca-server-template 4 | name: "Certificate Authority Server" 5 | description: | 6 | An X.509 Certificate Authority tool using OpenSSL 7 | itemType: template 8 | iconUrl: classpath://io.brooklyn.clocker.common:icons/openssl.png 9 | item: 10 | services: 11 | - type: ca-server 12 | 13 | - id: haproxy-load-balancer-template 14 | name: "HAProxy Load Balancer" 15 | description: | 16 | HAProxy load balancer entity 17 | itemType: template 18 | iconUrl: classpath://io.brooklyn.clocker.common:icons/haproxy.png 19 | item: 20 | services: 21 | - type: haproxy-load-balancer -------------------------------------------------------------------------------- /common/catalog/common/haproxy.bom: -------------------------------------------------------------------------------- 1 | brooklyn.catalog: 2 | version: "2.1.0-SNAPSHOT" # CLOCKER_VERSION 3 | publish: 4 | description: | 5 | HAProxy load balancer 6 | license_code: APACHE-2.0 7 | 8 | items: 9 | 10 | - id: haproxy-load-balancer 11 | name: "HAProxy Load Balancer" 12 | description: | 13 | HAProxy load balancer entity 14 | itemType: entity 15 | iconUrl: classpath://io.brooklyn.clocker.common:icons/haproxy.png 16 | item: 17 | type: centos-software-process 18 | name: "haproxy-load-balancer" 19 | 20 | brooklyn.parameters: 21 | - name: haproxy.version 22 | label: "HAProxy Version" 23 | description: | 24 | The HAProxy version to install 25 | type: string 26 | default: "1.6.7" 27 | - name: haproxy.port 28 | label: "HAProxy Port" 29 | description: | 30 | Port that HAProxy should listen on 31 | type: integer 32 | default: 8000 33 | - name: haproxy.protocol 34 | label: "HAProxy Protocol" 35 | description: | 36 | Protocol to forward (either http or https) 37 | type: string 38 | default: "http" 39 | - name: haproxy.bind.options 40 | label: "HAProxy Bind Options" 41 | description: | 42 | Extra bind configuration such as TLS certificate paths 43 | type: string 44 | 45 | brooklyn.config: 46 | haproxy.bind.options: 47 | 48 | shell.env: 49 | HOST_ADDRESS: $brooklyn:attributeWhenReady("host.address") 50 | SUBNET_ADDRESS: $brooklyn:attributeWhenReady("host.subnet.address") 51 | INSTALL_DIR: $brooklyn:attributeWhenReady("install.dir") 52 | RUN_DIR: $brooklyn:attributeWhenReady("run.dir") 53 | HAPROXY_VERSION: $brooklyn:config("haproxy.version") 54 | HAPROXY_PORT: $brooklyn:config("haproxy.port") 55 | HAPROXY_PROTOCOL: $brooklyn:config("haproxy.protocol") 56 | HAPROXY_BIND_OPTIONS: $brooklyn:config("haproxy.bind.options") 57 | 58 | install.command: | 59 | sudo yum install -y kernel-headers --disableexcludes=all 60 | sudo yum install -y gcc make openssl-devel wget util-linux 61 | haproxy_major_minor=$(echo ${HAPROXY_VERSION} | cut -d. -f1,2) 62 | wget "http://www.haproxy.org/download/${haproxy_major_minor}/src/haproxy-${HAPROXY_VERSION}.tar.gz" 63 | tar zxf haproxy-${HAPROXY_VERSION}.tar.gz 64 | cd haproxy-${HAPROXY_VERSION} 65 | make TARGET=linux26 USE_OPENSSL=true 66 | sudo cp haproxy /usr/bin 67 | 68 | customize.command: | 69 | cat > haproxy.conf <<-EOF 70 | global 71 | daemon 72 | maxconn 256 73 | pidfile ${PID_FILE} 74 | defaults 75 | option http-server-close 76 | timeout connect 5000ms 77 | timeout client 60s 78 | timeout server 60s 79 | frontend www-${HAPROXY_PROTOCOL} 80 | bind *:${HAPROXY_PORT} ${HAPROXY_BIND_OPTIONS} 81 | reqadd X-Forwarded-Proto:\ ${HAPROXY_PROTOCOL} 82 | default_backend servers 83 | mode tcp 84 | option tcplog 85 | log 127.0.0.1 syslog 86 | EOF 87 | echo "backend servers" > servers.conf 88 | 89 | launch.command: | 90 | haproxy -f haproxy.conf -f servers.conf -c && 91 | haproxy -D -f haproxy.conf -f servers.conf -sf $(cat ${PID_FILE}) 92 | 93 | brooklyn.initializers: 94 | - type: org.apache.brooklyn.core.effector.ssh.SshCommandEffector 95 | brooklyn.config: 96 | name: configureEndpoints 97 | description: | 98 | Generate HAProxy configuration from endpoint list 99 | shell.env: 100 | HAPROXY_PROTOCOL: $brooklyn:config("haproxy.protocol") 101 | HAPROXY_ENDPOINTS: $brooklyn:attributeWhenReady("haproxy.endpoints") 102 | ENTITY_ID: $brooklyn:attributeWhenReady("entity.id") 103 | command: | 104 | set -x 105 | command -v haproxy >/dev/null 2>&1 || { echo >&2 "HAProxy is not installed yet. Exiting quietly."; exit 0; } 106 | ( 107 | flock 9 108 | cat > ${RUN_DIR}/servers.conf <<-EOF 109 | backend servers 110 | EOF 111 | if [ "${HAPROXY_PROTOCOL}" == "http" ]; then 112 | cat >> ${RUN_DIR}/servers.conf <<-EOF 113 | mode http 114 | option httpchk 115 | EOF 116 | fi 117 | cat >> ${RUN_DIR}/servers.conf <<-EOF 118 | balance roundrobin 119 | EOF 120 | for endpoint in $(echo ${HAPROXY_ENDPOINTS} | tr ',' ' ') ; do 121 | if [ "${HAPROXY_PROTOCOL}" == "http" ]; then 122 | echo " server node$((++n)) ${endpoint} check" >> ${RUN_DIR}/servers.conf 123 | else 124 | echo " server node$((++n)) ${endpoint} maxconn 32 ssl ca-file ${RUN_DIR}/ca.pem crt ${RUN_DIR}/cert.pem" >> ${RUN_DIR}/servers.conf 125 | fi 126 | done 127 | old_pid=$(cat ${RUN_DIR}/pid.txt) 128 | if [ ! -z $old_pid ]; then 129 | haproxy -D -f ${RUN_DIR}/haproxy.conf -f ${RUN_DIR}/servers.conf -st ${old_pid} 9>/dev/null 130 | # wait for the old process to die before leaving the critical section 131 | while test -d /proc/${old_pid} 2> /dev/null; do echo >&2 "waiting for ${old_pid} to die" ; sleep 1; done 132 | else 133 | echo >&2 "no previous process to wait for" 134 | fi 135 | ) 9>> /tmp/configure.${ENTITY_ID}.lock 136 | 137 | brooklyn.policies: 138 | - type: org.apache.brooklyn.policy.InvokeEffectorOnSensorChange 139 | brooklyn.config: 140 | effector: configureEndpoints 141 | sensor: $brooklyn:sensor("haproxy.endpoints") 142 | - type: org.apache.brooklyn.policy.InvokeEffectorOnSensorChange 143 | brooklyn.config: 144 | effector: configureEndpoints 145 | sensor: $brooklyn:sensor("service.isUp") 146 | 147 | brooklyn.enrichers: 148 | # Publish host+port as main.uri 149 | - type: org.apache.brooklyn.enricher.stock.Transformer 150 | brooklyn.config: 151 | uniqueTag: haproxy-endpoint-publisher 152 | enricher.triggerSensors: 153 | - $brooklyn:sensor("host.name") 154 | enricher.targetSensor: $brooklyn:sensor("org.apache.brooklyn.core.entity.Attributes", "main.uri") 155 | enricher.targetValue: 156 | $brooklyn:formatString: 157 | - "%s://%s:%d" 158 | - $brooklyn:config("haproxy.protocol") 159 | - $brooklyn:attributeWhenReady("host.name") 160 | - $brooklyn:config("haproxy.port") 161 | -------------------------------------------------------------------------------- /common/catalog/docker/docker.bom: -------------------------------------------------------------------------------- 1 | brooklyn.catalog: 2 | version: "2.1.0-SNAPSHOT" # CLOCKER_VERSION 3 | publish: 4 | description: | 5 | Resources for working with Docker Engine from Apache Brooklyn 6 | license_code: APACHE-2.0 7 | overview: README.md 8 | qa: tests/docker.tests.bom 9 | 10 | items: 11 | - classpath://common/common.bom 12 | - classpath://common/ca.bom 13 | 14 | - id: docker-engine 15 | name: "Docker Engine" 16 | description: | 17 | The engine for running Docker containers 18 | itemType: entity 19 | iconUrl: classpath://io.brooklyn.clocker.common:icons/docker.png 20 | item: 21 | type: centos-software-process 22 | id: docker-engine 23 | 24 | brooklyn.parameters: 25 | - name: docker.package 26 | label: "Docker Package" 27 | description: | 28 | The Docker Engine package to install 29 | type: string 30 | - name: docker.version 31 | label: "Docker Version" 32 | description: | 33 | The Docker Engine version to install 34 | type: string 35 | - name: docker.repository.url 36 | label: "Docker Repository URL" 37 | description: | 38 | The Docker repository URL to use for installation 39 | type: string 40 | - name: docker.gpgkey.url 41 | label: "Docker GPG Key URL" 42 | description: | 43 | The Docker GPG key URL to use to authenticate the installation 44 | type: string 45 | - name: docker.additionaloptions 46 | label: "Docker Additional Options" 47 | description: | 48 | The additional options to pass to the engine on startup 49 | type: string 50 | - name: image.preinstall 51 | label: "Image Pre-install" 52 | description: | 53 | A docker hub image id to pull after installation 54 | type: string 55 | default: brooklyncentral/centos:7 56 | 57 | brooklyn.initializers: 58 | - type: org.apache.brooklyn.entity.machine.AddMachineMetrics 59 | - type: org.apache.brooklyn.core.sensor.ssh.SshCommandSensor 60 | brooklyn.config: 61 | name: docker.version 62 | period: 5m 63 | command: | 64 | docker info | grep "^Server Version" | sed -e "s/^Server Version: //" 65 | - type: org.apache.brooklyn.core.sensor.ssh.SshCommandSensor 66 | brooklyn.config: 67 | name: docker.container.count 68 | period: 1m 69 | targetType: integer 70 | command: | 71 | docker ps -q | wc -l 72 | 73 | brooklyn.config: 74 | defaultDisplayName: "docker-engine" 75 | 76 | image.preinstall: brooklyncentral/centos:7 77 | 78 | shell.env: 79 | DOCKER_ADDITIONAL_OPTIONS: $brooklyn:config("docker.additionaloptions") 80 | HOST_NAME: $brooklyn:attributeWhenReady("host.name") 81 | HOST_ADDRESS: $brooklyn:attributeWhenReady("host.address") 82 | DOCKER_IMAGE_PREINSTALL: $brooklyn:config("image.preinstall") 83 | DOCKER_PACKAGE: $brooklyn:config("docker.package") 84 | DOCKER_VERSION: $brooklyn:config("docker.version") 85 | DOCKER_REPOSITORY_URL: $brooklyn:config("docker.repository.url") 86 | DOCKER_GPG_KEY_URL: $brooklyn:config("docker.gpgkey.url") 87 | ENTITY_ID: $brooklyn:attributeWhenReady("entity.id") 88 | APPLICATION_ID: $brooklyn:attributeWhenReady("application.id") 89 | CLOCKER_VERSION: "2.1.0-SNAPSHOT" 90 | 91 | install.command: | 92 | set -e # need all commands to execute successfully 93 | 94 | sudo yum -y update 95 | 96 | echo "[CLOCKER] Configuring package manager" 97 | if [[ "${DOCKER_REPOSITORY_URL}" && "${DOCKER_GPG_KEY_URL}" ]] ; then 98 | # Commercially Supported Docker Engine 99 | sudo rpm --import "${DOCKER_GPG_KEY_URL}" 100 | sudo yum install -y yum-utils 101 | sudo yum-config-manager --add-repo "${DOCKER_REPOSITORY_URL}" 102 | else 103 | # Open-Source Docker Engine 104 | sudo tee /etc/yum.repos.d/docker.repo <<-EOF 105 | [dockerrepo] 106 | name=Docker Repository 107 | baseurl=https://yum.dockerproject.org/repo/main/centos/\$releasever/ 108 | enabled=1 109 | gpgcheck=1 110 | gpgkey=https://yum.dockerproject.org/gpg 111 | EOF 112 | fi 113 | if [[ "${DOCKER_VERSION}" ]] ; then 114 | sudo yum -y install ${DOCKER_PACKAGE:-docker-engine}-${DOCKER_VERSION} 115 | else 116 | sudo yum -y install ${DOCKER_PACKAGE:-docker-engine} 117 | fi 118 | 119 | echo "[CLOCKER] Setting up Docker systemd service" 120 | sudo mkdir -p /etc/systemd/system/docker.service.d 121 | sudo tee /etc/systemd/system/docker.service.d/docker.conf <<-EOF 122 | [Service] 123 | # Need to clear the default first and then set a custom value 124 | ExecStart= 125 | ExecStart=/usr/bin/docker daemon \ 126 | -H unix:///var/run/docker.sock \ 127 | --api-cors-header="*" \ 128 | --config-file /etc/systemd/system/docker.service.d/daemon.json \ 129 | ${DOCKER_ADDITIONAL_OPTIONS} 130 | ExecStartPost=/usr/bin/chown ${USER}:docker /var/run/docker.sock 131 | EOF 132 | sudo tee /etc/systemd/system/docker.service.d/daemon.json <<-EOF 133 | { 134 | "labels": [ 135 | "org.label-schema.schema-version=1.0", 136 | "org.label-schema.version=${CLOCKER_VERSION}", 137 | "org.label-schema.name=${HOST_ADDRESS}", 138 | "io.brooklyn.clocker.entity=${ENTITY_ID}", 139 | "io.brooklyn.clocker.application=${APPLICATION_ID}" 140 | ] 141 | } 142 | EOF 143 | 144 | if sudo systemctl list-unit-files | grep "rngd" ; then 145 | echo "[CLOCKER] Fix 100% CPU issue on some VMs" 146 | sudo service rngd stop || true 147 | sudo systemctl disable rngd.service 148 | fi 149 | 150 | sudo systemctl enable docker.service 151 | sudo systemctl daemon-reload 152 | 153 | post.install.command: | 154 | echo "[CLOCKER] Setting up user and group for Docker" 155 | sudo groupadd -f docker 156 | sudo usermod -aG docker ${USER} 157 | 158 | launch.command: | 159 | sudo service docker start && 160 | ( [ -z "${DOCKER_IMAGE_PREINSTALL}" ] || 161 | docker images --format="{{.Repository}}:{{.Tag}}" | grep -q "${DOCKER_IMAGE_PREINSTALL}" || 162 | docker pull ${DOCKER_IMAGE_PREINSTALL} ) 163 | 164 | stop.command: | 165 | sudo service docker stop 166 | 167 | checkRunning.command: | 168 | sudo service docker status 169 | 170 | # ensure docker running before starting children 171 | childStartMode: foreground_late 172 | 173 | - id: docker-engine-tls 174 | name: "Docker Engine with TLS" 175 | description: | 176 | A docker-engine customised with TLS 177 | itemType: entity 178 | iconUrl: classpath://io.brooklyn.clocker.common:icons/docker.png 179 | item: 180 | type: docker-engine 181 | 182 | brooklyn.parameters: 183 | - name: docker.port 184 | label: "Docker Port" 185 | description: | 186 | The TCP port for Docker to listen on 187 | type: integer 188 | default: 2376 189 | - name: docker.bindaddress 190 | label: "Docker Bind Address" 191 | description: | 192 | The docker network address to to listen on. 193 | type: string 194 | default: 0.0.0.0 195 | - name: ca.request.root.url 196 | label: "CA Request Root URL" 197 | description: | 198 | Optional root URL for a CA server. 199 | 200 | Use this or set the configuration for the certificate and key 201 | URLs separately. 202 | type: string 203 | - name: ca.cert.url 204 | label: "CA Certificate URL" 205 | description: | 206 | Optional URL for the CA certificate 207 | type: string 208 | - name: ca.cert 209 | label: "CA Certificate" 210 | description: | 211 | Optional CA certificate data 212 | type: string 213 | - name: node.cert.url 214 | label: "Node Certificate URL" 215 | description: | 216 | Optional URL for the TLS certificate for this Docker engine 217 | type: string 218 | - name: private.key.url 219 | label: "Private Key URL" 220 | description: | 221 | Optional URL for the private key of this Docker engine 222 | type: string 223 | 224 | brooklyn.enrichers: 225 | - type: org.apache.brooklyn.enricher.stock.Transformer 226 | brooklyn.config: 227 | uniqueTag: docker-public-endpoint-generator 228 | enricher.suppressDuplicates: false 229 | enricher.triggerSensors: 230 | - $brooklyn:sensor("host.address") 231 | enricher.targetSensor: $brooklyn:sensor("docker.endpoint.public") 232 | enricher.targetValue: 233 | $brooklyn:formatString: 234 | - "%s:%d" 235 | - $brooklyn:attributeWhenReady("host.address") 236 | - $brooklyn:config("docker.port") 237 | - type: org.apache.brooklyn.enricher.stock.Transformer 238 | brooklyn.config: 239 | uniqueTag: docker-endpoint-generator 240 | enricher.suppressDuplicates: false 241 | enricher.triggerSensors: 242 | - $brooklyn:sensor("host.subnet.address") 243 | enricher.targetSensor: $brooklyn:sensor("docker.endpoint") 244 | enricher.targetValue: 245 | $brooklyn:formatString: 246 | - "%s:%d" 247 | - $brooklyn:attributeWhenReady("host.subnet.address") 248 | - $brooklyn:config("docker.port") 249 | - type: org.apache.brooklyn.enricher.stock.Transformer 250 | brooklyn.config: 251 | uniqueTag: docker-url-generator 252 | enricher.suppressDuplicates: false 253 | enricher.triggerSensors: 254 | - $brooklyn:sensor("docker.endpoint") 255 | enricher.targetSensor: $brooklyn:sensor("docker.url") 256 | enricher.targetValue: 257 | $brooklyn:formatString: 258 | - "tcp://%s" 259 | - $brooklyn:attributeWhenReady("docker.endpoint") 260 | 261 | brooklyn.config: 262 | docker.cert.path: 263 | $brooklyn:formatString: 264 | - "%s/.certs" 265 | - $brooklyn:attributeWhenReady("install.dir") 266 | docker.tlsoptions: 267 | $brooklyn:formatString: 268 | - >- 269 | --tlsverify 270 | --tlscacert=%1$s/ca.pem 271 | --tlscert=%1$s/cert.pem 272 | --tlskey=%1$s/key.pem 273 | - $brooklyn:config("docker.cert.path") 274 | docker.additionaloptions.docker-engine-tls: 275 | $brooklyn:formatString: 276 | - "-H %s %s" 277 | - $brooklyn:attributeWhenReady("docker.bind.url") 278 | - $brooklyn:config("docker.tlsoptions") 279 | docker.additionaloptions: $brooklyn:config("docker.additionaloptions.docker-engine-tls") 280 | shell.env: 281 | CA_REQUEST_ROOT_URL: $brooklyn:config("ca.request.root.url") 282 | CA_CERT: $brooklyn:config("ca.cert") 283 | CA_CERT_URL: $brooklyn:config("ca.cert.url") 284 | NODE_CERT_URL: $brooklyn:config("node.cert.url") 285 | PRIV_KEY_URL: $brooklyn:config("private.key.url") 286 | HOST_ADDRESS: $brooklyn:attributeWhenReady("host.address") 287 | SUBNET_ADDRESS: $brooklyn:attributeWhenReady("host.subnet.address") 288 | INSTALL_DIR: $brooklyn:attributeWhenReady("install.dir") 289 | TLS_OPTIONS: $brooklyn:config("docker.tlsoptions") 290 | DOCKER_ENDPOINT: $brooklyn:attributeWhenReady("docker.endpoint") 291 | DOCKER_HOST: $brooklyn:attributeWhenReady("docker.url") 292 | DOCKER_TLS_VERIFY: true 293 | DOCKER_CERT_PATH: $brooklyn:config("docker.cert.path") 294 | latch.preInstall.resources: $brooklyn:entity("ca-server").attributeWhenReady("service.isUp") 295 | files.preinstall: 296 | "classpath://io.brooklyn.clocker.common:common/certificate-functions.sh": certificate-functions.sh 297 | customize.command: | 298 | set -e 299 | source ${INSTALL_DIR}/certificate-functions.sh 300 | 301 | echo "[CLOCKER] Creating ${DOCKER_CERT_PATH}" 302 | mkdir -p ${DOCKER_CERT_PATH} 303 | 304 | if [ "${CA_REQUEST_ROOT_URL}" ] ; then 305 | #echo "$CA_CERT" > ${DOCKER_CERT_PATH}/ca.pem # commented out until after we get back to this. 306 | getcert ${CA_REQUEST_ROOT_URL}/cacert/ca.pem ${DOCKER_CERT_PATH}/ca.pem 307 | 308 | generate_key ${DOCKER_CERT_PATH}/key.pem 309 | generate_conf ${DOCKER_CERT_PATH}/csr.cnf ${HOST_ADDRESS} ${SUBNET_ADDRESS} 310 | generate_csr ${DOCKER_CERT_PATH}/csr.cnf ${DOCKER_CERT_PATH}/key.pem ${DOCKER_CERT_PATH}/csr.pem 311 | 312 | echo "[CLOCKER] Requesting certificate from ${CA_REQUEST_ROOT_URL}" 313 | curl -X POST --data-binary @${DOCKER_CERT_PATH}/csr.pem ${CA_REQUEST_ROOT_URL}/sign > ${DOCKER_CERT_PATH}/cert.pem 314 | echo "[CLOCKER] Certifcate for ${HOST_ADDRESS} received" 315 | else 316 | echo "[CLOCKER] Downloading certificates from configuration settings" 317 | getcert ${CA_CERT_URL} > ${DOCKER_CERT_PATH}/ca.pem 318 | getcert ${NODE_CERT_URL} > ${DOCKER_CERT_PATH}/cert.pem 319 | getcert ${PRIV_KEY_URL} > ${DOCKER_CERT_PATH}/key.pem 320 | fi 321 | # TODO verify certs with openssl 322 | test -f ${DOCKER_CERT_PATH}/ca.pem || failwith "Failed to obtain ca.pem" 323 | test -f ${DOCKER_CERT_PATH}/cert.pem || failwith "Failed to obtain cert.pem" 324 | test -f ${DOCKER_CERT_PATH}/key.pem || failwith "Failed to obtain key.pem" 325 | post.customize.command: | 326 | echo "[CLOCKER] Set up Docker environment variables with TLS" 327 | if ! grep docker_client ${HOME}/.bashrc ; then 328 | echo ". docker_client.rc" >> ${HOME}/.bashrc 329 | fi 330 | cat > ${HOME}/docker_client.rc <<-EOF 331 | DOCKER_TLS_VERIFY=${DOCKER_TLS_VERIFY} 332 | DOCKER_CERT_PATH=${DOCKER_CERT_PATH} 333 | DOCKER_HOST=${DOCKER_HOST} 334 | export DOCKER_TLS_VERIFY DOCKER_CERT_PATH DOCKER_HOST 335 | EOF 336 | 337 | brooklyn.initializers: 338 | - type: org.apache.brooklyn.core.sensor.ssh.SshCommandSensor 339 | brooklyn.config: 340 | name: docker.csr 341 | period: 5m 342 | command: | 343 | cat ${DOCKER_CERT_PATH}/csr.pem 344 | - type: org.apache.brooklyn.core.sensor.StaticSensor 345 | brooklyn.config: 346 | name: docker.bind.url 347 | static.value: 348 | $brooklyn:formatString: 349 | - "tcp://%s:%d" 350 | - $brooklyn:config("docker.bindaddress") 351 | - $brooklyn:config("docker.port") 352 | 353 | - id: docker-engine-with-resilience 354 | name: "Docker Engine with Resilience" 355 | description: | 356 | A docker-engine configured with resilience policies 357 | itemType: entity 358 | iconUrl: classpath://io.brooklyn.clocker.common:icons/docker.png 359 | item: 360 | type: docker-engine-tls 361 | 362 | brooklyn.parameters: 363 | - name: docker.recovery.stabilizationDelay 364 | label: "Stabilization Delay" 365 | description: | 366 | Time period for which the service must be consistently in the same state to trigger an action. 367 | Should be long enough that a restart will not trigger failure 368 | type: org.apache.brooklyn.util.time.Duration 369 | default: 5m 370 | - name: docker.recovery.failOnRecurringFailuresInThisDuration 371 | label: "Fail Duration" 372 | description: | 373 | Reports entity as failed if it fails two or more times in this time window 374 | type: org.apache.brooklyn.util.time.Duration 375 | default: 15m 376 | 377 | brooklyn.policies: 378 | - type: org.apache.brooklyn.policy.ha.ServiceRestarter 379 | brooklyn.config: 380 | failOnRecurringFailuresInThisDuration: 381 | $brooklyn:config("docker.recovery.failOnRecurringFailuresInThisDuration") 382 | 383 | brooklyn.enrichers: 384 | - type: org.apache.brooklyn.policy.ha.ServiceFailureDetector 385 | brooklyn.config: 386 | serviceOnFire.stabilizationDelay: 387 | $brooklyn:config("docker.recovery.stabilizationDelay") 388 | entityFailed.stabilizationDelay: 389 | $brooklyn:config("docker.recovery.stabilizationDelay") 390 | entityRecovered.stabilizationDelay: 391 | $brooklyn:config("docker.recovery.stabilizationDelay") 392 | 393 | - id: docker-engine-container 394 | name: "Docker Container" 395 | description: | 396 | An easy way to launch a Docker container, as a child of a Docker Engine. 397 | itemType: entity 398 | iconUrl: classpath://io.brooklyn.clocker.common:icons/docker.png 399 | item: 400 | type: centos-software-process 401 | 402 | brooklyn.parameters: 403 | - name: image.details 404 | label: "Image Details" 405 | description: | 406 | The Docker Container image details. 407 | 408 | Either the name of a Docker Hub image or the id of an image that has 409 | been pulled and is available on the Engine already. 410 | type: string 411 | 412 | brooklyn.config: 413 | dontRequireTtyForSudo: true 414 | 415 | # TODO advertise container id as a sensor. 416 | 417 | shell.env: 418 | IMAGE_DETAILS: $brooklyn:config("image.details") 419 | 420 | launch.command: | 421 | docker run -d ${IMAGE_DETAILS} 422 | 423 | checkRunning.command: | 424 | result="$(docker ps | grep ${IMAGE_DETAILS} | wc -l)" 425 | if [ $result -ne 0 ]; then exit 0; else exit 1; fi; 426 | 427 | - id: docker-vm-container 428 | name: "Docker Entity" 429 | description: | 430 | An easy way to launch a single Docker container on a VM 431 | itemType: entity 432 | item: 433 | type: docker-engine 434 | 435 | brooklyn.parameters: 436 | - name: docker.image 437 | label: "Docker Image" 438 | description: | 439 | The docker image to use when running the container 440 | - name: docker.run.arguments 441 | label: "Docker Run Arguments" 442 | description: | 443 | Arguments to pass to the docker run command 444 | - name: docker.run.volumes 445 | label: "Container Volumns" 446 | type: java.util.List 447 | description: | 448 | List of volumes to mount. Items follow the documented docker format 449 | for the '-v' option 450 | default: [ ] 451 | - name: docker.run.env 452 | label: "Container Environment" 453 | type: java.util.Map 454 | description: | 455 | Map of environment variables to pass to the container 456 | default: { } 457 | - name: docker.restart 458 | label: "Restart policy" 459 | description: | 460 | Restart policy on the container. One of no, on-failure[:max-retries], 461 | always or unless-stopped 462 | - name: docker.run.additionaloptions 463 | label: "Run Additional Options" 464 | description: | 465 | Additional options to pass to the 'docker run' command 466 | 467 | brooklyn.config: 468 | defaultDisplayName: $brooklyn:config("docker.image") 469 | image.preinstall: 470 | 471 | shell.env: 472 | DOCKER_IMAGE: $brooklyn:config("docker.image") 473 | DOCKER_RUN_ARGUMENTS: $brooklyn:config("docker.run.arguments") 474 | DOCKER_RUN_VOLUMES: $brooklyn:config("docker.run.volumes") 475 | DOCKER_RUN_ENV: $brooklyn:config("docker.run.env") 476 | DOCKER_RESTART: $brooklyn:config("docker.restart") 477 | DOCKER_RUN_ADDITIONAL_OPTIONS: $brooklyn:config("docker.run.additionaloptions") 478 | 479 | pre.install.command: | 480 | sudo yum -y install epel-release 481 | sudo yum -y install jq 482 | 483 | pre.launch.command: | 484 | if [ -z "${DOCKER_IMAGE}" ]; then 485 | echo "[CLOCKER] 'docker.image' not configured on the entity" >&2 486 | exit 1 487 | fi 488 | 489 | post.launch.command: | 490 | set -e 491 | # Won't escape quotes in the arguments, but those are not expected 492 | function parse_docker_volumes { 493 | echo ${DOCKER_RUN_VOLUMES} | 494 | jq -r '["-v \"" + .[] + "\" "] | add' 495 | } 496 | function parse_docker_env { 497 | echo ${DOCKER_RUN_ENV} | 498 | jq -r 'to_entries | map("-e \"" + .key + "=" + .value + "\" ") | add' 499 | } 500 | rm -f "${PID_FILE}" # docker won't overwrite 501 | DOCKER="docker run -d --cidfile \"${PID_FILE}\" --net=host" 502 | [[ $DOCKER_RUN_VOLUMES != [] ]] && DOCKER="${DOCKER} $( parse_docker_volumes )" 503 | [[ $DOCKER_RUN_ENV != {} ]] && DOCKER="${DOCKER} $( parse_docker_env )" 504 | DOCKER="${DOCKER} --restart=${DOCKER_RESTART:-unless-stopped}" 505 | [ "${DOCKER_RUN_ADDITIONAL_OPTIONS}" ] && DOCKER="${DOCKER} ${DOCKER_RUN_ADDITIONAL_OPTIONS}" 506 | DOCKER="${DOCKER} \"${DOCKER_IMAGE}\"" 507 | [ "${DOCKER_RUN_ARGUMENTS}" ] && DOCKER="${DOCKER} ${DOCKER_RUN_ARGUMENTS}" 508 | echo "${DOCKER}" 509 | echo "${DOCKER}" | bash 510 | 511 | checkRunning.command: | 512 | STATE=$(docker inspect --format "{{ .State.Status }}" $(cat "${PID_FILE}")) 513 | sudo service docker status && [ "${STATE}" = "running" ] 514 | 515 | stop.command: | 516 | docker stop $(cat "${PID_FILE}") 517 | sudo service docker stop 518 | rm -f "${PID_FILE}" 519 | 520 | brooklyn.initializers: 521 | - type: org.apache.brooklyn.core.sensor.ssh.SshCommandSensor 522 | brooklyn.config: 523 | name: container.id 524 | period: 5m 525 | targetType: String 526 | command: | 527 | test -f pid.txt && 528 | cat pid.txt 529 | - type: org.apache.brooklyn.core.sensor.ssh.SshCommandSensor 530 | brooklyn.config: 531 | name: container.stats.cpu.percent 532 | period: 1m 533 | targetType: double 534 | command: | 535 | test -f pid.txt && 536 | ( docker stats --no-stream --format "table {{.CPUPerc}}" $(cat pid.txt) | 537 | sed -n '2s/%//p' ) 538 | - type: org.apache.brooklyn.core.sensor.ssh.SshCommandSensor 539 | brooklyn.config: 540 | name: container.stats.memory.percent 541 | period: 1m 542 | targetType: double 543 | command: | 544 | test -f pid.txt && 545 | ( docker stats --no-stream --format "table {{.MemPerc}}" $(cat pid.txt) | 546 | sed -n '2s/%//p' ) 547 | 548 | - id: docker-container-entity 549 | name: "Docker Container" 550 | description: | 551 | An easy way to launch a Docker container 552 | itemType: entity 553 | iconUrl: classpath://io.brooklyn.clocker.common:icons/docker.png 554 | item: 555 | type: org.apache.brooklyn.container.entity.docker.DockerContainer 556 | brooklyn.parameters: 557 | - name: docker.container.imageName 558 | label: "Docker Container Image Name" 559 | description: | 560 | The name of the image to use when starting the Docker container 561 | type: string 562 | - name: docker.container.inboundPorts 563 | label: "Docker Container Inbound Ports" 564 | description: | 565 | A list of ports to be opened for inbound access to the container 566 | type: java.util.List 567 | - name: docker.container.environment 568 | label: "Docker Container Environmrnt" 569 | description: | 570 | A map of the environment variables to be set when launching the Docker container 571 | type: java.util.Map 572 | -------------------------------------------------------------------------------- /common/examples/ca.yaml: -------------------------------------------------------------------------------- 1 | id: ca 2 | name: "Certificate Authority" 3 | description: | 4 | Standalone Certificate Authority server. 5 | 6 | location: 7 | jclouds:softlayer: 8 | region: ams01 9 | 10 | services: 11 | - type: ca-server 12 | id: ca-server 13 | name: "ca-server" 14 | -------------------------------------------------------------------------------- /common/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | 8 | io.brooklyn.clocker 9 | clocker-parent 10 | 2.1.0-SNAPSHOT 11 | 12 | 13 | Clocker :: Common 14 | clocker-common 15 | bundle 16 | 17 | 18 | 19 | 20 | catalog 21 | false 22 | 23 | 24 | resources 25 | false 26 | 27 | 28 | tests 29 | false 30 | tests 31 | 32 | 33 | 34 | 35 | 36 | org.codehaus.mojo 37 | build-helper-maven-plugin 38 | 39 | 40 | attach-artifact 41 | package 42 | 43 | attach-artifact 44 | 45 | 46 | 47 | 48 | ${project.basedir}/catalog/docker/docker.bom 49 | bom 50 | docker 51 | 52 | 53 | ${project.basedir}/catalog/common/ca.bom 54 | bom 55 | ca 56 | 57 | 58 | ${project.basedir}/catalog/common/haproxy.bom 59 | bom 60 | haproxy 61 | 62 | 63 | ${project.basedir}/catalog/common/haproxy-template.bom 64 | bom 65 | haproxy-template 66 | 67 | 68 | ${project.basedir}/catalog/common/common.bom 69 | bom 70 | common 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /common/resources/common/certificate-functions.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | function generate_key () { 4 | openssl genrsa -out $1 2048 5 | } 6 | 7 | function generate_conf () { 8 | local CNF=$1 9 | shift 1 10 | local ix=0 11 | cat > ${CNF} <<-EOF 12 | [ req ] 13 | req_extensions=v3_req 14 | distinguished_name=req_distinguished_name 15 | 16 | [ req_distinguished_name ] 17 | commonName = Common Name (eg, your name or your server\'s hostname) 18 | commonName_max = 64 19 | 20 | [ v3_req ] 21 | subjectAltName = @alt_names 22 | 23 | [ alt_names ] 24 | EOF 25 | 26 | while [ $# -gt 0 ] ; do 27 | ix=$(( $ix + 1 )) 28 | echo "IP.${ix} = $1" >> ${CNF} 29 | shift 1 30 | done 31 | } 32 | 33 | function generate_csr () { 34 | openssl req -config $1 -new -key $2 -days 1825 -subj "/CN=$(hostname)" -out $3 35 | } 36 | 37 | function failwith() { 38 | local err=$? 39 | 1>&2 echo "[CLOCKER] $1" 40 | exit $err 41 | } 42 | 43 | function getcert() { 44 | local url=$1 45 | local file=$2 46 | curl -L ${url} --output ${file} --write-out "%{http_code}" | grep 200 || 47 | failwith "${file} not received from CA" 48 | } 49 | -------------------------------------------------------------------------------- /common/resources/icons/centos.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brooklyncentral/clocker/e1ff91d4959d2238efcf78569d600f95273730d4/common/resources/icons/centos.png -------------------------------------------------------------------------------- /common/resources/icons/docker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brooklyncentral/clocker/e1ff91d4959d2238efcf78569d600f95273730d4/common/resources/icons/docker.png -------------------------------------------------------------------------------- /common/resources/icons/haproxy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brooklyncentral/clocker/e1ff91d4959d2238efcf78569d600f95273730d4/common/resources/icons/haproxy.png -------------------------------------------------------------------------------- /common/resources/icons/openssl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brooklyncentral/clocker/e1ff91d4959d2238efcf78569d600f95273730d4/common/resources/icons/openssl.png -------------------------------------------------------------------------------- /common/tests/docker/common.tests.bom: -------------------------------------------------------------------------------- 1 | brooklyn.catalog: 2 | version: "2.1.0-SNAPSHOT" # CLOCKER_VERSION 3 | iconUrl: https://raw.githubusercontent.com/docker-library/docs/c350af05d3fac7b5c3f6327ac82fe4d990d8729c/docker/logo.png 4 | license_code: APACHE-2.0 5 | 6 | items: 7 | - id: test-case 8 | item: 9 | type: org.apache.brooklyn.test.framework.TestCase 10 | 11 | - id: ssh-test 12 | item: 13 | type: org.apache.brooklyn.test.framework.TestSshCommand 14 | 15 | - id: sensor-test 16 | item: 17 | type: org.apache.brooklyn.test.framework.TestSensor 18 | # sensor: name 19 | 20 | - id: assert-up-initial 21 | item: 22 | type: org.apache.brooklyn.test.framework.TestSensor 23 | name: "TEST [service.isUp] IS [true]" 24 | sensor: service.isUp 25 | brooklyn.parameters: 26 | - name: timeout.initialStartup 27 | description: The timeout for provisioning, installing and launching the app-under-test. 28 | type: org.apache.brooklyn.util.time.Duration 29 | default: 1h 30 | brooklyn.config: 31 | timeout: $brooklyn:config("timeout.initialStartup") 32 | assert: 33 | - equals: true 34 | 35 | - id: assert-up 36 | item: 37 | type: sensor-test 38 | name: "TEST [service.isUp] IS [true]" 39 | sensor: service.isUp 40 | assert: 41 | - equals: true 42 | 43 | - id: assert-down 44 | item: 45 | type: sensor-test 46 | name: TEST [service.isUp] IS [false] 47 | sensor: service.isUp 48 | assert: 49 | - equals: false 50 | 51 | - id: assert-running 52 | item: 53 | type: sensor-test 54 | name: "TEST [service.state] IS [running]" 55 | sensor: service.state 56 | assert: 57 | - matches: running 58 | 59 | - id: assert-failed 60 | item: 61 | type: sensor-test 62 | name: "TEST [service.state] IS [on-fire]" 63 | sensor: service.state 64 | assert: 65 | - matches: on-fire 66 | 67 | - id: test-stop-machine 68 | item: 69 | name: "Invoke [stop] effector (machine)" 70 | type: org.apache.brooklyn.test.framework.TestEffector 71 | effector: stop 72 | 73 | - id: test-stop 74 | item: 75 | type: test-stop-machine 76 | 77 | - id: test-stop-process 78 | item: 79 | name: "Invoke [stop] effector (process)" 80 | type: org.apache.brooklyn.test.framework.TestEffector 81 | effector: stop 82 | brooklyn.config: 83 | params: 84 | stopMachineMode: NEVER 85 | 86 | - id: test-start 87 | item: 88 | name: "Invoke [start] effector" 89 | type: org.apache.brooklyn.test.framework.TestEffector 90 | effector: start 91 | 92 | - id: test-restart 93 | item: 94 | name: "Invoke [restart] effector" 95 | type: org.apache.brooklyn.test.framework.TestEffector 96 | effector: restart 97 | 98 | - id: test-restart-process 99 | item: 100 | name: "Invoke [restart] effector (process)" 101 | type: org.apache.brooklyn.test.framework.TestEffector 102 | effector: restart 103 | params: 104 | restartMachine: false 105 | 106 | - id: test-restart-machine 107 | item: 108 | name: "Invoke [restart] effector (machine)" 109 | type: org.apache.brooklyn.test.framework.TestEffector 110 | effector: restart 111 | params: 112 | restartMachine: true 113 | 114 | - id: test-http-status-200 115 | item: 116 | name: "Check HTTP Response Status Code" 117 | type: org.apache.brooklyn.test.framework.TestHttpCall 118 | brooklyn.config: 119 | applyAssertionTo: status 120 | assert: 121 | - isEqualTo: 200 122 | 123 | - id: test-http-body 124 | item: 125 | name: "Check HTTP Response Body" 126 | type: org.apache.brooklyn.test.framework.TestHttpCall 127 | brooklyn.config: 128 | applyAssertionTo: body 129 | 130 | - id: test-reachable 131 | item: 132 | name: "TEST endpoint reachable" 133 | type: org.apache.brooklyn.test.framework.TestEndpointReachable 134 | 135 | - id: loop-test-case 136 | item: 137 | name: "Loop over members" 138 | type: org.apache.brooklyn.test.framework.LoopOverGroupMembersTestCase 139 | 140 | - id: ssh-cmd-restart 141 | item: 142 | type: ssh-test 143 | name: "Restart Machine" 144 | brooklyn.config: 145 | command: | 146 | nohup sudo bash -c "sleep 5; shutdown -r now" & 147 | 148 | - id: test-docker-client 149 | item: 150 | type: centos-software-process 151 | name: "test-docker-client" 152 | 153 | brooklyn.config: 154 | pre.install.command: | 155 | echo "[TEST] Install docker so we can use it as a client" 156 | sudo tee /etc/yum.repos.d/docker.repo <<-EOF 157 | [dockerrepo] 158 | name=Docker Repository 159 | baseurl=https://yum.dockerproject.org/repo/main/centos/\$releasever/ 160 | enabled=1 161 | gpgcheck=1 162 | gpgkey=https://yum.dockerproject.org/gpg 163 | EOF 164 | 165 | install.command: | 166 | sudo yum -y update 167 | sudo yum -y install docker-engine 168 | 169 | launch.command: | 170 | while true ; do sleep 3600; done & echo $! > ${PID_FILE} 171 | 172 | - id: test-docker-client-with-tls 173 | item: 174 | type: test-docker-client 175 | name: "test-docker-client-with-tls" 176 | 177 | brooklyn.parameters: 178 | - name: docker.url 179 | description: URL of the docker endpoint 180 | - name: ca.url 181 | description: URL of the CA server 182 | - name: client.address 183 | description: Public address of this test client 184 | 185 | brooklyn.config: 186 | shell.env: 187 | INSTALL_DIR: $brooklyn:attributeWhenReady("install.dir") 188 | DOCKER_HOST: $brooklyn:config("docker.url") 189 | DOCKER_TLS_VERIFY: true 190 | DOCKER_CERT_PATH: 191 | $brooklyn:formatString: 192 | - "%s/.certs" 193 | - $brooklyn:attributeWhenReady("install.dir") 194 | IP: $brooklyn:config("client.address") 195 | CA: $brooklyn:config("ca.url") 196 | 197 | customize.command: | 198 | set -e 199 | CERT_DIR=${INSTALL_DIR}/.certs 200 | echo [TEST] Generating certificate request in ${CERT_DIR} 201 | mkdir -p ${CERT_DIR} 202 | openssl genrsa -out ${CERT_DIR}/key.pem 2048 203 | # provide defaults for most prompts as '.' below, meaning 'ignore'. CN is '*' 204 | openssl req -new -key ${CERT_DIR}/key.pem -days 1825 -out ${CERT_DIR}/csr.pem <<-EOF 205 | . 206 | . 207 | . 208 | . 209 | . 210 | * 211 | . 212 | . 213 | . 214 | EOF 215 | echo [TEST] Getting certificates from ${CA} 216 | curl -L ${CA}/cacert/ca.pem --output ${CERT_DIR}/ca.pem 217 | curl -X POST --data-binary @${CERT_DIR}/csr.pem ${CA}/sign > ${CERT_DIR}/cert.pem 218 | if ! grep docker_client ${HOME}/.bashrc ; then 219 | echo ". docker_client.rc" >> ${HOME}/.bashrc 220 | fi 221 | cat > ${HOME}/docker_client.rc <<-EOF 222 | export DOCKER_TLS_VERIFY=true 223 | export DOCKER_CERT_PATH=${DOCKER_CERT_PATH} 224 | export DOCKER_HOST=${DOCKER_HOST} 225 | EOF 226 | 227 | - id: test-connect-fails-without-tls 228 | item: 229 | type: ssh-test 230 | name: "Verify Connect Fails without TLS" 231 | command: | 232 | unset DOCKER_TLS_VERIFY 233 | unset DOCKER_CERT_PATH 234 | docker ps -a 235 | assertStatus: 236 | equals: 1 237 | assertErr: 238 | notEmpty: true 239 | 240 | - id: preinstall-image-tests 241 | name: Preinstalled Image Tests 242 | description: Tests on the default Docker image 243 | item: 244 | type: test-case 245 | 246 | brooklyn.parameters: 247 | - name: timeout.initialStartup 248 | description: | 249 | The timeout for provisioning, installing and launching the application 250 | under test. 251 | type: org.apache.brooklyn.util.time.Duration 252 | default: 1h 253 | - name: timeout.runtimeAssertion 254 | type: org.apache.brooklyn.util.time.Duration 255 | description: | 256 | The timeout for any other operation e.g. invoking an effector or 257 | waiting for a sensor to be updated. 258 | default: 15m 259 | 260 | brooklyn.config: 261 | image.preinstall: brooklyncentral/centos:7 262 | 263 | brooklyn.children: 264 | - type: ssh-test 265 | name: "TEST-1 docker stock image" 266 | brooklyn.config: 267 | # Should already be pulled by the docker-engine blueprint 268 | shell.env: 269 | IMAGE_PREINSTALLED: $brooklyn:config("image.preinstall") 270 | command: | 271 | docker images --format "{{.Repository}}:{{.Tag}}" | 272 | grep "${IMAGE_PREINSTALLED}" 273 | assert.status: 274 | equals: 0 275 | - type: ssh-test 276 | name: "TEST-2 Remove pre-installed image" 277 | brooklyn.config: 278 | # Should already be pulled by the docker-engine blueprint 279 | shell.env: 280 | IMAGE_PREINSTALLED: $brooklyn:config("image.preinstall") 281 | command: | 282 | docker rmi "${IMAGE_PREINSTALLED}" 283 | assert.status: 284 | equals: 0 285 | - type: test-restart 286 | name: "TEST-3 Restart to re-download image" 287 | - type: ssh-test 288 | name: "TEST-4 docker re-downloads stock images" 289 | brooklyn.config: 290 | # Should already be pulled by the docker-engine blueprint 291 | shell.env: 292 | IMAGE_PREINSTALLED: $brooklyn:config("image.preinstall") 293 | command: | 294 | docker images --format "{{.Repository}}:{{.Tag}}" | 295 | grep "${IMAGE_PREINSTALLED}" 296 | assert.status: 297 | equals: 0 298 | 299 | - id: no-preinstall-image-tests 300 | name: Empty Preinstalled Image Tests 301 | description: Tests empty image.preinstall will skip pull 302 | item: 303 | type: test-case 304 | 305 | brooklyn.parameters: 306 | - name: timeout.initialStartup 307 | description: | 308 | The timeout for provisioning, installing and launching the application 309 | under test. 310 | type: org.apache.brooklyn.util.time.Duration 311 | default: 1h 312 | - name: timeout.runtimeAssertion 313 | type: org.apache.brooklyn.util.time.Duration 314 | description: | 315 | The timeout for any other operation e.g. invoking an effector or 316 | waiting for a sensor to be updated. 317 | default: 15m 318 | 319 | brooklyn.children: 320 | - type: ssh-test 321 | name: "TEST-1 no docker images" 322 | brooklyn.config: 323 | command: | 324 | # Only header expected 325 | [ "$(docker images | wc -l)" -eq "1" ] 326 | assert.status: 327 | equals: 0 328 | 329 | ### 330 | # Tests that we can deploy a Docker Engine. We assert that it reports success, is reachable 331 | # and basic health checks (via Docker CLI) also report success. 332 | ## 333 | - id: docker-engine-test 334 | name: "Docker Engine test" 335 | description: Test that Docker Engine is deployed correctly 336 | item: 337 | type: test-case 338 | 339 | brooklyn.parameters: 340 | - name: timeout.initialStartup 341 | description: | 342 | The timeout for provisioning, installing and launching the application 343 | under test. 344 | type: org.apache.brooklyn.util.time.Duration 345 | default: 1h 346 | - name: timeout.runtimeAssertion 347 | type: org.apache.brooklyn.util.time.Duration 348 | description: | 349 | The timeout for any other operation e.g. invoking an effector or 350 | waiting for a sensor to be updated. 351 | default: 15m 352 | 353 | brooklyn.children: 354 | # Basic startup tests 355 | - type: assert-up 356 | name: "TEST-1-1 assert-up" 357 | timeout: $brooklyn:config("timeout.initialStartup") 358 | - type: assert-running 359 | name: "TEST-1-2 assert-running" 360 | timeout: $brooklyn:config("timeout.initialStartup") 361 | - type: ssh-test 362 | name: "TEST-1-3 docker CLI commands succeed" 363 | brooklyn.config: 364 | command: | 365 | docker ps 366 | 367 | # Test image pull and delete 368 | - type: test-case 369 | name: "TEST-2 image pull and delete" 370 | 371 | brooklyn.children: 372 | - type: ssh-test 373 | name: "TEST-2-1 docker pull" 374 | command: | 375 | docker pull redis 376 | - type: ssh-test 377 | name: "TEST-2-2 docker images added" 378 | command: | 379 | docker images 380 | assertOut: 381 | contains: redis 382 | - type: ssh-test 383 | name: "TEST-2-3 docker rmi" 384 | command: | 385 | docker rmi redis 386 | - type: ssh-test 387 | name: "TEST-2-4 docker images removed" 388 | command: | 389 | docker images | grep -c redis 390 | assertOut: 391 | equals: "0" 392 | 393 | # Test starting and stopping and restarting a container 394 | - type: test-case 395 | name: "TEST-3 docker containers" 396 | 397 | brooklyn.children: 398 | - type: ssh-test 399 | name: "TEST-3-1 docker run MongoDB" 400 | command: | 401 | docker pull mongo:latest 402 | docker run -d --name "test-MongoDB" mongo 403 | - type: ssh-test 404 | name: "TEST-3-2 docker ps MongoDB is up" 405 | command: | 406 | docker ps 407 | assertOut: 408 | contains: test-MongoDB 409 | - type: ssh-test 410 | name: "TEST-3-4 docker stop MongoDB" 411 | command: | 412 | docker stop test-MongoDB 413 | - type: ssh-test 414 | name: "TEST-3-5 docker ps MongoDB is stopped" 415 | command: | 416 | docker ps | grep -c test-MongoDB 417 | assertOut: 418 | equals: "0" 419 | - type: ssh-test 420 | name: "TEST-3-6 docker start MongoDB" 421 | command: | 422 | docker start test-MongoDB 423 | - type: ssh-test 424 | name: "TEST-3-7 docker ps MongoDB is up again" 425 | command: | 426 | docker ps 427 | assertOut: 428 | contains: test-MongoDB 429 | 430 | # Test building from a dockerfile 431 | - type: test-case 432 | name: "TEST-3-8 building from a dockerfile" 433 | brooklyn.children: 434 | - type: ssh-test 435 | name: "TEST-3-8a Setup Dockerfile" 436 | command: | 437 | mkdir test_dockerfile_dir 438 | printf "FROM ubuntu\nRUN echo hello world" > test_dockerfile_dir/Dockerfile 439 | - type: ssh-test 440 | name: "TEST-3-8b docker build" 441 | command: | 442 | docker build -t test_dockerfile:latest test_dockerfile_dir 443 | - type: ssh-test 444 | name: "TEST-3-8c docker images built" 445 | command: | 446 | docker images 447 | assertOut: 448 | contains: test_dockerfile 449 | 450 | - type: ssh-test 451 | name: "TEST-3-9 docker remove MongoDB" 452 | command: | 453 | docker rm -f test-MongoDB 454 | assertOut: 455 | contains: test-MongoDB 456 | 457 | ### 458 | # Tests that we can deploy a Docker Engine along with a long-running container. 459 | # We assert that the container comes up (according to the CLI command `docker ps`). 460 | ## 461 | - id: docker-engine-and-container-test 462 | name: "TEST-4 Docker Engine and Container test" 463 | description: | 464 | Test that can run a container on the Docker Engine 465 | item: 466 | type: test-case 467 | 468 | brooklyn.parameters: 469 | - name: timeout.initialStartup 470 | description: | 471 | The timeout for provisioning, installing and launching the application 472 | under test. 473 | type: org.apache.brooklyn.util.time.Duration 474 | default: 1h 475 | - name: timeout.runtimeAssertion 476 | type: org.apache.brooklyn.util.time.Duration 477 | description: | 478 | The timeout for any other operation e.g. invoking an effector or 479 | waiting for a sensor to be updated. 480 | default: 15m 481 | 482 | brooklyn.children: 483 | - type: assert-up 484 | name: "TEST-4-1 assert-up" 485 | brooklyn.config: 486 | timeout: $brooklyn:config("timeout.initialStartup") 487 | - type: ssh-test 488 | name: "TEST-4-2 assert-running" 489 | brooklyn.config: 490 | command: | 491 | docker ps 492 | assert.out: 493 | contains: brooklyncentral/centos:7 494 | -------------------------------------------------------------------------------- /common/tests/docker/docker.tests.bom: -------------------------------------------------------------------------------- 1 | brooklyn.catalog: 2 | version: "2.1.0-SNAPSHOT" # CLOCKER_VERSION 3 | iconUrl: https://raw.githubusercontent.com/docker-library/docs/c350af05d3fac7b5c3f6327ac82fe4d990d8729c/docker/logo.png 4 | dependsOn: 5 | - tests/common.tests.bom 6 | license_code: APACHE-2.0 7 | 8 | items: 9 | 10 | - id: docker-vm-container-happy-test 11 | name: Docker Entity tests 12 | description: Tests of wrapper-vm docker 13 | itemType: entity 14 | item: 15 | type: org.apache.brooklyn.entity.stock.BasicApplication 16 | name: Docker Entity test happy path 17 | 18 | brooklyn.config: 19 | timeout: 1h 20 | 21 | brooklyn.children: 22 | - type: docker-vm-container 23 | name: Docker Entity 24 | id: docker-entity 25 | brooklyn.config: 26 | # brooklyncentral/centos:7 fails because it tries to bind to the already reserved (by the host) port 22 27 | docker.image: redis:latest 28 | 29 | my.server.port: 6379 30 | 31 | - type: test-case 32 | name: Docker Entity tests 33 | targetId: docker-entity 34 | brooklyn.children: 35 | - type: assert-up-initial 36 | name: "TEST-01 check service is running" 37 | - type: test-stop-process 38 | name: "TEST-02 stop process" 39 | - type: test-start 40 | name: "TEST-03 start process" 41 | - type: test-restart-process 42 | name: "TEST-04 restart process" 43 | - type: test-case 44 | name: "TEST-05 reboot machine" 45 | brooklyn.children: 46 | - type: ssh-cmd-restart 47 | - type: assert-failed 48 | - type: assert-up 49 | - type: assert-running 50 | - type: test-reachable 51 | name: "TEST-06 check service is reachable" 52 | brooklyn.config: 53 | endpoint: 54 | $brooklyn:formatString: 55 | - "%s:6379" 56 | - $brooklyn:entity("docker-entity").attributeWhenReady("host.address") 57 | 58 | - id: docker-vm-container-run-options 59 | name: Docker Entity run options tests 60 | description: Tests of wrapper-vm docker 61 | itemType: entity 62 | item: 63 | type: org.apache.brooklyn.entity.stock.BasicApplication 64 | name: Docker Entity test run options 65 | 66 | brooklyn.config: 67 | timeout: 1h 68 | 69 | brooklyn.children: 70 | - type: docker-vm-container 71 | name: Docker Entity 72 | id: docker-vm-entity-run-options 73 | brooklyn.config: 74 | docker.image: busybox:1.24 75 | docker.run.arguments: /bin/nc -ll -p 1234 -e /bin/ls 76 | docker.run.volumes: 77 | - /tmp/vol1:/vol1 78 | - named:/named1 79 | - named:/named2 80 | docker.run.env: 81 | k1: v1 82 | k2: v2 83 | some weird key: multi space var 84 | docker.run.additionaloptions: >- 85 | --label "additional=option" 86 | 87 | my.server.port: 1234 88 | 89 | - type: test-case 90 | name: Docker Entity run options tests 91 | targetId: docker-vm-entity-run-options 92 | brooklyn.children: 93 | - type: assert-up 94 | name: "TEST-01 check service is running" 95 | brooklyn.parameters: 96 | - name: timeout.initialStartup 97 | description: The timeout for provisioning, installing and launching the app-under-test. 98 | type: org.apache.brooklyn.util.time.Duration 99 | default: 1h 100 | brooklyn.config: 101 | timeout: $brooklyn:config("timeout.initialStartup") 102 | - type: ssh-test 103 | name: "TEST-02 container arguments applied" 104 | brooklyn.config: 105 | env: 106 | CONTAINER_ID: $brooklyn:entity("docker-vm-entity-run-options").attributeWhenReady("container.id") 107 | command: | 108 | COMMAND=$(docker inspect --format "{{ .Path }} {{ .Args }}" ${CONTAINER_ID}) 109 | [ "${COMMAND}" = "/bin/nc [-ll -p 1234 -e /bin/ls]" ] 110 | - type: ssh-test 111 | name: "TEST-03 volume arguments applied" 112 | brooklyn.config: 113 | env: 114 | CONTAINER_ID: $brooklyn:entity("docker-vm-entity-run-options").attributeWhenReady("container.id") 115 | command: | 116 | ACTUAL=$(docker inspect --format "{{range .Mounts }}{{ .Name }}, {{ .Source }}, {{ .Destination }} 117 | {{ end }}" ${CONTAINER_ID} | sort) 118 | echo "ACTUAL=$ACTUAL" 119 | EXPECTED=$(printf "\nnamed, /var/lib/docker/volumes/named/_data, /named1\nnamed, /var/lib/docker/volumes/named/_data, /named2\n, /tmp/vol1, /vol1") 120 | [ "${ACTUAL}" = "${EXPECTED}" ] 121 | - type: ssh-test 122 | name: "TEST-04 environment arguments applied" 123 | brooklyn.config: 124 | env: 125 | CONTAINER_ID: $brooklyn:entity("docker-vm-entity-run-options").attributeWhenReady("container.id") 126 | command: | 127 | ACTUAL=$(docker inspect --format "{{ .Config.Env }}" ${CONTAINER_ID}) 128 | echo "ACTUAL=$ACTUAL" 129 | [ "${ACTUAL}" = "[k1=v1 k2=v2 some weird key=multi space var]" ] 130 | - type: ssh-test 131 | name: "TEST-05 default restart policy applied" 132 | brooklyn.config: 133 | env: 134 | CONTAINER_ID: $brooklyn:entity("docker-vm-entity-run-options").attributeWhenReady("container.id") 135 | command: | 136 | ACTUAL=$(docker inspect --format "{{ .HostConfig.RestartPolicy.Name }}" ${CONTAINER_ID}) 137 | echo "ACTUAL=$ACTUAL" 138 | [ "${ACTUAL}" = "unless-stopped" ] 139 | - type: ssh-test 140 | name: "TEST-06 Additional Options" 141 | brooklyn.config: 142 | env: 143 | CONTAINER_ID: $brooklyn:entity("docker-vm-entity-run-options").attributeWhenReady("container.id") 144 | command: | 145 | ACTUAL=$(docker inspect --format "{{ .Config.Labels.additional }}" ${CONTAINER_ID}) 146 | echo "ACTUAL=$ACTUAL" 147 | [ "${ACTUAL}" = "option" ] 148 | - type: test-reachable 149 | name: "TEST-07 Check service is reachable" 150 | brooklyn.config: 151 | endpoint: 152 | $brooklyn:formatString: 153 | - "%s:1234" 154 | - $brooklyn:entity("docker-vm-entity-run-options").attributeWhenReady("host.address") 155 | 156 | # TODO Unused, need to express that start effector is expected to fail 157 | - id: docker-vm-container-fails-test 158 | name: Docker Entity test failure on image exit 159 | description: Tests of wrapper-vm docker 160 | itemType: entity 161 | item: 162 | type: org.apache.brooklyn.entity.stock.BasicApplication 163 | name: Docker Entity test no image configured 164 | brooklyn.children: 165 | # Doesn't propagate failures 166 | - type: org.apache.brooklyn.entity.stock.BasicEntity 167 | name: Ignore failure wrapper 168 | brooklyn.children: 169 | - type: docker-vm-container 170 | name: Docker Entity 171 | id: docker-entity-no-image 172 | 173 | - type: test-case 174 | name: Docker Entity tests 175 | targetId: docker-entity-no-image 176 | brooklyn.children: 177 | - type: test-start 178 | brooklyn.parameters: 179 | - name: timeout.initialStartup 180 | description: The timeout for provisioning, installing and launching the app-under-test. 181 | type: org.apache.brooklyn.util.time.Duration 182 | default: 1h 183 | brooklyn.config: 184 | timeout: $brooklyn:config("timeout.initialStartup") 185 | 186 | # TODO Unused, need to express that start effector is expected to fail 187 | - id: docker-vm-container-exits-test 188 | name: Docker Entity test failure on image exit 189 | description: Tests of wrapper-vm docker 190 | itemType: entity 191 | item: 192 | type: org.apache.brooklyn.entity.stock.BasicApplication 193 | name: Docker Entity test image exits immediately failure 194 | 195 | brooklyn.config: 196 | timeout: 1h 197 | 198 | brooklyn.children: 199 | # Doesn't propagate failures 200 | - type: org.apache.brooklyn.entity.stock.BasicEntity 201 | name: Ignore failure wrapper 202 | brooklyn.children: 203 | - type: docker-vm-container 204 | name: Docker Entity 205 | id: docker-entity-exits 206 | brooklyn.config: 207 | docker.image: busybox:1.24 208 | 209 | - type: test-case 210 | name: Docker Entity tests 211 | targetId: docker-entity-exits 212 | brooklyn.children: 213 | - type: test-start 214 | brooklyn.parameters: 215 | - name: timeout.initialStartup 216 | description: The timeout for provisioning, installing and launching the app-under-test. 217 | type: org.apache.brooklyn.util.time.Duration 218 | default: 1h 219 | brooklyn.config: 220 | timeout: $brooklyn:config("timeout.initialStartup") 221 | - id: docker-vm-container-tests 222 | item: 223 | name: Docker VM Wrapper tests 224 | type: org.apache.brooklyn.entity.stock.BasicApplication 225 | brooklyn.children: 226 | - type: docker-vm-container-happy-test 227 | - type: docker-vm-container-run-options 228 | #- type: docker-vm-container-fails-test 229 | #- type: docker-vm-container-exits-test 230 | 231 | - id: docker-preinstall-tests 232 | name: Preinstalled Image Tests 233 | description: Tests of pre-installed Docker image 234 | itemType: entity 235 | item: 236 | type: org.apache.brooklyn.test.framework.TestCase 237 | 238 | brooklyn.children: 239 | 240 | - type: docker-engine 241 | name: Docker Engine 242 | id: preinstall-engine 243 | 244 | - type: preinstall-image-tests 245 | name: Preinstalled Image Tests 246 | targetId: preinstall-engine 247 | 248 | - id: docker-no-preinstall-tests 249 | name: Preinstalled image tests 250 | description: Tests of pre-installed Docker image 251 | itemType: entity 252 | item: 253 | type: org.apache.brooklyn.test.framework.TestCase 254 | 255 | brooklyn.children: 256 | 257 | - type: docker-engine 258 | name: Docker Engine 259 | id: no-preinstall-engine 260 | brooklyn.config: 261 | image.preinstall: 262 | 263 | - type: no-preinstall-image-tests 264 | name: Empty Preinstalled Image Tests 265 | targetId: no-preinstall-engine 266 | 267 | - id: docker-engine-tests 268 | name: Docker Engine Tests without TLS 269 | description: Tests on Docker Engine without TLS 270 | itemType: entity 271 | item: 272 | type: org.apache.brooklyn.test.framework.TestCase 273 | 274 | brooklyn.children: 275 | 276 | - type: docker-engine 277 | name: Docker Engine 278 | id: docker-engine 279 | 280 | - type: docker-engine-test 281 | name: Test Docker Engine 282 | targetId: docker-engine 283 | 284 | - type: docker-engine 285 | id: docker-engine-with-centos 286 | name: Docker Engine with Centos Container 287 | brooklyn.children: 288 | - type: docker-engine-container 289 | image.details: brooklyncentral/centos:7 290 | 291 | - type: docker-engine-and-container-test 292 | name: Test Docker with Container 293 | targetId: docker-engine-with-centos 294 | 295 | - id: docker-engine-tls-tests 296 | name: Docker Engine Tests with TLS 297 | description: Tests on Docker Engine with TLS 298 | itemType: entity 299 | item: 300 | type: org.apache.brooklyn.test.framework.TestCase 301 | 302 | brooklyn.children: 303 | 304 | # A CA server 305 | - type: ca-server 306 | name: CA 307 | id: ca-server 308 | 309 | # the engine protected by TLS 310 | - type: docker-engine-tls 311 | name: Docker Engine with TLS 312 | id: docker-engine-tls 313 | brooklyn.config: 314 | latch.customize: $brooklyn:entity("ca-server").attributeWhenReady("service.isUp") 315 | ca.request.root.url: 316 | $brooklyn:formatString: 317 | - "%s:%d" 318 | - $brooklyn:entity("ca-server").attributeWhenReady("host.address") 319 | - $brooklyn:entity("ca-server").config("ca.server.port") 320 | 321 | 322 | # A client for talking to the engine 323 | - type: test-docker-client-with-tls 324 | name: Docker client with TLS 325 | id: tls-client 326 | brooklyn.config: 327 | latch.customize: $brooklyn:entity("ca-server").attributeWhenReady("service.isUp") 328 | client.address: $brooklyn:attributeWhenReady("host.address") 329 | ca.url: $brooklyn:entity("ca-server").attributeWhenReady("main.uri") 330 | docker.url: 331 | $brooklyn:formatString: 332 | - "tcp://%s:%s/" 333 | - $brooklyn:entity("docker-engine-tls").attributeWhenReady("host.address") 334 | - $brooklyn:entity("docker-engine-tls").config("docker.port") 335 | 336 | - type: docker-engine-test 337 | name: Test Docker over TLS 338 | targetId: tls-client 339 | -------------------------------------------------------------------------------- /common/tests/docker/tests.bom: -------------------------------------------------------------------------------- 1 | brooklyn.catalog: 2 | version: "2.1.0-SNAPSHOT" # CLOCKER_VERSION 3 | iconUrl: https://raw.githubusercontent.com/docker-library/docs/471fa6e4cb58062ccbf91afc111980f9c7004981/swarm/logo.png 4 | dependsOn: 5 | - tests/docker.tests.bom 6 | - tests/swarm.tests.bom 7 | license_code: APACHE-2.0 8 | 9 | items: 10 | - id: docker-engine-common-tests 11 | name: "Docker Engine Common Tests" 12 | description: | 13 | Tests on Docker Engine with and without TLS, and on Swarm (with TLS) 14 | itemType: template 15 | item: 16 | brooklyn.config: 17 | timeout: 1h 18 | timeout.initialStartup: 1h 19 | timeout.runtimeAssertion: 1h 20 | 21 | services: 22 | - type: docker-engine-tests 23 | name: Docker Engine Tests 24 | - type: docker-engine-tls-tests 25 | name: Docker Engine TLS Tests 26 | - type: docker-preinstall-tests 27 | name: Docker Pre-install Tests 28 | - type: docker-vm-container-tests 29 | name: Docker VM Container Tests 30 | -------------------------------------------------------------------------------- /feature/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | clocker-parent 7 | io.brooklyn.clocker 8 | 2.1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | clocker-feature 13 | Clocker :: Feature 14 | feature 15 | 16 | 17 | 18 | 19 | org.apache.karaf.tooling 20 | karaf-maven-plugin 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /feature/src/main/feature/feature.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | mvn:io.brooklyn.etcd/brooklyn-etcd/${brooklyn-etcd.version}/xml/features 8 | 9 | 10 | clocker-dependencies 11 | clocker-common 12 | clocker-kubernetes 13 | clocker-swarm 14 | 15 | 16 | 17 | mvn:${project.groupId}/clocker-common/${project.version} 18 | 19 | 20 | 21 | mvn:${project.groupId}/clocker-kubernetes/${project.version} 22 | 23 | 24 | 25 | mvn:${project.groupId}/clocker-swarm/${project.version} 26 | 27 | 28 | 29 | brooklyn-etcd 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /kubernetes/catalog/catalog.bom: -------------------------------------------------------------------------------- 1 | brooklyn.catalog: 2 | items: 3 | - classpath://kubernetes/plugins.bom 4 | - classpath://kubernetes/pods.bom 5 | - classpath://kubernetes/kubernetes.bom 6 | 7 | - id: kubernetes-cluster-template 8 | name: "Kubernetes Cluster" 9 | description: | 10 | Kubernetes cluster with a master node and worker nodes 11 | iconUrl: classpath://io.brooklyn.clocker.kubernetes:icons/kubernetes.png 12 | itemType: template 13 | item: 14 | services: 15 | - type: kubernetes-cluster-application 16 | id: kubernetes-cluster-application 17 | name: "kubernetes-cluster-application" 18 | -------------------------------------------------------------------------------- /kubernetes/catalog/kubernetes/plugins.bom: -------------------------------------------------------------------------------- 1 | brooklyn.catalog: 2 | version: "2.1.0-SNAPSHOT" # CLOCKER_VERSION 3 | publish: 4 | description: | 5 | Resources for working with Docker Engine plugins from Apache Brooklyn 6 | license_code: APACHE-2.0 7 | 8 | items: 9 | 10 | - id: flannel-network-agent 11 | name: "Flannel Network Agent" 12 | description: | 13 | The Flannel virtual network agent 14 | itemType: entity 15 | iconUrl: classpath://io.brooklyn.clocker.kubernetes:icons/flannel.png 16 | item: 17 | type: child-software-process 18 | name: "flannel-network-agent" 19 | 20 | brooklyn.parameters: 21 | - name: flannel.version 22 | label: "Flannel Version" 23 | description: | 24 | The Flannel version to install 25 | type: string 26 | default: "0.6.2" 27 | - name: flannel.network 28 | label: "Flannel Network" 29 | description: | 30 | The Flannel network CIDR 31 | type: string 32 | default: "10.0.0.0/8" 33 | - name: flannel.subnet.size 34 | label: "Flannel Subnet Size" 35 | description: | 36 | The size of the subnet CIDRs to be created 37 | type: integer 38 | default: 20 39 | - name: flannel.transport 40 | label: "Flannel Transport" 41 | description: | 42 | The Flannel backend transport mechanism. Can be any of: 'udp', 43 | 'vxlan', 'host-gw', 'aws-vpc', 'gce' or 'alloc'. 44 | type: string 45 | default: "udp" 46 | - name: flannel.interface 47 | label: "Flannel Interface" 48 | description: | 49 | The Flannel interface for host to host traffic 50 | type: string 51 | default: "eth0" 52 | - name: etcd.client.version 53 | label: "Etcd Client Version" 54 | description: | 55 | The etcd client version to install 56 | type: string 57 | default: "3.0.3" 58 | - name: etcd.endpoints 59 | label: "Etcd Endpoints" 60 | description: | 61 | The URLs for an etcd KV store 62 | type: string 63 | 64 | brooklyn.config: 65 | install.unique_label: 66 | $brooklyn:formatString: 67 | - "plugin-flannel-%s" 68 | - $brooklyn:config("flannel.version") 69 | 70 | shell.env: 71 | ETCD_VERSION: $brooklyn:config("etcd.client.version") 72 | ETCD_ENDPOINTS: $brooklyn:config("etcd.endpoints") 73 | FLANNEL_VERSION: $brooklyn:config("flannel.version") 74 | FLANNEL_ADDRESS_RANGE: $brooklyn:config("flannel.network") 75 | FLANNEL_SUBNET_SIZE: $brooklyn:config("flannel.subnet.size") 76 | FLANNEL_TRANSPORT: $brooklyn:config("flannel.transport") 77 | FLANNEL_IFACE: $brooklyn:config("flannel.interface") 78 | HOST_ADDRESS: $brooklyn:parent().attributeWhenReady("host.address") 79 | HOST_SUBNET_ADDRESS: $brooklyn:parent().attributeWhenReady("host.subnet.address") 80 | FLANNEL_ETCD_PREFIX: "/io.cloudsoft/clocker/flannel" 81 | 82 | install.command: | 83 | wget https://github.com/coreos/flannel/releases/download/v${FLANNEL_VERSION}/flanneld-amd64 84 | chmod 755 flanneld-amd64 85 | sudo cp flanneld-amd64 /usr/bin/flanneld 86 | wget https://github.com/coreos/etcd/releases/download/v${ETCD_VERSION}/etcd-v${ETCD_VERSION}-linux-amd64.tar.gz 87 | tar zxvf etcd-v${ETCD_VERSION}-linux-amd64.tar.gz etcd-v${ETCD_VERSION}-linux-amd64/etcdctl 88 | sudo cp etcd-v${ETCD_VERSION}-linux-amd64/etcdctl /usr/bin 89 | sudo mkdir -p /var/run/flannel 90 | 91 | customize.command: | 92 | echo "[CLOCKER] Reset bridge and NAT configuration" 93 | ip link | grep docker0 && ( 94 | sudo ip link set dev docker0 down 95 | sudo ip link delete docker0 96 | ) 97 | sudo iptables -F -t nat 98 | 99 | echo "[CLOCKER] Configure Flannel for ${FLANNEL_TRANSPORT}" 100 | if [ "${FLANNEL_TRANSPORT}" == "vxlan" ] ; then 101 | FLANNEL_TRANSPORT_OPTS=", \"VNI\":1" 102 | fi 103 | cat > flannel.json <<-EOF 104 | { 105 | "Network": "${FLANNEL_ADDRESS_RANGE}", 106 | "SubnetLen": ${FLANNEL_SUBNET_SIZE}, 107 | "Backend": { 108 | "Type": "${FLANNEL_TRANSPORT}"${FLANNEL_TRANSPORT_OPTS} 109 | } 110 | } 111 | EOF 112 | etcdctl --peers ${ETCD_ENDPOINTS} mk ${FLANNEL_ETCD_PREFIX}/config < flannel.json || etcdctl --peers ${ETCD_ENDPOINTS} get ${FLANNEL_ETCD_PREFIX}/config 113 | 114 | sudo -E tee /etc/systemd/system/flannel.service <<-EOF 115 | [Unit] 116 | Description=Flannel Overlay Agent 117 | After=network.target 118 | Before=docker.service 119 | [Service] 120 | ExecStart=/usr/bin/flanneld \ 121 | -etcd-endpoints=${ETCD_ENDPOINTS} \ 122 | -etcd-prefix=${FLANNEL_ETCD_PREFIX} \ 123 | --iface ${FLANNEL_IFACE} \ 124 | --ip-masq \ 125 | --subnet-file=/var/run/flannel/subnet.env \ 126 | --public-ip=${HOST_SUBNET_ADDRESS} 127 | Type=notify 128 | [Install] 129 | WantedBy=multi-user.target 130 | RequiredBy=docker.service 131 | EOF 132 | 133 | launch.command: | 134 | sudo systemctl daemon-reload 135 | sudo systemctl enable flannel 136 | sudo systemctl start flannel 137 | 138 | checkRunning.command: | 139 | sudo systemctl status flannel 140 | 141 | brooklyn.initializers: 142 | - type: org.apache.brooklyn.core.sensor.ssh.SshCommandSensor 143 | brooklyn.config: 144 | name: flannel.mtu 145 | description: | 146 | The MTU for the Flannel network 147 | targetType: integer 148 | command: | 149 | source /var/run/flannel/subnet.env && echo ${FLANNEL_MTU} 150 | - type: org.apache.brooklyn.core.sensor.ssh.SshCommandSensor 151 | brooklyn.config: 152 | name: flannel.subnet 153 | description: | 154 | The Flannel subnet address range 155 | targetType: string 156 | command: | 157 | source /var/run/flannel/subnet.env && echo ${FLANNEL_SUBNET} 158 | 159 | - id: calico-cni-plugin 160 | name: "Calico CNI Plugin" 161 | description: | 162 | The Project Calico plugin for CNI 163 | itemType: entity 164 | iconUrl: classpath://io.brooklyn.clocker.kubernetes:icons/calico.png 165 | item: 166 | type: child-software-process 167 | name: "calico-network-plugin" 168 | 169 | brooklyn.parameters: 170 | - name: calico.version 171 | label: "Calico Version" 172 | description: | 173 | The Project Calico driver version 174 | type: string 175 | default: "0.22.0" 176 | - name: cni.version 177 | label: "CNI Version" 178 | description: | 179 | The CNI version 180 | type: string 181 | default: "0.3.0" 182 | - name: calico.cni.version 183 | label: "Calico CNI Version" 184 | description: | 185 | The Project Calico CNI version 186 | type: string 187 | default: "1.4.2" 188 | - name: etcd.endpoints 189 | label: "Etcd Endpoints" 190 | description: | 191 | The URLs for an etcd KV store 192 | type: string 193 | 194 | brooklyn.config: 195 | install.unique_label: 196 | $brooklyn:formatString: 197 | - "plugin-calico-cni-%s-%s" 198 | - $brooklyn:config("calico.version") 199 | - $brooklyn:config("calico.cni.version") 200 | 201 | shell.env: 202 | CALICO_VERSION: $brooklyn:config("calico.version") 203 | CALICO_CNI_VERSION: $brooklyn:config("calico.cni.version") 204 | CNI_VERSION: $brooklyn:config("cni.version") 205 | ETCD_ENDPOINTS: $brooklyn:config("etcd.endpoints") 206 | HOST_ADDRESS: $brooklyn:parent().attributeWhenReady("host.address") 207 | HOST_SUBNET_ADDRESS: $brooklyn:parent().attributeWhenReady("host.subnet.address") 208 | ENTITY_ID: $brooklyn:parent().attributeWhenReady("entity.id") 209 | 210 | install.command: | 211 | wget https://github.com/projectcalico/calico-containers/releases/download/v${CALICO_VERSION}/calicoctl 212 | chmod +x calicoctl 213 | sudo mv calicoctl /usr/bin 214 | sudo mkdir -p /opt/cni/bin 215 | wget https://github.com/containernetworking/cni/releases/download/v${CNI_VERSION}/cni-v${CNI_VERSION}.tgz 216 | sudo tar --strip-components=1 -xvzf cni-v${CNI_VERSION}.tgz -C /opt/cni/bin 217 | wget https://github.com/projectcalico/calico-cni/releases/download/v${CALICO_CNI_VERSION}/calico 218 | wget https://github.com/projectcalico/calico-cni/releases/download/v${CALICO_CNI_VERSION}/calico-ipam 219 | chmod +x calico calico-ipam 220 | sudo mv calico calico-ipam /opt/cni/bin 221 | docker pull calico/node:v${CALICO_VERSION} 222 | sudo yum install -y ipset 223 | sudo modprobe ip6_tables 224 | sudo modprobe xt_set 225 | 226 | customize.command: | 227 | sudo mkdir -p /etc/cni/net.d 228 | 229 | launch.command: | 230 | sudo -E tee /etc/systemd/system/calico-node.service <<-EOF 231 | [Unit] 232 | Description=Calico Node 233 | After=docker.service 234 | Requires=docker.service 235 | [Service] 236 | User=root 237 | PermissionsStartOnly=true 238 | Environment="ETCD_ENDPOINTS=${ETCD_ENDPOINTS}" 239 | Environment="CALICO_NETWORKING=false" 240 | Environment="HOSTNAME=${HOST_SUBNET_ADDRESS}" 241 | Environment="FELIX_FELIXHOSTNAME=${HOST_SUBNET_ADDRESS}" 242 | Environment="NO_DEFAULT_POOLS=true" 243 | ExecStart=/usr/bin/calicoctl node \ 244 | --ip=${HOST_SUBNET_ADDRESS} \ 245 | --no-pull \ 246 | --node-image=calico/node:v${CALICO_VERSION} \ 247 | --detach=false 248 | Restart=always 249 | RestartSec=10 250 | [Install] 251 | WantedBy=multi-user.target 252 | EOF 253 | sudo systemctl daemon-reload 254 | sudo systemctl enable calico-node 255 | sudo systemctl start calico-node 256 | 257 | checkRunning.command: | 258 | unset DOCKER_HOST 259 | sudo systemctl status calico-node 260 | -------------------------------------------------------------------------------- /kubernetes/catalog/kubernetes/pods.bom: -------------------------------------------------------------------------------- 1 | brooklyn.catalog: 2 | version: "2.1.0-SNAPSHOT" # CLOCKER_VERSION 3 | publish: 4 | description: | 5 | Resources for working with Kubernetes Pod deployments from Apache Brooklyn 6 | license_code: APACHE-2.0 7 | 8 | items: 9 | - id: kubernetes-pod 10 | name: "Kubernetes Pod" 11 | description: | 12 | A Kubernetes YAML pod deployment 13 | itemType: entity 14 | iconUrl: classpath://io.brooklyn.clocker.kubernetes:icons/kubernetes.png 15 | item: 16 | type: child-software-process 17 | 18 | brooklyn.parameters: 19 | - name: kubernetes.pod.file 20 | label: "Kubernetes Pod File" 21 | type: string 22 | - name: kubernetes.pod.namespace 23 | label: "Kubernetes Pod Namespace" 24 | type: string 25 | default: "default" 26 | - name: kubernetes.pod.name 27 | label: "Kubernetes Pod Name" 28 | type: string 29 | - name: template.substitutions 30 | label: "Template Substitutions" 31 | type: java.util.Map 32 | 33 | brooklyn.config: 34 | install.unique_label: 35 | $brooklyn:formatString: 36 | - "pod-%s-%s" 37 | - $brooklyn:config("kubernetes.pod.name") 38 | - $brooklyn:entity("kubernetes-cluster").config("kubernetes.version") 39 | 40 | templates.install: 41 | $brooklyn:config("kubernetes.pod.file"): "pod.yaml" 42 | 43 | shell.env: 44 | NAME: $brooklyn:config("kubernetes.pod.name") 45 | NAMESPACE: $brooklyn:config("kubernetes.pod.namespace") 46 | INSTALL_DIR: $brooklyn:attributeWhenReady("install.dir") 47 | 48 | pre.install.command: | 49 | mkdir -p ${INSTALL_DIR} 50 | 51 | install.command: | 52 | kubectl get namespace ${NAMESPACE} || 53 | ( kubectl create namespace ${NAMESPACE} || true ) 54 | 55 | launch.command: | 56 | kubectl create -f ${INSTALL_DIR}/pod.yaml 57 | 58 | checkRunning.command: | 59 | kubectl get pod --namespace=${NAMESPACE} -l app=${NAME} | 60 | grep "Pending\|ContainerCreating\|Running" 61 | 62 | brooklyn.initializers: 63 | - type: org.apache.brooklyn.core.sensor.ssh.SshCommandSensor 64 | brooklyn.config: 65 | name: kubernetes.pod.name 66 | description: | 67 | Kubernetes pod name 68 | targetType: string 69 | command: | 70 | kubectl get pod --namespace=${NAMESPACE} -l app=${NAME} --output=jsonpath='{range .items[0]}{.metadata.name}' 71 | - type: org.apache.brooklyn.core.sensor.ssh.SshCommandSensor 72 | brooklyn.config: 73 | name: kubernetes.pod.status 74 | description: | 75 | Kubernetes pod status 76 | targetType: string 77 | command: | 78 | kubectl get pod --namespace=${NAMESPACE} -l app=${NAME} -o wide | grep ${NAME} 79 | - type: org.apache.brooklyn.core.sensor.ssh.SshCommandSensor 80 | brooklyn.config: 81 | name: kubernetes.pod.node 82 | description: | 83 | Kubernetes host IP address for the service 84 | targetType: string 85 | command: | 86 | kubectl get pod --namespace=${NAMESPACE} -l app=${NAME} --output=jsonpath='{range .items[0]}{.status.hostIP}' 87 | - type: org.apache.brooklyn.core.sensor.ssh.SshCommandSensor 88 | brooklyn.config: 89 | name: kubernetes.service.port 90 | description: | 91 | Kubernetes exposed NodePort for a service 92 | targetType: integer 93 | command: | 94 | kubectl get service ${NAME} --namespace=${NAMESPACE} --output=jsonpath='{range .spec.ports[0]}{.nodePort}' 95 | - type: org.apache.brooklyn.core.sensor.ssh.SshCommandSensor 96 | brooklyn.config: 97 | name: kubernetes.pod.phase 98 | description: | 99 | Kubernetes pod status phase 100 | targetType: string 101 | command: | 102 | kubectl get pod --namespace=${NAMESPACE} -l app=${NAME} --output=jsonpath='{range .items[0]}{.status.phase}' 103 | 104 | brooklyn.enrichers: 105 | - type: org.apache.brooklyn.enricher.stock.Transformer 106 | brooklyn.config: 107 | uniqueTag: kubernetes-pod-url-publisher 108 | enricher.triggerSensors: 109 | - $brooklyn:sensor("kubernetes.pod.node") 110 | - $brooklyn:sensor("kubernetes.service.port") 111 | enricher.targetSensor: $brooklyn:sensor("kubernetes.service.url") 112 | enricher.targetValue: 113 | $brooklyn:formatString: 114 | - "http://%s:%d/" 115 | - $brooklyn:attributeWhenReady("kubernetes.pod.node") 116 | - $brooklyn:attributeWhenReady("kubernetes.service.port") 117 | - type: org.apache.brooklyn.enricher.stock.Propagator 118 | brooklyn.config: 119 | uniqueTag: kubernetes-pod-url-propagator 120 | enricher.propagating.sensorMapping: 121 | $brooklyn:sensor("kubernetes.service.url"): 122 | $brooklyn:sensor("org.apache.brooklyn.core.entity.Attributes", "main.uri") 123 | 124 | - id: kube-dns-pod 125 | name: "KubeDNS Pod" 126 | description: | 127 | KubeDNS service pod 128 | itemType: entity 129 | iconUrl: classpath://io.brooklyn.clocker.kubernetes:icons/kubernetes.png 130 | item: 131 | type: kubernetes-pod 132 | 133 | brooklyn.config: 134 | kubernetes.pod.name: "kube-dns" 135 | kubernetes.pod.file: "classpath://io.brooklyn.clocker.kubernetes:kubernetes/kube-dns.yaml" 136 | kubernetes.pod.namespace: "kube-system" 137 | 138 | template.substitutions: 139 | kubernetes_url: $brooklyn:entity("kubernetes-cluster").attributeWhenReady("kubernetes.url") 140 | replicas: $brooklyn:entity("kubernetes-cluster").config("kubernetes.initial.size") 141 | dns_service_ip: $brooklyn:entity("kubernetes-cluster").config("kubernetes.dns.address") 142 | dns_service_domain: $brooklyn:entity("kubernetes-cluster").config("kubernetes.dns.domain") 143 | 144 | - id: kubernetes-dashboard-pod 145 | name: "Kubernetes Dashboard Pod" 146 | description: | 147 | Kubernetes dashboard UI service pod 148 | itemType: entity 149 | iconUrl: classpath://io.brooklyn.clocker.kubernetes:icons/kubernetes.png 150 | item: 151 | type: kubernetes-pod 152 | 153 | brooklyn.config: 154 | kubernetes.pod.name: "kubernetes-dashboard" 155 | kubernetes.pod.file: "classpath://io.brooklyn.clocker.kubernetes:kubernetes/kubernetes-dashboard.yaml" 156 | kubernetes.pod.namespace: "kube-system" 157 | 158 | template.substitutions: 159 | kubernetes_url: $brooklyn:entity("kubernetes-cluster").attributeWhenReady("kubernetes.url") 160 | 161 | - id: calico-policy-controller-pod 162 | name: "Calico Policy Controller Pod" 163 | description: | 164 | Calico policy controller pod 165 | itemType: entity 166 | iconUrl: classpath://io.brooklyn.clocker.kubernetes:icons/calico.png 167 | item: 168 | type: kubernetes-pod 169 | 170 | brooklyn.config: 171 | kubernetes.pod.name: "policy-controller" 172 | kubernetes.pod.file: "classpath://io.brooklyn.clocker.kubernetes:kubernetes/policy-controller.yaml" 173 | kubernetes.pod.namespace: "kube-system" 174 | 175 | template.substitutions: 176 | kubernetes_url: $brooklyn:entity("kubernetes-cluster").attributeWhenReady("kubernetes.url") 177 | etcd_endpoints: $brooklyn:entity("etcd-cluster").attributeWhenReady("etcd.urls") 178 | 179 | - id: prometheus-pod 180 | name: "Prometheus Monitoring Pod" 181 | description: | 182 | Prometheus monitoring service pod 183 | itemType: entity 184 | iconUrl: 185 | iconUrl: classpath://io.brooklyn.clocker.kubernetes:icons/prometheus.png 186 | item: 187 | type: kubernetes-pod 188 | 189 | brooklyn.config: 190 | kubernetes.pod.name: "prometheus" 191 | kubernetes.pod.file: "classpath://io.brooklyn.clocker.kubernetes:kubernetes/prometheus.yaml" 192 | kubernetes.pod.namespace: "kube-system" 193 | 194 | template.substitutions: 195 | kubernetes_url: $brooklyn:entity("kubernetes-cluster").attributeWhenReady("kubernetes.url") 196 | -------------------------------------------------------------------------------- /kubernetes/examples/kubernetes-minimal.yaml: -------------------------------------------------------------------------------- 1 | id: kubernetes-minimal 2 | name: "Kubernetes Cluster" 3 | description: | 4 | Uses the default settings for configuring Kubernetes, apart from the initial 5 | size of the cluster of worker nodes. 6 | 7 | Deploys on AWS using only the default Kubernetes entity configuration. Requires 8 | a security group to be deined in the AWS region or VPC, which should be 9 | set in the 'templateOptions' of the location, as seen below. 10 | 11 | location: 12 | jclouds:aws-ec2: 13 | region: eu-central-1 14 | privateKeyFile: "~/.ssh/kubernetes.pem" 15 | loginUser.privateKeyFile: "~/.ssh/kubernetes.pem" 16 | keyPair: "kubernetes" 17 | templateOptions: 18 | securityGroups: 19 | - "kubernetes" 20 | 21 | services: 22 | - type: kubernetes-cluster-application 23 | name: "kubernetes-aws-ec2" 24 | brooklyn.config: 25 | kubernetes.initial.size: 2 26 | kubernetes.sharedsecuritygroup.create: true 27 | -------------------------------------------------------------------------------- /kubernetes/examples/kubernetes.yaml: -------------------------------------------------------------------------------- 1 | id: kubernetes 2 | name: "Kubernetes Cluster" 3 | description: | 4 | Includes built-in etcd discovery cluster and TLS protected Docker. 5 | 6 | Deploys on CentOS 7 VMs in SoftLayer, on a single VLAN segment. 7 | 8 | location: 9 | jclouds:softlayer: 10 | region: ams01 11 | identity: xxxxxxxx 12 | credential: XXXXXXXX 13 | privateKeyFile: ~/.ssh/softlayer.pem 14 | customizers: 15 | - $brooklyn:object: 16 | type: org.apache.brooklyn.location.jclouds.softlayer.SoftLayerSameVlanLocationCustomizer 17 | brooklyn.config: 18 | softlayer.vlan.scopeUid: "kubernetes" 19 | 20 | services: 21 | - type: kubernetes-cluster-application 22 | id: kubernetes 23 | name: "kubernetes" 24 | brooklyn.config: 25 | kubernetes.debug: true 26 | kubernetes.version: 1.4.3 27 | start.timeout: 30m 28 | kubernetes.master.size: 2 29 | kubernetes.initial.size: 4 30 | kubernetes.max.size: 16 31 | etcd.initial.size: 3 32 | kubernetes.apiserver.port: 8000 33 | kubernetes.scaling.cpu.limit: 0.80 34 | kubernetes.recovery.stabilizationDelay: 30s 35 | kubernetes.recovery.failOnRecurringFailuresInThisDuration: 300000 36 | docker.recovery.stabilizationDelay: 30s 37 | docker.recovery.failOnRecurringFailuresInThisDuration: 5m 38 | kubernetes.pod.cidr: "10.250.0.0/16" 39 | kubernetes.minRam: 10g 40 | kubernetes.minCores: 4 41 | provisioning.properties: 42 | minRam: 2g 43 | minCores: 1 44 | -------------------------------------------------------------------------------- /kubernetes/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | 8 | io.brooklyn.clocker 9 | clocker-parent 10 | 2.1.0-SNAPSHOT 11 | 12 | 13 | Clocker :: Kubernetes 14 | clocker-kubernetes 15 | bundle 16 | 17 | 18 | 19 | 20 | catalog 21 | false 22 | 23 | 24 | resources 25 | false 26 | 27 | 28 | external-resources 29 | false 30 | 31 | 32 | tests 33 | false 34 | tests 35 | 36 | 37 | 38 | 39 | 40 | org.codehaus.mojo 41 | build-helper-maven-plugin 42 | 43 | 44 | attach-artifact 45 | package 46 | 47 | attach-artifact 48 | 49 | 50 | 51 | 52 | ${project.basedir}/catalog/kubernetes/kubernetes.bom 53 | bom 54 | kubernetes 55 | 56 | 57 | ${project.basedir}/catalog/kubernetes/pods.bom 58 | bom 59 | pods 60 | 61 | 62 | ${project.basedir}/catalog/kubernetes/plugins.bom 63 | bom 64 | plugins 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /kubernetes/resources/icons/calico.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brooklyncentral/clocker/e1ff91d4959d2238efcf78569d600f95273730d4/kubernetes/resources/icons/calico.png -------------------------------------------------------------------------------- /kubernetes/resources/icons/flannel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brooklyncentral/clocker/e1ff91d4959d2238efcf78569d600f95273730d4/kubernetes/resources/icons/flannel.png -------------------------------------------------------------------------------- /kubernetes/resources/icons/kubernetes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brooklyncentral/clocker/e1ff91d4959d2238efcf78569d600f95273730d4/kubernetes/resources/icons/kubernetes.png -------------------------------------------------------------------------------- /kubernetes/resources/icons/openshift.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brooklyncentral/clocker/e1ff91d4959d2238efcf78569d600f95273730d4/kubernetes/resources/icons/openshift.png -------------------------------------------------------------------------------- /kubernetes/resources/icons/prometheus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brooklyncentral/clocker/e1ff91d4959d2238efcf78569d600f95273730d4/kubernetes/resources/icons/prometheus.png -------------------------------------------------------------------------------- /kubernetes/resources/kubernetes/basic_auth.csv: -------------------------------------------------------------------------------- 1 | guest,guest,1001 2 | p4ssw0rd,admin,1002 3 | pr0m3th3us,prometheus,1003 -------------------------------------------------------------------------------- /kubernetes/resources/kubernetes/kube-dns.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: kube-dns 5 | namespace: kube-system 6 | labels: 7 | app: kube-dns 8 | name: kube-dns-service 9 | kubernetes.io/cluster-service: "true" 10 | kubernetes.io/name: "KubeDNS" 11 | spec: 12 | selector: 13 | app: kube-dns 14 | clusterIP: ${config['template.substitutions']['dns_service_ip']} 15 | ports: 16 | - name: dns 17 | port: 53 18 | protocol: UDP 19 | - name: dns-tcp 20 | port: 53 21 | protocol: TCP 22 | --- 23 | apiVersion: v1 24 | kind: ReplicationController 25 | metadata: 26 | name: kube-dns 27 | namespace: kube-system 28 | labels: 29 | app: kube-dns 30 | name: kube-dns-replicationcontroller 31 | version: v20 32 | kubernetes.io/cluster-service: "true" 33 | spec: 34 | replicas: ${config['template.substitutions']['replicas']} 35 | selector: 36 | app: kube-dns 37 | version: v20 38 | template: 39 | metadata: 40 | labels: 41 | app: kube-dns 42 | version: v20 43 | kubernetes.io/cluster-service: "true" 44 | annotations: 45 | scheduler.alpha.kubernetes.io/critical-pod: '' 46 | scheduler.alpha.kubernetes.io/tolerations: '[{"key":"CriticalAddonsOnly", "operator":"Exists"}]' 47 | spec: 48 | containers: 49 | - name: kubedns 50 | image: gcr.io/google_containers/kubedns-amd64:1.8 51 | resources: 52 | limits: 53 | cpu: 100m 54 | memory: 170Mi 55 | requests: 56 | cpu: 100m 57 | memory: 70Mi 58 | livenessProbe: 59 | httpGet: 60 | path: /healthz 61 | port: 8080 62 | scheme: HTTP 63 | initialDelaySeconds: 60 64 | timeoutSeconds: 5 65 | successThreshold: 1 66 | failureThreshold: 5 67 | readinessProbe: 68 | httpGet: 69 | path: /readiness 70 | port: 8081 71 | scheme: HTTP 72 | initialDelaySeconds: 30 73 | timeoutSeconds: 5 74 | args: 75 | - --domain=${config['template.substitutions']['dns_service_domain']}.local. 76 | - --dns-port=10053 77 | - --kube-master-url=${config['template.substitutions']['kubernetes_url']} 78 | ports: 79 | - containerPort: 10053 80 | name: dns-local 81 | protocol: UDP 82 | - containerPort: 10053 83 | name: dns-tcp-local 84 | protocol: TCP 85 | - name: dnsmasq 86 | image: gcr.io/google_containers/kube-dnsmasq-amd64:1.3 87 | args: 88 | - --cache-size=1000 89 | - --no-resolv 90 | - --server=127.0.0.1#10053 91 | ports: 92 | - containerPort: 53 93 | name: dns 94 | protocol: UDP 95 | - containerPort: 53 96 | name: dns-tcp 97 | protocol: TCP 98 | - name: healthz 99 | image: gcr.io/google_containers/exechealthz-amd64:1.1 100 | resources: 101 | limits: 102 | cpu: 10m 103 | memory: 50Mi 104 | requests: 105 | cpu: 10m 106 | memory: 50Mi 107 | args: 108 | - >- 109 | -cmd=nslookup kubernetes.default.svc.${config['template.substitutions']['dns_service_domain']}.local 127.0.0.1 > /dev/null && 110 | nslookup kubernetes.default.svc.${config['template.substitutions']['dns_service_domain']}.local 127.0.0.1:10053 > /dev/null 111 | - -port=8080 112 | - -quiet 113 | ports: 114 | - containerPort: 8080 115 | protocol: TCP 116 | dnsPolicy: Default -------------------------------------------------------------------------------- /kubernetes/resources/kubernetes/kubernetes-dashboard.yaml: -------------------------------------------------------------------------------- 1 | kind: Deployment 2 | apiVersion: extensions/v1beta1 3 | metadata: 4 | name: kubernetes-dashboard 5 | namespace: kube-system 6 | labels: 7 | app: kubernetes-dashboard 8 | name: kubernetes-dashboard-deployment 9 | version: v1.4.1 10 | spec: 11 | replicas: 1 12 | selector: 13 | matchLabels: 14 | app: kubernetes-dashboard 15 | template: 16 | metadata: 17 | labels: 18 | app: kubernetes-dashboard 19 | annotations: 20 | scheduler.alpha.kubernetes.io/critical-pod: '' 21 | scheduler.alpha.kubernetes.io/tolerations: '[{"key":"CriticalAddonsOnly", "operator":"Exists"}]' 22 | spec: 23 | containers: 24 | - name: kubernetes-dashboard 25 | image: gcr.io/google_containers/kubernetes-dashboard-amd64:v1.4.1 26 | imagePullPolicy: Always 27 | ports: 28 | - containerPort: 9090 29 | protocol: TCP 30 | args: 31 | - --apiserver-host=${config['template.substitutions']['kubernetes_url']} 32 | livenessProbe: 33 | httpGet: 34 | path: / 35 | port: 9090 36 | initialDelaySeconds: 30 37 | timeoutSeconds: 30 38 | --- 39 | kind: Service 40 | apiVersion: v1 41 | metadata: 42 | name: kubernetes-dashboard 43 | namespace: kube-system 44 | labels: 45 | app: kubernetes-dashboard 46 | name: kubernetes-dashboard-service 47 | spec: 48 | type: NodePort 49 | ports: 50 | - port: 80 51 | targetPort: 9090 52 | selector: 53 | app: kubernetes-dashboard 54 | -------------------------------------------------------------------------------- /kubernetes/resources/kubernetes/policy-controller.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: extensions/v1beta1 2 | kind: ReplicaSet 3 | metadata: 4 | name: policy-controller 5 | namespace: kube-system 6 | labels: 7 | app: policy-controller 8 | name: policy-controller-pod 9 | version: "v0.3.0" 10 | kubernetes.io/cluster-service: "true" 11 | projectcalico.org/app: "policy-controller" 12 | spec: 13 | replicas: 1 14 | selector: 15 | matchLabels: 16 | app: policy-controller 17 | kubernetes.io/cluster-service: "true" 18 | template: 19 | metadata: 20 | name: policy-controller 21 | namespace: kube-system 22 | labels: 23 | app: policy-controller 24 | kubernetes.io/cluster-service: "true" 25 | spec: 26 | hostNetwork: true 27 | containers: 28 | - name: policy-controller 29 | image: calico/kube-policy-controller:v0.3.0 30 | env: 31 | - name: ETCD_ENDPOINTS 32 | value: "${config['template.substitutions']['etcd_endpoints']}" 33 | - name: K8S_API 34 | value: "${config['template.substitutions']['kubernetes_url']}" 35 | - name: LEADER_ELECTION 36 | value: "true" 37 | - name: CONFIGURE_ETC_HOSTS 38 | value: "true" 39 | - name: leader-elector 40 | image: quay.io/calico/leader-elector:v0.1.0 41 | imagePullPolicy: IfNotPresent 42 | args: 43 | - "--election=calico-policy-election" 44 | - "--election-namespace=kube-system" 45 | - "--http=127.0.0.1:4040" 46 | volumeMounts: 47 | - mountPath: "/kubeconfig" 48 | name: kubeconfig 49 | volumes: 50 | - name: kubeconfig 51 | hostPath: 52 | path: "/etc/kubernetes/kubeconfig" 53 | -------------------------------------------------------------------------------- /kubernetes/resources/kubernetes/prometheus.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: prometheus 5 | namespace: kube-system 6 | labels: 7 | app: prometheus 8 | name: prometheus-service 9 | annotations: 10 | prometheus.io/scrape: 'true' 11 | spec: 12 | selector: 13 | app: prometheus 14 | type: NodePort 15 | ports: 16 | - name: prometheus 17 | protocol: TCP 18 | port: 9090 19 | nodePort: 30900 20 | --- 21 | apiVersion: extensions/v1beta1 22 | kind: Deployment 23 | metadata: 24 | name: prometheus 25 | namespace: kube-system 26 | labels: 27 | app: prometheus 28 | name: prometheus-deployment 29 | spec: 30 | replicas: 1 31 | template: 32 | metadata: 33 | labels: 34 | app: prometheus 35 | spec: 36 | containers: 37 | - image: quay.io/prometheus/prometheus:v1.1.3 38 | name: prometheus 39 | command: 40 | - "/bin/prometheus" 41 | args: 42 | - "-config.file=/etc/prometheus/prometheus.yml" 43 | - "-storage.local.path=/prometheus" 44 | - "-storage.local.retention=24h" 45 | ports: 46 | - name: web 47 | containerPort: 9090 48 | protocol: TCP 49 | volumeMounts: 50 | - mountPath: "/prometheus" 51 | name: data 52 | - mountPath: "/etc/prometheus" 53 | name: config-volume 54 | resources: 55 | requests: 56 | cpu: 100m 57 | memory: 100Mi 58 | limits: 59 | cpu: 500m 60 | memory: 2500Mi 61 | volumes: 62 | - name: data 63 | emptyDir: {} 64 | - name: config-volume 65 | configMap: 66 | name: prometheus-config 67 | --- 68 | apiVersion: v1 69 | kind: ConfigMap 70 | metadata: 71 | name: prometheus-config 72 | namespace: kube-system 73 | data: 74 | prometheus.yml: |- 75 | global: 76 | scrape_interval: 30s 77 | scrape_timeout: 30s 78 | scrape_configs: 79 | - job_name: 'prometheus' 80 | static_configs: 81 | - targets: 82 | - localhost:9090 83 | - job_name: 'kubernetes-cluster' 84 | kubernetes_sd_configs: 85 | - api_servers: 86 | - ${config['template.substitutions']['kubernetes_url']} 87 | basic_auth: 88 | username: prometheus 89 | password: pr0m3th3us 90 | role: apiserver 91 | - job_name: 'kubernetes-nodes' 92 | kubernetes_sd_configs: 93 | - api_servers: 94 | - ${config['template.substitutions']['kubernetes_url']} 95 | basic_auth: 96 | username: prometheus 97 | password: pr0m3th3us 98 | role: node 99 | relabel_configs: 100 | - action: labelmap 101 | regex: __meta_kubernetes_node_label_(.+) 102 | - source_labels: [__meta_kubernetes_role] 103 | action: replace 104 | target_label: kubernetes_role 105 | - source_labels: [__address__] 106 | regex: (.*):10250 107 | replacement: ${r"${1}:10255"} 108 | target_label: __address__ 109 | - job_name: 'kubernetes-service-endpoints' 110 | kubernetes_sd_configs: 111 | - api_servers: 112 | - ${config['template.substitutions']['kubernetes_url']} 113 | basic_auth: 114 | username: prometheus 115 | password: pr0m3th3us 116 | role: endpoint 117 | relabel_configs: 118 | - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape] 119 | action: keep 120 | regex: true 121 | - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme] 122 | action: replace 123 | target_label: __scheme__ 124 | regex: (https?) 125 | - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path] 126 | action: replace 127 | target_label: __metrics_path__ 128 | regex: (.+) 129 | - source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port] 130 | action: replace 131 | target_label: __address__ 132 | regex: (.+)(?::\d+);(\d+) 133 | replacement: ${r"${1}:${2}"} 134 | - action: labelmap 135 | regex: __meta_kubernetes_service_label_(.+) 136 | - source_labels: [__meta_kubernetes_service_namespace] 137 | action: replace 138 | target_label: kubernetes_namespace 139 | - source_labels: [__meta_kubernetes_service_name] 140 | action: replace 141 | target_label: kubernetes_name -------------------------------------------------------------------------------- /kubernetes/tests/kubernetes/kubernetes.tests.bom: -------------------------------------------------------------------------------- 1 | brooklyn.catalog: 2 | items: 3 | - https://github.com/brooklyncentral/common-catalog-utils/releases/download/v0.1.0/common.tests.bom 4 | - id: kubernetes-cluster-tests 5 | version: "2.1.0-SNAPSHOT" # CLOCKER_VERSION 6 | itemType: template 7 | iconUrl: https://twitter.com/kubernetesio/profile_image?size=original 8 | name: Kubernetes Cluster Tests 9 | item: 10 | services: 11 | - type: kubernetes-cluster-template 12 | id: k8s-cluster 13 | - type: org.apache.brooklyn.test.framework.TestCase 14 | name: K8S Smoke Tests 15 | brooklyn.config: 16 | timeout: 1h 17 | targetId: k8s-cluster 18 | brooklyn.children: 19 | - type: assert-up-and-running-initial 20 | name: "1. K8S cluster up and running" 21 | - type: assert-reachable 22 | name: "2. K8S UI Reachable" 23 | brooklyn.config: 24 | endpointSensor: main.uri 25 | timeout: 5m 26 | - type: org.apache.brooklyn.test.framework.TestSensor 27 | name: "3. Size of kubernetes master cluster is 3" 28 | targetId: kubernetes-master-cluster 29 | sensor: group.members.count 30 | assert: 31 | equals: 3 32 | - type: org.apache.brooklyn.test.framework.SimpleShellCommandTest 33 | name: "4. Kill a master node" 34 | target: $brooklyn:entity("kubernetes-master-notfirst") 35 | command: | 36 | nohup sudo bash -c 'sleep 10 && shutdown -h -t0 now' & 37 | - type: org.apache.brooklyn.test.framework.TestSensor 38 | name: "5. Size of kubernetes master cluster increased to 4" 39 | targetId: kubernetes-master-cluster 40 | sensor: group.members.count 41 | assert: 42 | equals: 4 43 | - type: org.apache.brooklyn.test.framework.TestSensor 44 | name: "6. Size of kubernetes master cluster decreased to 3" 45 | targetId: kubernetes-master-cluster 46 | sensor: group.members.count 47 | assert: 48 | equals: 3 49 | - type: org.apache.brooklyn.test.framework.TestSensor 50 | name: "7. Size of kubernetes worker cluster is 3" 51 | targetId: kubernetes-worker-cluster 52 | sensor: group.members.count 53 | assert: 54 | equals: 3 55 | - type: org.apache.brooklyn.test.framework.SimpleShellCommandTest 56 | name: "8. Kill a worker node" 57 | target: $brooklyn:entity("kubernetes-worker") 58 | command: | 59 | nohup sudo bash -c 'sleep 10 && shutdown -h -t0 now' & 60 | - type: org.apache.brooklyn.test.framework.TestSensor 61 | name: "9. Size of kubernetes worker cluster increased to 4" 62 | targetId: kubernetes-worker-cluster 63 | sensor: group.members.count 64 | assert: 65 | equals: 4 66 | - type: org.apache.brooklyn.test.framework.TestSensor 67 | name: "10. Size of kubernetes worker cluster decreased to 3" 68 | targetId: kubernetes-worker-cluster 69 | sensor: group.members.count 70 | assert: 71 | equals: 3 72 | - type: invoke-effector 73 | name: "11. kubectl create deployment [A]" 74 | target: $brooklyn:entity("kubernetes-master") 75 | effector: kubectl 76 | params: 77 | args: 'run workload-a --image=brooklyncentral/centos:7 --replicas=1 --port=22' 78 | - type: org.apache.brooklyn.test.framework.SimpleShellCommandTest 79 | name: "12. kubectl create deployment [B]" 80 | target: $brooklyn:entity("kubernetes-master") 81 | assertStatus: 82 | equals: 0 83 | command: | 84 | kubectl run workload-b --image=brooklyncentral/centos:7 --replicas=1 --port=22 85 | - type: org.apache.brooklyn.test.framework.SimpleShellCommandTest 86 | name: "13. Assert [A] running" 87 | target: $brooklyn:entity("kubernetes-master-notfirst") 88 | command: | 89 | kubectl get pods | grep -i running 90 | assertOut: 91 | contains: 'workload-a' 92 | - type: org.apache.brooklyn.test.framework.SimpleShellCommandTest 93 | name: "14. Assert [B] running" 94 | target: $brooklyn:entity("kubernetes-master-notfirst") 95 | command: | 96 | kubectl get pods | grep -i running 97 | assertOut: 98 | contains: 'workload-b' 99 | - type: org.apache.brooklyn.test.framework.SimpleShellCommandTest 100 | name: "15. Test ICMP [A -> B]" 101 | target: $brooklyn:entity("kubernetes-master") 102 | command: | 103 | POD_A="$(kubectl get pods -o wide | grep workload-a | tr -s ' ' | cut -d ' ' -f1)" 104 | IP_B="$(kubectl get pods -o wide | grep workload-b | tr -s ' ' | cut -d ' ' -f6)" 105 | kubectl exec ${POD_A} -- ping -c 1 ${IP_B} 106 | assertOut: 107 | contains: '1 received' 108 | - type: org.apache.brooklyn.test.framework.SimpleShellCommandTest 109 | name: "16. Test ICMP [B -> A]" 110 | target: $brooklyn:entity("kubernetes-master") 111 | command: | 112 | POD_B="$(kubectl get pods -o wide | grep workload-b | tr -s ' ' | cut -d ' ' -f1)" 113 | IP_A="$(kubectl get pods -o wide | grep workload-a | tr -s ' ' | cut -d ' ' -f6)" 114 | kubectl exec ${POD_B} -- ping -c 1 ${IP_A} 115 | assertOut: 116 | contains: '1 received' 117 | - type: org.apache.brooklyn.test.framework.SimpleShellCommandTest 118 | name: "17. Install Netcat" 119 | target: $brooklyn:entity("kubernetes-master") 120 | command: | 121 | POD_A="$(kubectl get pods -o wide | grep workload-a | tr -s ' ' | cut -d ' ' -f1)" 122 | POD_B="$(kubectl get pods -o wide | grep workload-b | tr -s ' ' | cut -d ' ' -f1)" 123 | kubectl exec ${POD_A} -- yum install -y nc 124 | kubectl exec ${POD_B} -- yum install -y nc 125 | - type: org.apache.brooklyn.test.framework.SimpleShellCommandTest 126 | name: "18. Check TCP" 127 | target: $brooklyn:entity("kubernetes-master") 128 | command: | 129 | POD_A="$(kubectl get pods -o wide | grep workload-a | tr -s ' ' | cut -d ' ' -f1)" 130 | POD_B="$(kubectl get pods -o wide | grep workload-b | tr -s ' ' | cut -d ' ' -f1)" 131 | IP_A="$(kubectl get pods -o wide | grep workload-a | tr -s ' ' | cut -d ' ' -f6)" 132 | kubectl exec ${POD_A} -- bash -c "nohup nc -l -k 5000 >> /tmp/nohup.out 2>&1" & 133 | kubectl exec ${POD_A} -- bash -c "echo connect_from_A | nc -C localhost 5000" 134 | kubectl exec ${POD_B} -- bash -c "echo connect_from_B | nc -C ${IP_A} 5000" 135 | kubectl exec ${POD_A} -- cat /tmp/nohup.out | tr -d "\n\r" 136 | assertOut: 137 | contains: 'connect_from_Aconnect_from_B' 138 | - type: org.apache.brooklyn.test.framework.SimpleShellCommandTest 139 | name: "19. Check UDP" 140 | target: $brooklyn:entity("kubernetes-master") 141 | command: | 142 | POD_A="$(kubectl get pods -o wide | grep workload-a | tr -s ' ' | cut -d ' ' -f1)" 143 | POD_B="$(kubectl get pods -o wide | grep workload-b | tr -s ' ' | cut -d ' ' -f1)" 144 | IP_A="$(kubectl get pods -o wide | grep workload-a | tr -s ' ' | cut -d ' ' -f6)" 145 | kubectl exec ${POD_A} -- bash -c "nohup nc -u -l 5000 >> /tmp/nohup2.out 2>&1" & 146 | kubectl exec ${POD_A} -- bash -c "echo connect_from_A | nc -u -C localhost 5000" 147 | kubectl exec ${POD_A} -- bash -c "nohup nc -u -l 5001 >> /tmp/nohup2.out 2>&1" & 148 | kubectl exec ${POD_B} -- bash -c "echo connect_from_B | nc -u -C ${IP_A} 5001" 149 | kubectl exec ${POD_A} -- cat /tmp/nohup2.out | tr -d "\n\r" 150 | assertOut: 151 | contains: 'connect_from_Aconnect_from_B' 152 | - type: org.apache.brooklyn.test.framework.SimpleShellCommandTest 153 | name: "20. Kill deployments [A,B]" 154 | target: $brooklyn:entity("kubernetes-master") 155 | command: | 156 | kubectl delete deployment workload-a 157 | kubectl delete deployment workload-b 158 | - type: org.apache.brooklyn.test.framework.SimpleShellCommandTest 159 | name: "21. Assert [A,B] NOT running" 160 | target: $brooklyn:entity("kubernetes-master") 161 | command: | 162 | kubectl get deployments | grep workload- | wc -l 163 | assertOut: 164 | contains: '0' 165 | - type: org.apache.brooklyn.test.framework.TestSshCommand 166 | name: "22. Check Prometheus UI is Reachable" 167 | brooklyn.config: 168 | targetId: prometheus 169 | timeout: 1m 170 | shell.env: 171 | K8S_SERVICE_PORT: $brooklyn:entity("prometheus").attributeWhenReady("kubernetes.service.port") 172 | HOST_SUBNET_ADDRESS: $brooklyn:entity("prometheus").attributeWhenReady("host.subnet.address") 173 | command: | 174 | set -e 175 | sudo yum install -y curl 176 | curl -I --max-time 60 "http://${HOST_SUBNET_ADDRESS}:${K8S_SERVICE_PORT}" 177 | assertStatus: 178 | equals: 0 179 | -------------------------------------------------------------------------------- /kubernetes/tests/kubernetes/tests.default.bom: -------------------------------------------------------------------------------- 1 | brooklyn.catalog: 2 | version: "2.1.0-SNAPSHOT" # CLOCKER_VERSION 3 | iconUrl: https://twitter.com/kubernetesio/profile_image?size=original 4 | license_code: APACHE-2.0 5 | dependsOn: 6 | - tests/kubernetes.tests.bom 7 | items: 8 | - id: kubernetes-tests-default 9 | name: "Clocker Kubernetes Tests (DEFAULT)" 10 | description: | 11 | Tests on Kubernetes 12 | itemType: template 13 | item: 14 | brooklyn.config: 15 | timeout: 1h 16 | timeout.initialStartup: 1h 17 | timeout.runtimeAssertion: 1h 18 | kubernetes.master.size: 3 19 | kubernetes.initial.size: 3 20 | kubernetes.max.size: 5 21 | etcd.initial.size: 3 22 | kubernetes.version: 1.4.3 23 | kubernetes.cluster.name: clocker 24 | kubernetes.pod.cidr: 172.16.0.0/16 25 | kubernetes.apiserver.port: 8080 26 | kubernetes.sharedsecuritygroup.create: true 27 | kubernetes.minRam: 2000 28 | kubernetes.minCores: 1 29 | autoscaler.resizeUpStabilizationDelay: 60s 30 | kubernetes.scaling.cpu.limit: 2.0 31 | services: 32 | - type: kubernetes-cluster-tests 33 | -------------------------------------------------------------------------------- /kubernetes/tests/kubernetes/tests.no-shared-security-group.bom: -------------------------------------------------------------------------------- 1 | brooklyn.catalog: 2 | version: "2.1.0-SNAPSHOT" # CLOCKER_VERSION 3 | iconUrl: https://twitter.com/kubernetesio/profile_image?size=original 4 | license_code: APACHE-2.0 5 | dependsOn: 6 | - tests/kubernetes.tests.bom 7 | items: 8 | - id: kubernetes-tests-no-shared-security-group 9 | name: "Clocker Kubernetes Tests (NO SHARED SECURITY GROUP)" 10 | description: | 11 | Tests on Kubernetes 12 | itemType: template 13 | item: 14 | brooklyn.config: 15 | timeout: 1h 16 | timeout.initialStartup: 1h 17 | timeout.runtimeAssertion: 1h 18 | kubernetes.master.size: 3 19 | kubernetes.initial.size: 3 20 | kubernetes.max.size: 5 21 | etcd.initial.size: 3 22 | kubernetes.version: 1.4.3 23 | kubernetes.cluster.name: clocker 24 | kubernetes.pod.cidr: 172.16.0.0/16 25 | kubernetes.apiserver.port: 8080 26 | kubernetes.sharedsecuritygroup.create: false 27 | kubernetes.minRam: 2000 28 | kubernetes.minCores: 1 29 | autoscaler.resizeUpStabilizationDelay: 60s 30 | services: 31 | - type: kubernetes-cluster-tests 32 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | io.brooklyn.clocker 8 | clocker-parent 9 | pom 10 | 2.1.0-SNAPSHOT 11 | 12 | Clocker 13 | Apache Brooklyn blueprints to deploy and manage Docker environments 14 | https://github.com/brooklyncentral/clocker 15 | 16 | 17 | 0.1.3 18 | 2.7.0-SNAPSHOT 19 | 1.4 20 | 21 | 4.0.8 22 | 3.2.0 23 | 2.8.2 24 | 3.6.1 25 | 3.0.2 26 | 1.6 27 | UTF-8 28 | UTF-8 29 | 1.0 30 | 2.5.2 31 | 32 | 33 | 34 | common 35 | swarm 36 | kubernetes 37 | feature 38 | 39 | 40 | 41 | https://github.com/brooklyncentral/clocker 42 | scm:git:https://github.com/brooklyncentral/clocker.git 43 | scm:git:git@github.com:brooklyncentral/clocker.git 44 | HEAD 45 | 46 | 47 | 48 | GitHub Issues 49 | https://github.com/brooklyncentral/clocker/issues 50 | 51 | 52 | 53 | 54 | Apache 2.0 55 | http://www.apache.org/licenses/LICENSE-2.0.txt 56 | 57 | 58 | 59 | 60 | 61 | 62 | Andrew Kennedy 63 | https://github.com/grkvlt 64 | 65 | founder 66 | 67 | 68 | 69 | Aled Sage 70 | https://github.com/aledsage 71 | 72 | 73 | Mark McKenna 74 | https://github.com/m4rkmckenna 75 | 76 | 77 | 78 | 79 | 80 | sonatype-nexus-snapshots 81 | Sonatype Nexus Snapshots 82 | https://oss.sonatype.org/content/repositories/snapshots/ 83 | 84 | 85 | 86 | 87 | 88 | sonatype-nexus-snapshots 89 | Sonatype Nexus Snapshots 90 | https://oss.sonatype.org/content/repositories/snapshots 91 | 92 | false 93 | 94 | 95 | true 96 | 97 | 98 | 99 | 100 | 101 | 102 | sonatype-oss-releases 103 | https://oss.sonatype.org/content/repositories/releases/ 104 | 105 | 106 | sonatype-oss-snapshots 107 | https://oss.sonatype.org/content/repositories/snapshots 108 | 109 | false 110 | 111 | 112 | true 113 | 114 | 115 | 116 | apache-snapshots 117 | https://repository.apache.org/content/repositories/snapshots 118 | 119 | false 120 | 121 | 122 | true 123 | 124 | 125 | 126 | 127 | cloudsoft-releases 128 | http://ccweb.cloudsoftcorp.com/maven/libs-release-local/ 129 | 130 | 131 | cloudsoft-snapshots 132 | http://ccweb.cloudsoftcorp.com/maven/libs-snapshot-local/ 133 | 134 | false 135 | 136 | 137 | true 138 | 139 | 140 | 141 | cloudsoft-developers 142 | http://developers.cloudsoftcorp.com/download/maven2/ 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | org.apache.maven.plugins 151 | maven-compiler-plugin 152 | ${maven-compiler-plugin.version} 153 | 154 | 155 | org.apache.felix 156 | maven-bundle-plugin 157 | ${maven-bundle-plugin.version} 158 | 159 | 160 | org.apache.maven.plugins 161 | maven-deploy-plugin 162 | ${maven-deploy-plugin.version} 163 | 164 | 165 | org.codehaus.mojo 166 | buildnumber-maven-plugin 167 | ${buildnumber-maven-plugin.version} 168 | 169 | 170 | org.apache.maven.plugins 171 | maven-jar-plugin 172 | ${maven-jar-plugin.version} 173 | 174 | 175 | org.apache.maven.plugins 176 | maven-install-plugin 177 | ${maven-install-plugin.version} 178 | 179 | 180 | org.apache.maven.plugins 181 | maven-gpg-plugin 182 | ${maven-gpg-plugin.version} 183 | 184 | 185 | org.apache.karaf.tooling 186 | karaf-maven-plugin 187 | ${karaf-maven-plugin.version} 188 | true 189 | 190 | 191 | org.codehaus.mojo 192 | wagon-maven-plugin 193 | ${wagon-maven-plugin.version} 194 | 195 | 196 | 197 | 198 | 199 | 200 | org.apache.maven.plugins 201 | maven-compiler-plugin 202 | 203 | 1.8 204 | 1.8 205 | 206 | 207 | 208 | org.codehaus.mojo 209 | buildnumber-maven-plugin 210 | 211 | true 212 | 213 | 214 | 215 | validate 216 | 217 | create 218 | 219 | 220 | 221 | 222 | 223 | org.apache.felix 224 | maven-bundle-plugin 225 | true 226 | 227 | 228 | bundle-manifest 229 | process-classes 230 | 231 | manifest 232 | 233 | 234 | 235 | 236 | 237 | ${buildNumber} 238 | ${scmBranch} 239 | 240 | 241 | 242 | 243 | org.apache.maven.plugins 244 | maven-install-plugin 245 | 248 | 2.5.2 249 | 250 | 251 | 252 | 253 | 254 | 255 | sonatype-release 256 | 257 | 258 | brooklyn.deployTo 259 | sonatype 260 | 261 | 262 | 263 | 264 | sonatype-nexus-staging 265 | Nexus Release Repository 266 | https://oss.sonatype.org/service/local/staging/deploy/maven2/ 267 | 268 | 269 | sonatype-nexus-snapshots 270 | Sonatype Nexus Snapshots 271 | https://oss.sonatype.org/content/repositories/snapshots/ 272 | 273 | 274 | 275 | 276 | 277 | org.apache.maven.plugins 278 | maven-gpg-plugin 279 | ${maven-gpg-plugin.version} 280 | 281 | 282 | sign-artifacts 283 | verify 284 | 285 | sign 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | -------------------------------------------------------------------------------- /swarm/catalog/catalog.bom: -------------------------------------------------------------------------------- 1 | brooklyn.catalog: 2 | items: 3 | - classpath://swarm/swarm.bom 4 | -------------------------------------------------------------------------------- /swarm/examples/custom-swarm.yaml: -------------------------------------------------------------------------------- 1 | id: custom-swarm 2 | name: "Docker Swarm Cluster" 3 | description: | 4 | A custom Docker Swarm using a Consul cluster for discovery. 5 | 6 | This is intended to illustrate the process of composing a blueprint to 7 | create a Swarm, using pre-defined entities. For this purpose it uses both 8 | entities from the catalog for the Swarm and the CA server, and entities 9 | defined elsewhere for the Consul discovery cluster. 10 | 11 | See for the Consul blueprints. 12 | 13 | location: 14 | jclouds:softlayer: 15 | region: ams01 16 | 17 | services: 18 | - type: org.apache.brooklyn.entity.stock.BasicApplication 19 | id: swarm 20 | name: "swarm" 21 | brooklyn.enrichers: 22 | - type: org.apache.brooklyn.enricher.stock.Propagator 23 | brooklyn.config: 24 | producer: $brooklyn:child("swarm-cluster") 25 | propagating: 26 | - $brooklyn:sensor("swarm.url") 27 | brooklyn.children: 28 | - type: ca-server 29 | id: ca-server 30 | name: "ca-server" 31 | - type: consul-cluster 32 | id: consul-cluster 33 | name: "consul-cluster" 34 | brooklyn.config: 35 | initialSize: 3 36 | brooklyn.enrichers: 37 | - type: org.apache.brooklyn.enricher.stock.Transformer 38 | brooklyn.config: 39 | enricher.triggerSensors: 40 | - $brooklyn:sensor("cluster.nodeip.string") 41 | enricher.targetSensor: $brooklyn:sensor("consul.url") 42 | enricher.targetValue: 43 | $brooklyn:formatString: 44 | - "consul://%s" 45 | - $brooklyn:attributeWhenReady("cluster.nodeip.string") 46 | - type: docker-swarm-cluster 47 | id: swarm-cluster 48 | name: "swarm-cluster" 49 | brooklyn.config: 50 | swarm.manager.size: 3 51 | swarm.initial.size: 3 52 | swarm.max.size: 3 53 | swarm.discovery.url: $brooklyn:entity("consul-cluster").attributeWhenReady("consul.url") 54 | docker.discovery.url: $brooklyn:entity("consul-cluster").attributeWhenReady("consul.url") 55 | latch.launch: $brooklyn:entity("consul-cluster").attributeWhenReady("service.isUp") 56 | latch.customize: $brooklyn:entity("ca-server").attributeWhenReady("service.isUp") 57 | ca.request.root.url: $brooklyn:entity("ca-server").attributeWhenReady("main.uri") 58 | -------------------------------------------------------------------------------- /swarm/examples/swarm-byon.yaml: -------------------------------------------------------------------------------- 1 | id: swarm-byon 2 | name: "Docker Swarm Cluster" 3 | description: | 4 | Deploys to existing VMs (for example, that have been created using 5 | Vagrant) using the given BYON configuration. Ensure that enough VMs 6 | are available for the given maximum size of the Swarm cluster. 7 | 8 | location: 9 | byon: 10 | displayName: swarm-vagrant 11 | loginUser: vagrant 12 | user: vagrant 13 | privateKeyFile: ~/.ssh/swarm.pem 14 | loginUser.privateKeyFile: ~/.ssh/swarm.pem 15 | hosts: 16 | - 192.168.50.0/27 17 | 18 | services: 19 | - type: docker-swarm 20 | id: swarm 21 | name: "swarm" 22 | brooklyn.config: 23 | start.timeout: 30m 24 | swarm.initial.size: 5 25 | swarm.max.size: 10 26 | swarm.manager.size: 3 27 | etcd.initial.size: 3 28 | swarm.port: 4444 29 | swarm.defaultnetwork: "swarm" 30 | swarm.scaling.cpu.limit: 0.99 31 | docker.recovery.stabilizationDelay: 10s 32 | docker.recovery.failOnRecurringFailuresInThisDuration: 5m 33 | -------------------------------------------------------------------------------- /swarm/examples/swarm-minimal.yaml: -------------------------------------------------------------------------------- 1 | id: swarm-minimal 2 | name: "Docker Swarm Cluster" 3 | description: | 4 | Uses the default settings for configuring the Swarm, apart from the initial 5 | size of the cluster of Docker Engine nodes. 6 | 7 | Deploys on AWS using only the default Swarm entity configuration. Requires 8 | a security group to be deined in the AWS region or VPC, which should be 9 | set in the 'templateOptions' of the location, as seen below. The VMs 10 | must also have iptables disabled, which is accomplished by setting the 11 | 'stopIptables' configuration key to 'true' on the Swarm entity. 12 | 13 | location: 14 | jclouds:aws-ec2: 15 | region: eu-central-1 16 | privateKeyFile: "~/.ssh/swarm.pem" 17 | loginUser.privateKeyFile: "~/.ssh/swarm.pem" 18 | keyPair: "swarm" 19 | templateOptions: 20 | securityGroups: 21 | - "swarm" 22 | 23 | services: 24 | - type: docker-swarm 25 | name: "swarm-aws-ec2" 26 | brooklyn.config: 27 | stopIptables: true 28 | swarm.initial.size: 2 29 | swarm.sharedsecuritygroup.create: true 30 | -------------------------------------------------------------------------------- /swarm/examples/swarm-using-external-resources.yaml: -------------------------------------------------------------------------------- 1 | id: swarm-using-external-resources 2 | name: "Docker Swarm Cluster with Load-Balancer" 3 | description: | 4 | This uses an existing discovery mechanism (an Etcd cluster) and must be 5 | provided with URLs to download the TLS certificates and private keys for 6 | each Swarm node. 7 | 8 | Note the same URL will be used for each Swarm node so the certificate 9 | will have to be suitable for use on all of them, typically a wildcard 10 | certifiate. 11 | 12 | Deploys on CentOS 7 VMs. 13 | 14 | location: 15 | jclouds:softlayer: 16 | region: ams01 17 | 18 | services: 19 | - type: docker-swarm-cluster 20 | id: swarm 21 | name: "swarm" 22 | brooklyn.config: 23 | swarm.manager.size: 3 24 | swarm.initial.size: 3 25 | swarm.max.size: 5 26 | swarm.discovery.url: etcd://10.10.10.123:2380/ 27 | docker.discovery.url: etcd://10.10.10.123:2380/ 28 | ca.cert.url: http://10.10.10.101:8080/default/ca.pem 29 | node.cert.url: http://10.10.10.101:8080/default/cert.pem 30 | private.key.url: http://10.10.10.101:8080/default/key.pem 31 | -------------------------------------------------------------------------------- /swarm/examples/swarm.yaml: -------------------------------------------------------------------------------- 1 | id: swarm 2 | name: "Docker Swarm Cluster" 3 | description: | 4 | Includes built-in etcd discovery cluster, TLS protected endpoints, 5 | HAProxy load balancer for Swarm managers and a CA server to create 6 | certificates for the Swarm and etcd nodes and the load balancer. 7 | 8 | Deploys on CentOS 7 VMs in SoftLayer, on a single VLAN segment. 9 | 10 | location: 11 | jclouds:softlayer: 12 | region: ams01 13 | identity: xxxxxxxx 14 | credential: XXXXXXXX 15 | privateKeyFile: ~/.ssh/softlayer.pem 16 | customizers: 17 | - $brooklyn:object: 18 | type: org.apache.brooklyn.location.jclouds.softlayer.SoftLayerSameVlanLocationCustomizer 19 | brooklyn.config: 20 | softlayer.vlan.scopeUid: "swarm" 21 | 22 | services: 23 | - type: docker-swarm 24 | id: swarm 25 | name: "swarm" 26 | brooklyn.config: 27 | start.timeout: 30m 28 | swarm.initial.size: 8 29 | swarm.max.size: 16 30 | swarm.manager.size: 3 31 | etcd.initial.size: 3 32 | swarm.port: 4000 33 | swarm.defaultnetwork: "swarm" 34 | swarm.scaling.cpu.limit: 0.80 35 | swarm.strategy: "binpack" 36 | swarm.overcommit: 0.50 37 | docker.recovery.stabilizationDelay: 10s 38 | docker.recovery.failOnRecurringFailuresInThisDuration: 5m 39 | swarm.minRam: 32g 40 | swarm.minCores: 4 41 | provisioning.properties: 42 | minRam: 2g 43 | minCores: 1 44 | -------------------------------------------------------------------------------- /swarm/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | 8 | io.brooklyn.clocker 9 | clocker-parent 10 | 2.1.0-SNAPSHOT 11 | 12 | 13 | Clocker :: Swarm 14 | clocker-swarm 15 | bundle 16 | 17 | 18 | 19 | 20 | catalog 21 | false 22 | 23 | 24 | resources 25 | false 26 | 27 | 28 | tests 29 | false 30 | tests 31 | 32 | 33 | 34 | 35 | 36 | org.codehaus.mojo 37 | build-helper-maven-plugin 38 | 39 | 40 | attach-artifact 41 | package 42 | 43 | attach-artifact 44 | 45 | 46 | 47 | 48 | ${project.basedir}/catalog/swarm/swarm.bom 49 | bom 50 | swarm 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /swarm/resources/icons/swarm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brooklyncentral/clocker/e1ff91d4959d2238efcf78569d600f95273730d4/swarm/resources/icons/swarm.png -------------------------------------------------------------------------------- /swarm/tests/swarm/swarm.tests.bom: -------------------------------------------------------------------------------- 1 | brooklyn.catalog: 2 | version: "2.1.0-SNAPSHOT" # CLOCKER_VERSION 3 | iconUrl: https://raw.githubusercontent.com/docker-library/docs/471fa6e4cb58062ccbf91afc111980f9c7004981/swarm/logo.png 4 | dependsOn: 5 | - tests/common.tests.bom 6 | - tests/docker.tests.bom 7 | license_code: APACHE-2.0 8 | 9 | items: 10 | - id: test-docker-run-pulls 11 | item: 12 | type: test-case 13 | description: | 14 | Test that Docker Swarm cluster can pull containers from Docker Hub 15 | automatically 16 | brooklyn.children: 17 | - type: ssh-test 18 | command: | 19 | set -e 20 | docker rmi --force busybox || true 21 | ! docker images | grep busybox 22 | docker run --rm busybox echo "Hello from busybox-image" | grep busybox-image 23 | docker images | grep busybox 24 | assertStatus: 25 | equals: 0 26 | assertOut: 27 | contains: "busybox-image" 28 | 29 | - id: test-swarm-networking 30 | item: 31 | type: test-case 32 | description: | 33 | Test Swarm networking between containers on different hosts, using 34 | shared Docker overlay network 35 | brooklyn.parameters: 36 | - network.name 37 | brooklyn.children: 38 | - type: ssh-test 39 | name: "TEST-06-1 Test network exists" 40 | brooklyn.config: 41 | shell.env: 42 | NETWORK_NAME: $brooklyn:config("network.name") 43 | command: | 44 | echo "[TEST] Checking ID of network ${NETWORK_NAME}" 45 | docker network inspect --format "{{.ID}}" ${NETWORK_NAME} 46 | assertStatus: 47 | equals: 0 48 | assertErr: 49 | isEmpty: true 50 | - type: ssh-test 51 | name: "TEST-06-2 Test network properties" 52 | brooklyn.config: 53 | shell.env: 54 | NETWORK_NAME: $brooklyn:config("network.name") 55 | command: | 56 | echo "[TEST] Create container on ${NETWORK_NAME} network" 57 | docker run -di --name workload_A --net ${NETWORK_NAME} brooklyncentral/centos:7 /bin/bash 58 | CONTAINER_NETWORK_ID=$(docker inspect --format "{{.NetworkSettings.Networks.${NETWORK_NAME}.NetworkID}}" workload_A) 59 | NETWORK_ID=$(docker network inspect --format "{{.ID}}" ${NETWORK_NAME}) 60 | docker rm -f workload_A 61 | [[ "${CONTAINER_NETWORK_ID}" == "${NETWORK_ID}" ]] 62 | assertStatus: 63 | equals: 0 64 | assertErr: 65 | isEmpty: true 66 | - type: ssh-test 67 | name: "TEST-06-3 Test same network connectivity" 68 | brooklyn.config: 69 | shell.env: 70 | NETWORK_NAME: $brooklyn:config("network.name") 71 | command: | 72 | echo "[TEST] Creating two containers on ${NETWORK_NAME} network" 73 | docker run -di --name workload_B --net ${NETWORK_NAME} brooklyncentral/centos:7 /bin/bash 74 | docker run -di --name workload_C --net ${NETWORK_NAME} -e affinity:container!=workload_B brooklyncentral/centos:7 /bin/bash 75 | docker exec workload_B ping -W 10 -c 4 workload_C.${NETWORK_NAME} 76 | docker exec workload_C ping -W 10 -c 4 workload_B.${NETWORK_NAME} 77 | docker rm -f workload_B 78 | docker rm -f workload_C 79 | assertOut: 80 | - contains: 81 | $brooklyn:formatString: 82 | - "--- workload_B.%s ping statistics ---\n4 packets transmitted, 4 received" 83 | - $brooklyn:config("network.name") 84 | - contains: 85 | $brooklyn:formatString: 86 | - "--- workload_C.%s ping statistics ---\n4 packets transmitted, 4 received" 87 | - $brooklyn:config("network.name") 88 | assertErr: 89 | isEmpty: true 90 | - type: ssh-test 91 | name: "TEST-06-4 Test different network connectivity failure" 92 | brooklyn.config: 93 | shell.env: 94 | NETWORK_NAME: $brooklyn:config("network.name") 95 | command: | 96 | echo "[TEST] Creating two containers on different networks" 97 | docker run -di --name workload_D --net ${NETWORK_NAME} brooklyncentral/centos:7 /bin/bash 98 | docker run -di --name workload_E --net bridge -e affinity:container!=workload_D brooklyncentral/centos:7 /bin/bash 99 | WORKLOAD_D_IP=$(docker inspect --format "{{.NetworkSettings.Networks.${NETWORK_NAME}.IPAddress}}" workload_D) 100 | docker exec workload_E ping -W 10 -c 4 workload_D.${NETWORK_NAME} || true 101 | docker exec workload_E ping -W 10 -c 4 ${WORKLOAD_D_IP} || true 102 | docker rm -f workload_D 103 | docker rm -f workload_E 104 | assertErr: 105 | contains: 106 | $brooklyn:formatString: 107 | - "ping: workload_D.%s: Name or service not known" 108 | - $brooklyn:config("network.name") 109 | assertOut: 110 | contains: "ping statistics ---\n4 packets transmitted, 0 received" 111 | 112 | - id: test-swarm-scale-up 113 | item: 114 | type: test-case 115 | description: | 116 | Test Swarm can be scaled up 117 | brooklyn.children: 118 | - type: sensor-test 119 | name: "TEST-07-1 Initial Size of cluster is 2" 120 | targetId: docker-swarm-nodes 121 | sensor: group.members.count 122 | assert: 123 | equals: 2 124 | - type: ssh-test 125 | name: "TEST-07-2 Create load on server" 126 | brooklyn.config: 127 | command: | 128 | echo "[TEST] Creating load" 129 | docker run -di --name TEST_7_2_LOAD_1 -e affinity:container!=TEST_7_2_LOAD_2 brooklyncentral/centos:7 /bin/bash 130 | docker run -di --name TEST_7_2_LOAD_2 -e affinity:container!=TEST_7_2_LOAD_1 brooklyncentral/centos:7 /bin/bash 131 | docker exec -d TEST_7_2_LOAD_1 dd if=/dev/zero of=/dev/null 132 | docker exec -d TEST_7_2_LOAD_2 dd if=/dev/zero of=/dev/null 133 | - type: sensor-test 134 | name: "TEST-07-3 Final Size of cluster is 3" 135 | targetId: docker-swarm-nodes 136 | timeout: 20m 137 | sensor: group.members.count 138 | assert: 139 | equals: 3 140 | - type: ssh-test 141 | name: "TEST-07-4 Tear down load" 142 | brooklyn.config: 143 | command: | 144 | echo "[TEST] Removing load" 145 | docker rm -f TEST_7_2_LOAD_1 146 | docker rm -f TEST_7_2_LOAD_2 147 | 148 | - id: test-swarm-etcd-tls 149 | item: 150 | type: ssh-test 151 | name: "TEST-08-1 Swarm Etcd uses TLS" 152 | brooklyn.config: 153 | shell.env: 154 | ETCD_ENDPOINT_LIST: $brooklyn:entity("etcd-cluster").attributeWhenReady("etcd.endpoints") 155 | CERT_PATH: 156 | $brooklyn:formatString: 157 | - "%s/.certs" 158 | - $brooklyn:entity("swarm-client").attributeWhenReady("install.dir") 159 | command: | 160 | set -e 161 | for endpoint in ${ETCD_ENDPOINT_LIST//,/ } ; do 162 | ! curl https://${endpoint}/version --fail 163 | ! curl http://${endpoint}/version --fail 164 | curl --cacert "${CERT_PATH}/ca.pem" \ 165 | --cert "${CERT_PATH}/cert.pem" \ 166 | --key "${CERT_PATH}/key.pem" \ 167 | --fail \ 168 | https://${endpoint}/version 169 | done 170 | 171 | - id: test-swarm-restart 172 | item: 173 | type: test-case 174 | description: | 175 | Restart Swarm member (node/manager) 176 | brooklyn.children: 177 | - type: ssh-cmd-restart 178 | - type: assert-failed 179 | - type: assert-up 180 | 181 | - id: test-swarm-node-restart 182 | item: 183 | type: test-case 184 | brooklyn.children: 185 | - type: loop-test-case 186 | name: "TEST-09-1 Restart Swarm node" 187 | brooklyn.config: 188 | targetId: docker-swarm-nodes 189 | test.spec: 190 | $brooklyn:entitySpec: 191 | type: test-swarm-restart 192 | - type: loop-test-case 193 | name: "TEST-09-2 Restart Swarm manager" 194 | brooklyn.config: 195 | targetId: docker-swarm-managers 196 | test.spec: 197 | $brooklyn:entitySpec: 198 | type: test-swarm-restart 199 | - type: ssh-test 200 | name: "TEST-09-3 Assert Healthy Swarm" 201 | brooklyn.config: 202 | command: 203 | $brooklyn:formatString: 204 | - | 205 | NODES=$(docker info | grep "Nodes:") 206 | echo "${NODES}" 207 | [ "${NODES}" = "Nodes: %d" ] 208 | - $brooklyn:entity("docker-swarm-nodes").attributeWhenReady("group.members.count") 209 | 210 | - id: swarm-node-replacement-test 211 | name: Swarm Node Replace 212 | description: | 213 | Tests restarting and replacing failed swarm nodes 214 | itemType: entity 215 | item: 216 | type: test-case 217 | brooklyn.children: 218 | - type: assert-up 219 | name: TEST-10 Wait for Swarm to deploy 220 | targetId: swarm-cluster 221 | - type: cluster 222 | name: TEST-10 Swarm Node Lazy Holder 223 | id: node-to-fail-lazy-holder 224 | brooklyn.config: 225 | dynamiccluster.memberspec: 226 | $brooklyn:entitySpec: 227 | # At the time an entity is created out of the spec the swarm-node should already exist 228 | type: org.apache.brooklyn.entity.stock.BasicEntity 229 | id: node-to-fail-holder 230 | name: Swarm Node Holder 231 | brooklyn.initializers: 232 | - type: org.apache.brooklyn.core.sensor.StaticSensor 233 | brooklyn.config: 234 | name: node-to-fail 235 | # Pick one node to fail and cache it 236 | static.value: $brooklyn:entity("swarm-node") 237 | targetType: org.apache.brooklyn.api.entity.Entity 238 | - type: org.apache.brooklyn.core.sensor.StaticSensor 239 | brooklyn.config: 240 | name: initial-cluster-size 241 | static.value: $brooklyn:entity("docker-swarm-nodes").attributeWhenReady("group.members.count") 242 | targetType: Integer 243 | - type: org.apache.brooklyn.core.sensor.StaticSensor 244 | brooklyn.config: 245 | name: service.isUp 246 | static.value: true 247 | targetType: Boolean 248 | 249 | - type: test-case 250 | name: TEST-10 Asserts 251 | id: swarm-node-replacement-test 252 | brooklyn.config: 253 | target: $brooklyn:entity("node-to-fail-holder").attributeWhenReady("node-to-fail") 254 | brooklyn.children: 255 | - type: assert-up 256 | name: TEST-10-01. Wait for Swarm Node Holder 257 | target: $brooklyn:entity("node-to-fail-lazy-holder") 258 | - type: assert-up 259 | name: TEST-10-02. Wait for Swarm Node 260 | - type: ssh-test 261 | name: TEST-10-03. Fail Swarm Node 262 | brooklyn.config: 263 | command: | 264 | SWARM_ID=$(docker ps --filter name=swarm --format '{{ .ID }}' --no-trunc) 265 | if [ -z "${SWARM_ID}" ]; then 266 | echo "Swarm container not running" >&2 267 | exit 1 268 | fi 269 | docker rm -f ${SWARM_ID} 270 | - type: assert-down 271 | name: TEST-10-04. Check Failed 272 | - type: assert-up 273 | name: TEST-10-05. Check Recovered 274 | - type: ssh-test 275 | name: TEST-10-06. Re-Fail Swarm Node 276 | brooklyn.config: 277 | command: | 278 | # Wait for stabilization delay - 10s 279 | sleep 15 280 | 281 | SWARM_ID=$(docker ps --filter name=swarm --format '{{ .ID }}' --no-trunc) 282 | if [ -z "${SWARM_ID}" ]; then 283 | echo "Swarm container not running" >&2 284 | exit 1 285 | fi 286 | docker rm -f ${SWARM_ID} 287 | - type: assert-down 288 | name: TEST-10-07. Check Failed 289 | - type: sensor-test 290 | name: TEST-10-08. Check spinning up replacement 291 | brooklyn.config: 292 | target: $brooklyn:entity("docker-swarm-nodes") 293 | sensor: group.members.count 294 | timeout: $brooklyn:config("timeout.initialStartup") 295 | assert: 296 | - notEqual: $brooklyn:entity("node-to-fail-holder").attributeWhenReady("initial-cluster-size") 297 | - type: sensor-test 298 | name: TEST-10-09. Check failed node removed 299 | brooklyn.config: 300 | target: $brooklyn:entity("docker-swarm-nodes") 301 | sensor: group.members.count 302 | timeout: $brooklyn:config("timeout.initialStartup") 303 | assert: 304 | - equals: $brooklyn:entity("node-to-fail-holder").attributeWhenReady("initial-cluster-size") 305 | - type: sensor-test 306 | name: TEST-10-10. Check failed node unmanaged 307 | brooklyn.config: 308 | sensor: service.state 309 | assert: 310 | - matches: stopped 311 | - type: assert-running 312 | name: TEST-10-11. Check cluster healthy 313 | brooklyn.config: 314 | target: $brooklyn:entity("docker-swarm-nodes") 315 | 316 | # swarm manager failover tests 317 | - id: test-swarm-manager-failover 318 | item: 319 | type: test-case 320 | description: | 321 | Test Swarm manager failover behaviour 322 | brooklyn.children: 323 | - type: sensor-test 324 | name: "TEST-11-1 Size of manager cluster is 3" 325 | targetId: docker-swarm-managers 326 | sensor: group.members.count 327 | assert: 328 | equals: 3 329 | - type: test-stop-machine 330 | name: "TEST-11-2 Kill one node" 331 | target: $brooklyn:entity("docker-swarm-managers").attributeWhenReady("cluster.first.entity") 332 | - type: ssh-test 333 | name: "TEST-11-3 Manager endpoints active now 2" 334 | targetId: swarm-client 335 | brooklyn.config: 336 | shell.env: 337 | SWARM_ENDPOINTS: $brooklyn:entity("docker-swarm-managers").attributeWhenReady("swarm.endpoints") 338 | command: | 339 | echo ${SWARM_ENDPOINTS} | tr ',' ' ' | wc -w 340 | assertStatus: 341 | equals: 0 342 | assertOut: 343 | contains: "2" 344 | - type: ssh-test 345 | name: "TEST-11-4 Can still connect" 346 | timeout: 20m 347 | targetId: swarm-client 348 | brooklyn.config: 349 | command: | 350 | docker run -i hello-world 351 | assertStatus: 352 | equals: 0 353 | assertOut: 354 | contains: "Hello from Docker!" 355 | - type: ssh-test 356 | name: "TEST-11-5 Check load balancer" 357 | timeout: 20m 358 | targetId: swarm-client 359 | brooklyn.config: 360 | shell.env: 361 | HAPROXY_URL: 362 | $brooklyn:entity("swarm-manager-load-balancer").attributeWhenReady("swarm.url") 363 | CERT_PATH: 364 | $brooklyn:formatString: 365 | - "%s/.certs" 366 | - $brooklyn:entity("swarm-client").attributeWhenReady("install.dir") 367 | command: | 368 | SWARM_URL=${HAPROXY_URL/tcp/https} 369 | curl --cacert "${CERT_PATH}/ca.pem" \ 370 | --cert "${CERT_PATH}/cert.pem" \ 371 | --key "${CERT_PATH}/key.pem" \ 372 | ${SWARM_URL}/_ping 373 | assertStatus: 374 | equals: 0 375 | assertOut: 376 | equals: "OK" 377 | 378 | - id: docker-swarm-tests 379 | name: Docker Swarm Tests 380 | description: | 381 | Tests on Docker Swarm over TLS 382 | itemType: entity 383 | item: 384 | type: test-case 385 | name: "docker-swarm-tests" 386 | 387 | brooklyn.config: 388 | timeout: 1h 389 | timeout.initialStartup: 1h 390 | timeout.runtimeAssertion: 1h 391 | swarm.initial.size: 2 392 | swarm.manager.size: 3 393 | etcd.initial.size: 2 394 | swarm.max.size: 5 395 | swarm.scaling.cpu.limit: 0.95 396 | swarm.defaultnetwork: "brooklyn" 397 | swarm.port: 4000 398 | docker.recovery.stabilizationDelay: 10s 399 | docker.recovery.failOnRecurringFailuresInThisDuration: 5m 400 | 401 | brooklyn.children: 402 | - type: docker-swarm 403 | id: swarm 404 | name: "swarm" 405 | description: | 406 | The swarm to test 407 | 408 | - type: test-docker-client-with-tls 409 | id: swarm-client 410 | name: "swarm-client" 411 | description: | 412 | A client for talking to the swarm 413 | brooklyn.config: 414 | latch.customize: $brooklyn:entity("swarm").attributeWhenReady("service.isUp") 415 | client.address: $brooklyn:attributeWhenReady("host.address") 416 | ca.url: $brooklyn:entity("ca-server").attributeWhenReady("main.uri") 417 | docker.url: $brooklyn:entity("swarm").attributeWhenReady("swarm.url") 418 | 419 | - type: test-case 420 | name: "swarm-test-suite" 421 | brooklyn.children: 422 | - type: test-case 423 | name: "GROUP-1 Test Swarm entity" 424 | brooklyn.config: 425 | targetId: swarm 426 | brooklyn.children: 427 | - type: assert-up 428 | name: "TEST-01 Assert up" 429 | - type: assert-running 430 | name: "TEST-02 Assert running" 431 | - type: test-case 432 | name: "GROUP-2 Test Swarm client" 433 | brooklyn.config: 434 | targetId: swarm-client 435 | latch.start: $brooklyn:entity("swarm-client").attributeWhenReady("service.isUp") 436 | brooklyn.children: 437 | - type: test-swarm-scale-up 438 | name: "TEST-03 Test Swarm scale up" 439 | - type: swarm-node-replacement-test 440 | name: "TEST-04 Test Swarm node replace" 441 | - type: test-swarm-manager-failover 442 | name: "TEST-05 Test Swarm failover" 443 | - type: test-connect-fails-without-tls 444 | name: "TEST-06 Test connect fails without TLS" 445 | - type: docker-engine-test 446 | name: "TEST-07 Test Swarm over TLS" 447 | description: | 448 | Runs the docker tests against the swarm 449 | - type: test-docker-run-pulls 450 | name: "TEST-08 Test docker run pulls" 451 | - type: test-swarm-networking 452 | name: "TEST-09 Test Swarm networking" 453 | brooklyn.config: 454 | network.name: $brooklyn:component("swarm").config("swarm.defaultnetwork") 455 | - type: test-swarm-etcd-tls 456 | name: "TEST-10 Test Swarm etcd TLS" 457 | brooklyn.config: 458 | ca.url: $brooklyn:entity("ca-server").attributeWhenReady("main.uri") 459 | 460 | -------------------------------------------------------------------------------- /swarm/tests/swarm/tests_with_shared_group.bom: -------------------------------------------------------------------------------- 1 | brooklyn.catalog: 2 | version: "2.1.0-SNAPSHOT" # CLOCKER_VERSION 3 | iconUrl: https://raw.githubusercontent.com/docker-library/docs/471fa6e4cb58062ccbf91afc111980f9c7004981/swarm/logo.png 4 | dependsOn: 5 | - tests/docker.tests.bom 6 | - tests/swarm.tests.bom 7 | license_code: APACHE-2.0 8 | 9 | items: 10 | - id: docker-and-swarm-engine-tests 11 | name: "Docker Engine and Swarm Tests" 12 | description: | 13 | Tests on Docker Engine with and without TLS, and on Swarm (with TLS) 14 | itemType: template 15 | item: 16 | brooklyn.config: 17 | timeout: 90m 18 | timeout.initialStartup: 1h 19 | timeout.runtimeAssertion: 1h 20 | swarm.sharedsecuritygroup.create: true 21 | swarm.minRam: 2000 22 | swarm.minCores: 1 23 | 24 | services: 25 | - type: docker-swarm-tests 26 | -------------------------------------------------------------------------------- /swarm/tests/swarm/tests_without_shared_group.bom: -------------------------------------------------------------------------------- 1 | brooklyn.catalog: 2 | version: "2.1.0-SNAPSHOT" # CLOCKER_VERSION 3 | iconUrl: https://raw.githubusercontent.com/docker-library/docs/471fa6e4cb58062ccbf91afc111980f9c7004981/swarm/logo.png 4 | dependsOn: 5 | - tests/docker.tests.bom 6 | - tests/swarm.tests.bom 7 | license_code: APACHE-2.0 8 | 9 | items: 10 | - id: docker-and-swarm-engine-tests 11 | name: "Docker Engine and Swarm Tests" 12 | description: | 13 | Tests on Docker Engine with and without TLS, and on Swarm (with TLS) 14 | itemType: template 15 | item: 16 | brooklyn.config: 17 | timeout: 90m 18 | timeout.initialStartup: 1h 19 | timeout.runtimeAssertion: 1h 20 | swarm.sharedsecuritygroup.create: false 21 | swarm.minRam: 2000 22 | swarm.minCores: 1 23 | 24 | services: 25 | - type: docker-swarm-tests 26 | --------------------------------------------------------------------------------