prepd 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/CODE_OF_CONDUCT.md +49 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +335 -0
- data/Rakefile +2 -0
- data/TODO.md +17 -0
- data/bin/console +4 -0
- data/bin/setup +8 -0
- data/exe/prepd +6 -0
- data/lib/prepd/cli/commands.rb +37 -0
- data/lib/prepd/cli/options_parser.rb +42 -0
- data/lib/prepd/cli.rb +8 -0
- data/lib/prepd/models.rb +261 -0
- data/lib/prepd/schema.rb +23 -0
- data/lib/prepd/version.rb +3 -0
- data/lib/prepd.rb +47 -0
- data/prepd.gemspec +31 -0
- metadata +163 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 7da5fcedfd696ae8ed02c72983c3580aa81ebdb2
|
4
|
+
data.tar.gz: 5ff634d081c083161b62fef9b55506d7ffe0c0d8
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: eed08a0948cc105d1c88bc4ef489e35fd0dce5f5429c731c3f708689cc18ea14aee2f9413fdc85fce2c5fa926c93eb4b50203f80a221dc01c9ac4a15984fe770
|
7
|
+
data.tar.gz: 5d687fbcbc00fcb87c2d0c1f25e619ac0532f640220daea216be2f7fcb7d6243010a42328fe90e2249cb579130427c762325aedcd1103eb57851b565b22c6d62
|
data/.gitignore
ADDED
data/CODE_OF_CONDUCT.md
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
# Contributor Code of Conduct
|
2
|
+
|
3
|
+
As contributors and maintainers of this project, and in the interest of
|
4
|
+
fostering an open and welcoming community, we pledge to respect all people who
|
5
|
+
contribute through reporting issues, posting feature requests, updating
|
6
|
+
documentation, submitting pull requests or patches, and other activities.
|
7
|
+
|
8
|
+
We are committed to making participation in this project a harassment-free
|
9
|
+
experience for everyone, regardless of level of experience, gender, gender
|
10
|
+
identity and expression, sexual orientation, disability, personal appearance,
|
11
|
+
body size, race, ethnicity, age, religion, or nationality.
|
12
|
+
|
13
|
+
Examples of unacceptable behavior by participants include:
|
14
|
+
|
15
|
+
* The use of sexualized language or imagery
|
16
|
+
* Personal attacks
|
17
|
+
* Trolling or insulting/derogatory comments
|
18
|
+
* Public or private harassment
|
19
|
+
* Publishing other's private information, such as physical or electronic
|
20
|
+
addresses, without explicit permission
|
21
|
+
* Other unethical or unprofessional conduct
|
22
|
+
|
23
|
+
Project maintainers have the right and responsibility to remove, edit, or
|
24
|
+
reject comments, commits, code, wiki edits, issues, and other contributions
|
25
|
+
that are not aligned to this Code of Conduct, or to ban temporarily or
|
26
|
+
permanently any contributor for other behaviors that they deem inappropriate,
|
27
|
+
threatening, offensive, or harmful.
|
28
|
+
|
29
|
+
By adopting this Code of Conduct, project maintainers commit themselves to
|
30
|
+
fairly and consistently applying these principles to every aspect of managing
|
31
|
+
this project. Project maintainers who do not follow or enforce the Code of
|
32
|
+
Conduct may be permanently removed from the project team.
|
33
|
+
|
34
|
+
This code of conduct applies both within project spaces and in public spaces
|
35
|
+
when an individual is representing the project or its community.
|
36
|
+
|
37
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
38
|
+
reported by contacting a project maintainer at rjayroach@gmail.com. All
|
39
|
+
complaints will be reviewed and investigated and will result in a response that
|
40
|
+
is deemed necessary and appropriate to the circumstances. Maintainers are
|
41
|
+
obligated to maintain confidentiality with regard to the reporter of an
|
42
|
+
incident.
|
43
|
+
|
44
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
45
|
+
version 1.3.0, available at
|
46
|
+
[http://contributor-covenant.org/version/1/3/0/][version]
|
47
|
+
|
48
|
+
[homepage]: http://contributor-covenant.org
|
49
|
+
[version]: http://contributor-covenant.org/version/1/3/0/
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2016 Robert Roach
|
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
|
13
|
+
all 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
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,335 @@
|
|
1
|
+
# Prepd
|
2
|
+
|
3
|
+
Prepd - A Production Ready Environment for Project Development
|
4
|
+
|
5
|
+
One of the core principles of Agile Development is delivering viewable results
|
6
|
+
to the business from Week 1. Too often product developement begins with the
|
7
|
+
application software, while the infrastructure to deploy into is addressed as
|
8
|
+
and when it is needed.
|
9
|
+
|
10
|
+
Thankfully, many web application products get to market on similar,
|
11
|
+
if not identical, infrastructure. However setting up this infastructure takes time,
|
12
|
+
is error prone and typically is non-repeatable ending up as a unique snowflake.
|
13
|
+
|
14
|
+
To avoid this, many development teams turn to a PaaS service such as Heroku.
|
15
|
+
This has limitations and only addresses the final deployment infrastructure.
|
16
|
+
|
17
|
+
Prepd aims to address this by providing a 'convention over configruation' approach
|
18
|
+
to provisioning infrastructure. From local developer machines (vagrant running linux
|
19
|
+
on the developer's laptop) to staging and production running a docker swarm cluster.
|
20
|
+
|
21
|
+
With microservices becoming a common application development strategy, prepd
|
22
|
+
aims to make it dead simple to build and deploy a microservice based application.
|
23
|
+
Beginning with the end in mind, Prepd offers a simple, conventional way to provision
|
24
|
+
all this infrastructure, including CI workflow, secrets managment, 12-factor apps
|
25
|
+
|
26
|
+
Agile Development requires 'near production' infrastructure to be in place from Day 1.
|
27
|
+
Using Prepd, makes that possible quickly and easily without resorting to a PaaS provider.
|
28
|
+
|
29
|
+
## Focus
|
30
|
+
|
31
|
+
The focus of Prepd is on enabling developers to build and deploy applications following current
|
32
|
+
industry best practices with as little effort as possible. Being flexible and configurable
|
33
|
+
for the wide variety of application deployment strategies is currently a secondary goal to
|
34
|
+
getting something up and running. Therefore, choices are made:
|
35
|
+
|
36
|
+
1. Infrastructure is provisioned via:
|
37
|
+
..* Vagrantfile on local machines for development and a local cluster
|
38
|
+
..* Terraform plans for clutser infrastructure exclusively on AWS
|
39
|
+
2. Ansible is the automation tool used to configure the infrastructure for application deployment
|
40
|
+
3. Docker conatainer deployment is currently the only method for deploying applications
|
41
|
+
4. The development environment currently supports:
|
42
|
+
..* Postgres and Redis for data storage
|
43
|
+
..* Rails and Ember for application development
|
44
|
+
|
45
|
+
A future goal for Prepd is to enable more application types and tool support
|
46
|
+
|
47
|
+
# What is a Production Ready Environment?
|
48
|
+
|
49
|
+
It takes a lot of services tuned to work together to make smoothly running infrastructure
|
50
|
+
|
51
|
+
## Networking
|
52
|
+
- Domain names figured out and DNS running on Route53 etc
|
53
|
+
- Ability to programatically change and update DNS
|
54
|
+
- SSL certs are already installed so we do TLS from the beginning on all publicly available infrastructure
|
55
|
+
- Load Balancing is setup, configured and running in at least staging and production, but also possible in development
|
56
|
+
|
57
|
+
## Development Pipeline Required Services
|
58
|
+
|
59
|
+
Prepd provisions and configures the infrastructure and provides a tool to deploy applications into the infrastructure.
|
60
|
+
However, certain aspects of the pipeline are expected to be provided outside of Prepd, which are:
|
61
|
+
|
62
|
+
- Continuous Integration
|
63
|
+
- Container Build and Store
|
64
|
+
|
65
|
+
### Continuous Integration
|
66
|
+
|
67
|
+
CI is expected to be setup and configured as part of an automated deploy process from the outset of the project.
|
68
|
+
Here is an example overview of using CircleCI to test a Rails API application
|
69
|
+
|
70
|
+
- Create an account on CircleCI and link it to your GitHub account. Authorize CircleCI to access the account
|
71
|
+
- Add the Rails API repository as a project on CircleCI. If using rails-templates a circle.yml project already exists
|
72
|
+
- Configure slack notifications for when a build completes
|
73
|
+
|
74
|
+
### Container Build and Store
|
75
|
+
|
76
|
+
A container repository that also builds containers is expected to be provided.
|
77
|
+
Here is an example overview of using quay.io to build a Rails API application container
|
78
|
+
|
79
|
+
- Create an account on quay.io and link it to your GitHub account. Authorize quay.io to access the account
|
80
|
+
- Add the Rails API repository as a docker repository on quay.io
|
81
|
+
- Create a trigger to build the container when there is a push on a certain branch of the GitHub repository
|
82
|
+
|
83
|
+
Prepd provides ansible playbooks that invoke docker compose to deploy the container from quay.io to the target infrastructure
|
84
|
+
|
85
|
+
## Application Services (TODO)
|
86
|
+
|
87
|
+
Prepd will be augmented to provide playbooks for the default Application Group as well as Terraform plans that provide:
|
88
|
+
|
89
|
+
- Communication Services, e.g. SMTP, SNS (Push), Slack webhooks, Twilio, etc
|
90
|
+
- Logging in both local/development and in staging/production with ELK
|
91
|
+
- Monitoring/alert service (Prometheus)
|
92
|
+
- Additional common 3rd party services as needed
|
93
|
+
|
94
|
+
## Swarm Load Balancing
|
95
|
+
- network overlays
|
96
|
+
- load balancing between micro services
|
97
|
+
- manage cluster scaling with compose/swarm mode/ansible or some combination thereof
|
98
|
+
|
99
|
+
|
100
|
+
# Installation
|
101
|
+
|
102
|
+
Prepd is a ruby gem. It also requires software on the local laptop, including VirtualBox, Vagrant and Ansible
|
103
|
+
|
104
|
+
```bash
|
105
|
+
gem install prepd
|
106
|
+
```
|
107
|
+
|
108
|
+
## Automated Installation of Dependencies (TODO)
|
109
|
+
|
110
|
+
With the gem installed, navigate to it's directory and run bootstrap.sh to install dependencies
|
111
|
+
|
112
|
+
```bash
|
113
|
+
bundle cd prepd
|
114
|
+
./bootstrap.sh
|
115
|
+
```
|
116
|
+
|
117
|
+
This will:
|
118
|
+
|
119
|
+
- Install ansible
|
120
|
+
- Clone the ansible-roles repository
|
121
|
+
- Run ansible to install Virtualbox and Vagrant
|
122
|
+
|
123
|
+
## Manual Installation of Dependencies
|
124
|
+
|
125
|
+
### Ansible
|
126
|
+
|
127
|
+
Tested with version 2.2.0
|
128
|
+
|
129
|
+
#### Install on MacOS
|
130
|
+
|
131
|
+
If planning to install on a clean machine:
|
132
|
+
1. Wipe Mac: http://support.apple.com/kb/PH13871 OR http://support.apple.com/en-us/HT201376
|
133
|
+
2. Create New User with Admin rights
|
134
|
+
|
135
|
+
Install Homebrew:
|
136
|
+
|
137
|
+
```bash
|
138
|
+
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
|
139
|
+
```
|
140
|
+
|
141
|
+
Install python with zlib and ssl support
|
142
|
+
|
143
|
+
```bash
|
144
|
+
xcode-select --install
|
145
|
+
brew install openssl
|
146
|
+
brew link openssl --force
|
147
|
+
brew uninstall python
|
148
|
+
brew install python --with-brewed-openssl
|
149
|
+
sudo easy_install pip
|
150
|
+
sudo pip install -U ansible
|
151
|
+
sudo pip install -U setuptools cryptography markupsafe
|
152
|
+
sudo pip install -U ansible boto
|
153
|
+
```
|
154
|
+
|
155
|
+
#### Install on Ubuntu
|
156
|
+
|
157
|
+
```bash
|
158
|
+
apt-get install ansible
|
159
|
+
```
|
160
|
+
|
161
|
+
### VirtualBox
|
162
|
+
|
163
|
+
Install VirtualBox from [here](https://www.virtualbox.org/wiki/Downloads)
|
164
|
+
|
165
|
+
### Vagrant
|
166
|
+
|
167
|
+
Install Vagrant from [here](https://www.vagrantup.com/docs/installation/)
|
168
|
+
|
169
|
+
```bash
|
170
|
+
vagrant plugin install vagrant-vbguest # keep your VirtualBox Guest Additions up to date
|
171
|
+
vagrant plugin install vagrant-cachier # caches guest packages
|
172
|
+
vagrant plugin install vagrant-hostmanager # updates /etc/hosts file when machines go up/down
|
173
|
+
```
|
174
|
+
|
175
|
+
#### vagrant-hostmanager
|
176
|
+
This plugin automatically updates the host's /etc/hosts file when vagrant machines go up/down
|
177
|
+
|
178
|
+
In order to do that it needs sudo password or sudo priviledges.
|
179
|
+
To avoid being asked for the password every time the hosts file is updated,
|
180
|
+
[enable passwordless sudo](https://github.com/devopsgroup-io/vagrant-hostmanager#passwordless-sudo)
|
181
|
+
for the specific command that hostmanager uses to update the hosts file
|
182
|
+
|
183
|
+
|
184
|
+
# Prepd Actors
|
185
|
+
|
186
|
+
A Client may have multiples projects. Applications share common infrastructure that is defined by the Project
|
187
|
+
|
188
|
+
- Client: An organization with one or more projects, e.g Acme Corp
|
189
|
+
- Project: A definition of infrastructure provided for one or more applications
|
190
|
+
- Application: A logical group of deployable repositories, e.g. a Rails API server and an Ember web client
|
191
|
+
|
192
|
+
|
193
|
+
## Projects
|
194
|
+
|
195
|
+
- A project is comprised of Infrastructure Environments (IE) and Application Groups (AG)
|
196
|
+
- Infrastructure Environemnts are defined separately for each environment
|
197
|
+
- Application Groups are deployed into one or more Infrastructure EnvironmentS
|
198
|
+
|
199
|
+
## Infrastructure Environments
|
200
|
+
|
201
|
+
Infrastructure is either Vagrant machines for development and local environments or EC2 instances for staging and production
|
202
|
+
|
203
|
+
Local, Staging and Production Environments use a Docker swarm network to manage applicaiton groups
|
204
|
+
|
205
|
+
- local: virtual machines running on laptop via vagrant whose primary purpose is application development
|
206
|
+
- development: primary purpose is also application development, but the infrastructure is deployed in the cloud (AWS)
|
207
|
+
- staging: a mirror of production in every way with the possible exception of reduced or part-time resources
|
208
|
+
- production: production ;-)
|
209
|
+
|
210
|
+
## Applications
|
211
|
+
|
212
|
+
Applications are the content that actually gets deployed. The entire purpose of prepd is to provide a consistent
|
213
|
+
and easy to manage infrastructure for each environment into which the application will be deployed.
|
214
|
+
|
215
|
+
|
216
|
+
# Usage
|
217
|
+
|
218
|
+
## New Client
|
219
|
+
|
220
|
+
This overview assumes a complete greenfield, e.g. that no infrastructure exists, no applications exist or even 3rd
|
221
|
+
party service have been setup. To start from zero, then:
|
222
|
+
|
223
|
+
- Create a new GH Organization
|
224
|
+
- Create an AWS Account and two IAM Groups: Administrators and ReadOnlyAdministrators
|
225
|
+
- Create a CI Account and give it access to the GH Organization
|
226
|
+
- Create a Docker Private Repository account and give it access to the GH Organization
|
227
|
+
- Create the project in prepd
|
228
|
+
|
229
|
+
The first four items are outside the scope of this document.
|
230
|
+
|
231
|
+
```ruby
|
232
|
+
prepd
|
233
|
+
c = Client.create(name: 'Acme')
|
234
|
+
```
|
235
|
+
|
236
|
+
## New Project
|
237
|
+
- create a GH repo for the project
|
238
|
+
- create an IAM user for project_name-terraform and download the AWS credentials CSV
|
239
|
+
- create an IAM user for project_name-ansible and download the AWS credentials CSV
|
240
|
+
- use prepd to create the project using the repo_url and path names (tf_creds and ansible_creds) to CSV files
|
241
|
+
|
242
|
+
```ruby
|
243
|
+
c = Client.find_by(name: 'Acme')
|
244
|
+
c.projects.new(name: 'widget', repo_url: 'git@github.com:my_git_hub_account/widget.git')
|
245
|
+
c.tf_creds = 'Users/dude/aws/widget-terraform.csv'
|
246
|
+
c.ansible_creds = 'Users/dude/aws/widget-ansible.csv'
|
247
|
+
c.save
|
248
|
+
```
|
249
|
+
|
250
|
+
## New Application
|
251
|
+
|
252
|
+
View the [lego README.md](https://github.com/rjayroach/lego) on creating micro serivce applications with Rails and Ember
|
253
|
+
|
254
|
+
## Bring Up the Machine
|
255
|
+
|
256
|
+
```ruby
|
257
|
+
cd ~/prepd/acme/widget
|
258
|
+
vagrant up
|
259
|
+
vagrant ssh
|
260
|
+
```
|
261
|
+
|
262
|
+
|
263
|
+
# Credentials
|
264
|
+
|
265
|
+
## Project Credentials
|
266
|
+
Prepd will create the following credential (hidden) files in project_root:
|
267
|
+
|
268
|
+
- .boto: AWS IAM credentials that give read only access to Ansible
|
269
|
+
- .developer.yml: Developer’s git account (and other account) details
|
270
|
+
- .terraform-vars.txt: AWS IAM credentials that give full access to CRUD AWS resources
|
271
|
+
- .vault-password.txt: a UUID used to encrypt and decrypt ansible vault files
|
272
|
+
- .id_rsa.pub: the public key uploaded to AWS as the primary key pair for accessing EC2 instances
|
273
|
+
- .id_rsa: the private key
|
274
|
+
|
275
|
+
- terraform will use project_root/id_rsa.pub to upload key_material to AWS for the machine key
|
276
|
+
- config-development.yml checks the project_root and: 1) if .boto exists link it, 2) if id_rsa and id_rsa.pub exist then link them
|
277
|
+
- the developer can then do ssh-add which will auto load ~/.ssh/id_rsa to login or run ansible
|
278
|
+
|
279
|
+
|
280
|
+
## Transfer Credentials to New Machine
|
281
|
+
|
282
|
+
The prepd gem can encrypt the credentials using gpg which must be installed on the host machine
|
283
|
+
|
284
|
+
The encrypted credentials are written to and read from the user's home directory so that they are not accidentally
|
285
|
+
committed to the project repository
|
286
|
+
|
287
|
+
### Encrypt
|
288
|
+
|
289
|
+
```ruby
|
290
|
+
prepd
|
291
|
+
c = Client.find_by(name: 'Acme')
|
292
|
+
p = c.projects.find_by(name: 'widget')
|
293
|
+
p.encrypt
|
294
|
+
```
|
295
|
+
|
296
|
+
This will create a tar file containing the various project credentials. It will then invoke gpg to encrypt the archive.
|
297
|
+
The credentials will be placed in the project's data directory
|
298
|
+
|
299
|
+
You will be prompted for a passphrase to enter twice. After doing that send the file by email or other mechanism
|
300
|
+
|
301
|
+
### Decrypt
|
302
|
+
|
303
|
+
On the target machine, use prepd to decrypt the file and place it in the correct directory
|
304
|
+
|
305
|
+
- Clone the project repository
|
306
|
+
- Place the gpg tar file in the project's data directory
|
307
|
+
- Run prepd. It will expect to find the credentials file in the project's data directory
|
308
|
+
|
309
|
+
```ruby
|
310
|
+
prepd
|
311
|
+
c = Client.find_by(name: 'Acme')
|
312
|
+
p = c.projects.find_by(name: 'widget')
|
313
|
+
p.decrypt
|
314
|
+
```
|
315
|
+
|
316
|
+
## Authorization
|
317
|
+
|
318
|
+
If giving a developer access to the machine for development only (not terraform or ansible) then add their public key to the
|
319
|
+
instance’s ~/.ssh/authorized_keys. The developer uses ssh-agent forwarding to access the machine from the VM
|
320
|
+
|
321
|
+
|
322
|
+
# Development
|
323
|
+
|
324
|
+
After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
325
|
+
|
326
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
327
|
+
|
328
|
+
# Contributing
|
329
|
+
|
330
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/prepd. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
331
|
+
|
332
|
+
|
333
|
+
# License
|
334
|
+
|
335
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
data/TODO.md
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# TODO
|
2
|
+
|
3
|
+
- option to just gpg encrypt ansible-vault.txt rather than the full set of credentials
|
4
|
+
- move gpg files to the project's data dir instead of user's home dir
|
5
|
+
- add an option to tar, gizp and gpg the data directory as well
|
6
|
+
|
7
|
+
- update prepd-project readme when cloning existing to also pull in ansible-roles
|
8
|
+
|
9
|
+
|
10
|
+
- create a bootstrap.sh script that installs Ansible and dependencies, e.g. Homebrew, python, etc
|
11
|
+
- add a playbook that provisions a mac or ubuntu laptop with android, packer, extras, etc
|
12
|
+
|
13
|
+
- update README to document provisioning a mac (and ubuntu) from brand new:
|
14
|
+
1. git clone prepd
|
15
|
+
2. run bootstrap.sh
|
16
|
+
3. run ./laptop.yml
|
17
|
+
4. bin/console to create a client and project OR git clone a project created with prepd
|
data/bin/console
ADDED
data/bin/setup
ADDED
data/exe/prepd
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
module Prepd
|
2
|
+
def self.options=(options)
|
3
|
+
@options = options
|
4
|
+
end
|
5
|
+
def self.options; @options; end
|
6
|
+
|
7
|
+
def self.commands
|
8
|
+
puts (methods(false) - %i(:options= :options :commands default_settings)).join("\n")
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.new(name)
|
12
|
+
Client.create(name: name)
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.rm
|
16
|
+
FileUtils.rm_rf(work_dir)
|
17
|
+
FileUtils.rm_rf(data_dir)
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.clients; Client.pluck(:name); end
|
21
|
+
|
22
|
+
def self.projects; Project.pluck(:name); end
|
23
|
+
|
24
|
+
def self.current_client
|
25
|
+
@client
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.current_client=(client)
|
29
|
+
STDOUT.puts 'duh'
|
30
|
+
@client = client
|
31
|
+
Dir.chdir(client.path) do
|
32
|
+
Pry.start(client, prompt: [proc { "prepd(#{client.name}) > " }])
|
33
|
+
end
|
34
|
+
STDOUT.puts 'duh2'
|
35
|
+
nil
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
|
3
|
+
module Prepd::Cli
|
4
|
+
class OptionsParser
|
5
|
+
attr_accessor :options
|
6
|
+
|
7
|
+
def initialize(options = nil)
|
8
|
+
self.options = options || {}
|
9
|
+
end
|
10
|
+
|
11
|
+
def parse
|
12
|
+
optparse = OptionParser.new do |opts|
|
13
|
+
opts.on('-c', '--client [OPT]', 'Client') do |value|
|
14
|
+
options['CLIENT'] = value
|
15
|
+
end
|
16
|
+
|
17
|
+
opts.on( '-d', '--data_dir [OPT]', 'Data directory' ) do |value|
|
18
|
+
options['DATA_DIR'] = value
|
19
|
+
end
|
20
|
+
|
21
|
+
opts.on( '-p', '--project [OPT]', 'Project' ) do |value|
|
22
|
+
options['PROJECT'] = value
|
23
|
+
end
|
24
|
+
|
25
|
+
opts.on('-h', '--help', 'Display this screen') do
|
26
|
+
puts opts
|
27
|
+
exit
|
28
|
+
end
|
29
|
+
|
30
|
+
opts.on('-n', '--no-op', 'Show what would happen but do not execute') do
|
31
|
+
options.no_op = true
|
32
|
+
end
|
33
|
+
|
34
|
+
opts.on('-v', '--verbose', 'Display additional information') do
|
35
|
+
options.verbose = true
|
36
|
+
end
|
37
|
+
end
|
38
|
+
optparse.parse!
|
39
|
+
options
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/lib/prepd/cli.rb
ADDED
data/lib/prepd/models.rb
ADDED
@@ -0,0 +1,261 @@
|
|
1
|
+
module Prepd
|
2
|
+
class Client < ActiveRecord::Base
|
3
|
+
attr_accessor :data_dir
|
4
|
+
|
5
|
+
has_many :projects, dependent: :destroy
|
6
|
+
has_many :applications, through: :projects
|
7
|
+
|
8
|
+
before_validation :set_defaults
|
9
|
+
validates :name, :path, presence: true
|
10
|
+
|
11
|
+
after_create :setup
|
12
|
+
after_destroy :destroy_client
|
13
|
+
|
14
|
+
def set_defaults
|
15
|
+
self.path = "#{Prepd.options['DATA_DIR']}/#{name}"
|
16
|
+
end
|
17
|
+
|
18
|
+
def setup
|
19
|
+
FileUtils.mkdir_p(path) unless Dir.exists?(path)
|
20
|
+
end
|
21
|
+
|
22
|
+
def destroy_client
|
23
|
+
FileUtils.rm_rf("#{path}")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
class Project < ActiveRecord::Base
|
29
|
+
attr_accessor :tf_creds, :tf_key, :tf_secret, :ansible_creds, :ansible_key, :ansible_secret
|
30
|
+
|
31
|
+
belongs_to :client, required: true
|
32
|
+
has_many :applications, dependent: :destroy
|
33
|
+
|
34
|
+
validates :name, presence: true, uniqueness: { scope: :client }
|
35
|
+
|
36
|
+
after_create :create_project
|
37
|
+
after_destroy :destroy_project
|
38
|
+
|
39
|
+
#
|
40
|
+
# Initialize the prepd-project or just copy in developer credentials if the project already exists
|
41
|
+
#
|
42
|
+
def create_project
|
43
|
+
if Dir.exists?(path)
|
44
|
+
copy_developer_yml
|
45
|
+
return
|
46
|
+
end
|
47
|
+
setup_git
|
48
|
+
clone_submodules
|
49
|
+
copy_developer_yml
|
50
|
+
generate_credentials
|
51
|
+
encrypt_vault_files
|
52
|
+
end
|
53
|
+
|
54
|
+
#
|
55
|
+
# Destory the VM and remove the project from the file system
|
56
|
+
#
|
57
|
+
def destroy_project
|
58
|
+
Dir.chdir(path) { system('vagrant destroy') }
|
59
|
+
FileUtils.rm_rf(path)
|
60
|
+
end
|
61
|
+
|
62
|
+
#
|
63
|
+
# Clone prepd-project, remove the git history and start with a clean repository
|
64
|
+
#
|
65
|
+
def setup_git
|
66
|
+
Dir.chdir(client.path) { system("git clone git@github.com:rjayroach/prepd-project.git #{name}") }
|
67
|
+
Dir.chdir(path) do
|
68
|
+
FileUtils.rm_rf("#{path}/.git")
|
69
|
+
system('git init')
|
70
|
+
system('git add .')
|
71
|
+
system("git commit -m 'First commit from Prepd'")
|
72
|
+
system("git remote add origin #{repo_url}") if repo_url
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
#
|
77
|
+
# Clone ansible roles and terraform modules
|
78
|
+
#
|
79
|
+
def clone_submodules
|
80
|
+
Dir.chdir("#{path}/ansible") do
|
81
|
+
system('git submodule add git@github.com:rjayroach/ansible-roles.git roles')
|
82
|
+
end
|
83
|
+
Dir.chdir("#{path}/terraform") do
|
84
|
+
system('git submodule add git@github.com:rjayroach/terraform-modules.git modules')
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
#
|
89
|
+
# Copy developer credentials or create them if the file doesn't already exists
|
90
|
+
# TODO: Maybe the creation of developer creds should be done at startup of prepd
|
91
|
+
#
|
92
|
+
def copy_developer_yml
|
93
|
+
return if File.exists?("#{path}/.developer.yml")
|
94
|
+
Dir.chdir(path) do
|
95
|
+
if File.exists?("#{Prepd.work_dir}/developer.yml")
|
96
|
+
FileUtils.cp("#{Prepd.work_dir}/developer.yml", '.developer.yml')
|
97
|
+
elsif File.exists?("#{Dir.home}/.prepd-developer.yml")
|
98
|
+
FileUtils.cp("#{Dir.home}/.prepd-developer.yml", '.developer.yml')
|
99
|
+
else
|
100
|
+
File.open('.developer.yml', 'w') do |f|
|
101
|
+
f.puts('---')
|
102
|
+
f.puts("git_username: #{`git config --get user.name`.chomp}")
|
103
|
+
f.puts("git_email: #{`git config --get user.email`.chomp}")
|
104
|
+
f.puts("docker_username: ")
|
105
|
+
f.puts("docker_password: ")
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
#
|
112
|
+
# Create AWS credential files for Terraform and Ansible, ssh keys and and ansible-vault encryption key
|
113
|
+
# NOTE: The path to credentials is used in the ansible-role prepd
|
114
|
+
#
|
115
|
+
def generate_credentials
|
116
|
+
# self.tf_creds = '/Users/rjayroach/Documents/c2p4/aws/legos-terraform.csv'
|
117
|
+
# self.ansible_creds = '/Users/rjayroach/Documents/c2p4/aws/legos-ansible.csv'
|
118
|
+
generate_tf_creds
|
119
|
+
generate_ansible_creds
|
120
|
+
generate_ssh_keys
|
121
|
+
generate_vault_password
|
122
|
+
end
|
123
|
+
|
124
|
+
def generate_tf_creds
|
125
|
+
self.tf_key, self.tf_secret = CSV.read(tf_creds).last.slice(2,2) if tf_creds
|
126
|
+
unless tf_key and tf_secret
|
127
|
+
STDOUT.puts 'tf_key and tf_secret need to be set (or set tf_creds to path to CSV file)'
|
128
|
+
return
|
129
|
+
end
|
130
|
+
require 'csv'
|
131
|
+
Dir.chdir(path) do
|
132
|
+
File.open('.terraform-vars.txt', 'w') do |f|
|
133
|
+
f.puts("aws_access_key_id = \"#{tf_key}\"")
|
134
|
+
f.puts("aws_secret_access_key = \"#{tf_secret}\"")
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def generate_ansible_creds
|
140
|
+
self.ansible_key, self.ansible_secret = CSV.read(ansible_creds).last.slice(2,2) if ansible_creds
|
141
|
+
unless ansible_key and ansible_secret
|
142
|
+
STDOUT.puts 'ansible_key and ansible_secret need to be set (or set ansible_creds to path to CSV file)'
|
143
|
+
return
|
144
|
+
end
|
145
|
+
Dir.chdir(path) do
|
146
|
+
File.open('.boto', 'w') do |f|
|
147
|
+
f.puts('[Credentials]')
|
148
|
+
f.puts("aws_access_key_id = #{ansible_key}")
|
149
|
+
f.puts("aws_secret_access_key = #{ansible_secret}")
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
#
|
155
|
+
# Generate a key pair to be used as the EC2 key pair
|
156
|
+
#
|
157
|
+
def generate_ssh_keys(file_name = '.id_rsa')
|
158
|
+
Dir.chdir(path) { system("ssh-keygen -b 2048 -t rsa -f #{file_name} -q -N '' -C 'ansible@#{name}.#{client.name}.local'") }
|
159
|
+
end
|
160
|
+
|
161
|
+
#
|
162
|
+
# Generate the key to encrypt ansible-vault files
|
163
|
+
#
|
164
|
+
def generate_vault_password(file_name = '.vault-password.txt')
|
165
|
+
require 'securerandom'
|
166
|
+
Dir.chdir(path) { File.open(file_name, 'w') { |f| f.puts(SecureRandom.uuid) } }
|
167
|
+
end
|
168
|
+
|
169
|
+
#
|
170
|
+
# Use ansible-vault to encrypt the inventory group_vars
|
171
|
+
#
|
172
|
+
def encrypt_vault_files
|
173
|
+
Dir.chdir("#{path}/ansible") do
|
174
|
+
%w(all development local production staging).each do |env|
|
175
|
+
system("ansible-vault encrypt inventory/group_vars/#{env}/vault")
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
def encrypt(mode = :vault)
|
181
|
+
return unless executable?('gpg')
|
182
|
+
Dir.chdir(path) do
|
183
|
+
system "tar cf #{archive(:credentials)} #{file_list(mode)}"
|
184
|
+
end
|
185
|
+
system "gpg -c #{archive(:credentials)}"
|
186
|
+
FileUtils.rm(archive(:credentials))
|
187
|
+
"File created: #{archive(:credentials)}.gpg"
|
188
|
+
end
|
189
|
+
|
190
|
+
def encrypt_data
|
191
|
+
return unless executable?('gpg')
|
192
|
+
archive_path = "#{path}/#{client.name}-#{name}-data.tar"
|
193
|
+
Dir.chdir(path) do
|
194
|
+
system "tar cf #{archive_path} data"
|
195
|
+
end
|
196
|
+
system "gpg -c #{archive_path}"
|
197
|
+
FileUtils.rm(archive_path)
|
198
|
+
FileUtils.mv("#{archive_path}.gpg", "#{archive(:data)}.gpg")
|
199
|
+
"File created: #{archive(:data)}.gpg"
|
200
|
+
end
|
201
|
+
|
202
|
+
def decrypt(type = :credentials)
|
203
|
+
return unless %i(credentials data).include? type
|
204
|
+
return unless executable?('gpg')
|
205
|
+
unless File.exists?("#{archive(type)}.gpg")
|
206
|
+
STDOUT.puts "File not found: #{archive(type)}.gpg"
|
207
|
+
return
|
208
|
+
end
|
209
|
+
system "gpg #{archive(type)}.gpg"
|
210
|
+
Dir.chdir(path) do
|
211
|
+
system "tar xf #{archive(type)}"
|
212
|
+
end
|
213
|
+
FileUtils.rm(archive(type))
|
214
|
+
"File processed: #{archive(type)}.gpg"
|
215
|
+
end
|
216
|
+
|
217
|
+
def executable?(name = 'gpg')
|
218
|
+
require 'mkmf'
|
219
|
+
rv = find_executable(name)
|
220
|
+
STDOUT.puts "#{name} executable not found" unless rv
|
221
|
+
FileUtils.rm('mkmf.log')
|
222
|
+
rv
|
223
|
+
end
|
224
|
+
|
225
|
+
def file_list(mode)
|
226
|
+
return ".boto .id_rsa .id_rsa.pub .terraform-vars.txt .vault-password.txt" if mode.eql?(:all)
|
227
|
+
".vault-password.txt"
|
228
|
+
end
|
229
|
+
|
230
|
+
def archive(type = :credentials)
|
231
|
+
"#{data_path}/#{client.name}-#{name}-#{type}.tar"
|
232
|
+
end
|
233
|
+
|
234
|
+
def data_path
|
235
|
+
"#{path}/data"
|
236
|
+
end
|
237
|
+
|
238
|
+
def path
|
239
|
+
"#{client.path}/#{name}"
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
|
244
|
+
class Application < ActiveRecord::Base
|
245
|
+
belongs_to :project, required: true
|
246
|
+
|
247
|
+
validates :name, presence: true, uniqueness: { scope: :project }
|
248
|
+
|
249
|
+
after_create :setup
|
250
|
+
|
251
|
+
def setup
|
252
|
+
Dir.chdir("#{project.path}/ansible") do
|
253
|
+
FileUtils.cp_r('application', name)
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
def path
|
258
|
+
"#{project.path}/ansible/#{name}"
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|
data/lib/prepd/schema.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
ActiveRecord::Schema.define do
|
2
|
+
unless ActiveRecord::Base.connection.data_sources.include?('clients')
|
3
|
+
create_table :clients do |table|
|
4
|
+
table.column :name, :string
|
5
|
+
table.column :path , :string
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
unless ActiveRecord::Base.connection.data_sources.include?('projects')
|
10
|
+
create_table :projects do |table|
|
11
|
+
table.column :client_id, :integer # foreign key <table-name-singular>_id
|
12
|
+
table.column :name, :string
|
13
|
+
table.column :repo_url, :string
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
unless ActiveRecord::Base.connection.data_sources.include?('applications')
|
18
|
+
create_table :applications do |table|
|
19
|
+
table.column :project_id, :integer # foreign key <table-name-singular>_id
|
20
|
+
table.column :name, :string
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/prepd.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'prepd/version'
|
2
|
+
require 'dotenv'
|
3
|
+
require 'active_record'
|
4
|
+
require 'sqlite3'
|
5
|
+
require 'fileutils'
|
6
|
+
|
7
|
+
module Prepd
|
8
|
+
def self.work_dir; "#{Dir.home}/.prepd"; end
|
9
|
+
def self.data_dir; ENV['DATA_DIR']; end
|
10
|
+
|
11
|
+
def self.files; Dir.glob("#{work_dir}/*"); end
|
12
|
+
|
13
|
+
def self.config; "#{work_dir}/config"; end
|
14
|
+
|
15
|
+
def self.default_settings
|
16
|
+
{
|
17
|
+
'VERSION' => '1',
|
18
|
+
'DATA_DIR' => "#{Dir.home}/prepd",
|
19
|
+
'VAGRANT_BASE_BOX' => 'debian/contrib-jessie64'
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
# Create records for exisitng directories in the DATA_DIR
|
24
|
+
def self.scan
|
25
|
+
clients = Dir.entries(ENV['DATA_DIR'])
|
26
|
+
clients.select { |entry| !entry.starts_with?('.') }.each do |client_name|
|
27
|
+
c = Client.find_or_create_by(name: client_name)
|
28
|
+
projects = Dir.entries("#{ENV['DATA_DIR']}/#{client_name}")
|
29
|
+
projects.select { |entry| !entry.starts_with?('.') }.each do |project_name|
|
30
|
+
c.projects.find_or_create_by(name: project_name)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
FileUtils.mkdir_p work_dir
|
36
|
+
ActiveRecord::Base.logger = Logger.new(File.open("#{work_dir}/database.log", 'w'))
|
37
|
+
ActiveRecord::Base.establish_connection(adapter: :sqlite3, database: "#{work_dir}/sqlite.db")
|
38
|
+
unless File.exists?(config)
|
39
|
+
File.open(config, 'a') do |f|
|
40
|
+
default_settings.each { |key, value| f.puts("#{key}=#{value}") }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
Dotenv.load(config)
|
44
|
+
end
|
45
|
+
|
46
|
+
require 'prepd/schema'
|
47
|
+
require 'prepd/models'
|
data/prepd.gemspec
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'prepd/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'prepd'
|
8
|
+
spec.version = Prepd::VERSION
|
9
|
+
spec.authors = ['Robert Roach']
|
10
|
+
spec.email = ['rjayroach@gmail.com']
|
11
|
+
|
12
|
+
spec.summary = %q{An easy to use tool to create Production Ready Environments for Project Development}
|
13
|
+
spec.description = %q{Prepd assists builders of web application products to start with the end in mind by making it easy to stand up all required infrastructure
|
14
|
+
*before* starting to code the application}
|
15
|
+
spec.homepage = 'https://github.com/rjayroach/prepd-gem'
|
16
|
+
spec.license = 'MIT'
|
17
|
+
|
18
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
19
|
+
spec.bindir = 'exe'
|
20
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
21
|
+
spec.require_paths = ['lib']
|
22
|
+
|
23
|
+
spec.add_development_dependency 'bundler', '~> 1.12'
|
24
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
25
|
+
|
26
|
+
spec.add_dependency 'dotenv'
|
27
|
+
spec.add_dependency 'activerecord'
|
28
|
+
spec.add_dependency 'sqlite3'
|
29
|
+
spec.add_dependency 'pry'
|
30
|
+
spec.add_dependency 'awesome_print'
|
31
|
+
end
|
metadata
ADDED
@@ -0,0 +1,163 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: prepd
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Robert Roach
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-11-02 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.12'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.12'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: dotenv
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: activerecord
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: sqlite3
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: pry
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: awesome_print
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
description: |-
|
112
|
+
Prepd assists builders of web application products to start with the end in mind by making it easy to stand up all required infrastructure
|
113
|
+
*before* starting to code the application
|
114
|
+
email:
|
115
|
+
- rjayroach@gmail.com
|
116
|
+
executables:
|
117
|
+
- prepd
|
118
|
+
extensions: []
|
119
|
+
extra_rdoc_files: []
|
120
|
+
files:
|
121
|
+
- ".gitignore"
|
122
|
+
- CODE_OF_CONDUCT.md
|
123
|
+
- Gemfile
|
124
|
+
- LICENSE.txt
|
125
|
+
- README.md
|
126
|
+
- Rakefile
|
127
|
+
- TODO.md
|
128
|
+
- bin/console
|
129
|
+
- bin/setup
|
130
|
+
- exe/prepd
|
131
|
+
- lib/prepd.rb
|
132
|
+
- lib/prepd/cli.rb
|
133
|
+
- lib/prepd/cli/commands.rb
|
134
|
+
- lib/prepd/cli/options_parser.rb
|
135
|
+
- lib/prepd/models.rb
|
136
|
+
- lib/prepd/schema.rb
|
137
|
+
- lib/prepd/version.rb
|
138
|
+
- prepd.gemspec
|
139
|
+
homepage: https://github.com/rjayroach/prepd-gem
|
140
|
+
licenses:
|
141
|
+
- MIT
|
142
|
+
metadata: {}
|
143
|
+
post_install_message:
|
144
|
+
rdoc_options: []
|
145
|
+
require_paths:
|
146
|
+
- lib
|
147
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
148
|
+
requirements:
|
149
|
+
- - ">="
|
150
|
+
- !ruby/object:Gem::Version
|
151
|
+
version: '0'
|
152
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
153
|
+
requirements:
|
154
|
+
- - ">="
|
155
|
+
- !ruby/object:Gem::Version
|
156
|
+
version: '0'
|
157
|
+
requirements: []
|
158
|
+
rubyforge_project:
|
159
|
+
rubygems_version: 2.5.2.1
|
160
|
+
signing_key:
|
161
|
+
specification_version: 4
|
162
|
+
summary: An easy to use tool to create Production Ready Environments for Project Development
|
163
|
+
test_files: []
|