| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8"> |
| <title>cfg-checker agent</title> |
| {% include 'common_styles.j2' %} |
| {% include 'common_scripts.j2' %} |
| <script language="JavaScript"> |
| const getJSON = async url => { |
| const response = await fetch(url); |
| if(!response.ok) // check if response worked (no 404 errors etc...) |
| throw new Error(response.statusText); |
| |
| const data = response.json(); // get JSON from the response |
| return data; // returns a promise, which resolves to this data value |
| } |
| |
| function qStatus(uri, tagId) { |
| var dt, el; |
| |
| el = document.getElementById(tagId); |
| el.innerHTML = "calling " + uri; |
| |
| getJSON(uri).then(data => { |
| el.innerHTML = "<pre>" + JSON.stringify(data, null, ' ') + "</pre>"; |
| }).catch(error => { |
| el.innerHTML = JSON.stringify(error, null, ' '); |
| }); |
| }; |
| |
| function updateModules() { |
| var _n, _v, _hc, _s, _phead, _p; |
| |
| let mods = []; |
| // Jinja populated list |
| {% for mod in modules %} |
| mods.push("{{ mod }}"); |
| {% endfor %} |
| |
| mods.forEach((mod) => { |
| // get all ids needed to fill |
| _n = document.getElementById(mod + "_name"); |
| _v = document.getElementById(mod + "_version"); |
| _hc = document.getElementById(mod + "_healthcheck"); |
| _s = document.getElementById(mod + "_status"); |
| _phead = document.getElementById(mod + "_progress_head"); |
| _p = document.getElementById(mod + "_progress"); |
| |
| // Fill |
| _n.innerHTML = mod; |
| // get status |
| getJSON("api/" + mod).then(data => { |
| _v.innerHTML = data['healthcheck']['version']; |
| _hc.innerHTML = data['healthcheck']['ready']; |
| _s.innerHTML = data['status']; |
| if ((data['status'] == "idle") || (data['status'] == "finished")) { |
| if (_phead.className.indexOf("idle") < 0) { |
| _phead.className += " idle"; |
| } |
| } |
| else if (data['status'] == "running") { |
| _phead.className = _phead.className.replace(" idle", ""); |
| } |
| _p.style.width = data['progress'] + "%"; |
| }).catch(error => { |
| _v.innerHTML = "?"; |
| _hc.innerHTML = "No response"; |
| _s.innerHTML = "Unknown"; |
| _phead.className = _phead.className.replace(" idle", ""); |
| // set bar status to red later |
| //_p.style.width = "100%"; |
| }); |
| }) |
| }; |
| var interval = 500; |
| setInterval(updateModules, interval); |
| </script> |
| <style> |
| .barcontent { |
| margin: auto; |
| width: 1350px; |
| padding: 10px; |
| } |
| .bar-centered { |
| float: none; |
| transform: translate(25%); |
| } |
| .agent_labels { |
| display: inline-block; |
| margin: 0px; |
| margin-right: 5px; |
| |
| } |
| .info_label { |
| font-family: "LaoSangamMN", Monaco, monospace; |
| display: block; |
| float: left; |
| box-sizing: content-box; |
| background: #262; |
| color: white; |
| border-radius: 5px; |
| text-align: center; |
| padding: 0px 5px 5px 5px; |
| height: 14px; |
| margin: 5px 2px 5px 2px; |
| } |
| .gray_bg { background: #444; } |
| .section_head { font-size: 0.8em; color: Navy; padding-left: 2px; } |
| .row_button { |
| background-color: #468; |
| color: #fff; |
| cursor: pointer; |
| padding: 5px; |
| width: 100%; |
| border: none; |
| text-align: left; |
| outline: none; |
| font-size: 13px; |
| } |
| .row_button:after { |
| content: '\02795'; /* Unicode character for "plus" sign (+) */ |
| font-size: 13px; |
| color: white; |
| float: left; |
| margin-left: 5px; |
| } |
| |
| .row_active:after { |
| content: "\2796"; /* Unicode character for "minus" sign (-) */ |
| color: white |
| } |
| |
| .row_active, .row_button:hover { |
| background-color: #68a; |
| color: white |
| } |
| |
| .cell_button { |
| color: darkgreen; |
| cursor: pointer; |
| padding: 5px; |
| width: 100%; |
| border: none; |
| text-align: center; |
| outline: none; |
| } |
| .cell_button:hover { |
| background-color: gray; |
| } |
| |
| .tooltiptext { |
| transform: translate(100px); |
| } |
| |
| .console { |
| background-color: black; |
| font-family: "Lucida Console", Monaco, monospace; |
| font-size: 0.5em; |
| width: auto; |
| color: #fff; |
| border-radius: 6px; |
| padding: 5px 5px; |
| } |
| |
| .progress { |
| box-sizing: content-box; |
| height: 10px; /* Can be anything */ |
| position: relative; |
| background: #aaa; |
| border-radius: 5px; |
| padding: 5px; |
| box-shadow: inset 0 -1px 1px rgba(255, 255, 255, 0.3); |
| } |
| .progress > span { |
| display: block; |
| height: 100%; |
| border-top-right-radius: 3px; |
| border-bottom-right-radius: 3px; |
| border-top-left-radius: 5px; |
| border-bottom-left-radius: 5px; |
| background-color: rgb(43, 194, 83); |
| background-image: linear-gradient( |
| center bottom, |
| rgb(43, 194, 83) 37%, |
| rgb(84, 240, 84) 69% |
| ); |
| position: relative; |
| overflow: hidden; |
| } |
| .progress > span:after, |
| .animate > span > span { |
| content: ""; |
| position: absolute; |
| top: 0; |
| left: 0; |
| bottom: 0; |
| right: 0; |
| background-image: linear-gradient( |
| -45deg, |
| rgba(255, 255, 255, 0.1) 25%, |
| transparent 25%, |
| transparent 50%, |
| rgba(255, 255, 255, 0.1) 50%, |
| rgba(255, 255, 255, 0.1) 75%, |
| transparent 75%, |
| transparent |
| ); |
| z-index: 1; |
| background-size: 50px 50px; |
| animation: move 2s linear infinite; |
| border-top-right-radius: 8px; |
| border-bottom-right-radius: 8px; |
| border-top-left-radius: 20px; |
| border-bottom-left-radius: 20px; |
| overflow: hidden; |
| } |
| |
| .animate > span:after { |
| display: none; |
| } |
| |
| @keyframes move { |
| 0% { |
| background-position: 0 0; |
| } |
| 100% { |
| background-position: 50px 50px; |
| } |
| } |
| |
| .bluewish > span { |
| background-image: linear-gradient(#3d52b1, #3052b1); |
| } |
| .idle > span > span, |
| .idle > span::after { |
| background-image: none; |
| } |
| </style> |
| </head> |
| <body onload="init()"> |
| |
| <div class="header"> |
| <div class="label date">generated on: {{ gen_date }}</div> |
| </div> |
| |
| <div class="bar"> |
| <div class="bar-centered"> |
| <button class="bar-item" onclick="openBar(event, 'status')">Status</button> |
| </div> |
| </div> |
| |
| {% macro status_page(info, id_label) %} |
| <div id="{{ id_label }}" class="barcontent"> |
| <h5>{{ caller() }}</h5> |
| <hr> |
| <div class="agent_labels"> |
| <div class="info_label" onclick="updateModules()">{{ hostname }}</div> |
| <div class="info_label">{{ system }}</div> |
| <div class="info_label">{{ release }}</div> |
| <div class="info_label gray_bg">Started: {{ agent['started'] }}</div> |
| </div> |
| <hr> |
| {% for mod in modules %} |
| <div class="agent_labels"> |
| <div class="info_label" id="{{ mod }}_name">{{ mod }}</div> |
| <div class="info_label" id="{{ mod }}_version">unknown</div> |
| <div class="info_label" id="{{ mod }}_healthcheck">unknown</div> |
| <div class="info_label" id="{{ mod }}_status">unknown</div> |
| </div> |
| <div class="progress bluewish idle" id="{{ mod }}_progress_head"> |
| <span style="width: 0%" id="{{ mod }}_progress"></span> |
| </div> |
| <hr> |
| {% endfor %} |
| <div class="section_head">REST Api help:</div> |
| {% for uri, ops in help.items() %} |
| <div class="console"> |
| <div class="">{{ uri | escape }}</div> |
| {% for op, op_help in ops.items() %} |
| <div class="">{{ op }}: {{ op_help | escape }}</div> |
| {% endfor %} |
| </div> |
| <br> |
| {% endfor %} |
| <div class="section_head">Available modules: {{ modules | join(", ")}}</div> |
| <div class="section_head">Agent:</div> |
| <div class="console" onclick="qStatus('api/','agent')"> |
| <div class="" id="agent"></div> |
| </div> |
| |
| <div class="section_head">Status json:</div> |
| <div class="console" onclick="qStatus('api/{{ modules[0] }}','fio')"> |
| <div class="" id="fio"></div> |
| </div> |
| |
| |
| </div> |
| {% endmacro %} |
| |
| |
| {% call status_page(info, "status") %} |
| Agent status |
| {% endcall %} |
| </body> |
| </html> |