tfctl 1.0.0 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.bundle/config +3 -0
- data/.github/dependabot.yml +7 -0
- data/.gitignore +0 -1
- data/.rubocop.yml +9 -4
- data/.travis.yml +13 -12
- data/CHANGELOG.adoc +29 -0
- data/Makefile +4 -3
- data/README.adoc +61 -29
- data/RELEASING.adoc +13 -0
- data/bin/tfctl +6 -9
- data/docs/configuration.adoc +18 -8
- data/docs/control_tower.adoc +45 -27
- data/docs/creating_a_profile.adoc +5 -5
- data/docs/iam_permissions.adoc +2 -2
- data/docs/project_layout.adoc +8 -4
- data/examples/control_tower/profiles/example-profile/main.tf +1 -1
- data/examples/control_tower/profiles/example-profile/variables.tf +1 -1
- data/examples/control_tower/{conf/example.yaml → tfctl.yaml} +2 -2
- data/lib/hash.rb +2 -1
- data/lib/tfctl.rb +8 -8
- data/lib/tfctl/aws_org.rb +18 -16
- data/lib/tfctl/config.rb +5 -4
- data/lib/tfctl/executor.rb +1 -1
- data/lib/tfctl/generator.rb +12 -10
- data/lib/tfctl/logger.rb +1 -1
- data/lib/tfctl/schema.rb +3 -3
- data/lib/tfctl/version.rb +1 -1
- data/tfctl.gemspec +9 -6
- metadata +38 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5fe79c7d1c05d536eabd439037d74996bf35af1b72e359e34a0f52f32067fecf
|
4
|
+
data.tar.gz: 67c20fd6e27f58ce119e9c050923c80499b0054991716515f41dbbd2c4156336
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 693f29d4f7ddea34dfe9dbb747cf976452bdc8ff423bf63d41bc2f77f2ae05fb58ddb8b6d9a2d4c1f151749899a325b7326384e5e4128eda076d51c7c54bd8ca
|
7
|
+
data.tar.gz: a71acfa057e8a80923b7ec9c48ab2654af1fd6d73e4fa0259949d3bded769773dd3127590475266586fe48e3f5549a7f8725c111429a6ceb850389bb7fc63c01
|
data/.bundle/config
ADDED
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
---
|
2
2
|
AllCops:
|
3
|
-
TargetRubyVersion: 2.
|
3
|
+
TargetRubyVersion: 2.5
|
4
4
|
DisplayCopNames: true
|
5
|
+
NewCops: enable
|
5
6
|
|
6
7
|
Layout/IndentationWidth:
|
7
8
|
Width: 4
|
8
9
|
|
9
|
-
Layout/
|
10
|
+
Layout/HeredocIndentation:
|
10
11
|
Enabled: false
|
11
12
|
|
12
13
|
Layout/EmptyLines:
|
@@ -15,7 +16,7 @@ Layout/EmptyLines:
|
|
15
16
|
Layout/EmptyLinesAroundMethodBody:
|
16
17
|
Enabled: false
|
17
18
|
|
18
|
-
Layout/
|
19
|
+
Layout/HashAlignment:
|
19
20
|
EnforcedHashRocketStyle:
|
20
21
|
- table
|
21
22
|
EnforcedColonStyle:
|
@@ -45,7 +46,7 @@ Metrics/BlockLength:
|
|
45
46
|
Metrics/MethodLength:
|
46
47
|
Enabled: false
|
47
48
|
|
48
|
-
|
49
|
+
Layout/LineLength:
|
49
50
|
Max: 140
|
50
51
|
|
51
52
|
Metrics/AbcSize:
|
@@ -77,3 +78,7 @@ Style/TrailingCommaInHashLiteral:
|
|
77
78
|
|
78
79
|
Style/RedundantReturn:
|
79
80
|
Enabled: false
|
81
|
+
|
82
|
+
# don't break older Rubies just because of style
|
83
|
+
Style/RedundantBegin:
|
84
|
+
Enabled: false
|
data/.travis.yml
CHANGED
@@ -1,18 +1,19 @@
|
|
1
1
|
rvm:
|
2
|
-
|
3
|
-
|
2
|
+
- 2.5
|
3
|
+
- 2.6
|
4
|
+
- 2.7
|
4
5
|
os: linux
|
5
6
|
language: ruby
|
6
7
|
script: make test
|
7
8
|
jobs:
|
8
9
|
include:
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
10
|
+
- stage: Gem release
|
11
|
+
rvm: 2.6
|
12
|
+
deploy:
|
13
|
+
provider: rubygems
|
14
|
+
api_key:
|
15
|
+
secure: LAVcdER+LtQ2TSUrVOY7Be1BC7GXJRD0QBt386vRM5Nld5QaD9Ow9gtN6FprzkzloI4R8BkPWqZbAT6YjC+C0AFB5HK6iPwD2bLsiF9w3ccDD+yrW99RHxiErpmYMun2PqZv0WkJ/pkEplPCKMRFv7SM7W9DMRlU7dsXc1v6IVyIb5u3A04jErS2jXXKY0ijlCDJYVo8zzYL6yUmUcXhc//3CIVnu2Miu6Qr8h7e6jMXNUWfMkwEXsFP9id4TsCz7hRY+39PkiBAknHTN5UqjjJiEOknZnHeTBcVPvi2h2xv+fFLSzVTxlxaRsVoMCShQp5D12qzhQObRJsRVQFs8Yyg9IYMyPdxssFYyUZFaAy5taWDm57uM3HTHylm/Dq3LmXTgGNxWUUkf2oh1g7R6cYZpBUQwiEPzhZQ7CoBQbGUAJmH9ZU9m+cr8kuAOUipd6BNEDvn/fIH4WJsRCNP72JGX16JBpuICvpkuNhskZT91xFlYk1pTXHOxNpbTcxUTgMHhrTqspeRXPmf6DiYGvjMb2S6kaoGqCIRIcwl0TGKuMsOMqR9SqF8gubkqHMVbSl1E7mwBn4ke8/7IGoMkWOGwUpVxqVOLBHi6zSR09RTVSbKl4oiFV3ZwmVPSxDncq54MptyJ2WCZ7dD6ht2l+VA8iGwYeIoqOpwGWxyuNI=
|
16
|
+
gem: tfctl
|
17
|
+
on:
|
18
|
+
tags: true
|
19
|
+
repo: scalefactory/tfctl
|
data/CHANGELOG.adoc
CHANGED
@@ -1,5 +1,34 @@
|
|
1
1
|
= Changelog
|
2
2
|
|
3
|
+
== 1.3.0
|
4
|
+
|
5
|
+
* feat: support new Terraform provider syntax
|
6
|
+
|
7
|
+
BREAKING CHANGE: The minimum supported Terraform version has been bumped to
|
8
|
+
0.12.29. If you are running an older version of Terraform you will need to
|
9
|
+
update to the latest Terraform in 0.12.x series before updating tfctl. Once
|
10
|
+
tfctl is updated you can upgrade Terraform to further versions.
|
11
|
+
|
12
|
+
== 1.2.2
|
13
|
+
* chore: reverted PR #11 - not necessary and introduced regression. See PR #13 for details.
|
14
|
+
|
15
|
+
== 1.2.1
|
16
|
+
* chore: added required Ruby version to Gemspec.
|
17
|
+
|
18
|
+
== 1.2.0
|
19
|
+
|
20
|
+
* feat: pass TF_ environment variables to terraform (PR #11).
|
21
|
+
|
22
|
+
== 1.1.1
|
23
|
+
|
24
|
+
* fix: handle empty response from Organizations API containing children (thanks @grothja)
|
25
|
+
* chore: stopped testing on EOL Rubies 2.3 and 2.4 (but should still currently work)
|
26
|
+
* chore: dependencies minimum version bump
|
27
|
+
|
28
|
+
== 1.1.0
|
29
|
+
|
30
|
+
* feat: look for configuration in `tfctl.yaml` by default.
|
31
|
+
|
3
32
|
== 1.0.0
|
4
33
|
|
5
34
|
* feat(config): JSON schema config validation
|
data/Makefile
CHANGED
@@ -2,7 +2,8 @@
|
|
2
2
|
|
3
3
|
vendor:
|
4
4
|
$(info => Installing Ruby dependencies)
|
5
|
-
@bundle install
|
5
|
+
@bundle install
|
6
|
+
@bundle binstubs --all --path vendor/bin
|
6
7
|
|
7
8
|
test: vendor rubocop spec
|
8
9
|
|
@@ -10,11 +11,11 @@ guard: vendor
|
|
10
11
|
$(info => Starting guard)
|
11
12
|
@bundle exec guard
|
12
13
|
|
13
|
-
rubocop:
|
14
|
+
rubocop: vendor
|
14
15
|
$(info => Running rubocop)
|
15
16
|
@vendor/bin/rubocop
|
16
17
|
|
17
|
-
spec:
|
18
|
+
spec: vendor
|
18
19
|
$(info => Running spec tests)
|
19
20
|
@vendor/bin/rspec
|
20
21
|
|
data/README.adoc
CHANGED
@@ -28,19 +28,37 @@ toc::[]
|
|
28
28
|
|
29
29
|
== Overview
|
30
30
|
|
31
|
-
|
31
|
+
`tfctl` is a small Terraform wrapper for working with multi-account AWS
|
32
32
|
infrastructures where new accounts may be created dynamically and on-demand.
|
33
33
|
|
34
|
-
It discovers accounts by reading the AWS Organizations API and can assign
|
34
|
+
It discovers accounts by reading the AWS Organizations API, and can assign
|
35
35
|
Terraform resources to multiple accounts based on the organization hierarchy.
|
36
36
|
Resources can be assigned globally, based on organization unit or to individual
|
37
|
-
accounts. It supports
|
37
|
+
accounts. It supports hierarchies of nested Organizational Units (OUs),
|
38
|
+
and helps keep your Terraform DRY.
|
38
39
|
|
39
|
-
|
40
|
+
The Scale Factory originally created tfctl to integrate Terraform with
|
40
41
|
https://aws.amazon.com/solutions/aws-landing-zone/[AWS Landing Zone] and
|
41
42
|
https://aws.amazon.com/controltower/[Control Tower] but should work with most
|
42
43
|
other ways of managing accounts in AWS Organizations.
|
43
44
|
|
45
|
+
== Project status
|
46
|
+
|
47
|
+
`tfctl` is an open source project published by The Scale Factory.
|
48
|
+
|
49
|
+
We currently consider this project to be maintained but we don't actively
|
50
|
+
develop new features. We keep it security patched and ready for use in
|
51
|
+
production environments.
|
52
|
+
|
53
|
+
We’ll take a look at any issues or PRs you open and get back to you as soon as
|
54
|
+
we can. We don’t offer any formal SLA, but we’ll be checking on this project
|
55
|
+
periodically.
|
56
|
+
|
57
|
+
If your issue is urgent, you can flag it as such, and we’ll attempt to triage
|
58
|
+
appropriately, but we have paying customers who also have demands on our time.
|
59
|
+
If your business depends on this project and you have an urgent problem, then
|
60
|
+
you can talk to our sales team about paying us to support you.
|
61
|
+
|
44
62
|
== Features
|
45
63
|
|
46
64
|
* Discovers AWS accounts automatically.
|
@@ -56,8 +74,8 @@ other ways of managing accounts in AWS Organizations.
|
|
56
74
|
|
57
75
|
== Requirements
|
58
76
|
|
59
|
-
* Terraform >= 0.12
|
60
|
-
* Ruby >= 2.
|
77
|
+
* Terraform >= 0.12.29
|
78
|
+
* Ruby >= 2.5
|
61
79
|
* Accounts managed in AWS Organizations (by Landing Zone, Control Tower, some
|
62
80
|
other means)
|
63
81
|
|
@@ -65,17 +83,19 @@ other ways of managing accounts in AWS Organizations.
|
|
65
83
|
|
66
84
|
To install the latest release from RubyGems run:
|
67
85
|
|
86
|
+
[source,shell]
|
68
87
|
----
|
69
88
|
gem install tfctl
|
70
89
|
----
|
71
90
|
|
72
|
-
Alternatively you can build and install from this repo with:
|
91
|
+
Alternatively, you can build and install from this repo with:
|
73
92
|
|
93
|
+
[source,shell]
|
74
94
|
----
|
75
95
|
make install
|
76
96
|
----
|
77
97
|
|
78
|
-
==
|
98
|
+
== Documentation
|
79
99
|
|
80
100
|
* https://github.com/scalefactory/tfctl/tree/master/docs/control_tower.adoc[Control Tower quick start guide]
|
81
101
|
* https://github.com/scalefactory/tfctl/tree/master/docs/project_layout.adoc[Project layout]
|
@@ -85,23 +105,25 @@ make install
|
|
85
105
|
|
86
106
|
== Running tfctl
|
87
107
|
|
88
|
-
|
89
|
-
Terraform configuration in `.tfctl
|
108
|
+
You should run `tfctl` from the root of your project directory. It will generate
|
109
|
+
Terraform configuration in `.tfctl/` (add this to your `.gitignore`).
|
90
110
|
|
91
111
|
Anatomy of a tfctl command:
|
92
112
|
|
113
|
+
[source,shell]
|
93
114
|
----
|
94
115
|
tfctl -c CONFIG_FILE TARGET_OPTIONS -- TERRAFORM_COMMAND
|
95
116
|
----
|
96
117
|
|
97
|
-
* `-c` specifies which tfctl config file to use (
|
118
|
+
* `-c` specifies which tfctl config file to use (defaults to `tfctl.yaml` in
|
119
|
+
current working directory if not set)
|
98
120
|
* `TARGET_OPTIONS` specifies which accounts to target. This could be an individual
|
99
121
|
account, a group of accounts in an organizational unit or all accounts.
|
100
122
|
* `TERRAFORM_COMMAND` will be passed to `terraform` along with any
|
101
123
|
options. See https://www.terraform.io/docs/commands/index.html[Terraform
|
102
124
|
commands] for details.
|
103
125
|
|
104
|
-
NOTE: You must have your AWS credentials configured before
|
126
|
+
NOTE: You must have your AWS credentials configured before you run `tfctl`, or run
|
105
127
|
it using an AWS credentials helper such as
|
106
128
|
https://github.com/99designs/aws-vault[aws-vault].
|
107
129
|
|
@@ -109,68 +131,78 @@ https://github.com/99designs/aws-vault[aws-vault].
|
|
109
131
|
|
110
132
|
Show help:
|
111
133
|
|
134
|
+
[source,shell]
|
112
135
|
----
|
113
136
|
tfctl -h
|
114
137
|
----
|
115
138
|
|
116
139
|
Show merged configuration:
|
117
140
|
|
141
|
+
[source,shell]
|
118
142
|
----
|
119
|
-
tfctl -
|
143
|
+
tfctl -s
|
120
144
|
----
|
121
145
|
|
122
146
|
List all discovered accounts:
|
123
147
|
|
148
|
+
[source,shell]
|
124
149
|
----
|
125
|
-
tfctl
|
150
|
+
tfctl --all -l
|
126
151
|
----
|
127
152
|
|
128
153
|
TIP: This can be narrowed down using targeting options and is a good way to
|
129
154
|
test what accounts match.
|
130
155
|
|
131
|
-
Run
|
156
|
+
Run `terraform init` across all accounts:
|
132
157
|
|
158
|
+
[source,shell]
|
133
159
|
----
|
134
|
-
tfctl
|
160
|
+
tfctl --all -- init
|
135
161
|
----
|
136
162
|
|
137
|
-
|
163
|
+
Plan Terraform across all accounts in the `test` OU:
|
138
164
|
|
165
|
+
[source,shell]
|
139
166
|
----
|
140
|
-
tfctl -
|
167
|
+
tfctl -o test -- plan
|
141
168
|
----
|
142
169
|
|
143
|
-
|
170
|
+
Plan Terraform in `live` accounts, assuming that `live` is a child OU in multiple
|
144
171
|
organization units:
|
145
172
|
|
173
|
+
[source,shell]
|
146
174
|
----
|
147
|
-
tfctl -
|
175
|
+
tfctl -o '.*/live' -- plan
|
148
176
|
----
|
149
177
|
|
150
|
-
Run plan
|
178
|
+
Run a plan for an individual account:
|
151
179
|
|
180
|
+
[source,shell]
|
152
181
|
----
|
153
|
-
tfctl -
|
182
|
+
tfctl -a example-account - plan
|
154
183
|
----
|
155
184
|
|
156
|
-
|
185
|
+
Apply Terraform changes across all accounts:
|
157
186
|
|
187
|
+
[source,shell]
|
158
188
|
----
|
159
|
-
tfctl
|
189
|
+
tfctl --all -- apply
|
160
190
|
----
|
161
191
|
|
162
|
-
|
192
|
+
Destroy Terraform-managed resources in all the `test` OU accounts:
|
163
193
|
|
194
|
+
[source,shell]
|
164
195
|
----
|
165
|
-
tfctl -
|
196
|
+
tfctl -o test -- destroy -auto-approve
|
166
197
|
----
|
167
198
|
|
168
199
|
Don't buffer the output:
|
169
200
|
|
201
|
+
[source,shell]
|
170
202
|
----
|
171
|
-
tfctl -
|
203
|
+
tfctl -a example-account -u -- plan
|
172
204
|
----
|
173
205
|
|
174
206
|
This will show output in real time. Usually output is buffered and displayed
|
175
|
-
after Terraform command finishes to make it more readable when running
|
176
|
-
multiple accounts in parallel.
|
207
|
+
after the Terraform command finishes, to make it more readable when running
|
208
|
+
across multiple accounts in parallel.
|
data/RELEASING.adoc
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
= Releasing
|
2
|
+
|
3
|
+
This document is aimed at `tfctl` maintainers and describes the process of
|
4
|
+
releasing a new gem version.
|
5
|
+
|
6
|
+
== Process
|
7
|
+
|
8
|
+
* Smoke test in SF test accounts: https://github.com/scalefactory/tfctl-test
|
9
|
+
* Bump version in `lib/tfctl/version.rb`
|
10
|
+
* Update `CHANGELOG.adoc`
|
11
|
+
* Commit
|
12
|
+
* Create a new GitHub release and version tag using format: vX.X.X
|
13
|
+
* TravisCI will build and release the gem automatically: https://travis-ci.org/github/scalefactory/tfctl
|
data/bin/tfctl
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
if File.directory?(File.dirname(__FILE__)
|
4
|
+
if File.directory?("#{File.dirname(__FILE__)}/../vendor")
|
5
5
|
require 'bundler/setup'
|
6
6
|
end
|
7
7
|
require 'optparse'
|
@@ -22,7 +22,7 @@ options = {
|
|
22
22
|
ou: nil,
|
23
23
|
all: nil,
|
24
24
|
show_config: false,
|
25
|
-
config_file:
|
25
|
+
config_file: 'tfctl.yaml',
|
26
26
|
unbuffered: false,
|
27
27
|
debug: false,
|
28
28
|
use_cache: false,
|
@@ -68,10 +68,6 @@ begin
|
|
68
68
|
|
69
69
|
# Validate CLI arguments
|
70
70
|
|
71
|
-
if options[:config_file].nil?
|
72
|
-
raise OptionParser::MissingArgument, '--config-file'
|
73
|
-
end
|
74
|
-
|
75
71
|
unless File.exist? options[:config_file]
|
76
72
|
raise OptionParser::InvalidOption,
|
77
73
|
"Config file not found in: #{options[:config_file]}"
|
@@ -85,8 +81,8 @@ begin
|
|
85
81
|
targetting_opts = %i[account ou all]
|
86
82
|
targets_set = []
|
87
83
|
options.each do |k, v|
|
88
|
-
if targetting_opts.include?(k)
|
89
|
-
targets_set << k.to_s
|
84
|
+
if targetting_opts.include?(k) and !v.nil?
|
85
|
+
targets_set << k.to_s
|
90
86
|
end
|
91
87
|
end
|
92
88
|
if targets_set.length > 1
|
@@ -104,7 +100,7 @@ end
|
|
104
100
|
|
105
101
|
|
106
102
|
|
107
|
-
#
|
103
|
+
# Execute terraform in target accounts
|
108
104
|
def run_account(config, account, options, tf_argv, log)
|
109
105
|
|
110
106
|
# Skip excluded accounts
|
@@ -145,6 +141,7 @@ begin
|
|
145
141
|
log.info 'tfctl running'
|
146
142
|
|
147
143
|
config_name = File.basename(options[:config_file]).chomp('.yaml')
|
144
|
+
config_name = 'default' if config_name == 'tfctl'
|
148
145
|
log.info "Using config: #{config_name}"
|
149
146
|
|
150
147
|
log.info 'Working out AWS account topology'
|
data/docs/configuration.adoc
CHANGED
@@ -24,8 +24,8 @@ toc::[]
|
|
24
24
|
|
25
25
|
== Overview
|
26
26
|
|
27
|
-
|
28
|
-
it with configuration specified in
|
27
|
+
`tfctl` retrieves initial account configuration from AWS Organizations and merges
|
28
|
+
it with configuration specified in YAML format (`tfctl.yaml` by default).
|
29
29
|
|
30
30
|
The configuration is merged in the following order:
|
31
31
|
|
@@ -68,9 +68,9 @@ organization_units:
|
|
68
68
|
|
69
69
|
This will result in all three profiles deployed to accounts in `team` OU.
|
70
70
|
|
71
|
-
TIP: You can display the fully merged configuration by running `tfctl -
|
72
|
-
|
73
|
-
|
71
|
+
TIP: You can display the fully merged configuration by running `tfctl -s`.
|
72
|
+
It's safe to run as it doesn't make any changes to AWS resources. It's a good
|
73
|
+
way to test your configuration.
|
74
74
|
|
75
75
|
== Defining arbitrary data
|
76
76
|
|
@@ -83,7 +83,17 @@ above.
|
|
83
83
|
|
84
84
|
== Handling secrets
|
85
85
|
|
86
|
-
|
87
|
-
|
86
|
+
CAUTION: Do not commit secrets into your Terraform or tfctl configuration.
|
87
|
+
|
88
|
+
Instead, use AWS Secrets Manager and retrieve secrets in Terraform profiles using
|
89
|
+
the
|
88
90
|
https://www.terraform.io/docs/providers/aws/d/secretsmanager_secret.html[secrets
|
89
|
-
manager data source]
|
91
|
+
manager data source].
|
92
|
+
|
93
|
+
== Configuration Schema
|
94
|
+
|
95
|
+
The configuration file is validated using https://json-schema.org/[JSON Schema].
|
96
|
+
|
97
|
+
The schema is defined in
|
98
|
+
https://github.com/scalefactory/tfctl/blob/master/lib/tfctl/schema.rb[lib/tfctl/schema.rb]
|
99
|
+
and is a good place to look up all available options.
|
data/docs/control_tower.adoc
CHANGED
@@ -31,7 +31,7 @@ toc::[]
|
|
31
31
|
For state tracking we're going to create a dedicated `shared-services` account
|
32
32
|
under a `mgmt` organization unit. We'll use S3 for state storage and DynamoDB
|
33
33
|
for locking. `TerraformState` IAM role will be created for cross account
|
34
|
-
access to state resources from the primary account.
|
34
|
+
access to state resources from the primary AWS account.
|
35
35
|
|
36
36
|
In the primary account we'll create a `TfctlOrgAccess` role. It gives tfctl
|
37
37
|
read only access to AWS Organizations which is used to discover accounts and
|
@@ -50,9 +50,10 @@ and provision a couple of accounts for testing.
|
|
50
50
|
|
51
51
|
Before starting you'll need:
|
52
52
|
|
53
|
-
*
|
54
|
-
*
|
55
|
-
*
|
53
|
+
* An AWS account that is part of an Organization.
|
54
|
+
* Control Tower set up in your primary AWS account.
|
55
|
+
* A user with `AdministratorAccess` privileges in your primary AWS account.
|
56
|
+
* AWS CLI tools installed on your local machine.
|
56
57
|
* Terraform 0.12 or higher.
|
57
58
|
|
58
59
|
== Configure Control Tower
|
@@ -74,6 +75,7 @@ approximately 20 mins to provision one.
|
|
74
75
|
|
75
76
|
== Install tfctl
|
76
77
|
|
78
|
+
[source,shell]
|
77
79
|
----
|
78
80
|
git clone git@github.com:scalefactory/tfctl.git
|
79
81
|
cd tfctl/ && sudo make install
|
@@ -85,17 +87,21 @@ It's assumed you have configured AWS CLI access to the primary account.
|
|
85
87
|
|
86
88
|
We'll use CloudFormation templates in `examples/bootstrap/`.
|
87
89
|
|
88
|
-
First export configuration using environment variables making sure to change to
|
89
|
-
values to suit your
|
90
|
+
First export configuration using environment variables, making sure to change to
|
91
|
+
values to suit your setup:
|
90
92
|
|
93
|
+
[source,shell]
|
91
94
|
----
|
92
|
-
|
93
|
-
export
|
95
|
+
# Change these to match your setup
|
96
|
+
export PRIMARY_ACCOUNT_ID=123456789012
|
97
|
+
export SHARED_SERVICES_ACCOUNT_ID=345678901234
|
94
98
|
export STATE_BUCKET_NAME='example-terraform-state'
|
99
|
+
export AWS_REGION=eu-west-1
|
95
100
|
----
|
96
101
|
|
97
102
|
Create the remote state resources stack set:
|
98
103
|
|
104
|
+
[source,shell]
|
99
105
|
----
|
100
106
|
cd examples/bootstrap/
|
101
107
|
|
@@ -107,31 +113,34 @@ aws cloudformation create-stack-set \
|
|
107
113
|
--execution-role-name AWSControlTowerExecution \
|
108
114
|
--administration-role-arn arn:aws:iam::${PRIMARY_ACCOUNT_ID}:role/service-role/AWSControlTowerStackSetRole \
|
109
115
|
--parameters ParameterKey=PrimaryAccountId,ParameterValue=${PRIMARY_ACCOUNT_ID} \
|
110
|
-
ParameterKey=TerraformStateBucket,ParameterValue
|
116
|
+
ParameterKey=TerraformStateBucket,ParameterValue="${STATE_BUCKET_NAME}"
|
111
117
|
----
|
112
118
|
|
113
|
-
Create a stack set instance in
|
119
|
+
Create a stack set instance in your shared services account:
|
114
120
|
|
121
|
+
[source,shell]
|
115
122
|
----
|
116
123
|
aws cloudformation create-stack-instances \
|
117
124
|
--stack-set-name TerraformState \
|
118
125
|
--accounts ${SHARED_SERVICES_ACCOUNT_ID} \
|
119
|
-
--regions
|
126
|
+
--regions ${AWS_REGION}
|
120
127
|
----
|
121
128
|
|
122
129
|
Check status:
|
123
130
|
|
131
|
+
[source,shell]
|
124
132
|
----
|
125
133
|
aws cloudformation describe-stack-instance \
|
126
134
|
--stack-set-name TerraformState \
|
127
135
|
--stack-instance-account ${SHARED_SERVICES_ACCOUNT_ID} \
|
128
|
-
--stack-instance-region
|
136
|
+
--stack-instance-region ${AWS_REGION}
|
129
137
|
----
|
130
138
|
|
131
139
|
NOTE: Initial status will be `OUTDATED`, it should change to `CURRENT` once deployed.
|
132
140
|
|
133
|
-
Deploy `TfctlOrgAccess` IAM role stack:
|
141
|
+
Deploy the `TfctlOrgAccess` IAM role stack:
|
134
142
|
|
143
|
+
[source,shell]
|
135
144
|
----
|
136
145
|
aws cloudformation create-stack \
|
137
146
|
--stack-name TfctlOrgAccess \
|
@@ -142,6 +151,7 @@ aws cloudformation create-stack \
|
|
142
151
|
|
143
152
|
Check status:
|
144
153
|
|
154
|
+
[source,shell]
|
145
155
|
----
|
146
156
|
aws cloudformation describe-stacks --stack-name TfctlOrgAccess
|
147
157
|
----
|
@@ -151,14 +161,14 @@ NOTE: Successful status should read: `CREATE_COMPLETE`.
|
|
151
161
|
== Configure tfctl
|
152
162
|
|
153
163
|
Copy the example project directory `examples/control_tower` somewhere convenient
|
154
|
-
and edit `
|
164
|
+
and edit `tfctl.yaml`.
|
155
165
|
|
156
166
|
You need to modify the following parameters:
|
157
167
|
|
158
168
|
* `tf_state_bucket` - set to `$STATE_BUCKET_NAME`
|
159
169
|
* `tf_state_role_arn` - set shared services account ID
|
160
170
|
* `tfctl_role_arn` - set primary account ID
|
161
|
-
* `primary_account` - set the primary account name. You can find it
|
171
|
+
* `primary_account` - set the primary account name. You can find it through AWS Organizations in the console.
|
162
172
|
|
163
173
|
TIP: You should keep your project directory under version control.
|
164
174
|
|
@@ -169,43 +179,51 @@ and `mgmt` OUs.
|
|
169
179
|
|
170
180
|
NOTE: Run tfctl commands from the root of you project directory.
|
171
181
|
|
172
|
-
First dump the configuration to verify everything works:
|
182
|
+
First, dump the configuration to verify everything works:
|
173
183
|
|
184
|
+
[source,shell]
|
174
185
|
----
|
175
|
-
tfctl -
|
186
|
+
tfctl -s
|
176
187
|
----
|
177
188
|
|
178
|
-
This will not make any changes but will print out
|
189
|
+
This will not make any changes but will print out YAML containing the final,
|
179
190
|
merged configuration data. It should contain a list of discovered accounts and
|
180
191
|
their configuration.
|
181
192
|
|
182
|
-
Initialise
|
193
|
+
Initialise Terraform for all discovered accounts:
|
183
194
|
|
195
|
+
[source,shell]
|
184
196
|
----
|
185
|
-
tfctl
|
197
|
+
tfctl --all -- init
|
186
198
|
----
|
187
199
|
|
188
200
|
Tfctl will run Terraform against all accounts in parallel.
|
189
201
|
|
190
|
-
|
202
|
+
`plan` the Terraform:
|
191
203
|
|
204
|
+
[source,shell]
|
192
205
|
----
|
193
|
-
tfctl
|
206
|
+
tfctl --all -- plan
|
194
207
|
----
|
195
208
|
|
196
|
-
and apply:
|
209
|
+
and `apply` it:
|
197
210
|
|
211
|
+
[source,shell]
|
198
212
|
----
|
199
|
-
tfctl
|
213
|
+
tfctl --all -- apply
|
200
214
|
----
|
201
215
|
|
202
|
-
To destroy created resources run:
|
203
216
|
|
217
|
+
== Clean up
|
218
|
+
|
219
|
+
To destroy created resources, run:
|
220
|
+
|
221
|
+
[source,shell]
|
204
222
|
----
|
205
|
-
tfctl
|
223
|
+
tfctl --all -- destroy -auto-approve
|
206
224
|
----
|
207
225
|
|
208
|
-
That's it! You can now execute
|
226
|
+
That's it! You can now execute Terraform across your Control Tower estate.
|
209
227
|
|
210
228
|
TIP: Your project directory should be under version control excluding the
|
211
229
|
`.tfctl` directory which is automatically generated.
|
@@ -81,7 +81,7 @@ profile. Tfctl configuration can be accessed using this variable. This It
|
|
81
81
|
includes an array of all discovered accounts as well their parameters from
|
82
82
|
tfctl config file.
|
83
83
|
|
84
|
-
TIP: You can run `tfctl -
|
84
|
+
TIP: You can run `tfctl -s` to show the config data in
|
85
85
|
yaml format. This exact data is available in the `config` variable in your
|
86
86
|
profile.
|
87
87
|
|
@@ -124,7 +124,7 @@ You have few options here:
|
|
124
124
|
For the sake of this example we're going to deploy our bucket to all accounts
|
125
125
|
in `test` OU.
|
126
126
|
|
127
|
-
In tfctl
|
127
|
+
In `tfctl.yaml` add the profile to the `test` OU:
|
128
128
|
|
129
129
|
[source, yaml]
|
130
130
|
----
|
@@ -140,8 +140,8 @@ organization_units:
|
|
140
140
|
To see what would happen when the change is applied run:
|
141
141
|
|
142
142
|
----
|
143
|
-
tfctl -
|
144
|
-
tfctl -
|
143
|
+
tfctl -o test -- init
|
144
|
+
tfctl -o test -- plan
|
145
145
|
----
|
146
146
|
|
147
147
|
This will run `terraform init` to initialise terraform and then `terraform
|
@@ -187,5 +187,5 @@ next step.
|
|
187
187
|
|
188
188
|
Once you're happy with the plan, apply it.
|
189
189
|
----
|
190
|
-
tfctl -
|
190
|
+
tfctl -o test -- apply
|
191
191
|
----
|
data/docs/iam_permissions.adoc
CHANGED
@@ -20,7 +20,7 @@ endif::[]
|
|
20
20
|
|
21
21
|
= IAM roles
|
22
22
|
|
23
|
-
|
23
|
+
`tfctl` usually requires three IAM roles to be configured:
|
24
24
|
|
25
25
|
* `TfctlRole` - read only access to AWS Organizations set up in the primary account.
|
26
26
|
* `TerraformStateRole` - access to remote state resources (S3, DynamoDB) in the
|
@@ -28,7 +28,7 @@ Tfctl usually requires three IAM roles to be configured:
|
|
28
28
|
* `TerraformExecutionRole` - configured in all spoke accounts and used for executing Terraform.
|
29
29
|
|
30
30
|
The user executing tfctl needs permission to assume all three roles cross
|
31
|
-
account.
|
31
|
+
account. Once these are configured, tfctl automatically assumes roles for you.
|
32
32
|
|
33
33
|
It's possible to configure different Terraform execution roles in different
|
34
34
|
spoke accounts based on OU or account names. This can be used to restrict
|
data/docs/project_layout.adoc
CHANGED
@@ -23,8 +23,7 @@ endif::[]
|
|
23
23
|
Example project structure
|
24
24
|
----
|
25
25
|
project_dir/
|
26
|
-
├── conf
|
27
|
-
│ └── example.yaml
|
26
|
+
├── tfctl.conf
|
28
27
|
├── modules
|
29
28
|
│ └── s3-bucket
|
30
29
|
│ ├── main.tf
|
@@ -51,7 +50,12 @@ The configuration data is exposed to terraform via a profile `config` variable.
|
|
51
50
|
It also defines Terraform and tfctl configuration such as state tracking and
|
52
51
|
what IAM roles to use.
|
53
52
|
|
54
|
-
|
53
|
+
By default, tfctl will use `tfctl.yaml` in its current working directory. You
|
54
|
+
can specify a different file using `-c`. Multiple configurations are supported
|
55
|
+
in the same project directory and generated data will be stored separately for
|
56
|
+
each config file in `.tfctl/`.
|
57
|
+
|
58
|
+
== `profiles`
|
55
59
|
|
56
60
|
Profiles are re-usable collections of resources which can be applied to
|
57
61
|
accounts. They are implemented just like usual modules but provide an
|
@@ -60,6 +64,6 @@ other data sources). Profiles often compose multiple modules and provide
|
|
60
64
|
configuration data to them. This approach makes it possible to re-use standard
|
61
65
|
modules (e.g. Terraform module registry).
|
62
66
|
|
63
|
-
== modules
|
67
|
+
== `modules`
|
64
68
|
|
65
69
|
Standard Terraform modules.
|
@@ -7,6 +7,6 @@ variable "config" {
|
|
7
7
|
locals {
|
8
8
|
config = jsondecode(var.config)
|
9
9
|
account_id = "${data.aws_caller_identity.current.account_id}"
|
10
|
-
# get
|
10
|
+
# get account configuration from tfctl config
|
11
11
|
account = [ for account in local.config["accounts"]: account if account["id"] == local.account_id ][0]
|
12
12
|
}
|
@@ -5,7 +5,7 @@
|
|
5
5
|
# create final configuration used by tfctl. You can view the merged
|
6
6
|
# configuration by running:
|
7
7
|
#
|
8
|
-
# tfctl -c conf/
|
8
|
+
# tfctl -c conf/tfctl.yaml -s
|
9
9
|
#
|
10
10
|
|
11
11
|
#
|
@@ -17,7 +17,7 @@ tf_state_dynamodb_table: 'terraform-lock'
|
|
17
17
|
tf_state_region: 'eu-west-1'
|
18
18
|
# Role for accessing state resources
|
19
19
|
tf_state_role_arn: 'arn:aws:iam::SHARED_SERVICES_ACCOUNT_ID:role/TerraformStateRole'
|
20
|
-
tf_required_version: '>= 0.12.
|
20
|
+
tf_required_version: '>= 0.12.29'
|
21
21
|
aws_provider_version: '>= 2.14'
|
22
22
|
# Role used by tfctl to retrieve data from AWS Organizations
|
23
23
|
# Has to be set up in the primary org account
|
data/lib/hash.rb
CHANGED
@@ -18,13 +18,14 @@ class Hash
|
|
18
18
|
merge(second.to_h, &merger)
|
19
19
|
end
|
20
20
|
|
21
|
-
# Copied from ruby 2.6 Psych for 2.3 compatibility.
|
22
21
|
def symbolize_names!(result = self)
|
23
22
|
case result
|
24
23
|
when Hash
|
24
|
+
# rubocop:disable Style/HashEachMethods
|
25
25
|
result.keys.each do |key|
|
26
26
|
result[key.to_sym] = symbolize_names!(result.delete(key))
|
27
27
|
end
|
28
|
+
# rubocop:enable Style/HashEachMethods
|
28
29
|
when Array
|
29
30
|
result.map! { |r| symbolize_names!(r) }
|
30
31
|
end
|
data/lib/tfctl.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative 'tfctl/aws_org
|
4
|
-
require_relative 'tfctl/config
|
5
|
-
require_relative 'tfctl/error
|
6
|
-
require_relative 'tfctl/executor
|
7
|
-
require_relative 'tfctl/generator
|
8
|
-
require_relative 'tfctl/logger
|
9
|
-
require_relative 'tfctl/schema
|
10
|
-
require_relative 'tfctl/version
|
3
|
+
require_relative 'tfctl/aws_org'
|
4
|
+
require_relative 'tfctl/config'
|
5
|
+
require_relative 'tfctl/error'
|
6
|
+
require_relative 'tfctl/executor'
|
7
|
+
require_relative 'tfctl/generator'
|
8
|
+
require_relative 'tfctl/logger'
|
9
|
+
require_relative 'tfctl/schema'
|
10
|
+
require_relative 'tfctl/version'
|
data/lib/tfctl/aws_org.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative 'error
|
3
|
+
require_relative 'error'
|
4
4
|
require 'aws-sdk-organizations'
|
5
5
|
|
6
6
|
module Tfctl
|
@@ -71,23 +71,25 @@ module Tfctl
|
|
71
71
|
@aws_org_client.list_children(
|
72
72
|
child_type: 'ORGANIZATIONAL_UNIT',
|
73
73
|
parent_id: parent_id,
|
74
|
-
).
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
74
|
+
).each do |resp|
|
75
|
+
resp.children.each do |child|
|
76
|
+
|
77
|
+
begin
|
78
|
+
ou = @aws_org_client.describe_organizational_unit(
|
79
|
+
organizational_unit_id: child.id,
|
80
|
+
).organizational_unit
|
81
|
+
rescue Aws::Organizations::Errors::TooManyRequestsException
|
82
|
+
# FIXME: - use logger
|
83
|
+
puts 'AWS Organizations: too many requests. Retrying in 5 secs.'
|
84
|
+
sleep 5
|
85
|
+
retries += 1
|
86
|
+
retry if retries < 10
|
87
|
+
end
|
87
88
|
|
88
|
-
|
89
|
+
ou_name = parent_name == :root ? ou.name.to_sym : "#{parent_name}/#{ou.name}".to_sym
|
89
90
|
|
90
|
-
|
91
|
+
output[ou_name] = ou.id
|
92
|
+
end
|
91
93
|
end
|
92
94
|
output
|
93
95
|
end
|
data/lib/tfctl/config.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative '../hash
|
4
|
-
require_relative 'error
|
3
|
+
require_relative '../hash'
|
4
|
+
require_relative 'error'
|
5
5
|
require 'yaml'
|
6
6
|
require 'json'
|
7
7
|
|
@@ -48,7 +48,7 @@ module Tfctl
|
|
48
48
|
@config.to_json
|
49
49
|
end
|
50
50
|
|
51
|
-
# Filters accounts by account property
|
51
|
+
# Filters accounts by an account property
|
52
52
|
def find_accounts(property_name, property_value)
|
53
53
|
output =[]
|
54
54
|
@config[:accounts].each do |account|
|
@@ -88,7 +88,6 @@ module Tfctl
|
|
88
88
|
|
89
89
|
# Retrieves AWS Organizations data and merges it with data from yaml config.
|
90
90
|
def load_config(config_name, yaml_config, aws_org_config)
|
91
|
-
|
92
91
|
# AWS Organizations data
|
93
92
|
config = aws_org_config
|
94
93
|
# Merge organization sections from yaml file
|
@@ -122,7 +121,9 @@ module Tfctl
|
|
122
121
|
return config unless config.key?(:exclude_accounts)
|
123
122
|
|
124
123
|
config[:accounts].each_with_index do |account, idx|
|
124
|
+
# rubocop:disable Style/IfWithBooleanLiteralBranches
|
125
125
|
config[:accounts][idx][:excluded] = config[:exclude_accounts].include?(account[:name]) ? true : false
|
126
|
+
# rubocop:enable Style/IfWithBooleanLiteralBranches
|
126
127
|
end
|
127
128
|
|
128
129
|
config
|
data/lib/tfctl/executor.rb
CHANGED
data/lib/tfctl/generator.rb
CHANGED
@@ -10,21 +10,27 @@ module Tfctl
|
|
10
10
|
|
11
11
|
def write_json_block(path, block)
|
12
12
|
File.open(path, 'w') do |f|
|
13
|
-
f.write(JSON.pretty_generate(block)
|
13
|
+
f.write("#{JSON.pretty_generate(block)}\n")
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
17
|
def make(account:, config:)
|
18
18
|
target_dir = "#{PROJECT_ROOT}/.tfctl/#{config[:config_name]}/#{account[:name]}"
|
19
|
-
tf_version = config.fetch(:tf_required_version, '>= 0.12.
|
19
|
+
tf_version = config.fetch(:tf_required_version, '>= 0.12.29')
|
20
20
|
aws_provider_version = config.fetch(:aws_provider_version, '>= 2.14')
|
21
21
|
|
22
22
|
FileUtils.mkdir_p target_dir
|
23
23
|
|
24
24
|
terraform_block = {
|
25
25
|
'terraform' => {
|
26
|
-
'required_version'
|
27
|
-
'
|
26
|
+
'required_version' => tf_version,
|
27
|
+
'required_providers' => {
|
28
|
+
'aws' => {
|
29
|
+
'source' => 'hashicorp/aws',
|
30
|
+
'version' => aws_provider_version,
|
31
|
+
},
|
32
|
+
},
|
33
|
+
'backend' => {
|
28
34
|
's3' => {
|
29
35
|
'bucket' => config[:tf_state_bucket],
|
30
36
|
'key' => "#{account[:name]}/tfstate",
|
@@ -41,7 +47,6 @@ module Tfctl
|
|
41
47
|
provider_block = {
|
42
48
|
'provider' => {
|
43
49
|
'aws' => {
|
44
|
-
'version' => aws_provider_version,
|
45
50
|
'region' => account[:region],
|
46
51
|
'assume_role' => {
|
47
52
|
'role_arn' => "arn:aws:iam::#{account[:id]}:role/#{account[:tf_execution_role]}",
|
@@ -71,11 +76,8 @@ module Tfctl
|
|
71
76
|
profile_block = {
|
72
77
|
'module' => {
|
73
78
|
profile => {
|
74
|
-
'source'
|
75
|
-
'config'
|
76
|
-
'providers' => {
|
77
|
-
'aws' => 'aws',
|
78
|
-
},
|
79
|
+
'source' => "../../../profiles/#{profile}",
|
80
|
+
'config' => '${var.config}',
|
79
81
|
},
|
80
82
|
},
|
81
83
|
}
|
data/lib/tfctl/logger.rb
CHANGED
data/lib/tfctl/schema.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'json_schemer'
|
4
|
-
require_relative 'error
|
4
|
+
require_relative 'error'
|
5
5
|
|
6
6
|
# Config validator using JSON schema
|
7
7
|
|
@@ -29,7 +29,7 @@ module Tfctl
|
|
29
29
|
def main_schema
|
30
30
|
iam_arn_pattern = 'arn:aws:iam:[a-z\-0-9]*:[0-9]{12}:[a-zA-Z\/+@=.,]*'
|
31
31
|
|
32
|
-
# rubocop:disable Layout/
|
32
|
+
# rubocop:disable Layout/HashAlignment
|
33
33
|
{
|
34
34
|
'type' => 'object',
|
35
35
|
'properties' => {
|
@@ -61,7 +61,7 @@ module Tfctl
|
|
61
61
|
],
|
62
62
|
'additionalProperties' => false,
|
63
63
|
}
|
64
|
-
# rubocop:enable Layout/
|
64
|
+
# rubocop:enable Layout/HashAlignment
|
65
65
|
end
|
66
66
|
|
67
67
|
def org_schema
|
data/lib/tfctl/version.rb
CHANGED
data/tfctl.gemspec
CHANGED
@@ -23,14 +23,17 @@ Gem::Specification.new do |spec|
|
|
23
23
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
24
24
|
spec.require_paths = ['lib']
|
25
25
|
|
26
|
+
spec.required_ruby_version = '>= 2.5.0'
|
27
|
+
|
26
28
|
# Think when adding new dependencies. Is it really necessary?
|
27
29
|
# "The things you own end up owning you" etc.
|
28
|
-
spec.add_dependency 'aws-sdk-organizations', '~> 1.
|
30
|
+
spec.add_dependency 'aws-sdk-organizations', '~> 1.40'
|
29
31
|
spec.add_dependency 'json_schemer', '~> 0.2'
|
30
|
-
spec.add_dependency 'parallel', '~> 1.
|
31
|
-
spec.add_dependency 'terminal-table', '
|
32
|
+
spec.add_dependency 'parallel', '~> 1.19'
|
33
|
+
spec.add_dependency 'terminal-table', '>= 1.8', '< 4.0'
|
32
34
|
|
33
|
-
spec.add_development_dependency 'guard-rspec',
|
34
|
-
spec.add_development_dependency 'rspec',
|
35
|
-
spec.add_development_dependency 'rubocop',
|
35
|
+
spec.add_development_dependency 'guard-rspec', '~> 4.7'
|
36
|
+
spec.add_development_dependency 'rspec', '~> 3.9'
|
37
|
+
spec.add_development_dependency 'rubocop', '~> 1.3'
|
38
|
+
spec.add_development_dependency 'rubocop-rspec', '~> 2.2'
|
36
39
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tfctl
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Wasilczuk
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-05-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: aws-sdk-organizations
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '1.
|
19
|
+
version: '1.40'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '1.
|
26
|
+
version: '1.40'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: json_schemer
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -44,28 +44,34 @@ dependencies:
|
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '1.
|
47
|
+
version: '1.19'
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '1.
|
54
|
+
version: '1.19'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: terminal-table
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- - "
|
59
|
+
- - ">="
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '1.8'
|
62
|
+
- - "<"
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: '4.0'
|
62
65
|
type: :runtime
|
63
66
|
prerelease: false
|
64
67
|
version_requirements: !ruby/object:Gem::Requirement
|
65
68
|
requirements:
|
66
|
-
- - "
|
69
|
+
- - ">="
|
67
70
|
- !ruby/object:Gem::Version
|
68
71
|
version: '1.8'
|
72
|
+
- - "<"
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '4.0'
|
69
75
|
- !ruby/object:Gem::Dependency
|
70
76
|
name: guard-rspec
|
71
77
|
requirement: !ruby/object:Gem::Requirement
|
@@ -86,28 +92,42 @@ dependencies:
|
|
86
92
|
requirements:
|
87
93
|
- - "~>"
|
88
94
|
- !ruby/object:Gem::Version
|
89
|
-
version: '3.
|
95
|
+
version: '3.9'
|
90
96
|
type: :development
|
91
97
|
prerelease: false
|
92
98
|
version_requirements: !ruby/object:Gem::Requirement
|
93
99
|
requirements:
|
94
100
|
- - "~>"
|
95
101
|
- !ruby/object:Gem::Version
|
96
|
-
version: '3.
|
102
|
+
version: '3.9'
|
97
103
|
- !ruby/object:Gem::Dependency
|
98
104
|
name: rubocop
|
99
105
|
requirement: !ruby/object:Gem::Requirement
|
100
106
|
requirements:
|
101
107
|
- - "~>"
|
102
108
|
- !ruby/object:Gem::Version
|
103
|
-
version: '
|
109
|
+
version: '1.3'
|
110
|
+
type: :development
|
111
|
+
prerelease: false
|
112
|
+
version_requirements: !ruby/object:Gem::Requirement
|
113
|
+
requirements:
|
114
|
+
- - "~>"
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: '1.3'
|
117
|
+
- !ruby/object:Gem::Dependency
|
118
|
+
name: rubocop-rspec
|
119
|
+
requirement: !ruby/object:Gem::Requirement
|
120
|
+
requirements:
|
121
|
+
- - "~>"
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
version: '2.2'
|
104
124
|
type: :development
|
105
125
|
prerelease: false
|
106
126
|
version_requirements: !ruby/object:Gem::Requirement
|
107
127
|
requirements:
|
108
128
|
- - "~>"
|
109
129
|
- !ruby/object:Gem::Version
|
110
|
-
version: '
|
130
|
+
version: '2.2'
|
111
131
|
description:
|
112
132
|
email:
|
113
133
|
- akw@scalefactory.com
|
@@ -116,6 +136,8 @@ executables:
|
|
116
136
|
extensions: []
|
117
137
|
extra_rdoc_files: []
|
118
138
|
files:
|
139
|
+
- ".bundle/config"
|
140
|
+
- ".github/dependabot.yml"
|
119
141
|
- ".gitignore"
|
120
142
|
- ".rspec"
|
121
143
|
- ".rubocop.yml"
|
@@ -126,6 +148,7 @@ files:
|
|
126
148
|
- LICENSE
|
127
149
|
- Makefile
|
128
150
|
- README.adoc
|
151
|
+
- RELEASING.adoc
|
129
152
|
- bin/tfctl
|
130
153
|
- docs/configuration.adoc
|
131
154
|
- docs/control_tower.adoc
|
@@ -135,12 +158,12 @@ files:
|
|
135
158
|
- examples/bootstrap/terraform-exec-role.template
|
136
159
|
- examples/bootstrap/terraform-state.template
|
137
160
|
- examples/bootstrap/tfctl-org-access.template
|
138
|
-
- examples/control_tower/conf/example.yaml
|
139
161
|
- examples/control_tower/modules/s3-bucket/main.tf
|
140
162
|
- examples/control_tower/modules/s3-bucket/variables.tf
|
141
163
|
- examples/control_tower/profiles/example-profile/data.tf
|
142
164
|
- examples/control_tower/profiles/example-profile/main.tf
|
143
165
|
- examples/control_tower/profiles/example-profile/variables.tf
|
166
|
+
- examples/control_tower/tfctl.yaml
|
144
167
|
- lib/hash.rb
|
145
168
|
- lib/tfctl.rb
|
146
169
|
- lib/tfctl/aws_org.rb
|
@@ -164,15 +187,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
164
187
|
requirements:
|
165
188
|
- - ">="
|
166
189
|
- !ruby/object:Gem::Version
|
167
|
-
version:
|
190
|
+
version: 2.5.0
|
168
191
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
169
192
|
requirements:
|
170
193
|
- - ">="
|
171
194
|
- !ruby/object:Gem::Version
|
172
195
|
version: '0'
|
173
196
|
requirements: []
|
174
|
-
|
175
|
-
rubygems_version: 2.7.7
|
197
|
+
rubygems_version: 3.0.8
|
176
198
|
signing_key:
|
177
199
|
specification_version: 4
|
178
200
|
summary: Terraform wrapper for managing multi-account AWS infrastructures
|