knife-tidy 1.0.1 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|