terraorg 0.3.0 → 0.5.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +11 -1
- data/bin/terraorg +3 -1
- data/lib/terraorg/model/org.rb +39 -10
- data/lib/terraorg/model/person.rb +4 -1
- data/lib/terraorg/version.rb +1 -1
- metadata +17 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9d4bc0b594ccdebdbc4f31ec4825e6ba58ae14d594c5ba583be66110146bb87e
|
4
|
+
data.tar.gz: e91277122e80da862872e04377857462d77bde314c79be37e0c9ec223dcc985c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f3a0ba270dd09ea04cf4f4acf32374110e1563c56c4259dd2f6664dce55dd37330732fd7bfa2ac530638599afd9e8974ce59bbe452af52bf4d434c5593072ed5
|
7
|
+
data.tar.gz: 2bc8103395027c04b74483da0bb62779eefa0544b2f3fc54f2f68131a8d2bec5a35043de45835d15e32fed572acc8b353a27f7ae9d045faf6b308d93524f8a29
|
data/README.md
CHANGED
@@ -34,7 +34,9 @@ Based on the org that this tool was originally designed for, orgs are expected
|
|
34
34
|
to have three levels:
|
35
35
|
|
36
36
|
* *squads*: the base unit of team-dom, containing people, who may be in
|
37
|
-
different geographical regions.
|
37
|
+
different geographical regions. Teams contain _members_ (full time heads)
|
38
|
+
and _associates_ (typically part time floaters.) Any associate of a squad
|
39
|
+
must also have a home squad for which they are a full time member.
|
38
40
|
* *platoons*: a unit which contains squads and exceptional people who are
|
39
41
|
members of the platoon, but not part of any squad
|
40
42
|
* *org*: The whole organization, including its manager, any exceptional squads
|
@@ -45,6 +47,10 @@ The tool generates groups for each granular unit of organization in Okta and G
|
|
45
47
|
Suite in Terraform. With patching, it could be possible for more organizational
|
46
48
|
systems to be supported.
|
47
49
|
|
50
|
+
## Diagram
|
51
|
+
|
52
|
+
![Diagram of org structure](img/diagram.png)
|
53
|
+
|
48
54
|
## How it works
|
49
55
|
|
50
56
|
Firstly, take your entire existing organization and define it using the
|
@@ -120,6 +126,10 @@ information on how to configure the providers.
|
|
120
126
|
[articulate/terraform-provider-okta]: https://github.com/articulate/terraform-provider-okta
|
121
127
|
[DeviaVir/terraform-provider-gsuite]: https://github.com/DeviaVir/terraform-provider-gsuite
|
122
128
|
|
129
|
+
## Running tests
|
130
|
+
There are a limited number of tests that can be invoked with
|
131
|
+
`ruby -I lib test/terraorg/model/org_test.rb `
|
132
|
+
|
123
133
|
## Suggested process
|
124
134
|
|
125
135
|
At [LiveRamp], a pull request based workflow leveraging [Atlantis] is used to
|
data/bin/terraorg
CHANGED
@@ -32,6 +32,7 @@ ACTIONS = [
|
|
32
32
|
].freeze
|
33
33
|
|
34
34
|
STRICT_VALIDATION = ENV.fetch('TERRAORG_STRICT_VALIDATION', 'true')
|
35
|
+
ALLOW_ORPHANED_ASSOCIATES = ENV.fetch('ALLOW_ORPHANED_ASSOCIATES', 'false')
|
35
36
|
SQUADS_FILE = ENV.fetch('TERRAORG_SQUADS', 'squads.json')
|
36
37
|
PLATOONS_FILE = ENV.fetch('TERRAORG_PLATOONS', 'platoons.json')
|
37
38
|
ORG_FILE = ENV.fetch('TERRAORG_ROOT', 'org.json')
|
@@ -97,7 +98,8 @@ org_data = File.read(ORG_FILE)
|
|
97
98
|
org = Org.new(JSON.parse(org_data), platoons, squads, people, GSUITE_DOMAIN)
|
98
99
|
|
99
100
|
strict = (STRICT_VALIDATION == 'true')
|
100
|
-
|
101
|
+
allow_orphaned_associates = (ALLOW_ORPHANED_ASSOCIATES == 'true')
|
102
|
+
org.validate!(strict: strict, allow_orphaned_associates: allow_orphaned_associates)
|
101
103
|
|
102
104
|
case action
|
103
105
|
when 'generate-squads-md'
|
data/lib/terraorg/model/org.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# Copyright 2019-2020 LiveRamp Holdings, Inc.
|
2
|
+
# Copyright 2020- Joshua Kwan
|
2
3
|
#
|
3
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
5
|
# you may not use this file except in compliance with the License.
|
@@ -49,12 +50,12 @@ class Org
|
|
49
50
|
@squads = squads
|
50
51
|
end
|
51
52
|
|
52
|
-
def validate!(strict: true)
|
53
|
+
def validate!(strict: true, allow_orphaned_associates: false)
|
53
54
|
failure = false
|
54
55
|
|
55
56
|
# Do not allow the JSON files to contain any people who have left.
|
56
57
|
unless @people.inactive.empty?
|
57
|
-
$stderr.puts "ERROR: Users have left the company: #{@people.inactive.map(&:id).join(', ')}"
|
58
|
+
$stderr.puts "ERROR: Users have left the company, or are Suspended in Okta: #{@people.inactive.map(&:id).join(', ')}"
|
58
59
|
failure = true
|
59
60
|
end
|
60
61
|
|
@@ -97,7 +98,8 @@ class Org
|
|
97
98
|
# across the entire org. A person can be an associate of other squads
|
98
99
|
# at a different count. See top of file for defined limits.
|
99
100
|
squad_count = {}
|
100
|
-
all_squads.map(&:teams).flatten.map(&:values).flatten.map(&:members).flatten
|
101
|
+
all_members = all_squads.map(&:teams).flatten.map(&:values).flatten.map(&:members).flatten
|
102
|
+
all_members.each do |member|
|
101
103
|
squad_count[member.id] = squad_count.fetch(member.id, 0) + 1
|
102
104
|
end
|
103
105
|
more_than_max_squads = squad_count.select do |member, count|
|
@@ -109,7 +111,8 @@ class Org
|
|
109
111
|
end
|
110
112
|
|
111
113
|
associate_count = {}
|
112
|
-
all_squads.map(&:teams).flatten.map(&:values).flatten.map(&:associates).flatten
|
114
|
+
all_associates = all_squads.map(&:teams).flatten.map(&:values).flatten.map(&:associates).flatten
|
115
|
+
all_associates.each do |assoc|
|
113
116
|
associate_count[assoc.id] = associate_count.fetch(assoc.id, 0) + 1
|
114
117
|
end
|
115
118
|
more_than_max_squads = associate_count.select do |_, count|
|
@@ -130,6 +133,15 @@ class Org
|
|
130
133
|
failure = true
|
131
134
|
end
|
132
135
|
|
136
|
+
# Validate that any associate is a member of some squad
|
137
|
+
if !allow_orphaned_associates
|
138
|
+
associates_but_not_members = Set.new(all_associates.map(&:id)) - Set.new(all_members.map(&:id)) - exceptions
|
139
|
+
if !associates_but_not_members.empty?
|
140
|
+
$stderr.puts "ERROR: #{associates_but_not_members.to_a} are associates of squads but not members of any squad"
|
141
|
+
failure = true
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
133
145
|
raise "CRITICAL: Validation failed due to at least one error above" if failure && strict
|
134
146
|
end
|
135
147
|
|
@@ -193,13 +205,16 @@ class Org
|
|
193
205
|
md_lines.join("\n")
|
194
206
|
end
|
195
207
|
|
196
|
-
def
|
197
|
-
|
198
|
-
|
208
|
+
def generate_tf_platoons
|
209
|
+
@member_platoons.map { |p| p.generate_tf(@id) }.join("\n")
|
210
|
+
end
|
199
211
|
|
200
|
-
|
201
|
-
|
212
|
+
def generate_tf_squads
|
213
|
+
@member_exception_squads.map { |s| s.generate_tf(@id) }.join("\n")
|
214
|
+
end
|
202
215
|
|
216
|
+
def generate_tf_org
|
217
|
+
tf = ''
|
203
218
|
# Roll all platoons and exception squads into the org.
|
204
219
|
roll_up_to_org = \
|
205
220
|
@member_exception_squads.map { |s| s.unique_name(@id, nil) } + \
|
@@ -239,14 +254,18 @@ EOF
|
|
239
254
|
all_locations[@manager_location] = all_locations.fetch(@manager_location, Set.new).add(@manager)
|
240
255
|
|
241
256
|
all_locations.each do |l, m|
|
257
|
+
description = "#{@name} organization members based in #{l} (terraorg)"
|
242
258
|
name = "#{unique_name}-#{l.downcase}"
|
243
259
|
tf += <<-EOF
|
244
260
|
resource "okta_group" "#{name}" {
|
245
261
|
name = "#{name}"
|
246
|
-
description = "#{
|
262
|
+
description = "#{description}"
|
247
263
|
users = #{Util.persons_tf(m)}
|
248
264
|
}
|
265
|
+
|
266
|
+
#{Util.gsuite_group_tf(name, @gsuite_domain, m, description)}
|
249
267
|
EOF
|
268
|
+
|
250
269
|
end
|
251
270
|
|
252
271
|
# Generate a special GSuite group for all managers (org, platoon, squad
|
@@ -255,7 +274,17 @@ EOF
|
|
255
274
|
all_managers = Set.new([@manager] + @platoons.all.map(&:manager) + @squads.all.map(&:manager).select { |m| m })
|
256
275
|
manager_dl = "#{@id}-managers"
|
257
276
|
tf += Util.gsuite_group_tf(manager_dl, @gsuite_domain, all_managers, "All managers of the #{@name} organization (terraorg)")
|
277
|
+
tf
|
278
|
+
end
|
279
|
+
|
280
|
+
def generate_tf
|
281
|
+
tf = generate_tf_platoons
|
282
|
+
File.write('auto.platoons.tf', tf)
|
283
|
+
|
284
|
+
tf = generate_tf_squads
|
285
|
+
File.write('auto.exception_squads.tf', tf)
|
258
286
|
|
287
|
+
tf = generate_tf_org
|
259
288
|
File.write('auto.org.tf', tf)
|
260
289
|
end
|
261
290
|
|
@@ -14,8 +14,11 @@
|
|
14
14
|
|
15
15
|
require 'faraday'
|
16
16
|
|
17
|
+
# The following statuses are considered ACTIVE by terraorg, which allow PRs to continue and be merged.
|
18
|
+
# A DEACTIVATED account status needs to be removed from the repository before merging PRs
|
19
|
+
|
17
20
|
class Person
|
18
|
-
ACTIVE_USER_STATUSES = ['ACTIVE', 'PROVISIONED'].freeze
|
21
|
+
ACTIVE_USER_STATUSES = ['ACTIVE', 'PROVISIONED', 'PASSWORD_EXPIRED', 'SUSPENDED'].freeze
|
19
22
|
|
20
23
|
attr_accessor :id, :name, :okta_id, :email, :status
|
21
24
|
|
data/lib/terraorg/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: terraorg
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joshua Kwan
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-01-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: countries
|
@@ -66,6 +66,20 @@ dependencies:
|
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0.2'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: minitest
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '5.14'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '5.14'
|
69
83
|
description: Manage an organizational structure with Okta and G-Suite using Terraform
|
70
84
|
email: joshk@triplehelix.org
|
71
85
|
executables:
|
@@ -104,7 +118,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
104
118
|
- !ruby/object:Gem::Version
|
105
119
|
version: '0'
|
106
120
|
requirements: []
|
107
|
-
rubygems_version: 3.0.
|
121
|
+
rubygems_version: 3.0.8
|
108
122
|
signing_key:
|
109
123
|
specification_version: 4
|
110
124
|
summary: terraorg
|