puppetfactory 0.5.9 → 0.6.0

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