Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
slapos
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Tom Niget
slapos
Commits
4e15a53b
Commit
4e15a53b
authored
Mar 25, 2016
by
Alain Takoudjou
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
cleanup monitor2, allow to edit cors domain configurations
parent
e17666e2
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
80 additions
and
883 deletions
+80
-883
stack/monitor2/buildout.cfg
stack/monitor2/buildout.cfg
+3
-48
stack/monitor2/instance-monitor.cfg.jinja2.in
stack/monitor2/instance-monitor.cfg.jinja2.in
+3
-41
stack/monitor2/scripts/monitor-document.py
stack/monitor2/scripts/monitor-document.py
+43
-0
stack/monitor2/scripts/monitor.py
stack/monitor2/scripts/monitor.py
+31
-3
stack/monitor2/web/default-promise-interface.html
stack/monitor2/web/default-promise-interface.html
+0
-227
stack/monitor2/web/index.html
stack/monitor2/web/index.html
+0
-22
stack/monitor2/web/logout.html
stack/monitor2/web/logout.html
+0
-26
stack/monitor2/web/monitor-password-interface.html
stack/monitor2/web/monitor-password-interface.html
+0
-253
stack/monitor2/web/monitor.css
stack/monitor2/web/monitor.css
+0
-57
stack/monitor2/web/monitor.js
stack/monitor2/web/monitor.js
+0
-206
No files found.
stack/monitor2/buildout.cfg
View file @
4e15a53b
...
@@ -54,41 +54,6 @@ eggs +=
...
@@ -54,41 +54,6 @@ eggs +=
Jinja2
Jinja2
# Monitor html files
# XXX Can be removed from software release
[monitor-web-default-promise-interface]
<= monitor-web-base
filename = default-promise-interface.html
md5sum = eaedae330cd155f8b693b418286d0d98
[monitor-web-index-html]
<= monitor-web-base
filename = index.html
md5sum = 58fe6ada21d1b0b25a2a38374ec676d3
[monitor-web-monitor-css]
<= monitor-web-base
filename = monitor.css
md5sum = 3cb91de30c729143af78461431fc6f8c
[monitor-web-monitor-js]
<= monitor-web-base
filename = monitor.js
md5sum = 29ee4b9a99a7164581ccf5cbf75d33ba
[monitor-web-monitor-logout-page]
<= monitor-web-base
filename = logout.html
md5sum = b210c6842df541305d299081bc1bf81e
[monitor-password-promise-interface]
<= monitor-download-base
filename = monitor-password-interface.html
url = ${:_profile_base_location_}/web/${:filename}
md5sum = 04b664dfb47bfd3d01502768311aa239
# End Monitor web files
# Monitor templates files
# Monitor templates files
[monitor-httpd-conf]
[monitor-httpd-conf]
<= monitor-template-base
<= monitor-template-base
...
@@ -127,7 +92,7 @@ recipe = slapos.recipe.template:jinja2
...
@@ -127,7 +92,7 @@ recipe = slapos.recipe.template:jinja2
filename = template-monitor.cfg
filename = template-monitor.cfg
template = ${:_profile_base_location_}/instance-monitor.cfg.jinja2.in
template = ${:_profile_base_location_}/instance-monitor.cfg.jinja2.in
rendered = ${buildout:directory}/template-monitor.cfg
rendered = ${buildout:directory}/template-monitor.cfg
md5sum =
c26a0f81d67dd28b7150b97eb21b4f37
md5sum =
e439e22e754a50e1a3500cd4a995f6d8
context =
context =
key apache_location apache:location
key apache_location apache:location
key gzip_location gzip:location
key gzip_location gzip:location
...
@@ -139,16 +104,6 @@ context =
...
@@ -139,16 +104,6 @@ context =
raw monitor_instance_info ${monitor-instance-info:location}/${monitor-instance-info:filename}
raw monitor_instance_info ${monitor-instance-info:location}/${monitor-instance-info:filename}
raw monitor_globalstate ${monitor-globalstate:location}/${monitor-globalstate:filename}
raw monitor_globalstate ${monitor-globalstate:location}/${monitor-globalstate:filename}
raw monitor_password_promise_template ${monitor-password-promise:location}/${monitor-password-promise:filename}
raw monitor_password_promise_template ${monitor-password-promise:location}/${monitor-password-promise:filename}
raw monitor_password_cgi_template ${monitor-password-py-cgi:location}/${monitor-password-py-cgi:filename}
raw monitor_password_promise_interface_template ${monitor-password-promise-interface:location}/${monitor-password-promise-interface:filename}
raw monitor_web_default_promise_interface ${monitor-web-default-promise-interface:location}/${monitor-web-default-promise-interface:filename}
raw monitor_web_index_html ${monitor-web-index-html:location}/${monitor-web-index-html:filename}
raw monitor_web_monitor_css ${monitor-web-monitor-css:location}/${monitor-web-monitor-css:filename}
raw monitor_web_directory ${monitor-web-index-html:location}
key monitor_web_monitor_logout_cgi monitor-web-monitor-logout-cgi:rendered
raw monitor_web_monitor_logout_page ${monitor-web-monitor-logout-page:location}/${monitor-web-monitor-logout-page:filename}
raw monitor_web_monitor_promise_runner_cgi ${monitor-web-monitor-promise-runner-cgi:location}/${monitor-web-monitor-promise-runner-cgi:filename}
raw monitor_web_monitor_js ${monitor-web-monitor-js:location}/${monitor-web-monitor-js:filename}
raw curl_executable_location ${curl:location}/bin/curl
raw curl_executable_location ${curl:location}/bin/curl
raw dash_executable_location ${dash:location}/bin/dash
raw dash_executable_location ${dash:location}/bin/dash
raw dcron_executable_location ${dcron:location}/sbin/crond
raw dcron_executable_location ${dcron:location}/sbin/crond
...
@@ -165,7 +120,7 @@ context =
...
@@ -165,7 +120,7 @@ context =
[monitor2-bin]
[monitor2-bin]
<= monitor-template-script
<= monitor-template-script
filename = monitor.py
filename = monitor.py
md5sum =
af9eba3b4e7f265f9779874df6b94afb
md5sum =
927501a8c4ce8dcc39d55af1efdc66ed
[run-promise-py]
[run-promise-py]
recipe = slapos.recipe.template:jinja2
recipe = slapos.recipe.template:jinja2
...
@@ -199,7 +154,7 @@ md5sum = cc65aebd4c35b3172a7ca83abde761bc
...
@@ -199,7 +154,7 @@ md5sum = cc65aebd4c35b3172a7ca83abde761bc
[monitor-document-edit]
[monitor-document-edit]
<= monitor-template-script
<= monitor-template-script
filename = monitor-document.py
filename = monitor-document.py
md5sum =
e9a41ff86b3d598e8f72d22d2ff3f838
md5sum =
79c53518e53ae8c8487b09bb49bc7b80
[make-rss-script]
[make-rss-script]
...
...
stack/monitor2/instance-monitor.cfg.jinja2.in
View file @
4e15a53b
...
@@ -227,10 +227,10 @@ password = ${monitor-instance-parameter:password}
...
@@ -227,10 +227,10 @@ password = ${monitor-instance-parameter:password}
[monitor-httpd-conf-parameter]
[monitor-httpd-conf-parameter]
listening-ip = ${monitor-instance-parameter:monitor-httpd-ipv6}
listening-ip = ${monitor-instance-parameter:monitor-httpd-ipv6}
port = ${monitor-instance-parameter:monitor-httpd-port}
port = ${monitor-instance-parameter:monitor-httpd-port}
pid-file = ${directory:run}/httpd.pid
pid-file = ${directory:run}/
monitor-
httpd.pid
cgid-pid-file = ${directory:run}/cgid.pid
cgid-pid-file = ${directory:run}/cgid.pid
access-log = ${monitor-directory:log}/httpd-access.log
access-log = ${monitor-directory:log}/
monitor-
httpd-access.log
error-log = ${monitor-directory:log}/httpd-error.log
error-log = ${monitor-directory:log}/
monitor-
httpd-error.log
cert-file = ${ca-directory:certs}/httpd.crt
cert-file = ${ca-directory:certs}/httpd.crt
key-file = ${ca-directory:certs}/httpd.key
key-file = ${ca-directory:certs}/httpd.key
htpasswd-file = ${httpd-monitor-htpasswd:htpasswd-path}
htpasswd-file = ${httpd-monitor-htpasswd:htpasswd-path}
...
@@ -312,28 +312,6 @@ name = monitor-configurator
...
@@ -312,28 +312,6 @@ name = monitor-configurator
frequency = * * * * *
frequency = * * * * *
command = ${monitor-configurator-wrapper:wrapper-path}
command = ${monitor-configurator-wrapper:wrapper-path}
[monitor-web-directory]
recipe = plone.recipe.command
command = cp -f {{ monitor_web_directory }}/* ${monitor-directory:web-dir}
update-command = ${:command}
[monitor-web-monitor-logout-cgi]
recipe = slapos.recipe.template:jinja2
template = {{ monitor_web_monitor_logout_cgi }}
rendered = ${monitor-directory:cgi-bin}/monitor-logout.cgi
mode = 0755
context =
[monitor-web-monitor-promise-runner-cgi]
recipe = slapos.recipe.template:jinja2
template = {{ monitor_web_monitor_promise_runner_cgi }}
rendered = ${monitor-directory:cgi-bin}/monitor-run-promise.cgi
mode = 0755
context =
raw python_executable {{ python_executable }}
key promise_wrapper_folder monitor-directory:promise-wrapper
[monitor-httpd-promise]
[monitor-httpd-promise]
recipe = slapos.cookbook:check_url_available
recipe = slapos.cookbook:check_url_available
path = ${directory:promises}/${:filename}
path = ${directory:promises}/${:filename}
...
@@ -382,22 +360,6 @@ rendered = ${directory:monitor-promise}/${monitor-password-promise:filename}.cfg
...
@@ -382,22 +360,6 @@ rendered = ${directory:monitor-promise}/${monitor-password-promise:filename}.cfg
mode = 0644
mode = 0644
context = section parameter_dict monitor-password-promise-conf-parameter
context = section parameter_dict monitor-password-promise-conf-parameter
[monitor-password-cgi]
recipe = slapos.recipe.template:jinja2
template = {{ monitor_password_cgi_template }}
rendered = ${monitor-directory:cgi-bin}/monitor-password.cgi
context =
raw python_executable {{ python_executable }}
key password_changed_once_path monitor-password-parameter:password-changed-once-path
raw htpasswd_executable {{ apache_location }}/bin/htpasswd
key htpasswd_path httpd-monitor-htpasswd:htpasswd-path
[monitor-password-promise-interface]
recipe = slapos.recipe.template:jinja2
template = {{ monitor_password_promise_interface_template }}
rendered = ${monitor-directory:monitor-password-interface}/index.html
context =
[publish]
[publish]
<= monitor-base
<= monitor-base
monitor-base-url = ${monitor-conf-parameters:base-url}
monitor-base-url = ${monitor-conf-parameters:base-url}
...
...
stack/monitor2/scripts/monitor-document.py
View file @
4e15a53b
...
@@ -2,6 +2,7 @@
...
@@ -2,6 +2,7 @@
import
sys
import
sys
import
os
import
os
import
re
import
json
import
json
import
argparse
import
argparse
import
subprocess
import
subprocess
...
@@ -50,6 +51,46 @@ def htpasswdWrite(htpasswd_bin, parameter_dict, value):
...
@@ -50,6 +51,46 @@ def htpasswdWrite(htpasswd_bin, parameter_dict, value):
pfile
.
write
(
value
)
pfile
.
write
(
value
)
return
True
return
True
def
httpdCorsDomainWrite
(
httpd_cors_file
,
httpd_gracefull_bin
,
cors_domain
):
cors_string
=
""
cors_domain_list
=
cors_domain
.
split
()
old_httpd_cors_file
=
os
.
path
.
join
(
os
.
path
.
dirname
(
httpd_cors_file
),
'prev_%s'
%
os
.
path
.
basename
(
httpd_cors_file
)
)
if
os
.
path
.
exists
(
old_httpd_cors_file
)
and
os
.
path
.
isfile
(
old_httpd_cors_file
):
try
:
with
open
(
old_httpd_cors_file
,
'r'
)
as
cors_file
:
if
cors_file
.
read
()
==
cors_domain
:
return
True
except
OSError
,
e
:
print
"Failed to open file at %s.
\
n
%s"
%
(
old_httpd_cors_file
,
str
(
e
))
for
domain
in
cors_domain_list
:
if
cors_string
:
cors_string
+=
'|'
cors_string
+=
re
.
escape
(
domain
)
try
:
with
open
(
httpd_cors_file
,
'w'
)
as
file
:
file
.
write
(
'SetEnvIf Origin "^http(s)?://(.+
\
.)?(%s)$
"
origin_is=$0
\
n
'
%
cors_string
)
file
.
write
(
'Header always set Access-Control-Allow-Origin %{origin_is}e env=origin_is'
)
except
OSError
,
e
:
print
"ERROR while writing CORS changes to %s.
\
n
%s"
%
(
httpd_cors_file
,
str
(
e
))
return
False
# Save current cors domain list
try
:
with
open
(
old_httpd_cors_file
,
'w'
)
as
cors_file
:
cors_file
.
write
(
cors_domain
)
except
OSError
,
e
:
print
"Failed to open file at %s.
\
n
%s"
%
(
old_httpd_cors_file
,
str
(
e
))
return
False
# Restart httpd process
try
:
subprocess
.
call
(
httpd_gracefull_bin
)
except
OSError
,
e
:
print
"Failed to execute command %s.
\
n
%s"
%
(
httpd_gracefull_bin
,
str
(
e
))
return
False
def
applyEditChage
(
parser
):
def
applyEditChage
(
parser
):
parameter_tmp_file
=
os
.
path
.
join
(
parser
.
config_folder
,
'config.tmp.json'
)
parameter_tmp_file
=
os
.
path
.
join
(
parser
.
config_folder
,
'config.tmp.json'
)
...
@@ -83,6 +124,8 @@ def applyEditChage(parser):
...
@@ -83,6 +124,8 @@ def applyEditChage(parser):
result_dict
[
key
]
=
fileWrite
(
description_entry
[
'file'
],
new_parameter_list
[
i
][
'value'
])
result_dict
[
key
]
=
fileWrite
(
description_entry
[
'file'
],
new_parameter_list
[
i
][
'value'
])
elif
description_entry
[
'type'
]
==
'htpasswd'
:
elif
description_entry
[
'type'
]
==
'htpasswd'
:
result_dict
[
key
]
=
htpasswdWrite
(
parser
.
htpasswd_bin
,
description_entry
,
new_parameter_list
[
i
][
'value'
])
result_dict
[
key
]
=
htpasswdWrite
(
parser
.
htpasswd_bin
,
description_entry
,
new_parameter_list
[
i
][
'value'
])
elif
description_entry
[
'type'
]
==
'httpdcors'
:
result_dict
[
key
]
=
httpdCorsDomainWrite
(
description_entry
[
'cors_file'
],
description_entry
[
'gracefull_bin'
],
new_parameter_list
[
i
][
'value'
])
if
(
parser
.
output_cfg_file
):
if
(
parser
.
output_cfg_file
):
try
:
try
:
...
...
stack/monitor2/scripts/monitor.py
View file @
4e15a53b
...
@@ -120,7 +120,7 @@ class Monitoring(object):
...
@@ -120,7 +120,7 @@ class Monitoring(object):
return
config
return
config
def
readInstanceConfiguration
(
self
):
def
readInstanceConfiguration
(
self
):
type_list
=
[
'raw'
,
'file'
,
'htpasswd'
]
type_list
=
[
'raw'
,
'file'
,
'htpasswd'
,
'httpdcors'
]
configuration_list
=
[]
configuration_list
=
[]
if
not
self
.
parameter_list
:
if
not
self
.
parameter_list
:
...
@@ -152,14 +152,42 @@ class Monitoring(object):
...
@@ -152,14 +152,42 @@ class Monitoring(object):
if
config_list
[
0
]
==
'htpasswd'
:
if
config_list
[
0
]
==
'htpasswd'
:
if
len
(
config_list
)
!=
5
or
not
os
.
path
.
exists
(
config_list
[
4
]):
if
len
(
config_list
)
!=
5
or
not
os
.
path
.
exists
(
config_list
[
4
]):
print
'htpasswd file is not specified: %s'
%
str
(
config_list
)
print
'htpasswd file is not specified: %s'
%
str
(
config_list
)
return
continue
parameter
[
'description'
][
'user'
]
=
config_list
[
3
]
parameter
[
'description'
][
'user'
]
=
config_list
[
3
]
parameter
[
'description'
][
'htpasswd'
]
=
config_list
[
4
]
parameter
[
'description'
][
'htpasswd'
]
=
config_list
[
4
]
configuration_list
.
append
(
parameter
)
configuration_list
.
append
(
parameter
)
except
OSError
,
e
:
except
OSError
,
e
:
print
'Cannot read file %s, Error is: %s'
%
(
config_list
[
2
],
str
(
e
))
print
'Cannot read file %s, Error is: %s'
%
(
config_list
[
2
],
str
(
e
))
pass
pass
elif
config_list
[
0
]
==
'httpdcors'
and
os
.
path
.
exists
(
config_list
[
2
])
and
\
os
.
path
.
exists
(
config_list
[
3
]):
old_cors_file
=
os
.
path
.
join
(
os
.
path
.
dirname
(
config_list
[
2
]),
'prev_%s'
%
os
.
path
.
basename
(
config_list
[
2
])
)
try
:
cors_content
=
""
if
os
.
path
.
exists
(
old_cors_file
):
with
open
(
old_cors_file
)
as
cfile
:
cors_content
=
cfile
.
read
()
else
:
# Create empty file
with
open
(
old_cors_file
,
'w'
)
as
cfile
:
cfile
.
write
(
""
)
parameter
=
dict
(
key
=
config_list
[
1
],
title
=
config_list
[
1
],
value
=
cors_content
,
description
=
{
"type"
:
config_list
[
0
],
"cors_file"
:
config_list
[
2
],
"gracefull_bin"
:
config_list
[
3
]
}
)
configuration_list
.
append
(
parameter
)
except
OSError
,
e
:
print
'Cannot read file at %s, Error is: %s'
%
(
old_cors_file
,
str
(
e
))
pass
return
configuration_list
return
configuration_list
def
setupPromiseDictFromFolder
(
self
,
folder
):
def
setupPromiseDictFromFolder
(
self
,
folder
):
...
...
stack/monitor2/web/default-promise-interface.html
deleted
100644 → 0
View file @
e17666e2
<!DOCTYPE html>
<html>
<head>
<title>
Promise status
</title>
<style>
input
,
button
{
min-height
:
10mm
;
min-width
:
10mm
;
}
</style>
<script>
function
getServiceName
()
{
var
match
=
/
(?:
&|
\?)
service_name=
([^
&
]
*
)
/
.
exec
(
location
.
search
);
if
(
match
)
{
return
match
[
1
];
}
throw
new
Error
(
"
no service name found
"
);
}
var
service_name
=
getServiceName
(),
monitor_json_url
=
"
/monitor.haljson
"
,
status_json_url
=
"
/public/
"
+
service_name
+
"
.status.json
"
,
rerun_cgi_url
=
"
/cgi-bin/monitor-run-promise.cgi?service=
"
+
service_name
;
function
newDeferred
()
{
var
d
=
{
"
promise
"
:
undefined
,
"
resolve
"
:
undefined
,
"
reject
"
:
undefined
};
d
.
promise
=
new
Promise
(
function
(
resolve
,
reject
)
{
d
.
resolve
=
resolve
;
d
.
reject
=
reject
;
});
return
d
;
}
function
xhr
(
param
)
{
/*global XMLHttpRequest */
var
d
=
newDeferred
(),
xhr
=
new
XMLHttpRequest
(),
k
,
i
,
l
,
a
;
d
.
promise
.
cancel
=
function
()
{
xhr
.
abort
();
};
xhr
.
open
((
param
.
method
||
"
GET
"
).
toUpperCase
(),
param
.
url
,
true
);
xhr
.
responseType
=
param
.
responseType
||
""
;
if
(
param
.
withCredentials
!==
undefined
)
{
xhr
.
withCredentials
=
param
.
withCredentials
;
}
if
(
param
.
headers
)
{
a
=
Object
.
keys
(
param
.
headers
);
l
=
a
.
length
;
for
(
i
=
0
;
i
<
l
;
i
+=
1
)
{
k
=
a
[
i
];
xhr
.
setRequestHeader
(
k
,
param
.
headers
[
k
]);
}
}
xhr
.
addEventListener
(
"
load
"
,
function
(
e
)
{
var
r
,
t
=
e
.
target
,
callback
;
if
(
param
.
noStatusCheck
)
{
d
.
resolve
(
t
);
}
else
if
(
t
.
status
<
400
)
{
d
.
resolve
(
t
);
}
else
{
d
.
reject
(
new
Error
(
"
HTTP:
"
+
(
t
.
status
?
t
.
status
+
"
"
:
""
)
+
(
t
.
statusText
||
"
Unknown
"
)));
}
},
false
);
xhr
.
addEventListener
(
"
error
"
,
function
(
e
)
{
return
d
.
reject
(
new
Error
(
"
HTTP: Error
"
));
},
false
);
xhr
.
addEventListener
(
"
abort
"
,
function
(
e
)
{
return
d
.
reject
(
new
Error
(
"
HTTP: Aborted
"
));
},
false
);
xhr
.
send
(
param
.
data
);
return
d
.
promise
;
}
function
unexpectedError
(
reason
)
{
console
.
error
(
reason
);
alert
(
reason
);
}
function
PromiseStatusInterface
(
config
)
{
var
it
=
this
,
statusP
=
document
.
createElement
(
"
p
"
),
descriptionH2
=
document
.
createElement
(
"
h2
"
),
descriptionP
=
document
.
createElement
(
"
p
"
),
errorH2
=
document
.
createElement
(
"
h2
"
),
errorPre
=
document
.
createElement
(
"
pre
"
),
header
=
document
.
createElement
(
"
header
"
),
h1
=
document
.
createElement
(
"
h1
"
),
h2
=
document
.
createElement
(
"
h2
"
),
a
=
document
.
createElement
(
"
a
"
),
button
=
document
.
createElement
(
"
button
"
);
this
.
element
=
config
.
rootElement
||
document
.
createElement
(
"
div
"
);
this
.
statusP
=
statusP
;
this
.
descriptionP
=
descriptionP
;
this
.
errorH2
=
errorH2
;
this
.
errorPre
=
errorPre
;
this
.
element
.
appendChild
(
header
);
header
.
appendChild
(
a
);
a
.
setAttribute
(
"
tabindex
"
,
"
-1
"
);
a
.
setAttribute
(
"
href
"
,
"
/
"
);
a
.
appendChild
(
button
);
button
.
textContent
=
"
Home
"
;
a
=
document
.
createElement
(
"
a
"
);
button
=
document
.
createElement
(
"
button
"
);
header
.
appendChild
(
a
);
a
.
setAttribute
(
"
tabindex
"
,
"
-1
"
);
a
.
setAttribute
(
"
href
"
,
""
);
a
.
appendChild
(
button
);
button
.
textContent
=
"
Refresh
"
;
button
=
document
.
createElement
(
"
button
"
);
header
.
appendChild
(
button
);
button
.
textContent
=
"
Run promise now
"
;
button
.
onclick
=
function
()
{
this
.
runPromiseNow
();
}.
bind
(
this
);
this
.
runPromiseNowButton
=
button
;
this
.
element
.
appendChild
(
h1
);
h1
.
textContent
=
"
Promise status
"
;
this
.
element
.
appendChild
(
statusP
);
this
.
element
.
appendChild
(
descriptionH2
);
descriptionH2
.
textContent
=
"
Description
"
;
this
.
element
.
appendChild
(
descriptionP
);
this
.
element
.
appendChild
(
errorH2
);
errorH2
.
textContent
=
"
Error output
"
;
errorH2
.
style
.
display
=
"
none
"
;
this
.
element
.
appendChild
(
errorPre
);
errorPre
.
style
.
display
=
"
none
"
;
this
.
loadStatusUi
();
this
.
loadDescriptionUi
();
this
.
loadErrorUi
();
}
PromiseStatusInterface
.
prototype
.
loadStatusJson
=
function
()
{
if
(
this
.
status_json_promise
)
{
return
;
}
this
.
status_json_promise
=
Promise
.
resolve
().
then
(
function
()
{
return
xhr
({
url
:
status_json_url
,
withCredentials
:
true
,
responseType
:
"
json
"
});
}).
then
(
function
(
xhr
)
{
return
xhr
.
response
;
});
this
.
status_json_promise
.
catch
(
function
()
{
return
;
}).
then
(
function
()
{
setTimeout
(
function
()
{
delete
this
.
status_json_promise
;
}.
bind
(
this
),
1000
);
}.
bind
(
this
));
return
this
.
status_json_promise
;
};
PromiseStatusInterface
.
prototype
.
loadStatusUi
=
function
()
{
this
.
loadStatusJson
();
this
.
statusP
.
textContent
=
"
Loading status...
"
;
return
this
.
status_json_promise
.
then
(
function
(
status_json
)
{
if
(
status_json
.
status
===
"
OK
"
)
{
this
.
statusP
.
textContent
=
"
Status: OK.
"
;
}
else
{
this
.
statusP
.
textContent
=
"
Status: BAD (
"
+
status_json
.
status
+
"
).
"
;
}
if
(
status_json
.
message
)
{
this
.
statusP
.
appendChild
(
document
.
createTextNode
(
"
"
+
status_json
.
message
));
}
}.
bind
(
this
),
function
(
reason
)
{
var
message
=
reason
&&
(
reason
.
target
&&
(
reason
.
target
.
statusText
||
"
Unknown
"
)
||
reason
.
message
);
this
.
statusP
.
textContent
=
"
Status Json Error:
"
+
(
message
||
"
Unknown error
"
);
}.
bind
(
this
)).
catch
(
unexpectedError
);
};
PromiseStatusInterface
.
prototype
.
loadDescriptionUi
=
function
()
{
this
.
loadStatusJson
();
this
.
descriptionP
.
textContent
=
"
Loading description...
"
;
return
this
.
status_json_promise
.
then
(
function
(
status_json
)
{
if
(
status_json
.
description
)
{
this
.
descriptionP
.
textContent
=
status_json
.
description
;
}
else
{
this
.
descriptionP
.
textContent
=
"
No description
"
;
}
}.
bind
(
this
),
function
(
reason
)
{
var
message
=
reason
&&
(
reason
.
target
&&
(
reason
.
target
.
statusText
||
"
Unknown
"
)
||
reason
.
message
);
this
.
descriptionP
.
textContent
=
"
Status Json Error:
"
+
(
message
||
"
Unknown error
"
);
}.
bind
(
this
)).
catch
(
unexpectedError
);
};
PromiseStatusInterface
.
prototype
.
loadErrorUi
=
function
()
{
this
.
loadStatusJson
();
this
.
errorPre
.
textContent
=
"
Loading error output...
"
;
return
this
.
status_json_promise
.
then
(
function
(
status_json
)
{
if
(
status_json
.
error
)
{
this
.
errorH2
.
style
.
display
=
""
;
this
.
errorPre
.
style
.
display
=
""
;
this
.
errorPre
.
textContent
=
status_json
.
error
;
}
else
{
this
.
errorH2
.
style
.
display
=
"
none
"
;
this
.
errorPre
.
style
.
display
=
"
none
"
;
this
.
errorPre
.
textContent
=
""
;
}
}.
bind
(
this
),
function
(
reason
)
{
var
message
=
reason
&&
(
reason
.
target
&&
(
reason
.
target
.
statusText
||
"
Unknown
"
)
||
reason
.
message
);
this
.
errorPre
.
textContent
=
"
Status Json Error:
"
+
(
message
||
"
Unknown error
"
);
}.
bind
(
this
)).
catch
(
unexpectedError
);
};
PromiseStatusInterface
.
prototype
.
runPromiseNow
=
function
()
{
this
.
runPromiseNowButton
.
disabled
=
true
;
var
original_text
=
this
.
runPromiseNowButton
.
textContent
;
this
.
runPromiseNowButton
.
textContent
=
"
Sending message...
"
;
return
Promise
.
resolve
().
then
(
function
()
{
return
xhr
({
url
:
rerun_cgi_url
,
method
:
"
POST
"
,
withCredentials
:
true
});
}).
catch
(
unexpectedError
).
then
(
function
()
{
this
.
runPromiseNowButton
.
textContent
=
original_text
;
}.
bind
(
this
));
};
/*global setTimeout */
setTimeout
(
function
()
{
/*global document */
document
.
body
.
innerHTML
=
""
;
return
new
PromiseStatusInterface
({
rootElement
:
document
.
body
});
});
</script>
</head>
<body>
<h1>
Promise status
</h1>
<noscript>
Javascript should be enabled
</noscript>
</body>
</html>
stack/monitor2/web/index.html
deleted
100644 → 0
View file @
e17666e2
<!DOCTYPE html>
<html>
<head>
<meta
charset=
"utf-8"
>
<meta
http-equiv=
"X-UA-Compatible"
content=
"IE=edge"
>
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script
src=
"https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"
></script>
<!-- Latest compiled and minified CSS -->
<link
rel=
"stylesheet"
href=
"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css"
integrity=
"sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7"
crossorigin=
"anonymous"
>
<!-- Optional theme -->
<link
rel=
"stylesheet"
href=
"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap-theme.min.css"
integrity=
"sha384-fLW2N01lMqjakBkx3l/M9EahuwpSfeNvV63J5ezn3uZzapT0u7EYsXMjQV+0En5r"
crossorigin=
"anonymous"
>
<!-- Latest compiled and minified JavaScript -->
<script
src=
"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"
integrity=
"sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS"
crossorigin=
"anonymous"
></script>
<link
rel=
"stylesheet"
href=
"monitor.css"
/>
<script
src=
"monitor.js"
></script>
</head>
<body>
<noscript>
Please enable javascript on your browser to make this application to work.
</noscript>
</body>
</html>
stack/monitor2/web/logout.html
deleted
100644 → 0
View file @
e17666e2
<!DOCTYPE html>
<html>
<head><title>
Monitor logout
</title></head>
<body>
<noscript>
Cannot logout without javascript
</noscript>
<script>
var
logoutURL
=
"
/cgi-bin/monitor-logout.cgi
"
,
xhr
=
new
XMLHttpRequest
();
xhr
.
onload
=
function
()
{
if
(
xhr
.
status
===
401
)
{
document
.
body
.
innerHTML
=
"
<p>You are now logged out. You can go back to the monitor interface <a href=
\"
/
\"
>here</a>.</p>
"
;
}
else
{
console
.
error
(
"
Cannot logout (
"
+
xhr
.
status
+
"
)
"
);
document
.
body
.
innerHTML
=
"
<p>Cannot logout, retrying in 5 seconds.</p>
"
;
setTimeout
(
location
.
reload
.
bind
(
location
),
5000
);
}
};
xhr
.
onerror
=
function
()
{
document
.
body
.
innerHTML
=
"
<p>Cannot logout, please try again later.</p>
"
;
};
xhr
.
open
(
"
POST
"
,
logoutURL
,
true
,
"
logout
"
,
"
password
"
);
xhr
.
send
();
document
.
body
.
innerHTML
=
"
<p>Logging out...</p>
"
;
</script>
</body>
</html>
stack/monitor2/web/monitor-password-interface.html
deleted
100644 → 0
View file @
e17666e2
<!DOCTYPE html>
<html>
<head>
<meta
charset=
"utf-8"
/>
<title>
Monitor password
</title>
<style>
input
,
button
{
min-height
:
10mm
;
min-width
:
10mm
;
}
</style>
<script>
var
service_name
=
"
monitor-password
"
,
// XXX hardcoded
monitor_json_url
=
"
/monitor.haljson
"
,
status_json_url
=
"
/public/
"
+
service_name
+
"
.status.json
"
,
rerun_cgi_url
=
"
/cgi-bin/monitor-run-promise.cgi?service=
"
+
service_name
,
password_cgi_url_part
=
"
/cgi-bin/monitor-password.cgi?password=
"
;
function
newDeferred
()
{
var
d
=
{
"
promise
"
:
undefined
,
"
resolve
"
:
undefined
,
"
reject
"
:
undefined
};
d
.
promise
=
new
Promise
(
function
(
resolve
,
reject
)
{
d
.
resolve
=
resolve
;
d
.
reject
=
reject
;
});
return
d
;
}
function
xhr
(
param
)
{
/*global XMLHttpRequest */
var
d
=
newDeferred
(),
xhr
=
new
XMLHttpRequest
(),
k
,
i
,
l
,
a
;
d
.
promise
.
cancel
=
function
()
{
xhr
.
abort
();
};
if
(
param
.
username
)
{
xhr
.
open
((
param
.
method
||
"
GET
"
).
toUpperCase
(),
param
.
url
,
true
,
param
.
username
,
param
.
password
);
}
else
{
xhr
.
open
((
param
.
method
||
"
GET
"
).
toUpperCase
(),
param
.
url
,
true
);
}
xhr
.
responseType
=
param
.
responseType
||
""
;
if
(
param
.
withCredentials
!==
undefined
)
{
xhr
.
withCredentials
=
param
.
withCredentials
;
}
if
(
param
.
headers
)
{
a
=
Object
.
keys
(
param
.
headers
);
l
=
a
.
length
;
for
(
i
=
0
;
i
<
l
;
i
+=
1
)
{
k
=
a
[
i
];
xhr
.
setRequestHeader
(
k
,
param
.
headers
[
k
]);
}
}
xhr
.
addEventListener
(
"
load
"
,
function
(
e
)
{
var
r
,
t
=
e
.
target
,
callback
;
if
(
param
.
noStatusCheck
)
{
d
.
resolve
(
t
);
}
else
if
(
t
.
status
<
400
)
{
d
.
resolve
(
t
);
}
else
{
r
=
new
Error
(
"
HTTP:
"
+
(
t
.
status
?
t
.
status
+
"
"
:
""
)
+
(
t
.
statusText
||
"
Unknown
"
));
r
.
target
=
t
;
d
.
reject
(
r
);
}
},
false
);
xhr
.
addEventListener
(
"
error
"
,
function
(
e
)
{
return
d
.
reject
(
new
Error
(
"
HTTP: Error
"
));
},
false
);
xhr
.
addEventListener
(
"
abort
"
,
function
(
e
)
{
return
d
.
reject
(
new
Error
(
"
HTTP: Aborted
"
));
},
false
);
xhr
.
send
(
param
.
data
);
return
d
.
promise
;
}
function
unexpectedError
(
reason
)
{
console
.
error
(
reason
);
alert
(
reason
);
}
function
MonitorPasswordInterface
(
config
)
{
var
it
=
this
,
statusP
=
document
.
createElement
(
"
p
"
),
descriptionP
=
document
.
createElement
(
"
p
"
),
form
=
document
.
createElement
(
"
form
"
),
formPassword1Input
=
document
.
createElement
(
"
input
"
),
formPassword2Input
=
document
.
createElement
(
"
input
"
),
formChangePasswordButton
=
document
.
createElement
(
"
button
"
),
errorH2
=
document
.
createElement
(
"
h2
"
),
errorPre
=
document
.
createElement
(
"
pre
"
),
header
=
document
.
createElement
(
"
header
"
),
h1
=
document
.
createElement
(
"
h1
"
),
h2
=
document
.
createElement
(
"
h2
"
),
a
=
document
.
createElement
(
"
a
"
),
button
=
document
.
createElement
(
"
button
"
);
this
.
element
=
config
.
rootElement
||
document
.
createElement
(
"
div
"
);
this
.
statusP
=
statusP
;
this
.
descriptionP
=
descriptionP
;
this
.
formPassword1Input
=
formPassword1Input
;
this
.
formPassword2Input
=
formPassword2Input
;
this
.
formChangePasswordButton
=
formChangePasswordButton
;
this
.
errorH2
=
errorH2
;
this
.
errorPre
=
errorPre
;
this
.
element
.
appendChild
(
header
);
header
.
appendChild
(
a
);
a
.
setAttribute
(
"
tabindex
"
,
"
-1
"
);
a
.
setAttribute
(
"
href
"
,
"
/
"
);
a
.
appendChild
(
button
);
button
.
textContent
=
"
Home
"
;
a
=
document
.
createElement
(
"
a
"
);
button
=
document
.
createElement
(
"
button
"
);
header
.
appendChild
(
a
);
a
.
setAttribute
(
"
tabindex
"
,
"
-1
"
);
a
.
setAttribute
(
"
href
"
,
""
);
a
.
appendChild
(
button
);
button
.
textContent
=
"
Refresh
"
;
this
.
element
.
appendChild
(
h1
);
h1
.
textContent
=
"
Monitor password
"
;
this
.
element
.
appendChild
(
statusP
);
this
.
element
.
appendChild
(
descriptionP
);
this
.
element
.
appendChild
(
form
);
form
.
appendChild
(
formPassword1Input
);
formPassword1Input
.
setAttribute
(
"
type
"
,
"
password
"
);
form
.
onsubmit
=
this
.
onFormSubmit
.
bind
(
this
);
form
.
appendChild
(
document
.
createElement
(
"
br
"
));
form
.
appendChild
(
formPassword2Input
);
formPassword2Input
.
setAttribute
(
"
type
"
,
"
password
"
);
form
.
appendChild
(
document
.
createElement
(
"
br
"
));
form
.
appendChild
(
formChangePasswordButton
);
formChangePasswordButton
.
setAttribute
(
"
type
"
,
"
submit
"
);
formChangePasswordButton
.
textContent
=
"
Change password
"
;
this
.
element
.
appendChild
(
errorH2
);
errorH2
.
textContent
=
"
Operational error
"
;
errorH2
.
style
.
display
=
"
none
"
;
this
.
element
.
appendChild
(
errorPre
);
errorPre
.
style
.
display
=
"
none
"
;
this
.
loadStatusUi
();
this
.
loadDescriptionUi
();
this
.
loadErrorUi
();
}
MonitorPasswordInterface
.
prototype
.
loadStatusJson
=
function
()
{
if
(
this
.
status_json_promise
)
{
return
;
}
this
.
status_json_promise
=
Promise
.
resolve
().
then
(
function
()
{
return
xhr
({
url
:
status_json_url
,
withCredentials
:
true
,
responseType
:
"
json
"
});
}).
then
(
function
(
xhr
)
{
return
xhr
.
response
;
});
this
.
status_json_promise
.
catch
(
function
()
{
return
;
}).
then
(
function
()
{
setTimeout
(
function
()
{
delete
this
.
status_json_promise
;
}.
bind
(
this
),
1000
);
}.
bind
(
this
));
return
this
.
status_json_promise
;
};
MonitorPasswordInterface
.
prototype
.
loadStatusUi
=
function
()
{
this
.
loadStatusJson
();
this
.
statusP
.
textContent
=
"
Loading status...
"
;
return
this
.
status_json_promise
.
then
(
function
(
status_json
)
{
if
(
status_json
.
status
===
"
OK
"
)
{
this
.
statusP
.
innerHTML
=
"
"
;
}
else
{
this
.
statusP
.
textContent
=
"
/!
\\
The password needs to be changed at least once! /!
\\
"
;
}
}.
bind
(
this
),
function
(
reason
)
{
if
(
reason
&&
reason
.
target
&&
reason
.
target
.
status
===
404
)
{
this
.
statusP
.
textContent
=
"
/!
\\
The password needs to be changed at least once! /!
\\
"
;
return
;
}
var
message
=
reason
&&
(
reason
.
target
&&
(
reason
.
target
.
statusText
||
"
Unknown
"
)
||
reason
.
message
);
this
.
statusP
.
textContent
=
"
Status Json Error:
"
+
(
message
||
"
Unknown error
"
);
}.
bind
(
this
)).
catch
(
unexpectedError
);
};
MonitorPasswordInterface
.
prototype
.
loadDescriptionUi
=
function
()
{
this
.
descriptionP
.
textContent
=
[
"
The monitor password is the password used to connect to this interface.
"
,
"
Here you can change the monitor password by filling the formular just below.
"
].
join
(
"
\n
"
);
};
MonitorPasswordInterface
.
prototype
.
loadErrorUi
=
function
()
{
this
.
loadStatusJson
();
this
.
errorPre
.
textContent
=
"
Loading error output...
"
;
return
this
.
status_json_promise
.
then
(
function
(
status_json
)
{
if
(
status_json
.
error
)
{
this
.
errorH2
.
style
.
display
=
""
;
this
.
errorPre
.
style
.
display
=
""
;
this
.
errorPre
.
textContent
=
status_json
.
error
;
}
else
{
this
.
errorH2
.
style
.
display
=
"
none
"
;
this
.
errorPre
.
style
.
display
=
"
none
"
;
this
.
errorPre
.
textContent
=
""
;
}
}.
bind
(
this
),
function
(
reason
)
{
var
message
=
reason
&&
(
reason
.
target
&&
(
reason
.
target
.
statusText
||
"
Unknown
"
)
||
reason
.
message
);
this
.
errorPre
.
textContent
=
"
Status Json Error:
"
+
(
message
||
"
Unknown error
"
);
}.
bind
(
this
)).
catch
(
unexpectedError
);
};
MonitorPasswordInterface
.
prototype
.
onFormSubmit
=
function
(
event
)
{
event
.
preventDefault
();
event
.
stopPropagation
();
this
.
execForm
();
};
MonitorPasswordInterface
.
prototype
.
execForm
=
function
()
{
if
(
this
.
formPassword1Input
.
value
!==
this
.
formPassword2Input
.
value
)
{
this
.
statusP
.
textContent
=
"
The two typed passwords should match!
"
;
return
;
}
this
.
statusP
.
textContent
=
"
Changing password...
"
;
var
password
=
this
.
formPassword1Input
.
value
;
return
Promise
.
resolve
().
then
(
function
()
{
return
xhr
({
url
:
password_cgi_url_part
+
password
,
method
:
"
POST
"
,
withCredentials
:
true
});
}).
then
(
function
()
{
this
.
statusP
.
textContent
=
"
Password changed succesfully!
"
;
this
.
formPassword1Input
.
value
=
this
.
formPassword2Input
.
value
=
""
;
// rerun promise with new login (also does the relogin)
xhr
({
url
:
rerun_cgi_url
,
method
:
"
POST
"
,
withCredentials
:
true
,
username
:
"
admin
"
,
password
:
password
});
}.
bind
(
this
),
function
(
reason
)
{
var
message
=
reason
&&
(
reason
.
target
&&
(
reason
.
target
.
statusText
||
"
Unknown
"
)
||
reason
.
message
);
this
.
statusP
.
textContent
=
"
Status Json Error:
"
+
(
message
||
"
Unknown error
"
);
}.
bind
(
this
));
};
MonitorPasswordInterface
.
prototype
.
runPromiseNow
=
function
()
{
this
.
runPromiseNowButton
.
disabled
=
true
;
var
original_text
=
this
.
runPromiseNowButton
.
textContent
;
this
.
runPromiseNowButton
.
textContent
=
"
Sending message...
"
;
return
Promise
.
resolve
().
then
(
function
()
{
return
xhr
({
url
:
rerun_cgi_url
,
method
:
"
POST
"
,
withCredentials
:
true
});
}).
catch
(
unexpectedError
).
then
(
function
()
{
this
.
runPromiseNowButton
.
textContent
=
original_text
;
}.
bind
(
this
));
};
/*global setTimeout */
setTimeout
(
function
()
{
/*global document */
document
.
body
.
innerHTML
=
""
;
return
new
MonitorPasswordInterface
({
rootElement
:
document
.
body
});
});
</script>
</head>
<body>
<h1>
Monitor password
</h1>
<noscript>
Javascript should be enabled
</noscript>
</body>
</html>
stack/monitor2/web/monitor.css
deleted
100644 → 0
View file @
e17666e2
body
{
width
:
80vw
;
margin
:
auto
;
padding-top
:
1%
;
}
/* h1 { align-text: center; margin: auto; } */
/*td { padding: 0 2%; }/**/
td
{
padding
:
0
1em
;
}
/**/
table
{
border
:
1px
solid
black
;
}
table
>
table
{
margin-top
:
1em
;
}
input
{
box-sizing
:
border-box
;
min-height
:
10mm
;
min-width
:
10mm
;
}
button
{
box-sizing
:
border-box
;
min-height
:
10mm
;
min-width
:
10mm
;
background-color
:
lightgray
;
background
:
linear-gradient
(
180deg
,
#F6F6F6
0%
,
#DDDDDD
100%
);
border-radius
:
2px
;
border-style
:
solid
;
border-width
:
1px
;
border-color
:
#A4A4A4
;
}
a
.as-button
{
display
:
inline-block
;
box-sizing
:
border-box
;
min-height
:
10mm
;
min-width
:
10mm
;
padding
:
0.5em
0.5em
;
text-align
:
center
;
text-decoration
:
initial
;
}
a
.as-button
{
color
:
black
;
background-color
:
lightgray
;
background
:
linear-gradient
(
180deg
,
#F6F6F6
0%
,
#DDDDDD
100%
);
border-radius
:
2px
;
border-style
:
solid
;
border-width
:
1px
;
border-color
:
#A4A4A4
;
}
a
.as-button
:active
,
button
:active
{
background-color
:
white
;
background
:
linear-gradient
(
0deg
,
#F6F6F6
0%
,
#DDDDDD
100%
);
}
a
.as-button
:hover
,
button
:hover
{
border-color
:
#777777
;
}
.monitor-section
{
float
:
left
;
table-layout
:
fixed
;
margin-top
:
30px
;
margin-right
:
30px
;
}
\ No newline at end of file
stack/monitor2/web/monitor.js
deleted
100644 → 0
View file @
e17666e2
/*jslint indent:2 */
(
function
()
{
"
use strict
"
;
var
monitor_title
=
'
Monitoring interface
'
,
RSS_ICON_DATA_URI
=
[
"
data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIj8+CjwhRE9DVFlQR
"
,
"
SBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cu
"
,
"
dzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+CjxzdmcgeG1sbnM
"
,
"
9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2ZXJzaW9uPSIxLjEiIHdpZHRoPS
"
,
"
IxMjhweCIgaGVpZ2h0PSIxMjhweCIgdmlld0JveD0iMCAwIDI1NiAyNTYiPgo8cmVjd
"
,
"
CB3aWR0aD0iMjU2IiBoZWlnaHQ9IjI1NiIgeD0iMCIgIHk9IjAiICBmaWxsPSIjRjQ5
"
,
"
QzUyIi8+CjxjaXJjbGUgY3g9IjY4IiBjeT0iMTg5IiByPSIyNCIgZmlsbD0iI0ZGRiI
"
,
"
vPgo8cGF0aCBkPSJNMTYwIDIxM2gtMzRhODIgODIgMCAwIDAgLTgyIC04MnYtMzRhMT
"
,
"
E2IDExNiAwIDAgMSAxMTYgMTE2eiIgZmlsbD0iI0ZGRiIvPgo8cGF0aCBkPSJNMTg0I
"
,
"
DIxM0ExNDAgMTQwIDAgMCAwIDQ0IDczIFYgMzhhMTc1IDE3NSAwIDAgMSAxNzUgMTc1
"
,
"
eiIgZmlsbD0iI0ZGRiIvPgo8L3N2Zz4K
"
].
join
(
""
);
function
loadJson
(
url
)
{
/*global XMLHttpRequest */
return
new
Promise
(
function
(
resolve
,
reject
)
{
var
xhr
=
new
XMLHttpRequest
();
xhr
.
onload
=
function
(
event
)
{
var
response
=
event
.
target
;
if
(
response
.
status
<
400
)
{
try
{
var
data
=
(
response
.
responseType
===
'
text
'
||
response
.
responseType
===
''
)
?
JSON
.
parse
(
response
.
responseText
)
:
response
.
response
;
resolve
(
data
);
}
catch
(
e
)
{
reject
(
e
);
}
}
else
{
reject
(
new
Error
(
"
XHR:
"
+
response
.
status
+
"
:
"
+
response
.
statusText
));
}
};
xhr
.
onerror
=
function
()
{
reject
(
new
Error
(
"
XHR: Error
"
));
};
xhr
.
open
(
"
GET
"
,
url
,
true
);
xhr
.
send
();
});
}
///////////////////
// tools for HAL //
function
getProperty
(
object
,
path
)
{
if
(
Array
.
isArray
(
path
))
{
while
(
path
.
length
)
{
object
=
object
[
path
.
shift
()];
}
}
else
{
return
object
[
path
];
}
return
object
;
}
function
softGetProperty
(
object
,
path
)
{
try
{
return
getProperty
(
object
,
path
);
}
catch
(
ignored
)
{
return
undefined
;
}
}
function
forceList
(
value
)
{
if
(
Array
.
isArray
(
value
))
{
return
value
;
}
return
[
value
];
}
function
softGetPropertyAsList
(
object
,
path
)
{
try
{
return
forceList
(
getProperty
(
object
,
path
));
}
catch
(
ignored
)
{
return
[];
}
}
///////////////////
function
htmlToElementList
(
html
)
{
/*global document */
var
div
=
document
.
createElement
(
"
div
"
);
div
.
innerHTML
=
html
;
return
div
.
querySelectorAll
(
"
*
"
);
}
function
resolveUrl
(
firstUrl
)
{
/*jslint plusplus: true */
/*global URL, location */
var
l
=
arguments
.
length
,
i
=
1
,
url
=
new
URL
(
firstUrl
,
location
.
href
);
while
(
i
<
l
)
{
url
=
new
URL
(
arguments
[
i
++
],
url
);
}
return
url
.
href
;
}
function
joinUrl
(
url
,
path
)
{
if
(
path
&&
path
[
0
]
===
'
/
'
)
{
path
=
path
.
slice
(
1
);
}
if
(
url
.
indexOf
(
'
/
'
,
url
.
length
-
1
)
===
-
1
)
{
return
url
+
'
/
'
+
path
;
}
return
url
+
escapeHtml
(
path
);
}
function
escapeHtml
(
html
)
{
return
html
.
replace
(
/&/g
,
"
&
"
).
replace
(
/</g
,
"
<
"
).
replace
(
/>/g
,
"
>
"
).
replace
(
/"/g
,
"
"
"
).
replace
(
/'/g
,
"
'
"
);
}
function
loadAndRenderMonitorSection
(
root
,
monitor_dict
,
monitor_url
)
{
var
table
,
service_list
=
softGetPropertyAsList
(
monitor_dict
,
[
"
_embedded
"
,
"
service
"
]);
if
(
!
service_list
)
{
root
.
textContent
=
""
;
return
;
}
table
=
document
.
createElement
(
"
table
"
);
table
.
className
=
"
monitor-section
"
;
root
.
appendChild
(
table
);
return
Promise
.
all
(
service_list
.
map
(
function
(
service_dict
)
{
var
interface_url
=
softGetProperty
(
service_dict
,
[
"
_links
"
,
"
interface
"
,
"
href
"
]),
status_url
=
softGetProperty
(
service_dict
,
[
"
_links
"
,
"
status
"
,
"
href
"
]),
href_html_part
=
(
interface_url
?
"
href=
\"
"
+
escapeHtml
(
interface_url
)
+
"
\"
"
:
""
),
title_html_part
=
(
service_dict
.
title
?
escapeHtml
(
service_dict
.
title
)
:
(
service_dict
.
id
||
"
Untitled
"
)),
row
=
htmlToElementList
(
"
<table><tbody><tr><td><a
"
+
href_html_part
+
"
>
"
+
title_html_part
+
"
</a></td><td>Loading status...</td><td><a
"
+
href_html_part
+
"
><div style=
\"
height: 10mm; width: 10mm; background-color: gray;
\"
></div></a></td></tr></tbody></table>
"
);
table
.
appendChild
(
row
[
2
]);
if
(
!
status_url
)
{
row
[
5
].
textContent
=
"
No status
"
;
return
;
}
var
full_status_url
=
(
monitor_url
===
undefined
)
?
resolveUrl
(
monitor_url
,
status_url
):
joinUrl
(
monitor_url
,
status_url
);
return
loadJson
(
full_status_url
).
then
(
function
(
status_dict
)
{
if
(
status_dict
.
description
)
{
row
[
2
].
title
=
status_dict
.
description
;
}
row
[
5
].
textContent
=
status_dict
.
message
||
""
;
row
[
8
].
style
.
backgroundColor
=
status_dict
.
status
===
"
OK
"
?
"
green
"
:
"
red
"
;
}).
catch
(
function
(
reason
)
{
row
[
5
].
textContent
=
(
reason
&&
(
reason
.
name
+
"
:
"
+
reason
.
message
));
row
[
8
].
style
.
backgroundColor
=
"
red
"
;
});
}));
}
function
loadAndRenderMonitorJson
(
root
)
{
root
.
textContent
=
"
Loading monitor section...
"
;
return
loadJson
(
"
monitor.haljson
"
).
then
(
function
(
monitor_dict
)
{
//monitor_json_list.push(monitor_dict);
root
.
innerHTML
=
""
;
var
loading
=
loadAndRenderMonitorSection
(
root
,
monitor_dict
),
related_monitor_list
=
softGetPropertyAsList
(
monitor_dict
,
[
"
_links
"
,
"
related_monitor
"
]);
if
(
!
related_monitor_list
.
length
)
{
return
loading
;
}
return
Promise
.
all
([
loading
,
Promise
.
all
(
related_monitor_list
.
map
(
function
(
link
)
{
var
div
=
htmlToElementList
(
"
<div>Loading monitor section...</div>
"
)[
0
];
root
.
appendChild
(
div
);
if
(
link
.
href
[
link
.
href
.
length
-
1
]
!==
"
/
"
)
{
link
.
href
+=
"
/
"
;
}
var
haljson_link
=
resolveUrl
(
link
.
href
,
"
monitor.haljson
"
);
return
loadJson
(
haljson_link
).
catch
(
function
(
reason
)
{
div
.
textContent
=
(
reason
&&
(
reason
.
name
+
"
:
"
+
reason
.
message
));
}).
then
(
function
(
monitor_dict
)
{
//monitor_json_list.push(monitor_dict);
div
.
remove
();
return
loadAndRenderMonitorSection
(
root
,
monitor_dict
,
link
.
href
);
});
}))]);
});
}
function
bootstrap
(
root
)
{
var
element_list
=
htmlToElementList
([
"
<header>
"
,
"
<a href=
\"\"
class=
\"
as-button
\"
>Refresh</a>
"
,
"
<a href=
\"
/logout.html
\"
class=
\"
as-button
\"
>Logout</a>
"
,
"
<a href=
\"
/feed
\"
><img src=
\"
"
+
RSS_ICON_DATA_URI
+
"
\"
style=
\"
width: 10mm; height: 10mm; vertical-align: middle;
\"
alt=
\"
[RSS Feed]
\"
/></a>
"
,
"
</header>
"
,
"
<h1>
"
+
monitor_title
+
"
</h1>
"
,
"
<h2>System health status</h2>
"
,
"
<p>This interface allow to see the status of several features, it may show problems and sometimes provides a way to fix them.</p>
"
,
"
<p>Red square means the feature has a problem, green square means it is ok.</p>
"
,
"
<p>You can click on a feature below to get more precise information.</p>
"
].
join
(
"
\n
"
)),
div
=
document
.
createElement
(
"
div
"
),
tmp
;
[].
reduce
.
call
(
element_list
,
function
(
array
,
element
)
{
if
(
element
.
parentNode
.
parentNode
)
{
return
array
;
}
array
.
push
(
element
);
return
array
;
},
[]).
forEach
(
function
(
element
)
{
root
.
appendChild
(
element
);
});
document
.
title
=
monitor_title
;
root
.
appendChild
(
div
);
/*global alert */
tmp
=
loadAndRenderMonitorJson
(
div
);
tmp
.
catch
(
alert
);
/*global console */
tmp
.
catch
(
console
.
error
.
bind
(
console
));
}
/*global setTimeout */
setTimeout
(
function
()
{
/*global document */
bootstrap
(
document
.
body
);
});
}());
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment