├── .gitignore ├── CONTRIBUTING.md ├── LICENSE ├── MAINTAINERS ├── README.md ├── assets ├── jq │ ├── Darwin │ │ └── jq │ └── Linux │ │ └── jq ├── services │ ├── coreos │ │ ├── alias.sh │ │ ├── docker.service │ │ ├── launch_units.sh │ │ ├── list_units.sh │ │ └── user-data.yaml │ ├── dj.service │ ├── dj.timer │ ├── dj │ │ ├── dj.sh │ │ ├── load-up │ │ ├── reset │ │ ├── start │ │ └── status │ ├── elasticsearch-discovery@.service │ ├── elasticsearch-dv@.service │ ├── elasticsearch-proxy.service │ ├── elasticsearch@.service │ ├── gitlab-postgres.service │ ├── gitlab-redis.service │ ├── gitlab.service │ ├── httpbin.service │ ├── jenkins.service │ ├── kibana.service │ ├── logspout.service │ ├── logstash.service │ ├── meta │ │ ├── elk.service │ │ └── rds.service │ ├── myapp.service │ ├── nginx.service │ ├── rds-logger.service │ ├── registry.service │ └── skydns │ │ ├── skydns.install.service │ │ └── skydns.service ├── stax │ ├── fleetlogs │ ├── servicerunner │ ├── slogans │ └── words └── vpc │ ├── nat_monitor.sh │ └── user-data-nat.sh ├── config ├── simple.json.example ├── stax.config ├── vpc-default.json.example ├── vpc-mon.json └── vpc.json ├── docs ├── aws-ha-nat.png └── aws-stax.png ├── stax └── template ├── simple.json ├── vpc-default.json └── vpc-default.services.example /.gitignore: -------------------------------------------------------------------------------- 1 | config.json 2 | config.json.tmp 3 | *.swp 4 | run 5 | config/rds.json 6 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Contribution Guidelines 2 | 3 | See https://github.com/MonsantoCo/standards/blob/master/CONTRIBUTING.md 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 philcryer 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MAINTAINERS: -------------------------------------------------------------------------------- 1 | philcryer (Phil Cryer) BDFL 2 | ddgenome (David Dooling) 3 | cgswong (Stuart Wong) 4 | tj-corrigan (T.J. Corrigan) 5 | bkrodgers (Brian Rodgers) 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Stax 2 | 3 | ## About 4 | 5 | Stax creates and manages CloudFormation stacks (aka stax) in AWS ([Amazon Web Services](aws.amazon.com)). Several CloudFormation templates are provided with stax, take a look at them in the `templates` directory to modify and create your own. 6 | 7 | As an illustration, with the proper configuration and templates, `stax` can create a set of entities in AWS like those shown in the diagram below. 8 | 9 | ![AWS Stax Diagram](docs/aws-stax.png) 10 | 11 | ## Requirements 12 | 13 | Stax requires Linux (tested on Debian GNU/Linux 7/8 and Ubuntu 14.04/15.04) and Apple OS X (tested on 10.09/10.10). You'll also need an account with [Amazon Web Services](aws.amazon.com). 14 | 15 | ### Homebrew (Mac OS X only) 16 | 17 | Install [Homebrew](http://brew.sh/) for OS X, which '...installs the stuff you need that Apple didn’t'. Basically it's a \*nix package manager like we have in Linux. It's easy to install via their setup script: 18 | 19 | ``` 20 | $ ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" 21 | ``` 22 | 23 | Visit their site to learn how to install it manually if you don't trust that line. 24 | 25 | ### curl 26 | 27 | Install [curl](http://curl.haxx.se/) if you don't already have it installed (OS X has it by default, and most Linux distros have it by default) on your client. 28 | 29 | ```bash 30 | $ apt-get install curl # Debian GNU/Linux, Ubuntu 31 | $ yum install curl # Red Hat Enterprise Linux (RHEL), CentOS, Amazon Linux 32 | ``` 33 | 34 | ### awscli 35 | 36 | Install [aws-cli](https://github.com/aws/aws-cli) (Universal Command Line Interface for Amazon Web Services) on your client. 37 | 38 | NOTE: the version in the Debian repo is out of date, but we'll need the latest version, to get that we'll first need to install the Python package manager `pip`. These [install docs](http://www.cyberciti.biz/faq/debian-ubuntu-centos-rhel-linux-install-pipclient/] will help you get `pip` installed, once complete, go to the next step to install `awscli`. 39 | 40 | ```bash 41 | $ pip install awscli # Debian GNU/Linux, Ubuntu 42 | $ brew install awscli # Apple OS X ([via Homebrew](http://brew.sh/)) 43 | $ yum install awscli # Red Hat Enterprise Linux (RHEL), CentOS, Amazon Linux 44 | ``` 45 | 46 | After installing the AWS CLI, you will need to configure it with your AWS access credentials, specifically an AWS API key and secret. You can generate these credentials from your [IAM user page](https://console.aws.amazon.com/iam/home#users) on the AWS Console. Choose your username, scroll down to Security Credentials > Access Keys (Acess Key ID and Secret Access Key), and click Create Keys if you haven't created them yet. Running stax requires many permissions in AWS, so be sure the IAM user you are running stax as has sufficient permissions, and in an admin group (called 'wheel' by default). If you already have this group, and your user is in that group, continue to 'aws configure' - otherwise follow the next steps to setup the 'wheel' group. 47 | 48 | NOTE: if this is a new install (the AWS environment hasn't been used before) you'll need to create the wheel group, and add your user to that group for the user to have permissions to build on AWS. 49 | 50 | * In the AWS Console, under the Services tab, choose IAM > Groups > Create New Group > Name it 'wheel' > Next Step > Create Group 51 | * Now go into the group to define the 'Inline Policies'. Again, in the AWS Console, under the Services tab, choose IAM > Groups > Choose the new 'wheel' group > Scroll down to 'Inline Policies' and click on that > In that dropdown click 'click here' on the line that says "To create one, click here." - Now choose Custom Policy > Select > In 'Policy Name' call it 'wheel' then under Policy Document, enter the following: 52 | 53 | ``` 54 | { 55 | "Version": "2012-10-17", 56 | "Statement": [ 57 | { 58 | "Effect": "Allow", 59 | "Action": "*", 60 | "Resource": "*" 61 | } 62 | ] 63 | } 64 | ``` 65 | 66 | Click 'Apply Policy' - Now apply your user to that group, click Users > Click your new user > Click Add User to Groups > select the 'wheel' group > Click Add to Groups 67 | 68 | Run the AWS configure utility to enter your keys and regions. 69 | 70 | ```bash 71 | $ aws configure 72 | ``` 73 | 74 | You will be prompted to enter your access key and secret access key, copy this from the AWS Console you opened above. Next you will be prompted to enter your AWS region, currently we have stax setup to use `us-east-1`. Finally you will be prompted for the default output format, enter `json`. The AWS CLI will store your configuration in `~/.aws/credentials`. If you need to change your configuration, you can either run `aws configure` again or edit this file directly. 75 | 76 | ## Templates 77 | 78 | Two templates are provided with stax to get you started, below are brief descriptions. 79 | 80 | ### simple.json 81 | 82 | The template `template/simple.json` stands up a simple AWS environment. Since it is simple to comprehend and spins up quickly, this template is intended as a sandbox to stand up and test new CloudFormation entities. For example, the implementation of CloudWatch Alarms was first tested using this template. The `config/simple.json` has minimal parameters and the default values are acceptable for all but the project/team/cost parameters. 83 | 84 | * `Project` __REQUIRED__: Name for the project with which this application ecosystem is associated 85 | * `Product` __REQUIRED__: Name for the end-user facing product service by this application ecosystem 86 | * `Group` __REQUIRED__: Name of the group that created this stack 87 | * `Team` __REQUIRED__: Name of the team that created this stack 88 | * `Environment` __REQUIRED__: Type of environment, e. g., production, test, branch name 89 | * `KeepAlive` __REQUIRED__: Tag to avoid the reaper, default is false 90 | * `InstanceType`: AWS EC2 instance type for NAT instances, default is t2.micro 91 | * `Owner` __REQUIRED__: Tag for owner of the stack, if set to `@OWNER@` stax will substitute the current user id 92 | * `KeyName` __REQUIRED__: AWS EC2 Key Pair to use when launching instances, if set to `@KEY_NAME@` stax will use a key pair it creates 93 | * `SSHLocation`: CIDR IP range to allow SSH access to bastion host, if set to `@SSH_FROM@` stax will replace it with the CIDR IP of the host running stax, default is 0.0.0.0/0 94 | 95 | ### vpc-default.json 96 | 97 | The template `template/vpc-default.json` creates an environment useful for deploying microservices as docker containers in AWS. The following entities are created: 98 | 99 | * __1 VPC__ (vpc-) Isolated Virtual Private Cloud network. 100 | * __1 EC2 instance__ Bastion Host (bastion-) Provides SSH access to 101 | the VPC. 102 | * __2 EC2 instances__ NAT boxes (nat1-, nat2-) Proxy network 103 | connections to and from the internal CoreOS hosts to the public 104 | internet. These instances log all traffic and monitor each other to 105 | ensure high availability. 106 | * __1 Elastic Load Balancer__ Gateway ELB (gateway-elb-) Load balancer 107 | for traffic to the Gateway Cluster 108 | * __1 Auto Scaling Group__ Gateway Cluster (gateway-) An auto scaling 109 | group with a default size of 2 of instances running CoreOS. 110 | The instances serve as the gateway/router to the internal service 111 | instances. 112 | * __3 EC2 Instances__ Service Leaders (service-leader-N-) Three 113 | instances with CloudWatch Alarms for auto-recovery should they fail 114 | that serve as the cluster leaders for etcd and consul. 115 | * __1 Auto Scaling Group__ Service Cluster (service-) An auto scaling 116 | group with a default size of zero on which, along with the service 117 | leaders, all services deployed to the VPC will run. 118 | 119 | The text in parentheses is the first part of the name given to the entity, with the latter part being the CloudFormation stack name. 120 | 121 | This template takes the following parameters, see `config/vpc-default.json.example` for the format. 122 | 123 | * `Project` __REQUIRED__: Name for the project with which this 124 | application ecosystem is associated 125 | * `Product` __REQUIRED__: Name for the end-user facing product 126 | service by this application ecosystem 127 | * `Group` __REQUIRED__: Name of the group that created this stack 128 | * `Team` __REQUIRED__: Name of the team that created this stack 129 | * `Environment` __REQUIRED__: Type of environment, e. g., production, test, branch name 130 | * `KeepAlive` __REQUIRED__: Tag to avoid the reaper, default is false 131 | * `Owner` __REQUIRED__: Tag for owner of the stack, if set to `@OWNER@` stax will 132 | substitute the current user id 133 | * `KeyName` __REQUIRED__: AWS EC2 Key Pair to use when launching instances, if set 134 | to `@KEY_NAME@` stax will use a key pair it creates 135 | * `ServiceELBSubdomainName`: Route 53 subdomain, leave blank to not 136 | create one 137 | * `ServiceELBBaseDomainName`: Route 53 base domain name, leave blank 138 | to not create one 139 | * `ServiceELBSSLCertName`: IAM name of SSL existing certificate, leave 140 | blank to not use SSL 141 | * `DockerRegistryUser`: Private Docker registry user name 142 | * `DockerRegistryPass`: Private Docker registry password 143 | * `DockerRegistryEmail`: Private Docker registry email address 144 | * `DockerRegistryUrl`: Private Docker registry URL, defaults to https://index.docker.io/v1/ 145 | * `ServiceClusterSize`: Target size of Service Cluster auto scaling 146 | group, default is 0 147 | * `GatewayClusterSize`: Target size of Gateway Cluster auto scaling 148 | group, default is 2 149 | * `BastionInstanceType`: AWS EC2 instance type for bastion host, 150 | default is t2.micro 151 | * `NATInstanceType`: AWS EC2 instance type for NAT instances, default 152 | is t2.micro 153 | * `DockerInstanceType`: AWS EC2 instance type for CoreOS/Docker hosts, 154 | default is m3.medium 155 | * `CoreOSChannelAMI`: CoreOS channel (stable, beta, alpha) to use for 156 | CoreOS instances, default is CoreOSStableAMI 157 | * `AdvertisedIPAddress`: Which instance IP address to use for 158 | clustering, private or public, default is private, use public to 159 | cluster across unpaired VPCs 160 | * `AutoScaleCooldown`: Auto scaling cooldown period, in seconds, after 161 | an auto scaling event, default is 300 162 | * `AllowSSHFrom`: CIDR IP range to allow SSH access to bastion host, 163 | if set to `@SSH_FROM@` stax will replace it with the CIDR IP of the 164 | host running stax 165 | * `AllowHTTPFrom`: CIDR IP range from which to allow HTTP access to 166 | the Gateway ELB, if set to `@HTTP_FROM@` stax will replace it with 167 | the CIDR IP of the host running stax 168 | 169 | 170 | ## Usage 171 | 172 | * To get started, first clone stax 173 | 174 | ```bash 175 | $ git clone https://github.com/MonsantoCo/stax 176 | $ cd stax 177 | ``` 178 | 179 | * Copy the example default config file 180 | 181 | ```bash 182 | $ cp config/vpc-default.json.example config/vpc-default.json 183 | ``` 184 | 185 | * Configure the config file replacing all instances of ``. 186 | 187 | ```bash 188 | $ vi config/vpc-default.json 189 | ``` 190 | 191 | * Run stax 192 | 193 | ```bash 194 | $ ./stax 195 | Usage: stax [OPTIONS] COMMAND [COMMAND_ARGS] 196 | 197 | Options: 198 | -c,--config=CONFIG Use file CONFIG rather than config/vpc-default.json 199 | -d,--debug Turn on verbose messages 200 | -h,--help Output this message 201 | -j,--jump=IP SSH through host with IP address IP 202 | -m,--module=MOD Use config/MOD.json and template/MOD.json 203 | -q,--quiet Mute status messages 204 | -t,--template=TEMPLATE Use file TEMPLATE rather than template/vpc-default.json 205 | -v,--version Print name and version information 206 | -y,--yes Do not prompt for confirmation 207 | 208 | If an argument is required for a long option, so to the short. Same for 209 | optional arguments. 210 | 211 | Commands: 212 | add Add functionality to an existing VPC 213 | add-logger Add logging functionality to an existing VPC 214 | auto-services Lanch multiple services on fleet using a template/NAME.services file 215 | check Run various tests against an existing stax 216 | connect [TARGET] Connect to bastion|gateway|service in the VPC stax over SSH 217 | create Create a new VPC stax in AWS 218 | describe Describe the stax created from this host 219 | delete Delete the existing VPC stax 220 | dockerip-update Fetch docker IP addresses and update related files 221 | fleet Run various fleetctl commands against the fleet cluster 222 | help Output this message 223 | history View history of recently created/deleted stax 224 | list List all completely built and running stax 225 | rds PASSWORD Create an RDS instance in the DB subnet 226 | rds-delete RDSIN Delete RDS instance RDSIN 227 | remove ADD Remove the previously added ADD 228 | services List servers that are available to run across a stax 229 | slack Post usage report to Slack, define hook in stax.config 230 | sleep Turn on/off bastion host which allows ssh access into the VPC 231 | start SERVICE Start service SERVICE in the fleet cluster 232 | test Automated test to exercise functionality of stax 233 | update Update an existing VPC with changes from Cloudformation 234 | validate Validate CloudFormation template 235 | 236 | For more help, check the docs: https://github.com/MonsantoCo/stax 237 | ``` 238 | 239 | * Create a stax cluster on AWS. __WARNING: This will cost you money!__ 240 | 241 | ```bash 242 | $ ./stax --config=config/vpc-default.json --template=template/vpc-default.json create 243 | ``` 244 | 245 | * Watch for any errors. 246 | 247 | ## Accessing the cluster 248 | 249 | It will take ~5 minutes to build, you can test if it's ready by trying 250 | to connect. 251 | 252 | ```bash 253 | $ ./stax connect 254 | ``` 255 | 256 | The command will check if the cluster is built, and if it is, it will 257 | populate the bastion host with needed information and then connect you 258 | to it. 259 | 260 | * You can access specific hosts in the Gateway Cluster and Service Cluster using the following commands: 261 | 262 | ```bash 263 | $ ./stax connect gateway[N] 264 | $ ./stax connect service[N] 265 | ``` 266 | 267 | * You can get information about the fleet cluster with the `fleet` command: 268 | 269 | ```bash 270 | $ ./stax fleet 271 | ``` 272 | 273 | * You can test the general operation of the stack with the `check` command: 274 | 275 | ```bash 276 | $ ./stax check 277 | ``` 278 | 279 | * You can get a list of service stax knows how to deploy with the following command: 280 | 281 | ```bash 282 | $ ./stax services 283 | ``` 284 | 285 | * You can deploy one of those services using the start command: 286 | 287 | ```bash 288 | $ ./stax start SERVICE 289 | ``` 290 | 291 | replacing `SERVICE` with the name of the service you want to deploy. 292 | The service deployment is done using `fleet`. 293 | 294 | * You can create a PostgreSQL RDS instance with the following command: 295 | 296 | ```bash 297 | $ ./stax rds PASSWORD 298 | ``` 299 | 300 | replacing `PASSWORD` with a password you will need to connect to the 301 | database. 302 | 303 | ## Destroying the cluster 304 | 305 | To delete the stack and the other entities stax creates as part of its management, e. g., the S3 bucket, EC2 Key Pair, and RDS instances, run the following command: 306 | 307 | ```bash 308 | $ ./stax delete 309 | ``` 310 | 311 | ## stax.config 312 | 313 | An optional customization configuration file is available at `config/stax.config`, which allows you to specify option parameters for your stax. Currently the file allows customization of the prefix stax uses to name your stax, an ssh jumpbox you might have to proxy through to get to your stax, and integration with [Slack](https://slack.com/). 314 | 315 | ``` 316 | ## stax.config - optional parameters specific to your environment 317 | 318 | # the prefix for the name of your stax 319 | STAX_TAG_PREFIX="" 320 | 321 | # the hostname or IP of a ssh 'jumpbox' to proxy connections to your VPC 322 | STAX_JUMP="" 323 | 324 | # the webhook URL to allow stax to post to a slack channel (#stax by default) 325 | # see https://slack.com/services/ for setup documentation 326 | STAX_SLACK_WHOOK="" 327 | ``` 328 | 329 | * To install stax.config 330 | 331 | ``` 332 | cp config/stax.config ~/.stax.config 333 | ``` 334 | 335 | * Edit the contents of `~/.stax.config` and enter your values 336 | 337 | Now, running stax will see that file and source it, using the found variables over any others in the `config` directory. 338 | 339 | ## Acknowledgements 340 | 341 | The stax project started off with ideas from the following projects: 342 | 343 | * [emmanuel/coreos-skydns-cloudformation](https://github.com/emmanuel/coreos-skydns-cloudformation) 344 | * [xueshanf/coreos-aws-cloudformation](https://github.com/xueshanf/coreos-aws-cloudformation) 345 | * [kelseyhightower/kubernetes-coreos](https://github.com/kelseyhightower/kubernetes-coreos) 346 | 347 | Thanks everyone, Open Source FTW! 348 | 349 | ## License 350 | 351 | ``` 352 | # Modified BSD License 353 | 354 | Copyright (c) 2015, Monsanto Company 355 | All rights reserved. 356 | 357 | Redistribution and use in source and binary forms, with or without 358 | modification, are permitted provided that the following conditions are met: 359 | * Redistributions of source code must retain the above copyright 360 | notice, this list of conditions and the following disclaimer. 361 | * Redistributions in binary form must reproduce the above copyright 362 | notice, this list of conditions and the following disclaimer in the 363 | documentation and/or other materials provided with the distribution. 364 | * Neither the name of the Monsanto Company nor the 365 | names of its contributors may be used to endorse or promote products 366 | derived from this software without specific prior written permission. 367 | 368 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 369 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 370 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 371 | DISCLAIMED. IN NO EVENT SHALL MONSANTO COMPANY BE LIABLE FOR ANY 372 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 373 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 374 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 375 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 376 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 377 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 378 | ``` 379 | 380 | ## Stax Studio 381 | 382 | Stax, besides being a clever take on the word stacks, is named after 383 | the famous Stax Recording Studio in Memphis, TN. If you're ever in 384 | Memphis, visit the awesome 385 | [Stax Museum](http://www.staxmuseum.com/)... it's far more interesting 386 | than Sun Studios, but I digress. 387 | 388 | ![Stax Museum](https://media-cdn.tripadvisor.com/media/photo-s/01/70/29/68/stax-recording-studio.jpg) 389 | -------------------------------------------------------------------------------- /assets/jq/Darwin/jq: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/philcryer/stax/5c229709f182982800250b6603c2da26e91344aa/assets/jq/Darwin/jq -------------------------------------------------------------------------------- /assets/jq/Linux/jq: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/philcryer/stax/5c229709f182982800250b6603c2da26e91344aa/assets/jq/Linux/jq -------------------------------------------------------------------------------- /assets/services/coreos/alias.sh: -------------------------------------------------------------------------------- 1 | alias ll='ls -l' 2 | alias d='docker ' 3 | alias ds='docker ps' 4 | alias di='docker images' 5 | alias drm='docker rm -f $(docker ps -qa)' 6 | alias sd='sudo systemctl' 7 | alias cci='sudo coreos-cloudinit --from-file' 8 | alias j='journalctl' 9 | function nsa { sudo nsenter -p -u -m -i -n -t $(docker inspect -f '{{ .State.Pid }}' $1) ; } 10 | -------------------------------------------------------------------------------- /assets/services/coreos/docker.service: -------------------------------------------------------------------------------- 1 | .include /usr/lib/systemd/system/docker.service 2 | 3 | [Service] 4 | ExecStart= 5 | ExecStart=/usr/bin/docker -d -s=btrfs -r=false -H fd:// --dns=172.17.42.1 --dns-search=cluster.local 6 | -------------------------------------------------------------------------------- /assets/services/coreos/launch_units.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ -z "$FLEETCTL_TUNNEL" ]; then 4 | answer='N' 5 | echo -n "Are you on one of the cluster machines? [Y/N]" 6 | read answer 7 | echo "" 8 | if [ "X$answer" = "XY" ]; then 9 | echo "Continue." 10 | else 11 | echo "You must set FLEETCTL_TUNNEL (a resolvable address to one of your CoreOS instances)" 12 | echo "e.g.:" 13 | echo "export FLEETCTL_TUNNEL=1.2.3.4" 14 | exit 1 15 | fi 16 | fi 17 | 18 | SCRIPT_PATH=$( cd $(dirname $0) ; pwd -P ) 19 | cd $SCRIPT_PATH/../units 20 | 21 | # Add the service templates to Fleet 22 | fleetctl submit registry/registry@.service 23 | # Start instantiated units from the templates (+ a number) 24 | fleetctl start registry/registry@1.service 25 | -------------------------------------------------------------------------------- /assets/services/coreos/list_units.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | SCRIPT_PATH=$( cd $(dirname $0) ; pwd -P ) 4 | cd $SCRIPT_PATH/../units 5 | 6 | fleetctl list-units 7 | fleetctl list-machines 8 | -------------------------------------------------------------------------------- /assets/services/coreos/user-data.yaml: -------------------------------------------------------------------------------- 1 | #cloud-config 2 | 3 | users: 4 | - name: skydns 5 | system: true 6 | coreos: 7 | update: 8 | reboot-strategy: etcd-lock 9 | etcd: 10 | discovery: https://discovery.etcd.io/ 11 | addr: $private_ipv4:4001 12 | peer-addr: $private_ipv4:7001 13 | fleet: 14 | public-ip: $private_ipv4 15 | metadata: public_ip=$public_ipv4,region=us-west-2,instance-type=m3.medium 16 | units: 17 | - name: etcd.service 18 | command: start 19 | - name: fleet.service 20 | command: start 21 | - name: skydns.installer.service 22 | command: start 23 | content: | 24 | [Unit] 25 | Description=SkyDNS Installer 26 | [Service] 27 | Type=oneshot 28 | RemainAfterExit=true 29 | ExecStart=-/usr/bin/mkdir -p /var/lib/skydns/bin 30 | ExecStart=-/usr/bin/curl -o /var/lib/skydns/bin/skydns https://s3-us-west-2.amazonaws.com/coreos-beta/skydns 31 | ExecStart=/usr/bin/chown skydns:skydns /var/lib/skydns/bin/skydns 32 | ExecStart=/usr/bin/chmod +x /var/lib/skydns/bin/skydns 33 | - name: skydns.service 34 | command: start 35 | enable: true 36 | content: | 37 | [Unit] 38 | Description=skydns 39 | Requires=skydns.installer.service 40 | Requires=etcd.service 41 | Requires=docker.service 42 | After=skydns.installer.service 43 | After=etcd.service 44 | After=docker.service 45 | [Service] 46 | User=skydns 47 | Group=skydns 48 | Type=simple 49 | ExecStartPre=/usr/bin/etcdctl set /skydns/local/cluster/hosts/%m '{\"host\":\"${COREOS_PRIVATE_IPV4}\"}' 50 | ExecStart=/var/lib/skydns/bin/skydns -addr 172.17.42.1:5333 -verbose=true -discover=true -domain cluster.local. -local %m.hosts.cluster.local 51 | ExecStopPost=/usr/bin/etcdctl rm /skydns/local/cluster/hosts/%m 52 | PermissionsStartOnly=true 53 | ExecStartPre=-/sbin/iptables -D INPUT -p udp --dport 5333 -j ACCEPT 54 | ExecStartPre=-/sbin/iptables -t nat -D PREROUTING -p udp --dport 53 -j REDIRECT --to-ports 5333 55 | ExecStartPre=/sbin/iptables -A INPUT -p udp --dport 5333 -j ACCEPT 56 | ExecStartPre=/sbin/iptables -t nat -A PREROUTING -p udp --dport 53 -j REDIRECT --to-ports 5333 57 | ExecStopPost=/sbin/iptables -D INPUT -p udp --dport 5333 -j ACCEPT 58 | ExecStopPost=/sbin/iptables -t nat -D PREROUTING -p udp --dport 53 -j REDIRECT --to-ports 5333 59 | Restart=always 60 | RestartSec=5 61 | ReadOnlyDirectories=/etc 62 | [Install] 63 | WantedBy=multi-user.target 64 | - name: cadvisor.service 65 | command: start 66 | enable: true 67 | content: | 68 | [Unit] 69 | Description=cAdvisor 70 | Requires=docker.service 71 | After=docker.service 72 | After=skydns.service 73 | [Service] 74 | Type=simple 75 | Environment=ENV=test 76 | ExecStart=/usr/bin/docker run \ 77 | --volume=/var/run:/var/run:rw \ 78 | --volume=/sys:/sys:ro \ 79 | --volume=/var/lib/docker/:/var/lib/docker:ro \ 80 | --volume=/tmp:/tmp:rw \ 81 | --publish=8080:8080 \ 82 | --name=cadvisor \ 83 | --dns-search=${ENV}.cluster.local \ 84 | google/cadvisor:latest \ 85 | -storage_driver=influxdb \ 86 | -storage_driver_host=influxdb-1:8086 \ 87 | -storage_driver_db=cadvisor \ 88 | -storage_driver_user=root \ 89 | -storage_driver_password=root 90 | Restart=always 91 | RestartSec=5 92 | [Install] 93 | WantedBy=multi-user.target 94 | - name: sysinfo_influxdb.service 95 | command: start 96 | enable: true 97 | content: | 98 | [Unit] 99 | Description=sysinfo_influxdb 100 | Requires=docker.service 101 | After=docker.service 102 | After=skydns.service 103 | [Service] 104 | Type=simple 105 | Environment="ENV=test" 106 | Restart=always 107 | RestartSec=10 108 | ExecStart=/usr/bin/docker run \ 109 | --name=sysinfo_influxdb \ 110 | --dns-search ${ENV}.cluster.local \ 111 | nordstrom/sysinfo_influxdb:latest 112 | [Install] 113 | WantedBy=multi-user.target 114 | -------------------------------------------------------------------------------- /assets/services/dj.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=DJ (Docker janitor) clears out stopped containers and unused images 3 | 4 | After=docker.service 5 | Requires=docker.service 6 | 7 | [Service] 8 | SuccessExitStatus=1 123 9 | Type=simple 10 | ExecStart=/bin/bash -c 'docker ps -aq --no-trunc -f status=exited | xargs --no-run-if-empty docker rm -v && docker images -a -q | xargs --no-run-if-empty docker rmi -f' 11 | 12 | [Install] 13 | WantedBy=multi-user.target 14 | 15 | [X-Fleet] 16 | MachineOf=dj.timer -------------------------------------------------------------------------------- /assets/services/dj.timer: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Runs DJ (Docker janitor) on schedule 3 | 4 | Requires=docker.service 5 | 6 | [Timer] 7 | OnBootSec=1d 8 | OnCalendar=01:00 9 | Persistent=true 10 | 11 | [Install] 12 | WantedBy=multi-user.target -------------------------------------------------------------------------------- /assets/services/dj/dj.sh: -------------------------------------------------------------------------------- 1 | srv_name="dj" 2 | 3 | # removes any duplicate services (if they exist) 4 | fleetctl destroy $(fleetctl list-units | grep "^$srv_name") 5 | 6 | # loads the service and timer units 7 | fleetctl load $srv_name.timer 8 | fleetctl load $srv_name.service 9 | 10 | # starts the timer 11 | fleetctl start $srv_name.timer 12 | -------------------------------------------------------------------------------- /assets/services/dj/load-up: -------------------------------------------------------------------------------- 1 | ## load-up 2 | docker pull philcryer/min-jessie 3 | docker pull philcryer/min-jessie-nginx 4 | docker pull philcryer/min-wheezy 5 | docker pull alpine:latest 6 | docker run -it `docker images|grep nginx|awk -F " " '{print $3}'` echo "ohai" 7 | docker run -it `docker images|grep nginx|awk -F " " '{print $3}'` echo "ohai" 8 | docker run -it `docker images|grep nginx|awk -F " " '{print $3}'` echo "ohai" 9 | docker run -it `docker images|grep nginx|awk -F " " '{print $3}'` echo "ohai" 10 | docker run -it `docker images|grep nginx|awk -F " " '{print $3}'` echo "ohai" 11 | -------------------------------------------------------------------------------- /assets/services/dj/reset: -------------------------------------------------------------------------------- 1 | ## Reset 2 | fleetctl unload dj.service; 3 | fleetctl unload dj.timer; 4 | fleetctl destroy dj.service; 5 | fleetctl destroy dj.timer; 6 | #journalctl -f 7 | -------------------------------------------------------------------------------- /assets/services/dj/start: -------------------------------------------------------------------------------- 1 | ## Start 2 | fleetctl load dj.timer 3 | fleetctl load dj.service 4 | fleetctl start dj.timer 5 | -------------------------------------------------------------------------------- /assets/services/dj/status: -------------------------------------------------------------------------------- 1 | ## Status 2 | echo -n " (unit-files) " 3 | fleetctl list-unit-files 4 | echo "------------------" 5 | echo -n " (units) " 6 | fleetctl list-units 7 | echo "------------------" 8 | echo " (dockers) `docker ps -a|head -n-1 |wc -l`" 9 | echo "------------------" 10 | echo " (dockers-img) `docker images -a|head -n-1 |wc -l`" 11 | -------------------------------------------------------------------------------- /assets/services/elasticsearch-discovery@.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Elasticsearch Discovery Service 3 | 4 | # Requirements 5 | Requires=docker.service 6 | Requires=etcd.service 7 | Requires=fleet.service 8 | Wants=elasticsearch@%i.service 9 | 10 | # Dependency ordering and binding 11 | After=docker.service 12 | After=etcd.service 13 | After=fleet.service 14 | After=elasticsearch@%i.service 15 | BindsTo=elasticsearch@%i.service 16 | PartOf=elasticsearch@%i.service 17 | 18 | [Service] 19 | TimeoutStartSec=10m 20 | Restart=on-failure 21 | RestartSec=5s 22 | 23 | # Set environmental variables 24 | EnvironmentFile=/etc/environment 25 | Environment="ES_CLUSTER=es01" 26 | 27 | ExecStart=/bin/bash -c '\ 28 | while true; do \ 29 | curl -Ls ${COREOS_PRIVATE_IPV4}:9200 > /dev/null ;\ 30 | [ $? -eq 0 ] && curl -L http://${COREOS_PRIVATE_IPV4}:4001/v2/keys/services/logging/es/${ES_CLUSTER}/host/${COREOS_PRIVATE_IPV4}?ttl=60 -XPUT -d value=\'{"host":"%H","http_port":9200,"cluster_port":9300}\' ;\ 31 | sleep 50 ;\ 32 | done' 33 | 34 | ExecStop=/usr/bin/curl -L http://${COREOS_PRIVATE_IPV4}:4001/v2/keys/services/logging/es/${ES_CLUSTER}/host/${COREOS_PRIVATE_IPV4} -XDELETE 35 | 36 | [X-Fleet] 37 | MachineOf=elasticsearch@%i.service -------------------------------------------------------------------------------- /assets/services/elasticsearch-dv@.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Elasticsearch Data Volume 3 | 4 | # Requirements 5 | Requires=docker.service 6 | After=docker.service 7 | Before=elasticsearch@%i.service 8 | 9 | [Service] 10 | Type=oneshot 11 | RemainAfterExit=yes 12 | ExecStart=/bin/sh -c "docker inspect %p-%i >/dev/null 2>&1 || docker run --name %p-%i -v /var/lib/elasticsearch busybox chmod -R 0777 /var/lib/elasticsearch" -------------------------------------------------------------------------------- /assets/services/elasticsearch-proxy.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Elasticsearch Proxy 3 | 4 | # Requirements 5 | Requires=docker.service 6 | Requires=etcd.service 7 | Requires=fleet.service 8 | 9 | # Dependency ordering and binding 10 | After=docker.service 11 | After=etcd.service 12 | After=fleet.service 13 | 14 | [Service] 15 | TimeoutStartSec=10m 16 | Restart=on-failure 17 | RestartSec=10s 18 | 19 | LimitNOFILE=65535 20 | LimitMEMLOCK=infinity 21 | 22 | # Set environmental variables 23 | EnvironmentFile=/etc/environment 24 | Environment="ES_CLUSTER=es01" 25 | 26 | LimitNOFILE=65535 27 | LimitMEMLOCK=infinity 28 | 29 | ExecStartPre=-/usr/bin/docker kill %p 30 | ExecStartPre=-/usr/bin/docker rm %p 31 | ExecStartPre=/usr/bin/docker pull monsantoco/elasticsearch:v1.5.0 32 | 33 | ExecStart=/bin/bash -c '\ 34 | curl -sf ${COREOS_PRIVATE_IPV4}:4001/v2/keys/services/logging/es/${ES_CLUSTER}/host > /dev/null ;\ 35 | if [ $? -eq 0 ]; then \ 36 | UNICAST_HOSTS=$(for key in $(etcdctl ls --recursive /services/logging/es/${ES_CLUSTER}/host); do \ 37 | ip=$(echo $key | cut -d/ -f7) ;\ 38 | port=$(etcdctl get $key | cut -d, -f3 | cut -d: -f2 | tr -d "} ") ;\ 39 | echo "$ip:$port" ;\ 40 | done | paste -s -d",") ;\ 41 | else \ 42 | UNICAST_HOSTS="" ;\ 43 | fi ;\ 44 | /usr/bin/docker run \ 45 | --name %p \ 46 | --publish 9200:9200 \ 47 | --publish 9300:9300 \ 48 | --env ES_CLUSTER=${ES_CLUSTER} \ 49 | --env SERVICE_NAME=%p \ 50 | --dns $(ip route | awk \'/docker0/ { print $NF }\') \ 51 | --dns-search service.consul \ 52 | monsantoco/elasticsearch:v1.5.0 \ 53 | --node.name=%p \ 54 | --node.data=false \ 55 | --node.master=false \ 56 | --network.publish_host=${COREOS_PRIVATE_IPV4} \ 57 | --discovery.zen.ping.multicast.enabled=false \ 58 | --discovery.zen.ping.unicast.hosts=$UNICAST_HOSTS' 59 | 60 | ExecStartPost=/usr/bin/curl -L http://${COREOS_PRIVATE_IPV4}:4001/v2/keys/services/logging/es/${ES_CLUSTER}/proxy/${COREOS_PRIVATE_IPV4} -XPUT -d value='{"host":"%H","http_port":9200,"cluster_port":9300}' 61 | 62 | ExecStop=-/usr/bin/docker stop %p 63 | ExecStop=-/usr/bin/docker kill %p 64 | ExecStop=-/usr/bin/docker rm %p 65 | 66 | ExecStopPost=/usr/bin/bash -c '\ 67 | if [ $(etcdctl ls --recursive /services/logging/es/${ES_CLUSTER}/proxy | wc -l) -le 2 ]; then \ 68 | curl -L http://${COREOS_PRIVATE_IPV4}:4001/v2/keys/services/logging/es/${ES_CLUSTER}/proxy?recursive=true -XDELETE ;\ 69 | else \ 70 | curl -L http://${COREOS_PRIVATE_IPV4}:4001/v2/keys/services/logging/es/${ES_CLUSTER}/proxy/${COREOS_PRIVATE_IPV4} -XDELETE ;\ 71 | fi' 72 | 73 | [Install] 74 | WantedBy=multi-user.target 75 | 76 | [X-Fleet] 77 | Conflicts=elasticsearch@*.service -------------------------------------------------------------------------------- /assets/services/elasticsearch@.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Elasticsearch 3 | 4 | # Requirements 5 | Requires=docker.service 6 | Requires=etcd.service 7 | Requires=fleet.service 8 | Requires=elasticsearch-dv@%i.service 9 | 10 | # Dependency ordering and binding 11 | After=docker.service 12 | After=etcd.service 13 | After=fleet.service 14 | After=elasticsearch-dv@%i.service 15 | BindsTo=elasticsearch-dv@%i.service 16 | 17 | [Service] 18 | TimeoutStartSec=10m 19 | Restart=on-failure 20 | RestartSec=10s 21 | 22 | LimitNOFILE=65535 23 | LimitMEMLOCK=infinity 24 | 25 | # Set environmental variables 26 | EnvironmentFile=/etc/environment 27 | Environment="ES_CLUSTER=es01" 28 | 29 | LimitNOFILE=65535 30 | LimitMEMLOCK=infinity 31 | 32 | ExecStartPre=-/usr/bin/docker kill %p-%i 33 | ExecStartPre=-/usr/bin/docker rm %p-%i 34 | ExecStartPre=/usr/bin/docker pull monsantoco/elasticsearch:v1.5.0 35 | 36 | ExecStart=/bin/bash -c '\ 37 | curl -sf ${COREOS_PRIVATE_IPV4}:4001/v2/keys/services/logging/es/${ES_CLUSTER}/host > /dev/null ;\ 38 | if [ $? -eq 0 ]; then \ 39 | UNICAST_HOSTS=$(for key in $(etcdctl ls --recursive /services/logging/es/${ES_CLUSTER}/host); do \ 40 | ip=$(echo $key | cut -d/ -f7) ;\ 41 | port=$(etcdctl get $key | cut -d, -f3 | cut -d: -f2 | tr -d "} ") ;\ 42 | echo "$ip:$port" ;\ 43 | done | paste -s -d",") ;\ 44 | else \ 45 | UNICAST_HOSTS="" ;\ 46 | fi ;\ 47 | /usr/bin/docker run \ 48 | --name %p-%i \ 49 | --publish 9200:9200 \ 50 | --publish 9300:9300 \ 51 | --volumes-from elasticsearch-dv-%i \ 52 | --env ES_CLUSTER=${ES_CLUSTER} \ 53 | monsantoco/elasticsearch:v1.5.0 \ 54 | --node.name=%H \ 55 | --network.publish_host=${COREOS_PRIVATE_IPV4} \ 56 | --discovery.zen.ping.multicast.enabled=false \ 57 | --discovery.zen.ping.unicast.hosts=$UNICAST_HOSTS' 58 | 59 | ExecStop=-/usr/bin/docker stop %p-%i 60 | ExecStop=-/usr/bin/docker kill %p-%i 61 | ExecStop=-/usr/bin/docker rm %p-%i 62 | 63 | [Install] 64 | WantedBy=multi-user.target 65 | 66 | [X-Fleet] 67 | Conflicts=%p@*.service 68 | MachineOf=elasticsearch-dv@%i.service -------------------------------------------------------------------------------- /assets/services/gitlab-postgres.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Postgres for gitlab 3 | After=docker.service 4 | Requires=docker.service 5 | 6 | [Service] 7 | ExecStartPre=-/usr/bin/docker kill gitlab-postgres 8 | ExecStartPre=-/usr/bin/docker rm gitlab-postgres 9 | ExecStartPre=/usr/bin/docker pull postgres:9.4.0 10 | ExecStart=/usr/bin/docker run --name gitlab-postgres -e 'DB_NAME=gitlabhq_production' -e 'DB_USER=gitlab' -e 'DB_PASS=dockerrules!' -v /opt/redis:/var/lib/redis postgres:9.4.0 11 | ExecStop=/usr/bin/docker stop gitlab-postgres 12 | 13 | [X-Fleet] 14 | MachineOf=gitlab-redis.service -------------------------------------------------------------------------------- /assets/services/gitlab-redis.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Redis for gitlab 3 | After=docker.service 4 | Requires=docker.service 5 | 6 | [Service] 7 | ExecStartPre=-/usr/bin/docker kill gitlab-redis 8 | ExecStartPre=-/usr/bin/docker rm gitlab-redis 9 | ExecStartPre=/usr/bin/docker pull philcryer/min-redis:latest 10 | ExecStart=/usr/bin/docker run --name gitlab-redis -v /opt/redis:/var/lib/redis philcryer/min-redis:latest 11 | ExecStop=/usr/bin/docker stop gitlab-redis 12 | -------------------------------------------------------------------------------- /assets/services/gitlab.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Gitlab 3 | After=docker.service 4 | Requires=docker.service 5 | 6 | [Service] 7 | ExecStartPre=-/usr/bin/docker kill gitlab 8 | ExecStartPre=-/usr/bin/docker rm gitlab 9 | ExecStartPre=/usr/bin/docker pull sameersbn/gitlab:latest 10 | ExecStart=/usr/bin/docker run --name gitlab -p 10080:80 -p 10022:22 -v /opt/gitlab/data:/home/git/data -e 'GITLAB_HOST=%H' -e 'GITLAB_PORT=10080' -e 'GITLAB_SSH_PORT=10022' --link gitlab-redis:redisio --link gitlab-postgres:postgresql sameersbn/gitlab:latest 11 | ExecStop=/usr/bin/docker stop gitlab 12 | 13 | [X-Fleet] 14 | MachineOf=gitlab-postgres.service 15 | -------------------------------------------------------------------------------- /assets/services/httpbin.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Httpbin 3 | After=docker.service 4 | Requires=docker.service 5 | 6 | [Service] 7 | TimeoutStartSec=0 8 | ExecStartPre=-/usr/bin/docker kill httpbin 9 | ExecStartPre=-/usr/bin/docker rm httpbin 10 | ExecStartPre=/usr/bin/docker pull citizenstig/httpbin:latest 11 | ExecStart=/usr/bin/docker run --name httpbin -P citizenstig/httpbin:latest 12 | ExecStop=/usr/bin/docker stop httpbin 13 | -------------------------------------------------------------------------------- /assets/services/jenkins.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Jenkins 3 | After=docker.service 4 | Requires=docker.service 5 | 6 | [Service] 7 | ExecStartPre=-/usr/bin/docker kill jenkins 8 | ExecStartPre=-/usr/bin/docker rm jenkins 9 | ExecStartPre=/usr/bin/docker pull monsantoco/jenkins-docker:latest 10 | ExecStart=/usr/bin/docker run --name jenkins -P -v /var/run/docker.sock:/var/run/docker.sock monsantoco/jenkins-docker:latest 11 | ExecStop=/usr/bin/docker stop jenkins 12 | -------------------------------------------------------------------------------- /assets/services/kibana.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Kibana 3 | 4 | # Requirements 5 | Requires=docker.service 6 | Requires=etcd.service 7 | Requires=fleet.service 8 | 9 | # Dependency ordering and binding 10 | After=docker.service 11 | After=etcd.service 12 | After=fleet.service 13 | 14 | [Service] 15 | TimeoutStartSec=10m 16 | Restart=on-failure 17 | RestartSec=5s 18 | 19 | # Get CoreOS environmental variables 20 | EnvironmentFile=/etc/environment 21 | Environment="ES_CLUSTER=es01" 22 | 23 | ExecStartPre=-/usr/bin/docker stop %p 24 | ExecStartPre=-/usr/bin/docker kill %p 25 | ExecStartPre=/usr/bin/docker pull monsantoco/kibana:v4.0.2 26 | 27 | ExecStart=/bin/bash -c "\ 28 | /usr/bin/docker run --name %p \ 29 | --publish 5601:5601 \ 30 | --env ES_URL=elasticsearch-proxy:9200 \ 31 | --env SERVICE_NAME=%p \ 32 | --dns $(ip route | awk '/docker0/ { print $NF }') \ 33 | --dns-search service.consul \ 34 | monsantoco/kibana:v4.0.2" 35 | 36 | ExecStartPost=/usr/bin/curl -L http://${COREOS_PRIVATE_IPV4}:4001/v2/keys/services/logging/kibana/host/${COREOS_PRIVATE_IPV4} -XPUT -d value="%H" 37 | 38 | ExecStop=-/usr/bin/docker stop %p 39 | ExecStop=-/usr/bin/docker kill %p 40 | ExecStop=-/usr/bin/docker rm %p 41 | 42 | ExecStopPost=/usr/bin/curl -L http://${COREOS_PRIVATE_IPV4}:4001/v2/keys/services/logging/kibana/host/${COREOS_PRIVATE_IPV4} -XDELETE 43 | 44 | [Install] 45 | WantedBy=multi-user.target 46 | 47 | [X-Fleet] 48 | Conflicts=%p.service 49 | -------------------------------------------------------------------------------- /assets/services/logspout.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Logspout 3 | 4 | # Requirements 5 | Requires=docker.service 6 | Requires=fleet.service 7 | Requires=consul.service 8 | 9 | # Dependency ordering and binding 10 | After=docker.service 11 | After=fleet.service 12 | After=consul.service 13 | 14 | [Service] 15 | TimeoutStartSec=10m 16 | Restart=on-failure 17 | RestartSec=5s 18 | 19 | # Setup environment 20 | EnvironmentFile=/etc/environment 21 | Environment="ES_CLUSTER=es01" 22 | 23 | # Startup/shutdown 24 | ExecStartPre=-/usr/bin/docker kill %p 25 | ExecStartPre=-/usr/bin/docker rm %p 26 | ExecStartPre=/usr/bin/docker pull gliderlabs/logspout:latest 27 | 28 | ExecStart=/usr/bin/docker run --name %p \ 29 | -P \ 30 | --volume=/var/run/docker.sock:/tmp/docker.sock \ 31 | --hostname=$HOSTNAME \ 32 | --dns $(ip route | awk '/docker0/ { print $NF }') \ 33 | --dns-search service.consul \ 34 | gliderlabs/logspout:latest syslog://logstash:5000 35 | 36 | ExecStop=-/usr/bin/docker stop %p 37 | ExecStop=-/usr/bin/docker kill %p 38 | ExecStop=-/usr/bin/docker rm %p 39 | 40 | [Install] 41 | WantedBy=multi-user.target 42 | 43 | [X-Fleet] 44 | Global=true -------------------------------------------------------------------------------- /assets/services/logstash.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Logstash 3 | 4 | # Requirements 5 | Requires=docker.service 6 | Requires=etcd.service 7 | Requires=fleet.service 8 | 9 | # Dependency ordering and binding 10 | After=docker.service 11 | After=etcd.service 12 | After=fleet.service 13 | 14 | [Service] 15 | TimeoutStartSec=10m 16 | Restart=on-failure 17 | RestartSec=5s 18 | 19 | # Get CoreOS environmental variables 20 | EnvironmentFile=/etc/environment 21 | Environment="ES_CLUSTER=es01" 22 | 23 | ExecStartPre=-/usr/bin/docker stop %p 24 | ExecStartPre=-/usr/bin/docker kill %p 25 | ExecStartPre=/usr/bin/docker pull monsantoco/logstash:v1.5.0 26 | 27 | ExecStart=/bin/bash -c "\ 28 | /usr/bin/docker run --name %p \ 29 | --publish 5000:5000 \ 30 | --publish 5000:5000/udp \ 31 | --publish 5002:5002 \ 32 | --publish 5004:5004 \ 33 | --publish 5100:5100 \ 34 | --publish 5200:5200 \ 35 | --env ES_CLUSTER=${ES_CLUSTER} \ 36 | --env ES_HOST=elasticsearch-proxy \ 37 | --env ES_PORT=9200 \ 38 | --env SERVICE_NAME=%p \ 39 | --dns $(ip route | awk '/docker0/ { print $NF }') \ 40 | --dns-search service.consul \ 41 | monsantoco/logstash:v1.5.0" 42 | 43 | ExecStartPost=/usr/bin/curl -L http://${COREOS_PRIVATE_IPV4}:4001/v2/keys/services/logging/logstash/host/${COREOS_PRIVATE_IPV4} -XPUT -d value="%H" 44 | 45 | ExecStop=-/usr/bin/docker stop %p 46 | ExecStop=-/usr/bin/docker kill %p 47 | ExecStop=-/usr/bin/docker rm %p 48 | 49 | ExecStopPost=/usr/bin/curl -L http://${COREOS_PRIVATE_IPV4}:4001/v2/keys/services/logging/logstash/host/${COREOS_PRIVATE_IPV4} -XDELETE 50 | 51 | [Install] 52 | WantedBy=multi-user.target 53 | 54 | [X-Fleet] 55 | Conflicts=%p.service -------------------------------------------------------------------------------- /assets/services/meta/elk.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Elasticsearch 3 | 4 | # Requirements 5 | Requires=docker.service 6 | Requires=fleet.service 7 | Requires=consul.service 8 | 9 | # Dependency ordering and binding 10 | After=docker.service 11 | After=fleet.service 12 | After=consul.service 13 | 14 | [Service] 15 | TimeoutStartSec=0 16 | 17 | # Get CoreOS environmental variables 18 | EnvironmentFile=/etc/environment 19 | 20 | ExecStartPre=/usr/bin/mkdir -p /es/data 21 | ExecStartPre=/usr/bin/docker pull monsantoco/elasticsearch 22 | ExecStart=/usr/bin/docker run --rm --name %p -v /es/data:/esvol/data -p 9200:9200 -p 9300:9300 -e KV_HOST=${COREOS_PRIVATE_IPV4} -e ES_CLUSTER=elk01 monsantoco/elasticsearch 23 | #ExecStart=/usr/bin/docker run --rm --name %p -v /es/data:/esvol/data -p 9200:9200 -p 9300:9300 -e KV_TYPE=consul -e KV_HOST=${COREOS_PRIVATE_IPV4} -e ES_CLUSTER=elk01 monsantoco/elasticsearch 24 | #ExecStartPost=/usr/bin/etcdctl set /es/host/%H '{"ipv4":${COREOS_PRIVATE_IPV4},"http_port":9200,"cluster_port":9300,"cluster":"elk01"}' 25 | ExecStartPost=/usr/bin/etcdctl set /es/host/%H "${COREOS_PRIVATE_IPV4}:9200" 26 | #ExecStartPost=/usr/bin/curl -L http://${COREOS_PRIVATE_IPV4}:8500/v1/kv/es/host/%H -XPUT -d value='{"ipv4":${COREOS_PUBLIC_IPV4},"http_port":9200,"cluster_port":9300,"cluster":"elk01"}' 27 | #ExecStartPost=/usr/bin/curl -L http://${COREOS_PRIVATE_IPV4}:8500/v1/kv/es/host/%H -XPUT -d value=${COREOS_PUBLIC_IPV4} 28 | ExecStop=/usr/bin/docker stop %p 29 | ExecStop=/usr/bin/docker kill %p 30 | ExecStop=/usr/bin/docker rm %p 31 | ExecStopPost=/usr/bin/etcdctl rmdir /es/host/%H 32 | #ExecStopPost=/usr/bin/curl -L http://${COREOS_PRIVATE_IPV4}:8500/v1/kv/es/host/%H -XDELETE 33 | 34 | [X-Fleet] 35 | Conflicts=%p.service 36 | 37 | [Unit] 38 | Description=Logstash 39 | 40 | # Requirements 41 | Requires=docker.service 42 | Requires=fleet.service 43 | Requires=consul.service 44 | 45 | # Dependency ordering and binding 46 | After=docker.service 47 | After=fleet.service 48 | After=consul.service 49 | 50 | [Service] 51 | TimeoutStartSec=0 52 | 53 | # Get CoreOS environmental variables 54 | EnvironmentFile=/etc/environment 55 | 56 | ExecStartPre=/usr/bin/docker pull monsantoco/logstash 57 | #ExecStart=/usr/bin/docker run --rm --name %p -e KV_TYPE=consul -e KV_HOST=${COREOS_PRIVATE_IPV4} -p 5000:5000 -p 5010:5010 -p 5020:5020 -p 5025:5025 monsantoco/logstash 58 | ExecStart=/usr/bin/docker run --rm --name %p -e KV_HOST=${COREOS_PRIVATE_IPV4} -p 5000:5000 -p 5010:5010 -p 5020:5020 -p 5025:5025 monsantoco/logstash 59 | ExecStartPost=/usr/bin/etcdctl set /logstash/host/%H ${COREOS_PRIVATE_IPV4} 60 | #ExecStartPost=/usr/bin/curl -L http://${COREOS_PRIVATE_IPV4}:8500/v1/kv/logstash/host/%H -XPUT -d value=${COREOS_PUBLIC_IPV4} 61 | ExecStop=/usr/bin/docker stop %p 62 | ExecStop=/usr/bin/docker kill %p 63 | ExecStop=/usr/bin/docker rm %p 64 | ExecStopPost=/usr/bin/etcdctl rmdir /logstash/host/%H 65 | #ExecStopPost=/usr/bin/curl -L http://${COREOS_PRIVATE_IPV4}:8500/v1/kv/es/host/%H -XDELETE 66 | 67 | [X-Fleet] 68 | Conflicts=%p.service 69 | 70 | [Unit] 71 | Description=Kibana 72 | 73 | # Requirements 74 | Requires=docker.service 75 | Requires=fleet.service 76 | 77 | # Dependency ordering and binding 78 | After=docker.service 79 | After=fleet.service 80 | 81 | [Service] 82 | TimeoutStartSec=0 83 | 84 | # Get CoreOS environmental variables 85 | EnvironmentFile=/etc/environment 86 | 87 | ExecStartPre=/usr/bin/docker pull monsantoco/kibana 88 | ExecStart=/usr/bin/docker run --rm --name %p -p 5601:5601 -e KV_HOST=${COREOS_PRIVATE_IPV4} monsantoco/kibana 89 | #ExecStart=/usr/bin/docker run --rm --name %p -p 5601:5601 -e KV_HOST=${COREOS_PRIVATE_IPV4} -e KV_TYPE=consul monsantoco/kibana 90 | ExecStartPost=/usr/bin/etcdctl set /kibana/host/%H ${COREOS_PRIVATE_IPV4} 91 | #ExecStartPost=/usr/bin/curl -L http://${COREOS_PRIVATE_IPV4}:8500/v1/kv/kibana/host/%H -XPUT -d value=${COREOS_PUBLIC_IPV4} 92 | ExecStop=/usr/bin/docker stop %p 93 | ExecStop=/usr/bin/docker kill %p 94 | ExecStop=/usr/bin/docker rm %p 95 | ExecStopPost=/usr/bin/etcdctl rmdir /kibana/host/%H 96 | #ExecStopPost=/usr/bin/curl -L http://${COREOS_PRIVATE_IPV4}:8500/v1/kv/kibana/host/%H -XDELETE 97 | 98 | [X-Fleet] 99 | Conflicts=%p.service 100 | -------------------------------------------------------------------------------- /assets/services/meta/rds.service: -------------------------------------------------------------------------------- 1 | ryan wants us to figure out how to get something like RDS, an amazon resource to an existing VPC... 2 | -------------------------------------------------------------------------------- /assets/services/myapp.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=MyApp 3 | After=docker.service 4 | Requires=docker.service 5 | 6 | [Service] 7 | TimeoutStartSec=0 8 | ExecStartPre=-/usr/bin/docker kill busybox1 9 | ExecStartPre=-/usr/bin/docker rm busybox1 10 | ExecStartPre=/usr/bin/docker pull busybox 11 | ExecStart=/usr/bin/docker run --name busybox1 busybox /bin/sh -c "while true; do echo Hello World; sleep 1; done" 12 | ExecStop=/usr/bin/docker stop busybox1 13 | -------------------------------------------------------------------------------- /assets/services/nginx.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Nginx web front-end 3 | After=docker.service 4 | Requires=docker.service 5 | 6 | [Service] 7 | TimeoutStartSec=0 8 | ExecStartPre=/usr/bin/docker pull nginx 9 | ExecStart=/usr/bin/docker run --rm --name nginx -p 80:80 nginx 10 | ExecStop=/usr/bin/docker stop nginx 11 | -------------------------------------------------------------------------------- /assets/services/rds-logger.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=RDS Logging Service 3 | 4 | [Service] 5 | TimeoutStartSec=10m 6 | Restart=on-failure 7 | RestartSec=5s 8 | 9 | # Set environmental variables 10 | EnvironmentFile=/etc/environment 11 | 12 | ExecStartPre=-/usr/bin/docker kill %p 13 | ExecStartPre=/usr/bin/docker pull cgswong/aws:latest 14 | 15 | ExecStart=/usr/bin/docker run --name %p cgswong/aws:latest rds-watch-db-logfile $DBINST --log-file-name error/postgres.log >&2 -I $AWS_ACCESS_KEY_ID -S $AWS_SECRET_KEY 16 | 17 | ExecStop=-/usr/bin/docker stop %p 18 | ExecStop=-/usr/bin/docker kill %p 19 | ExecStop=-/usr/bin/docker rm %p -------------------------------------------------------------------------------- /assets/services/registry.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Private Docker Registry 3 | After=docker.service 4 | Requires=docker.service 5 | 6 | [Service] 7 | ExecStartPre=-/usr/bin/docker kill registry 8 | ExecStartPre=-/usr/bin/docker rm registry 9 | ExecStartPre=/usr/bin/docker pull registry:0.9.1 10 | ExecStart=/usr/bin/docker run --name register -P registry:0.9.1 11 | ExecStop=/usr/bin/docker stop registry 12 | -------------------------------------------------------------------------------- /assets/services/skydns/skydns.install.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=SkyDNS Installer 3 | 4 | [Service] 5 | Type=oneshot 6 | RemainAfterExit=true 7 | ExecStart=-/usr/bin/mkdir -p /var/lib/skydns/bin 8 | ExecStart=-/usr/bin/curl -s -o /var/lib/skydns/bin/skydns https://coreos-beta.s3.amazonaws.com/skydns 9 | ExecStart=/usr/bin/chown -R skydns:skydns /var/lib/skydns 10 | ExecStart=/usr/bin/chmod +x /var/lib/skydns/bin/skydns 11 | -------------------------------------------------------------------------------- /assets/services/skydns/skydns.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=SkyDNS 3 | Requires=skydns.install.service 4 | Requires=etcd.service 5 | Requires=docker.service 6 | After=skydns.install.service 7 | After=etcd.service 8 | After=docker.service 9 | 10 | [Service] 11 | Type=simple 12 | User=skydns 13 | Group=skydns 14 | EnvironmentFile=/etc/environment 15 | # see: http://coreos.com/blog/docker-dynamic-ambassador-powered-by-etcd/#toc_4 16 | # "172.17.42.1:4001 is the known address for etcd on every CoreOS instance from inside of a Docker container" 17 | ExecStartPre=/usr/bin/etcdctl set /skydns/local/cluster/hosts/%m '{"host":"${COREOS_PRIVATE_IPV4}"}' 18 | ExecStart=/var/lib/skydns/bin/skydns -addr 172.17.42.1:5333 -verbose=true -discover=true -local %m.hosts.cluster.local -domain cluster.local. 19 | ExecStopPost=/usr/bin/etcdctl rm /skydns/local/cluster/hosts/%m 20 | 21 | PermissionsStartOnly=true 22 | # ExecStartPre=/usr/sbin/sysctl -w net.ipv4.ip_forward=1 23 | ExecStartPre=-/sbin/iptables -D INPUT -p udp --dport 5333 -j ACCEPT 24 | ExecStartPre=-/sbin/iptables -t nat -D PREROUTING -p udp --dport 53 -j REDIRECT --to-ports 5333 25 | ExecStartPre=/sbin/iptables -A INPUT -p udp --dport 5333 -j ACCEPT 26 | ExecStartPre=/sbin/iptables -t nat -A PREROUTING -p udp --dport 53 -j REDIRECT --to-ports 5333 27 | ExecStopPost=/sbin/iptables -D INPUT -p udp --dport 5333 -j ACCEPT 28 | ExecStopPost=/sbin/iptables -t nat -D PREROUTING -p udp --dport 53 -j REDIRECT --to-ports 5333 29 | 30 | Restart=always 31 | RestartSec=5 32 | # WorkingDirectory=/tmp 33 | # PrivateTmp=true 34 | # NoNewPrivileges=true 35 | ReadOnlyDirectories=/etc 36 | -------------------------------------------------------------------------------- /assets/stax/fleetlogs: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "${yellow}[ ${cyan}----${yellow} ]${reset} running CoreOS hosts: " 4 | echo "{" 5 | ssh -i ~/.ssh/STAX_KEY.pem -l core -o "UserKnownHostsFile=/dev/null" -o "StrictHostKeyChecking=no" -o "LogLevel=quiet" `python -c "import random, sys; print random.choice(open(sys.argv[1]).readlines())," docker_hosts` 'fleetctl list-machines' 6 | echo "}" 7 | echo "${yellow}[ ${cyan}----${yellow} ]${reset} running Docker Units: " 8 | echo "{" 9 | ssh -i ~/.ssh/STAX_KEY.pem -l core -o "UserKnownHostsFile=/dev/null" -o "LogLevel=quiet" -o "StrictHostKeyChecking no" `python -c "import random, sys; print random.choice(open(sys.argv[1]).readlines())," docker_hosts` 'fleetctl list-units' 10 | echo "}" 11 | echo "${yellow}[ ${cyan}----${yellow} ]${reset} loaded Unit Files on CoreOS hosts: " 12 | echo "{" 13 | ssh -i ~/.ssh/STAX_KEY.pem -l core -o "UserKnownHostsFile=/dev/null" -o "LogLevel=quiet" -o "StrictHostKeyChecking no" `python -c "import random, sys; print random.choice(open(sys.argv[1]).readlines())," docker_hosts` 'journalctl -f -u fleet' 14 | echo "}" 15 | -------------------------------------------------------------------------------- /assets/stax/servicerunner: -------------------------------------------------------------------------------- 1 | runner=`cat docker_hosts|tail -n1` 2 | scp -q -r -i ~/.ssh/@STAX_KEY@.pem -o "StrictHostKeyChecking no" services core@${runner}:~ 3 | ssh -i ~/.ssh/@STAX_KEY@.pem -o "StrictHostKeyChecking no" core@${runner} 'fleetctl submit ~/services/@SOME_SERVICE@.service' 4 | ssh -i ~/.ssh/@STAX_KEY@.pem -o "StrictHostKeyChecking no" core@${runner} 'fleetctl start ~/services/@SOME_SERVICE@.service' 5 | echo "`date +'%Y-%m-%d.%H:%M'`-fleetctl-started-@SOME_SERVICE@-on-${runner}" >> audit 6 | -------------------------------------------------------------------------------- /assets/stax/slogans: -------------------------------------------------------------------------------- 1 | for running a vpc on aws ec2 ftw 2 | you know, for cloud 3 | the new hotness 4 | this should work 5 | vagrant destroy -f 6 | ianad, but you knew that 7 | docker + venture capital 8 | cloudy with a chance of fog 9 | teenage riot in a public station 10 | we take cloud computing cirrusly 11 | cloud; security you can blame on someone else 12 | every cloud has a silicon lining 13 | is cloud computing the next big thing in vaporware? 14 | all glory to the hypnotoad! 15 | what's a computer? eat yourself fitter! 16 | cloud capacity: 1000 17 | because Bash is better than Go 18 | to the cloud! 19 | more cloud than you can shake a rainstick at 20 | not to be taken internally 21 | works on my cloud 22 | light fuse, get away 23 | sudo make me a cloud 24 | Hey, you, get off of my cloud 25 | backups are a good thing, unless they come from the sewer 26 | never siphon by mouth 27 | not a significant source of protein 28 | cottonheaded ninny muggins 29 | meeting area for short duration meetings only 30 | this meeting does not require a password 31 | hi, who just joined? 32 | yeah, that's not supported 33 | filmed before a live studio audience 34 | I don't always use aws, but when I do, I prefer stax 35 | thank you for your support 36 | from the land of sky blue waters, and clouds 37 | wait for it 38 | due to unusually high call volume, your wait time is greater than expected 39 | we appreciate your patience; please hold for the next available representative 40 | if you know your party's extension you may enter it at any time 41 | latecomers will be seated at the discretion of management 42 | objects in mirror are closer than they appear 43 | your stax delivered in 30 minutes or less or it's free 44 | we are all made of clouds 45 | recommended by 4 out of 5 dentists surveyed 46 | you're welcome 47 | if you lived here, you'd be home by now 48 | international data rates may apply 49 | do NOT contact me with unsolicited services or offers 50 | never submit passwords through Google Forms 51 | packaged in a plant that also processes peanuts and tree nuts 52 | not responsible for lost or stolen property 53 | resale prices often exceed the tickets' face value 54 | warning: stay back 200 feet, we are not responsible for broken windshields 55 | thank you for participating in the survey 56 | Stax would like to add you to its professional network on LinkedIn 57 | restrooms are for customers only 58 | prior results do not guarantee future results 59 | professional driver on a closed course. do not attempt 60 | -------------------------------------------------------------------------------- /assets/stax/words: -------------------------------------------------------------------------------- 1 | jehovistic 2 | humpbacked 3 | predescent 4 | gothicized 5 | hysteretic 6 | yellowtail 7 | arrhythmia 8 | nonfeeding 9 | antiseptic 10 | alodiality 11 | cryptology 12 | nonmulched 13 | prominency 14 | unmaltable 15 | nonstudied 16 | ghelderode 17 | illuminate 18 | unfeminist 19 | printanier 20 | telegnosis 21 | mischanter 22 | humanising 23 | tiahuanaco 24 | resignaled 25 | delsartian 26 | distressed 27 | fastidious 28 | desecrater 29 | plainchant 30 | assimilate 31 | songstress 32 | vesicatory 33 | suboptical 34 | subfestive 35 | unfeverish 36 | trasimenus 37 | nongaseous 38 | adventitia 39 | promontory 40 | winchester 41 | duumvirate 42 | intercivic 43 | shagginess 44 | patricidal 45 | repository 46 | unclothing 47 | monogamous 48 | chlidanope 49 | inundatory 50 | satisfying 51 | parentlike 52 | unjoinable 53 | indonesian 54 | hyperploid 55 | theorising 56 | thingumbob 57 | lactonized 58 | jackassism 59 | unsurveyed 60 | chopsticks 61 | convulsive 62 | acquitting 63 | erinaceous 64 | barbershop 65 | appositely 66 | semimature 67 | hithermost 68 | intimating 69 | geodesical 70 | hucklebone 71 | nonfavored 72 | chlorinate 73 | palatinate 74 | versicular 75 | unmorality 76 | harassment 77 | carnifying 78 | unhelmeted 79 | subjective 80 | unambulant 81 | episcopize 82 | shopkeeper 83 | strelitzia 84 | gooseflesh 85 | trihydroxy 86 | unlaureled 87 | mayakovsky 88 | impudicity 89 | lambdacism 90 | overhanded 91 | lipophilic 92 | subpalmate 93 | diagnosing 94 | isopiestic 95 | tablespoon 96 | celebrated 97 | tautomeric 98 | leatheroid 99 | unforegone 100 | cashdrawer 101 | emblazoner 102 | postmortem 103 | overpamper 104 | argillitic 105 | cartoonist 106 | granulitic 107 | oppositely 108 | ammoniacal 109 | unwomanish 110 | jeanerette 111 | bouldering 112 | sanctifier 113 | unrabbeted 114 | perfervour 115 | feathercut 116 | reidentify 117 | phrensying 118 | congestive 119 | balkanized 120 | maculation 121 | swivelling 122 | antichurch 123 | unbothered 124 | unboastful 125 | hagiocracy 126 | rinderpest 127 | spermicide 128 | perversion 129 | iridaceous 130 | andromache 131 | antinomian 132 | unpunctual 133 | joyfulness 134 | mistracing 135 | unfavoring 136 | demonising 137 | waitewoman 138 | ereshkigel 139 | uninsulate 140 | saurashtra 141 | dictatress 142 | unestopped 143 | overchased 144 | housephone 145 | yellowweed 146 | caracolled 147 | disdainful 148 | anastigmat 149 | biometrics 150 | reprovable 151 | distribute 152 | proscience 153 | folliculin 154 | headmaster 155 | dicynodont 156 | hypertelic 157 | peptonizer 158 | vitalising 159 | subtleness 160 | unreleased 161 | equivocate 162 | unliveried 163 | candlepins 164 | antileague 165 | pocketbook 166 | casterless 167 | checkmated 168 | nonbending 169 | unprecious 170 | immoralism 171 | circassian 172 | chestnutty 173 | conducible 174 | triskelion 175 | hydrorhiza 176 | impeccable 177 | vespertide 178 | scrapingly 179 | nonvesting 180 | thunderbox 181 | millington 182 | tonguefish 183 | uncalcined 184 | reirrigate 185 | sperrylite 186 | hypolimnia 187 | notionally 188 | binoxalate 189 | euphemizer 190 | unusurious 191 | femininely 192 | thirstiest 193 | unreminded 194 | poriferous 195 | prayerless 196 | leichhardt 197 | throatlash 198 | subjugator 199 | quiescence 200 | unendorsed 201 | crossleted 202 | crumbliest 203 | homeliness 204 | dihydrated 205 | perquisite 206 | patriotism 207 | chubbiness 208 | pancosmism 209 | schizocarp 210 | lenticular 211 | stateliest 212 | omnivorous 213 | opposingly 214 | decadently 215 | vandenberg 216 | anemoscope 217 | stellately 218 | preproving 219 | nationwide 220 | gelatinity 221 | impersonal 222 | bamboozler 223 | pantagruel 224 | monopteroi 225 | palatially 226 | orchectomy 227 | theogonist 228 | muciferous 229 | hydrolyzer 230 | passionate 231 | touchstone 232 | babylonian 233 | ellisville 234 | unobsolete 235 | dibasicity 236 | outwriggle 237 | monetarily 238 | flapdragon 239 | shrewsbury 240 | sermonizer 241 | reichsrath 242 | garbleable 243 | argillitic 244 | comparable 245 | relaxalaid 246 | impanelled 247 | quadrisect 248 | bestiaries 249 | liquidizer 250 | undewiness 251 | triglyphed 252 | centiliter 253 | nonspatial 254 | bolsheviki 255 | tombouctou 256 | thuddingly 257 | boehmenism 258 | ametabolic 259 | emulsoidal 260 | separation 261 | hatshepsut 262 | distrainer 263 | confiscate 264 | boyishness 265 | triturator 266 | byssinosis 267 | agrarianly 268 | gastralgia 269 | puberulent 270 | cassiopean 271 | anatomiser 272 | inimicable 273 | mistakenly 274 | antipastos 275 | hausfrauen 276 | underclerk 277 | outpitying 278 | substriate 279 | fenestrate 280 | vulcanalia 281 | simulatory 282 | discontent 283 | lindenwold 284 | hornblende 285 | supergiant 286 | unmuscular 287 | pohutukawa 288 | scytheless 289 | desolately 290 | enphytotic 291 | cussedness 292 | motionless 293 | jaguarondi 294 | herpangina 295 | amphithyra 296 | apodeictic 297 | unkenneled 298 | miscellany 299 | unpatented 300 | devilishly 301 | volleyball 302 | trichocyst 303 | squirarchy 304 | haustorium 305 | bandleader 306 | durational 307 | hektostere 308 | misplacing 309 | neoterized 310 | oversupped 311 | stewardess 312 | smokestack 313 | unreverted 314 | prewhipped 315 | unpedestal 316 | spacecraft 317 | cortically 318 | subtotemic 319 | nonaccrued 320 | italicized 321 | animatedly 322 | paramatman 323 | untangible 324 | leukocidin 325 | electively 326 | levitation 327 | caballeros 328 | woodenware 329 | poulticing 330 | ejaculated 331 | homostyled 332 | anatomized 333 | metabolize 334 | percentage 335 | continuate 336 | hypothecia 337 | drudgingly 338 | pantothere 339 | keratalgia 340 | petechiate 341 | undaintily 342 | protostele 343 | airbrasive 344 | mutilative 345 | prostigmin 346 | california 347 | noncurrent 348 | italianist 349 | cateringly 350 | serologist 351 | scarcement 352 | ectodermal 353 | archaizing 354 | kremenchug 355 | kicksorter 356 | curvaceous 357 | dismissive 358 | heterodyne 359 | beaujolais 360 | redeclared 361 | notifiable 362 | insectlike 363 | disocclude 364 | dorsigrade 365 | writhingly 366 | garnierite 367 | dilatation 368 | chophouses 369 | egyptology 370 | ophicleide 371 | classicize 372 | unabducted 373 | unaccurate 374 | trihydrate 375 | profascism 376 | illaudably 377 | unwontedly 378 | crispinian 379 | balneology 380 | bennington 381 | henotheist 382 | undersized 383 | walterboro 384 | tanganyika 385 | reexplored 386 | divisional 387 | absorptive 388 | undergrown 389 | negligence 390 | growlingly 391 | beaverlike 392 | eurychoric 393 | acidolysis 394 | untemporal 395 | forcedness 396 | appetising 397 | stenograph 398 | menopausic 399 | alternated 400 | puberulous 401 | maidenhair 402 | oireachtas 403 | personally 404 | filamented 405 | formicaria 406 | afterpains 407 | untortious 408 | unrestored 409 | mudcapping 410 | tenantable 411 | puristical 412 | undoubting 413 | flangeless 414 | unsuffixed 415 | undisputed 416 | attributer 417 | unreversed 418 | anemometer 419 | thenardite 420 | angulation 421 | modernised 422 | unarticled 423 | quarreling 424 | coarseness 425 | unriveting 426 | lexigraphy 427 | katalyzing 428 | listerised 429 | nonedified 430 | centilitre 431 | oxychloric 432 | plebeianly 433 | epiphyseal 434 | cyclopedic 435 | wappenshaw 436 | interphone 437 | extinction 438 | nesselrode 439 | melancholy 440 | pseudooval 441 | unfocusing 442 | rethreaten 443 | proclaimer 444 | heptagonal 445 | southfield 446 | greensburg 447 | percentage 448 | rainforest 449 | liverwurst 450 | outarguing 451 | emblements 452 | incasement 453 | tuffaceous 454 | throatlash 455 | ableptical 456 | alliaceous 457 | sweetwater 458 | preinclude 459 | roadrunner 460 | nickelised 461 | prairillon 462 | feneration 463 | typothetae 464 | automobile 465 | elderberry 466 | humanistic 467 | ascription 468 | telegraphy 469 | tachypneic 470 | untwirling 471 | nonadorner 472 | improviser 473 | chumminess 474 | spikedaces 475 | headworker 476 | draughtily 477 | outdrawing 478 | yeastiness 479 | unbreeched 480 | antimasker 481 | allhallows 482 | paraglossa 483 | hemelytron 484 | folkestone 485 | towardness 486 | ineloquent 487 | nonshipper 488 | uncrippled 489 | sapiential 490 | kibbutznik 491 | iconoclast 492 | fleetingly 493 | popularise 494 | mistassini 495 | coyotillos 496 | prediscuss 497 | chautauqua 498 | immaturely 499 | bluejacket 500 | plasmocyte 501 | lophophore 502 | demonizing 503 | censurable 504 | deadpanned 505 | unrewarded 506 | matozinhos 507 | cohabitant 508 | stalemated 509 | unsecreted 510 | milkfishes 511 | abridgment 512 | intertrace 513 | plasmacyte 514 | emeryville 515 | durability 516 | crossbirth 517 | husbandage 518 | phyllotaxy 519 | ecospecies 520 | blinkingly 521 | diadochian 522 | bellefonte 523 | odontalgic 524 | ruthenious 525 | phenotypic 526 | tiemannite 527 | trouvaille 528 | autonomous 529 | melicertes 530 | subpleural 531 | unpleasant 532 | salientian 533 | misopaedia 534 | revegetate 535 | unhobbling 536 | savageness 537 | arrephoros 538 | engrossing 539 | enumerable 540 | worshipped 541 | denouncing 542 | nonfervent 543 | mastermind 544 | adipopexic 545 | antibaryon 546 | unwearying 547 | artophoria 548 | predeceive 549 | usurpation 550 | waterhouse 551 | priestlike 552 | unlounging 553 | alienating 554 | publicness 555 | champignon 556 | hemachrome 557 | hemophilus 558 | abominator 559 | deflowerer 560 | polyparian 561 | overstarch 562 | subversive 563 | gravettian 564 | squalliest 565 | goldilocks 566 | buttonhook 567 | katabolism 568 | execrative 569 | tinglingly 570 | judicature 571 | oxygenator 572 | sailorlike 573 | routemarch 574 | governable 575 | undershrub 576 | intrastate 577 | doylestown 578 | intendency 579 | toastiness 580 | overhearty 581 | archemorus 582 | unfabulous 583 | naturalist 584 | frigidaria 585 | namability 586 | paracasein 587 | barycentre 588 | ghostwrite 589 | promptbook 590 | volapukist 591 | examinable 592 | garnisheed 593 | underruled 594 | prearrange 595 | storyboard 596 | prenominal 597 | buonarroti 598 | simplified 599 | blotchiest 600 | barricaded 601 | stabiliser 602 | nidicolous 603 | polypetaly 604 | venetianed 605 | dithionate 606 | attainture 607 | heroically 608 | reclosable 609 | windsucker 610 | epicondyle 611 | governessy 612 | villainies 613 | ammiaceous 614 | falfurrias 615 | vulgarised 616 | angiosperm 617 | carchemish 618 | brownshirt 619 | exsanguine 620 | comparable 621 | chauffeuse 622 | hyalograph 623 | schematism 624 | liquefying 625 | isoglossal 626 | unresigned 627 | disinherit 628 | oversupply 629 | rattlehead 630 | unmodified 631 | proscenium 632 | tirelessly 633 | prophesier 634 | calcareous 635 | periosteum 636 | distension 637 | nonemotive 638 | unplacated 639 | avirulence 640 | racecourse 641 | earwigging 642 | glassworks 643 | laurelling 644 | circumcise 645 | graptolite 646 | virtuously 647 | antimerism 648 | misreprint 649 | detractory 650 | distrainer 651 | applicably 652 | marshiness 653 | broomstick 654 | officially 655 | pentateuch 656 | bedeviling 657 | cyanogenic 658 | pentathlon 659 | tricktrack 660 | hydrolysis 661 | deficiency 662 | thunderbox 663 | prealgebra 664 | radarscope 665 | campestral 666 | parnellism 667 | hemiglobin 668 | tropicbird 669 | prerouting 670 | hermitlike 671 | machinator 672 | perilously 673 | appetising 674 | bunkhouses 675 | somersault 676 | megasporic 677 | streetlike 678 | embassador 679 | outfitting 680 | overaffect 681 | complainer 682 | firedragon 683 | turbulence 684 | unmeriting 685 | insentient 686 | misprising 687 | bespeaking 688 | reoxidized 689 | heterogeny 690 | pantomimic 691 | adramelech 692 | doctorfish 693 | lysenkoism 694 | undeceased 695 | hemisphere 696 | plasmagene 697 | semiresiny 698 | cardialgia 699 | semeiology 700 | arctogaeal 701 | tonguelike 702 | gillingham 703 | siderocyte 704 | eurypterid 705 | acroterial 706 | tromometry 707 | costusroot 708 | reichsmark 709 | pressurize 710 | intenerate 711 | geothermal 712 | sulphation 713 | funiculate 714 | metallurgy 715 | accountant 716 | intertrigo 717 | aestivator 718 | undesigned 719 | unphysical 720 | shrubbiest 721 | readvising 722 | nationhood 723 | mariolatry 724 | hambroline 725 | unturbaned 726 | preassured 727 | acidolysis 728 | spathulate 729 | nonpsychic 730 | insentient 731 | olivaceous 732 | willowherb 733 | unportable 734 | dishwasher 735 | enlistment 736 | permutably 737 | dovetailed 738 | varicotomy 739 | endorsable 740 | substriate 741 | unremanded 742 | antimonous 743 | unrendered 744 | matozinhos 745 | unsibilant 746 | economised 747 | kittenlike 748 | influenzal 749 | delphinine 750 | expiration 751 | autotelism 752 | unbilleted 753 | hatshepsut 754 | cerebritis 755 | proctodeal 756 | decurrence 757 | hypanthial 758 | praetextae 759 | sylphidine 760 | scaloppine 761 | cyclically 762 | fabricated 763 | chinoleine 764 | criticised 765 | flugelhorn 766 | discommode 767 | anesthetic 768 | infusorian 769 | fledgeless 770 | florencita 771 | catenulate 772 | excrescent 773 | outdodging 774 | defoliated 775 | palaeolith 776 | flashboard 777 | concerning 778 | chatelaine 779 | unrevetted 780 | belshazzar 781 | unthematic 782 | extrorsely 783 | homostylic 784 | unrubified 785 | justiciary 786 | tasimetric 787 | unvolitive 788 | lubricator 789 | beechdrops 790 | nomothetic 791 | pigeonhole 792 | unhydrated 793 | reabridged 794 | presetting 795 | unbrutized 796 | steakhouse 797 | subaverage 798 | micrifying 799 | lambrequin 800 | adjectival 801 | firecuring 802 | isogonally 803 | upbringing 804 | embargoing 805 | feigningly 806 | invocating 807 | monkfishes 808 | tromometer 809 | hephaestus 810 | carbonless 811 | surrogated 812 | sulphonate 813 | unflitched 814 | pedimented 815 | coleoptera 816 | perfervour 817 | biostatics 818 | asymmetric 819 | mousseline 820 | pornocracy 821 | wearyingly 822 | vinylation 823 | talismanic 824 | incitation 825 | deepfreeze 826 | autonomist 827 | fossilised 828 | balkanised 829 | fustinella 830 | accountant 831 | campaigner 832 | interclasp 833 | bolshevism 834 | conformism 835 | uninfusing 836 | unbearably 837 | epidiorite 838 | neonatally 839 | brodehurst 840 | sidereally 841 | literation 842 | unparceled 843 | scordatura 844 | tetrabasic 845 | unsurgical 846 | notionless 847 | vendettist 848 | pedimental 849 | undidactic 850 | misopaedia 851 | guttenberg 852 | formalizer 853 | appraising 854 | owlishness 855 | undaunting 856 | praenomina 857 | solidarize 858 | ophicleide 859 | mudskipper 860 | unenduring 861 | undertrump 862 | ordainment 863 | giacometti 864 | antiseptic 865 | newsletter 866 | mythicized 867 | dramatiser 868 | peripheral 869 | weinberger 870 | cornerwise 871 | fruiteries 872 | brawniness 873 | annunziata 874 | faceteness 875 | pneumatics 876 | predescend 877 | titillated 878 | outshowing 879 | cephalonia 880 | unrequited 881 | eosinophil 882 | autopsical 883 | paracelsic 884 | attributor 885 | waterbrain 886 | pluraliser 887 | changeover 888 | nonplusing 889 | mithgarthr 890 | cartwright 891 | reindulged 892 | corregidor 893 | anaplastic 894 | undiluting 895 | absentness 896 | zooplastic 897 | submarshal 898 | pesticidal 899 | pressingly 900 | necrophile 901 | beefburger 902 | pepsinogen 903 | ballistite 904 | corollated 905 | unlionized 906 | forecasted 907 | grittiness 908 | strabotomy 909 | chaptalize 910 | academical 911 | nonrevenue 912 | antileague 913 | unenviable 914 | commutated 915 | despairful 916 | unembossed 917 | unmortised 918 | subfactory 919 | ungoitered 920 | jumblement 921 | unciteable 922 | irishising 923 | woodenware 924 | ausforming 925 | eighteenmo 926 | expiratory 927 | eradicable 928 | gradualist 929 | piccaninny 930 | repostpone 931 | expression 932 | perchromic 933 | undrifting 934 | epigrapher 935 | unpromised 936 | anemophily 937 | ungrateful 938 | hippodrome 939 | disfavorer 940 | dekagramme 941 | prewrapped 942 | maneuverer 943 | unstayable 944 | tarkington 945 | sinfulness 946 | strasbourg 947 | unmodelled 948 | snakemouth 949 | almondlike 950 | strikeover 951 | decahedron 952 | fetterless 953 | outquibble 954 | ontologise 955 | lowbrowism 956 | talebearer 957 | syntonizer 958 | reverencer 959 | drossiness 960 | anemotaxis 961 | heterodyne 962 | bernalillo 963 | nephoscope 964 | unbeguiled 965 | segmentary 966 | previolate 967 | overbright 968 | unoppugned 969 | somniloquy 970 | adaptively 971 | triliteral 972 | unfestered 973 | ethnocracy 974 | shoplifter 975 | unbranched 976 | shakuntala 977 | predivider 978 | paratactic 979 | elzevirian 980 | japanesque 981 | unincluded 982 | peroxyacid 983 | lyricising 984 | pannicular 985 | sousaphone 986 | chaparejos 987 | cravenette 988 | literation 989 | multibirth 990 | bitingness 991 | bridgework 992 | persistent 993 | fairground 994 | vagotropic 995 | kriegspiel 996 | cactuslike 997 | infiltrate 998 | unmissable 999 | tollhouses 1000 | billowiest 1001 | praepostor 1002 | noncitable 1003 | carbonylic 1004 | reindicate 1005 | shortbread 1006 | petechiate 1007 | husbandage 1008 | enumerator 1009 | pollinosis 1010 | scutellate 1011 | brahmaloka 1012 | rigoristic 1013 | eucryptite 1014 | corporeity 1015 | stigmatise 1016 | plasmolyse 1017 | corelative 1018 | auxochrome 1019 | nonsterile 1020 | lopatnikov 1021 | unmeriting 1022 | preepochal 1023 | expressman 1024 | signalized 1025 | engrossing 1026 | unhealable 1027 | chromomere 1028 | unifoliate 1029 | epigrapher 1030 | moderation 1031 | proferment 1032 | siphonless 1033 | challenger 1034 | untruckled 1035 | handleable 1036 | ironhanded 1037 | misleading 1038 | figurehead 1039 | initialing 1040 | unfeatured 1041 | drosophila 1042 | butterball 1043 | nonseriate 1044 | khitmatgar 1045 | piccaninny 1046 | diathermia 1047 | surrealist 1048 | unsafetied 1049 | scrappiest 1050 | gottschalk 1051 | zaporozhye 1052 | intervened 1053 | distichous 1054 | ridiculous 1055 | panegyrise 1056 | trigeminal 1057 | nonradical 1058 | revivingly 1059 | predeathly 1060 | follansbee 1061 | schmoosing 1062 | cataclinal 1063 | autoecious 1064 | fasciculus 1065 | unfighting 1066 | dicoumarin 1067 | condylomas 1068 | doughiness 1069 | myxomatous 1070 | shapeliest 1071 | reasonably 1072 | kommunarsk 1073 | matchmaker 1074 | mitigatory 1075 | cicatrizer 1076 | symphonise 1077 | unpartible 1078 | uncavalier 1079 | tertullian 1080 | doughbelly 1081 | urtication 1082 | miamisburg 1083 | outlancing 1084 | crapulency 1085 | venustiano 1086 | unbankable 1087 | uncommonly 1088 | sulphonium 1089 | pyrochlore 1090 | townswomen 1091 | gasometric 1092 | palliative 1093 | petrouchka 1094 | voluminous 1095 | famatinite 1096 | dubitation 1097 | winebibber 1098 | hydrotheca 1099 | uncanceled 1100 | tittivator 1101 | trivalency 1102 | nonlogical 1103 | crystaling 1104 | appreciate 1105 | melezitose 1106 | chaparajos 1107 | percolator 1108 | teniacidal 1109 | amputative 1110 | naprapathy 1111 | sulfureous 1112 | handsomely 1113 | uncasketed 1114 | hinayanist 1115 | bluefields 1116 | jaundicing 1117 | balanchine 1118 | drillstock 1119 | misderived 1120 | anorectous 1121 | makedhonia 1122 | overnarrow 1123 | distilland 1124 | superlunar 1125 | capsizable 1126 | theophilus 1127 | unignorant 1128 | shockstall 1129 | willoughby 1130 | folliculin 1131 | unturreted 1132 | unexpanded 1133 | ingressive 1134 | prebidding 1135 | antonymous 1136 | karyotypic 1137 | interreign 1138 | catalogist 1139 | herigonius 1140 | nonadaptor 1141 | houpelande 1142 | preaxially 1143 | tavernless 1144 | remonetise 1145 | unsnaffled 1146 | mysophilia 1147 | farcically 1148 | anastrophe 1149 | geophagism 1150 | divulgence 1151 | hilltopped 1152 | subtangent 1153 | irishwoman 1154 | believably 1155 | exhilarant 1156 | phlogopite 1157 | pauperised 1158 | presupport 1159 | nonarrival 1160 | defeminize 1161 | capitation 1162 | maximilian 1163 | antibiotic 1164 | channeller 1165 | deiformity 1166 | eyewitness 1167 | razzmatazz 1168 | expatriate 1169 | simulation 1170 | renotation 1171 | spermaceti 1172 | hypodermal 1173 | readoption 1174 | hambroline 1175 | gentlehood 1176 | noctilucan 1177 | magnetizer 1178 | proscriber 1179 | radiosonde 1180 | clownishly 1181 | xenophanes 1182 | repraising 1183 | naturalist 1184 | shotgunned 1185 | apopemptic 1186 | duplicator 1187 | obeliskoid 1188 | pickpocket 1189 | turpentine 1190 | deforciant 1191 | hemizygote 1192 | cantaloupe 1193 | streakedly 1194 | mediatised 1195 | revilingly 1196 | guachamole 1197 | tenderfoot 1198 | unreversed 1199 | martensite 1200 | bannisters 1201 | antichrist 1202 | supposedly 1203 | consistory 1204 | imposthume 1205 | prerailway 1206 | fleshiness 1207 | gonopodium 1208 | sniffiness 1209 | triskelion 1210 | unitemized 1211 | judicially 1212 | nyctalopia 1213 | girderless 1214 | carabineer 1215 | seferiades 1216 | archaizing 1217 | bonhoeffer 1218 | persecutor 1219 | windsucker 1220 | pouncingly 1221 | outscoring 1222 | brickmaker 1223 | undershoot 1224 | acarpelous 1225 | crashingly 1226 | gymnosophy 1227 | serviceman 1228 | unresolved 1229 | henotheism 1230 | tetrarchic 1231 | unstrident 1232 | panegyrize 1233 | matrilocal 1234 | modernness 1235 | overscored 1236 | valerianic 1237 | predoubter 1238 | herakleion 1239 | unreferred 1240 | outchatter 1241 | nonsensory 1242 | homologate 1243 | condescend 1244 | leftwardly 1245 | chockstone 1246 | sermonized 1247 | menshevist 1248 | assignably 1249 | unsociable 1250 | harborward 1251 | recappable 1252 | hovertrain 1253 | pyrochlore 1254 | crystaling 1255 | fishmonger 1256 | ineloquent 1257 | provitamin 1258 | undeniable 1259 | portsmouth 1260 | mesitylene 1261 | bandinelli 1262 | disenthral 1263 | prenatural 1264 | unswathing 1265 | reserviced 1266 | helicoidal 1267 | resolution 1268 | jacksonism 1269 | carburetor 1270 | audiogenic 1271 | pleximetry 1272 | nonbuoyant 1273 | nephridial 1274 | carpsucker 1275 | beaujolais 1276 | balladised 1277 | compositor 1278 | considerer 1279 | dragsawing 1280 | falconnoid 1281 | crenulated 1282 | perversion 1283 | everything 1284 | turnverein 1285 | negativing 1286 | guggenheim 1287 | yesteryear 1288 | unslacking 1289 | sufflation 1290 | draughtier 1291 | hypogeusia 1292 | belwhopped 1293 | rectifying 1294 | castellany 1295 | villanelle 1296 | metaplasia 1297 | silverware 1298 | mercantile 1299 | palermitan 1300 | girlfriend 1301 | carbonised 1302 | allodially 1303 | minnesotan 1304 | troglodyte 1305 | spiritless 1306 | needlework 1307 | unpunished 1308 | predispute 1309 | antipapism 1310 | divergence 1311 | eisenhower 1312 | unreformed 1313 | egyptology 1314 | preknowing 1315 | glagolitic 1316 | flashiness 1317 | labilizing 1318 | lombrosian 1319 | acetylized 1320 | rawsthorne 1321 | liquidator 1322 | haematinic 1323 | spotlessly 1324 | thioacetic 1325 | antitoxine 1326 | castleford 1327 | plexiglass 1328 | undefensed 1329 | crammingly 1330 | formatting 1331 | unbankable 1332 | pinnulated 1333 | grandstand 1334 | relativise 1335 | butcheries 1336 | fluoresced 1337 | nonradiant 1338 | superstage 1339 | gnosticise 1340 | disfigurer 1341 | woefulness 1342 | bernouilli 1343 | crispbread 1344 | understrap 1345 | gunrunning 1346 | unassigned 1347 | interstice 1348 | tendrillar 1349 | reunionist 1350 | ungodliest 1351 | spirograph 1352 | footlocker 1353 | lamentable 1354 | documental 1355 | desecrator 1356 | emmetropic 1357 | nitrometer 1358 | silhouette 1359 | glancingly 1360 | preimposed 1361 | bolshevist 1362 | norristown 1363 | barbershop 1364 | untruckled 1365 | scutellate 1366 | sternwards 1367 | capturable 1368 | reemerging 1369 | pasargadae 1370 | waterproof 1371 | unrambling 1372 | structural 1373 | publicness 1374 | chlorinous 1375 | agallochum 1376 | fingerling 1377 | decelerate 1378 | sizzlingly 1379 | selenodesy 1380 | calaverite 1381 | motordrome 1382 | fescennine 1383 | eruptivity 1384 | prejudiced 1385 | improperly 1386 | hinayanist 1387 | subcaptain 1388 | leichhardt 1389 | palisading 1390 | monorhinal 1391 | aparavidya 1392 | untellable 1393 | unslippery 1394 | unmutinous 1395 | initialled 1396 | adsorbable 1397 | predriving 1398 | fetterlock 1399 | ruminating 1400 | outroguing 1401 | believably 1402 | dolomitise 1403 | contactual 1404 | roughrider 1405 | crosscheck 1406 | undertaxed 1407 | haemoblast 1408 | detectable 1409 | planoblast 1410 | quodlibetz 1411 | subminimal 1412 | plattensee 1413 | preconsent 1414 | throughway 1415 | uninfusive 1416 | laterality 1417 | noninduced 1418 | trichotomy 1419 | recognizor 1420 | suprarenal 1421 | ticklishly 1422 | epicondyle 1423 | occidental 1424 | checkmated 1425 | bannerlike 1426 | flusterate 1427 | plagiarism 1428 | uncallused 1429 | relativism 1430 | nonspecial 1431 | footnoting 1432 | luxembourg 1433 | idolatrise 1434 | hemikaryon 1435 | analytique 1436 | nonorganic 1437 | underbough 1438 | turkmenian 1439 | leisurable 1440 | geodesical 1441 | corticated 1442 | detestable 1443 | excusingly 1444 | lilienthal 1445 | helioscope 1446 | leptospira 1447 | prerejoice 1448 | asyntactic 1449 | appointive 1450 | seminormal 1451 | viviparism 1452 | portliness 1453 | intertrigo 1454 | calcifying 1455 | nontaxable 1456 | pyrrhotite 1457 | foundation 1458 | flourisher 1459 | petrogenic 1460 | snakestone 1461 | reproclaim 1462 | solifidian 1463 | evolvement 1464 | evangelism 1465 | anticyclic 1466 | temporiser 1467 | colascione 1468 | nonradiant 1469 | chauffeuse 1470 | paralleled 1471 | phallicist 1472 | tallyhoing 1473 | cataclinal 1474 | statampere 1475 | dissatisfy 1476 | decollated 1477 | normalised 1478 | femininity 1479 | paynimhood 1480 | bestriding 1481 | accelerant 1482 | cittticano 1483 | scriptural 1484 | deformedly 1485 | polymerism 1486 | capreolate 1487 | prevetoing 1488 | affirmable 1489 | dilettanti 1490 | stanchless 1491 | farforthly 1492 | horselaugh 1493 | unreceding 1494 | hurryingly 1495 | figurehead 1496 | obscuredly 1497 | hyacinthin 1498 | expatriate 1499 | impaneling 1500 | perishable 1501 | farcically 1502 | parchingly 1503 | unpermeant 1504 | nouakchott 1505 | imbitterer 1506 | unallotted 1507 | mignonette 1508 | unsheathed 1509 | trihydrate 1510 | besottedly 1511 | underrealm 1512 | preacidity 1513 | stagnating 1514 | oldfangled 1515 | negritised 1516 | mucronated 1517 | siderolite 1518 | scratchier 1519 | percentile 1520 | nephridial 1521 | prejustify 1522 | prefrontal 1523 | accessibly 1524 | undertribe 1525 | websterian 1526 | parlormaid 1527 | plagiarize 1528 | flavescent 1529 | squareness 1530 | unlaunched 1531 | hiccupping 1532 | corelative 1533 | profascism 1534 | unhuskable 1535 | unrebutted 1536 | bastardize 1537 | underbough 1538 | morpholine 1539 | prealluded 1540 | coyishness 1541 | alphabetic 1542 | cryogenics 1543 | vaporizing 1544 | reflexness 1545 | resentment 1546 | leprechaun 1547 | noneatable 1548 | restringer 1549 | cylindroma 1550 | outbragged 1551 | stabbingly 1552 | unexceeded 1553 | similitude 1554 | weathering 1555 | outwriting 1556 | mitigative 1557 | sanctitude 1558 | strychnine 1559 | marvellous 1560 | homogonous 1561 | unpointing 1562 | telephoned 1563 | cartwright 1564 | breeziness 1565 | tigerishly 1566 | enthusiasm 1567 | precognize 1568 | untrenched 1569 | celebesian 1570 | urogenital 1571 | silverware 1572 | doctorship 1573 | absorbency 1574 | unprovided 1575 | oppression 1576 | colascione 1577 | timoshenko 1578 | cismontane 1579 | scotticism 1580 | gratinated 1581 | unbackward 1582 | galleylike 1583 | rededicate 1584 | calenderer 1585 | stuccowork 1586 | hydroponic 1587 | accursedly 1588 | synoecious 1589 | chatoyancy 1590 | eximiously 1591 | khitmatgar 1592 | nonbreeder 1593 | interloper 1594 | taperingly 1595 | untuneable 1596 | unpolished 1597 | corpulence 1598 | dominative 1599 | achromatic 1600 | asphyxiant 1601 | retelevise 1602 | shorewards 1603 | chloroform 1604 | bowdlerise 1605 | antanarivo 1606 | pentimento 1607 | australorp 1608 | unfinished 1609 | auctioneer 1610 | mordacious 1611 | rhumbatron 1612 | undercrier 1613 | stabilizer 1614 | pozzuolana 1615 | smoothness 1616 | reexpelled 1617 | coactively 1618 | critically 1619 | huntingdon 1620 | unjewelled 1621 | flakeboard 1622 | bluejacket 1623 | unvalorous 1624 | everywhere 1625 | suffragist 1626 | unwithered 1627 | interweave 1628 | dysgraphia 1629 | semilunate 1630 | leaderless 1631 | middelburg 1632 | larvicidal 1633 | outpricing 1634 | semeiology 1635 | hydrophily 1636 | semaphored 1637 | breakwater 1638 | pathogenic 1639 | enstatitic 1640 | misframing 1641 | sherardize 1642 | shabbiness 1643 | sarcophile 1644 | predislike 1645 | fleeciness 1646 | speciosity 1647 | complexity 1648 | aubergiste 1649 | outjutting 1650 | laboristic 1651 | tiebreaker 1652 | bolshevize 1653 | acuminated 1654 | remultiply 1655 | gargantuan 1656 | semipostal 1657 | aspidistra 1658 | phoniatric 1659 | deracinate 1660 | unrepelled 1661 | nucleating 1662 | pemphigoid 1663 | heidenstam 1664 | peptonised 1665 | trusteeing 1666 | grimaldian 1667 | cyclopedia 1668 | exurbanite 1669 | theistical 1670 | bibulously 1671 | mediatized 1672 | believably 1673 | prandially 1674 | excitingly 1675 | cyclotomic 1676 | cloddishly 1677 | euphoriant 1678 | pasionaria 1679 | unsmokable 1680 | humidifier 1681 | nonmusical 1682 | dreamfully 1683 | misleading 1684 | applicably 1685 | fussbudget 1686 | quadrantes 1687 | narcomania 1688 | cancrizans 1689 | deontology 1690 | emmetropia 1691 | stratiform 1692 | reinvading 1693 | contravene 1694 | lysenkoism 1695 | logography 1696 | gelatinate 1697 | disproving 1698 | underlimit 1699 | dibasicity 1700 | wallington 1701 | cataractal 1702 | spriggiest 1703 | recogniser 1704 | integrated 1705 | unfoliaged 1706 | draggingly 1707 | unfastener 1708 | nomologist 1709 | intendment 1710 | unyielding 1711 | aureomycin 1712 | woollybutt 1713 | pepperwood 1714 | tabescence 1715 | tenterhook 1716 | coercivity 1717 | strawberry 1718 | confounded 1719 | bacillemia 1720 | corruption 1721 | vernalized 1722 | homagyrius 1723 | nonbreeder 1724 | cytissorus 1725 | succulence 1726 | thioacetic 1727 | evaluation 1728 | hyetograph 1729 | insentient 1730 | unreckoned 1731 | textualist 1732 | undeprived 1733 | distillate 1734 | escalading 1735 | cacodaemon 1736 | lugubrious 1737 | unconfuted 1738 | stentorian 1739 | homebodies 1740 | curatorial 1741 | casseroled 1742 | amiability 1743 | subcordate 1744 | comestible 1745 | horsecloth 1746 | diagraming 1747 | xiphosuran 1748 | hypotactic 1749 | unmournful 1750 | altercated 1751 | necrolatry 1752 | saracenism 1753 | graphalloy 1754 | federation 1755 | tripartite 1756 | fahrenheit 1757 | unripeness 1758 | rumrunning 1759 | consociate 1760 | complainer 1761 | preconceal 1762 | forswearer 1763 | overwarily 1764 | unbiasedly 1765 | homogenate 1766 | polyphonic 1767 | intertidal 1768 | necroscopy 1769 | transgress 1770 | leopardess 1771 | inflatedly 1772 | zoographic 1773 | enolizable 1774 | miamisburg 1775 | affiancing 1776 | intolerant 1777 | bitterling 1778 | attirement 1779 | manchoukuo 1780 | naughtiest 1781 | terrifying 1782 | middlemost 1783 | shipmaster 1784 | greenbrier 1785 | liberation 1786 | secretaire 1787 | slipstream 1788 | amphigouri 1789 | itinerancy 1790 | butterbush 1791 | granulator 1792 | seminaries 1793 | impressure 1794 | outringing 1795 | nonseriate 1796 | chaplainry 1797 | antimasque 1798 | unnumerous 1799 | unablative 1800 | parmigiana 1801 | superfused 1802 | ubermensch 1803 | fetterless 1804 | predicably 1805 | allhallows 1806 | perlucidus 1807 | plagiarize 1808 | inveracity 1809 | laundromat 1810 | uncombated 1811 | department 1812 | birdliming 1813 | nonstorage 1814 | videophone 1815 | subarcuate 1816 | mindszenty 1817 | masterwork 1818 | preexposed 1819 | overrigged 1820 | exhilarate 1821 | anatomizer 1822 | osmaterium 1823 | empathetic 1824 | activation 1825 | nonroyalty 1826 | centipedal 1827 | reinspired 1828 | telpherage 1829 | carcaneted 1830 | grangerism 1831 | meticulous 1832 | heavenward 1833 | transudate 1834 | diactinism 1835 | subjugular 1836 | teletypist 1837 | chatterbox 1838 | platysmata 1839 | recidivate 1840 | amputation 1841 | socketless 1842 | theurgical 1843 | propositus 1844 | arithmetic 1845 | unovercome 1846 | monadistic 1847 | hypolithic 1848 | aerologist 1849 | crapulency 1850 | yonkersite 1851 | studfishes 1852 | complement 1853 | borderland 1854 | pergelisol 1855 | jacobitish 1856 | nonvoluble 1857 | geophysics 1858 | suspensive 1859 | misperform 1860 | episodical 1861 | chapfallen 1862 | piliferous 1863 | nonscience 1864 | boswellism 1865 | counterman 1866 | pulpitless 1867 | adipopexis 1868 | pillowslip 1869 | lambrequin 1870 | sequential 1871 | carmichael 1872 | unexpelled 1873 | glauconite 1874 | carpetweed 1875 | rubiaceous 1876 | luluabourg 1877 | contracted 1878 | outbarring 1879 | platoniser 1880 | pittsfield 1881 | silverizer 1882 | radiolysis 1883 | capability 1884 | apocopated 1885 | unprecious 1886 | harassable 1887 | subtiliser 1888 | victimiser 1889 | arciniegas 1890 | unspecious 1891 | unfocussed 1892 | unshadowed 1893 | capetonian 1894 | underyield 1895 | obturation 1896 | greediness 1897 | reviewable 1898 | unliveable 1899 | testifying 1900 | pretelling 1901 | fleshliest 1902 | jinrikisha 1903 | familistic 1904 | plasmosome 1905 | exhibitory 1906 | submeaning 1907 | execrative 1908 | detruncate 1909 | organicity 1910 | prerelease 1911 | appeasable 1912 | slipstream 1913 | prandially 1914 | apterygote 1915 | viniferous 1916 | diadochian 1917 | patroniser 1918 | importuned 1919 | heptarchic 1920 | surcharger 1921 | potamology 1922 | triturated 1923 | dynamitist 1924 | excitement 1925 | personator 1926 | frigidaria 1927 | mortifying 1928 | involutely 1929 | pressboard 1930 | orchiditis 1931 | morbifical 1932 | clabularia 1933 | semiglazed 1934 | woodcutter 1935 | postdating 1936 | heathenish 1937 | fortifying 1938 | cordiality 1939 | exonerated 1940 | springtide 1941 | pacificism 1942 | flapdragon 1943 | localising 1944 | enumerated 1945 | coralberry 1946 | preconvict 1947 | needlelike 1948 | expurgated 1949 | sulphurate 1950 | impregnate 1951 | amoebocyte 1952 | paramaribo 1953 | platinised 1954 | undernurse 1955 | chrysippus 1956 | rethreaten 1957 | improvably 1958 | musicology 1959 | hybridised 1960 | ariovistus 1961 | curatorial 1962 | seismology 1963 | holohedral 1964 | ascariasis 1965 | benzocaine 1966 | epineurial 1967 | anglistics 1968 | unrumoured 1969 | thermistor 1970 | unflexible 1971 | reperusing 1972 | sultanlike 1973 | unsmoothed 1974 | maimedness 1975 | tortellini 1976 | unsickerly 1977 | unassuring 1978 | turkophile 1979 | designator 1980 | bosporanic 1981 | acidogenic 1982 | horridness 1983 | washerless 1984 | unjewelled 1985 | snakestone 1986 | unbearable 1987 | detachment 1988 | dystrophia 1989 | aspiratory 1990 | barebacked 1991 | nonvoluble 1992 | pernambuco 1993 | maudlinism 1994 | germanized 1995 | subterfuge 1996 | illiteracy 1997 | preinherit 1998 | curarizing 1999 | indirectly 2000 | economized 2001 | gallicised 2002 | garnierite 2003 | journalize 2004 | unaspersed 2005 | acidometer 2006 | unaccurate 2007 | liquidized 2008 | fetchingly 2009 | gouverneur 2010 | derogating 2011 | glacialist 2012 | lesbianism 2013 | salmagundi 2014 | rhizomorph 2015 | mollescent 2016 | fricasseed 2017 | laloplegia 2018 | diathermic 2019 | sublighted 2020 | nonsensual 2021 | tcherepnin 2022 | eventuated 2023 | graecising 2024 | muddlehead 2025 | pulveriser 2026 | undeadened 2027 | nonstriped 2028 | oceanicity 2029 | excitation 2030 | gigasecond 2031 | proselyter 2032 | acanthosis 2033 | linecaster 2034 | subsessile 2035 | throughout 2036 | dicoumarol 2037 | unplayable 2038 | unswingled 2039 | heartbreak 2040 | predietary 2041 | pregenital 2042 | sociometry 2043 | hypothetic 2044 | actomyosin 2045 | unmythical 2046 | scornfully 2047 | watchtower 2048 | ratskeller 2049 | acromicria 2050 | variolitic 2051 | persephone 2052 | tachymetry 2053 | undeviable 2054 | governance 2055 | waterfront 2056 | simulacrum 2057 | tittivated 2058 | positivism 2059 | noncogency 2060 | cloudberry 2061 | navigating 2062 | monandrous 2063 | eskilstuna 2064 | adjustable 2065 | dreikanter 2066 | controller 2067 | dysenteric 2068 | ectocornea 2069 | hyporchema 2070 | consuetude 2071 | outchasing 2072 | angwantibo 2073 | stomatitic 2074 | normanizer 2075 | proctodeal 2076 | subobscure 2077 | piatigorsk 2078 | anglophobe 2079 | spongingly 2080 | derisively 2081 | ridiculous 2082 | hogarthian 2083 | temporiser 2084 | barbellate 2085 | porphyroid 2086 | palateless 2087 | mohammedan 2088 | prelingual 2089 | gerundival 2090 | illegalize 2091 | barrelfish 2092 | energising 2093 | mystagogic 2094 | stomatopod 2095 | glyoxaline 2096 | insatiable 2097 | resolutely 2098 | catholicus 2099 | emigrating 2100 | bloomfield 2101 | monophobia 2102 | rabbitfish 2103 | miscoinage 2104 | pruriently 2105 | valladolid 2106 | uninsulate 2107 | relapsable 2108 | barkantine 2109 | autumnally 2110 | excerption 2111 | ghastfully 2112 | spumescent 2113 | profoundly 2114 | groundsill 2115 | devoutness 2116 | provitamin 2117 | pilastrade 2118 | parchising 2119 | grizzliest 2120 | synderesis 2121 | racemously 2122 | invigorate 2123 | oleography 2124 | retraction 2125 | vitriolise 2126 | plasmochin 2127 | snottiness 2128 | feebleness 2129 | epigastric 2130 | responsive 2131 | revelatory 2132 | geologized 2133 | winterthur 2134 | reissuable 2135 | proanarchy 2136 | pellucidly 2137 | phenomenal 2138 | unsecretly 2139 | disfavorer 2140 | paperknife 2141 | medication 2142 | antagonism 2143 | unbarreled 2144 | homeopathy 2145 | deoxidizer 2146 | nonscaling 2147 | investable 2148 | achromycin 2149 | splashiest 2150 | afteryears 2151 | suprarenal 2152 | sandbagged 2153 | outwitting 2154 | liberalise 2155 | billfishes 2156 | pupiparous 2157 | goatsbeard 2158 | unevocable 2159 | auriscopic 2160 | couponless 2161 | rubberised 2162 | tesselated 2163 | glairiness 2164 | embroidery 2165 | anisotropy 2166 | undrenched 2167 | piriformis 2168 | impeccance 2169 | concinnous 2170 | adiactinic 2171 | eructative 2172 | syncretise 2173 | nonfertile 2174 | nonblended 2175 | supplejack 2176 | unboastful 2177 | geneticist 2178 | prespecify 2179 | synecdoche 2180 | bundesrath 2181 | abstrusely 2182 | misfortune 2183 | benedictus 2184 | leptosomic 2185 | modernized 2186 | impeccance 2187 | benumbment 2188 | irradiated 2189 | stepparent 2190 | minimising 2191 | preumbonal 2192 | intervisit 2193 | scantiness 2194 | spongocoel 2195 | quaternate 2196 | stagiritic 2197 | corrivalry 2198 | salientian 2199 | royersford 2200 | misapplier 2201 | reseparate 2202 | nondensity 2203 | overactive 2204 | pennsauken 2205 | proafrican 2206 | satyagraha 2207 | twickenham 2208 | toxalbumin 2209 | khrushchev 2210 | kingfishes 2211 | diminutive 2212 | implorable 2213 | snubbingly 2214 | uncombined 2215 | operettist 2216 | bibliotics 2217 | estimating 2218 | unsqueezed 2219 | cottonweed 2220 | pretelling 2221 | prosthesis 2222 | pseudocele 2223 | opposingly 2224 | bemusement 2225 | flashingly 2226 | remultiply 2227 | aesthetics 2228 | uncascaded 2229 | cashmerian 2230 | overstrain 2231 | allomerism 2232 | revampment 2233 | disgruntle 2234 | goldfishes 2235 | convalesce 2236 | larvicidal 2237 | translator 2238 | provitamin 2239 | unbloodily 2240 | infallible 2241 | epexegetic 2242 | unsortable 2243 | changeling 2244 | stridulate 2245 | voluminous 2246 | homogonous 2247 | fianchetto 2248 | antibiosis 2249 | perforable 2250 | monozygous 2251 | wainwright 2252 | delocalize 2253 | staminodia 2254 | tyrannised 2255 | snatchable 2256 | madagascar 2257 | mcreynolds 2258 | untruthful 2259 | strongbark 2260 | formalized 2261 | otoplastic 2262 | wheatgrass 2263 | unmarching 2264 | tremolitic 2265 | nonassault 2266 | unballoted 2267 | nonarrival 2268 | locomotion 2269 | unpartisan 2270 | chevallier 2271 | considered 2272 | inthroning 2273 | registerer 2274 | picrotoxic 2275 | uruguaiana 2276 | mischarged 2277 | binghamton 2278 | stoopingly 2279 | apiculture 2280 | admittance 2281 | septennial 2282 | freckliest 2283 | understate 2284 | stomodaeum 2285 | collimator 2286 | sympathize 2287 | hemostasia 2288 | intendment 2289 | fieldstone 2290 | brandisher 2291 | shampooing 2292 | carboniser 2293 | pocahontas 2294 | partiality 2295 | chitarrone 2296 | predevised 2297 | signalment 2298 | uninherent 2299 | nonchalant 2300 | jadishness 2301 | cruciately 2302 | officiated 2303 | overground 2304 | preentitle 2305 | precocious 2306 | chinchilla 2307 | hambroline 2308 | accessibly 2309 | negligibly 2310 | interceder 2311 | albigenses 2312 | reblending 2313 | brahminist 2314 | picnicking 2315 | zooplastic 2316 | insobriety 2317 | undateable 2318 | subglenoid 2319 | allegorise 2320 | amenorrhea 2321 | syncopated 2322 | firewarden 2323 | catacumbal 2324 | supplicate 2325 | superacute 2326 | sexavalent 2327 | decorating 2328 | matozinhos 2329 | columbiana 2330 | concurring 2331 | enzymology 2332 | buttonbush 2333 | unmarketed 2334 | achaemenes 2335 | unexcepted 2336 | cognizable 2337 | galloglass 2338 | deathwatch 2339 | spirantism 2340 | doubleness 2341 | espadrille 2342 | bludgeoner 2343 | hargreaves 2344 | rectifying 2345 | samothrake 2346 | gynophoric 2347 | arrephoria 2348 | hinterland 2349 | photoflood 2350 | nonaphasic 2351 | backhouses 2352 | lothringen 2353 | numerology 2354 | hypoplasia 2355 | gorgeously 2356 | israelitic 2357 | preinhabit 2358 | ineludibly 2359 | bastnasite 2360 | immiscibly 2361 | dichogamic 2362 | rhapsodise 2363 | nonnebular 2364 | inequality 2365 | immemorial 2366 | doorkeeper 2367 | aromatised 2368 | cryptology 2369 | caracolled 2370 | stereogram 2371 | capetonian 2372 | chilomonas 2373 | unfamiliar 2374 | branchless 2375 | bewitchery 2376 | dissoluble 2377 | rebuffably 2378 | figureless 2379 | sneeringly 2380 | unswarming 2381 | repackaged 2382 | semilucent 2383 | propaganda 2384 | groundling 2385 | compellent 2386 | brokenness 2387 | unrepulsed 2388 | nonvintage 2389 | premedical 2390 | elementary 2391 | worryingly 2392 | appendaged 2393 | membranous 2394 | monohybrid 2395 | cognizable 2396 | cuttlebone 2397 | tachometer 2398 | preholding 2399 | hemophilus 2400 | princeless 2401 | harvardian 2402 | legitimise 2403 | apostatism 2404 | herniotomy 2405 | wolframite 2406 | segregated 2407 | nonerasure 2408 | grillading 2409 | gilbertian 2410 | hecticness 2411 | predeposit 2412 | summariser 2413 | exothermic 2414 | treponemas 2415 | enwrapping 2416 | unscowling 2417 | underframe 2418 | aggregated 2419 | tablecloth 2420 | executable 2421 | unharmonic 2422 | subdeposit 2423 | repacified 2424 | erysipelas 2425 | sclerotium 2426 | unerodable 2427 | headworker 2428 | capacitate 2429 | peptoniser 2430 | moralising 2431 | alternator 2432 | colligated 2433 | implacably 2434 | deathwatch 2435 | comatosely 2436 | onomastics 2437 | alteration 2438 | tendential 2439 | tongueless 2440 | ungrappled 2441 | fulfilling 2442 | preextract 2443 | bladdernut 2444 | macfarlane 2445 | underprize 2446 | manometric 2447 | erzgebirge 2448 | unspending 2449 | sporophore 2450 | elongating 2451 | coloration 2452 | uninsulted 2453 | uncankered 2454 | truistical 2455 | overstrict 2456 | ghostwrote 2457 | megagamete 2458 | heartshake 2459 | azerbaijan 2460 | armageddon 2461 | pulpitless 2462 | overpruned 2463 | legitimize 2464 | colonising 2465 | reliefless 2466 | dermotherm 2467 | glossmeter 2468 | irrational 2469 | distrainee 2470 | nicotinism 2471 | colchester 2472 | galvanised 2473 | sarmentose 2474 | gaucheness 2475 | alteration 2476 | tactlessly 2477 | innumerate 2478 | inaptitude 2479 | tinselling 2480 | astringing 2481 | arpeggioed 2482 | difference 2483 | battleship 2484 | triglyphic 2485 | systemiser 2486 | sophrosyne 2487 | experience 2488 | komsomolsk 2489 | cowpuncher 2490 | dekadrachm 2491 | rearranged 2492 | doubtfully 2493 | unventured 2494 | itinerated 2495 | plasmochin 2496 | subvillain 2497 | sustention 2498 | gorgonized 2499 | chargeless 2500 | concoctive 2501 | timoshenko 2502 | detestably 2503 | uninterred 2504 | cleverness 2505 | anticipant 2506 | unjustness 2507 | bondswoman 2508 | notionless 2509 | glycopexis 2510 | sportively 2511 | subvention 2512 | juneteenth 2513 | rheumatics 2514 | teleostean 2515 | hylotheism 2516 | vendettist 2517 | sagittally 2518 | underprize 2519 | enrollment 2520 | decadently 2521 | stalactite 2522 | vitelluses 2523 | transposed 2524 | mystifying 2525 | hemiplegic 2526 | acosmistic 2527 | sphericity 2528 | disgorging 2529 | tramontana 2530 | pianissimo 2531 | effectible 2532 | hagiocracy 2533 | preexecute 2534 | tritanopic 2535 | unstonable 2536 | unciteable 2537 | plasticine 2538 | unfestered 2539 | stunningly 2540 | redelivery 2541 | overexpand 2542 | saltcellar 2543 | ringhalses 2544 | uninformed 2545 | clarabella 2546 | exsiccator 2547 | macadamise 2548 | peddleries 2549 | untapering 2550 | nonaligned 2551 | catnapping 2552 | overreduce 2553 | emancipist 2554 | thunderous 2555 | preimposed 2556 | micronesia 2557 | piccaninny 2558 | bootloader 2559 | nonsubtile 2560 | tetrabasic 2561 | untentered 2562 | braggartly 2563 | flabellate 2564 | princelier 2565 | preincline 2566 | cedarhurst 2567 | cockleboat 2568 | albuminize 2569 | bannisters 2570 | jadotville 2571 | hypolimnia 2572 | malleation 2573 | stringendo 2574 | centrality 2575 | cretaceous 2576 | giovannida 2577 | pontypridd 2578 | filtrating 2579 | plasmolyze 2580 | elongative 2581 | bisulphide 2582 | nonsummons 2583 | archiplasm 2584 | cheliceral 2585 | undeducted 2586 | overthrust 2587 | outhearing 2588 | redivorced 2589 | soniferous 2590 | superdural 2591 | housewares 2592 | annullable 2593 | metrizable 2594 | hildebrand 2595 | unpacified 2596 | qualifying 2597 | specialism 2598 | nongrained 2599 | dispassion 2600 | calciminer 2601 | unculpable 2602 | harmlessly 2603 | synteresis 2604 | colossally 2605 | seersucker 2606 | rotational 2607 | leeuwarden 2608 | emblazonry 2609 | preadmirer 2610 | unreckoned 2611 | profaculty 2612 | defacement 2613 | overcredit 2614 | swearingly 2615 | acetylated 2616 | authorship 2617 | predeceive 2618 | undilating 2619 | rethinking 2620 | contingent 2621 | harborward 2622 | phanerogam 2623 | caravaning 2624 | nonallelic 2625 | sanctitude 2626 | weimaraner 2627 | phytocidal 2628 | uneducable 2629 | crosscheck 2630 | dehumidify 2631 | nonmelodic 2632 | kalimantan 2633 | nightstand 2634 | nonmedical 2635 | phonetical 2636 | spotlessly 2637 | renotified 2638 | unbeholden 2639 | hobnobbing 2640 | clockmaker 2641 | mistassini 2642 | prehominid 2643 | dilemmatic 2644 | quadrating 2645 | upbringing 2646 | lopatnikov 2647 | maculation 2648 | escapingly 2649 | unscolding 2650 | outdeiling 2651 | uniformize 2652 | diorthosis 2653 | angwantibo 2654 | unperverse 2655 | buttonhole 2656 | pleximeter 2657 | background 2658 | reconvened 2659 | underdried 2660 | ectophytic 2661 | economiser 2662 | markedness 2663 | palilicium 2664 | homoeopath 2665 | bumblingly 2666 | admiringly 2667 | gangliform 2668 | spongeless 2669 | granulitic 2670 | larksville 2671 | chesterton 2672 | decrepitly 2673 | suberising 2674 | unwreathed 2675 | orbiculate 2676 | dermoptera 2677 | montgomery 2678 | unsurmised 2679 | adjectival 2680 | collielike 2681 | thereunder 2682 | unmothered 2683 | prolocutor 2684 | vindicated 2685 | outcaviled 2686 | regreasing 2687 | syndicship 2688 | lincolnian 2689 | goalkeeper 2690 | propositus 2691 | improvised 2692 | formulizer 2693 | caqueteuse 2694 | outcaroled 2695 | precyclone 2696 | arrephoria 2697 | blitzkrieg 2698 | moroseness 2699 | nonassumed 2700 | bestridden 2701 | mulligrubs 2702 | unspeckled 2703 | unfletched 2704 | gravitater 2705 | indonesian 2706 | unsnaffled 2707 | dishonesty 2708 | footnoting 2709 | leprosaria 2710 | replanning 2711 | annexation 2712 | promiseful 2713 | denominate 2714 | tantamount 2715 | embroidery 2716 | douspacing 2717 | subscleral 2718 | complotter 2719 | thrushlike 2720 | scutellate 2721 | puerperium 2722 | unsavorily 2723 | determiner 2724 | calescence 2725 | baptistery 2726 | untaciturn 2727 | overgentle 2728 | revilingly 2729 | kazazachki 2730 | unmailable 2731 | stitchlike 2732 | chelicerae 2733 | chromatoid 2734 | andalusite 2735 | unintruded 2736 | silkscreen 2737 | sinfulness 2738 | menckenian 2739 | leprechaun 2740 | stenotopic 2741 | caretaking 2742 | culinarian 2743 | civilising 2744 | insecurity 2745 | grooveless 2746 | intrepidly 2747 | ommatidium 2748 | cottontail 2749 | gynophoric 2750 | simoniacal 2751 | farforthly 2752 | lengthwise 2753 | fahrenheit 2754 | admittable 2755 | astromancy 2756 | hypnologic 2757 | novobiocin 2758 | hemochrome 2759 | maidenhead 2760 | wunderkind 2761 | doctorship 2762 | sicklebill 2763 | nonfascist 2764 | arbalester 2765 | unpenciled 2766 | nonscoring 2767 | undreading 2768 | unshouting 2769 | separatrix 2770 | hymeneally 2771 | cinderlike 2772 | nonuseable 2773 | flocculant 2774 | brutalised 2775 | colchester 2776 | instigated 2777 | impassably 2778 | pulverable 2779 | oversubtle 2780 | artesonado 2781 | pirouetted 2782 | accidental 2783 | clinometry 2784 | exaggerate 2785 | undercurve 2786 | epileptoid 2787 | rhizogenic 2788 | weightedly 2789 | undiseased 2790 | bricklayer 2791 | masterwork 2792 | unamending 2793 | convulsive 2794 | epeirogeny 2795 | germinated 2796 | potamogale 2797 | grangerize 2798 | inactivity 2799 | costarring 2800 | histolysis 2801 | bluebonnet 2802 | deciduitis 2803 | haemophile 2804 | unbluffing 2805 | untragical 2806 | winklehawk 2807 | marvellous 2808 | backsheesh 2809 | brocatelle 2810 | channelled 2811 | ordainable 2812 | barysphere 2813 | blastomata 2814 | phenolated 2815 | unarguable 2816 | preearthly 2817 | disparaged 2818 | twinflower 2819 | bluetongue 2820 | trasentine 2821 | maleficent 2822 | patisserie 2823 | glistening 2824 | ossiferous 2825 | underplain 2826 | vendmiaire 2827 | subtiliser 2828 | pedimented 2829 | unlathered 2830 | repugnancy 2831 | undertided 2832 | nonnasally 2833 | explicitly 2834 | inshrining 2835 | sandalling 2836 | denouncing 2837 | pluralizer 2838 | transposal 2839 | interchase 2840 | overruling 2841 | freakiness 2842 | photophily 2843 | palinodist 2844 | epineurium 2845 | lignocaine 2846 | terrorised 2847 | guayaberas 2848 | synthetise 2849 | subaqueous 2850 | sharpsburg 2851 | purtenance 2852 | verkrampte 2853 | unejective 2854 | flashiness 2855 | occultness 2856 | epicentrum 2857 | fetterlock 2858 | nonemanant 2859 | tachymeter 2860 | maupassant 2861 | adenovirus 2862 | unbuttered 2863 | confidante 2864 | malthusian 2865 | unbestowed 2866 | titivating 2867 | resplicing 2868 | subfoliate 2869 | precloacal 2870 | churchiest 2871 | unrewarded 2872 | drivelling 2873 | panegyrise 2874 | princelier 2875 | unrefining 2876 | excrescent 2877 | hatshepset 2878 | cumbersome 2879 | unbesought 2880 | heterodoxy 2881 | seasonless 2882 | indonesian 2883 | dichogamic 2884 | admittible 2885 | cystoscope 2886 | syndetical 2887 | indocility 2888 | acephalous 2889 | resolutive 2890 | articulate 2891 | ossiferous 2892 | helicoidal 2893 | aesthetics 2894 | butlerlike 2895 | centonical 2896 | anchesmius 2897 | ethnogenic 2898 | traumatise 2899 | governance 2900 | explicitly 2901 | cystectomy 2902 | hitchhiked 2903 | vitriolize 2904 | celebrater 2905 | zoomorphic 2906 | turkophobe 2907 | neuropathy 2908 | resituated 2909 | teetotally 2910 | thingumbob 2911 | diskophile 2912 | adrenergic 2913 | forcefully 2914 | applausive 2915 | friendless 2916 | plasticity 2917 | cultivator 2918 | unchivalry 2919 | unturnable 2920 | actualized 2921 | necrotized 2922 | aethelbert 2923 | futureless 2924 | capablanca 2925 | friskiness 2926 | homogenise 2927 | umbiliform 2928 | vignetting 2929 | trajection 2930 | rebiddable 2931 | hazelbelle 2932 | brightwork 2933 | provincial 2934 | unhuskable 2935 | antifreeze 2936 | additional 2937 | sufflation 2938 | pluperfect 2939 | deplorably 2940 | providable 2941 | cooperated 2942 | tearjerker 2943 | apostatize 2944 | commonweal 2945 | ingestible 2946 | fontanelle 2947 | unallotted 2948 | relegating 2949 | tuffaceous 2950 | quantizing 2951 | quadrature 2952 | tyrannised 2953 | semipublic 2954 | marionette 2955 | duodecagon 2956 | unmirthful 2957 | turkmenian 2958 | hereabouts 2959 | unanointed 2960 | reelevated 2961 | sestertium 2962 | stereobate 2963 | unrepelled 2964 | rotatively 2965 | strainless 2966 | seasonally 2967 | leverhulme 2968 | iatrogenic 2969 | misgauging 2970 | subcalibre 2971 | debauchery 2972 | cumberment 2973 | appareling 2974 | preenforce 2975 | peroxidase 2976 | veneration 2977 | unreticent 2978 | rouletting 2979 | unilingual 2980 | uxorilocal 2981 | olympiadic 2982 | sensuality 2983 | cauliflory 2984 | menstruums 2985 | revivified 2986 | omophagist 2987 | protractor 2988 | blouselike 2989 | louisbourg 2990 | dilettante 2991 | overdearly 2992 | hygrograph 2993 | bearbaiter 2994 | reacquired 2995 | interceder 2996 | decomposer 2997 | abominator 2998 | dianthuses 2999 | overhearer 3000 | odontology 3001 | amateurish 3002 | handsomest 3003 | highbrowed 3004 | landlubber 3005 | intrastate 3006 | nonwalking 3007 | punctually 3008 | calyciform 3009 | immanently 3010 | preserving 3011 | preprofess 3012 | bibliogony 3013 | subvisible 3014 | lethbridge 3015 | attainable 3016 | ethereally 3017 | barehanded 3018 | supportive 3019 | hyphenated 3020 | unyielding 3021 | insociably 3022 | pyogenesis 3023 | subovarian 3024 | parentalia 3025 | stalagmite 3026 | capriccios 3027 | unexcluded 3028 | unemergent 3029 | africanise 3030 | unnarrowed 3031 | manageable 3032 | undercover 3033 | unprofound 3034 | unfiltered 3035 | diagnosing 3036 | pomiferous 3037 | nightrider 3038 | haleyville 3039 | glaciology 3040 | potbellied 3041 | eruptivity 3042 | bunchberry 3043 | modulating 3044 | worryingly 3045 | unroutable 3046 | plagiarist 3047 | daugavpils 3048 | cruisingly 3049 | heterogony 3050 | superlucky 3051 | unradiated 3052 | busybodies 3053 | adulteress 3054 | synostosis 3055 | melodizing 3056 | zinckenite 3057 | -------------------------------------------------------------------------------- /assets/vpc/nat_monitor.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # This script will monitor another NAT instance and take over its routes 3 | # if communication with the other instance fails 4 | 5 | # NAT instance variables 6 | # Other instance's IP to ping and route to grab if other node goes down 7 | NAT_ID="$1" 8 | NAT_RT_ID="$2" 9 | 10 | # My route to grab when I come back up 11 | My_RT_ID="$3" 12 | 13 | # Specify the EC2 region that this will be running in (e.g. https://ec2.us-east-1.amazonaws.com) 14 | EC2_URL="$4" 15 | 16 | # Health Check variables 17 | Num_Pings=3 18 | Ping_Timeout=1 19 | Wait_Between_Pings=2 20 | Wait_for_Instance_Stop=60 21 | Wait_for_Instance_Start=300 22 | 23 | # Run aws-apitools-common.sh to set up default environment variables and to 24 | # leverage AWS security credentials provided by EC2 roles 25 | . /etc/profile.d/aws-apitools-common.sh 26 | 27 | # Determine the NAT instance private IP so we can ping the other NAT instance, take over 28 | # its route, and reboot it. Requires EC2 DescribeInstances, ReplaceRoute, and Start/RebootInstances 29 | # permissions. The following example EC2 Roles policy will authorize these commands: 30 | # { 31 | # "Statement": [ 32 | # { 33 | # "Action": [ 34 | # "ec2:DescribeInstances", 35 | # "ec2:CreateRoute", 36 | # "ec2:ReplaceRoute", 37 | # "ec2:StartInstances", 38 | # "ec2:StopInstances" 39 | # ], 40 | # "Effect": "Allow", 41 | # "Resource": "*" 42 | # } 43 | # ] 44 | # } 45 | 46 | # Get this instance's ID 47 | Instance_ID=`/usr/bin/curl --silent http://169.254.169.254/latest/meta-data/instance-id` 48 | # Get the other NAT instance's IP 49 | NAT_IP=`/opt/aws/bin/ec2-describe-instances $NAT_ID -U $EC2_URL | grep PRIVATEIPADDRESS -m 1 | awk '{print $2;}'` 50 | 51 | echo `date` "-- Starting NAT monitor" 52 | echo `date` "-- Adding this instance to $My_RT_ID default route on start" 53 | /opt/aws/bin/ec2-replace-route $My_RT_ID -r 0.0.0.0/0 -i $Instance_ID -U $EC2_URL 54 | # If replace-route failed, then the route might not exist and may need to be created instead 55 | if [ "$?" != "0" ]; then 56 | /opt/aws/bin/ec2-create-route $My_RT_ID -r 0.0.0.0/0 -i $Instance_ID -U $EC2_URL 57 | fi 58 | 59 | while [ . ]; do 60 | # Check health of other NAT instance 61 | pingresult=`ping -c $Num_Pings -W $Ping_Timeout $NAT_IP | grep time= | wc -l` 62 | # Check to see if any of the health checks succeeded, if not 63 | if [ "$pingresult" == "0" ]; then 64 | # Set HEALTHY variables to unhealthy (0) 65 | ROUTE_HEALTHY=0 66 | NAT_HEALTHY=0 67 | STOPPING_NAT=0 68 | while [ "$NAT_HEALTHY" == "0" ]; do 69 | # NAT instance is unhealthy, loop while we try to fix it 70 | if [ "$ROUTE_HEALTHY" == "0" ]; then 71 | echo `date` "-- Other NAT heartbeat failed, taking over $NAT_RT_ID default route" 72 | /opt/aws/bin/ec2-replace-route $NAT_RT_ID -r 0.0.0.0/0 -i $Instance_ID -U $EC2_URL 73 | ROUTE_HEALTHY=1 74 | fi 75 | # Check NAT state to see if we should stop it or start it again 76 | # This sample script works well with EC2 API tools version 1.6.12.2 2013-10-15. If you are using a different version and your script is stuck at NAT_STATE, please modify the script to "print $5;" instead of "print $4;". 77 | NAT_STATE=`/opt/aws/bin/ec2-describe-instances $NAT_ID -U $EC2_URL | grep INSTANCE | awk '{print $5}'` 78 | if [ "$NAT_STATE" == "stopped" ]; then 79 | echo `date` "-- Other NAT instance stopped, starting it back up" 80 | /opt/aws/bin/ec2-start-instances $NAT_ID -U $EC2_URL 81 | NAT_HEALTHY=1 82 | sleep $Wait_for_Instance_Start 83 | else 84 | if [ "$STOPPING_NAT" == "0" ]; then 85 | echo `date` "-- Other NAT instance $NAT_STATE, attempting to stop for reboot" 86 | /opt/aws/bin/ec2-stop-instances $NAT_ID -U $EC2_URL 87 | STOPPING_NAT=1 88 | fi 89 | sleep $Wait_for_Instance_Stop 90 | fi 91 | done 92 | else 93 | sleep $Wait_Between_Pings 94 | fi 95 | done 96 | -------------------------------------------------------------------------------- /assets/vpc/user-data-nat.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -v 2 | # set up ha nat monitoring 3 | # read command line arguments 4 | other_route_table="$1" 5 | my_route_table="$2" 6 | aws_region="$3" 7 | nat_monitor_bucket="$4" 8 | 9 | ec2_url="https://ec2.${aws_region}.amazonaws.com" 10 | 11 | # Configure iptables 12 | /sbin/iptables -t nat -A POSTROUTING -o eth0 -s 0.0.0.0/0 -j MASQUERADE 13 | /sbin/iptables-save > /etc/sysconfig/iptables 14 | # Configure ip forwarding and redirects 15 | echo 1 > /proc/sys/net/ipv4/ip_forward && echo 0 > /proc/sys/net/ipv4/conf/eth0/send_redirects 16 | mkdir -p /etc/sysctl.d/ 17 | cat < /etc/sysctl.d/nat.conf 18 | net.ipv4.ip_forward = 1 19 | net.ipv4.conf.eth0.send_redirects = 0 20 | EOF 21 | # Get ID of other NAT 22 | NAT_ID= 23 | # CloudFormation should have updated the other route table by now (due to yum update), however loop to make sure 24 | while [ -z "$NAT_ID" ]; do 25 | sleep 60 26 | NAT_ID=`/opt/aws/bin/ec2-describe-route-tables "$other_route_table" -U "$ec2_url" | awk '/0.0.0.0\/0/ {print $2}'` 27 | done 28 | # Download nat_monitor.sh and configure 29 | aws s3 cp "s3://$nat_monitor_bucket/nat_monitor.sh" /root/nat_monitor.sh 30 | nat_monitor="/bin/bash /root/nat_monitor.sh $NAT_ID $other_route_table $my_route_table $ec2_url" 31 | echo "@reboot $nat_monitor > /tmp/nat_monitor.log" | crontab 32 | $nat_monitor >> /tmp/nat_monitor.log & 33 | #### 20141202 - added to provide traffic logging 34 | ## Enable logging of this userdata script for review post build 35 | exec > >(tee /var/log/user-data.log | logger -t user-data -s 2>/dev/console) 2>&1 36 | ##Tell Rsyslog to log all Netfilter traffic to its own file 37 | echo ':msg, contains, "NETFILTER" /var/log/iptables.log' >>/etc/rsyslog.conf 38 | echo ':msg, contains, "NETFILTER" ~' >>/etc/rsyslog.conf 39 | ##Restart rsyslog 40 | service rsyslog restart 41 | ##Create log rotation for connection logging 42 | cat > /etc/logrotate.d/iptables << EOF 43 | /var/log/iptables.log { 44 | missingok 45 | notifempty 46 | compress 47 | size 20k 48 | daily 49 | rotate 28 50 | create 0600 root root 51 | } 52 | EOF 53 | ##Stop IPtables if started 54 | service iptables stop 55 | ##Backup current IPtables 56 | cp /etc/sysconfig/iptables /etc/sysconfig/iptables.bkup 57 | ##Start IP Tables 58 | service iptables start 59 | ##Clear all current rules 60 | iptables --flush 61 | ##Enable logging on all new connections inbound and outbound 62 | iptables -I INPUT -m state --state NEW -j LOG --log-prefix "NETFILTER" 63 | iptables -I OUTPUT -m state --state NEW -j LOG --log-prefix "NETFILTER" 64 | ##Save our IPtables rules to persist reboot 65 | service iptables save 66 | #### 20141202 - added to provide traffic logging 67 | -------------------------------------------------------------------------------- /config/simple.json.example: -------------------------------------------------------------------------------- 1 | [ 2 | { "ParameterKey": "Project", "ParameterValue": "" }, 3 | { "ParameterKey": "Product", "ParameterValue": "" }, 4 | { "ParameterKey": "Group", "ParameterValue": "" }, 5 | { "ParameterKey": "Team", "ParameterValue": "" }, 6 | { "ParameterKey": "Environment", "ParameterValue": "" }, 7 | { "ParameterKey": "KeepAlive", "ParameterValue": "false" }, 8 | { "ParameterKey": "InstanceType", "ParameterValue": "t2.micro" }, 9 | { "ParameterKey": "Owner", "ParameterValue": "@OWNER@" }, 10 | { "ParameterKey": "KeyName", "ParameterValue": "@KEY_NAME@" }, 11 | { "ParameterKey": "SSHLocation", "ParameterValue": "@SSH_FROM@" } 12 | ] 13 | -------------------------------------------------------------------------------- /config/stax.config: -------------------------------------------------------------------------------- 1 | ## stax.config - optional parameters specific to your environment 2 | 3 | # the prefix for the name of your stax 4 | STAX_TAG_PREFIX="" 5 | 6 | # the hostname or IP of a ssh 'jumpbox' to proxy connections to your VPC 7 | STAX_JUMP="" 8 | 9 | # the webhook URL to allow stax to post to a slack channel (#stax by default) 10 | # see https://slack.com/services/ for setup documentation 11 | STAX_SLACK_WHOOK="" 12 | 13 | # the encryption to use with S3. valid values are 'AES256' and 'aws:kms' 14 | STAX_AWS_S3_SSE="AES256" 15 | -------------------------------------------------------------------------------- /config/vpc-default.json.example: -------------------------------------------------------------------------------- 1 | [ 2 | { "ParameterKey": "Team", "ParameterValue": "" }, 3 | { "ParameterKey": "Group", "ParameterValue": "" }, 4 | { "ParameterKey": "Project", "ParameterValue": "" }, 5 | { "ParameterKey": "Product", "ParameterValue": "" }, 6 | { "ParameterKey": "Environment", "ParameterValue": "" }, 7 | { "ParameterKey": "ServiceELBSubdomainName", "ParameterValue": "" }, 8 | { "ParameterKey": "ServiceELBBaseDomainName", "ParameterValue": "" }, 9 | { "ParameterKey": "ServiceELBSSLCertName", "ParameterValue": "" }, 10 | { "ParameterKey": "DockerRegistryUser", "ParameterValue": "" }, 11 | { "ParameterKey": "DockerRegistryPass", "ParameterValue": "" }, 12 | { "ParameterKey": "DockerRegistryEmail", "ParameterValue": "" }, 13 | { "ParameterKey": "DockerRegistryUrl", "ParameterValue": "https://index.docker.io/v1/" }, 14 | { "ParameterKey": "ServiceClusterSize", "ParameterValue": "0" }, 15 | { "ParameterKey": "GatewayClusterSize", "ParameterValue": "2" }, 16 | { "ParameterKey": "KeepAlive", "ParameterValue": "false" }, 17 | { "ParameterKey": "BastionInstanceType", "ParameterValue": "t2.micro" }, 18 | { "ParameterKey": "NATInstanceType", "ParameterValue": "t2.micro" }, 19 | { "ParameterKey": "DockerInstanceType", "ParameterValue": "m3.medium" }, 20 | { "ParameterKey": "CoreOSChannelAMI", "ParameterValue": "CoreOSStableAMI" }, 21 | { "ParameterKey": "AdvertisedIPAddress", "ParameterValue": "private" }, 22 | { "ParameterKey": "AutoScaleCooldown", "ParameterValue": "300" }, 23 | { "ParameterKey": "Owner", "ParameterValue": "@OWNER@" }, 24 | { "ParameterKey": "KeyName", "ParameterValue": "@KEY_NAME@" }, 25 | { "ParameterKey": "AllowSSHFrom", "ParameterValue": "@SSH_FROM@" }, 26 | { "ParameterKey": "AllowHTTPFrom", "ParameterValue": "@HTTP_FROM@" } 27 | ] 28 | -------------------------------------------------------------------------------- /config/vpc-mon.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "ParameterKey": "Project", 3 | "ParameterValue": "test" 4 | }, { 5 | "ParameterKey": "Product", 6 | "ParameterValue": "test" 7 | }, { 8 | "ParameterKey": "Group", 9 | "ParameterValue": "ITSA" 10 | }, { 11 | "ParameterKey": "Team", 12 | "ParameterValue": "ArchEng" 13 | }, { 14 | "ParameterKey": "Owner", 15 | "ParameterValue": "@OWNER@" 16 | }, { 17 | "ParameterKey": "Environment", 18 | "ParameterValue": "test" 19 | }, { 20 | "ParameterKey": "KeepAlive", 21 | "ParameterValue": "false" 22 | }, { 23 | "ParameterKey": "CostCenter", 24 | "ParameterValue": "5180-9130-SLR74733" 25 | }, { 26 | "ParameterKey": "DockerRegistryUrl", 27 | "ParameterValue": "https://docker-registry.agro.services" 28 | }, { 29 | "ParameterKey": "DockerRegistryUser", 30 | "ParameterValue": "fleeter" 31 | }, { 32 | "ParameterKey": "DockerRegistryPass", 33 | "ParameterValue": "5sTZh6OkzPC1nM8osRhk" 34 | }, { 35 | "ParameterKey": "DockerRegistryEmail", 36 | "ParameterValue": "nobody@null.com" 37 | }, { 38 | "ParameterKey": "KeyName", 39 | "ParameterValue": "@KEY_NAME@" 40 | }, { 41 | "ParameterKey": "BastionInstanceType", 42 | "ParameterValue": "t2.micro" 43 | }, { 44 | "ParameterKey": "NATInstanceType", 45 | "ParameterValue": "t2.micro" 46 | }, { 47 | "ParameterKey": "NumberOfPings", 48 | "ParameterValue": "3" 49 | }, { 50 | "ParameterKey": "PingTimeout", 51 | "ParameterValue": "10" 52 | }, { 53 | "ParameterKey": "WaitBetweenPings", 54 | "ParameterValue": "2" 55 | }, { 56 | "ParameterKey": "WaitForInstanceStop", 57 | "ParameterValue": "60" 58 | }, { 59 | "ParameterKey": "WaitForInstanceStart", 60 | "ParameterValue": "300" 61 | }, { 62 | "ParameterKey": "DockerInstanceType", 63 | "ParameterValue": "t2.micro" 64 | }, { 65 | "ParameterKey": "ServiceClusterSize", 66 | "ParameterValue": "0" 67 | }, { 68 | "ParameterKey": "GatewayClusterSize", 69 | "ParameterValue": "2" 70 | }, { 71 | "ParameterKey": "AutoScaleCooldown", 72 | "ParameterValue": "300" 73 | }, { 74 | "ParameterKey": "AdvertisedIPAddress", 75 | "ParameterValue": "private" 76 | }, { 77 | "ParameterKey": "CoreOSChannelAMI", 78 | "ParameterValue": "CoreOSAlphaAMI" 79 | }, { 80 | "ParameterKey": "ELKInstanceType", 81 | "ParameterValue": "m3.medium" 82 | }, { 83 | "ParameterKey": "ELKEBSVolumeSize", 84 | "ParameterValue": "30" 85 | }, { 86 | "ParameterKey": "VpcCidr", 87 | "ParameterValue": "10.183.0.0/16" 88 | }, { 89 | "ParameterKey": "AllowHTTPFrom", 90 | "ParameterValue": "0.0.0.0/0" 91 | }, { 92 | "ParameterKey": "AllowSSHFrom", 93 | "ParameterValue": "@SSH_FROM@" 94 | }, { 95 | "ParameterKey": "AvailabilityZone1", 96 | "ParameterValue": "us-east-1a" 97 | }, { 98 | "ParameterKey": "AvailabilityZone2", 99 | "ParameterValue": "us-east-1b" 100 | }, { 101 | "ParameterKey": "PublicSubnet1", 102 | "ParameterValue": "10.183.1.0/24" 103 | }, { 104 | "ParameterKey": "PrivateSubnet1", 105 | "ParameterValue": "10.183.0.0/24" 106 | }, { 107 | "ParameterKey": "PublicSubnet2", 108 | "ParameterValue": "10.183.3.0/24" 109 | }, { 110 | "ParameterKey": "PrivateSubnet2", 111 | "ParameterValue": "10.183.2.0/24" 112 | }, { 113 | "ParameterKey": "ServiceELBSSLCertName", 114 | "ParameterValue": "agro-services-ssl" 115 | }, { 116 | "ParameterKey": "ServiceELBSubdomainName", 117 | "ParameterValue": "djdool" 118 | }, { 119 | "ParameterKey": "ServiceELBBaseDomainName", 120 | "ParameterValue": "agro.services" 121 | }, { 122 | "ParameterKey": "DBSubnet1Cidr", 123 | "ParameterValue": "10.183.100.0/24" 124 | }, { 125 | "ParameterKey": "DBSubnet2Cidr", 126 | "ParameterValue": "10.183.101.0/24" 127 | }, { 128 | "ParameterKey": "AkanaPMURL", 129 | "ParameterValue": "https://pm.agro.services/" 130 | }, { 131 | "ParameterKey": "AkanaPMContainerManagerUser", 132 | "ParameterValue": "administrator" 133 | }, { 134 | "ParameterKey": "AkanaPMContainerManagerPass", 135 | "ParameterValue": "0UdIMwCX#GYD" 136 | }, { 137 | "ParameterKey": "WebELBBaseDomainName", 138 | "ParameterValue": "agro.services" 139 | }, { 140 | "ParameterKey": "WebELBSubdomainName", 141 | "ParameterValue": "djdool" 142 | }, { 143 | "ParameterKey": "WebELBSSLCertName", 144 | "ParameterValue": "agro-services-ssl" 145 | }, { 146 | "ParameterKey": "WebOAuthClientID", 147 | "ParameterValue": "" 148 | }, { 149 | "ParameterKey": "WebOAuthClientSecret", 150 | "ParameterValue": "" 151 | }, { 152 | "ParameterKey": "WebOAuthProvider", 153 | "ParameterValue": "ping" 154 | }, { 155 | "ParameterKey": "WebOAuthProviderBaseURL", 156 | "ParameterValue": "https://test.amp.monsanto.com" 157 | }, { 158 | "ParameterKey": "SwarmEnabled", 159 | "ParameterValue": "false" 160 | }] 161 | -------------------------------------------------------------------------------- /config/vpc.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "ParameterKey": "Project", 3 | "ParameterValue": "test" 4 | }, { 5 | "ParameterKey": "Product", 6 | "ParameterValue": "test" 7 | }, { 8 | "ParameterKey": "Group", 9 | "ParameterValue": "SPAA" 10 | }, { 11 | "ParameterKey": "Team", 12 | "ParameterValue": "VendorMgmt" 13 | }, { 14 | "ParameterKey": "Owner", 15 | "ParameterValue": "@OWNER@" 16 | }, { 17 | "ParameterKey": "Environment", 18 | "ParameterValue": "test" 19 | }, { 20 | "ParameterKey": "KeepAlive", 21 | "ParameterValue": "false" 22 | }, { 23 | "ParameterKey": "CostCenter", 24 | "ParameterValue": "5180-9130-SLR74733" 25 | }, { 26 | "ParameterKey": "DockerRegistryUrl", 27 | "ParameterValue": "https://docker-registry.agro.services" 28 | }, { 29 | "ParameterKey": "DockerRegistryUser", 30 | "ParameterValue": "fleeter" 31 | }, { 32 | "ParameterKey": "DockerRegistryPass", 33 | "ParameterValue": "5sTZh6OkzPC1nM8osRhk" 34 | }, { 35 | "ParameterKey": "DockerRegistryEmail", 36 | "ParameterValue": "nobody@null.com" 37 | }, { 38 | "ParameterKey": "KeyName", 39 | "ParameterValue": "@KEY_NAME@" 40 | }, { 41 | "ParameterKey": "BastionInstanceType", 42 | "ParameterValue": "t2.micro" 43 | }, { 44 | "ParameterKey": "NATInstanceType", 45 | "ParameterValue": "t2.micro" 46 | }, { 47 | "ParameterKey": "NumberOfPings", 48 | "ParameterValue": "3" 49 | }, { 50 | "ParameterKey": "PingTimeout", 51 | "ParameterValue": "10" 52 | }, { 53 | "ParameterKey": "WaitBetweenPings", 54 | "ParameterValue": "2" 55 | }, { 56 | "ParameterKey": "WaitForInstanceStop", 57 | "ParameterValue": "60" 58 | }, { 59 | "ParameterKey": "WaitForInstanceStart", 60 | "ParameterValue": "300" 61 | }, { 62 | "ParameterKey": "DockerInstanceType", 63 | "ParameterValue": "t2.micro" 64 | }, { 65 | "ParameterKey": "ServiceClusterSize", 66 | "ParameterValue": "0" 67 | }, { 68 | "ParameterKey": "GatewayClusterSize", 69 | "ParameterValue": "2" 70 | }, { 71 | "ParameterKey": "AutoScaleCooldown", 72 | "ParameterValue": "300" 73 | }, { 74 | "ParameterKey": "AdvertisedIPAddress", 75 | "ParameterValue": "private" 76 | }, { 77 | "ParameterKey": "CoreOSChannelAMI", 78 | "ParameterValue": "CoreOSAlphaAMI" 79 | }, { 80 | "ParameterKey": "ELKInstanceType", 81 | "ParameterValue": "m3.medium" 82 | }, { 83 | "ParameterKey": "ELKEBSVolumeSize", 84 | "ParameterValue": "30" 85 | }, { 86 | "ParameterKey": "VpcCidr", 87 | "ParameterValue": "10.183.0.0/16" 88 | }, { 89 | "ParameterKey": "AllowHTTPFrom", 90 | "ParameterValue": "0.0.0.0/0" 91 | }, { 92 | "ParameterKey": "AllowSSHFrom", 93 | "ParameterValue": "@SSH_FROM@" 94 | }, { 95 | "ParameterKey": "AvailabilityZone1", 96 | "ParameterValue": "us-east-1a" 97 | }, { 98 | "ParameterKey": "AvailabilityZone2", 99 | "ParameterValue": "us-east-1b" 100 | }, { 101 | "ParameterKey": "PublicSubnet1", 102 | "ParameterValue": "10.183.1.0/24" 103 | }, { 104 | "ParameterKey": "PrivateSubnet1", 105 | "ParameterValue": "10.183.0.0/24" 106 | }, { 107 | "ParameterKey": "PublicSubnet2", 108 | "ParameterValue": "10.183.3.0/24" 109 | }, { 110 | "ParameterKey": "PrivateSubnet2", 111 | "ParameterValue": "10.183.2.0/24" 112 | }, { 113 | "ParameterKey": "ServiceELBSSLCertName", 114 | "ParameterValue": "agro-services-ssl" 115 | }, { 116 | "ParameterKey": "ServiceELBSubdomainName", 117 | "ParameterValue": "mawhee" 118 | }, { 119 | "ParameterKey": "ServiceELBBaseDomainName", 120 | "ParameterValue": "agro.services" 121 | }, { 122 | "ParameterKey": "DBSubnet1Cidr", 123 | "ParameterValue": "10.183.100.0/24" 124 | }, { 125 | "ParameterKey": "DBSubnet2Cidr", 126 | "ParameterValue": "10.183.101.0/24" 127 | }, { 128 | "ParameterKey": "AkanaPMURL", 129 | "ParameterValue": "https://pm.agro.services/" 130 | }, { 131 | "ParameterKey": "AkanaPMContainerManagerUser", 132 | "ParameterValue": "" 133 | }, { 134 | "ParameterKey": "AkanaPMContainerManagerPass", 135 | "ParameterValue": "" 136 | }, { 137 | "ParameterKey": "WebELBBaseDomainName", 138 | "ParameterValue": "agro.services" 139 | }, { 140 | "ParameterKey": "WebELBSubdomainName", 141 | "ParameterValue": "mawhee" 142 | }, { 143 | "ParameterKey": "WebELBSSLCertName", 144 | "ParameterValue": "agro-services-ssl" 145 | }, { 146 | "ParameterKey": "WebOAuthClientID", 147 | "ParameterValue": "" 148 | }, { 149 | "ParameterKey": "WebOAuthClientSecret", 150 | "ParameterValue": "" 151 | }, { 152 | "ParameterKey": "WebOAuthProvider", 153 | "ParameterValue": "ping" 154 | }, { 155 | "ParameterKey": "WebOAuthProviderBaseURL", 156 | "ParameterValue": "https://test.amp.monsanto.com" 157 | }, { 158 | "ParameterKey": "SwarmEnabled", 159 | "ParameterValue": "false" 160 | }] 161 | -------------------------------------------------------------------------------- /docs/aws-ha-nat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/philcryer/stax/5c229709f182982800250b6603c2da26e91344aa/docs/aws-ha-nat.png -------------------------------------------------------------------------------- /docs/aws-stax.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/philcryer/stax/5c229709f182982800250b6603c2da26e91344aa/docs/aws-stax.png -------------------------------------------------------------------------------- /stax: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | ##################################################################### 3 | # stax - creates and manages CloudFormation stacks in AWS 4 | # See LICENSE file for license - See README.md file for readme 5 | ##################################################################### 6 | 7 | # variables 8 | pkg="stax" 9 | version="0.10" 10 | script_path=$(cd $(dirname $0); pwd -P) 11 | system=$(uname) 12 | STAX_DIR="$script_path/run" 13 | STAX_NAME_FILE="$STAX_DIR/stax-name" 14 | stax_log="$STAX_DIR/stax.log" 15 | SSH_OPTIONS="-q" 16 | host=$(hostname) 17 | 18 | # create a dir to store stax stuff 19 | if [[ ! -d $STAX_DIR ]]; then 20 | if ! mkdir -p "$STAX_DIR"; then 21 | echo "$pkg: failed to make run directory: $STAX_DIR" 22 | exit 1 23 | fi 24 | if ! chmod 700 "$STAX_DIR"; then 25 | echo "$pkg: failed to chmod $STAX_DIR" 26 | exit 1 27 | fi 28 | fi 29 | # create audit dir for stax 30 | if [[ ! -d $STAX_DIR/audit ]]; then 31 | if ! mkdir -p "$STAX_DIR/audit"; then 32 | echo "$pkg: failed to make audit directory: $STAX_DIR/audit" 33 | exit 1 34 | fi 35 | fi 36 | 37 | # set colors 38 | red=$(tput setaf 1) 39 | green=$(tput setaf 2) 40 | yellow=$(tput setaf 3) 41 | blue=$(tput setaf 4) 42 | purple=$(tput setaf 5) 43 | cyan=$(tput setaf 6) 44 | white=$(tput setaf 7) 45 | reset=$(tput sgr0) 46 | 47 | stax-message(){ 48 | declare msg="$1" 49 | stax-logger "INFO: $msg" 50 | [[ $quiet ]] && return 51 | shift 52 | pref="----" 53 | if [[ $1 ]]; then 54 | pref="${1:0:4}" 55 | shift 56 | fi 57 | echo "${yellow}[ $cyan$pref$yellow ]$reset $msg" 58 | } 59 | 60 | stax-error(){ 61 | declare msg="$1" 62 | stax-logger "ERROR: $msg" 63 | echo "${yellow}[ ${red}ERRR$yellow ]$reset $msg" 64 | } 65 | 66 | stax-error-exit(){ 67 | declare msg="$1" 68 | declare status="$2" 69 | stax-error "$msg" 70 | exit $status 71 | } 72 | 73 | stax-logger(){ 74 | declare msg="$1" 75 | if [[ ! $stax_log ]]; then 76 | echo "$pkg: cannot call stax-logger with stax_log undefined" 77 | exit 5 78 | fi 79 | echo "$(date +'%b %d %T') $host $pkg: $msg" >> "$stax_log" 80 | } 81 | 82 | stax-usage(){ 83 | cat < < ' 137 | echo "|___/\__\__,_/_/\_\ ${reset} `echo $version`" 138 | echo 139 | } 140 | 141 | stax-preflight(){ 142 | # check for required cli tools 143 | for cli in aws ssh; do 144 | if ! type "$cli" > /dev/null 2>&1; then 145 | stax-error-exit "$pkg: $cli is not in the PATH. Aborting." 1 146 | fi 147 | done 148 | # check if awscli tools are configured 149 | if [[ ! -f $HOME/.aws/config ]]; then 150 | stax-error-exit "awscli not configured, run 'aws configure'. Aborting." 1 151 | fi 152 | # check for jq, use system installed version if found, otherwise use bundled 153 | if which jq > /dev/null; then 154 | jq=$(which jq) 155 | else 156 | jq="assets/jq/$system/jq" 157 | if [[ ! -f $jq ]]; then 158 | stax-error-exit "no viable jq binary found, Aborting." 1 159 | fi 160 | fi 161 | # determine which way to reverse cat a file 162 | if [[ $system == Linux ]]; then 163 | tac=tac 164 | elif [[ $system == Darwin ]]; then 165 | tac="tail -r" 166 | else 167 | stax-error-exit "unsupported platform: $system" 1 168 | fi 169 | if [ -f "$HOME/.stax.config" ]; then 170 | source $HOME/.stax.config 171 | fi 172 | tag_prefix=${STAX_TAG_PREFIX:-"stax"} 173 | s3_sse=${STAX_AWS_S3_SSE:-"AES256"} 174 | if [ "$STAX_AWS_S3_SSE" != "AES256" -a "$STAX_AWS_S3_SSE" != "aws:kms" ]; then 175 | stax-error-exit "invalid encryption specified for S3. Must be 'AES256' or 'aws:kms'." 176 | fi 177 | } 178 | 179 | stax-create-key(){ 180 | stax-message "creating ssh key pair in aws" 181 | STAX_KEY="$STAX_NAME" 182 | STAX_PRIV_KEY="$STAX_DIR/$STAX_NAME.pem" 183 | touch "$STAX_PRIV_KEY" 184 | chmod 600 "$STAX_PRIV_KEY" 185 | stax-message " creating key pair" 186 | if ! aws ec2 create-key-pair --key-name "$STAX_NAME" --query 'KeyMaterial' --output text > "$STAX_PRIV_KEY"; then 187 | stax-error "failed to create key pair in aws" 188 | return 1 189 | fi 190 | stax-message " key pair created" 191 | stax-message " generating public key" 192 | STAX_PUB_KEY="$STAX_PRIV_KEY.pub" 193 | if ! ssh-keygen -y -f "$STAX_PRIV_KEY" > "$STAX_PUB_KEY"; then 194 | stax-error "failed to generate public key from private key: $STAX_PRIV_KEY $STAX_PUB_KEY" 195 | stax-delete-key 196 | return 1 197 | fi 198 | stax-message " public key generated" 199 | } 200 | 201 | stax-create-bucket(){ 202 | stax-message "create bucket" 203 | bucket="$STAX_NAME" 204 | if [[ $1 ]]; then 205 | bucket="$1" 206 | fi 207 | if [[ ! $bucket ]]; then 208 | stax-error-exit "you must supply the name for the bucket to be created" 5 209 | fi 210 | stax-message " creating bucket $bucket" 211 | if ! aws s3 mb "s3://$bucket" > /dev/null; then 212 | stax-error "failed to create bucket: $bucket" 213 | return 1 214 | fi 215 | stax-message " created bucket $bucket" 216 | } 217 | 218 | stax-upload-template(){ 219 | if [[ ! $1 ]]; then 220 | stax-error "stax-upload-template requires the template path as an argument" 221 | return 10 222 | fi 223 | template_path="$1" 224 | target_base="$STAX_NAME" 225 | if [[ $2 ]]; then 226 | target_base="$2" 227 | fi 228 | if [[ ! -f $template_path ]]; then 229 | stax-error "template file not found: $template_path" 230 | return 1 231 | fi 232 | template_s3="$STAX_NAME/$target_base.json" 233 | stax-message " uploading template" 234 | if ! aws s3 cp --sse $s3_sse "$template_path" "s3://$template_s3" > /dev/null; then 235 | stax-error "failed to copy $template_path to s3" 236 | return 1 237 | fi 238 | STAX_TEMPLATE_URL="https://s3.amazonaws.com/$template_s3" 239 | stax-message " template uploaded to $STAX_TEMPLATE_URL" 240 | } 241 | 242 | stax-validate-template(){ 243 | stax-message "validate template" 244 | if [[ ! $STAX_TEMPLATE_URL ]]; then 245 | stax-error "cannot call stax-validate-template without defining STAX_TEMPLATE_URL first" 246 | stax-error "call stax-upload-template first" 247 | return 10 248 | fi 249 | template_url="$STAX_TEMPLATE_URL" 250 | stax-message " validating template $template_url" 251 | if ! aws cloudformation validate-template --template-url "$template_url" > /dev/null; then 252 | stax-error "template failed to validate, exiting" 253 | return 1 254 | fi 255 | stax-message " validated template $template_url" 256 | } 257 | 258 | stax-validate(){ 259 | stax-message "validate template" 260 | if [[ ! $1 ]]; then 261 | stax-error "stax-validate requires the template path as an argument" 262 | return 10 263 | fi 264 | template_path="$1" 265 | if ! stax-generate; then 266 | stax-error "failed to set up stax" 267 | return 1 268 | fi 269 | if ! $jq . "$template_path" >/dev/null; then 270 | stax-error "template $template_path failed jq validation, see error above" 271 | return 1 272 | fi 273 | if ! stax-create-bucket; then 274 | stax-error "failed to create bucket for upload" 275 | return 1 276 | fi 277 | if ! stax-upload-template "$template_path"; then 278 | stax-delete-bucket 279 | stax-error "failed to upload template" 280 | return 1 281 | fi 282 | if ! stax-validate-template; then 283 | stax-delete-bucket 284 | stax-error "failed to validate template" 285 | return 1 286 | fi 287 | if ! stax-delete-bucket; then 288 | stax-error "failed to delete bucket, please do so manually" 289 | return 1 290 | fi 291 | } 292 | 293 | stax-add(){ 294 | stax-message "adding template to existing vpc" 295 | if [[ $# != 2 ]]; then 296 | stax-error "stax-add: you must provide the template and config file" 297 | return 10 298 | fi 299 | template_path="$1" 300 | config="$2" 301 | postfix=$(stax-generate-random) 302 | if [[ $? != 0 ]]; then 303 | stax-error "failed to generate name for add" 304 | return 1 305 | fi 306 | STAX_NAME_ADD="$STAX_NAME-add-$postfix" 307 | stax-message "$STAX_NAME_ADD" "NAME" 308 | if ! stax-add-config "$config"; then 309 | stax-error "failed to create parameter file" 310 | return 1 311 | fi 312 | stax-message " checking for valid json file format" 313 | if ! $jq . "$template_path" >/dev/null; then 314 | stax-error "template $template_path failed jq validation, see error above" 315 | rm -f $STAX_ADD_PARAMS 316 | return 1 317 | fi 318 | if ! stax-upload-template "$template_path" "$STAX_NAME_ADD"; then 319 | stax-error "failed to upload template to s3: $template_path" 320 | rm -f $STAX_ADD_PARAMS 321 | return 1 322 | fi 323 | if ! stax-validate-template; then 324 | stax-error "template did not validate: $template_path" 325 | aws s3 rm "s3://$STAX_NAME/$STAX_NAME_ADD.json" > /dev/null 326 | rm -f $STAX_ADD_PARAMS 327 | return 1 328 | fi 329 | stax-message " adding $template_path to stax" 330 | if ! aws cloudformation create-stack \ 331 | --stack-name "$STAX_NAME_ADD" \ 332 | --template-url "$STAX_TEMPLATE_URL" \ 333 | --parameters "$(<$STAX_ADD_PARAMS)" > /dev/null 334 | then 335 | stax-error "creation of $template_path failed" 336 | aws s3 rm "s3://$STAX_NAME/$STAX_NAME_ADD.json" > /dev/null 337 | rm -f $STAX_ADD_PARAMS 338 | return 1 339 | fi 340 | date=$(date +'%Y%m%d-%H%M%S') 341 | touch "$STAX_DIR/audit/$STAX_NAME/$date-added-$STAX_NAME_ADD" 342 | if mkdir -p "$STAX_DIR/audit/$STAX_NAME_ADD"; then 343 | touch "$STAX_DIR/audit/$STAX_NAME_ADD/$date-created" 344 | else 345 | stax-error "failed to create audit directory: $STAX_DIR/audit/$STAX_NAME_ADD" 346 | stax-error "please create the audit directory yourself" 347 | fi 348 | if ! echo "$STAX_NAME_ADD" >> "$STAX_DIR/$STAX_NAME.add"; then 349 | stax-error "failed to add $STAX_NAME_ADD to add file: $STAX_DIR/$STAX_NAME.add" 350 | stax-error "this will create problems when trying to delete this stack" 351 | return 2 352 | fi 353 | stax-message " stax addition complete" 354 | } 355 | 356 | stax-add-logger(){ 357 | stax-message "adding logger functionality to existing vpc" 358 | stax-message " ready to do the needful" 359 | stax-message " - starting elasticsearch" 360 | stax-start-service elasticsearch 361 | stax-start-service logstash 362 | stax-start-service logspout 363 | stax-start-service kibana 364 | date=$(date +'%Y%m%d-%H%M%S') 365 | touch "$STAX_DIR/audit/$STAX_NAME/$date-added-logger" 366 | if mkdir -p "$STAX_DIR/audit/${STAX_NAME}-logger"; then 367 | touch "$STAX_DIR/audit/$STAX_NAME-logger/${date}-added" 368 | else 369 | stax-error "failed to create audit directory: $STAX_DIR/audit/$STAX_NAME$date-added-logger" 370 | stax-error "please create the audit directory yourself" 371 | fi 372 | if ! echo "logger-added" >> "$STAX_DIR/$STAX_NAME.add"; then 373 | stax-error "failed to add logger-added to add file: $STAX_DIR/$STAX_NAME.add" 374 | stax-error "this will create problems when trying to delete this stack" 375 | return 2 376 | fi 377 | stax-message " stax add-logger complete - current cluster status from fleet" 378 | sleep 5 379 | stax-fleetstats 380 | } 381 | 382 | stax-remove(){ 383 | stax-message "removing add" 384 | if [[ ! $1 ]]; then 385 | stax-error "stax-remove: you must supply the name of the addition to remove" 386 | return 10 387 | fi 388 | addition="$1" 389 | stax-message " removing $addition" 390 | if ! grep -q "^$addition\$" "$STAX_DIR/$STAX_NAME.add" > /dev/null 2>&1; then 391 | stax-error "unknown addition: $addition" 392 | return 1 393 | fi 394 | if ! aws cloudformation delete-stack --stack-name "$addition" > /dev/null; then 395 | stax-error "removal failed: $addition" 396 | return 1 397 | fi 398 | if ! sed -i.bak "/^$addition\$/d" "$STAX_DIR/$STAX_NAME.add"; then 399 | stax-error "failed to remove $addition from $STAX_DIR/$STAX_NAME.add" 400 | stax-error "this may cause problems when deleting the stack" 401 | return 2 402 | fi 403 | rm -f "$STAX_DIR/$STAX_NAME.add.bak" 404 | stax-message " removal complete" 405 | date=$(date +'%Y%m%d-%H%M%S') 406 | touch "$STAX_DIR/audit/$STAX_NAME/$date-removed-$addition" 407 | touch "$STAX_DIR/audit/$addition/$date-delete" 408 | } 409 | 410 | stax-template-find() { 411 | if [[ -f "$1" ]]; then 412 | echo "$1" 413 | else 414 | base="${1##*/}" 415 | base="${base%%.json}" 416 | temp="template/$base.json" 417 | if [[ -f $temp ]]; then 418 | echo "$temp" 419 | else 420 | return 1 421 | fi 422 | fi 423 | } 424 | 425 | stax-parameter-tag(){ 426 | if [[ ! $1 ]]; then 427 | stax-error "stax-parameter-tag require the parameter name as an argument" 428 | return 10 429 | fi 430 | if [[ ! $STAX_PARAMS ]]; then 431 | stax-error "STAX_PARAMS must be defined when calling stax-parameter-tag" 432 | return 10 433 | fi 434 | if [[ ! -f $STAX_PARAMS ]]; then 435 | stax-error "parameter file does not exist: $STAX_PARAMS" 436 | return 10 437 | fi 438 | param="$1" 439 | tag_value=$($jq --raw-output ".[] | select(.ParameterKey==\"$param\").ParameterValue" "$STAX_PARAMS") 440 | if [[ $? != 0 || ! $tag_value ]]; then 441 | echo "failed to parse $STAX_PARAMS for parameter $param" 442 | return 1 443 | fi 444 | tag_name=$(echo $param | sed 's/\(.\)\([[:upper:]]\)/\1-\2/g' | tr '[:upper:]' '[:lower:]') 445 | if [[ $? != 0 || ! $tag_name ]]; then 446 | echo "failed to create tag name from for parameter $param" 447 | return 1 448 | fi 449 | tag_name="$tag_prefix:$tag_name" 450 | echo "{\"Key\":\"$tag_name\",\"Value\":\"$tag_value\"}" 451 | } 452 | 453 | stax-update(){ 454 | stax-message "updating existing stax $STAX_NAME" 455 | if [[ ! $1 ]]; then 456 | stax-error-exit "stax-update takes the template path as an argument" 10 457 | fi 458 | template_path="$(stax-template-find $1)" 459 | if [[ $? != 0 || ! $template_path ]]; then 460 | stax-error-exit "could not find template $1" 1 461 | fi 462 | if ! stax-config; then 463 | stax-error-exit "failed to generate updated stax config" 1 464 | fi 465 | if [[ ! -f $template_path ]]; then 466 | stax-error-exit "updated template file does not exist: $template_path" 1 467 | fi 468 | stax-message " checking template for valid json file format" 469 | if ! $jq . "$template_path" >/dev/null; then 470 | stax-delete-files 471 | stax-error-exit "template $template_path failed jq validation, see error above" 1 472 | fi 473 | if ! stax-upload-template "$template_path"; then 474 | stax-delete-bucket 475 | stax-delete-key 476 | stax-delete-files 477 | stax-error-exit "failed to upload template to s3" 1 478 | fi 479 | if ! stax-validate-template; then 480 | stax-delete-bucket 481 | stax-delete-key 482 | stax-delete-files 483 | stax-error-exit "failed to validate template" 1 484 | fi 485 | ti=0 486 | template_save="run/$STAX_NAME.template$ti" 487 | while [[ -f $template_save ]]; do 488 | template_save="run/$STAX_NAME.template$((++ti))" 489 | done 490 | if ! cp "$template_path" "$template_save"; then 491 | stax-error "failed to save template $template_path, continuing" 492 | fi 493 | stax-message " uploading updated vpc assets" 494 | for f in assets/vpc/*; do 495 | if ! aws s3 cp --sse $s3_sse "$f" "s3://$STAX_NAME/" > /dev/null; then 496 | stax-error "failed to upload file $f to bucket $STAX_NAME" 497 | stax-delete-bucket 498 | stax-delete-key 499 | stax-delete-files 500 | stax-error-exit "asset upload failed" 1 501 | fi 502 | done 503 | stax-message " updated vpc assets uploaded" 504 | stax-message " updating stax in aws" 505 | #if ! aws cloudformation create-stack \ 506 | if ! aws cloudformation update-stack \ 507 | --stack-name "$STAX_NAME" \ 508 | --template-url "$STAX_TEMPLATE_URL" \ 509 | --parameters "$(<$STAX_PARAMS)" \ 510 | --capabilities CAPABILITY_IAM > /dev/null 511 | then 512 | stax-error "updated failed, sorry about that" 513 | stax-error-exit "update failed, exiting" 1 514 | fi 515 | touch "$STAX_DIR/audit/$STAX_NAME/$(date +'%Y%m%d-%H%M%S')-updated" 516 | stax-message " stax update complete" 517 | } 518 | 519 | stax-create(){ 520 | stax-message "creating stax" 521 | if [[ ! $1 ]]; then 522 | stax-error-exit "stax-create takes the template path as an argument" 10 523 | fi 524 | template_path="$(stax-template-find $1)" 525 | if [[ $? != 0 || ! $template_path ]]; then 526 | stax-error-exit "could not find template $1" 1 527 | fi 528 | if [[ -f $STAX_NAME_FILE ]]; then 529 | existing_name=$(<$STAX_NAME_FILE) 530 | stax-error "existing stax defined: $existing_name" 531 | stax-error-exit "currently having only one stack is supported, exiting" 1 532 | fi 533 | if ! stax-generate; then 534 | stax-error-exit "failed to set up stax" 1 535 | fi 536 | stax-message "$STAX_NAME" "NAME" 537 | if ! stax-config; then 538 | stax-error-exit "failed to generate stax config" 1 539 | fi 540 | if [[ ! -f $template_path ]]; then 541 | stax-error-exit "template file does not exist: $template_path" 1 542 | fi 543 | stax-message " checking for valid json file format" 544 | if ! $jq . "$template_path" >/dev/null; then 545 | stax-delete-files 546 | stax-error-exit "template $template_path failed jq validation, see error above" 1 547 | fi 548 | if ! stax-create-key; then 549 | stax-delete-files 550 | stax-error-exit "failed to create key pair" 1 551 | fi 552 | if ! stax-create-bucket; then 553 | stax-delete-key 554 | stax-delete-files 555 | stax-error-exit "failed to create bucket" 1 556 | fi 557 | # upload template to s3 to have bigger size limits 558 | if ! stax-upload-template "$template_path"; then 559 | stax-delete-bucket 560 | stax-delete-key 561 | stax-delete-files 562 | stax-error-exit "failed to upload template to s3" 1 563 | fi 564 | if ! stax-validate-template; then 565 | stax-delete-bucket 566 | stax-delete-key 567 | stax-delete-files 568 | stax-error-exit "failed to validate template" 1 569 | fi 570 | # save template 571 | if ! cp "$template_path" "run/$STAX_NAME.template"; then 572 | stax-error "failed to save template $template_path, continuing" 573 | fi 574 | stax-message " uploading vpc assets" 575 | for f in assets/vpc/*; do 576 | if ! aws s3 cp --sse $s3_sse "$f" "s3://$STAX_NAME/" > /dev/null; then 577 | stax-error "failed to upload file $f to bucket $STAX_NAME" 578 | stax-delete-bucket 579 | stax-delete-key 580 | stax-delete-files 581 | stax-error-exit "asset upload failed" 1 582 | fi 583 | done 584 | stax-message " vpc assets uploaded" 585 | stax-message " extracting tags from parameter file" 586 | tags= 587 | for param in Project Group Owner Environment KeepAlive; do 588 | new_tag=$(stax-parameter-tag "$param") 589 | if [[ $? != 0 ]]; then 590 | stax-error "failed to extract tag: $new_tag" 591 | stax-error "you must specify the value for parameter $param in the config" 592 | stax-delete-bucket 593 | stax-delete-key 594 | stax-delete-files 595 | return 1 596 | fi 597 | if [[ $tags ]]; then 598 | tags="$tags,$new_tag" 599 | else 600 | tags="[$new_tag" 601 | fi 602 | done 603 | tags="$tags]" 604 | stax-message " using tags: $tags" 605 | stax-message " creating stax in aws" 606 | if ! aws cloudformation create-stack \ 607 | --stack-name "$STAX_NAME" \ 608 | --template-url "$STAX_TEMPLATE_URL" \ 609 | --parameters "$(<$STAX_PARAMS)" \ 610 | --tags "$tags" \ 611 | --capabilities CAPABILITY_IAM > /dev/null 612 | then 613 | stax-error "creation failed, cleaning up" 614 | stax-delete-bucket 615 | stax-delete-key 616 | stax-delete-files 617 | stax-error-exit "creation failed, exiting" 1 618 | fi 619 | if ! echo "$STAX_NAME" > "$STAX_NAME_FILE"; then 620 | stax-error "failed to create STAX_NAME_FILE: echo $STAX_NAME > $STAX_NAME_FILE" 621 | stax-error-exit "stax will not be able to function without it" 1 622 | fi 623 | # new 'audit' functionality, save names and create date of stax you've created 624 | # if useful, we could save this to S3: and make it persist (well sure, uh, or the fax) 625 | if mkdir -p "$STAX_DIR/audit/$STAX_NAME"; then 626 | touch "$STAX_DIR/audit/$STAX_NAME/$(date +'%Y%m%d-%H%M%S')-created" 627 | else 628 | stax-error "failed to create audit directory: $STAX_DIR/audit/$STAX_NAME" 629 | stax-error "please create the audit directory yourself" 630 | fi 631 | stax-message " stax creation complete" 632 | } 633 | 634 | stax-ssh-config(){ 635 | stax-message "creating ssh_config" 636 | STAX_SSH_CONFIG="$STAX_DIR/$STAX_NAME.ssh_config" 637 | gwhosts="$STAX_DIR/$STAX_NAME.gateway_hosts" 638 | shosts="$STAX_DIR/$STAX_NAME.service_hosts" 639 | elkhost="$STAX_DIR/$STAX_NAME.elk_host" 640 | for host_file in $gwhosts $shosts $elkhost; do 641 | if [[ ! -f $host_file ]]; then 642 | stax-error "missing host file: $host_file" 643 | return 10 644 | fi 645 | done 646 | elk_ip=$(<$elkhost) 647 | stax-message " writing $STAX_SSH_CONFIG" 648 | cat > "$STAX_SSH_CONFIG" <> "$STAX_SSH_CONFIG" <> "$STAX_SSH_CONFIG" <> "$STAX_SSH_CONFIG" <> "$STAX_SSH_CONFIG" < "$STAX_JUMP_FILE" 724 | fi 725 | STAX_SSH_CONFIG="$STAX_DIR/$STAX_NAME.ssh_config" 726 | SSH_OPTIONS="$SSH_OPTIONS -F $STAX_SSH_CONFIG" 727 | } 728 | 729 | # save the description of the stax to a file 730 | stax-describe(){ 731 | stax-message "describe stax" 732 | if [[ ! $STAX_NAME ]]; then 733 | stax-error "cannot call stax-describe with STAX_NAME undefined" 734 | return 10 735 | fi 736 | stax-message "$STAX_NAME" "NAME" 737 | stax-message " querying aws" 738 | STAX_DESC="$STAX_DIR/$STAX_NAME.json" 739 | if ! aws --output json cloudformation describe-stacks --stack-name "$STAX_NAME" > "$STAX_DESC"; then 740 | stax-error-message "failed to get stax information for $STAX_NAME from aws" 741 | return 1 742 | fi 743 | stax-message " query complete" 744 | stax-message " see $STAX_DESC for details" 745 | } 746 | 747 | stax-autoservices(){ 748 | # MonsantoCo/3ga-sprint-planning/issues/56 749 | if [[ ! $1 ]]; then 750 | stax-error "template path must be provided when calling stax-autoservices()" 751 | return 10 752 | fi 753 | template_path="$1" 754 | services_file="$(echo $template_path|cut -d"." -f1).services" 755 | if [[ $services_file == .services ]]; then 756 | stax-error "unable to create name of services file from template path: $template_path" 757 | return 1 758 | fi 759 | if [[ ! -f $services_file ]]; then 760 | stax-message "services file $services_file does not exist, no services to launch" 761 | return 0 762 | fi 763 | stax-message " using services file: $services_file" 764 | if ! stax-complete 1; then 765 | return 1 766 | fi 767 | if [ ! -f "$STAX_BASTION_FILE" ]; then 768 | stax-bastionip 769 | if ! stax-getdockerips; then 770 | exit 1 771 | fi 772 | if ! stax-ssh-config; then 773 | exit 1 774 | fi 775 | fi 776 | STAX_PUB_IP=$(<$STAX_BASTION_FILE) 777 | stax-message " checking fleet" 778 | GatewayClusterSize=`cat $STAX_PARAMS|grep GatewayClusterSize|cut -d"\"" -f 8` 779 | machine_num=$((GatewayClusterSize+1)) 780 | elapsed_time="0" 781 | sleep_int="10" 782 | while :; do 783 | status=`stax-fleetstats | grep "location=" | wc -l` 784 | if [[ $status == $machine_num ]]; then 785 | stax-message " fleet clustering complete" 786 | break 787 | fi 788 | stax-message " fleet cluster not completed ($status / $machine_num completed)" 789 | stax-message " sleeping $sleep_int seconds (elapsed: $elapsed_time seconds) " "zzzz" 790 | sleep $sleep_int 791 | elapsed_time=$(($elapsed_time+$sleep_int)) 792 | done 793 | stax-message "fleet is available on the cluster, ready to install services" "!!!!" 794 | stax-message "starting all services in $services_file" 795 | services=$(<$services_file) 796 | for service in $services; do 797 | stax-message " installing $service" "----" 798 | service_file="assets/services/$service.service" 799 | if [[ ! -f $service_file ]]; then 800 | stax-error " service file $service_file not found" 801 | return 1 802 | fi 803 | service_basename=${service_file##*/} 804 | stax-message " copying $service_file to service docker host" "++++" 805 | scp_cmd="scp $SSH_OPTIONS $service_file service:$service_basename" 806 | if ! $scp_cmd; then 807 | stax-error "failed to copy service file to service docker host: $scp_cmd" 808 | return 1 809 | fi 810 | stax-message " submitting service $service to fleet" "++++" 811 | submit_cmd="ssh $SSH_OPTIONS service fleetctl submit $service_basename" 812 | if ! $submit_cmd; then 813 | stax-error "failed to submit service to docker host: $submit_cmd" 814 | return 1 815 | fi 816 | stax-message " starting service $service in fleet" "++++" 817 | start_cmd="ssh $SSH_OPTIONS service fleetctl start $service_basename" 818 | if ! $start_cmd; then 819 | stax-error "failed to start service on docker host: $start_cmd" 820 | return 1 821 | fi 822 | stax-message " $service running on Docker service cluster" "++++" 823 | touch "$STAX_DIR/audit/$STAX_NAME/$(date +'%Y%m%d-%H%M%S')-fleetctl-started-service-$service" 824 | done 825 | } 826 | 827 | # ensure stax creation is complete 828 | stax-complete(){ 829 | wait="$1" 830 | stax-message "checking if stax build is complete" 831 | elapsed_time="0" 832 | sleep_int="30" 833 | while :; do 834 | if ! stax-describe; then 835 | stax-error "unable to get information about stax $STAX_NAME" 836 | return 1 837 | fi 838 | status=$($jq --raw-output '.Stacks[].StackStatus' "$STAX_DESC") 839 | if [[ $status == CREATE_COMPLETE ]]; then 840 | break 841 | elif [[ $status == UPDATE_COMPLETE ]]; then 842 | break 843 | elif [[ $status == UPDATE_IN_PROGRESS ]]; then 844 | stax-error "it appears the build is still updating: $status" 845 | return 1 846 | elif [[ $status != CREATE_IN_PROGRESS ]]; then 847 | stax-error "it appears the build failed: $status" 848 | return 1 849 | fi 850 | stax-message " stax build not complete: $status" 851 | if [[ $wait ]]; then 852 | stax-message " waiting for build to complete, sleeping $sleep_int seconds (elapsed $elapsed_time)" "zzzz" 853 | else 854 | return 1 855 | fi 856 | sleep $sleep_int 857 | elapsed_time=$(($elapsed_time+$sleep_int)) 858 | done 859 | stax-message " stack $STAX_NAME build complete" 860 | } 861 | 862 | stax-running-instances(){ 863 | aws --output json ec2 describe-instances --filter Name="instance-state-code",Values="16" | grep "\"Instances\"\:" | wc -l | sed 's/ //g' 864 | } 865 | 866 | stax-list(){ 867 | stax-message "list currently running stax" 868 | stax-message " querying aws for currently running stax" 869 | running_stax=$(aws --output json cloudformation list-stacks --stack-status-filter CREATE_COMPLETE UPDATE_COMPLETE | $jq --raw-output '.StackSummaries[].StackName' | grep "^$prefix-$pkg-") 870 | if [[ $? != 0 || ! $running_stax ]]; then 871 | #stax-error " aws query failed" 872 | stax-error " aws query failed or produced a blank set" 873 | stax-error " - this could be indicitive of an error" 874 | stax-error " unless this is a brand new instance, if so, ignore this error" 875 | #FIX ME - if query works but there are no instances, users gets error and we stop - account for that and keep going 876 | #return 1 877 | fi 878 | n_running_stax=$(echo "$running_stax" | wc -l) 879 | stax-message " $n_running_stax running stax" 880 | stax-message " (the * denotes one handled by local node)" 881 | my_stax=$(ls -1 "$STAX_DIR/audit") 882 | # put a * by one if it was launched from here 883 | for stack in $running_stax; do 884 | echo -n "$stack" 885 | for mine in $my_stax; do 886 | if [[ $stack == $mine ]]; then 887 | echo -n " *" 888 | fi 889 | done 890 | echo "" 891 | done 892 | stax-message "list currently running ec2 instances" 893 | stax-message " querying aws " 894 | n_running_ec2=$(stax-running-instances) 895 | stax-message " $n_running_ec2 running ec2 instances" 896 | } 897 | 898 | stax-services(){ 899 | stax-message "services that stax can run on the cluster" 900 | echo "{" 901 | ls -1 assets/services/*.service | cut -d"/" -f3 | cut -d"." -f1 902 | echo "}" 903 | } 904 | 905 | stax-start-service(){ 906 | if [ -z "$1" ]; then 907 | stax-error "you must provide a service name, exiting" 908 | return 10 909 | fi 910 | stax-message "starting timer for $service on the stax service cluster" "++++" 911 | service="$1" 912 | service_file="assets/services/$service.service" 913 | timer_file="assets/services/$service.timer" 914 | service_basename=${service_file##*/} 915 | timer_basename=${timer_file##*/} 916 | if [[ ! -f $service_file ]]; then 917 | stax-error "unknown service: $service" 918 | return 1 919 | fi 920 | 921 | if [[ -f $timer_file ]]; then 922 | stax-message "starting timer for $service on the stax service cluster" "++++" 923 | 924 | stax-message " copying $service_file to service docker host" "++++" 925 | scp_cmd="scp $SSH_OPTIONS $service_file service:$service_basename" 926 | if ! $scp_cmd; then 927 | stax-error "failed to copy service file to service docker host: $scp_cmd" 928 | return 1 929 | fi 930 | 931 | stax-message " copying $timer_file to service docker host" "++++" 932 | scp_cmd="scp $SSH_OPTIONS $timer_file service:$timer_basename" 933 | if ! $scp_cmd; then 934 | stax-error "failed to copy timer file to service docker host: $scp_cmd" 935 | return 1 936 | fi 937 | 938 | #fleetctl load dj.timer 939 | stax-message " loading timer $service to fleet" "++++" 940 | submit_cmd="ssh $SSH_OPTIONS service fleetctl load $timer_basename" 941 | if ! $submit_cmd; then 942 | stax-error "failed to submit timer to docker host: $submit_cmd" 943 | return 1 944 | fi 945 | 946 | #fleetctl load dj.service 947 | stax-message " loading service $service to fleet" "++++" 948 | submit_cmd="ssh $SSH_OPTIONS service fleetctl load $service_basename" 949 | if ! $submit_cmd; then 950 | stax-error "failed to submit service to docker host: $submit_cmd" 951 | return 1 952 | fi 953 | 954 | # fleetctl start dj.timer 955 | stax-message " starting timer $service in fleet" "++++" 956 | start_cmd="ssh $SSH_OPTIONS service fleetctl start $timer_basename" 957 | if ! $start_cmd; then 958 | stax-error "failed to start timer on docker host: $start_cmd" 959 | return 1 960 | fi 961 | stax-message " timer $service running on Docker service cluster - it will control $service_basename" "++++" 962 | else 963 | stax-message " copying $service_file to service docker host" "++++" 964 | scp_cmd="scp $SSH_OPTIONS $service_file service:$service_basename" 965 | if ! $scp_cmd; then 966 | stax-error "failed to copy service file to service docker host: $scp_cmd" 967 | return 1 968 | fi 969 | 970 | stax-message " submitting service $service to fleet" "++++" 971 | submit_cmd="ssh $SSH_OPTIONS service fleetctl submit $service_basename" 972 | if ! $submit_cmd; then 973 | stax-error "failed to submit service to docker host: $submit_cmd" 974 | return 1 975 | fi 976 | 977 | stax-message " starting service $service in fleet" "++++" 978 | start_cmd="ssh $SSH_OPTIONS service fleetctl start $service_basename" 979 | if ! $start_cmd; then 980 | stax-error "failed to start service on docker host: $start_cmd" 981 | return 1 982 | fi 983 | stax-message " $service running on Docker service cluster" "++++" 984 | fi 985 | touch "$STAX_DIR/audit/$STAX_NAME/$(date +'%Y%m%d-%H%M%S')-fleetctl-started-service-$service" 986 | } 987 | 988 | stax-fleetstats(){ 989 | stax-message "status from fleetctl on the service cluster" 990 | for fleet_cmd in "list-machines" "list-units" "list-unit-files"; do 991 | stax-message " running $fleet_cmd" 992 | if ! stax-connect service fleetctl $fleet_cmd; then 993 | stax-error "command failed on service host: fleetctl $fleet_cmd" 994 | return 1 995 | fi 996 | done 997 | } 998 | 999 | stax-history(){ 1000 | stax-message "history" 1001 | stax-message " recently created and deleted stax" 1002 | for stack in $(ls -dtr run/audit/*); do 1003 | echo "${stack##*/}:" 1004 | ls -1tr "$stack" | sed 's/^/ /' 1005 | done 1006 | } 1007 | 1008 | stax-sleep(){ 1009 | stax-existing 1010 | stax-describe 1011 | if [ ! -f "$STAX_BASTION_FILE" ]; then 1012 | stax-bastionip 1013 | fi 1014 | stax-message " checking bastion status in aws" 1015 | BASTION_IP=$($jq --raw-output '.Stacks[].Outputs[] | select(.OutputKey=="BastionEIP").OutputValue' "$STAX_DESC") 1016 | if [[ ! $BASTION_IP ]]; then 1017 | stax-error "unable to determine public IP address of bastion host" 1018 | return 1 1019 | fi 1020 | stax-message " instance IP = $BASTION_IP" 1021 | 1022 | BASTION_ID=`aws ec2 describe-addresses | $jq --raw-output '.Addresses[] | select(.PublicIp=="'$BASTION_IP'").InstanceId'` 1023 | if [[ ! $BASTION_ID ]]; then 1024 | stax-error "unable to determine instance ID of bastion host" 1025 | return 1 1026 | fi 1027 | stax-message " instance ID = $BASTION_ID" 1028 | 1029 | BASTION_STATUS=`aws ec2 describe-instances --instance-id $BASTION_ID | $jq --raw-output '.Reservations[].Instances[].State.Name'` 1030 | if [[ ! $BASTION_STATUS ]]; then 1031 | stax-error "unable to determine status of bastion host" 1032 | return 1 1033 | fi 1034 | stax-message " bastion status: $BASTION_STATUS" 1035 | 1036 | stax-message "Will toggle ssh access to $STAX_NAME bastion host" "++++" 1037 | if [[ $BASTION_STATUS == running ]]; then 1038 | ec2_cmd="stop-instances" 1039 | stax-message " stopping bastion host" 1040 | elif [[ $BASTION_STATUS == stopped ]]; then 1041 | ec2_cmd="start-instances" 1042 | stax-message " starting bastion host" 1043 | else 1044 | stax-error "unsupported instance state: $BASTION_STATUS" 1045 | return 1 1046 | fi 1047 | if ! aws ec2 $ec2_cmd --instance-id $BASTION_ID > /dev/null; then 1048 | stax-error "bastion toggle failed, exiting" 1049 | return 1 1050 | fi 1051 | stax-message " waiting 15 seconds for state change" "zzzz"; sleep 15 1052 | BASTION_STATUS=`aws ec2 describe-instances --instance-id $BASTION_ID|$jq --raw-output '.Reservations[].Instances[].State.Name'` 1053 | stax-message " bastion status: $BASTION_STATUS" 1054 | } 1055 | 1056 | stax-bastionip(){ 1057 | stax-message "getting public IP (EIP)" 1058 | if [[ ! $STAX_DESC ]]; then 1059 | stax-error "cannot call stax-bastionip without STAX_DESC defined" 1060 | return 10 1061 | fi 1062 | if [[ ! -f $STAX_DESC ]]; then 1063 | stax-error "stax description file not found: $STAX_DESC" 1064 | return 1 1065 | fi 1066 | STAX_BASTION_FILE="$STAX_DIR/$STAX_NAME.bastion" 1067 | STAX_PUB_IP=$($jq --raw-output '.Stacks[].Outputs[] | select(.OutputKey=="BastionEIP").OutputValue' "$STAX_DESC") 1068 | stax-message " public IP (EIP): $STAX_PUB_IP" 1069 | stax-message " writing to $STAX_BASTION_FILE" 1070 | echo "$STAX_PUB_IP" > "$STAX_BASTION_FILE" 1071 | } 1072 | 1073 | stax-getdockerips(){ 1074 | stax-message "get gateway and service IPs" 1075 | stax-message " querying aws for gateway hosts" 1076 | gateway_hosts="$STAX_DIR/$STAX_NAME.gateway_hosts" 1077 | if ! aws --output json ec2 describe-instances | $jq --raw-output ".Reservations[].Instances[] | select(.Tags[].Value==\"gateway-$STAX_NAME\").PrivateIpAddress" > "$gateway_hosts" 2>/dev/null; then 1078 | stax-error "failed to query aws for gateway instances" 1079 | return 1 1080 | fi 1081 | service_hosts="$STAX_DIR/$STAX_NAME.service_hosts" 1082 | > "$service_hosts" # truncate file 1083 | stax-message " getting service leaders" 1084 | for i in 1 2 3; do 1085 | if ! $jq --raw-output ".Stacks[].Outputs[] | select(.OutputKey==\"ServiceLeader${i}IP\").OutputValue" "$STAX_DIR/$STAX_NAME.json" >> "$service_hosts" 2>/dev/null; then 1086 | stax-error "failed to get IP for leader $i from $STAX_DIR/$STAX_NAME.json" 1087 | fi 1088 | done 1089 | stax-message " querying aws for service hosts" 1090 | if ! aws --output json ec2 describe-instances | $jq --raw-output ".Reservations[].Instances[] | select(.Tags[].Value==\"service-$STAX_NAME\").PrivateIpAddress" >> "$service_hosts" 2>/dev/null; then 1091 | stax-error "failed to query aws for service instances" 1092 | return 1 1093 | fi 1094 | elk_host="$STAX_DIR/$STAX_NAME.elk_host" 1095 | stax-message " getting elk host" 1096 | if ! aws --output json ec2 describe-instances | $jq --raw-output ".Reservations[].Instances[] | select(.Tags[].Value==\"elk-$STAX_NAME\").PrivateIpAddress" > "$elk_host" 2>/dev/null; then 1097 | stax-error "failed to get IP for elk host" 1098 | return 1 1099 | fi 1100 | } 1101 | 1102 | stax-connect(){ 1103 | target="bastion" 1104 | if [[ $1 ]]; then 1105 | target="$1" 1106 | shift 1107 | case "$target" in 1108 | bastion|gateway*|service*|elk) 1109 | :;; 1110 | *) 1111 | stax-error "unknown connection target: $target" 1112 | return 1 1113 | ;; 1114 | esac 1115 | fi 1116 | # only print message when no command supplied 1117 | if [[ $# == 0 ]]; then 1118 | stax-message "connecting to stax: $target" 1119 | fi 1120 | ssh_cmd="ssh $SSH_OPTIONS $target $@" 1121 | if ! $ssh_cmd; then 1122 | stax-error "ssh command failed: $ssh_cmd" 1123 | return 1 1124 | fi 1125 | } 1126 | 1127 | stax-delete-key(){ 1128 | stax-message "deleting key pair" 1129 | stax-message " making sure key $STAX_NAME exists in aws" 1130 | if ! aws ec2 describe-key-pairs --key-names "$STAX_NAME" > /dev/null 2>&1; then 1131 | stax-message " key $STAX_NAME does not exist in aws" 1132 | return 0 1133 | fi 1134 | stax-message " deleting $STAX_NAME key from aws" 1135 | status=0 1136 | if ! aws ec2 delete-key-pair --key-name "$STAX_NAME" > /dev/null; then 1137 | stax-error "failed to delete key $STAX_NAME, please remove it manually" 1138 | return 1 1139 | fi 1140 | rm -f $STAX_PUB_KEY $STAX_PRIV_KEY 1141 | } 1142 | 1143 | stax-delete-files(){ 1144 | stax-message "deleting local files" 1145 | if [[ ! $STAX_NAME ]]; then 1146 | stax-error "cannot delete files if STAX_NAME is not defined" 1147 | return 10 1148 | fi 1149 | stax-message " deleting $STAX_NAME files" 1150 | rm -f "$STAX_DIR/$STAX_NAME"* "$STAX_NAME_FILE" > /dev/null 1151 | } 1152 | 1153 | stax-delete-bucket(){ 1154 | stax-message "removing s3 bucket" 1155 | if [[ ! $STAX_NAME ]]; then 1156 | stax-error "cannot delete bucket if STAX_NAME is not defined" 1157 | return 10 1158 | fi 1159 | stax-message " making sure bucket $STAX_NAME exists in aws" 1160 | if ! aws --output json s3api list-buckets | $jq --raw-output '.Buckets[].Name' | grep -q "^$STAX_NAME$" > /dev/null 2>&1; then 1161 | stax-error "bucket $STAX_NAME does not exist" 1162 | return 1 1163 | fi 1164 | stax-message " removing s3 bucket $STAX_NAME" 1165 | if ! aws s3 rb --force "s3://$STAX_NAME" > /dev/null; then 1166 | stax-error "failed to delete 3 bucket $STAX_NAME, please remove it manually" 1167 | fi 1168 | } 1169 | 1170 | stax-delete(){ 1171 | stax-message "delete stax" 1172 | if [[ $yes != y ]]; then 1173 | read -p "${yellow}[ ${cyan}????${yellow} ]${reset} ok to delete $STAX_NAME [y/n]? " answer 1174 | if [[ $answer != y ]] ; then 1175 | stax-message " will not delete $STAX_NAME" 1176 | return 0 1177 | fi 1178 | fi 1179 | stop= 1180 | # remove any databases 1181 | if [[ -f $STAX_DIR/$STAX_NAME.rds ]]; then 1182 | for rds in $($tac "$STAX_DIR/$STAX_NAME.rds"); do 1183 | if [[ $yes != y ]]; then 1184 | read -p "${yellow}[ ${cyan}????${yellow} ]${reset} ok to delete $rds [y/n]? " answer 1185 | if [[ $answer != y ]] ; then 1186 | stax-message " will not delete $addition" 1187 | stop=1 1188 | continue 1189 | fi 1190 | fi 1191 | if ! stax-rds-delete "$rds"; then 1192 | stax-error "failed to remove rds: $rds" 1193 | stax-error "continuing but deleting stax will likely fail" 1194 | fi 1195 | done 1196 | fi 1197 | # remove any additions 1198 | if [[ -f $STAX_DIR/$STAX_NAME.add ]]; then 1199 | for addition in $($tac "$STAX_DIR/$STAX_NAME.add"); do 1200 | if [[ $yes != y ]]; then 1201 | read -p "${yellow}[ ${cyan}????${yellow} ]${reset} ok to delete $addition [y/n]? " answer 1202 | if [[ $answer != y ]] ; then 1203 | stax-message " will not delete $addition" 1204 | stop=1 1205 | continue 1206 | fi 1207 | fi 1208 | if ! stax-remove "$addition"; then 1209 | stax-error "failed to remove addition: $addition" 1210 | stax-error "continuing but deleting stax will likely fail" 1211 | fi 1212 | done 1213 | fi 1214 | if [[ $stop ]]; then 1215 | stax-error "you chose not to remove some additions, so we will not attempt to delete the stack" 1216 | return 1 1217 | fi 1218 | if [[ -d $STAX_DIR/audit/$STAX_NAME-logger ]]; then 1219 | touch "$STAX_DIR/audit/$STAX_NAME-logger/$date-deleted-logger" 1220 | fi 1221 | stax-message "deleting $STAX_NAME stax" 1222 | if ! aws cloudformation delete-stack --stack-name "$STAX_NAME" > /dev/null; then 1223 | stax-error "stax delete of $STAX_NAME failed" 1224 | stax-error "you will need to clean up the stack, key, bucket, and files" 1225 | return 1 1226 | fi 1227 | stax-message " delete started successfully" 1228 | touch "$STAX_DIR/audit/$STAX_NAME/$(date +'%Y%m%d-%H%M%S')-delete" 1229 | status=0 1230 | if ! stax-delete-bucket; then 1231 | status=2 1232 | fi 1233 | if ! stax-delete-key; then 1234 | status=2 1235 | fi 1236 | if ! stax-delete-files; then 1237 | status=2 1238 | fi 1239 | return $status 1240 | } 1241 | 1242 | stax-generate-random(){ 1243 | random_num=$((RANDOM%100000+10000)) 1244 | if [[ ! $random_num || $random_num < 10000 ]]; then 1245 | stax-error "failed to generate random number" 1246 | return 1 1247 | fi 1248 | stax_words="assets/stax/words" 1249 | if [[ ! -f $stax_words ]]; then 1250 | stax-error "stax words file is missing: $stax_words" 1251 | return 1 1252 | fi 1253 | numw=$(wc -l < "$stax_words" | tr -d ' ') 1254 | if [[ ! $numw || $numw < 1 ]]; then 1255 | stax-error "failed to get number of words in words file: $stax_words" 1256 | return 1 1257 | fi 1258 | random_name=$(head -n $(($RANDOM % $numw + 1)) $stax_words | tail -n 1) 1259 | if [[ ! $random_name ]]; then 1260 | stax-error "failed to generate random name" 1261 | return 1 1262 | fi 1263 | echo "$random_num-$random_name" 1264 | } 1265 | 1266 | # bootstrap: set up STAX_NAME 1267 | prefix="vpc" 1268 | stax-generate(){ 1269 | if [[ $1 ]]; then 1270 | prefix="$1" 1271 | fi 1272 | postfix=$(stax-generate-random) 1273 | if [[ $? != 0 ]]; then 1274 | stax-error "failed to generate random part of name: $postfix" 1275 | return 1 1276 | fi 1277 | STAX_NAME="$prefix-$pkg-$postfix" 1278 | } 1279 | 1280 | # FIXME: combine the config functions into one 1281 | # generate parameters file 1282 | stax-config(){ 1283 | stax-message "creating parameter file" 1284 | # verify config is filled out 1285 | if [[ ! -f $config ]]; then 1286 | stax-error "config file does not exist: $config" 1287 | stax-error "configuration required" 1288 | stax-error "copy example to config directory, configure it and run again." 1289 | stax-error " $ cp $config.example $config" 1290 | return 1 1291 | fi 1292 | # make sure they did not just copy the file and not edit 1293 | if grep -q '' "$config" > /dev/null 2>&1; then 1294 | stax-error "you did not provide valid values for some parameters in the config: $config" 1295 | default_params="$($jq --raw-output '.[] | select(.ParameterValue=="").ParameterKey' $config | xargs)" 1296 | stax-error "parameters with invalid defaults: $default_params" 1297 | return 1 1298 | fi 1299 | # initialize sed command 1300 | sed="sed -e s/@KEY_NAME@/$STAX_NAME/" 1301 | # check what subsitutions need to be done 1302 | if grep -q '@OWNER@' "$config" > /dev/null 2>&1; then 1303 | owner="$(id -u -n)" 1304 | if [[ -z $owner ]]; then 1305 | stax-error "failed to determine user" 1306 | return 1 1307 | fi 1308 | sed="$sed -e s/@OWNER@/$owner/" 1309 | fi 1310 | external_cidr="$(curl -s http://icanhazip.com)/32" 1311 | if [[ -z $external_cidr ]]; then 1312 | stax-error "failed to get external IP address for local machine" 1313 | fi 1314 | if grep -q '@HTTP_FROM@' "$config" > /dev/null 2>&1; then 1315 | if [[ ! $external_cidr ]]; then 1316 | stax-error "config requests replacement for @HTTP_FROM@ but unable to determine external IP" 1317 | return 1 1318 | fi 1319 | sed="$sed -e s|@HTTP_FROM@|$external_cidr|" 1320 | fi 1321 | if grep -q '@SSH_FROM@' "$config" > /dev/null 2>&1; then 1322 | if [[ $STAX_JUMP ]]; then 1323 | ssh_from="$STAX_JUMP/32" 1324 | else 1325 | if [[ ! $external_cidr ]]; then 1326 | stax-error "config requests replacement for @SSH_FROM@ but unable to determine external IP" 1327 | return 1 1328 | fi 1329 | ssh_from="$external_cidr" 1330 | fi 1331 | sed="$sed -e s|@SSH_FROM@|$ssh_from|" 1332 | fi 1333 | STAX_PARAMS="$STAX_DIR/$STAX_NAME.params" 1334 | if ! $sed "$config" > "$STAX_PARAMS"; then 1335 | stax-error "sed failed to replace elements in $config: $sed" 1336 | return 1 1337 | fi 1338 | } 1339 | 1340 | # generate add parameters file 1341 | stax-add-config(){ 1342 | stax-message "creating parameter file for add" 1343 | if [[ ! $1 ]]; then 1344 | stax-error "you must supply the config file path when calling stax-add-config" 1345 | return 10 1346 | fi 1347 | config="$1" 1348 | # verify config is filled out 1349 | if [[ ! -f $config ]]; then 1350 | stax-error "config file does not exist: $config" 1351 | stax-error "configuration required" 1352 | stax-error "copy example to config directory, configure it and run again." 1353 | stax-error " $ cp rds.json.example rds.json" 1354 | return 1 1355 | fi 1356 | if ! grep -q '@VPC_ID@' "$config" > /dev/null 2>&1; then 1357 | stax-error "the replacement string @VPC_ID@ does not appear in the config: $config" 1358 | stax-error "refusing to continue since this does not appear to be adding to an existing vpc" 1359 | return 1 1360 | fi 1361 | vpc_id=$($jq --raw-output '.Stacks[].Outputs[] | select(.OutputKey=="VPCID").OutputValue' "$STAX_DIR/$STAX_NAME.json") 1362 | if [[ ! $vpc_id ]]; then 1363 | stax-error "failed to determine vpc id" 1364 | return 1 1365 | fi 1366 | sed="sed -e s/@VPC_ID@/$vpc_id/" 1367 | if grep -q '@SERVICE_SG_ID@' "$config" > /dev/null 2>&1; then 1368 | service_sg_id=$($jq --raw-output '.Stacks[].Outputs[] | select(.OutputKey=="ServiceCoreOSSecurityGroup").OutputValue' "$STAX_DIR/$STAX_NAME.json") 1369 | if [[ ! $service_sg_id ]]; then 1370 | stax-error "failed to determine service security group id" 1371 | return 1 1372 | fi 1373 | sed="$sed -e s/@SERVICE_SG_ID@/$service_sg_id/" 1374 | fi 1375 | if grep -q '@OWNER@' "$config" > /dev/null 2>&1; then 1376 | owner="$(id -u -n)" 1377 | if [[ -z $owner ]]; then 1378 | stax-error "failed to determine user" 1379 | return 1 1380 | fi 1381 | sed="$sed -e s/@OWNER@/$owner/" 1382 | fi 1383 | STAX_ADD_PARAMS="$STAX_DIR/$STAX_NAME_ADD.params" 1384 | stax-message " building params file: $STAX_ADD_PARAMS" 1385 | if ! $sed "$config" > "$STAX_ADD_PARAMS"; then 1386 | stax-error "sed failed to replace elements in $config: $sed $config > $STAX_ADD_PARAMS" 1387 | return 1 1388 | fi 1389 | } 1390 | 1391 | # stax-rds PASSWORD [NAME USER ENGINE SIZE INSTANCE_CLASS STORAGE_TYPE] 1392 | stax-rds(){ 1393 | stax-message "creating rds instance" 1394 | if [[ $# < 1 ]]; then 1395 | stax-error "you must provide a password when calling stax-rds" 1396 | return 10 1397 | fi 1398 | password="$1" 1399 | name="test" 1400 | user="tester" 1401 | engine="postgres" 1402 | size="5" 1403 | instance_class="db.m3.medium" 1404 | storage_type="gp2" 1405 | if [[ $2 ]]; then name="$2"; fi 1406 | if [[ $3 ]]; then user="$3"; fi 1407 | if [[ $4 ]]; then engine="$4"; fi 1408 | if [[ $5 ]]; then size="$5"; fi 1409 | if [[ $6 ]]; then instance_class="$6"; fi 1410 | if [[ $7 ]]; then storage_type="$7"; fi 1411 | rds_name=$(stax-generate-random) 1412 | if [[ $? != 0 ]]; then 1413 | stax-error "failed to generate name for add" 1414 | return 1 1415 | fi 1416 | STAX_NAME_RDS="$STAX_NAME-rds-$rds_name" 1417 | stax-message "$STAX_NAME_RDS" "NAME" 1418 | db_subnet_group=$($jq --raw-output '.Stacks[].Outputs[] | select(.OutputKey=="DBSubnetGroup").OutputValue' "$STAX_DIR/$STAX_NAME.json") 1419 | if [[ $? != 0 || ! $db_subnet_group ]]; then 1420 | stax-error "failed to determine db subnet group" 1421 | return 1 1422 | fi 1423 | stax-message " using db subnet $db_subnet_group" 1424 | vpc_sg_id=$($jq --raw-output '.Stacks[].Outputs[] | select(.OutputKey=="DBVPCSecurityGroup").OutputValue' "$STAX_DIR/$STAX_NAME.json") 1425 | if [[ $? != 0 || ! $vpc_sg_id ]]; then 1426 | stax-error "failed to determine vpc security group id" 1427 | return 1 1428 | fi 1429 | stax-message " using vpc security group $vpc_sg_id" 1430 | owner="$(id -u -n)" 1431 | if [[ $? != 0 || ! $owner ]]; then 1432 | stax-error "failed to determine user" 1433 | return 1 1434 | fi 1435 | stax-message " extracting tags from parameter file" 1436 | tags="[{\"Key\":\"stax:name\",\"Value\":\"$STAX_NAME\"},{\"Key\":\"$tag_prefix:owner\",\"Value\":\"$owner\"}" 1437 | for param in Project Group Environment CostCenter KeepAlive; do 1438 | new_tag=$(stax-parameter-tag "$param") 1439 | if [[ $? != 0 ]]; then 1440 | stax-error "failed to extract tag: $new_tag" 1441 | stax-error "you must specify the value for parameter $param in the config" 1442 | return 1 1443 | fi 1444 | tags="$tags,$new_tag" 1445 | done 1446 | tags="$tags]" 1447 | stax-message " using tags: $tags" 1448 | stax-message " creating rds instance $STAX_NAME_RDS" 1449 | if ! aws rds create-db-instance \ 1450 | --db-name "$name" \ 1451 | --db-instance-identifier "$STAX_NAME_RDS" \ 1452 | --allocated-storage "$size" \ 1453 | --db-instance-class "$instance_class" \ 1454 | --engine "$engine" \ 1455 | --master-username "$user" \ 1456 | --master-user-password "$password" \ 1457 | --vpc-security-group-ids "$vpc_sg_id" \ 1458 | --db-subnet-group-name "$db_subnet_group" \ 1459 | --backup-retention-period "7" \ 1460 | --multi-az \ 1461 | --no-publicly-accessible \ 1462 | --storage-type "$storage_type" \ 1463 | --storage-encrypted \ 1464 | --tags "$tags" > /dev/null 1465 | then 1466 | stax-error "failed to create rds instance" 1467 | return 1 1468 | fi 1469 | date=$(date +'%Y%m%d-%H%M%S') 1470 | touch "$STAX_DIR/audit/$STAX_NAME/$date-rds-$STAX_NAME_RDS" 1471 | if ! echo "$STAX_NAME_RDS" >> "$STAX_DIR/$STAX_NAME.rds"; then 1472 | stax-error "failed to add $STAX_NAME_RDS to RDS file: $STAX_DIR/$STAX_NAME.rds" 1473 | stax-error "this will create problems when trying to delete this stack" 1474 | return 2 1475 | fi 1476 | stax-message " rds creation complete" 1477 | } 1478 | 1479 | stax-rds-delete(){ 1480 | stax-message "removing rds" 1481 | if [[ ! $1 ]]; then 1482 | stax-error "stax-remove: you must supply the name of the rds to remove" 1483 | return 10 1484 | fi 1485 | rds="$1" 1486 | stax-message " removing $rds" 1487 | if ! grep -q "^$rds\$" "$STAX_DIR/$STAX_NAME.rds" > /dev/null 2>&1; then 1488 | stax-error "unknown rds: $rds" 1489 | return 1 1490 | fi 1491 | if ! aws rds delete-db-instance \ 1492 | --db-instance-identi "$rds" \ 1493 | --no-skip-final-snapshot \ 1494 | --final-db-snapshot-identifier "$rds-final" > /dev/null 1495 | then 1496 | stax-error "failed to remove rds: $rds" 1497 | return 1 1498 | fi 1499 | if ! sed -i.bak "/^$rds\$/d" "$STAX_DIR/$STAX_NAME.rds"; then 1500 | stax-error "failed to remove $rds from $STAX_DIR/$STAX_NAME.rds" 1501 | stax-error "this may cause problems when deleting the stack" 1502 | return 2 1503 | fi 1504 | rm -f "$STAX_DIR/$STAX_NAME.rds.bak" 1505 | stax-message " removal complete" 1506 | date=$(date +'%Y%m%d-%H%M%S') 1507 | touch "$STAX_DIR/audit/$STAX_NAME/$date-removed-$rds" 1508 | } 1509 | 1510 | stax-slack(){ 1511 | if [ ! -z "$STAX_SLACK_WHOOK" ]; then 1512 | stax-message "posting results to slack/#stax" 1513 | report= 1514 | if [[ $1 ]]; then 1515 | status="$1" 1516 | fi 1517 | slack_curl="curl --silent -X POST --data-urlencode" 1518 | user=$(id -u -n) 1519 | slack_payload_prefix="payload={\"channel\":\"#stax\",\"username\":\"staxbot\",\"icon_emoji\":\":ghost:\",\"text\":\"$user@$host:" 1520 | if [[ $status ]]; then 1521 | slack_payload="$slack_payload_prefix $status $STAX_NAME\"}" 1522 | $slack_curl "$slack_payload" $STAX_SLACK_WHOOK > /dev/null 1523 | fi 1524 | slack_instances=$(stax-running-instances) 1525 | slack_payload="$slack_payload_prefix currently $slack_instances running ec2 instances\"}" 1526 | $slack_curl "$slack_payload" $STAX_SLACK_WHOOK > /dev/null 1527 | else 1528 | return 1 1529 | fi 1530 | } 1531 | 1532 | # automated test 1533 | stax-test-create(){ 1534 | stax-message "building test stax" 1535 | if [[ ! $1 ]]; then 1536 | stax-error-exit "stax-test takes the template path as an argument" 10 1537 | fi 1538 | template_path="$1" 1539 | stax-message " create dummy parameter config" 1540 | user=$(id -u -n) 1541 | config="$STAX_DIR/test-config-$user-$$-$RANDOM.json" 1542 | if ! cat > "$config" <AWS CloudFormation sample PHP application';\n", 304 | "?>\n" 305 | ]]}, 306 | "mode" : "000644", 307 | "owner" : "apache", 308 | "group" : "apache" 309 | }, 310 | 311 | 312 | "/etc/cfn/cfn-hup.conf" : { 313 | "content" : { "Fn::Join" : ["", [ 314 | "[main]\n", 315 | "stack=", { "Ref" : "AWS::StackId" }, "\n", 316 | "region=", { "Ref" : "AWS::Region" }, "\n" 317 | ]]}, 318 | "mode" : "000400", 319 | "owner" : "root", 320 | "group" : "root" 321 | }, 322 | 323 | "/etc/cfn/hooks.d/cfn-auto-reloader.conf" : { 324 | "content": { "Fn::Join" : ["", [ 325 | "[cfn-auto-reloader-hook]\n", 326 | "triggers=post.update\n", 327 | "path=Resources.WebServerInstance.Metadata.AWS::CloudFormation::Init\n", 328 | "action=/opt/aws/bin/cfn-init -s ", { "Ref" : "AWS::StackId" }, " -r WebServerInstance ", 329 | " --region ", { "Ref" : "AWS::Region" }, "\n", 330 | "runas=root\n" 331 | ]]} 332 | } 333 | }, 334 | 335 | "services" : { 336 | "sysvinit" : { 337 | "httpd" : { "enabled" : "true", "ensureRunning" : "true" }, 338 | "sendmail" : { "enabled" : "false", "ensureRunning" : "false" } 339 | } 340 | } 341 | } 342 | } 343 | }, 344 | "Properties" : { 345 | "ImageId" : { "Fn::FindInMap" : [ "RegionMap", { "Ref" : "AWS::Region" }, "AMI" ]}, 346 | "SecurityGroupIds" : [{ "Ref" : "InstanceSecurityGroup" }], 347 | "SubnetId" : { "Ref" : "Subnet" }, 348 | "InstanceType" : { "Ref" : "InstanceType" }, 349 | "KeyName" : { "Ref" : "KeyName" }, 350 | "Monitoring" : "true", 351 | "Tags" : [ {"Key" : "Application", "Value" : { "Ref" : "AWS::StackId"} } ], 352 | "UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [ 353 | "#!/bin/bash\n", 354 | "yum update -y aws-cfn-bootstrap\n", 355 | 356 | "# Helper function\n", 357 | "function error_exit\n", 358 | "{\n", 359 | " /opt/aws/bin/cfn-signal -e 1 -r \"$1\" '", { "Ref" : "WebServerWaitHandle" }, "'\n", 360 | " exit 1\n", 361 | "}\n", 362 | 363 | "# Install the simple web page\n", 364 | "/opt/aws/bin/cfn-init -s ", { "Ref" : "AWS::StackId" }, " -r WebServerInstance ", 365 | " --region ", { "Ref" : "AWS::Region" }, " || error_exit 'Failed to run cfn-init'\n", 366 | 367 | "# Start up the cfn-hup daemon to listen for changes to the Web Server metadata\n", 368 | "/opt/aws/bin/cfn-hup || error_exit 'Failed to start cfn-hup'\n", 369 | 370 | "# All done so signal success\n", 371 | "/opt/aws/bin/cfn-signal -e 0 -r \"WebServer setup complete\" '", { "Ref" : "WebServerWaitHandle" }, "'\n" 372 | ]]}} 373 | } 374 | }, 375 | 376 | "WebServerWaitHandle" : { 377 | "Type" : "AWS::CloudFormation::WaitConditionHandle" 378 | }, 379 | 380 | "WebServerWaitCondition" : { 381 | "Type" : "AWS::CloudFormation::WaitCondition", 382 | "DependsOn" : "WebServerInstance", 383 | "Properties" : { 384 | "Handle" : {"Ref" : "WebServerWaitHandle"}, 385 | "Timeout" : "300" 386 | } 387 | } 388 | }, 389 | 390 | "Outputs" : { 391 | "BastionEIP": { 392 | "Description": "WebServer IP Address", 393 | "Value": {"Ref": "IPAddress"} 394 | }, 395 | "URL" : { 396 | "Value" : { "Fn::Join" : [ "", ["http://", { "Fn::GetAtt" : ["WebServerInstance", "PublicIp"] }]]}, 397 | "Description" : "Newly created application URL" 398 | } 399 | } 400 | } 401 | -------------------------------------------------------------------------------- /template/vpc-default.services.example: -------------------------------------------------------------------------------- 1 | nginx 2 | myapp 3 | --------------------------------------------------------------------------------