capistrano-terraform 0.1.0
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/.rspec_status +0 -0
- data/.rubocop.yml +68 -0
- data/CHANGELOG.md +20 -0
- data/Gemfile +11 -0
- data/Gemfile.lock +59 -0
- data/LICENSE.txt +21 -0
- data/README.md +179 -0
- data/Rakefile +8 -0
- data/capistrano-terraform.gemspec +41 -0
- data/lib/capistrano-terraform.rb +1 -0
- data/lib/capistrano/tasks/terraform.rake +42 -0
- data/lib/capistrano/tasks/terraform_doctor.rake +14 -0
- data/lib/capistrano/tasks/terraform_hooks.rake +7 -0
- data/lib/capistrano/terraform.rb +13 -0
- data/lib/capistrano/terraform/doctor.rb +5 -0
- data/lib/capistrano/terraform/doctor/terraform_doctor.rb +48 -0
- data/lib/capistrano/terraform/dsl.rb +20 -0
- data/lib/capistrano/terraform/hooks.rb +3 -0
- data/lib/capistrano/terraform/tasks.rb +3 -0
- data/lib/capistrano/terraform/terraform.rb +277 -0
- data/lib/capistrano/terraform/terraforms.rb +65 -0
- metadata +110 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 233beb5261914e15999372e9e910378d04729118
|
4
|
+
data.tar.gz: 4402e39655b48ad886f8831f00400a3c0349d691
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 65c2e03330f18da9299a8393c588c6757642ecadbedc2fee5386069f555555ee9cbbb1bdcb4ffbae2a1e51e2bb780cac77aeff8fe40bb281d58866a0d2d0e431
|
7
|
+
data.tar.gz: 9a8f156c5c6eab3e7220eac45e2da8d14370ec4968670e11bd8bb18f4d7c378cbde00433ae3f959c8a9f8ff71e0392d4c6ddfad2d9d86fe9eccfc553c83c7b26
|
data/.rspec_status
ADDED
File without changes
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
AllCops:
|
2
|
+
TargetRubyVersion: 2.4
|
3
|
+
|
4
|
+
Style/FrozenStringLiteralComment:
|
5
|
+
Enabled: true
|
6
|
+
|
7
|
+
Style/StringLiterals:
|
8
|
+
EnforcedStyle: single_quotes
|
9
|
+
# Exclude:
|
10
|
+
# - 'db/schema.rb'
|
11
|
+
# - 'db/migrate/*.rb'
|
12
|
+
|
13
|
+
Style/RedundantReturn:
|
14
|
+
Enabled: false
|
15
|
+
Style/HashSyntax:
|
16
|
+
Enabled: false
|
17
|
+
Style/UnneededPercentQ:
|
18
|
+
Enabled: false
|
19
|
+
Style/GuardClause:
|
20
|
+
Enabled: false
|
21
|
+
Style/IfUnlessModifier:
|
22
|
+
Enabled: false
|
23
|
+
Style/UnlessElse:
|
24
|
+
Enabled: false
|
25
|
+
Style/SymbolArray:
|
26
|
+
Enabled: false
|
27
|
+
Style/Documentation:
|
28
|
+
Enabled: false
|
29
|
+
Style/ConditionalAssignment:
|
30
|
+
Enabled: false
|
31
|
+
Style/ClassVars:
|
32
|
+
Enabled: false
|
33
|
+
Style/TrailingCommaInHashLiteral:
|
34
|
+
EnforcedStyleForMultiline: consistent_comma
|
35
|
+
Style/TrailingCommaInArrayLiteral:
|
36
|
+
EnforcedStyleForMultiline: comma
|
37
|
+
Style/ExpandPathArguments:
|
38
|
+
Enabled: false
|
39
|
+
|
40
|
+
Layout/EmptyLinesAroundBlockBody:
|
41
|
+
Enabled: false
|
42
|
+
Layout/SpaceBeforeBlockBraces:
|
43
|
+
Enabled: false
|
44
|
+
Layout/SpaceInsideBlockBraces:
|
45
|
+
Enabled: false
|
46
|
+
Layout/EmptyLinesAroundModuleBody:
|
47
|
+
Enabled: false
|
48
|
+
Layout/EmptyLinesAroundClassBody:
|
49
|
+
Enabled: false
|
50
|
+
Layout/EmptyLines:
|
51
|
+
Enabled: false
|
52
|
+
|
53
|
+
Metrics/PerceivedComplexity:
|
54
|
+
Enabled: false
|
55
|
+
Metrics/CyclomaticComplexity:
|
56
|
+
Enabled: false
|
57
|
+
Metrics/BlockLength:
|
58
|
+
Enabled: false
|
59
|
+
Metrics/AbcSize:
|
60
|
+
Enabled: false
|
61
|
+
Metrics/LineLength:
|
62
|
+
Enabled: false
|
63
|
+
Max: 160
|
64
|
+
Metrics/MethodLength:
|
65
|
+
Enabled: false
|
66
|
+
|
67
|
+
Bundler/OrderedGems:
|
68
|
+
Enabled: false
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# capistrano-terraform 1.x Changelog
|
2
|
+
|
3
|
+
All notable changes to this project will be documented in this file, in reverse chronological order.
|
4
|
+
|
5
|
+
**capistrano-terraform strives to follow [SemVer](http://semver.org)**, similar to the Ruby on Rails project. For a `X.Y.Z` release:
|
6
|
+
|
7
|
+
* `Z` indicates bug fixes only; no breaking changes and no new features, except as necessary for security fixes.
|
8
|
+
* `Y` is bumped when we add new features. Occasionally a `Y` release may include small breaking changes. We will notify via CHANGELOG entries and/or deprecation notices if there are breaking changes.
|
9
|
+
* `X` is incremented for significant breaking changes. This is reserved for special occasions, like a complete rewrite.
|
10
|
+
|
11
|
+
**capistrano-terraform has no current release cadence. That stuff is for adults!** At the moment, this project is a one-man-show. I release stuff when I damn well please, when it pleases me the most. If you don't like that, speak up and become a contributor. If you do that, we can change this line in this file to something less antagonistic.
|
12
|
+
|
13
|
+
### I'm not dedicating any real time here just yet
|
14
|
+
Until this project becomes more meaningfully maintained, the following update notes will be updated as deemed fit and/or by chance of my mind recognizing documentation significance. If you include this code in your project, your crap may break whenever I happenstantially push things that also makes my own crap break. I'll probably be working to fix it soon'ish, but also maybe I'll spend the weekend eating tacos and sleeping instead. The risk is all yours.
|
15
|
+
|
16
|
+
|
17
|
+
# Update notes
|
18
|
+
|
19
|
+
## [`1.0.0`] (2018-07-16)
|
20
|
+
First public release.
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
capistrano-terraform (0.1.0)
|
5
|
+
capistrano (>= 3.11)
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: https://rubygems.org/
|
9
|
+
specs:
|
10
|
+
airbrussh (1.3.0)
|
11
|
+
sshkit (>= 1.6.1, != 1.7.0)
|
12
|
+
capistrano (3.11.0)
|
13
|
+
airbrussh (>= 1.0.0)
|
14
|
+
i18n
|
15
|
+
rake (>= 10.0.0)
|
16
|
+
sshkit (>= 1.9.0)
|
17
|
+
coderay (1.1.2)
|
18
|
+
concurrent-ruby (1.0.5)
|
19
|
+
diff-lcs (1.3)
|
20
|
+
i18n (1.0.1)
|
21
|
+
concurrent-ruby (~> 1.0)
|
22
|
+
method_source (0.9.0)
|
23
|
+
net-scp (1.2.1)
|
24
|
+
net-ssh (>= 2.6.5)
|
25
|
+
net-ssh (5.0.2)
|
26
|
+
pry (0.11.3)
|
27
|
+
coderay (~> 1.1.0)
|
28
|
+
method_source (~> 0.9.0)
|
29
|
+
rake (12.0.0)
|
30
|
+
rspec (3.7.0)
|
31
|
+
rspec-core (~> 3.7.0)
|
32
|
+
rspec-expectations (~> 3.7.0)
|
33
|
+
rspec-mocks (~> 3.7.0)
|
34
|
+
rspec-core (3.7.1)
|
35
|
+
rspec-support (~> 3.7.0)
|
36
|
+
rspec-expectations (3.7.0)
|
37
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
38
|
+
rspec-support (~> 3.7.0)
|
39
|
+
rspec-mocks (3.7.0)
|
40
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
41
|
+
rspec-support (~> 3.7.0)
|
42
|
+
rspec-support (3.7.1)
|
43
|
+
sshkit (1.16.1)
|
44
|
+
net-scp (>= 1.1.2)
|
45
|
+
net-ssh (>= 2.8.0)
|
46
|
+
|
47
|
+
PLATFORMS
|
48
|
+
ruby
|
49
|
+
|
50
|
+
DEPENDENCIES
|
51
|
+
bundler (~> 1.14)
|
52
|
+
capistrano-terraform!
|
53
|
+
pry
|
54
|
+
rake (~> 12.0)
|
55
|
+
rspec
|
56
|
+
rspec-core
|
57
|
+
|
58
|
+
BUNDLED WITH
|
59
|
+
1.14.5
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2018 Eric Shorkey
|
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,179 @@
|
|
1
|
+
# capistrano-terraform
|
2
|
+
|
3
|
+
Run Terraform tasks as part of your Capistrano v3 deployments; or just plain use Capistrano v3 to run your Terraform, even if you don't deploy your code with Capistrano.
|
4
|
+
|
5
|
+
```sh
|
6
|
+
cap production terraform:deploy # run all registered terraform deployment tasks
|
7
|
+
```
|
8
|
+
|
9
|
+
This plugin also hooks into the default `cap <environment> deploy` flow as a build action. See [Usage](#usage) for more details.
|
10
|
+
|
11
|
+
Hence this also works:
|
12
|
+
```sh
|
13
|
+
cap production deploy # run all app deployment tasks, and terraform is going to run in there somewhere based on your configs
|
14
|
+
```
|
15
|
+
|
16
|
+
|
17
|
+
----
|
18
|
+
|
19
|
+
## Installation
|
20
|
+
|
21
|
+
Add these lines to your application's Gemfile:
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
gem 'capistrano', '~> 3.11' # capistrano at least version 3.11
|
25
|
+
gem 'capistrano-terraform', '~> 1.0' # the meaty bits of this plugin - 1.X to ensure you always have the best available
|
26
|
+
```
|
27
|
+
|
28
|
+
And then execute:
|
29
|
+
|
30
|
+
```sh
|
31
|
+
$ bundle
|
32
|
+
```
|
33
|
+
|
34
|
+
Or install it yourself as:
|
35
|
+
|
36
|
+
```sh
|
37
|
+
$ gem install capistrano-terraform
|
38
|
+
```
|
39
|
+
|
40
|
+
----
|
41
|
+
|
42
|
+
## Usage
|
43
|
+
|
44
|
+
### Configure your project
|
45
|
+
|
46
|
+
#### Require in Capfile:
|
47
|
+
```ruby
|
48
|
+
require 'capistrano/terraform'
|
49
|
+
```
|
50
|
+
|
51
|
+
#### Optionally define a Terraform host in deploy.rb or the appropriate deploy/stage.rb:
|
52
|
+
```ruby
|
53
|
+
role :terraform, %w{localhost} # role syntax, this one making localhost the terraform agent
|
54
|
+
# -- or... --
|
55
|
+
server 'my.build.server', roles: %w{terraform} # server syntax, declaring a remote server
|
56
|
+
```
|
57
|
+
|
58
|
+
If no `:terraform` host/role is defined, all Terraform actions will be ran directly from the host currently running `cap` according to the contents of the current working project directory (some use-cases make this desirable, for example some automated CI/CD pipelines work better this way). A maximum of one `:terraform` host can be defined.
|
59
|
+
|
60
|
+
> **Note**: Setting the `:terraform` host/role to `localhost` is *not* the same as leaving it undefined (or set to nil). If the `:terraform` role is defined, the full code checkout process is expected to take place prior to terraform actions.
|
61
|
+
|
62
|
+
> _Note: There is currently no embedded mechanism to ensure the declared terraform host/role (or the localhost if none defined) has the necessary permissions to perform the desired terraform actions against the IAAS service provider. It's entirely up to you to preemptively set up any necessary AWS keys, SSH keys, environment variables, etc, to enable the worker to perform the desired terraform actions. For AWS, I've found it easiest to simply set up the aws-cli environment variables/tokens on the host prior to running `cap`. Discussions/proposals around this are welcome as github issues._
|
63
|
+
|
64
|
+
#### Optionally define the Terraform root directory:
|
65
|
+
```ruby
|
66
|
+
set :terraform_root, "infra"
|
67
|
+
```
|
68
|
+
This is the sub-directory from which all `capistrano/terraform` related files/references will be evaluated from. If left undefined, it will be assumed to be the project root directory (ie: where `Capfile` is defined)
|
69
|
+
|
70
|
+
#### Declare global Terraform variables, variable files, etc
|
71
|
+
|
72
|
+
```ruby
|
73
|
+
append :terraform_var_file, 'common.tfvars'
|
74
|
+
```
|
75
|
+
|
76
|
+
#### Declare your Terraform project directories and their specific configurations:
|
77
|
+
The minimum terraform step definition includes a name. The path (relative to `:terraform_root`) is actually optional. For example:
|
78
|
+
```ruby
|
79
|
+
terraform :my_terraform_action, path: 'directory/path'
|
80
|
+
```
|
81
|
+
|
82
|
+
If no `:path` option is provided, the `:terraform_root` is the assumed directory.
|
83
|
+
|
84
|
+
No checking is performed to ensure that declared terraform project directories are unique by path, only the first parameter for the `terraform` DSL method (ie, the name) is used to determine uniqueness.
|
85
|
+
|
86
|
+
All future references to the same terraform action (by name) are additive. This allows you to declare basic Terraform options within the `deploy.rb` config file, and then add/replace options specific to a particular deployment stage within that stage specific `deploy/stagename.rb` config file.
|
87
|
+
|
88
|
+
This plugin automatically hooks the normal [Capistrano deploy flow](https://capistranorb.com/documentation/getting-started/flow/) around the _publish_ stage. The default timing is to run terraforms _before_ `deploy:publishing`. However, through a configuration option, terraforms can be selectively performed _after_ `deploy:published` instead.
|
89
|
+
|
90
|
+
To select the after publish timing, simply add the `after_publish: true` option setting to individual `terraform` declaration:
|
91
|
+
```ruby
|
92
|
+
terraform :my_terraform_action, path: 'directory/path', after_publish: true
|
93
|
+
```
|
94
|
+
|
95
|
+
To opt-out of the deploy flow for all of `capistrano/terraform`, add this line to your `config/deploy.rb` or to a specific `config/deploy/<stage>.rb` file:
|
96
|
+
```ruby
|
97
|
+
set :terraform_deploy, false
|
98
|
+
```
|
99
|
+
|
100
|
+
To opt-out of the deploy flow for an individual terraform declaration, simply add `deploy: false` to the declaration options:
|
101
|
+
```ruby
|
102
|
+
terraform :my_terraform, path: 'directory/path', deploy: false
|
103
|
+
```
|
104
|
+
Individually excluding a terraform from deploys via `deploy: false` also removes it from the `cap <stage> terraform:deploy` flow.
|
105
|
+
|
106
|
+
Any terraform actions/project-directories that are excluded from the deploy flow are still available to run individually via `cap terraform:my_terraform:deploy` (or their related tasks).
|
107
|
+
|
108
|
+
|
109
|
+
### Run a deploy:
|
110
|
+
|
111
|
+
For a normal full deploy:
|
112
|
+
```ruby
|
113
|
+
cap <stage> deploy # the default hooks will run terraform actions at the appropriate times
|
114
|
+
```
|
115
|
+
|
116
|
+
For independent terraform runs:
|
117
|
+
```ruby
|
118
|
+
cap <stage> terraform:deploy # runs both the before and after publish tasks, hooks in that order, without attempting to publishing code -- if you're running this within a CI pipeline (like Circle or CodeShip) this is probably what you want for simple terraform-first style projects
|
119
|
+
```
|
120
|
+
|
121
|
+
#### Getting a little more granular...
|
122
|
+
|
123
|
+
You should also notice there are a number of granular cap tasks automatically defined around your terraform projects/directories, allowing you to run only what you want, when you want.
|
124
|
+
|
125
|
+
> Beware: All granular `cap <stage> terraform:X` tasks will still honor the `:terraform` server role, if one is defined. Something to be aware of...
|
126
|
+
|
127
|
+
For example, to selectively run before and after publish deploy stages (without involving the code/app deploy bits):
|
128
|
+
- `cap <stage> terraform:deploy_before`
|
129
|
+
- `cap <stage> terraform:deploy_after`
|
130
|
+
|
131
|
+
Additionally, every `terraform` declaration within the cap deploy configs generates a number of individually addressable cap tasks that can be ran independently:
|
132
|
+
- `cap <stage> terraform:<name>:init` # just terraform init
|
133
|
+
- `cap <stage> terraform:<name>:plan` # just terraform plan
|
134
|
+
- `cap <stage> terraform:<name>:apply` # just terraform apply
|
135
|
+
- `cap <stage> terraform:<name>:deploy` # terraform init -> plan -> apply
|
136
|
+
- ???
|
137
|
+
- `cap <stage> terraform:<name>:destroy` # just terraform apply
|
138
|
+
- `cap <stage> terraform:<name>:clean` # delete any left over plan files and cleans up the .terraform temporary directory
|
139
|
+
|
140
|
+
|
141
|
+
To view all the cap tasks (and their descriptions) that are readily runnable for your project, based on the current config files, run `cap -T` to generate the full list.
|
142
|
+
|
143
|
+
|
144
|
+
|
145
|
+
### Configurable options:
|
146
|
+
|
147
|
+
Global
|
148
|
+
|
149
|
+
terraform DSL method
|
150
|
+
|
151
|
+
|
152
|
+
|
153
|
+
|
154
|
+
|
155
|
+
|
156
|
+
|
157
|
+
|
158
|
+
|
159
|
+
|
160
|
+
## Why?
|
161
|
+
|
162
|
+
Because.
|
163
|
+
|
164
|
+
One day I literally put "`capistrano terraform`" into Google and surprisingly didn't find any projects that already directly addressed running Terraform from Capistrano. So here we are.
|
165
|
+
|
166
|
+
## Development
|
167
|
+
|
168
|
+
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.
|
169
|
+
|
170
|
+
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).
|
171
|
+
|
172
|
+
## Contributing
|
173
|
+
|
174
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/eshork/capistrano-terraform
|
175
|
+
|
176
|
+
|
177
|
+
## License
|
178
|
+
|
179
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
lib = File.expand_path('../lib', __FILE__)
|
5
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
6
|
+
|
7
|
+
Gem::Specification.new do |spec|
|
8
|
+
spec.name = 'capistrano-terraform'
|
9
|
+
spec.version = '0.1.0'
|
10
|
+
spec.authors = ['Eric Shorkey']
|
11
|
+
spec.email = ['eric.shorkey@gmail.com']
|
12
|
+
spec.summary = 'Terraform plugin for Capistrano'
|
13
|
+
spec.description = 'Run Terraform tasks as part of your Capistrano v3 deployments,' \
|
14
|
+
' or just simply use Capistrano to manage your Terraform.' \
|
15
|
+
' Multi-stage -- run your Terraform from a pre or post release hook (or a little of both).' \
|
16
|
+
' Runs directly from localhost or a remote build/deploy host.'
|
17
|
+
spec.homepage = 'https://github.com/eshork/capistrano-terraform'
|
18
|
+
spec.license = 'MIT'
|
19
|
+
|
20
|
+
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
|
21
|
+
# to allow pushing to a single host or delete this section to allow pushing to any host.
|
22
|
+
# if spec.respond_to?(:metadata)
|
23
|
+
# spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com'"
|
24
|
+
# else
|
25
|
+
# raise 'RubyGems 2.0 or newer is required to protect against public gem pushes.'
|
26
|
+
# end
|
27
|
+
|
28
|
+
# spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
29
|
+
# f.match(%r{^(test|spec|features)/})
|
30
|
+
# end
|
31
|
+
|
32
|
+
spec.files = `git ls-files`.split($/)
|
33
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
34
|
+
spec.require_paths = ['lib']
|
35
|
+
|
36
|
+
spec.add_dependency 'capistrano', '>= 3.11'
|
37
|
+
|
38
|
+
spec.add_development_dependency 'bundler', '~> 1.14'
|
39
|
+
spec.add_development_dependency 'rake', '~> 12.0'
|
40
|
+
# spec.add_development_dependency 'rspec', '~> 3.0'
|
41
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
# an empty .rb file for bundler to auto-require
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
set :terraform_plan_opts, ['-input=false']
|
4
|
+
set :terraform_init_opts, ['-input=false']
|
5
|
+
set :terraform_apply_opts, nil
|
6
|
+
|
7
|
+
namespace :terraform do
|
8
|
+
desc 'initialize all terraform directories'
|
9
|
+
task :init do
|
10
|
+
::Capistrano::Terraforms.all.each_pair do |terraform_id, terraform_obj|
|
11
|
+
invoke "terraform:#{terraform_id}:init" if terraform_obj.deploy?
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
desc 'plan all terraform directories'
|
16
|
+
task :plan do
|
17
|
+
::Capistrano::Terraforms.all.each_pair do |terraform_id, terraform_obj|
|
18
|
+
invoke "terraform:#{terraform_id}:plan" if terraform_obj.deploy?
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
desc 'apply all planned terraform directories'
|
23
|
+
task :apply do
|
24
|
+
::Capistrano::Terraforms.all.each_pair do |terraform_id, terraform_obj|
|
25
|
+
invoke "terraform:#{terraform_id}:apply" if terraform_obj.deploy?
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
desc 'clean all terraform directories'
|
30
|
+
task :clean do
|
31
|
+
::Capistrano::Terraforms.all.each_pair do |terraform_id, terraform_obj|
|
32
|
+
invoke "terraform:#{terraform_id}:clean" if terraform_obj.deploy?
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# desc 'clear all terraform initializations'
|
37
|
+
# task :distclean
|
38
|
+
|
39
|
+
# desc 'list all terraform directories'
|
40
|
+
# task :list
|
41
|
+
|
42
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Add ourself to the standard 'cap <stage> doctor' invocation
|
4
|
+
task doctor: 'doctor:terraform'
|
5
|
+
|
6
|
+
# alias common misusage
|
7
|
+
task 'terraform:doctor' => 'doctor:terraform'
|
8
|
+
|
9
|
+
namespace :doctor do
|
10
|
+
desc 'Display the effective terraform configuration'
|
11
|
+
task :terraform do
|
12
|
+
Capistrano::Doctor::TerraformDoctor.new.call
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# add the build->push process onto the end of the deploy:published stack
|
4
|
+
# after 'deploy:published', 'docker:capdeploy_hook'
|
5
|
+
|
6
|
+
# push the no_release auto-cull to the very front of the task stack
|
7
|
+
# before 'deploy:starting', 'docker:trim_release_roles'
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# include some special sauce
|
4
|
+
require_relative 'terraform/terraforms.rb'
|
5
|
+
require_relative 'terraform/terraform.rb'
|
6
|
+
|
7
|
+
# include our DSL updates
|
8
|
+
require_relative 'terraform/dsl.rb'
|
9
|
+
|
10
|
+
# include standard tasks and cap flow hooks
|
11
|
+
require_relative 'terraform/tasks'
|
12
|
+
require_relative 'terraform/hooks'
|
13
|
+
require_relative 'terraform/doctor'
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'capistrano/doctor/output_helpers'
|
4
|
+
|
5
|
+
module Capistrano
|
6
|
+
module Doctor
|
7
|
+
class TerraformDoctor
|
8
|
+
include Capistrano::Doctor::OutputHelpers
|
9
|
+
|
10
|
+
def call
|
11
|
+
title('Terraform Globals')
|
12
|
+
tf_globals = [
|
13
|
+
{ var: :terraform_root, resolver: ->{ ::Capistrano::Terraforms.root } },
|
14
|
+
{ var: :terraform_deploy, resolver: ->{ ::Capistrano::Terraforms.deploy } },
|
15
|
+
{ var: :terraform_var, resolver: ->{ ::Capistrano::Terraforms.vars } },
|
16
|
+
{ var: :terraform_var_file, resolver: ->{ ::Capistrano::Terraforms.var_files } },
|
17
|
+
{ var: :terraform_target, resolver: ->{ ::Capistrano::Terraforms.targets } },
|
18
|
+
]
|
19
|
+
|
20
|
+
table(tf_globals) do |tf_global, row|
|
21
|
+
vname = tf_global[:var]
|
22
|
+
vvalue = nil
|
23
|
+
if tf_global[:resolver]
|
24
|
+
vvalue = tf_global[:resolver].call
|
25
|
+
end
|
26
|
+
|
27
|
+
row << ":#{vname}"
|
28
|
+
row << 'nil' if vvalue.nil?
|
29
|
+
if vvalue.is_a?(String)
|
30
|
+
row << "\"#{vvalue}\""
|
31
|
+
else
|
32
|
+
row << vvalue
|
33
|
+
end
|
34
|
+
end
|
35
|
+
puts
|
36
|
+
|
37
|
+
all_terrforms = ::Capistrano::Terraforms.all
|
38
|
+
title("Terraform Paths/Projects (#{all_terrforms.size})")
|
39
|
+
table(all_terrforms) do |terraform, row|
|
40
|
+
row << terraform[0].to_s
|
41
|
+
row << terraform[1].to_s
|
42
|
+
end
|
43
|
+
puts
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Augments the standard Capistrano DSL with terraform specific methods
|
4
|
+
|
5
|
+
module Capistrano
|
6
|
+
module DSL
|
7
|
+
module Env
|
8
|
+
def terraform(terraform_id, params = {})
|
9
|
+
_terraform_upsert(terraform_id, params)
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def _terraform_upsert(terraform_id, params)
|
15
|
+
return ::Capistrano::Terraforms.upsert(terraform_id, params)
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,277 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Capistrano
|
4
|
+
class Terraform
|
5
|
+
|
6
|
+
def initialize(params = {})
|
7
|
+
@path = nil
|
8
|
+
@var = nil
|
9
|
+
@var_file = nil
|
10
|
+
@target = nil
|
11
|
+
@after_publish = nil
|
12
|
+
@deploy = nil
|
13
|
+
@backend_config = nil
|
14
|
+
update(params)
|
15
|
+
end
|
16
|
+
|
17
|
+
def update(params = {})
|
18
|
+
# handle path updates
|
19
|
+
@path = params[:path] if params.key?(:path)
|
20
|
+
|
21
|
+
# handle var_file upserts
|
22
|
+
if params.key?(:var_file)
|
23
|
+
@var_file ||= []
|
24
|
+
@var_file.push(params[:var_file])
|
25
|
+
@var_file.flatten!
|
26
|
+
end
|
27
|
+
@var_file = nil if @var_file == []
|
28
|
+
|
29
|
+
# handle var upserts
|
30
|
+
if params.key?(:var)
|
31
|
+
@var ||= []
|
32
|
+
@var.push(params[:var])
|
33
|
+
@var&.flatten!&.uniq!
|
34
|
+
end
|
35
|
+
@var = nil if @var == []
|
36
|
+
|
37
|
+
# handle target upserts
|
38
|
+
if params.key?(:target)
|
39
|
+
@target ||= []
|
40
|
+
@target.push(params[:target])
|
41
|
+
@target&.flatten!&.uniq!
|
42
|
+
end
|
43
|
+
@target = nil if @target == []
|
44
|
+
|
45
|
+
# handle after_publish upserts
|
46
|
+
if params.key?(:after_publish)
|
47
|
+
@after_publish = params[:after_publish]
|
48
|
+
end
|
49
|
+
@after_publish = nil unless @after_publish == true
|
50
|
+
|
51
|
+
# handle deploy upserts
|
52
|
+
if params.key?(:deploy)
|
53
|
+
@deploy = params[:deploy]
|
54
|
+
end
|
55
|
+
@deploy = nil unless @deploy == false
|
56
|
+
|
57
|
+
# handle backend_config upserts
|
58
|
+
if params.key?(:backend_config)
|
59
|
+
@backend_config ||= []
|
60
|
+
@backend_config.push(params[:backend_config])
|
61
|
+
@backend_config&.flatten!&.uniq!
|
62
|
+
end
|
63
|
+
@backend_config = nil if @backend_config == []
|
64
|
+
end
|
65
|
+
|
66
|
+
def to_hash
|
67
|
+
return {
|
68
|
+
path: @path,
|
69
|
+
var: @var,
|
70
|
+
var_file: @var_file,
|
71
|
+
target: @target,
|
72
|
+
backend_config: @backend_config,
|
73
|
+
after_publish: @after_publish,
|
74
|
+
deploy: @deploy,
|
75
|
+
}.compact
|
76
|
+
end
|
77
|
+
|
78
|
+
def to_s
|
79
|
+
return to_hash
|
80
|
+
end
|
81
|
+
|
82
|
+
def deploy?
|
83
|
+
return @deploy != false
|
84
|
+
end
|
85
|
+
|
86
|
+
def targets
|
87
|
+
targets_ary = []
|
88
|
+
Terraforms.targets.each do |t|
|
89
|
+
targets_ary << t
|
90
|
+
end
|
91
|
+
@target&.each do |t|
|
92
|
+
targets_ary << t
|
93
|
+
end
|
94
|
+
return targets_ary.uniq
|
95
|
+
end
|
96
|
+
|
97
|
+
def plan_outfile
|
98
|
+
# fetch :terraform_plan_outfile, 'tf.plan'
|
99
|
+
'tf.plan'
|
100
|
+
end
|
101
|
+
|
102
|
+
def run_path
|
103
|
+
return Terraforms.root_path.join(@path) if @path
|
104
|
+
return Terraforms.root_path
|
105
|
+
end
|
106
|
+
|
107
|
+
def init_cmd_line
|
108
|
+
cmd_ary = [Terraforms.terraform_cmd, :init]
|
109
|
+
cmd_ary << fetch(:terraform_init_opts, [])
|
110
|
+
cmd_ary << '-reconfigure' # always reconfigure to preserve states across stages
|
111
|
+
|
112
|
+
root_relative = Terraforms.root_path.relative_path_from(run_path)
|
113
|
+
fetch(:terraform_backend_config, []).uniq.each do |bec|
|
114
|
+
if bec.include?('=')
|
115
|
+
cmd_ary << "-backend-config='#{bec}'"
|
116
|
+
else
|
117
|
+
cmd_ary << "-backend-config='#{root_relative.join(bec)}'"
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
@backend_config&.each do |bec|
|
122
|
+
cmd_ary << "-backend-config='#{bec}'"
|
123
|
+
end
|
124
|
+
|
125
|
+
return cmd_ary.flatten
|
126
|
+
end
|
127
|
+
|
128
|
+
def plan_cmd_line
|
129
|
+
cmd_ary = [Terraforms.terraform_cmd, :plan]
|
130
|
+
cmd_ary << fetch(:terraform_plan_opts, [])
|
131
|
+
cmd_ary << "-out='#{plan_outfile}'"
|
132
|
+
|
133
|
+
root_relative = Terraforms.root_path.relative_path_from(run_path)
|
134
|
+
|
135
|
+
fetch(:terraform_var_file, []).uniq.each do |tf_var_file|
|
136
|
+
cmd_ary << "-var-file='#{root_relative.join(tf_var_file)}'"
|
137
|
+
end
|
138
|
+
|
139
|
+
fetch(:terraform_var, []).uniq.each do |tf_var|
|
140
|
+
cmd_ary << "-var='#{tf_var}'"
|
141
|
+
end
|
142
|
+
|
143
|
+
@var_file&.each do |var_file|
|
144
|
+
cmd_ary << "-var-file='#{var_file}'"
|
145
|
+
end
|
146
|
+
|
147
|
+
@var&.each do |var|
|
148
|
+
cmd_ary << "-var='#{var}'"
|
149
|
+
end
|
150
|
+
|
151
|
+
targets.each do |target|
|
152
|
+
cmd_ary << "-target='#{target}'"
|
153
|
+
end
|
154
|
+
|
155
|
+
return cmd_ary.flatten
|
156
|
+
end
|
157
|
+
|
158
|
+
def apply_cmd_line
|
159
|
+
cmd_ary = [Terraforms.terraform_cmd, :apply]
|
160
|
+
cmd_ary << fetch(:terraform_apply_opts, [])
|
161
|
+
cmd_ary << "'#{plan_outfile}'"
|
162
|
+
return cmd_ary.flatten
|
163
|
+
end
|
164
|
+
|
165
|
+
def create_tasks(terraform_id)
|
166
|
+
create_init_task(terraform_id)
|
167
|
+
create_plan_task(terraform_id)
|
168
|
+
create_clean_task(terraform_id)
|
169
|
+
create_apply_task(terraform_id)
|
170
|
+
end
|
171
|
+
|
172
|
+
def create_init_task(terraform_id)
|
173
|
+
task = Rake::Task.define_task "terraform:#{terraform_id}:init" do
|
174
|
+
terraform_obj = Terraforms.find(terraform_id)
|
175
|
+
terraform_cmd = terraform_obj.init_cmd_line
|
176
|
+
|
177
|
+
if roles(:terraform).first
|
178
|
+
on roles(:terraform).first do |_terraform_remote|
|
179
|
+
info "Running terraform:#{terraform_id}:init..."
|
180
|
+
within terraform_obj.run_path do
|
181
|
+
execute :pwd
|
182
|
+
raise 'nyi'
|
183
|
+
end
|
184
|
+
end
|
185
|
+
else
|
186
|
+
run_locally do
|
187
|
+
info "Running terraform:#{terraform_id}:init..."
|
188
|
+
within terraform_obj.run_path do
|
189
|
+
execute :pwd
|
190
|
+
execute(*terraform_cmd)
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
task.comment = "initialize specific terraform: #{terraform_id}"
|
196
|
+
end
|
197
|
+
|
198
|
+
def create_plan_task(terraform_id)
|
199
|
+
task = Rake::Task.define_task "terraform:#{terraform_id}:plan" do
|
200
|
+
terraform_obj = Terraforms.find(terraform_id)
|
201
|
+
terraform_cmd = terraform_obj.plan_cmd_line
|
202
|
+
|
203
|
+
if roles(:terraform).first
|
204
|
+
on roles(:terraform).first do |_terraform_remote|
|
205
|
+
info "Running terraform:#{terraform_id}:plan..."
|
206
|
+
within terraform_obj.run_path do
|
207
|
+
execute :pwd
|
208
|
+
execute(*terraform_cmd)
|
209
|
+
end
|
210
|
+
end
|
211
|
+
else
|
212
|
+
run_locally do
|
213
|
+
info "Running terraform:#{terraform_id}:plan..."
|
214
|
+
within terraform_obj.run_path do
|
215
|
+
execute :pwd
|
216
|
+
execute(*terraform_cmd)
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
221
|
+
task.comment = "plan specific terraform: #{terraform_id}"
|
222
|
+
end
|
223
|
+
|
224
|
+
def create_apply_task(terraform_id)
|
225
|
+
task = Rake::Task.define_task "terraform:#{terraform_id}:apply" do
|
226
|
+
terraform_obj = Terraforms.find(terraform_id)
|
227
|
+
terraform_cmd = terraform_obj.apply_cmd_line
|
228
|
+
|
229
|
+
if roles(:terraform).first
|
230
|
+
on roles(:terraform).first do |_terraform_remote|
|
231
|
+
info "Running terraform:#{terraform_id}:apply..."
|
232
|
+
within terraform_obj.run_path do
|
233
|
+
execute :pwd
|
234
|
+
execute(*terraform_cmd)
|
235
|
+
end
|
236
|
+
end
|
237
|
+
else
|
238
|
+
run_locally do
|
239
|
+
info "Running terraform:#{terraform_id}:apply..."
|
240
|
+
within terraform_obj.run_path do
|
241
|
+
execute :pwd
|
242
|
+
execute(*terraform_cmd)
|
243
|
+
end
|
244
|
+
end
|
245
|
+
end
|
246
|
+
end
|
247
|
+
task.comment = "apply specific terraform: #{terraform_id}"
|
248
|
+
end
|
249
|
+
|
250
|
+
def create_clean_task(terraform_id)
|
251
|
+
task = Rake::Task.define_task "terraform:#{terraform_id}:clean" do
|
252
|
+
terraform_obj = Terraforms.find(terraform_id)
|
253
|
+
terraform_cmd = [:rm, '-rf', '.terraform', plan_outfile]
|
254
|
+
|
255
|
+
if roles(:terraform).first
|
256
|
+
on roles(:terraform).first do |_terraform_remote|
|
257
|
+
info "Cleaning terraform:#{terraform_id}..."
|
258
|
+
within terraform_obj.run_path do
|
259
|
+
execute :pwd
|
260
|
+
execute(*terraform_cmd)
|
261
|
+
end
|
262
|
+
end
|
263
|
+
else
|
264
|
+
run_locally do
|
265
|
+
info "Cleaning terraform:#{terraform_id}:plan..."
|
266
|
+
within terraform_obj.run_path do
|
267
|
+
execute :pwd
|
268
|
+
execute(*terraform_cmd)
|
269
|
+
end
|
270
|
+
end
|
271
|
+
end
|
272
|
+
end
|
273
|
+
task.comment = "clean specific terraform: #{terraform_id}"
|
274
|
+
end
|
275
|
+
|
276
|
+
end
|
277
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'terraform.rb'
|
4
|
+
|
5
|
+
module Capistrano
|
6
|
+
class Terraforms
|
7
|
+
|
8
|
+
def self.terraform_cmd
|
9
|
+
fetch(:terraform_cmd, :terraform)
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.root
|
13
|
+
fetch :terraform_root, nil
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.vars
|
17
|
+
fetch :terraform_var, []
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.var_files
|
21
|
+
fetch(:terraform_var_file, []).uniq
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.targets
|
25
|
+
[fetch(:terraform_target, [])].flatten.uniq
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.deploy
|
29
|
+
fetch :terraform_deploy, true
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.root_path
|
33
|
+
if roles(:terraform).first
|
34
|
+
return deploy_path.join(fetch(:current_directory, 'current')).join(fetch(:terraform_root, '.'))
|
35
|
+
else
|
36
|
+
return Pathname.new(fetch(:terraform_root, '.'))
|
37
|
+
end
|
38
|
+
|
39
|
+
# return deploy_path.join(fetch(:current_directory, 'current')) if build_dir.nil?
|
40
|
+
# return Pathname.new(build_dir.strip) if build_dir.strip[0] == '/'
|
41
|
+
# return deploy_path.join(fetch(:current_directory, 'current'), build_dir)
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.upsert(terraform_id, params = {})
|
45
|
+
@@terraforms ||= {} # auto-init class variable on usage
|
46
|
+
terraform_id = terraform_id.to_sym
|
47
|
+
if @@terraforms.key?(terraform_id)
|
48
|
+
@@terraforms[terraform_id].update(params)
|
49
|
+
else
|
50
|
+
@@terraforms[terraform_id] = ::Capistrano::Terraform.new(params)
|
51
|
+
@@terraforms[terraform_id].create_tasks(terraform_id)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.all
|
56
|
+
@@terraforms ||= {} # auto-init class variable on usage
|
57
|
+
return @@terraforms
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.find(terraform_id)
|
61
|
+
return all[terraform_id]
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
end
|
metadata
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: capistrano-terraform
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Eric Shorkey
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-08-15 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: capistrano
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3.11'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '3.11'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.14'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.14'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '12.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '12.0'
|
55
|
+
description: Run Terraform tasks as part of your Capistrano v3 deployments, or just
|
56
|
+
simply use Capistrano to manage your Terraform. Multi-stage -- run your Terraform
|
57
|
+
from a pre or post release hook (or a little of both). Runs directly from localhost
|
58
|
+
or a remote build/deploy host.
|
59
|
+
email:
|
60
|
+
- eric.shorkey@gmail.com
|
61
|
+
executables: []
|
62
|
+
extensions: []
|
63
|
+
extra_rdoc_files: []
|
64
|
+
files:
|
65
|
+
- ".rspec_status"
|
66
|
+
- ".rubocop.yml"
|
67
|
+
- CHANGELOG.md
|
68
|
+
- Gemfile
|
69
|
+
- Gemfile.lock
|
70
|
+
- LICENSE.txt
|
71
|
+
- README.md
|
72
|
+
- Rakefile
|
73
|
+
- capistrano-terraform.gemspec
|
74
|
+
- lib/capistrano-terraform.rb
|
75
|
+
- lib/capistrano/tasks/terraform.rake
|
76
|
+
- lib/capistrano/tasks/terraform_doctor.rake
|
77
|
+
- lib/capistrano/tasks/terraform_hooks.rake
|
78
|
+
- lib/capistrano/terraform.rb
|
79
|
+
- lib/capistrano/terraform/doctor.rb
|
80
|
+
- lib/capistrano/terraform/doctor/terraform_doctor.rb
|
81
|
+
- lib/capistrano/terraform/dsl.rb
|
82
|
+
- lib/capistrano/terraform/hooks.rb
|
83
|
+
- lib/capistrano/terraform/tasks.rb
|
84
|
+
- lib/capistrano/terraform/terraform.rb
|
85
|
+
- lib/capistrano/terraform/terraforms.rb
|
86
|
+
homepage: https://github.com/eshork/capistrano-terraform
|
87
|
+
licenses:
|
88
|
+
- MIT
|
89
|
+
metadata: {}
|
90
|
+
post_install_message:
|
91
|
+
rdoc_options: []
|
92
|
+
require_paths:
|
93
|
+
- lib
|
94
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
95
|
+
requirements:
|
96
|
+
- - ">="
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '0'
|
99
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
requirements: []
|
105
|
+
rubyforge_project:
|
106
|
+
rubygems_version: 2.6.8
|
107
|
+
signing_key:
|
108
|
+
specification_version: 4
|
109
|
+
summary: Terraform plugin for Capistrano
|
110
|
+
test_files: []
|