puppet-classroom-manager 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +201 -0
- data/README.md +52 -0
- data/bin/classroom +115 -0
- data/lib/classroom/help.rb +59 -0
- data/lib/classroom/page.rb +41 -0
- data/lib/classroom/performance.rb +41 -0
- data/lib/classroom/reset.rb +121 -0
- data/lib/classroom/restart.rb +91 -0
- data/lib/classroom/sanitize.rb +76 -0
- data/lib/classroom/submit.rb +72 -0
- data/lib/classroom/troubleshoot.rb +178 -0
- data/lib/classroom/validate.rb +17 -0
- data/lib/classroom/version.rb +3 -0
- data/lib/classroom.rb +54 -0
- metadata +134 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 91bd91d0dc4b47cffaf1dcc62cb23f167e9ac4e5
|
4
|
+
data.tar.gz: 1f74d7f92c3b89f52528cbdf1771749d512508f9
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c2a71798353538217e3e563360204406b0004ddb540969c80a2f56e0701afcec7506eeb8c18ce6cd50a819695289d4cd25ef161bad623f4949bf274c500c55c4
|
7
|
+
data.tar.gz: c2d572e1ac680bf66210f9e9b210bee4c372e66fff808c54f91c6058d73b45367e314b8f3b3c9cc40af4984f3404162a696ef2a122744dfda3062c19fa2f47bd
|
data/LICENSE
ADDED
@@ -0,0 +1,201 @@
|
|
1
|
+
Apache License
|
2
|
+
Version 2.0, January 2004
|
3
|
+
http://www.apache.org/licenses/
|
4
|
+
|
5
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
6
|
+
|
7
|
+
1. Definitions.
|
8
|
+
|
9
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
10
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
11
|
+
|
12
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
13
|
+
the copyright owner that is granting the License.
|
14
|
+
|
15
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
16
|
+
other entities that control, are controlled by, or are under common
|
17
|
+
control with that entity. For the purposes of this definition,
|
18
|
+
"control" means (i) the power, direct or indirect, to cause the
|
19
|
+
direction or management of such entity, whether by contract or
|
20
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
21
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
22
|
+
|
23
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
24
|
+
exercising permissions granted by this License.
|
25
|
+
|
26
|
+
"Source" form shall mean the preferred form for making modifications,
|
27
|
+
including but not limited to software source code, documentation
|
28
|
+
source, and configuration files.
|
29
|
+
|
30
|
+
"Object" form shall mean any form resulting from mechanical
|
31
|
+
transformation or translation of a Source form, including but
|
32
|
+
not limited to compiled object code, generated documentation,
|
33
|
+
and conversions to other media types.
|
34
|
+
|
35
|
+
"Work" shall mean the work of authorship, whether in Source or
|
36
|
+
Object form, made available under the License, as indicated by a
|
37
|
+
copyright notice that is included in or attached to the work
|
38
|
+
(an example is provided in the Appendix below).
|
39
|
+
|
40
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
41
|
+
form, that is based on (or derived from) the Work and for which the
|
42
|
+
editorial revisions, annotations, elaborations, or other modifications
|
43
|
+
represent, as a whole, an original work of authorship. For the purposes
|
44
|
+
of this License, Derivative Works shall not include works that remain
|
45
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
46
|
+
the Work and Derivative Works thereof.
|
47
|
+
|
48
|
+
"Contribution" shall mean any work of authorship, including
|
49
|
+
the original version of the Work and any modifications or additions
|
50
|
+
to that Work or Derivative Works thereof, that is intentionally
|
51
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
52
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
53
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
54
|
+
means any form of electronic, verbal, or written communication sent
|
55
|
+
to the Licensor or its representatives, including but not limited to
|
56
|
+
communication on electronic mailing lists, source code control systems,
|
57
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
58
|
+
Licensor for the purpose of discussing and improving the Work, but
|
59
|
+
excluding communication that is conspicuously marked or otherwise
|
60
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
61
|
+
|
62
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
63
|
+
on behalf of whom a Contribution has been received by Licensor and
|
64
|
+
subsequently incorporated within the Work.
|
65
|
+
|
66
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
67
|
+
this License, each Contributor hereby grants to You a perpetual,
|
68
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
69
|
+
copyright license to reproduce, prepare Derivative Works of,
|
70
|
+
publicly display, publicly perform, sublicense, and distribute the
|
71
|
+
Work and such Derivative Works in Source or Object form.
|
72
|
+
|
73
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
74
|
+
this License, each Contributor hereby grants to You a perpetual,
|
75
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
76
|
+
(except as stated in this section) patent license to make, have made,
|
77
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
78
|
+
where such license applies only to those patent claims licensable
|
79
|
+
by such Contributor that are necessarily infringed by their
|
80
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
81
|
+
with the Work to which such Contribution(s) was submitted. If You
|
82
|
+
institute patent litigation against any entity (including a
|
83
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
84
|
+
or a Contribution incorporated within the Work constitutes direct
|
85
|
+
or contributory patent infringement, then any patent licenses
|
86
|
+
granted to You under this License for that Work shall terminate
|
87
|
+
as of the date such litigation is filed.
|
88
|
+
|
89
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
90
|
+
Work or Derivative Works thereof in any medium, with or without
|
91
|
+
modifications, and in Source or Object form, provided that You
|
92
|
+
meet the following conditions:
|
93
|
+
|
94
|
+
(a) You must give any other recipients of the Work or
|
95
|
+
Derivative Works a copy of this License; and
|
96
|
+
|
97
|
+
(b) You must cause any modified files to carry prominent notices
|
98
|
+
stating that You changed the files; and
|
99
|
+
|
100
|
+
(c) You must retain, in the Source form of any Derivative Works
|
101
|
+
that You distribute, all copyright, patent, trademark, and
|
102
|
+
attribution notices from the Source form of the Work,
|
103
|
+
excluding those notices that do not pertain to any part of
|
104
|
+
the Derivative Works; and
|
105
|
+
|
106
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
107
|
+
distribution, then any Derivative Works that You distribute must
|
108
|
+
include a readable copy of the attribution notices contained
|
109
|
+
within such NOTICE file, excluding those notices that do not
|
110
|
+
pertain to any part of the Derivative Works, in at least one
|
111
|
+
of the following places: within a NOTICE text file distributed
|
112
|
+
as part of the Derivative Works; within the Source form or
|
113
|
+
documentation, if provided along with the Derivative Works; or,
|
114
|
+
within a display generated by the Derivative Works, if and
|
115
|
+
wherever such third-party notices normally appear. The contents
|
116
|
+
of the NOTICE file are for informational purposes only and
|
117
|
+
do not modify the License. You may add Your own attribution
|
118
|
+
notices within Derivative Works that You distribute, alongside
|
119
|
+
or as an addendum to the NOTICE text from the Work, provided
|
120
|
+
that such additional attribution notices cannot be construed
|
121
|
+
as modifying the License.
|
122
|
+
|
123
|
+
You may add Your own copyright statement to Your modifications and
|
124
|
+
may provide additional or different license terms and conditions
|
125
|
+
for use, reproduction, or distribution of Your modifications, or
|
126
|
+
for any such Derivative Works as a whole, provided Your use,
|
127
|
+
reproduction, and distribution of the Work otherwise complies with
|
128
|
+
the conditions stated in this License.
|
129
|
+
|
130
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
131
|
+
any Contribution intentionally submitted for inclusion in the Work
|
132
|
+
by You to the Licensor shall be under the terms and conditions of
|
133
|
+
this License, without any additional terms or conditions.
|
134
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
135
|
+
the terms of any separate license agreement you may have executed
|
136
|
+
with Licensor regarding such Contributions.
|
137
|
+
|
138
|
+
6. Trademarks. This License does not grant permission to use the trade
|
139
|
+
names, trademarks, service marks, or product names of the Licensor,
|
140
|
+
except as required for reasonable and customary use in describing the
|
141
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
142
|
+
|
143
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
144
|
+
agreed to in writing, Licensor provides the Work (and each
|
145
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
146
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
147
|
+
implied, including, without limitation, any warranties or conditions
|
148
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
149
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
150
|
+
appropriateness of using or redistributing the Work and assume any
|
151
|
+
risks associated with Your exercise of permissions under this License.
|
152
|
+
|
153
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
154
|
+
whether in tort (including negligence), contract, or otherwise,
|
155
|
+
unless required by applicable law (such as deliberate and grossly
|
156
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
157
|
+
liable to You for damages, including any direct, indirect, special,
|
158
|
+
incidental, or consequential damages of any character arising as a
|
159
|
+
result of this License or out of the use or inability to use the
|
160
|
+
Work (including but not limited to damages for loss of goodwill,
|
161
|
+
work stoppage, computer failure or malfunction, or any and all
|
162
|
+
other commercial damages or losses), even if such Contributor
|
163
|
+
has been advised of the possibility of such damages.
|
164
|
+
|
165
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
166
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
167
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
168
|
+
or other liability obligations and/or rights consistent with this
|
169
|
+
License. However, in accepting such obligations, You may act only
|
170
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
171
|
+
of any other Contributor, and only if You agree to indemnify,
|
172
|
+
defend, and hold each Contributor harmless for any liability
|
173
|
+
incurred by, or claims asserted against, such Contributor by reason
|
174
|
+
of your accepting any such warranty or additional liability.
|
175
|
+
|
176
|
+
END OF TERMS AND CONDITIONS
|
177
|
+
|
178
|
+
APPENDIX: How to apply the Apache License to your work.
|
179
|
+
|
180
|
+
To apply the Apache License to your work, attach the following
|
181
|
+
boilerplate notice, with the fields enclosed by brackets "{}"
|
182
|
+
replaced with your own identifying information. (Don't include
|
183
|
+
the brackets!) The text should be enclosed in the appropriate
|
184
|
+
comment syntax for the file format. We also recommend that a
|
185
|
+
file or class name and description of purpose be included on the
|
186
|
+
same "printed page" as the copyright notice for easier
|
187
|
+
identification within third-party archives.
|
188
|
+
|
189
|
+
Copyright {yyyy} {name of copyright owner}
|
190
|
+
|
191
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
192
|
+
you may not use this file except in compliance with the License.
|
193
|
+
You may obtain a copy of the License at
|
194
|
+
|
195
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
196
|
+
|
197
|
+
Unless required by applicable law or agreed to in writing, software
|
198
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
199
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
200
|
+
See the License for the specific language governing permissions and
|
201
|
+
limitations under the License.
|
data/README.md
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
# Puppet Classroom Manager
|
2
|
+
|
3
|
+
Usage : `classroom <action> [subject] [options]`
|
4
|
+
|
5
|
+
Manage Puppet classroom VMs and updating courseware. This includes
|
6
|
+
troubleshooting and maintenance tasks to be used as needed during
|
7
|
+
the delivery and facilities for resetting the VM for use across
|
8
|
+
multiple deliveries. This is pre-installed on the classroom VM and
|
9
|
+
is only of use to trainers delivering Puppet Inc. classes.
|
10
|
+
|
11
|
+
Available actions:
|
12
|
+
|
13
|
+
* `classroom update`
|
14
|
+
This updates your VM to the latest released version. This includes all
|
15
|
+
cached packages, gems, modules, etc. and pre-installed courseware.
|
16
|
+
|
17
|
+
You should run this command before each delivery. It may take several
|
18
|
+
minutes to complete. When finished, it will run the validate task.
|
19
|
+
|
20
|
+
* `classroom validate`
|
21
|
+
This runs built in serverspec tests to check the VM for consistency.
|
22
|
+
It is run automatically by the update task so you likely don't need
|
23
|
+
to run it yourself.
|
24
|
+
|
25
|
+
* `classroom submit`
|
26
|
+
This task replaces the old `rake submit` tasks and uploads classroom
|
27
|
+
statistics to the EDU department for analysis.
|
28
|
+
|
29
|
+
* `classroom sanitize`
|
30
|
+
Running this task will remove all traces of students in preparation
|
31
|
+
for using the same VM for the next delivery.
|
32
|
+
|
33
|
+
* `classroom performance log <message>`
|
34
|
+
The VM periodically records performance metrics. These are included
|
35
|
+
in the information uploaded with the `submit` task. This task allows
|
36
|
+
you to annotate those logs with arbitrary information.
|
37
|
+
|
38
|
+
* `classroom reset password | certificates | filesync`
|
39
|
+
This task resets the specified information. Using this to reset the
|
40
|
+
root password ensures that it is still displayed on the login console.
|
41
|
+
This can also regenerate all monolithic PE certificates or use the
|
42
|
+
so-called "nuclear" option to blow away and redeploy filesync.
|
43
|
+
|
44
|
+
* `classroom restart <PE services>`
|
45
|
+
Gracefully restart PE services in the proper order. Run without a
|
46
|
+
service to see usage information.
|
47
|
+
|
48
|
+
* `classroom troubleshoot`
|
49
|
+
Run through various troubleshooting checks and fixes.
|
50
|
+
|
51
|
+
* `classroom page`
|
52
|
+
This will page on call classroom support in case of emergency.
|
data/bin/classroom
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
require 'optparse'
|
3
|
+
require 'logger'
|
4
|
+
|
5
|
+
require 'classroom'
|
6
|
+
|
7
|
+
$logger = Logger.new(STDOUT)
|
8
|
+
$logger.level = Logger::INFO
|
9
|
+
$logger.formatter = proc do |severity, datetime, progname, msg|
|
10
|
+
"#{severity}: #{msg}\n"
|
11
|
+
end
|
12
|
+
|
13
|
+
config = {}
|
14
|
+
optparse = OptionParser.new { |opts|
|
15
|
+
opts.banner = "Usage : classroom <action> [subject] [options]
|
16
|
+
|
17
|
+
Manage Puppet classroom VMs and updating courseware. This includes
|
18
|
+
troubleshooting and maintenance tasks to be used as needed during
|
19
|
+
the delivery and facilities for resetting the VM for use across
|
20
|
+
multiple deliveries. This is pre-installed on the classroom VM.
|
21
|
+
|
22
|
+
Type courseware help for full usage instructions.
|
23
|
+
|
24
|
+
"
|
25
|
+
|
26
|
+
opts.on("-d", "--debug", "Display debugging messages") do
|
27
|
+
$logger.level = Logger::DEBUG
|
28
|
+
end
|
29
|
+
|
30
|
+
opts.on("-f", "--force", "When restarting services, force a hard restart.") do
|
31
|
+
config[:force] = true
|
32
|
+
end
|
33
|
+
|
34
|
+
opts.separator('')
|
35
|
+
|
36
|
+
opts.on("-v", "--version", "Print out the version") do
|
37
|
+
require 'courseware/version'
|
38
|
+
puts Courseware::VERSION
|
39
|
+
exit
|
40
|
+
end
|
41
|
+
|
42
|
+
opts.on("-h", "--help", "Displays this help") do
|
43
|
+
puts opts
|
44
|
+
puts
|
45
|
+
exit 1
|
46
|
+
end
|
47
|
+
}
|
48
|
+
optparse.parse!
|
49
|
+
|
50
|
+
# hardcode for now. Decide if we need configurability later
|
51
|
+
config[:basedir] = '/opt/pltraining'
|
52
|
+
config[:bindir] = "#{config[:basedir]}/bin"
|
53
|
+
config[:confdir] = "#{config[:basedir]}/etc/puppet"
|
54
|
+
config[:specdir] = "#{config[:basedir]}/spec"
|
55
|
+
config[:learndot] = 'https://learn.puppet.com/manage/instructor/dashboard.html'
|
56
|
+
|
57
|
+
# grab the arguments after we've scraped the options out
|
58
|
+
verb, *subject = ARGV.collect {|arg| arg.to_sym }
|
59
|
+
|
60
|
+
classroom = Classroom.new(config)
|
61
|
+
begin
|
62
|
+
case verb
|
63
|
+
when :update
|
64
|
+
classroom.update
|
65
|
+
classroom.validate
|
66
|
+
|
67
|
+
when :validate
|
68
|
+
classroom.validate
|
69
|
+
# serverspec tests on the master MV
|
70
|
+
|
71
|
+
when :submit
|
72
|
+
classroom.submit
|
73
|
+
# submit classroom presentation stats
|
74
|
+
|
75
|
+
when :sanitize
|
76
|
+
classroom.sanitize
|
77
|
+
# remove users, etc to start a new delivery
|
78
|
+
|
79
|
+
when :performance
|
80
|
+
classroom.performance subject
|
81
|
+
# reset certificates, environments, node groups, courseware, etc
|
82
|
+
# is this even a thing???
|
83
|
+
|
84
|
+
when :reset
|
85
|
+
classroom.reset subject
|
86
|
+
# reset master certificates
|
87
|
+
# reset VM password
|
88
|
+
|
89
|
+
when :restart
|
90
|
+
classroom.restart subject
|
91
|
+
# restart PE services
|
92
|
+
|
93
|
+
when :troubleshoot
|
94
|
+
classroom.troubleshoot
|
95
|
+
# run troubleshooting scripts
|
96
|
+
|
97
|
+
when :page
|
98
|
+
classroom.page
|
99
|
+
|
100
|
+
when :help
|
101
|
+
classroom.help
|
102
|
+
|
103
|
+
when :shell
|
104
|
+
classroom.debug
|
105
|
+
|
106
|
+
else
|
107
|
+
$logger.warn "Unknown verb: #{verb}"
|
108
|
+
classroom.help
|
109
|
+
|
110
|
+
end
|
111
|
+
rescue RuntimeError => e
|
112
|
+
puts "Error: #{e.message}"
|
113
|
+
puts e.backtrace.join("\n\t") if config[:debug]
|
114
|
+
exit 1
|
115
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
class Classroom
|
2
|
+
HELP = <<-EOF
|
3
|
+
|
4
|
+
Usage : classroom <action> [subject] [options]
|
5
|
+
|
6
|
+
Manage Puppet classroom VMs and updating courseware. This includes
|
7
|
+
troubleshooting and maintenance tasks to be used as needed during
|
8
|
+
the delivery and facilities for resetting the VM for use across
|
9
|
+
multiple deliveries. This is pre-installed on the classroom VM and
|
10
|
+
is only of use to trainers delivering Puppet Inc. classes.
|
11
|
+
|
12
|
+
Available actions:
|
13
|
+
|
14
|
+
* classroom update:
|
15
|
+
This updates your VM to the latest released version. This includes all
|
16
|
+
cached packages, gems, modules, etc. and pre-installed courseware.
|
17
|
+
|
18
|
+
You should run this command before each delivery. It may take several
|
19
|
+
minutes to complete. When finished, it will run the validate task.
|
20
|
+
|
21
|
+
* classroom validate
|
22
|
+
This runs built in serverspec tests to check the VM for consistency.
|
23
|
+
It is run automatically by the update task so you likely don't need
|
24
|
+
to run it yourself.
|
25
|
+
|
26
|
+
* classroom submit
|
27
|
+
This task replaces the old `rake submit` tasks and uploads classroom
|
28
|
+
statistics to the EDU department for analysis.
|
29
|
+
|
30
|
+
* classroom sanitize
|
31
|
+
Running this task will remove all traces of students in preparation
|
32
|
+
for using the same VM for the next delivery.
|
33
|
+
|
34
|
+
* classroom performance log <message>
|
35
|
+
The VM periodically records performance metrics. These are included
|
36
|
+
in the information uploaded with the `submit` task. This task allows
|
37
|
+
you to annotate those logs with arbitrary information.
|
38
|
+
|
39
|
+
* classroom reset password | certificates | filesync
|
40
|
+
This task resets the specified information. Using this to reset the
|
41
|
+
root password ensures that it is still displayed on the login console.
|
42
|
+
This can also regenerate all monolithic PE certificates or use the
|
43
|
+
so-called "nuclear" option to blow away and redeploy filesync.
|
44
|
+
|
45
|
+
* classroom restart <PE services>
|
46
|
+
Gracefully restart PE services in the proper order. Run without a
|
47
|
+
service to see usage information.
|
48
|
+
|
49
|
+
* classroom troubleshoot
|
50
|
+
Run through various troubleshooting checks and fixes.
|
51
|
+
|
52
|
+
* classroom page
|
53
|
+
This will page on call classroom support in case of emergency.
|
54
|
+
|
55
|
+
* classroom help
|
56
|
+
You're looking at it!
|
57
|
+
|
58
|
+
EOF
|
59
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
class Classroom
|
2
|
+
def page
|
3
|
+
require 'json'
|
4
|
+
require 'rest-client'
|
5
|
+
|
6
|
+
begin
|
7
|
+
config = JSON.parse(File.read('/opt/pltraining/etc/classroom.json'))
|
8
|
+
pd_key = File.read('/opt/pltraining/etc/pagerduty.key')
|
9
|
+
rescue => e
|
10
|
+
puts "Cannot load configuration"
|
11
|
+
puts e.message
|
12
|
+
exit 1
|
13
|
+
end
|
14
|
+
|
15
|
+
puts "--------- You're about to page and possibly wake somone up. ---------"
|
16
|
+
puts "Please check the Troubleshooting Guide for solutions to common problems."
|
17
|
+
puts
|
18
|
+
puts "https://github.com/puppetlabs/courseware/blob/master/TroubleshootingGuide.md"
|
19
|
+
puts
|
20
|
+
if confirm?("Have you done everything in the troubleshooting guide?") then
|
21
|
+
puts "Sending page. Make sure you've posted about the issue in HipChat."
|
22
|
+
config = load_metadata
|
23
|
+
page_message = "Instructor: #{config['name']}\n" +
|
24
|
+
"Email: #{config['email']}\n" +
|
25
|
+
"Course: #{config['course']}\n" +
|
26
|
+
"ID: #{config['event_id']}"
|
27
|
+
page_data = {
|
28
|
+
"service_key" => pd_key,
|
29
|
+
"event_type" => "trigger",
|
30
|
+
"description" => page_message
|
31
|
+
}
|
32
|
+
response = RestClient.post(
|
33
|
+
"https://events.pagerduty.com/generic/2010-04-15/create_event.json",
|
34
|
+
page_data.to_json,
|
35
|
+
:content_type => :json,
|
36
|
+
:accept => :json
|
37
|
+
)
|
38
|
+
puts response
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
class Classroom
|
2
|
+
def performance(subject)
|
3
|
+
if subject.empty?
|
4
|
+
puts "This will take performance related snapshots, which will be uploaded for"
|
5
|
+
puts "engineering analysis. You may also record performance notes into the log."
|
6
|
+
puts
|
7
|
+
puts "Usage: classroom performance [ log <message> | snapshot ]"
|
8
|
+
puts
|
9
|
+
puts " * log: Record a message into classroom log and take a snapshot."
|
10
|
+
puts " * snapshot: Save snapshot of classroom statistics."
|
11
|
+
puts
|
12
|
+
exit 1
|
13
|
+
end
|
14
|
+
|
15
|
+
case subject.shift
|
16
|
+
when 'log'
|
17
|
+
message = subject.empty? ? "Misc performance issue noted." : subject.join(' ')
|
18
|
+
$logger.warn message
|
19
|
+
record_snapshot
|
20
|
+
|
21
|
+
when 'snapshot'
|
22
|
+
$logger.debug "Scheduled performance snapshot"
|
23
|
+
record_snapshot
|
24
|
+
|
25
|
+
else
|
26
|
+
raise "No such action"
|
27
|
+
end
|
28
|
+
|
29
|
+
def record_snapshot
|
30
|
+
$logger.debug "-------------------------------- top -bn1 ----------------------------------\n#{`top -bn1`}"
|
31
|
+
$logger.debug "-------------------------------- vmstat ------------------------------------\n#{`vmstat`}"
|
32
|
+
$logger.debug "-------------------------------- netstat -a --------------------------------\n#{`netstat -a`}"
|
33
|
+
$logger.debug "-------------------------------- iostat ------------------------------------\n#{`iostat`}"
|
34
|
+
$logger.debug "-------------------------------- mpstat -P ALL -----------------------------\n#{`mpstat -P ALL`}"
|
35
|
+
|
36
|
+
FileUtils.mkdir_p '/var/log/puppetlabs/classroom-traffic'
|
37
|
+
`tcpdump -G 15 -W 1 -w /var/log/puppetlabs/classroom-traffic/#{Time.now.to_i}.pcap -i any > /dev/null 2>&1 &`
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
class Classroom
|
2
|
+
def reset(subject)
|
3
|
+
if subject.size != 1
|
4
|
+
puts <<-EOF
|
5
|
+
Usage: classroom reset <password | certificates | filesync>
|
6
|
+
|
7
|
+
This tool will reset or regenerate:
|
8
|
+
* root's login password and update the /etc/issue screen
|
9
|
+
* delete and redeploy all FileSync caches
|
10
|
+
* *all* ssl certificates in the PE stack. (warning: destructive!)
|
11
|
+
|
12
|
+
EOF
|
13
|
+
exit 1
|
14
|
+
end
|
15
|
+
|
16
|
+
case subject.first
|
17
|
+
when :password
|
18
|
+
reset_password
|
19
|
+
when :certificates
|
20
|
+
reset_certificates
|
21
|
+
when :filesync
|
22
|
+
reset_filesync
|
23
|
+
else
|
24
|
+
raise "Unknown action."
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def reset_password
|
29
|
+
print "Enter new root password: "
|
30
|
+
password = gets.chomp
|
31
|
+
|
32
|
+
%x(echo "root:#{password}"|chpasswd)
|
33
|
+
|
34
|
+
File.open('/var/local/password','w') do |f|
|
35
|
+
f.puts password
|
36
|
+
end
|
37
|
+
|
38
|
+
%x(/etc/rc.local 2>/dev/null)
|
39
|
+
end
|
40
|
+
|
41
|
+
def reset_certificates
|
42
|
+
require "fileutils"
|
43
|
+
|
44
|
+
# Automate the process of regenerating certificates on a monolithic master
|
45
|
+
# https://docs.puppet.com/pe/latest/trouble_regenerate_certs_monolithic.html
|
46
|
+
#
|
47
|
+
timestamp = Time.now.to_i
|
48
|
+
certname = `puppet master --configprint certname`.strip
|
49
|
+
ssldir = '/etc/puppetlabs/puppet/ssl'
|
50
|
+
puppetdbcerts = '/etc/puppetlabs/puppetdb/ssl'
|
51
|
+
consolecerts = '/opt/puppetlabs/server/data/console-services/certs'
|
52
|
+
pgsqlcerts = '/opt/puppetlabs/server/data/postgresql/9.4/data/certs'
|
53
|
+
orchcerts = '/etc/puppetlabs/orchestration-services/ssl'
|
54
|
+
|
55
|
+
["puppet", "puppetdb", "console-services", "postgresql", "orchestration"].each do |path|
|
56
|
+
FileUtils.mkdir_p("/root/certificates.bak/#{path}")
|
57
|
+
end
|
58
|
+
FileUtils.cp_r("#{ssldir}", "/root/certificates.bak/puppet/#{timestamp}")
|
59
|
+
FileUtils.cp_r("#{puppetdbcerts}", "/root/certificates.bak/puppetdb/#{timestamp}")
|
60
|
+
FileUtils.cp_r("#{consolecerts}", "/root/certificates.bak/console-services/#{timestamp}")
|
61
|
+
FileUtils.cp_r("#{pgsqlcerts}", "/root/certificates.bak/postgresql/#{timestamp}")
|
62
|
+
FileUtils.cp_r("#{orchcerts}", "/root/certificates.bak/orchestration/#{timestamp}")
|
63
|
+
|
64
|
+
puts "Certificates backed up to ~/certificates.bak"
|
65
|
+
|
66
|
+
puts
|
67
|
+
puts
|
68
|
+
puts "#####################################################################"
|
69
|
+
puts
|
70
|
+
puts " If you regenerate the Puppet CA to start fresh, then"
|
71
|
+
puts "ALL client certificates will be invalidated and must be regenerated!"
|
72
|
+
puts
|
73
|
+
puts " -- This should only be done as a last resort --"
|
74
|
+
puts
|
75
|
+
puts "#####################################################################"
|
76
|
+
puts
|
77
|
+
if confirm?('Would you like to regenerate the CA?', false)
|
78
|
+
FileUtils.rm_rf("#{ssldir}/*")
|
79
|
+
system("puppet cert list -a")
|
80
|
+
end
|
81
|
+
|
82
|
+
FileUtils.rm_f("/opt/puppetlabs/puppet/cache/client_data/catalog/#{certname}.json")
|
83
|
+
system("puppet cert clean #{certname}")
|
84
|
+
system("puppet infrastructure configure --no-recover")
|
85
|
+
system("puppet agent -t")
|
86
|
+
|
87
|
+
puts "All done. If you regenerated the CA, then regenerate all client certificates now."
|
88
|
+
end
|
89
|
+
|
90
|
+
def reset_filesync
|
91
|
+
puts
|
92
|
+
puts
|
93
|
+
puts "################################################################################"
|
94
|
+
puts
|
95
|
+
puts "This script will completely delete and redeploy all environments without backup!"
|
96
|
+
puts " The operation may take up to five minutes to complete."
|
97
|
+
puts
|
98
|
+
puts "################################################################################"
|
99
|
+
puts
|
100
|
+
bailout?
|
101
|
+
|
102
|
+
system("systemctl stop pe-puppetserver")
|
103
|
+
|
104
|
+
# filesync cache
|
105
|
+
FileUtils.rm_rf("/opt/puppetlabs/server/data/puppetserver/filesync")
|
106
|
+
|
107
|
+
# r10k cache
|
108
|
+
FileUtils.rm_rf("/opt/puppetlabs/server/data/code-manager/git")
|
109
|
+
|
110
|
+
# code manager worker thread caches
|
111
|
+
FileUtils.rm_rf("/opt/puppetlabs/server/data/code-manager/worker-caches")
|
112
|
+
FileUtils.rm_rf("/opt/puppetlabs/server/data/code-manager/cache")
|
113
|
+
|
114
|
+
# possibly stale environment codebases
|
115
|
+
FileUtils.rm_rf("/etc/puppetlabs/code/*")
|
116
|
+
FileUtils.rm_rf("/etc/puppetlabs/code-staging/environments")
|
117
|
+
|
118
|
+
system("systemctl start pe-puppetserver")
|
119
|
+
system("puppet code deploy --all --wait")
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
class Classroom
|
2
|
+
def restart(subject)
|
3
|
+
if subject.empty?
|
4
|
+
puts <<-EOF
|
5
|
+
This tool simply helps restart the PE services in the right order.
|
6
|
+
It will send a HUP signal to Puppetserver by default which is much
|
7
|
+
faster than a full restart.
|
8
|
+
|
9
|
+
You can also restart Docker containers in classes that use them.
|
10
|
+
|
11
|
+
If you do need the full restart, please pass the -f option.
|
12
|
+
|
13
|
+
Service names:
|
14
|
+
* puppetserver
|
15
|
+
* console
|
16
|
+
* puppetdb
|
17
|
+
* orchestration
|
18
|
+
* mcollective
|
19
|
+
* containers
|
20
|
+
* all (restart all PE services in the proper order)
|
21
|
+
|
22
|
+
Examples:
|
23
|
+
* classroom restart puppetdb puppetserver
|
24
|
+
* classroom restart puppetserver console -f
|
25
|
+
* classroom restart all -f
|
26
|
+
|
27
|
+
EOF
|
28
|
+
exit 1
|
29
|
+
end
|
30
|
+
|
31
|
+
# normalize to lowercase strings so we can pattern match
|
32
|
+
subject.map! { |x| x.to_s.downcase }
|
33
|
+
|
34
|
+
if subject.include? 'all'
|
35
|
+
puts "Restarting all PE stack services. This may take a few minutes..."
|
36
|
+
subject.concat ['puppetdb', 'puppetserver', 'orchestrator', 'console', 'mcollective', 'puppet']
|
37
|
+
subject.uniq!
|
38
|
+
else
|
39
|
+
puts "Restarting selected PE components."
|
40
|
+
end
|
41
|
+
|
42
|
+
if subject.grep(/puppetdb|pdb/).any?
|
43
|
+
restart_service('pe-postgresql.service')
|
44
|
+
restart_service('pe-puppetdb.service')
|
45
|
+
end
|
46
|
+
|
47
|
+
if subject.grep(/puppetserver|server/).any?
|
48
|
+
if @config[:force]
|
49
|
+
restart_service('pe-puppetserver.service')
|
50
|
+
else
|
51
|
+
reload_service('pe-puppetserver.service', 'puppet-server')
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
if subject.grep(/orch|pxp/).any?
|
56
|
+
restart_service('pe-orchestration-services.service')
|
57
|
+
restart_service('pxp-agent.service')
|
58
|
+
end
|
59
|
+
|
60
|
+
if subject.grep(/console/).any?
|
61
|
+
restart_service('pe-console-services.service')
|
62
|
+
restart_service('pe-nginx.service')
|
63
|
+
end
|
64
|
+
|
65
|
+
if subject.grep(/mco/).any?
|
66
|
+
restart_service('pe-activemq.service')
|
67
|
+
restart_service('mcollective.service')
|
68
|
+
end
|
69
|
+
|
70
|
+
if subject.include? 'puppet'
|
71
|
+
restart_service('puppet.service')
|
72
|
+
end
|
73
|
+
|
74
|
+
if subject.include? 'containers'
|
75
|
+
`systemctl list-units`.each_line do |line|
|
76
|
+
restart_service($1) if line =~ /^(docker-\S+)/
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
def restart_service(service)
|
83
|
+
puts "- Restarting #{service}..."
|
84
|
+
system("systemctl restart #{service}")
|
85
|
+
end
|
86
|
+
|
87
|
+
def reload_service(service, pattern)
|
88
|
+
puts "> Reloading #{service}..."
|
89
|
+
system("kill -HUP `pgrep -f #{pattern}`")
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
class Classroom
|
2
|
+
def sanitize
|
3
|
+
require 'yaml'
|
4
|
+
require 'fileutils'
|
5
|
+
require 'puppetclassify'
|
6
|
+
|
7
|
+
puts 'Sanitizing your VM for your next delivery...'
|
8
|
+
|
9
|
+
certname = `puppet master --configprint certname`.strip
|
10
|
+
master = `puppet agent --configprint server`.strip
|
11
|
+
classifier = "http://#{master}:4433/classifier-api"
|
12
|
+
known_groups = [ 'All Nodes', 'Agent-specified environment', 'Production environment', /PE / ]
|
13
|
+
known_users = [ 'admin"=', 'api_user', 'deployer' ]
|
14
|
+
auth_info = {
|
15
|
+
'ca_certificate_path' => `puppet master --configprint localcacert`.strip,
|
16
|
+
'certificate_path' => `puppet master --configprint hostcert`.strip,
|
17
|
+
'private_key_path' => `puppet master --configprint hostprivkey`.strip,
|
18
|
+
}
|
19
|
+
|
20
|
+
group_pattern = Regexp.union(known_groups)
|
21
|
+
puppetclassify = PuppetClassify.new(classifier, auth_info)
|
22
|
+
puppetclassify.groups.get_groups.each do |group|
|
23
|
+
next if group['name'].match(group_pattern)
|
24
|
+
puppetclassify.groups.delete_group(group['id'])
|
25
|
+
print '.'
|
26
|
+
end
|
27
|
+
puts
|
28
|
+
|
29
|
+
# depends on pltraining/rbac module
|
30
|
+
users = YAML.load(`puppet resource rbac_user --to_yaml`)
|
31
|
+
users['rbac_user'].each do |user, data|
|
32
|
+
next if known_users.include? user
|
33
|
+
puts "puppet resource rbac_user #{user} ensure=absent"
|
34
|
+
system("puppet resource rbac_user #{user} ensure=absent")
|
35
|
+
print '.'
|
36
|
+
end
|
37
|
+
puts
|
38
|
+
|
39
|
+
`puppet cert list --all --machine-readable`.each_line do |line|
|
40
|
+
next unless line.start_with? '+'
|
41
|
+
name = line.gsub('"', '').split[1]
|
42
|
+
next if name.start_with? 'pe-internal'
|
43
|
+
next if name == certname
|
44
|
+
|
45
|
+
system("puppet node deactivate #{name}")
|
46
|
+
system("puppet cert clean #{name}")
|
47
|
+
print '.'
|
48
|
+
end
|
49
|
+
puts
|
50
|
+
|
51
|
+
Dir.glob('/home/*').each do |path|
|
52
|
+
next if ['/home/training', '/home/showoff'].include? path
|
53
|
+
system("userdel #{File.basename(path)}")
|
54
|
+
FileUtils.rm_rf path
|
55
|
+
print '.'
|
56
|
+
end
|
57
|
+
puts
|
58
|
+
|
59
|
+
Dir.glob('/etc/puppetlabs/code-staging/environments/*').each do |path|
|
60
|
+
next if File.basename(path) == 'production'
|
61
|
+
FileUtils.rm_rf path
|
62
|
+
print '.'
|
63
|
+
end
|
64
|
+
puts
|
65
|
+
|
66
|
+
Dir.glob('/etc/puppetlabs/code/environments/*').each do |path|
|
67
|
+
next if File.basename(path) == 'production'
|
68
|
+
FileUtils.rm_rf path
|
69
|
+
print '.'
|
70
|
+
end
|
71
|
+
puts
|
72
|
+
|
73
|
+
FileUtils.rm_rf('/var/repositories/*')
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
class Classroom
|
2
|
+
def submit
|
3
|
+
require 'fileutils'
|
4
|
+
require 'aws-sdk'
|
5
|
+
|
6
|
+
if puppetlabs_instructor?
|
7
|
+
puts "Please go to your learn dashboard and ensure that attendance is accurate"
|
8
|
+
puts "and then close this class delivery to mark it as complete."
|
9
|
+
puts " -- #{@config[:learndot]}"
|
10
|
+
puts
|
11
|
+
end
|
12
|
+
|
13
|
+
presentation = showoff_working_directory()
|
14
|
+
|
15
|
+
data = JSON.parse(File.read("#{presentation}/stats/metadata.json")) rescue {}
|
16
|
+
event_id = data['event_id'] || Time.now.to_i
|
17
|
+
course = data['course'] || 'none'
|
18
|
+
email = data['email'] || 'none'
|
19
|
+
|
20
|
+
begin
|
21
|
+
# depends on root's credentials as managed by bootstrap
|
22
|
+
s3 = Aws::S3::Resource.new(region:'us-west-2')
|
23
|
+
|
24
|
+
# record the module versions in use
|
25
|
+
system("puppet module list > /var/log/puppetlabs/classroom-modules")
|
26
|
+
|
27
|
+
filename = "classroom-perflogs-#{course}-#{email}-#{event_id}.tar.gz"
|
28
|
+
system("tar -cf /var/cache/#{filename} /var/log/puppetlabs/")
|
29
|
+
obj = s3.bucket(PERF_BUCKET).object(filename)
|
30
|
+
obj.upload_file("/var/cache/#{filename}")
|
31
|
+
FileUtils.rm(filename)
|
32
|
+
|
33
|
+
filename = "classroom-stats-#{course}-#{email}-#{event_id}.tar.gz"
|
34
|
+
system("tar -cf /var/cache/#{filename} #{presentation}/stats/")
|
35
|
+
obj = s3.bucket(STATS_BUCKET).object(filename)
|
36
|
+
obj.upload_file("/var/cache/#{filename}")
|
37
|
+
FileUtils.rm(filename)
|
38
|
+
|
39
|
+
rescue LoadError, StandardError => e
|
40
|
+
LOGGER.warn "S3 upload failed. No network?"
|
41
|
+
LOGGER.warn e.message
|
42
|
+
LOGGER.debug e.backtrace
|
43
|
+
end
|
44
|
+
|
45
|
+
# clean up for next delivery
|
46
|
+
system("puppet resource service showoff-courseware ensure=stopped")
|
47
|
+
FileUtils.rm_rf("#{presentation}/stats")
|
48
|
+
FileUtils.rm_f("#{presentation}/courseware.yaml")
|
49
|
+
FileUtils.rm_f("#{presentation}/_files/share/nearby_events.html")
|
50
|
+
system("puppet resource service showoff-courseware ensure=running")
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
def puppetlabs_instructor?
|
55
|
+
# TODO: how do?
|
56
|
+
false
|
57
|
+
end
|
58
|
+
|
59
|
+
def showoff_working_directory
|
60
|
+
# get the path of the currently configured showoff presentation
|
61
|
+
data = {}
|
62
|
+
path = '/usr/lib/systemd/system/showoff-courseware.service'
|
63
|
+
File.read(path).each_line do |line|
|
64
|
+
setting = line.split('=')
|
65
|
+
next unless setting.size == 2
|
66
|
+
|
67
|
+
data[setting.first] = setting.last
|
68
|
+
end
|
69
|
+
data['WorkingDirectory']
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
@@ -0,0 +1,178 @@
|
|
1
|
+
class Classroom
|
2
|
+
def troubleshoot
|
3
|
+
master = `puppet agent --configprint server`.strip
|
4
|
+
codedir = `puppet master --configprint codedir`.strip
|
5
|
+
filesync = '/etc/puppetlabs/puppetserver/conf.d/file-sync.conf'
|
6
|
+
release = File.read('/etc/puppetlabs-release').to_f rescue 0
|
7
|
+
legacy = release < 7.0
|
8
|
+
|
9
|
+
if File.exist? filesync
|
10
|
+
# why isn't there a configprint setting for this?
|
11
|
+
staging = `hocon -f #{filesync} get file-sync.repos.puppet-code.staging-dir`.strip
|
12
|
+
puts "Running checks for Code Manager configurations:"
|
13
|
+
else
|
14
|
+
staging = codedir
|
15
|
+
puts "Running checks for configurations without Code Manager:"
|
16
|
+
end
|
17
|
+
|
18
|
+
print "Cleaning any stray .git directories in: #{codedir}..."
|
19
|
+
sleep 1
|
20
|
+
system("find #{codedir} -name .git -type d -print -exec rm -rf {} \\;")
|
21
|
+
check_success
|
22
|
+
|
23
|
+
print "Validating permissions on: #{codedir}..."
|
24
|
+
sleep 1
|
25
|
+
system("find #{codedir} '!' -user pe-puppet -print -exec chown pe-puppet:pe-puppet {} \\;")
|
26
|
+
check_success
|
27
|
+
|
28
|
+
if codedir != staging
|
29
|
+
puts "Validating permissions on: #{staging}..."
|
30
|
+
sleep 1
|
31
|
+
system("find #{staging} '!' -user pe-puppet -print -exec chown pe-puppet:pe-puppet {} \\;")
|
32
|
+
check_success
|
33
|
+
end
|
34
|
+
|
35
|
+
# only check legacy systems that rely on manual installs
|
36
|
+
if legacy
|
37
|
+
if File.exist? '/home/training/courseware'
|
38
|
+
print "Sanitizing uploaded courseware..."
|
39
|
+
sleep 1
|
40
|
+
FileUtils.rm_f '/home/training/courseware/stats/viewstats.json'
|
41
|
+
FileUtils.rm_f '/home/training/courseware/stats/forms.json'
|
42
|
+
check_success
|
43
|
+
else
|
44
|
+
check_success(false)
|
45
|
+
puts "\tYou don't seem to have uploaded the courseware from your host system"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
print "Checking Forge connection..."
|
50
|
+
if system("ping -c1 -W2 forge.puppet.com >/dev/null 2>&1")
|
51
|
+
if legacy
|
52
|
+
puts "Ensuring the latest version of pltraining/classroom in #{staging}..."
|
53
|
+
system("puppet module upgrade pltraining/classroom --modulepath #{staging}")
|
54
|
+
check_success
|
55
|
+
else
|
56
|
+
check_success(true)
|
57
|
+
end
|
58
|
+
else
|
59
|
+
if `awk '$1 == "server" {print $2}' /etc/ntp.conf` != master
|
60
|
+
check_success(false)
|
61
|
+
puts "\tCould not reach the Forge. You should classify your master as $offline => true"
|
62
|
+
else
|
63
|
+
puts "\tYou appear to be in offline mode."
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
if codedir != staging
|
68
|
+
print "Ensuring you have a valid deploy token..."
|
69
|
+
if File.exist? '/root/.puppetlabs/token'
|
70
|
+
token = `puppet access show`
|
71
|
+
api = 'https://#{master}:4433/rbac-api/v1/users/current'
|
72
|
+
status = `curl -k --write-out "%{http_code}" --silent --output /dev/null #{api} -H "X-Authentication:#{token}"`.strip
|
73
|
+
if status != "200"
|
74
|
+
print "\nRegenerating invalid token..."
|
75
|
+
FileUtils.rm_f('/root/.puppetlabs/token')
|
76
|
+
check_success
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
unless File.exist? '/root/.puppetlabs/token'
|
81
|
+
print "\nGenerating new token."
|
82
|
+
system('puppet plugin download > /dev/null')
|
83
|
+
system('puppet resource rbac_user deployer ensure=present display_name=deployer email=deployer@puppetlabs.vm password=puppetlabs roles=4 > /dev/null')
|
84
|
+
system('echo "puppetlabs" | HOME=/root /opt/puppetlabs/bin/puppet-access login deployer --lifetime 14d > /dev/null')
|
85
|
+
check_success
|
86
|
+
else
|
87
|
+
check_success(true)
|
88
|
+
end
|
89
|
+
|
90
|
+
puts
|
91
|
+
puts "If you're having trouble with Code Manager or FileSync, deleting all deployed"
|
92
|
+
puts "code and destroying all caches can sometimes help you get going again."
|
93
|
+
puts
|
94
|
+
if confirm?('Would you like to nuke it all and start over?', false)
|
95
|
+
reset([:filesync])
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
print "Validating SSL certificates..."
|
100
|
+
if valid_certificates
|
101
|
+
check_success(true)
|
102
|
+
else
|
103
|
+
puts
|
104
|
+
puts "It looks like there is an inconsistency with your master's SSL certificates."
|
105
|
+
puts "Regenerating certificates may take up to five minutes."
|
106
|
+
puts
|
107
|
+
if confirm?('Would you like to try regenerating certificates?', false)
|
108
|
+
reset([:certificates])
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
puts
|
113
|
+
puts 'Done checking. Fix any errors noted above and try again.'
|
114
|
+
puts 'If still having troubles, try some of the following steps.'
|
115
|
+
puts 'Note that both tail and journalctl have a "-f" follow mode.'
|
116
|
+
puts
|
117
|
+
puts 'Log files:'
|
118
|
+
puts ' * tail /var/log/puppetlabs/puppetserver/puppetserver.log'
|
119
|
+
puts ' * tail /var/log/puppetlabs/console-services/console-services.log'
|
120
|
+
puts ' * tail any other interesting log files in /var/log/puppetlabs'
|
121
|
+
puts 'System logs:'
|
122
|
+
puts ' * journalctl -eu pe-puppetserver'
|
123
|
+
puts ' * journalctl -eu pe-console-services'
|
124
|
+
puts ' * systemctl list-units | egrep "pe-|puppet"'
|
125
|
+
puts 'Edu tools:'
|
126
|
+
puts ' * tail /var/log/puppetfactory'
|
127
|
+
puts ' * journalctl -eu abalone'
|
128
|
+
puts ' * journalctl -eu puppetfactory'
|
129
|
+
puts ' * journalctl -eu showoff-courseware'
|
130
|
+
puts ' * reset_ssl_certificates.sh'
|
131
|
+
puts ' * restart_classroom_services.rb'
|
132
|
+
puts ' * dependency_nuke.rb'
|
133
|
+
puts
|
134
|
+
puts 'Have you searched the Troubleshooting Guide for your issue?'
|
135
|
+
puts "If you're still stuck, page the on-call support with 'classroom page'"
|
136
|
+
end
|
137
|
+
|
138
|
+
def valid_certificates
|
139
|
+
certname = `puppet master --configprint certname`.strip
|
140
|
+
ssldir = '/etc/puppetlabs/puppet/ssl'
|
141
|
+
puppetdbcerts = '/etc/puppetlabs/puppetdb/ssl'
|
142
|
+
consolecerts = '/opt/puppetlabs/server/data/console-services/certs'
|
143
|
+
pgsqlcerts = '/opt/puppetlabs/server/data/postgresql/9.4/data/certs'
|
144
|
+
orchcerts = '/etc/puppetlabs/orchestration-services/ssl'
|
145
|
+
|
146
|
+
cert = same_file("#{ssldir}/certs/#{certname}.pem", [
|
147
|
+
"#{puppetdbcerts}/#{certname}.cert.pem",
|
148
|
+
"#{pgsqlcerts}/_local.cert.pem",
|
149
|
+
"#{consolecerts}/#{certname}.cert.pem",
|
150
|
+
"#{orchcerts}/#{certname}.cert.pem",
|
151
|
+
])
|
152
|
+
public_key = same_file("#{ssldir}/public_keys/#{certname}.pem", [
|
153
|
+
"#{puppetdbcerts}/#{certname}.public_key.pem",
|
154
|
+
"#{consolecerts}/#{certname}.public_key.pem",
|
155
|
+
"#{orchcerts}/#{certname}.public_key.pem",
|
156
|
+
])
|
157
|
+
private_key = same_file("#{ssldir}/private_keys/#{certname}.pem", [
|
158
|
+
"#{puppetdbcerts}/#{certname}.private_key.pem",
|
159
|
+
"#{pgsqlcerts}/_local.private_key.pem",
|
160
|
+
"#{consolecerts}/#{certname}.private_key.pem",
|
161
|
+
"#{orchcerts}/#{certname}.private_key.pem",
|
162
|
+
])
|
163
|
+
|
164
|
+
return (cert and public_key and private_key)
|
165
|
+
end
|
166
|
+
|
167
|
+
def same_file(filename, list)
|
168
|
+
require 'digest'
|
169
|
+
list = Array(list) # coerce if needed
|
170
|
+
left = Digest::MD5.hexdigest(File.read(filename))
|
171
|
+
|
172
|
+
list.each do |path|
|
173
|
+
return false unless (left == Digest::MD5.hexdigest(File.read(path)))
|
174
|
+
end
|
175
|
+
|
176
|
+
return true
|
177
|
+
end
|
178
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class Classroom
|
2
|
+
def validate
|
3
|
+
require 'rake'
|
4
|
+
require 'rspec/core/rake_task'
|
5
|
+
|
6
|
+
puts "Validating configuration..."
|
7
|
+
Dir.chdir(@config[:specdir]) do
|
8
|
+
RSpec::Core::RakeTask.new(:spec) do |t|
|
9
|
+
t.rspec_opts = "-I #{@config[:specdir]}"
|
10
|
+
t.pattern = 'localhost/*_spec.rb'
|
11
|
+
end
|
12
|
+
|
13
|
+
Rake::Task[:spec].invoke
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
data/lib/classroom.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
class Classroom
|
2
|
+
require 'classroom/performance'
|
3
|
+
require 'classroom/reset'
|
4
|
+
require 'classroom/restart'
|
5
|
+
require 'classroom/sanitize'
|
6
|
+
require 'classroom/submit'
|
7
|
+
require 'classroom/troubleshoot'
|
8
|
+
require 'classroom/validate'
|
9
|
+
require 'classroom/version'
|
10
|
+
|
11
|
+
def initialize(config)
|
12
|
+
@config = config
|
13
|
+
end
|
14
|
+
|
15
|
+
def update
|
16
|
+
puts "Updating system and courseware..."
|
17
|
+
system("#{@config[:bindir]}/puppet agent -t --confdir #{@config[:confdir]}")
|
18
|
+
end
|
19
|
+
|
20
|
+
def confirm?(message = 'Continue?', default = true)
|
21
|
+
if default
|
22
|
+
print "#{message} [Y/n]: "
|
23
|
+
return [ 'y', 'yes', '' ].include? STDIN.gets.strip.downcase
|
24
|
+
else
|
25
|
+
print "#{message} [y/N]: "
|
26
|
+
return [ 'y', 'yes' ].include? STDIN.gets.strip.downcase
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def bailout?(message = 'Continue?')
|
31
|
+
raise "User cancelled" unless confirm?(message)
|
32
|
+
end
|
33
|
+
|
34
|
+
def check_success(status=nil)
|
35
|
+
status = status.nil? ? ($? == 0) : status
|
36
|
+
|
37
|
+
if status
|
38
|
+
printf("\[\033[32m OK \033[0m]\n")
|
39
|
+
else
|
40
|
+
printf("[\033[31m FAIL \033[0m]\n")
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def help
|
45
|
+
require 'classroom/help'
|
46
|
+
puts Classroom::HELP
|
47
|
+
end
|
48
|
+
|
49
|
+
def debug
|
50
|
+
require 'pry'
|
51
|
+
binding.pry
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
metadata
ADDED
@@ -0,0 +1,134 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: puppet-classroom-manager
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ben Ford
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-08-10 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: aws-sdk
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: puppetclassify
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: serverspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: hocon
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rest-client
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
description: |2
|
84
|
+
Manage Puppet classroom VMs and updating courseware. This includes
|
85
|
+
troubleshooting and maintenance tasks to be used as needed during
|
86
|
+
the delivery and facilities for resetting the VM for use across
|
87
|
+
multiple deliveries. This is pre-installed on the classroom VM.
|
88
|
+
|
89
|
+
If you are not teaching Puppet Inc. classes, this is not for you.
|
90
|
+
email: education@puppetlabs.com
|
91
|
+
executables:
|
92
|
+
- classroom
|
93
|
+
extensions: []
|
94
|
+
extra_rdoc_files: []
|
95
|
+
files:
|
96
|
+
- README.md
|
97
|
+
- LICENSE
|
98
|
+
- bin/classroom
|
99
|
+
- lib/classroom/help.rb
|
100
|
+
- lib/classroom/page.rb
|
101
|
+
- lib/classroom/performance.rb
|
102
|
+
- lib/classroom/reset.rb
|
103
|
+
- lib/classroom/restart.rb
|
104
|
+
- lib/classroom/sanitize.rb
|
105
|
+
- lib/classroom/submit.rb
|
106
|
+
- lib/classroom/troubleshoot.rb
|
107
|
+
- lib/classroom/validate.rb
|
108
|
+
- lib/classroom/version.rb
|
109
|
+
- lib/classroom.rb
|
110
|
+
homepage: http://github.com/puppetlabs/puppet-classroom-manager
|
111
|
+
licenses:
|
112
|
+
- Apache-2.0
|
113
|
+
metadata: {}
|
114
|
+
post_install_message:
|
115
|
+
rdoc_options: []
|
116
|
+
require_paths:
|
117
|
+
- lib
|
118
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
119
|
+
requirements:
|
120
|
+
- - ">="
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: '0'
|
123
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
124
|
+
requirements:
|
125
|
+
- - ">="
|
126
|
+
- !ruby/object:Gem::Version
|
127
|
+
version: '0'
|
128
|
+
requirements: []
|
129
|
+
rubyforge_project:
|
130
|
+
rubygems_version: 2.0.14.1
|
131
|
+
signing_key:
|
132
|
+
specification_version: 4
|
133
|
+
summary: Manage Puppet classroom VMs and updating courseware.
|
134
|
+
test_files: []
|