puppetfactory 0.5.9 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 60c925f67c54a20814cd88a9c1b0db49d12e44a9
4
- data.tar.gz: 6ffa50fac51bdca43e47891a886c780d0ed0b1d3
3
+ metadata.gz: f68142c666caae7ed6041926b898235c8ec86adb
4
+ data.tar.gz: 3e44a08a9800fe697b19d0e310f04324e26bb636
5
5
  SHA512:
6
- metadata.gz: f68d09e430b101a71c1103da68a5c3d022085cca5e668ca221037342fac00ad775d38984c8044da7bd41560d6ac4bdfc70b5bc2762f3600e5243991b796efb54
7
- data.tar.gz: d65e3d31ec098f7f00d10506ddc98065762f5d63397daf7fd18352c5edc885ffaaf2ab615d4230d0e6a13492557f6d501d38a4000a9a6a29ce6e9d63d76ecce5
6
+ metadata.gz: 8a13501a324ee2f1657437b6c3af2da79a9daa79f95556e29597fe80157bf43a21e2429cf36865dc5458cc52f0e7a716bf965288517a627f2b14ce1c2c11bec9
7
+ data.tar.gz: 676a0e83e781edea7579224602899865edf35019b9998340ec15504afbe827f1f4fb572ee0689555c902def65f0a84f19dbdc4d364467794f22ee542af53c476
@@ -85,7 +85,7 @@ options[:gituser] ||= 'puppetlabs'
85
85
  options[:controlrepo] ||= 'control-repo.git'
86
86
  options[:repomodel] ||= :single
87
87
 
88
- options[:plugins] ||= [:ShellUser, :Logs]
88
+ options[:plugins] ||= [:ShellUser, :Logs, :LoginShell]
89
89
 
90
90
  def validate(options, option, values)
91
91
  unless values.include? options[option]
@@ -106,7 +106,10 @@ $logger.formatter = proc { |severity,datetime,progname,msg| "[#{datetime}] #{sev
106
106
 
107
107
  # if no arguments, start up the server
108
108
  if ARGV.size == 0
109
- Puppetfactory.run! options
109
+ # TODO: remove this insane timeout once we have a progressive user creation dialog
110
+ Puppetfactory.run!(options) do |server|
111
+ server.timeout = 180
112
+ end
110
113
 
111
114
  # opts = {
112
115
  # :Port => 8000,
@@ -26,7 +26,7 @@ class Puppetfactory < Sinatra::Base
26
26
 
27
27
  configure :production, :development do
28
28
  enable :logging
29
- use Rack::Session::Cookie,
29
+ use Rack::Session::Cookie,
30
30
  :key => 'puppetfactory.session',
31
31
  :path => '/',
32
32
  :expire_after => 2592000, # In seconds
@@ -37,7 +37,7 @@ class Puppetfactory < Sinatra::Base
37
37
  # IE is cache happy. Let's make that go away.
38
38
  cache_control :no_cache, :max_age => 0
39
39
  end
40
-
40
+
41
41
  def initialize(app=nil)
42
42
  super(app)
43
43
 
@@ -66,14 +66,11 @@ class Puppetfactory < Sinatra::Base
66
66
  # UI tab endpoints
67
67
  get '/' do
68
68
  @tabs = merge(plugins(:tabs, privileged?))
69
+ @current = merge(plugins(:userinfo, session[:username], true)) if session.include? :username
69
70
 
70
71
  erb :index
71
72
  end
72
73
 
73
- get '/home' do
74
- erb :home
75
- end
76
-
77
74
  get '/users' do
78
75
  @users = load_users()
79
76
  @current = merge(plugins(:userinfo, session[:username], true)) if session.include? :username
@@ -88,16 +85,38 @@ class Puppetfactory < Sinatra::Base
88
85
 
89
86
  # set the currently active user. This should probably be a PUT action.
90
87
  get '/users/active/:username' do |username|
88
+ username ||= myParams[user]
89
+
90
+ users ||= load_users()
91
+
92
+ unless users.include?(username)
93
+ return {
94
+ "status" => "failure",
95
+ "message" => "invalid user"
96
+ }.to_json
97
+ end
98
+
91
99
  session[:username] = username
92
100
  {"status" => "ok"}.to_json
101
+ redirect '/'
102
+ end
103
+
104
+ get '/users/deactive' do
105
+ session.delete :username
106
+ redirect '/'
93
107
  end
94
108
 
95
109
  # admin login
96
- get '/login' do
110
+ get '/admin-login' do
97
111
  protected!
98
112
  redirect '/'
99
113
  end
100
114
 
115
+ get '/admin-logout' do
116
+ remove_privileges!
117
+ redirect '/'
118
+ end
119
+
101
120
  # create a new username with the default password.
102
121
  get '/new/:username' do |username|
103
122
  protected!
@@ -300,10 +319,14 @@ class Puppetfactory < Sinatra::Base
300
319
  session[:privileges] = 'admin'
301
320
  true
302
321
  else
303
- session.delete :privileges
322
+ remove_privileges!
304
323
  false
305
324
  end
306
325
  end
307
326
 
327
+ def remove_privileges!
328
+ session.delete :privileges
329
+ end
330
+
308
331
  end
309
332
  end
@@ -33,7 +33,7 @@ class Puppetfactory::Plugins::Docker < Puppetfactory::Plugins
33
33
  "/var/yum:/var/yum",
34
34
  "/var/cache:/var/cache",
35
35
  "/etc/pki/rpm-gpg:/etc/pki/rpm-gpg",
36
- "/etc/yum.repos.d:/etc/yum.repos.d",
36
+ # "/etc/yum.repos.d:/etc/yum.repos.d", # we can't share this because of pe_repo.repo
37
37
  "/opt/puppetlabs/server:/opt/puppetlabs/server",
38
38
  "/home/#{username}/puppet:#{@confdir}",
39
39
  "/sys/fs/cgroup:/sys/fs/cgroup:ro"
@@ -1,5 +1,6 @@
1
1
  require 'json'
2
2
  require 'fileutils'
3
+ require 'restclient'
3
4
  require 'puppetfactory'
4
5
 
5
6
  class Puppetfactory::Plugins::Gitea < Puppetfactory::Plugins
@@ -7,49 +8,40 @@ class Puppetfactory::Plugins::Gitea < Puppetfactory::Plugins
7
8
  def initialize(options)
8
9
  super(options)
9
10
 
11
+ @cache_dir = '/var/cache/puppetfactory/gitea'
12
+ @lockfile = '/var/cache/puppetfactory/gitea.lock'
10
13
  @suffix = options[:usersuffix]
11
14
  @controlrepo = options[:controlrepo]
12
15
  @reponame = File.basename(@controlrepo, '.git')
13
- @gitea_path = options[:gitea_path] || '/home/git/go/bin/gitea'
16
+ @repopath = "#{@cache_dir}/#{@reponame}"
17
+ @gitea_cmd = options[:gitea_cmd] || '/home/git/go/bin/gitea'
14
18
  @admin_username = options[:gitea_admin_username] || 'root'
15
19
  @admin_password = options[:gitea_admin_password] || 'puppetlabs'
16
- @gitea_port = options[:gitea_port] || '3000'
20
+ @gitea_port = options[:gitea_port] || '3000'
21
+ @gitea_user = options[:gitea_user] || 'git'
22
+ @gitea_homedir = Dir.home(@gitea_user)
17
23
 
18
- @cache_dir = '/var/cache/puppetfactory/gitea'
19
-
20
- if (!File.directory?("#{@cache_dir}/#{@reponame}"))
21
- $logger.info "Migrating repository #{@reponame}"
22
- begin
23
- `curl -su "#{@admin_username}:#{@admin_password}" --data "clone_addr=https://github.com/puppetlabs-education/#{@controlrepo}&uid=1&repo_name=#{@reponame}" http://localhost:#{@gitea_port}/api/v1/repos/migrate`
24
- FileUtils::mkdir_p @cache_dir
25
- Dir.chdir(@cache_dir) do
26
- `git clone --depth 1 http://#{@admin_username}:#{@admin_password}@localhost:#{@gitea_port}/#{@admin_username}/#{@controlrepo}`
27
- end
28
- rescue => e
29
- $logger.error "Error migrating repository: #{e.message}"
30
- return false
31
- end
32
- end
33
- end
34
-
35
- def add_collaborator(owner, repo, username, permission)
36
- `curl -su "#{@admin_username}:#{@admin_password}" -X PUT -H "Content-Type: application/json" -d '{"permissions":"#{permission}"}' http://localhost:#{@gitea_port}/api/v1/repos/#{owner}/#{repo}/collaborators/#{username}`
37
- end
38
-
39
- def make_branch(username)
40
- Dir.chdir("#{@cache_dir}/#{@reponame}") do
41
- `git checkout -b #{username} && git push origin #{username}`
42
- end
24
+ migrate_repo! unless File.directory?(@cache_dir)
43
25
  end
44
26
 
45
27
  def create(username, password)
46
28
  begin
47
- `su git -c "cd && #{@gitea_path} admin create-user --name #{username} --password #{password} --email #{username}@#{@suffix}"`
48
- add_collaborator(@admin_username, @reponame, username, 'write')
49
- make_branch(username)
50
- $logger.info "Created Gitea user #{username}."
29
+ # since we're changing directories, none of this can be done concurrently; lock it all.
30
+ #
31
+ # TODO: consider forking worker processes so that CWD doesn't leak between threads.
32
+ File.open(@lockfile, 'w') do |file|
33
+ file.flock(File::LOCK_EX)
34
+
35
+ make_user(username, password)
36
+ $logger.debug "Created Gitea user #{username}."
37
+ make_branch(username)
38
+ $logger.debug "Created Gitea branch #{username}."
39
+ add_collaborator(@admin_username, @reponame, username, 'write')
40
+ $logger.info "Created Gitea collaborator #{username}."
41
+ end
51
42
  rescue => e
52
- $logger.error "Error creating Gitea user #{username}: #{e.message}"
43
+ $logger.error "Error configuring Gitea for #{username}: #{e.message}"
44
+ $logger.error e.backtrace.join("\n")
53
45
  return false
54
46
  end
55
47
 
@@ -58,7 +50,7 @@ class Puppetfactory::Plugins::Gitea < Puppetfactory::Plugins
58
50
 
59
51
  def delete(username)
60
52
  begin
61
- `curl -su "#{@admin_username}:#{@admin_password}" -X "DELETE" http://localhost:#{@gitea_port}/api/v1/admin/users/#{username}`
53
+ remove_user(username)
62
54
  $logger.info "Removed Gitea user #{username}."
63
55
  rescue => e
64
56
  $logger.error "Error removing Gitea user #{username}: #{e.message}"
@@ -68,4 +60,73 @@ class Puppetfactory::Plugins::Gitea < Puppetfactory::Plugins
68
60
  true
69
61
  end
70
62
 
63
+ private
64
+ def migrate_repo!
65
+ FileUtils::mkdir_p @cache_dir
66
+ $logger.info "Migrating repository #{@reponame}"
67
+ begin
68
+ RestClient.post("http://#{@admin_username}:#{@admin_password}@localhost:#{@gitea_port}/api/v1/repos/migrate", {
69
+ 'clone_addr' => "https://github.com/puppetlabs-education/#{@controlrepo}",
70
+ 'uid' => 1,
71
+ 'repo_name' => @reponame,
72
+ })
73
+
74
+ # make sure the server has time to finish cloning from GitHub before cloning
75
+ sleep 5
76
+
77
+ Dir.chdir(@cache_dir) do
78
+ repo_uri = "http://#{@admin_username}:#{@admin_password}@localhost:#{@gitea_port}/#{@admin_username}/#{@controlrepo}"
79
+ output, status = Open3.capture2e('git', 'clone', '--depth', '1', repo_uri)
80
+ raise output unless status.success?
81
+ end
82
+
83
+ rescue => e
84
+ $logger.error "Error migrating repository: #{e.message}"
85
+ $logger.error e.backtrace.join("\n")
86
+ return false
87
+ end
88
+ end
89
+
90
+ def make_user(username, password)
91
+ Dir.chdir(@gitea_homedir) do
92
+ uid = Etc.getpwnam(@gitea_user).uid
93
+ pid = Process.fork do
94
+ ENV['USER'] = @gitea_user
95
+ Process.uid = uid
96
+ Process.euid = uid
97
+
98
+ output, status = Open3.capture2e(@gitea_cmd, 'admin', 'create-user',
99
+ '--name', username,
100
+ '--password', password,
101
+ '--email', "#{username}@#{@suffix}")
102
+
103
+ $logger.error output unless status.success?
104
+ exit status.exitstatus
105
+ end
106
+
107
+ pid, status = Process.wait2(pid)
108
+ raise "Error creating Gitea user #{username}" unless status.success?
109
+ end
110
+ end
111
+
112
+ def add_collaborator(owner, repo, username, permission)
113
+ repo_uri = "http://#{@admin_username}:#{@admin_password}@localhost:#{@gitea_port}/api/v1/repos/#{owner}/#{repo}/collaborators/#{username}"
114
+ RestClient.put(repo_uri, {'permissions' => permission}.to_json)
115
+ end
116
+
117
+ def make_branch(username)
118
+ Dir.chdir(@repopath) do
119
+ # use --force in case the branch already exists
120
+ output, status = Open3.capture2e('git', 'branch', '--force', username)
121
+ raise output unless status.success?
122
+
123
+ output, status = Open3.capture2e('git', 'push', 'origin', username)
124
+ raise output unless status.success?
125
+ end
126
+ end
127
+
128
+ def remove_user(username)
129
+ RestClient.delete("http://#{@admin_username}:#{@admin_password}@localhost:#{@gitea_port}/api/v1/admin/users/#{username}")
130
+ end
131
+
71
132
  end
@@ -14,6 +14,16 @@ footer {
14
14
  width: 100%;
15
15
  }
16
16
 
17
+ hr {
18
+ border: none;
19
+ border-top: 2px solid #222222;
20
+ margin: 2em 0 1em;
21
+ }
22
+
23
+ article {
24
+ margin: 6em 4em 2em 4em;
25
+ }
26
+
17
27
  a {
18
28
  text-decoration: none;
19
29
  color: #3880ff;
@@ -28,24 +38,31 @@ button:focus {
28
38
  outline: none;
29
39
  }
30
40
 
41
+ code {
42
+ background-color: #ddd;
43
+ border-bottom: 2px dotted #aaa;
44
+ padding: 0.25em;
45
+ }
46
+
31
47
  header {
32
48
  height: 4em;
33
49
  top: 0;
34
50
  }
35
51
 
52
+ header ul,
53
+ header li,
54
+ header a {
55
+ display: inline-block;
56
+ }
57
+
36
58
  header ul {
37
59
  margin: 0;
38
60
  padding: 0;
39
61
  list-style: none;
40
62
  }
41
63
 
42
- header li {
43
- float: left;
44
- padding: 1.2em 2em;
45
- }
46
-
47
- header li a {
48
- display: block;
64
+ header a {
65
+ margin: 1.2em 1em;
49
66
  color: #ffffff;
50
67
  }
51
68
 
@@ -55,13 +72,14 @@ a:hover {
55
72
 
56
73
  header a:hover,
57
74
  .ui-tabs-active a,
58
- #login:hover {
75
+ #admin-login:hover {
59
76
  color: #ffae1a;
60
77
  border-color: #ffae1a;
61
78
  }
62
79
 
63
80
  input[type="button"],
64
- .ui-dialog button {
81
+ .ui-dialog button,
82
+ .button {
65
83
  padding: .5em 1em;
66
84
  border: none;
67
85
  background-color: #ffae1a;
@@ -73,10 +91,6 @@ input[type="button"]:hover {
73
91
  opacity: .7;
74
92
  }
75
93
 
76
- article {
77
- margin: 6em 4em 2em 4em;
78
- }
79
-
80
94
  li {
81
95
  margin-bottom: .5em;
82
96
  }
@@ -95,10 +109,29 @@ tr:nth-child(2n+2) {
95
109
  background: #dedede;
96
110
  }
97
111
 
98
- .right {
99
- float: right;
112
+ input[type="text"],
113
+ input[type="password"] {
114
+ font-size: .8em;
115
+ width: 100%;
116
+ max-width: 100%;
117
+ padding: 8px 12px;
118
+ border: 2px solid #dedede;
119
+ outline: none;
120
+ }
121
+
122
+ input.fail {
123
+ background-color: #f88484;
124
+ border-color: #d63700;
100
125
  }
101
126
 
127
+ .flexrow { display: flex; }
128
+
129
+ .flex-7 { flex: 7; }
130
+ .flex-3 { flex: 3; }
131
+
132
+ .flex-right { margin-left: 1em; }
133
+ .flex-left { margin-right: 1em; }
134
+
102
135
  .ui-dialog {
103
136
  background-color: #ffffff;
104
137
  padding: 1em 2em;
@@ -111,85 +144,42 @@ tr:nth-child(2n+2) {
111
144
 
112
145
  #nav-logo {
113
146
  float: left;
114
- padding: 1em 2em;
147
+ padding: 1em 1em 1em 2em;
115
148
  height: 2em;
116
149
  }
117
150
 
118
- #login {
119
- color: transparent;
120
- background-color: transparent;
121
- }
122
-
123
- #userslist,
124
- #shellwrapper {
125
- display: none;
126
- }
127
-
128
- #usercontent {
129
- position: relative;
130
- }
131
-
132
- #newuserwrapper {
133
- margin-top: 2em;
151
+ #admin-login,
152
+ #admin-logout {
153
+ float: right;
154
+ margin: 1.2em 2em;
155
+ color: #ffffff;
134
156
  }
135
157
 
136
- #newuser {
158
+ #userslist {
137
159
  display: none;
138
- margin-top: 0.5em;
139
- padding: 1em;
140
160
  }
141
161
 
142
- #newuser div {
162
+ #user-wrapper div {
143
163
  margin: .5em 0;
144
164
  }
145
165
 
146
- #newuser.processing,
147
166
  #newuser.processing input {
148
167
  background: #dedede;
149
- color: #ffffff;
150
- border: none;
151
- }
152
-
153
- #newuser.processing {
154
- border-color: #565656;
155
- }
156
-
157
- #newuser label {
158
- display: inline-block;
159
- width: 6em;
168
+ border: #4e4e4e;
160
169
  }
161
170
 
162
- #newuser input[type="text"],
163
- #newuser input[type="password"] {
164
- font-family: 'Calibre-Regular', sans-serif;
165
- font-size: 1em;
166
- display: inline-block;
167
- box-sizing: border-box;
168
- width: 25%;
169
- max-width: 100%;
170
- padding: 8px 12px;
171
- line-height: 1em;
172
- border: 2px solid #dedede;
173
- outline: none;
174
- }
175
-
176
- #newuser input.fail {
177
- background: #f88484;
171
+ #user-wrapper h3 {
172
+ margin-top: 0;
178
173
  }
179
174
 
180
175
  #currentuser {
181
- margin-bottom: 4em;
176
+ margin-bottom: 1em;
182
177
  }
183
178
 
184
179
  #currentuser th.header {
185
- width: 10%;
186
- white-space: nowrap;
187
180
  text-align: right;
188
181
  padding-right: 1em;
189
182
  }
190
- #currentuser tr.actions {
191
- text-align: right;
192
- }
193
183
 
194
184
  #users {
195
185
  margin-top: 1em;
@@ -203,42 +193,20 @@ tr:nth-child(2n+2) {
203
193
  text-align: center;
204
194
  }
205
195
 
206
- #users td.select {
207
- font-size: 0.8em;
208
- }
209
-
210
196
  #console {
211
197
  width: 100%;
212
- height: 24em;
213
- resize: vertical;
214
- }
215
-
216
- #shell code {
217
- background-color: #ddd;
218
- border-bottom: 2px dotted #aaa;
219
- padding: 0.25em;
198
+ height: 36em;
220
199
  }
221
200
 
222
- #alternate,
223
201
  #explanation {
224
202
  display: none;
225
203
  }
226
204
 
227
- #show-alternate {
228
- float: right;
229
- margin-left: 0.5em;
230
- }
231
-
232
- #dashboard {
233
-
234
- }
235
-
236
- #dashboard #notifications {
237
- font-size: 0.5em;
205
+ #notifications {
238
206
  color: #666;
239
207
  }
240
208
 
241
- #dashboard #notifications.fail {
209
+ #notifications.fail {
242
210
  font-weight: bold;
243
211
  background-color: red;
244
212
  border: 1px solid black;
@@ -246,18 +214,13 @@ tr:nth-child(2n+2) {
246
214
  padding: 0.25em 0.5em;
247
215
  }
248
216
 
249
- #dashboard #tools {
217
+ #tools {
250
218
  float: right;
251
219
  top: 1em;
252
- font-size: 0.8em;
253
220
  margin-bottom: 0.5em;
254
221
  }
255
222
 
256
- #dashboard #tools * {
257
- font-size: 0.8em;
258
- }
259
-
260
- #dashboard #tools * .ui-button-text {
223
+ #tools * .ui-button-text {
261
224
  padding-top: 0.25em;
262
225
  padding-bottom: 0.25em;
263
226
  }
@@ -274,7 +237,6 @@ tr:nth-child(2n+2) {
274
237
  background-color: #ffdddd;
275
238
  border-radius: 0.25em;
276
239
  box-shadow: 0 2px 3px rgba(0, 0, 0, 0.25) inset;
277
- font-size: 0.8em;
278
240
  }
279
241
 
280
242
  #dashboard .gutter .label {
@@ -292,7 +254,6 @@ tr:nth-child(2n+2) {
292
254
  }
293
255
 
294
256
  #dashboard .completed a {
295
- font-size: 0.5em;
296
257
  text-decoration: none;
297
258
  }
298
259
 
@@ -300,7 +261,20 @@ tr:nth-child(2n+2) {
300
261
  border-bottom: 2px solid black;
301
262
  }
302
263
 
264
+ #logs .data {
265
+ font-family: monospace;
266
+ font-size: 1.2em;
267
+ white-space: pre-wrap;
268
+ }
269
+
303
270
  #gitviz {
304
271
  width: 100%;
305
272
  min-height: 600px;
306
273
  }
274
+
275
+ @media ( max-width: 1024px ) {
276
+ .flexrow { flex-direction: column; }
277
+
278
+ .flex-right { margin-left: 0; }
279
+ .flex-left { margin-right: 0; }
280
+ }
@@ -9,6 +9,7 @@ p {
9
9
 
10
10
  .container {
11
11
  padding: 0;
12
+ min-width: 1150px;
12
13
  }
13
14
 
14
15
  #menuwrapper {
@@ -16,12 +16,6 @@ $(document).ready(function(){
16
16
  return keepLoading;
17
17
  },
18
18
  });
19
-
20
- $('#login').button({
21
- icons: {
22
- primary: "ui-icon-locked"
23
- }
24
- });
25
19
  });
26
20
 
27
21
  function updatePage(name) {
@@ -32,5 +26,11 @@ function updatePage(name) {
32
26
  var idx = $("#tabs").tabs("option","active");
33
27
  }
34
28
 
35
- $("#tabs").tabs('load', idx);
29
+ // force a hard reload if we're already on the desired page
30
+ if ($("#tabs").tabs("option","active") == idx) {
31
+ location.reload(true);
32
+ }
33
+ else {
34
+ $("#tabs").tabs('load', idx);
35
+ }
36
36
  }
@@ -9,19 +9,6 @@ $(document).ready(function(){
9
9
  return true;
10
10
  };
11
11
 
12
- function open() {
13
- $('#showuser').hide();
14
- $('#newuserwrapper').addClass("open");
15
- $('#newuser').slideDown("fast");
16
- $('#user').focus();
17
- }
18
-
19
- function close() {
20
- $('#showuser').show();
21
- $('#newuserwrapper').removeClass("open");
22
- $('#newuser').hide();
23
- }
24
-
25
12
  function start_processing() {
26
13
  $('#newuser input[type=button]').attr("disabled", true);
27
14
  $('#newuser').addClass("processing");
@@ -48,15 +35,22 @@ $(document).ready(function(){
48
35
  close();
49
36
  });
50
37
 
51
- $('#users .select a').click(function(event){
38
+ $('#users .select a, #user-logout').click(function(event){
52
39
  event.preventDefault();
53
40
  var action = $(this).attr('href');
54
-
55
41
  $.get(action, function(data) {
56
42
  updatePage();
57
43
  });
58
44
  });
59
45
 
46
+ $('#login-submit').click(function (event) {
47
+ event.preventDefault();
48
+ var action = $(this).attr('href');
49
+ var user = $('#login-user').val();
50
+
51
+ $.get(action, {user: user});
52
+ });
53
+
60
54
  // save the new user
61
55
  $('#save').click(function(){
62
56
  var username = $('#user').val();
@@ -0,0 +1,51 @@
1
+ <div id="currentuser-wrapper">
2
+ <% if @current %>
3
+ <h3>Selected User</h3>
4
+ <table id="currentuser">
5
+ <tr><th class="header">Username:</th> <td><%= @current[:username] %></td></tr>
6
+ <tr><th class="header">Certname:</th> <td><%= @current[:certname] %></td></tr>
7
+ <% if @current[:port] -%>
8
+ <tr><th class="header">Webserver URL:</th> <td><a href="/port/<%= @current[:port] %>/"><%= @current[:url] %></a></td></tr>
9
+ <% end -%>
10
+ <% if @current[:container_status] -%>
11
+ <tr><th class="header">Container:</th> <td><%= @current[:container_status]['Description'] %></td></tr>
12
+ <% end -%>
13
+ <% if @current[:node_group_url] -%>
14
+ <tr><th class="header">Node Group:</th> <td><a href="https://<%= request.host %>/<%= @current[:node_group_url] %>" target="_console">Console login</a></td></tr>
15
+ <% end -%>
16
+ <% if @current[:controlrepo] -%>
17
+ <tr><th class="header">Control Repo:</th> <td><a href="<%= @current[:controlrepo] %>" target="_repository"><%= @current[:controlrepo] %></a></td></tr>
18
+ <% end -%>
19
+ <% if @current[:latestcommit] -%>
20
+ <tr><th class="header">Latest Commit:</th>
21
+ <td>
22
+ <a href="<%= @current[:latestcommit][:url] %>" target="_repository"><%= @current[:latestcommit][:message] %></a>
23
+ <small>(<%= @current[:latestcommit][:time] %>)</small>
24
+ </td></tr>
25
+ <% end -%>
26
+ <% if settings.plugins.include? :Dashboard -%>
27
+ <tr><th class="header">Spec Tests:</th> <td><a href="/dashboard/details/<%= @current[:username] %>" target="_results">results</a> <small>(may not always be available)</small></td></tr>
28
+ <% end -%>
29
+ <% if @current[:tree] -%>
30
+ <tr>
31
+ <th class="header">Environment Structure:</th>
32
+ <td><div id="tree"></div></td>
33
+ </tr>
34
+ <% end -%>
35
+ </table>
36
+ <% if action_enabled? :deploy -%>
37
+ <i class="fa"></i><input type="button" id="deploy" data-user="<%= @current[:username] %>" value="Deploy Environment">
38
+ <% end -%>
39
+ <div>
40
+ <a class="user-logout" href="/users/deactive">Logout</a>
41
+ </div>
42
+ <% end %>
43
+
44
+ <% if @current and @current[:tree] %>
45
+ <script type="text/javascript">
46
+ $(document).ready(function() {
47
+ $('#tree').jstree({ 'core': { 'data': <%= @current[:tree] %> } });
48
+ });
49
+ </script>
50
+ <% end %>
51
+ </div>
@@ -1,37 +1,59 @@
1
1
  <html>
2
2
  <head>
3
- <title>Puppet Training Classroom Manager</title>
4
- <link rel="stylesheet" type="text/css" href="font-awesome/css/font-awesome.min.css">
5
- <link rel="stylesheet" type="text/css" href="jstree-3.3.3/themes/default/style.min.css" />
6
- <link rel="stylesheet" type="text/css" href="css/style.css" />
7
- <script type="text/javascript" src="js/jquery.js"></script>
8
- <script type="text/javascript" src="js/jquery-ui.min.js"></script>
9
- <script type="text/javascript" src="js/scripts.js"></script>
10
- <script type="text/javascript" src="js/jquery.activity-indicator-1.0.0.min.js"></script>
11
- <script type="text/javascript" src="jstree-3.3.3/jstree.min.js"></script>
3
+ <title>PuppetFactory</title>
4
+ <link rel="stylesheet" type="text/css" href="font-awesome/css/font-awesome.min.css">
5
+ <link rel="stylesheet" type="text/css" href="jstree-3.3.3/themes/default/style.min.css" />
6
+ <link rel="stylesheet" type="text/css" href="css/style.css" />
7
+ <script type="text/javascript" src="js/jquery.js"></script>
8
+ <script type="text/javascript" src="js/jquery-ui.min.js"></script>
9
+ <script type="text/javascript" src="js/scripts.js"></script>
10
+ <script type="text/javascript" src="js/jquery.activity-indicator-1.0.0.min.js"></script>
11
+ <script type="text/javascript" src="jstree-3.3.3/jstree.min.js"></script>
12
+ <script type="text/javascript" src="js/usermanagement.js"></script>
12
13
  </head>
13
14
  <body>
14
15
  <div id="tabs">
15
16
  <header>
17
+ <img src="/images/Puppet-Logo-Mark-Amber-sm.png" alt="logo" id="nav-logo">
16
18
  <ul>
17
- <img src="/images/Puppet-Logo-Amber-White-sm.png" alt="logo" id="nav-logo">
18
- <li><a href="#home">Home</a></li>
19
- <li><a href="/users">Users</a></li>
20
- <li><a class="cache" href="/shell">SSH Login</a></li>
21
- <% @tabs.each do |url, title| %>
22
- <li><a href="/<%= url %>"><%= title %></a></li>
19
+ <li><a href="#home" class="cache">Home</a></li>
20
+ <% if privileged? %>
21
+ <li><a href="/users">Users</a></li>
22
+ <% @tabs.each do |url, title| %>
23
+ <li><a href="/<%= url %>"><%= title %></a></li>
24
+ <% end %>
23
25
  <% end %>
24
- <li class="right">
25
- <% unless privileged? %><a href="/login" id="login">Admin Login</a><% end %>
26
- </li>
27
26
  </ul>
27
+ <a href="http://<%= request.host %>:9090" target="_presentation">Presentation</a>
28
+ <a href="https://<%= request.host %>" target="_console">PE Console</a>
29
+ <% if settings.plugins.include? :Gitea -%>
30
+ <a href="http://<%= request.host %>:3000" target="_gitea">Code Repository</a>
31
+ <% end %>
32
+ <% if privileged? %>
33
+ <a href="/admin-logout" id="admin-logout">Logout</a>
34
+ <% else %>
35
+ <a href="/admin-login" id="admin-login">Admin Login</a>
36
+ <% end %>
28
37
  </header>
29
- <article>
30
- <h1>Puppet Training Classroom Manager</h1>
38
+ <article>
39
+ <h2>Puppet Classroom</h2>
31
40
  <div id="home">
32
- <%= erb :home %>
41
+ <div class="flexrow">
42
+ <div class="flex-7 flex-left">
43
+ <%= erb :shell %>
44
+ </div>
45
+ <div id="user-wrapper" class="flex-3 flex-right">
46
+ <% if @current %>
47
+ <%= erb :currentuser %>
48
+ <% else %>
49
+ <%= erb :newuser %>
50
+ <hr>
51
+ <%= erb :userlogin %>
52
+ <% end -%>
53
+ </div>
54
+ </div>
33
55
  </div>
34
- </article>
56
+ </article>
35
57
  </div>
36
58
  </body>
37
59
  </html>
@@ -14,7 +14,7 @@
14
14
 
15
15
  // use timeout instead of an interval so that in case of network error
16
16
  // we don't end up with a queue of requests stacked up.
17
- setTimeout(loadLogs, 5000);
17
+ setTimeout(function(){loadLogs}, 5000);
18
18
  });
19
19
  }
20
20
 
@@ -22,12 +22,3 @@
22
22
  loadLogs(true);
23
23
  });
24
24
  </script>
25
-
26
- <style>
27
- #logs .data {
28
- font-family: monospace;
29
- white-space: pre-wrap;
30
- height: 500px;
31
- overflow-y: scroll;
32
- }
33
- </style>
@@ -0,0 +1,19 @@
1
+ <div id="newuser">
2
+ <h3>Create a new user</h3>
3
+ <div>
4
+ <label for="user">Username:</label><input type="text" id="user" value="" />
5
+ </div>
6
+ <div>
7
+ <label for="password">Password:</label><input type="password" id="password" value="" />
8
+ </div>
9
+ <div>
10
+ <label for="password2">Repeat:</label><input type="password" id="password2" value="" />
11
+ </div>
12
+ <div>
13
+ <label for="session">Session ID:</label><input type="text" id="session" value="" />
14
+ <p></p>
15
+ </div>
16
+ <div>
17
+ <input type="button" id="save" value="Submit" />
18
+ </div>
19
+ </div>
@@ -1,35 +1,35 @@
1
1
  <div id="shell">
2
- <p>
3
- <input type="button" id="show-alternate" value="Other ways to log in" />
4
- Shell accounts have been created for each student for editing code and
5
- running Puppet interactively. Log in using the user account and credentials
6
- you created.
7
- </p>
8
- <p>
9
- <iframe id="console" src="/shell/login/"></iframe>
10
- </p>
11
- <div id="alternate" title="Alternate Login Methods">
12
- <p>
13
- If you prefer, you may also use any standard SSH client using the username
14
- and password you specified. Some common SSH clients include:
15
- <p>
2
+ <% if @current %>
3
+ <iframe id="console" src="/shell/login/"></iframe>
4
+ <% else %>
5
+ <p>
6
+ Welcome to the Puppet Classroom. Please log in or create a user account.
7
+ </p>
8
+ <p>
9
+ We will provision a Puppet agent node for you and you'll use it to complete labs and
10
+ exercises. This node can be accessed through a web terminal once you've logged in.
11
+ </p>
12
+ <p>
13
+ If you prefer, you may also use any standard SSH client using the username
14
+ and password you specified. Some common SSH clients include:
15
+ <p>
16
+ <ul>
17
+ <li>
18
+ Built-in to Mac OSX and Linux:
19
+ <ol>
20
+ <li>Start Terminal.app or any terminal emulator to get to the command line</li>
21
+ <li>Run <code>ssh <%= request.host %></code></li>
22
+ </ol>
23
+ </li>
24
+ <li>
25
+ Windows:
16
26
  <ul>
17
- <li>
18
- Built-in to Mac OSX and Linux:
19
- <ol>
20
- <li>Start Terminal.app or any terminal emulator to get to the command line</li>
21
- <li>Run <code>ssh <%= request.host %></code></li>
22
- </ol>
23
- </li>
24
- <li>
25
- Windows:
26
- <ul>
27
- <li><a href="http://the.earth.li/~sgtatham/putty/latest/x86/putty.exe">PuTTY</a></li>
28
- <li><a href="http://winscp.net/eng/download.php#download2" target="_new">WinSCP</a></li>
29
- <li><a href="http://www.vandyke.com/download/securecrt/download.html" target="_new">SecureCRT</a></li>
30
- </ul>
31
- </li>
27
+ <li><a href="https://github.com/PowerShell/Win32-OpenSSH/wiki/Install-Win32-OpenSSH">OpenSSH</a></li>
28
+ <li><a href="http://the.earth.li/~sgtatham/putty/latest/x86/putty.exe">PuTTY</a></li>
29
+ <li><a href="http://winscp.net/eng/download.php#download2" target="_new">WinSCP</a></li>
30
+ <li><a href="http://www.vandyke.com/download/securecrt/download.html" target="_new">SecureCRT</a></li>
32
31
  </ul>
33
- </div>
32
+ </li>
33
+ </ul>
34
+ <% end -%>
34
35
  </div>
35
- <script type="text/javascript" src="js/loginscripts.js"></script>
@@ -0,0 +1,9 @@
1
+ <div id="login">
2
+ <h3>Login</h3>
3
+ <div>
4
+ <label for="login-user">Username:</label><input type="text" id="login-user" value="" />
5
+ </div>
6
+ <div>
7
+ <a href="#" id="login-submit" class="button">Login</a>
8
+ </div>
9
+ </div>
@@ -1,43 +1,4 @@
1
1
  <div id="usercontent">
2
-
3
- <% if @current %>
4
- <h3>Selected User</h3>
5
- <table id="currentuser">
6
- <tr><th class="header">Username:</th> <td><%= @current[:username] %></td></tr>
7
- <tr><th class="header">Certname:</th> <td><%= @current[:certname] %></td></tr>
8
- <% if @current[:port] -%>
9
- <tr><th class="header">Webserver URL:</th> <td><a href="/port/<%= @current[:port] %>/"><%= @current[:url] %></a></td></tr>
10
- <% end -%>
11
- <% if @current[:container_status] -%>
12
- <tr><th class="header">Container:</th> <td><%= @current[:container_status]['Description'] %></td></tr>
13
- <% end -%>
14
- <% if @current[:node_group_url] -%>
15
- <tr><th class="header">Node Group:</th> <td><a href="https://<%= request.host %>/<%= @current[:node_group_url] %>" target="_console">Console login</a></td></tr>
16
- <% end -%>
17
- <% if @current[:controlrepo] -%>
18
- <tr><th class="header">Control Repo:</th> <td><a href="<%= @current[:controlrepo] %>" target="_repository"><%= @current[:controlrepo] %></a></td></tr>
19
- <% end -%>
20
- <% if @current[:latestcommit] -%>
21
- <tr><th class="header">Latest Commit:</th>
22
- <td>
23
- <a href="<%= @current[:latestcommit][:url] %>" target="_repository"><%= @current[:latestcommit][:message] %></a>
24
- <small>(<%= @current[:latestcommit][:time] %>)</small>
25
- </td></tr>
26
- <% end -%>
27
- <% if settings.plugins.include? :Dashboard -%>
28
- <tr><th class="header">Spec Tests:</th> <td><a href="/dashboard/details/<%= @current[:username] %>" target="_results">results</a> <small>(may not always be available)</small></td></tr>
29
- <% end -%>
30
- <% if action_enabled? :deploy -%>
31
- <tr class="actions"><td colspan=2><i class="fa"></i><input type="button" id="deploy" data-user="<%= @current[:username] %>" value="Deploy Environment"></td></tr>
32
- <% end -%>
33
- <% if @current[:tree] -%>
34
- <tr>
35
- <th class="header">Environment Structure:</th>
36
- <td><div id="tree"></div></td>
37
- </tr>
38
- <% end -%>
39
- </table>
40
- <% end %>
41
2
  <h3>All Users</h3>
42
3
  <table id="users">
43
4
  <tr class="header">
@@ -60,32 +21,3 @@
60
21
  <% end %>
61
22
  </table>
62
23
  </div>
63
-
64
- <div id="newuserwrapper">
65
- <input type="button" id="showuser" value="+ New User" />
66
- <div id="newuser">
67
- <div>
68
- <label for="user">Username:</label><input type="text" id="user" value="" />
69
- </div>
70
- <div>
71
- <label for="password">Password:</label><input type="password" id="password" value="" />
72
- </div>
73
- <div>
74
- <label for="password2">Repeat:</label><input type="password" id="password2" value="" />
75
- </div>
76
- <div>
77
- <label for="session">Session ID:</label><input type="text" id="session" value="" />
78
- </div>
79
- <input type="button" id="hideuser" value="Cancel" />
80
- <input type="button" id="save" value="Save" />
81
- </div>
82
- </div>
83
-
84
- <script type="text/javascript" src="js/usermanagement.js"></script>
85
- <% if @current and @current[:tree] %>
86
- <script type="text/javascript">
87
- $(document).ready(function() {
88
- $('#tree').jstree({ 'core': { 'data': <%= @current[:tree] %> } });
89
- });
90
- </script>
91
- <% end %>
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: puppetfactory
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.9
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Ford
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2017-09-20 00:00:00.000000000 Z
13
+ date: 2017-10-31 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: sinatra
@@ -225,12 +225,11 @@ files:
225
225
  - public/font-awesome/fonts/fontawesome-webfont.ttf
226
226
  - public/font-awesome/fonts/fontawesome-webfont.woff
227
227
  - public/font-awesome/fonts/fontawesome-webfont.woff2
228
- - public/images/Puppet-Logo-Amber-White-sm.png
228
+ - public/images/Puppet-Logo-Mark-Amber-sm.png
229
229
  - public/js/dashboard.js
230
230
  - public/js/jquery-ui.min.js
231
231
  - public/js/jquery.activity-indicator-1.0.0.min.js
232
232
  - public/js/jquery.js
233
- - public/js/loginscripts.js
234
233
  - public/js/scripts.js
235
234
  - public/js/usermanagement.js
236
235
  - public/jstree-3.3.3/jstree.js
@@ -248,11 +247,13 @@ files:
248
247
  - templates/init_scripts.erb
249
248
  - templates/puppet.conf.erb
250
249
  - templates/site.pp.erb
250
+ - views/currentuser.erb
251
251
  - views/dashboard.erb
252
- - views/home.erb
253
252
  - views/index.erb
254
253
  - views/logs.erb
254
+ - views/newuser.erb
255
255
  - views/shell.erb
256
+ - views/userlogin.erb
256
257
  - views/users.erb
257
258
  homepage: https://github.com/puppetlabs/puppetfactory
258
259
  licenses:
@@ -1,18 +0,0 @@
1
- $(document).ready(function(){
2
- $('#show-alternate').click( function(e) {
3
- e.preventDefault();
4
-
5
- $( "#alternate" ).dialog({
6
- title: $(this).attr("title"),
7
- buttons: {
8
- Ok: function() {
9
- $( this ).dialog( "close" );
10
- }
11
- },
12
- open: function () {
13
- $(this).parent().find('button:nth-child(1)').focus();
14
- },
15
- width: '500px',
16
- });
17
- });
18
- });
@@ -1,44 +0,0 @@
1
- <p>
2
- A simulated Puppet Enterprise infrastructure has been constructed on the
3
- classroom server. Each student has an environment providing a sandboxed
4
- container for Puppet code and configuration. The classroom server is also
5
- running the unmodified Puppet Enterprise Console with an account for each
6
- student.
7
- </p>
8
-
9
- <p>
10
- Students have full <code>root</code> access on their container, meaning that all
11
- Puppet commands and resources work as expected. Each container also exposes
12
- port 80 as a high port proxied from the Master, meaning that students are able
13
- to run a web server inside their sandbox environment. A link to this proxied
14
- port is listed for each user on the <em>Users</em> tab.
15
- </p>
16
-
17
- <h3>Resources:</h3>
18
- <ul>
19
- <li><a href="http://<%= request.host %>:9090" target="_showoff">Course Material Presentation</a>
20
- <ul>
21
- <li>Follow along with the instructor's slides, or navigate it independently.</li>
22
- </ul>
23
- </li>
24
- <li><a href="https://<%= request.host %>" target="_console">Puppet Enterprise Console</a>
25
- <ul>
26
- <li>Log into the PE Console using the credentials of the user account you created.</li>
27
- </ul>
28
- </li>
29
- <% if settings.plugins.include? :Gitea -%>
30
- <li><a href="http://<%= request.host %>:3000" target="_gitea">Git Repository Server</a>
31
- <ul>
32
- <li>Log into the Gitea server using the credentials of the user account you created.</li>
33
- </ul>
34
- </li>
35
- <% end -%>
36
- </ul>
37
-
38
- <h3>Accessing your environment:</h3>
39
-
40
- <ol>
41
- <li>First create your account on the <em>Users</em> tab.</li>
42
- <li>Log in to your sandbox following the directions on the <em>SSH Login</em> tab.</li>
43
- <li>Log in to the <a href="https://<%= request.host %>" target="_console">Puppet Enterprise Console</a></li>
44
- <ol>