knife-tidy 1.0.1 → 1.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 +5 -5
- data/CHANGELOG.md +8 -205
- data/Rakefile +2 -2
- data/lib/chef/knife/tidy_backup_clean.rb +20 -22
- data/lib/chef/knife/tidy_base.rb +6 -8
- data/lib/chef/knife/tidy_notify.rb +116 -79
- data/lib/chef/knife/tidy_server_clean.rb +17 -17
- data/lib/chef/knife/tidy_server_report.rb +4 -3
- data/lib/chef/tidy_acls.rb +20 -24
- data/lib/chef/tidy_common.rb +3 -3
- data/lib/chef/tidy_substitutions.rb +2 -3
- data/lib/knife-tidy/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: fefc42c2e244bb50117ab8ce5fc5b8b6c5263a6211571279b9288e7f4132cc8e
|
4
|
+
data.tar.gz: b989cd57166d61a455619598b56f950449a05fdac1181f23edf20f0045dd9e2a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4570d1e16e3b42d1c356b27464d5de59d9dccd8700c6f0c7525da06ede382c8007ec4d8c2a8be6e4da991f3c62f302021f42cad7495d4ed6c1f6436620555bed
|
7
|
+
data.tar.gz: dce7f38a43495322dfac2cb5e9f12ebe1647a931b70bb16a08210bf975866eab94e47717224ce58763df3ee9775d77228a4e862cbf81454e9970bb44458aa920
|
data/CHANGELOG.md
CHANGED
@@ -1,220 +1,23 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
-
## [1.0
|
4
|
-
[Full Changelog](https://github.com/chef-customers/knife-tidy/compare/1.
|
3
|
+
## [1.1.0](https://github.com/chef-customers/knife-tidy/tree/1.1.0) (2018-01-11)
|
4
|
+
[Full Changelog](https://github.com/chef-customers/knife-tidy/compare/1.1.0...1.1.0)
|
5
5
|
|
6
6
|
**Closed issues:**
|
7
7
|
|
8
|
-
-
|
9
|
-
-
|
8
|
+
- notifications fail for chef orgs containing an underscore [\#77](https://github.com/chef-customers/knife-tidy/issues/77)
|
9
|
+
- Add option to attach raw JSON report files to the email notification [\#75](https://github.com/chef-customers/knife-tidy/issues/75)
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
- Fix validate\_user\_acls and default\_user\_acl methods [\#73](https://github.com/chef-customers/knife-tidy/pull/73) ([itmustbejj](https://github.com/itmustbejj))
|
14
|
-
|
15
|
-
## [1.0.0](https://github.com/chef-customers/knife-tidy/tree/1.0.0) (2017-12-04)
|
16
|
-
[Full Changelog](https://github.com/chef-customers/knife-tidy/compare/0.7.0...1.0.0)
|
17
|
-
|
18
|
-
**Merged pull requests:**
|
19
|
-
|
20
|
-
- Enabled cookbook deletion [\#71](https://github.com/chef-customers/knife-tidy/pull/71) ([itmustbejj](https://github.com/itmustbejj))
|
21
|
-
- Add option for backup path to server clean [\#70](https://github.com/chef-customers/knife-tidy/pull/70) ([TheLunaticScripter](https://github.com/TheLunaticScripter))
|
22
|
-
- Warn the user if there are nodes created in the last hour that haven'… [\#67](https://github.com/chef-customers/knife-tidy/pull/67) ([itmustbejj](https://github.com/itmustbejj))
|
23
|
-
- Add guard to skip generating org reports if the search index is not u… [\#66](https://github.com/chef-customers/knife-tidy/pull/66) ([itmustbejj](https://github.com/itmustbejj))
|
24
|
-
- Enable server clean command and clarify confirmation dialogue [\#31](https://github.com/chef-customers/knife-tidy/pull/31) ([jonlives](https://github.com/jonlives))
|
25
|
-
|
26
|
-
## [0.7.0](https://github.com/chef-customers/knife-tidy/tree/0.7.0) (2017-11-29)
|
27
|
-
[Full Changelog](https://github.com/chef-customers/knife-tidy/compare/0.6.1...0.7.0)
|
28
|
-
|
29
|
-
**Closed issues:**
|
30
|
-
|
31
|
-
- Users/clients from backups older than CS 12.5 may be missing read acls on clients [\#63](https://github.com/chef-customers/knife-tidy/issues/63)
|
32
|
-
- notify subcommand ignores --orgs option [\#59](https://github.com/chef-customers/knife-tidy/issues/59)
|
33
|
-
|
34
|
-
**Merged pull requests:**
|
35
|
-
|
36
|
-
- release 0.7.0 [\#65](https://github.com/chef-customers/knife-tidy/pull/65) ([jeremymv2](https://github.com/jeremymv2))
|
37
|
-
- Add admins/users groups to the read acl for clients from \< CS 12.5 [\#64](https://github.com/chef-customers/knife-tidy/pull/64) ([itmustbejj](https://github.com/itmustbejj))
|
38
|
-
- Restore acls for ::server-admins and org read access groups if they a… [\#61](https://github.com/chef-customers/knife-tidy/pull/61) ([itmustbejj](https://github.com/itmustbejj))
|
39
|
-
- Filter email notifications on org\_list config option. [\#60](https://github.com/chef-customers/knife-tidy/pull/60) ([itmustbejj](https://github.com/itmustbejj))
|
40
|
-
- Set default encoding to utf-8 to properly handle non-ascii in backups. [\#58](https://github.com/chef-customers/knife-tidy/pull/58) ([itmustbejj](https://github.com/itmustbejj))
|
41
|
-
- Add check for pre-12.3 nodes to report generation… [\#57](https://github.com/chef-customers/knife-tidy/pull/57) ([jonlives](https://github.com/jonlives))
|
42
|
-
- bump path to 0.6.1 [\#55](https://github.com/chef-customers/knife-tidy/pull/55) ([jeremymv2](https://github.com/jeremymv2))
|
43
|
-
|
44
|
-
## [0.6.1](https://github.com/chef-customers/knife-tidy/tree/0.6.1) (2017-10-26)
|
45
|
-
[Full Changelog](https://github.com/chef-customers/knife-tidy/compare/0.6.0...0.6.1)
|
46
|
-
|
47
|
-
**Closed issues:**
|
48
|
-
|
49
|
-
- knife tidy server clean - org names with \_ [\#53](https://github.com/chef-customers/knife-tidy/issues/53)
|
50
|
-
|
51
|
-
**Merged pull requests:**
|
52
|
-
|
53
|
-
- fixing orgs with underscores [\#54](https://github.com/chef-customers/knife-tidy/pull/54) ([jeremymv2](https://github.com/jeremymv2))
|
54
|
-
- Jeremymv2/release 0 6 0 [\#52](https://github.com/chef-customers/knife-tidy/pull/52) ([jeremymv2](https://github.com/jeremymv2))
|
55
|
-
|
56
|
-
## [0.6.0](https://github.com/chef-customers/knife-tidy/tree/0.6.0) (2017-10-23)
|
57
|
-
[Full Changelog](https://github.com/chef-customers/knife-tidy/compare/0.5.2...0.6.0)
|
58
|
-
|
59
|
-
**Merged pull requests:**
|
60
|
-
|
61
|
-
- fix travis [\#51](https://github.com/chef-customers/knife-tidy/pull/51) ([jeremymv2](https://github.com/jeremymv2))
|
62
|
-
- Add knife tidy notify command [\#50](https://github.com/chef-customers/knife-tidy/pull/50) ([jonlives](https://github.com/jonlives))
|
63
|
-
- bump to 0.5.2 [\#49](https://github.com/chef-customers/knife-tidy/pull/49) ([jeremymv2](https://github.com/jeremymv2))
|
64
|
-
|
65
|
-
## [0.5.2](https://github.com/chef-customers/knife-tidy/tree/0.5.2) (2017-10-20)
|
66
|
-
[Full Changelog](https://github.com/chef-customers/knife-tidy/compare/0.5.1...0.5.2)
|
67
|
-
|
68
|
-
**Merged pull requests:**
|
69
|
-
|
70
|
-
- fixing regex for whitespace [\#48](https://github.com/chef-customers/knife-tidy/pull/48) ([jeremymv2](https://github.com/jeremymv2))
|
71
|
-
- bump patch to 0.5.1 [\#47](https://github.com/chef-customers/knife-tidy/pull/47) ([jeremymv2](https://github.com/jeremymv2))
|
72
|
-
|
73
|
-
## [0.5.1](https://github.com/chef-customers/knife-tidy/tree/0.5.1) (2017-10-19)
|
74
|
-
[Full Changelog](https://github.com/chef-customers/knife-tidy/compare/0.5.0...0.5.1)
|
75
|
-
|
76
|
-
**Merged pull requests:**
|
77
|
-
|
78
|
-
- Add node\_count to stale node json output. [\#46](https://github.com/chef-customers/knife-tidy/pull/46) ([MarkGibbons](https://github.com/MarkGibbons))
|
79
|
-
- bump to 0.5.0 [\#45](https://github.com/chef-customers/knife-tidy/pull/45) ([jeremymv2](https://github.com/jeremymv2))
|
80
|
-
|
81
|
-
## [0.5.0](https://github.com/chef-customers/knife-tidy/tree/0.5.0) (2017-10-06)
|
82
|
-
[Full Changelog](https://github.com/chef-customers/knife-tidy/compare/0.4.1...0.5.0)
|
83
|
-
|
84
|
-
**Closed issues:**
|
85
|
-
|
86
|
-
- Supermarket.chef.io [\#37](https://github.com/chef-customers/knife-tidy/issues/37)
|
87
|
-
|
88
|
-
**Merged pull requests:**
|
89
|
-
|
90
|
-
- enabling deletion of stale nodes [\#44](https://github.com/chef-customers/knife-tidy/pull/44) ([jeremymv2](https://github.com/jeremymv2))
|
91
|
-
- better warning message before confirmation [\#43](https://github.com/chef-customers/knife-tidy/pull/43) ([jeremymv2](https://github.com/jeremymv2))
|
92
|
-
- Jeremymv2/chef sugar fix default [\#42](https://github.com/chef-customers/knife-tidy/pull/42) ([jeremymv2](https://github.com/jeremymv2))
|
93
|
-
- deleting nodes also deletes client [\#41](https://github.com/chef-customers/knife-tidy/pull/41) ([jeremymv2](https://github.com/jeremymv2))
|
94
|
-
- Change nodes\_list method to get all nodes [\#40](https://github.com/chef-customers/knife-tidy/pull/40) ([nsdavidson](https://github.com/nsdavidson))
|
95
|
-
- bump version to 0.4.1 [\#39](https://github.com/chef-customers/knife-tidy/pull/39) ([jeremymv2](https://github.com/jeremymv2))
|
96
|
-
|
97
|
-
## [0.4.1](https://github.com/chef-customers/knife-tidy/tree/0.4.1) (2017-09-27)
|
98
|
-
[Full Changelog](https://github.com/chef-customers/knife-tidy/compare/0.4.0...0.4.1)
|
99
|
-
|
100
|
-
**Merged pull requests:**
|
101
|
-
|
102
|
-
- fixing corrupt invitations and invalid platform names with commas in … [\#38](https://github.com/chef-customers/knife-tidy/pull/38) ([jeremymv2](https://github.com/jeremymv2))
|
103
|
-
- bump to 0.4.0 [\#36](https://github.com/chef-customers/knife-tidy/pull/36) ([jeremymv2](https://github.com/jeremymv2))
|
104
|
-
|
105
|
-
## [0.4.0](https://github.com/chef-customers/knife-tidy/tree/0.4.0) (2017-09-26)
|
106
|
-
[Full Changelog](https://github.com/chef-customers/knife-tidy/compare/0.3.6...0.4.0)
|
107
|
-
|
108
|
-
**Merged pull requests:**
|
109
|
-
|
110
|
-
- fix NilClass on env\_run\_lists [\#35](https://github.com/chef-customers/knife-tidy/pull/35) ([jeremymv2](https://github.com/jeremymv2))
|
111
|
-
- fix merge conflict from rebase [\#34](https://github.com/chef-customers/knife-tidy/pull/34) ([jeremymv2](https://github.com/jeremymv2))
|
112
|
-
- Simple feature to clean up EC11 org objects which don't load into CS12 [\#33](https://github.com/chef-customers/knife-tidy/pull/33) ([irvingpop](https://github.com/irvingpop))
|
113
|
-
- role run\_list clean up and metadata name regex simplification [\#32](https://github.com/chef-customers/knife-tidy/pull/32) ([jeremymv2](https://github.com/jeremymv2))
|
114
|
-
- bump to 0.3.6 [\#30](https://github.com/chef-customers/knife-tidy/pull/30) ([jeremymv2](https://github.com/jeremymv2))
|
115
|
-
|
116
|
-
## [0.3.6](https://github.com/chef-customers/knife-tidy/tree/0.3.6) (2017-09-25)
|
117
|
-
[Full Changelog](https://github.com/chef-customers/knife-tidy/compare/0.3.5...0.3.6)
|
118
|
-
|
119
|
-
**Merged pull requests:**
|
120
|
-
|
121
|
-
- first check if the\_user.has\_key?\('email'\) [\#29](https://github.com/chef-customers/knife-tidy/pull/29) ([jeremymv2](https://github.com/jeremymv2))
|
122
|
-
- bump to 0.3.5 [\#28](https://github.com/chef-customers/knife-tidy/pull/28) ([jeremymv2](https://github.com/jeremymv2))
|
123
|
-
|
124
|
-
## [0.3.5](https://github.com/chef-customers/knife-tidy/tree/0.3.5) (2017-09-20)
|
125
|
-
[Full Changelog](https://github.com/chef-customers/knife-tidy/compare/0.3.4...0.3.5)
|
126
|
-
|
127
|
-
**Merged pull requests:**
|
128
|
-
|
129
|
-
- Catch pins with no cookbooks [\#27](https://github.com/chef-customers/knife-tidy/pull/27) ([nsdavidson](https://github.com/nsdavidson))
|
130
|
-
|
131
|
-
## [0.3.4](https://github.com/chef-customers/knife-tidy/tree/0.3.4) (2017-09-16)
|
132
|
-
[Full Changelog](https://github.com/chef-customers/knife-tidy/compare/0.3.3...0.3.4)
|
133
|
-
|
134
|
-
**Merged pull requests:**
|
135
|
-
|
136
|
-
- check if metadata.has\_key?\('platforms'\) [\#26](https://github.com/chef-customers/knife-tidy/pull/26) ([jeremymv2](https://github.com/jeremymv2))
|
137
|
-
|
138
|
-
## [0.3.3](https://github.com/chef-customers/knife-tidy/tree/0.3.3) (2017-09-15)
|
139
|
-
[Full Changelog](https://github.com/chef-customers/knife-tidy/compare/0.3.2...0.3.3)
|
140
|
-
|
141
|
-
**Merged pull requests:**
|
142
|
-
|
143
|
-
- boiler plate gsub file now works [\#25](https://github.com/chef-customers/knife-tidy/pull/25) ([jeremymv2](https://github.com/jeremymv2))
|
144
|
-
- fixing null values and emtpy arrays in metadata.json [\#24](https://github.com/chef-customers/knife-tidy/pull/24) ([jeremymv2](https://github.com/jeremymv2))
|
145
|
-
- Jeremyv2/action needed notification [\#23](https://github.com/chef-customers/knife-tidy/pull/23) ([jeremymv2](https://github.com/jeremymv2))
|
146
|
-
|
147
|
-
## [0.3.2](https://github.com/chef-customers/knife-tidy/tree/0.3.2) (2017-09-14)
|
148
|
-
[Full Changelog](https://github.com/chef-customers/knife-tidy/compare/0.3.1...0.3.2)
|
149
|
-
|
150
|
-
**Merged pull requests:**
|
151
|
-
|
152
|
-
- fixed name mismatch in metadata.json [\#22](https://github.com/chef-customers/knife-tidy/pull/22) ([jeremymv2](https://github.com/jeremymv2))
|
153
|
-
|
154
|
-
## [0.3.1](https://github.com/chef-customers/knife-tidy/tree/0.3.1) (2017-09-14)
|
155
|
-
[Full Changelog](https://github.com/chef-customers/knife-tidy/compare/0.3.0...0.3.1)
|
156
|
-
|
157
|
-
**Merged pull requests:**
|
158
|
-
|
159
|
-
- generate a metadata.rb if needed [\#21](https://github.com/chef-customers/knife-tidy/pull/21) ([jeremymv2](https://github.com/jeremymv2))
|
160
|
-
- newline for action needed messages [\#20](https://github.com/chef-customers/knife-tidy/pull/20) ([jeremymv2](https://github.com/jeremymv2))
|
161
|
-
|
162
|
-
## [0.3.0](https://github.com/chef-customers/knife-tidy/tree/0.3.0) (2017-09-14)
|
163
|
-
[Full Changelog](https://github.com/chef-customers/knife-tidy/compare/0.2.4...0.3.0)
|
11
|
+
## [1.1.0](https://github.com/chef-customers/knife-tidy/tree/1.1.0) (2018-01-11)
|
12
|
+
[Full Changelog](https://github.com/chef-customers/knife-tidy/compare/1.0.1...1.1.0)
|
164
13
|
|
165
14
|
**Closed issues:**
|
166
15
|
|
167
|
-
-
|
168
|
-
|
169
|
-
**Merged pull requests:**
|
170
|
-
|
171
|
-
- bump to 0.3.0 [\#19](https://github.com/chef-customers/knife-tidy/pull/19) ([jeremymv2](https://github.com/jeremymv2))
|
172
|
-
- added dry-run to server clean [\#18](https://github.com/chef-customers/knife-tidy/pull/18) ([jeremymv2](https://github.com/jeremymv2))
|
173
|
-
|
174
|
-
## [0.2.4](https://github.com/chef-customers/knife-tidy/tree/0.2.4) (2017-09-12)
|
175
|
-
[Full Changelog](https://github.com/chef-customers/knife-tidy/compare/0.2.3...0.2.4)
|
176
|
-
|
177
|
-
**Merged pull requests:**
|
178
|
-
|
179
|
-
- disable server clean [\#17](https://github.com/chef-customers/knife-tidy/pull/17) ([jeremymv2](https://github.com/jeremymv2))
|
180
|
-
- bump patch to 0.2.4 [\#16](https://github.com/chef-customers/knife-tidy/pull/16) ([jeremymv2](https://github.com/jeremymv2))
|
181
|
-
- correct any cookbook metadata name issues [\#15](https://github.com/chef-customers/knife-tidy/pull/15) ([jeremymv2](https://github.com/jeremymv2))
|
182
|
-
|
183
|
-
## [0.2.3](https://github.com/chef-customers/knife-tidy/tree/0.2.3) (2017-09-11)
|
184
|
-
[Full Changelog](https://github.com/chef-customers/knife-tidy/compare/0.2.2...0.2.3)
|
185
|
-
|
186
|
-
**Merged pull requests:**
|
187
|
-
|
188
|
-
- setting required ruby to \>= 2.0.0 [\#14](https://github.com/chef-customers/knife-tidy/pull/14) ([jeremymv2](https://github.com/jeremymv2))
|
189
|
-
|
190
|
-
## [0.2.2](https://github.com/chef-customers/knife-tidy/tree/0.2.2) (2017-09-11)
|
191
|
-
[Full Changelog](https://github.com/chef-customers/knife-tidy/compare/0.2.1...0.2.2)
|
192
|
-
|
193
|
-
**Merged pull requests:**
|
194
|
-
|
195
|
-
- Jeremymv2/fix to i [\#13](https://github.com/chef-customers/knife-tidy/pull/13) ([jeremymv2](https://github.com/jeremymv2))
|
196
|
-
- release 0.2.1 [\#11](https://github.com/chef-customers/knife-tidy/pull/11) ([jeremymv2](https://github.com/jeremymv2))
|
197
|
-
|
198
|
-
## [0.2.1](https://github.com/chef-customers/knife-tidy/tree/0.2.1) (2017-09-01)
|
199
|
-
[Full Changelog](https://github.com/chef-customers/knife-tidy/compare/0.2.0...0.2.1)
|
200
|
-
|
201
|
-
**Merged pull requests:**
|
202
|
-
|
203
|
-
- first round of tests [\#10](https://github.com/chef-customers/knife-tidy/pull/10) ([jeremymv2](https://github.com/jeremymv2))
|
204
|
-
- Add environment checking for unused cookbook list [\#9](https://github.com/chef-customers/knife-tidy/pull/9) ([nsdavidson](https://github.com/nsdavidson))
|
205
|
-
- disable [\#8](https://github.com/chef-customers/knife-tidy/pull/8) ([jeremymv2](https://github.com/jeremymv2))
|
206
|
-
- server object deletion [\#7](https://github.com/chef-customers/knife-tidy/pull/7) ([jeremymv2](https://github.com/jeremymv2))
|
207
|
-
- bump version to 0.2.0 [\#6](https://github.com/chef-customers/knife-tidy/pull/6) ([jeremymv2](https://github.com/jeremymv2))
|
208
|
-
|
209
|
-
## [0.2.0](https://github.com/chef-customers/knife-tidy/tree/0.2.0) (2017-08-16)
|
210
|
-
[Full Changelog](https://github.com/chef-customers/knife-tidy/compare/0.1.1...0.2.0)
|
16
|
+
- the backup-path should default to current working directory [\#79](https://github.com/chef-customers/knife-tidy/issues/79)
|
211
17
|
|
212
18
|
**Merged pull requests:**
|
213
19
|
|
214
|
-
-
|
215
|
-
- Jeremymv2/acl items [\#4](https://github.com/chef-customers/knife-tidy/pull/4) ([jeremymv2](https://github.com/jeremymv2))
|
216
|
-
- updated changelog [\#3](https://github.com/chef-customers/knife-tidy/pull/3) ([jeremymv2](https://github.com/jeremymv2))
|
217
|
-
- bump version to 0.1.1 [\#2](https://github.com/chef-customers/knife-tidy/pull/2) ([jeremymv2](https://github.com/jeremymv2))
|
20
|
+
- Jjh/fix notification reports [\#80](https://github.com/chef-customers/knife-tidy/pull/80) ([itmustbejj](https://github.com/itmustbejj))
|
218
21
|
|
219
22
|
|
220
23
|
|
data/Rakefile
CHANGED
@@ -48,8 +48,8 @@ namespace :changelog do
|
|
48
48
|
require 'github_changelog_generator/task'
|
49
49
|
|
50
50
|
GitHubChangelogGenerator::RakeTask.new :changelog do |config|
|
51
|
-
config.since_tag = '0.1
|
52
|
-
config.future_release = '
|
51
|
+
config.since_tag = '1.0.1'
|
52
|
+
config.future_release = '1.1.0'
|
53
53
|
end
|
54
54
|
end
|
55
55
|
end
|
@@ -3,7 +3,6 @@ require 'chef/knife/tidy_base'
|
|
3
3
|
class Chef
|
4
4
|
class Knife
|
5
5
|
class TidyBackupClean < Knife
|
6
|
-
|
7
6
|
deps do
|
8
7
|
require 'chef/cookbook_loader'
|
9
8
|
require 'chef/cookbook/metadata'
|
@@ -16,21 +15,21 @@ class Chef
|
|
16
15
|
require 'securerandom'
|
17
16
|
end
|
18
17
|
|
19
|
-
banner
|
18
|
+
banner 'knife tidy backup clean (options)'
|
20
19
|
|
21
20
|
include Knife::TidyBase
|
22
21
|
|
23
22
|
option :backup_path,
|
24
|
-
:
|
25
|
-
:
|
23
|
+
long: '--backup-path path/to/backup',
|
24
|
+
description: 'The path to the knife-ec-backup backup directory'
|
26
25
|
|
27
26
|
option :gsub_file,
|
28
|
-
:
|
29
|
-
:
|
27
|
+
long: '--gsub-file path/to/gsub/file',
|
28
|
+
description: 'The path to the file used for substitutions. If non-existant, a boiler plate one will be created.'
|
30
29
|
|
31
30
|
option :gen_gsub,
|
32
|
-
:
|
33
|
-
:
|
31
|
+
long: '--gen-gsub',
|
32
|
+
description: 'Generate a new boiler plate global substitutions file: \'substitutions.json\'.'
|
34
33
|
|
35
34
|
def run
|
36
35
|
FileUtils.rm_f(action_needed_file_path)
|
@@ -76,7 +75,7 @@ class Chef
|
|
76
75
|
email = ''
|
77
76
|
ui.stdout.puts "INFO: Validating #{user}"
|
78
77
|
the_user = FFI_Yajl::Parser.parse(::File.read(::File.join(tidy.users_path, "#{user}.json")), symbolize_names: false)
|
79
|
-
if the_user.
|
78
|
+
if the_user.key?('email') && the_user['email'].match(/\A[^@\s]+@[^@\s]+\z/)
|
80
79
|
if emails_seen.include?(the_user['email'])
|
81
80
|
ui.stdout.puts "REPAIRING: Already saw #{user}'s email, creating a unique one."
|
82
81
|
email = tidy.unique_email
|
@@ -105,12 +104,12 @@ class Chef
|
|
105
104
|
ui.stdout.puts "INFO: Validating org object for #{org}"
|
106
105
|
org_object = load_org_object(org)
|
107
106
|
|
108
|
-
unless org_object.keys.count == 3
|
107
|
+
unless org_object.keys.count == 3 # cheapo, maybe expect the exact names?
|
109
108
|
ui.stdout.puts "REPAIRING: org object for #{org} contains extra/missing fields. Fixing that for you"
|
110
109
|
# quick/dirty attempt at fixing any of the required fields in case they're nil
|
111
110
|
good_name = org_object['name'] || org
|
112
111
|
good_full_name = org_object['full_name'] || org
|
113
|
-
good_guid = org_object['guid'] || SecureRandom.uuid.
|
112
|
+
good_guid = org_object['guid'] || SecureRandom.uuid.delete('-')
|
114
113
|
fixed_org_object = { name: good_name, full_name: good_full_name, guid: good_guid }
|
115
114
|
|
116
115
|
write_org_object(org, fixed_org_object)
|
@@ -121,11 +120,11 @@ class Chef
|
|
121
120
|
JSON.parse(File.read(File.join(tidy.org_path(org), 'org.json')))
|
122
121
|
rescue Errno::ENOENT, JSON::ParserError
|
123
122
|
ui.stdout.puts "REPAIRING: org object for organization #{org} is missing or corrupt. Generating a new one"
|
124
|
-
return { name: org, full_name: org, guid: SecureRandom.uuid.
|
123
|
+
return { name: org, full_name: org, guid: SecureRandom.uuid.delete('-') }
|
125
124
|
end
|
126
125
|
|
127
126
|
def write_org_object(org, org_object)
|
128
|
-
File.write(File.join(tidy.org_path(org), 'org.json')
|
127
|
+
File.write(File.join(tidy.org_path(org), 'org.json'), JSON.pretty_generate(org_object))
|
129
128
|
end
|
130
129
|
|
131
130
|
def add_cookbook_name_to_metadata(cookbook_name, rb_path)
|
@@ -179,7 +178,7 @@ class Chef
|
|
179
178
|
broken_path = ::File.join(tidy.org_path(org), 'cookbooks.broken')
|
180
179
|
FileUtils.mkdir(broken_path) unless ::File.directory?(broken_path)
|
181
180
|
Dir[::File.join(tidy.cookbooks_path(org), "#{cookbook}*")].each do |cb|
|
182
|
-
FileUtils.mv(cb, broken_path, :
|
181
|
+
FileUtils.mv(cb, broken_path, verbose: true, force: true)
|
183
182
|
end
|
184
183
|
end
|
185
184
|
|
@@ -198,12 +197,12 @@ class Chef
|
|
198
197
|
patterns = [
|
199
198
|
{
|
200
199
|
search: '^require .*/lib/chef/sugar/version',
|
201
|
-
replace: "# require File.expand_path('../lib/chef/sugar/version', *__FILE__)"
|
200
|
+
replace: "# require File.expand_path('../lib/chef/sugar/version', *__FILE__)",
|
202
201
|
},
|
203
202
|
{
|
204
203
|
search: '^version *Chef::Sugar::VERSION',
|
205
|
-
replace: "version '#{version}'"
|
206
|
-
}
|
204
|
+
replace: "version '#{version}'",
|
205
|
+
},
|
207
206
|
]
|
208
207
|
patterns.each do |p|
|
209
208
|
s.sub_in_file(file, Regexp.new(p[:search]), p[:replace])
|
@@ -236,11 +235,11 @@ class Chef
|
|
236
235
|
md[key] = 'default value'
|
237
236
|
end
|
238
237
|
end
|
239
|
-
if metadata.
|
238
|
+
if metadata.key?('platforms')
|
240
239
|
metadata['platforms'].each_pair do |key, value|
|
241
240
|
# platform key cannot contain comma delimited values
|
242
241
|
md['platforms'].delete(key) if key =~ /,/
|
243
|
-
if value.
|
242
|
+
if value.is_a?(Array) && value.empty?
|
244
243
|
ui.stdout.puts "REPAIRING: Fixing empty platform key for for key #{key} in #{json_path}"
|
245
244
|
md['platforms'][key] = '>= 0.0.0'
|
246
245
|
end
|
@@ -280,7 +279,7 @@ class Chef
|
|
280
279
|
def create_minimal_metadata(cookbook_path)
|
281
280
|
name = tidy.cookbook_name_from_path(cookbook_path)
|
282
281
|
components = cookbook_path.split(File::SEPARATOR)
|
283
|
-
name_version = components[components.index('cookbooks')+1]
|
282
|
+
name_version = components[components.index('cookbooks') + 1]
|
284
283
|
version = name_version.match(/\d+\.\d+\.\d+/).to_s
|
285
284
|
metadata = {}
|
286
285
|
metadata['name'] = name
|
@@ -352,7 +351,6 @@ class Chef
|
|
352
351
|
end
|
353
352
|
|
354
353
|
def repair_role_run_lists(role_path)
|
355
|
-
# rubocop:disable MethodLength
|
356
354
|
the_role = FFI_Yajl::Parser.parse(::File.read(role_path), symbolize_names: false)
|
357
355
|
new_role = the_role.clone
|
358
356
|
rl = Chef::RunList.new
|
@@ -365,7 +363,7 @@ class Chef
|
|
365
363
|
ui.stdout.puts "REPAIRING: Invalid Recipe Item: #{item} in run_list from #{role_path}"
|
366
364
|
end
|
367
365
|
end
|
368
|
-
if the_role.
|
366
|
+
if the_role.key?('env_run_lists')
|
369
367
|
the_role['env_run_lists'].each_pair do |key, value|
|
370
368
|
new_role['env_run_lists'][key] = []
|
371
369
|
value.each do |item|
|
data/lib/chef/knife/tidy_base.rb
CHANGED
@@ -21,24 +21,22 @@ require 'chef/server_api'
|
|
21
21
|
class Chef
|
22
22
|
class Knife
|
23
23
|
module TidyBase
|
24
|
-
|
25
24
|
def self.included(includer)
|
26
25
|
includer.class_eval do
|
27
|
-
|
28
26
|
deps do
|
29
27
|
require 'chef/tidy_server'
|
30
28
|
require 'chef/tidy_common'
|
31
29
|
end
|
32
30
|
|
33
31
|
option :org_list,
|
34
|
-
:
|
35
|
-
:
|
36
|
-
|
32
|
+
long: '--orgs ORG1,ORG2',
|
33
|
+
description: 'Only apply to objects in the named organizations'
|
34
|
+
end
|
37
35
|
end
|
38
36
|
|
39
37
|
def server
|
40
38
|
@server ||= if Chef::Config.chef_server_root.nil?
|
41
|
-
ui.warn(
|
39
|
+
ui.warn('chef_server_root not found in knife configuration; using chef_server_url')
|
42
40
|
Chef::TidyServer.from_chef_server_url(Chef::Config.chef_server_url)
|
43
41
|
else
|
44
42
|
Chef::TidyServer.new(Chef::Config.chef_server_root)
|
@@ -58,7 +56,7 @@ class Chef
|
|
58
56
|
end
|
59
57
|
|
60
58
|
def completion_message
|
61
|
-
ui.stdout.puts
|
59
|
+
ui.stdout.puts ui.color('** Finished **', :magenta).to_s
|
62
60
|
end
|
63
61
|
|
64
62
|
def action_needed_file_path
|
@@ -69,7 +67,7 @@ class Chef
|
|
69
67
|
::File.expand_path('reports/knife-tidy-server-warnings.txt')
|
70
68
|
end
|
71
69
|
|
72
|
-
def action_needed(msg, file_path=action_needed_file_path)
|
70
|
+
def action_needed(msg, file_path = action_needed_file_path)
|
73
71
|
::File.open(file_path, 'a') do |f|
|
74
72
|
f.write(msg + "\n")
|
75
73
|
end
|
@@ -3,68 +3,68 @@ require 'chef/knife/tidy_base'
|
|
3
3
|
class Chef
|
4
4
|
class Knife
|
5
5
|
class TidyNotify < Knife
|
6
|
-
|
7
6
|
deps do
|
8
7
|
require 'ffi_yajl'
|
9
8
|
require 'net/smtp'
|
10
9
|
end
|
11
10
|
|
12
|
-
banner
|
11
|
+
banner 'knife tidy notify (options)'
|
13
12
|
|
14
13
|
option :smtp_server,
|
15
|
-
:
|
16
|
-
:
|
17
|
-
:
|
18
|
-
:
|
14
|
+
short: '-s SERVER_NAME',
|
15
|
+
long: '--smtp_server SERVER_NAME',
|
16
|
+
default: 'localhost',
|
17
|
+
description: 'SMTP Server to be used for emailling reports to organization admins (defaults to localhost)'
|
19
18
|
|
20
19
|
option :smtp_port,
|
21
|
-
:
|
22
|
-
:
|
23
|
-
:
|
24
|
-
:
|
20
|
+
short: '-p SMTP_PORT',
|
21
|
+
long: '--smtp_port SMTP_PORT',
|
22
|
+
default: 25,
|
23
|
+
description: 'SMTP port to be used for emailling reports to organization admins (defaults to 25)'
|
25
24
|
|
26
25
|
option :smtp_helo,
|
27
|
-
:
|
28
|
-
:
|
29
|
-
:
|
30
|
-
:
|
26
|
+
short: '-h SMTP_HELO',
|
27
|
+
long: '--smtp_helo SMTP_HELO',
|
28
|
+
default: 'localhost',
|
29
|
+
description: 'SMTP HELO to be used for emailling reports to organization admins (defaults to localhost)'
|
31
30
|
|
32
31
|
option :smtp_username,
|
33
|
-
:
|
34
|
-
:
|
35
|
-
:
|
32
|
+
short: '-u SMTP_USERNAME',
|
33
|
+
long: '--smtp_username SMTP_USERNAME',
|
34
|
+
description: 'SMTP Username to be used for emailling reports to organization admins'
|
36
35
|
|
37
36
|
option :smtp_password,
|
38
|
-
:
|
39
|
-
:
|
37
|
+
long: '--smtp_password SMTP_PASSWORD',
|
38
|
+
description: 'SMTP Password to be used for emailling reports to organization admins'
|
40
39
|
|
41
40
|
option :smtp_from,
|
42
|
-
:
|
43
|
-
:
|
41
|
+
long: '--smtp_from SMTP_FROM',
|
42
|
+
description: 'SMTP From address to be used for emailling reports to organization admins'
|
44
43
|
|
45
44
|
option :smtp_use_tls,
|
46
|
-
:
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
45
|
+
long: '--smtp_use_tls',
|
46
|
+
short: '-t',
|
47
|
+
default: false,
|
48
|
+
boolean: true | false,
|
49
|
+
description: 'Whether TLS should be used for emailling reports to organization admins (defaults to false if omitted)'
|
52
50
|
|
53
51
|
include Knife::TidyBase
|
54
52
|
|
55
53
|
def run
|
56
|
-
|
57
54
|
reports_dir = tidy.reports_dir
|
58
|
-
|
59
|
-
|
60
|
-
|
55
|
+
report_file_suffixes = ['_unused_cookbooks.json', '_cookbook_count.json', '_stale_nodes.json']
|
56
|
+
# Only grab the files matching the report_file_suffixes
|
57
|
+
report_files = Dir["#{reports_dir}/*{#{report_file_suffixes.join(',')}}"]
|
61
58
|
|
62
59
|
ui.info "Reading from #{tidy.reports_dir} directory"
|
63
60
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
61
|
+
# Fetch list of organization names from reports directory
|
62
|
+
begin
|
63
|
+
org_names = report_files.map { |r_file| r_file.match("#{reports_dir}\/(.*)(#{report_file_suffixes.join('|')})").captures.first }.uniq
|
64
|
+
rescue NoMethodError
|
65
|
+
ui.stderr.puts 'Failed to parse json reports files. Please ensure your reports are valid.'
|
66
|
+
return
|
67
|
+
end
|
68
68
|
if config[:org_list]
|
69
69
|
filter_orgs = config[:org_list].split(',')
|
70
70
|
# Take the intersection of org_names and filter_orgs
|
@@ -73,102 +73,139 @@ class Chef
|
|
73
73
|
|
74
74
|
reports = {}
|
75
75
|
|
76
|
-
# Iterate through list of collected
|
76
|
+
# Iterate through list of collected organizations and parse any report files into JSON objects
|
77
|
+
|
78
|
+
unless org_names
|
79
|
+
ui.std.puts 'No valid org reports found to send notifications. Exiting.'
|
80
|
+
return
|
81
|
+
end
|
77
82
|
|
78
83
|
org_names.each do |org|
|
79
|
-
ui.info("Fetching report data for
|
84
|
+
ui.info("Fetching report data for organization #{org}")
|
80
85
|
reports[org] = {}
|
81
86
|
report_file_suffixes.each do |report|
|
82
87
|
begin
|
83
88
|
file_name = "#{reports_dir}/#{org}#{report}"
|
84
89
|
ui.info(" Parsing file #{file_name}")
|
85
90
|
json_string = File.read(file_name)
|
86
|
-
reports[org][report] = FFI_Yajl::Parser.parse(
|
91
|
+
reports[org][report] = FFI_Yajl::Parser.parse(json_string)
|
87
92
|
rescue Errno::ENOENT
|
88
|
-
ui.info(" Skipping file #{file_name} - not found for
|
93
|
+
ui.info(" Skipping file #{file_name} - not found for organization #{org}")
|
89
94
|
reports[org][report] = {}
|
90
95
|
end
|
91
96
|
end
|
92
97
|
|
93
|
-
# Fetch a list of admin users for the current
|
94
|
-
ui.info("Fetching admins users for
|
98
|
+
# Fetch a list of admin users for the current organization
|
99
|
+
ui.info("Fetching admins users for organization #{org}")
|
95
100
|
begin
|
96
101
|
admins = org_admins(org)
|
97
|
-
reports[org]['admins'] = admins.map{|name,
|
102
|
+
reports[org]['admins'] = admins.map { |name, _data| org_user(org, name) unless name == 'pivotal' }
|
98
103
|
rescue Net::HTTPServerException
|
99
|
-
ui.info(" Cannot fetch admin users for
|
104
|
+
ui.info(" Cannot fetch admin users for organization #{org} as it does not exist on the server")
|
100
105
|
end
|
101
106
|
|
102
107
|
# Build list of email recipients from the collected admin users (display name and email address of each)
|
103
|
-
email_recipients = reports[org]['admins'].map{|admin|{name: admin['display_name'], email: admin['email']} unless admin.nil?}.compact
|
108
|
+
email_recipients = reports[org]['admins'].map { |admin| { name: admin['display_name'], email: admin['email'] } unless admin.nil? }.compact
|
104
109
|
|
105
|
-
# Send a report email to all admin users of the
|
106
|
-
ui.info "Sending email reports for
|
107
|
-
email_content = generate_email(reports,org, email_recipients)
|
108
|
-
send_email(email_content,email_recipients)
|
110
|
+
# Send a report email to all admin users of the organization
|
111
|
+
ui.info "Sending email reports for organization #{org}"
|
112
|
+
email_content = generate_email(reports, org, email_recipients, report_file_suffixes)
|
113
|
+
send_email(email_content, email_recipients)
|
109
114
|
end
|
110
|
-
|
111
|
-
|
112
|
-
|
113
115
|
end
|
114
116
|
|
115
117
|
private
|
116
118
|
|
117
|
-
def generate_email(report_data,
|
119
|
+
def generate_email(report_data, organization, recipients, report_file_suffixes)
|
120
|
+
mime_boundary = "==Multipart_Boundary_x#{srand}x"
|
118
121
|
message = <<MESSAGE_END
|
119
122
|
From: Knife Tidy <#{config[:smtp_from]}>
|
120
|
-
To: #{recipients.map{|recipient|"#{recipient[:name]} <#{recipient[:email]}>"}.join(
|
123
|
+
To: #{recipients.map { |recipient| "#{recipient[:name]} <#{recipient[:email]}>" }.join(', ')}
|
124
|
+
MIME-Version: 1.0
|
125
|
+
Subject: Knife Tidy Cleanup Report for Organization "#{organization}"
|
126
|
+
Content-Type: multipart/mixed; boundary="#{mime_boundary}";
|
127
|
+
--#{mime_boundary}
|
121
128
|
Content-type: text/html
|
122
|
-
|
129
|
+
Content-Transfer-Encoding: 7bit
|
130
|
+
|
131
|
+
The following reports were generated by <a href="https://github.com/chef-customers/knife-tidy">knife-tidy</a>, and contain a list of unused cookbooks and stale nodes for the Chef server organization "#{organization}"
|
132
|
+
#{generate_total_cookbooks_table(report_data, organization)}
|
133
|
+
#{generate_unused_cookbooks_table(report_data, organization)}
|
134
|
+
#{generate_node_table(report_data, organization)}
|
135
|
+
MESSAGE_END
|
136
|
+
|
137
|
+
report_file_suffixes.each do |suffix|
|
138
|
+
message += <<MESSAGE_END
|
139
|
+
--#{mime_boundary}
|
140
|
+
Content-Transfer-Encoding:7bit
|
141
|
+
Content-Type: plain/text;name="#{organization}#{suffix}";charset="UTF-8"
|
142
|
+
Content-Disposition: attachment;filename="#{organization}#{suffix}"
|
143
|
+
|
144
|
+
#{report_data[organization][suffix].to_json}
|
123
145
|
|
124
|
-
The following report was generated by <a href="https://github.com/chef-customers/knife-tidy">knife-tidy</a>, and contains a list of unused cookbooks and stale nodes for the Chef server organisation "#{organisation}"
|
125
|
-
#{generate_cookbook_table(report_data,organisation)}
|
126
|
-
<br>
|
127
|
-
#{generate_node_table(report_data,organisation)}
|
128
146
|
MESSAGE_END
|
147
|
+
end
|
129
148
|
|
149
|
+
message += <<MESSAGE_END
|
150
|
+
--#{mime_boundary}--
|
151
|
+
MESSAGE_END
|
152
|
+
puts message
|
130
153
|
message
|
131
154
|
end
|
132
155
|
|
133
|
-
def
|
156
|
+
def generate_total_cookbooks_table(report_data, organization)
|
157
|
+
table_start = "<h2>Total Versions by Cookbook</h2><p>This table contains the count of versions of each cookbook stored on the Chef Server.<p><table border='1' cellpadding='1' cellspacing='0'>"
|
158
|
+
table_end = '</table><br/>'
|
159
|
+
header_string = '<tr><th>Cookbook Name</th><th>Total Version Count</th></tr>'
|
160
|
+
table_body = if report_data[organization]['_cookbook_count.json'].empty?
|
161
|
+
"<tr><td colspan='2'>No cookbook versions</td></tr>"
|
162
|
+
else
|
163
|
+
report_data[organization]['_cookbook_count.json'].map { |cookbook_name, cookbook_count| "<tr><td>#{cookbook_name}</td><td>#{cookbook_count}</td></tr>" }.join("\n")
|
164
|
+
end
|
165
|
+
table_start + header_string + table_body + table_end
|
166
|
+
end
|
134
167
|
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
168
|
+
def generate_unused_cookbooks_table(report_data, organization)
|
169
|
+
table_start = "<h2>Unused Cookbooks</h2><p>This table contains cookbook names and the count of their versions that are not currently in the runlists of any nodes.<p><table border='1' cellpadding='1' cellspacing='0'>"
|
170
|
+
table_end = '</table><br/>'
|
171
|
+
header_string = '<tr><th>Cookbook Name</th><th>Unused Versions</th></tr>'
|
172
|
+
table_body = if report_data[organization]['_unused_cookbooks.json'].empty?
|
173
|
+
"<tr><td colspan='2'>No unused cookbook versions</td></tr>"
|
174
|
+
else
|
175
|
+
report_data[organization]['_unused_cookbooks.json'].map { |cookbook_name, cookbook_versions| "<tr><td>#{cookbook_name}</td><td>#{cookbook_versions.join('<br>')}</td></tr>" }.join("\n")
|
176
|
+
end
|
144
177
|
table_start + header_string + table_body + table_end
|
145
178
|
end
|
146
179
|
|
147
|
-
def generate_node_table(report_data,
|
148
|
-
table_start = "<h2>Stale Nodes</h2><p>This table contains nodes that have not checked in to the Chef Server in #{report_data[
|
149
|
-
table_end =
|
150
|
-
header_string =
|
151
|
-
table_body = report_data[
|
180
|
+
def generate_node_table(report_data, organization)
|
181
|
+
table_start = "<h2>Stale Nodes</h2><p>This table contains nodes that have not checked in to the Chef Server in #{report_data[organization]['_stale_nodes.json']['threshold_days']} days.<p><table border='1' cellpadding='1' cellspacing='0'>"
|
182
|
+
table_end = '</table>'
|
183
|
+
header_string = '<tr><th>Node Name</th></tr>'
|
184
|
+
table_body = if report_data[organization]['_stale_nodes.json'].empty? || report_data[organization]['_stale_nodes.json']['count'] == 0
|
185
|
+
"<tr><td colspan='2'>No stale nodes</td></tr>"
|
186
|
+
else
|
187
|
+
report_data[organization]['_stale_nodes.json']['list'].map { |node_name| "<tr><td>#{node_name}</td></tr>" }.join("\n")
|
188
|
+
end
|
152
189
|
table_start + header_string + table_body + table_end
|
153
190
|
end
|
154
191
|
|
155
|
-
def send_email(mail_content,recipients)
|
156
|
-
smtp = Net::SMTP.new(config[:smtp_server],config[:smtp_port])
|
192
|
+
def send_email(mail_content, recipients)
|
193
|
+
smtp = Net::SMTP.new(config[:smtp_server], config[:smtp_port])
|
157
194
|
smtp.enable_starttls if config[:smtp_use_tls]
|
158
|
-
smtp.start(config[:smtp_helo],config[:smtp_username],config[:smtp_password]
|
159
|
-
server.send_message(mail_content, config[:smtp_from], recipients.map{|recipient|recipient[:email]})
|
195
|
+
smtp.start(config[:smtp_helo], config[:smtp_username], config[:smtp_password], :login) do |server|
|
196
|
+
server.send_message(mail_content, config[:smtp_from], recipients.map { |recipient| recipient[:email] })
|
160
197
|
end
|
161
198
|
end
|
162
199
|
|
163
200
|
def org_admins(org)
|
164
201
|
admins = {}
|
165
|
-
rest.get("/organizations/#{org}/groups/admins")[
|
202
|
+
rest.get("/organizations/#{org}/groups/admins")['users'].each do |name|
|
166
203
|
admins[name] = {}
|
167
204
|
end
|
168
205
|
admins
|
169
206
|
end
|
170
207
|
|
171
|
-
def org_user(org,username)
|
208
|
+
def org_user(org, username)
|
172
209
|
rest.get("/organizations/#{org}/users/#{username}")
|
173
210
|
end
|
174
211
|
end
|
@@ -10,28 +10,28 @@ class Chef
|
|
10
10
|
require 'chef/util/threaded_job_queue'
|
11
11
|
end
|
12
12
|
|
13
|
-
banner
|
13
|
+
banner 'knife tidy server clean (options)'
|
14
14
|
|
15
15
|
option :backup_path,
|
16
|
-
:
|
17
|
-
:
|
16
|
+
long: '--backup-path path/to/backup',
|
17
|
+
description: 'The path to the knife-ec-backup backup directory'
|
18
18
|
|
19
19
|
option :concurrency,
|
20
|
-
:
|
21
|
-
:
|
22
|
-
:
|
20
|
+
long: '--concurrency THREADS',
|
21
|
+
default: 1,
|
22
|
+
description: 'Maximum number of simultaneous requests to send (default: 1)'
|
23
23
|
|
24
24
|
option :only_cookbooks,
|
25
|
-
:
|
26
|
-
:
|
25
|
+
long: '--only-cookbooks',
|
26
|
+
description: 'Only delete unused cookbooks from Chef Server.'
|
27
27
|
|
28
28
|
option :only_nodes,
|
29
|
-
:
|
30
|
-
:
|
29
|
+
long: '--only-nodes',
|
30
|
+
description: 'Only delete stale nodes (and associated clients and ACLs) from Chef Server.'
|
31
31
|
|
32
32
|
option :dry_run,
|
33
|
-
:
|
34
|
-
:
|
33
|
+
long: '--dry-run',
|
34
|
+
description: 'Do not perform any actual deletion, only report on what would have been deleted.'
|
35
35
|
|
36
36
|
def run
|
37
37
|
STDOUT.sync = true
|
@@ -56,11 +56,11 @@ class Chef
|
|
56
56
|
end
|
57
57
|
|
58
58
|
deletions = if config[:only_cookbooks]
|
59
|
-
|
59
|
+
'cookbooks'
|
60
60
|
elsif config[:only_nodes]
|
61
|
-
|
61
|
+
'nodes (and associated clients and ACLs)'
|
62
62
|
else
|
63
|
-
|
63
|
+
'cookbooks and nodes (and associated clients and ACLs)'
|
64
64
|
end
|
65
65
|
|
66
66
|
orgs = if config[:org_list]
|
@@ -94,7 +94,7 @@ class Chef
|
|
94
94
|
unused_cookbooks.keys.each do |cookbook|
|
95
95
|
versions = unused_cookbooks[cookbook]
|
96
96
|
versions.each do |version|
|
97
|
-
queue <<
|
97
|
+
queue << -> { delete_cookbook_job(org, cookbook, version) }
|
98
98
|
end
|
99
99
|
end
|
100
100
|
queue.process(config[:concurrency].to_i)
|
@@ -118,7 +118,7 @@ class Chef
|
|
118
118
|
ui.stdout.puts "INFO: Cleaning stale nodes for Org: #{org}, using #{stale_nodes_file}"
|
119
119
|
stale_nodes = FFI_Yajl::Parser.parse(::File.read(stale_nodes_file), symbolize_names: true)
|
120
120
|
stale_nodes[:list].each do |node|
|
121
|
-
queue <<
|
121
|
+
queue << -> { delete_node_job(org, node) }
|
122
122
|
end
|
123
123
|
queue.process(config[:concurrency].to_i)
|
124
124
|
end
|
@@ -68,8 +68,8 @@ class Chef
|
|
68
68
|
nodes.select{|node| !node['cookbooks'].nil?}.each do |node|
|
69
69
|
node['cookbooks'].each do |name, version_hash|
|
70
70
|
version = Gem::Version.new(version_hash['version']).to_s
|
71
|
-
if used_cookbooks[name]
|
72
|
-
used_cookbooks[name].push(version)
|
71
|
+
if used_cookbooks[name]
|
72
|
+
used_cookbooks[name].push(version) unless used_cookbooks[name].include?(version)
|
73
73
|
else
|
74
74
|
used_cookbooks[name] = [version]
|
75
75
|
end
|
@@ -168,7 +168,8 @@ class Chef
|
|
168
168
|
if used_list[name].nil? # Not in the used list at all (Remove all versions)
|
169
169
|
unused_list[name] = versions
|
170
170
|
elsif used_list[name].sort != versions # Is in the used cookbook list, but version arrays do not match (Find unused versions)
|
171
|
-
|
171
|
+
unused = versions - used_list[name] - [versions.last] # Don't delete the most recent version as it might not be in a run_list yet.
|
172
|
+
unused_list[name] = unused unless unused.empty?
|
172
173
|
end
|
173
174
|
end
|
174
175
|
unused_list
|
data/lib/chef/tidy_acls.rb
CHANGED
@@ -18,7 +18,7 @@ class Chef
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def load_users
|
21
|
-
@tidy.ui.stdout.puts
|
21
|
+
@tidy.ui.stdout.puts 'INFO: Loading users'
|
22
22
|
Dir[::File.join(@tidy.users_path, '*.json')].each do |user|
|
23
23
|
@users.push(FFI_Yajl::Parser.parse(::File.read(user), symbolize_names: true))
|
24
24
|
end
|
@@ -70,15 +70,15 @@ class Chef
|
|
70
70
|
end
|
71
71
|
|
72
72
|
def valid_org_member?(actor)
|
73
|
-
|
73
|
+
!@members.select { |user| user[:user][:username] == actor }.empty?
|
74
74
|
end
|
75
75
|
|
76
76
|
def valid_org_client?(actor)
|
77
|
-
|
77
|
+
!@clients.select { |client| client[:name] == actor }.empty?
|
78
78
|
end
|
79
79
|
|
80
80
|
def valid_global_user?(actor)
|
81
|
-
|
81
|
+
!@users.select { |user| user[:username] == actor }.empty?
|
82
82
|
end
|
83
83
|
|
84
84
|
def invalid_group?(actor)
|
@@ -101,7 +101,7 @@ class Chef
|
|
101
101
|
|
102
102
|
def org_acls
|
103
103
|
@org_acls ||= Dir[::File.join(@tidy.org_acls_path(@org), '**.json')] +
|
104
|
-
|
104
|
+
Dir[::File.join(@tidy.org_acls_path(@org), '**', '*.json')]
|
105
105
|
end
|
106
106
|
|
107
107
|
def fix_ambiguous_actor(actor)
|
@@ -153,7 +153,7 @@ class Chef
|
|
153
153
|
|
154
154
|
def ensure_client_read_acls(acl_file)
|
155
155
|
acl = FFI_Yajl::Parser.parse(::File.read(acl_file), symbolize_names: false)
|
156
|
-
%w(users admins).each do |
|
156
|
+
%w(users admins).each do |group|
|
157
157
|
unless acl['read']['groups'].include? group
|
158
158
|
@tidy.ui.stdout.puts "REPAIRING: Adding read acl for #{group} in #{acl_file}"
|
159
159
|
acl['read']['groups'].push(group)
|
@@ -177,27 +177,25 @@ class Chef
|
|
177
177
|
end
|
178
178
|
end
|
179
179
|
actors_groups[:groups].each do |group|
|
180
|
-
if invalid_group?(group)
|
181
|
-
remove_group_from_acl(group, acl_file)
|
182
|
-
end
|
180
|
+
remove_group_from_acl(group, acl_file) if invalid_group?(group)
|
183
181
|
end
|
184
182
|
end
|
185
183
|
end
|
186
184
|
|
187
185
|
def default_user_acl(client)
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
186
|
+
{ create: { actors: ['pivotal', client], groups: ['::server-admins'] },
|
187
|
+
read: { actors: ['pivotal', client], groups: ['::server-admins', "::#{@org}_read_access_group"] },
|
188
|
+
update: { actors: ['pivotal', client], groups: ['::server-admins'] },
|
189
|
+
delete: { actors: ['pivotal', client], groups: ['::server-admins'] },
|
190
|
+
grant: { actors: ['pivotal', client], groups: ['::server-admins'] } }
|
193
191
|
end
|
194
192
|
|
195
193
|
def default_client_acl(client_name)
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
194
|
+
{ create: { actors: ['pivotal', "#{@org}-validator", client_name], groups: ['admins'] },
|
195
|
+
read: { actors: ['pivotal', "#{@org}-validator", client_name], groups: %w(admins users) },
|
196
|
+
update: { actors: ['pivotal', client_name], groups: ['admins'] },
|
197
|
+
delete: { actors: ['pivotal', client_name], groups: %w(admins users) },
|
198
|
+
grant: { actors: ['pivotal', client_name], groups: ['admins'] } }
|
201
199
|
end
|
202
200
|
|
203
201
|
def validate_user_acls
|
@@ -207,15 +205,13 @@ class Chef
|
|
207
205
|
user_acl = FFI_Yajl::Parser.parse(::File.read(user_acl_path), symbolize_names: false)
|
208
206
|
rescue Errno::ENOENT
|
209
207
|
@tidy.ui.stdout.puts "REPAIRING: Replacing missing user acl for #{member[:user][:username]}."
|
210
|
-
@tidy.write_new_file(default_user_acl(member), user_acl_path, backup=false)
|
208
|
+
@tidy.write_new_file(default_user_acl(member), user_acl_path, backup = false)
|
211
209
|
user_acl = FFI_Yajl::Parser.parse(::File.read(user_acl_path), symbolize_names: false)
|
212
210
|
end
|
213
211
|
ensure_global_group_acls(user_acl_path)
|
214
212
|
actors_groups = acl_actors_groups(user_acl)
|
215
213
|
actors_groups[:groups].each do |group|
|
216
|
-
if invalid_group?(group)
|
217
|
-
remove_group_from_acl(group, user_acl_path)
|
218
|
-
end
|
214
|
+
remove_group_from_acl(group, user_acl_path) if invalid_group?(group)
|
219
215
|
end
|
220
216
|
end
|
221
217
|
end
|
@@ -227,7 +223,7 @@ class Chef
|
|
227
223
|
client_acl = FFI_Yajl::Parser.parse(::File.read(client_acl_path), symbolize_names: false)
|
228
224
|
rescue Errno::ENOENT
|
229
225
|
@tidy.ui.stdout.puts "REPAIRING: Replacing missing client acl for #{client[:name]} in #{client_acl_path}."
|
230
|
-
@tidy.write_new_file(default_client_acl(client[:name]), client_acl_path, backup=false)
|
226
|
+
@tidy.write_new_file(default_client_acl(client[:name]), client_acl_path, backup = false)
|
231
227
|
client_acl = FFI_Yajl::Parser.parse(::File.read(client_acl_path), symbolize_names: false)
|
232
228
|
end
|
233
229
|
ensure_client_read_acls(client_acl_path)
|
data/lib/chef/tidy_common.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'ffi_yajl'
|
2
2
|
require 'fileutils'
|
3
|
-
require
|
3
|
+
require 'chef/knife/core/ui'
|
4
4
|
|
5
5
|
class Chef
|
6
6
|
class TidyCommon
|
@@ -67,12 +67,12 @@ class Chef
|
|
67
67
|
end
|
68
68
|
end
|
69
69
|
|
70
|
-
def write_new_file(contents, path, backup=true)
|
70
|
+
def write_new_file(contents, path, backup = true)
|
71
71
|
if ::File.exist?(path) && backup
|
72
72
|
FileUtils.cp(path, "#{path}.orig") unless ::File.exist?("#{path}.orig")
|
73
73
|
end
|
74
74
|
::File.open(path, 'w+') do |f|
|
75
|
-
|
75
|
+
f.write(FFI_Yajl::Encoder.encode(contents, pretty: true))
|
76
76
|
end
|
77
77
|
end
|
78
78
|
|
@@ -30,12 +30,11 @@ class Chef
|
|
30
30
|
|
31
31
|
def cookbook_version_from_path(path)
|
32
32
|
components = path.split(File::SEPARATOR)
|
33
|
-
name_version = components[components.index('cookbooks')+1]
|
33
|
+
name_version = components[components.index('cookbooks') + 1]
|
34
34
|
name_version.match(/\d+\.\d+\.\d+/).to_s
|
35
35
|
end
|
36
36
|
|
37
37
|
def revert
|
38
|
-
|
39
38
|
end
|
40
39
|
|
41
40
|
def sub_in_file(path, search, replace)
|
@@ -69,7 +68,7 @@ class Chef
|
|
69
68
|
@data[entry][glob].each do |substitution|
|
70
69
|
search = Regexp.new(substitution['pattern'])
|
71
70
|
replace = substitution['replace'].dup
|
72
|
-
replace.gsub!(/\!COOKBOOK_VERSION\!/) { |
|
71
|
+
replace.gsub!(/\!COOKBOOK_VERSION\!/) { |_m| "'" + cookbook_version_from_path(file) + "'" }
|
73
72
|
sub_in_file(file, search, replace)
|
74
73
|
end
|
75
74
|
end
|
data/lib/knife-tidy/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: knife-tidy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeremy Miller
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-01-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -145,7 +145,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
145
145
|
version: '0'
|
146
146
|
requirements: []
|
147
147
|
rubyforge_project:
|
148
|
-
rubygems_version: 2.
|
148
|
+
rubygems_version: 2.7.3
|
149
149
|
signing_key:
|
150
150
|
specification_version: 4
|
151
151
|
summary: Report on stale Chef Server nodes and cookbooks and clean up data integrity
|