sync for dev 033026

This commit is contained in:
2026-03-30 19:59:39 -07:00
parent ba849b150c
commit 36917ffa39
18 changed files with 317 additions and 84 deletions

View File

@ -56,6 +56,7 @@ REAL_API_KEY: "{{ lookup('password', '/dev/null length=64 chars=ascii_letters,di
# dashboard vars # dashboard vars
service_control_web_folder: "{{ service_folder }}/web" service_control_web_folder: "{{ service_folder }}/web"
service_control_docker_folder: "{{ service_folder }}/docker"
public_dashboard: true public_dashboard: true
custom_port: "80" custom_port: "80"
web_src: "/web" web_src: "/web"
@ -63,19 +64,21 @@ web_src: "/web"
# other vars # other vars
quick_refresh: false quick_refresh: false
x64_arch: true x64_arch: true
refresh_special: false
special_server: "none"
# cosmostat_settings, will be for special_server defaults # cosmostat_settings, will be for special_server defaults
noisy_test: false noisy_test: false
debug_output: true debug_output: false
secure_api: true secure_api: true
push_redis: false push_redis: false
run_background : true run_background : true
log_output: true log_output: true
update_frequency: "1" update_frequency: "1"
cosmostat_server: true cosmostat_server: false
cosmostat_server_api: "https://cosmostat.testy-cal.com/" cosmostat_server_api: "https://cosmostat.matt-cloud.com/"
local_api_address: "http://{{ cosmostat_server_ip }}:{{ custom_api_port }}/" local_api_address: "http://{{ cosmostat_server_ip }}:{{ custom_api_port }}/"
cosmostat_server_reporter: false cosmostat_server_reporter: true
# setting this to true for default install # setting this to true for default install
disable_local_api: true disable_local_api: true
... ...

View File

@ -21,7 +21,8 @@ app_settings = {
"REAL_API_KEY": ''.join(secrets.choice(string.ascii_letters + string.digits) for _ in range(256)), "REAL_API_KEY": ''.join(secrets.choice(string.ascii_letters + string.digits) for _ in range(256)),
"disable_local_api": False, "disable_local_api": False,
"local_api_address": "http://10.200.27.20:5000/", "local_api_address": "http://10.200.27.20:5000/",
"cosmostat_server_ip": "10.200.27.20" "cosmostat_server_ip": "10.200.27.20",
"api_bind_ip": "192.168.37.1"
} }
with open('cosmostat_settings.yaml', 'r') as f: with open('cosmostat_settings.yaml', 'r') as f:
@ -71,10 +72,7 @@ def service_gateway_ip():
return result return result
def redis_gateway_ip(): def redis_gateway_ip():
if cosmostat_settings["secure_api"]:
return cosmostat_bind_ip() return cosmostat_bind_ip()
else:
return "0.0.0.0"
def cosmostat_server_api(): def cosmostat_server_api():
return cosmostat_settings["cosmostat_server_api"] return cosmostat_settings["cosmostat_server_api"]

View File

@ -170,11 +170,10 @@ def get_php_summary():
system_components.append(this_component) system_components.append(this_component)
if run_cosmostat_server(): if run_cosmostat_server():
print(cosmostat_client.name)
client_uuid = cosmostat_server.get_uuid_from_hostname(cosmostat_client.name) client_uuid = cosmostat_server.get_uuid_from_hostname(cosmostat_client.name)
print(client_uuid)
data_timestamp = cosmostat_server.get_system(client_uuid) data_timestamp = cosmostat_server.get_system(client_uuid)
print(data_timestamp) log_string = f"Cosmostat Client Name: {cosmostat_client.name} - UUID: {client_uuid}- Timestamp: {data_timestamp}"
log_data(log_output = log_string, log_level = "log_output")
component_age = { component_age = {
"component_name": "Data Timestamp", "component_name": "Data Timestamp",
"info_strings": f"Data is {data_timestamp} seconds old" "info_strings": f"Data is {data_timestamp} seconds old"
@ -221,7 +220,10 @@ def create_client():
if not cosmostat_server.check_uuid(payload["uuid"]): if not cosmostat_server.check_uuid(payload["uuid"]):
result = run_create_client(payload) result = run_create_client(payload)
else: else:
result = {"message": "object already exists, skipping creation"} result = {
"message": "object already exists, skipping creation",
"system_exists": "True"
}
return jsonify(result), 200 return jsonify(result), 200
# api to validate Cosmostat Class # api to validate Cosmostat Class
@ -280,6 +282,7 @@ def run_update_client(this_client):
return { return {
"status": update_status, "status": update_status,
"client_updated": "True",
"uuid": this_client["uuid"], "uuid": this_client["uuid"],
"redis_data": this_client, "redis_data": this_client,
"timestamp_update": timestamp_update "timestamp_update": timestamp_update
@ -296,6 +299,7 @@ def run_create_client(this_client):
update_status = f'created client {this_client["short_id"]}' update_status = f'created client {this_client["short_id"]}'
return { return {
"status": update_status, "status": update_status,
"client_created": "True",
"uuid": this_client["uuid"], "uuid": this_client["uuid"],
"client_properties": this_client, "client_properties": this_client,
"timestamp_update": timestamp_update "timestamp_update": timestamp_update
@ -372,13 +376,15 @@ def get_client_details():
# Cosmostat Client Reporter # Cosmostat Client Reporter
def client_update(): def client_update():
api_url = f"{cosmostat_server_api()}update_client" api_url = f"{cosmostat_server_api()}update_client"
print(api_url)
payload = get_client_payload(get_client_redis_data(human_readable = False), "redis_data") payload = get_client_payload(get_client_redis_data(human_readable = False), "redis_data")
log_data(log_output = f"API Update Called - {api_url}", log_level = "debug_output")
log_data(log_output = "client_update - redis data from local client:", log_level = "noisy_test") log_data(log_output = "client_update - redis data from local client:", log_level = "noisy_test")
log_data(log_output = payload, log_level = "noisy_test") log_data(log_output = payload, log_level = "noisy_test")
# execute API call # execute API call
result = client_submission_handler(api_url, payload) result = client_submission_handler(api_url, payload)
client_api_initialize() if not result or not result.get('client_updated'):
log_data(log_output = f"Client not updated, initializing", log_level = "log_output")
result = client_api_initialize()
return result return result
# Cosmostat Client Initializer # Cosmostat Client Initializer
@ -434,6 +440,7 @@ if __name__ == '__main__':
###################################### ######################################
### Main Functions ### Main Functions
###################################### ######################################
log_data(log_output = f"Main Function Start", log_level = "log_output")
# instantiate and return the Client System object # instantiate and return the Client System object
def new_cosmos_client(): def new_cosmos_client():
@ -480,9 +487,13 @@ if __name__ == '__main__':
###################################### ######################################
# local client System Class Object # local client System Class Object
log_data(log_output = f"Cosmostat Client Start", log_level = "log_output")
cosmostat_client = new_cosmos_client() cosmostat_client = new_cosmos_client()
cosmostat_client.update_system_state()
# remote client reporter # remote client reporter
if app_settings["cosmostat_server_reporter"] and not app_settings["cosmostat_server"]: if app_settings["cosmostat_server_reporter"] and not app_settings["cosmostat_server"]:
log_data(log_output = f"Initialize Client Reporter", log_level = "log_output")
client_api_initialize() client_api_initialize()
###################################### ######################################
@ -491,15 +502,19 @@ if __name__ == '__main__':
cosmostat_server = None cosmostat_server = None
if run_cosmostat_server(): if run_cosmostat_server():
log_data(log_output = f"Cosmostat Server Start", log_level = "log_output")
cosmostat_server = new_cosmostat_server() cosmostat_server = new_cosmostat_server()
this_client = get_client_payload(get_php_summary(), "client_properties") this_client = get_client_payload(get_php_summary(), "client_properties")
timestamp_update = cosmostat_server.add_system(system_dictionary = this_client) timestamp_update = cosmostat_server.add_system(system_dictionary = this_client)
# moving this here so all the bits exist
client_update()
###################################### ######################################
# send initial stats update to redis # send initial stats update to redis
###################################### ######################################
if app_settings["push_redis"] and not app_settings["disable_local_api"]: if app_settings["push_redis"] and not app_settings["disable_local_api"]:
log_data(log_output = f"Initial Redis Push", log_level = "log_output")
update_redis_server() update_redis_server()
###################################### ######################################
@ -507,6 +522,7 @@ if __name__ == '__main__':
###################################### ######################################
if app_settings["run_background"] and not app_settings["disable_local_api"]: if app_settings["run_background"] and not app_settings["disable_local_api"]:
log_data(log_output = f"Background Function Initializing", log_level = "log_output")
log_data(log_output = "Loading flask background subroutine...", log_level = "log_output") log_data(log_output = "Loading flask background subroutine...", log_level = "log_output")
scheduler.add_job(id='background_loop', scheduler.add_job(id='background_loop',
@ -523,16 +539,18 @@ if __name__ == '__main__':
###################################### ######################################
# Flask API # Flask API
###################################### ######################################
print(f"gateway: {service_gateway_ip()} - port: {service_api_port()}") log_data(log_output = f"gateway: {service_gateway_ip()} - port: {service_api_port()}", log_level = "log_output")
if not app_settings["disable_local_api"]: if not app_settings["disable_local_api"]:
log_data(log_output = f"Main API Start", log_level = "log_output")
app.run(debug=False, host=service_gateway_ip(), port=service_api_port()) app.run(debug=False, host=service_gateway_ip(), port=service_api_port())
else: else:
# if local API disabled, phone home if configured # if local API disabled, phone home if configured
print("Internal API Disabled.") log_data(log_output = f"Internal API Disabled", log_level = "log_output")
while True:
if int(time.time()) % 5 == 0 and not cosmostat_client.check_system_timer():
cosmostat_client.update_system_state() cosmostat_client.update_system_state()
client_update() client_update()
time.sleep(0.5) while True:
cosmostat_client.update_system_state()
client_update()
time.sleep(5)

View File

@ -91,7 +91,8 @@
"Clock Speed" "Clock Speed"
], ],
"php_extra" :[ "php_extra" :[
"CPU Model" "CPU Model",
"Core Count"
] ]
}, },
{ {
@ -236,12 +237,13 @@
"name": "DVD", "name": "DVD",
"description": "{Device Path} is a DVD or Virtual DVD drive.", "description": "{Device Path} is a DVD or Virtual DVD drive.",
"multi_check": "True", "multi_check": "True",
"device_list": "lsblk -d -o NAME,SIZE | grep sr0| awk '{print $1}'", "device_list": "lsblk -d -o NAME,SIZE | grep sr0 | awk '{print $1}'",
"properties": { "properties": {
"Device Name": "echo {this_device}", "Device Name": "echo {this_device}",
"Device Path": "lsblk -d -o NAME,SIZE | grep -v -e 0B -e NAME | awk '{{print \"/dev/\"$1}}' | grep {this_device}", "Device Path": "lsblk -d -o NAME,SIZE | grep -v -e 0B -e NAME | awk '{{print \"/dev/\"$1}}' | grep {this_device}",
"Total Capacity": "lsblk -d -o NAME,SIZE | grep {this_device} | awk '{{print $2}}'" "Total Capacity": "lsblk -d -o NAME,SIZE | grep {this_device} | awk '{{print $2}}'"
}, },
"precheck": "lspci | grep sr0 | wc -l",
"metrics": { "metrics": {
"placeholder": "" "placeholder": ""
} }

91
files/docker/Dockerfile Normal file
View File

@ -0,0 +1,91 @@
# ------------------------------------------------------------------
# 1. Base image
# ------------------------------------------------------------------
# We use a slim Debian base so we can use aptget to pull every
# component in one go. Debian Bookworm contains all the
# packages we need (nodejs 18, redis, nginx, php8fpm, etc.).
# ------------------------------------------------------------------
FROM php:8.0-apache
# ------------------------------------------------------------------
# 2. Build arguments handy if you want to change the port numbers
# without touching the Dockerfile
# ------------------------------------------------------------------
ARG REDIS_PORT=6379
ARG NODE_PORT=3000
ARG PHP_PORT=8080
ARG NGX_PORT=80
ENV REDIS_PORT=${REDIS_PORT}
ENV NODE_PORT=${NODE_PORT}
ENV PHP_PORT=${PHP_PORT}
ENV NGX_PORT=${NGX_PORT}
# ------------------------------------------------------------------
# 3. Install all the system packages we need
# ------------------------------------------------------------------
RUN apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y \
curl gnupg ca-certificates \
nodejs npm \
redis-server \
nginx \
supervisor \
&& apt-get clean && rm -rf /var/lib/apt/lists/*
# ------------------------------------------------------------------
# 4. Prepare the working directories
# ------------------------------------------------------------------
# Node app
WORKDIR /app
COPY web/node_server/package.json ./
RUN npm install
COPY web/node_server/ ./
# Webdashboard static files
COPY web/html /var/www/html/
# API settings file
COPY cosmostat_settings.yaml /app/cosmostat_settings.yaml
# Nginx config you can keep the same file you used for the
# proxy service in the compose file. It will proxy 3000 (WS)
# and 8080 (PHP) to the local container.
COPY web/proxy/nginx.conf /etc/nginx/nginx.conf
# ------------------------------------------------------------------
# 5. Supervisord configuration
# ------------------------------------------------------------------
# Create a minimal supervisord.conf that will launch the four
# services from the same container.
RUN mkdir -p /etc/supervisor/conf.d && \
cat > /etc/supervisor/conf.d/supervisord.conf <<EOF
[supervisord]
nodaemon=true
[program:redis]
command=/usr/bin/redis-server --port ${REDIS_PORT}
autostart=true
autorestart=true
user=root
[program:node]
command=npm run start
autostart=true
autorestart=true
user=root
[program:nginx]
command=/usr/sbin/nginx -g 'daemon off;'
autostart=true
autorestart=true
user=root
EOF
# ------------------------------------------------------------------
# 6. Expose the ports
# ------------------------------------------------------------------
EXPOSE ${REDIS_PORT} ${NGX_PORT}
# 7. Default command start supervisord
CMD ["supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"]

48
files/docker/Dockerfile-1 Normal file
View File

@ -0,0 +1,48 @@
FROM php:8.0-apache
RUN set -eux; \
apt-get update && apt-get install -y --no-install-recommends \
ca-certificates \
gnupg \
lsb-release \
wget \
curl \
sudo \
redis-server \
nginx \
supervisor \
&& curl -fsSL https://deb.nodesource.com/setup_18.x | bash - \
&& apt-get install -y --no-install-recommends nodejs \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
# Node application
COPY web/node_server/ .
RUN npm install --only=production
#RUN npm ci --production
# PHP static files (public web root)
COPY web/html/ /var/www/html/
# NGINX config (overwrites the default)
COPY web/proxy/nginx.conf /etc/nginx/conf.d/default.conf
# Shared settings file (readonly)
COPY cosmostat_settings.yaml /app/cosmostat_settings.yaml
# Supervisor configuration
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
# Entrypoint script
COPY entrypoint.sh /usr/local/bin/entrypoint.sh
RUN chmod +x /usr/local/bin/entrypoint.sh
EXPOSE 6379
EXPOSE 80
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
CMD ["supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"]

View File

@ -0,0 +1,6 @@
#!/bin/sh
# Ensure the shared config file is readable
chmod 644 /app/cosmostat_settings.yaml
# Let Supervisor do the heavy lifting
exec "$@"

View File

@ -0,0 +1,22 @@
[supervisord]
nodaemon=true
[program:redis]
command=/usr/bin/redis-server
stdout_logfile=/dev/stdout
stderr_logfile=/dev/stderr
[program:node]
command=sh -c "cd /app && node server.js"
stdout_logfile=/dev/stdout
stderr_logfile=/dev/stderr
[program:apache]
command=/usr/sbin/httpd -DFOREGROUND
stdout_logfile=/dev/stdout
stderr_logfile=/dev/stderr
[program:nginx]
command=nginx -g "daemon off;"
stdout_logfile=/dev/stdout
stderr_logfile=/dev/stderr

View File

@ -6,7 +6,7 @@ function h(string $s): string
} }
// Load API data // Load API data
$raw_api_settings = file('/opt/api_settings/cosmostat_settings.yaml', $raw_api_settings = file('/app/cosmostat_settings.yaml',
FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$api_settings = []; $api_settings = [];

View File

@ -15,25 +15,20 @@
pingTimeout: 5000, pingTimeout: 5000,
pingInterval: 25000, pingInterval: 25000,
}); });
/* ========================================================== /* ==========================================================
Color constants Color constants
========================================================== */ ========================================================== */
const GREEN = [ 39, 174, 96]; // #27ae60 const GREEN = [ 39, 174, 96]; // #27ae60
const YELLOW = [243, 156, 18]; // #f39c12 const YELLOW = [243, 156, 18]; // #f39c12
const RED = [192, 57, 43]; // #c0392b const RED = [192, 57, 43]; // #c0392b
/* ========================================================== /* ==========================================================
Helpers Helpers
========================================================== */ ========================================================== */
const hostTimestamps = {}; // keyed by short_id const hostTimestamps = {}; // keyed by short_id
const toRgb = (r, g, b) => `rgb(${r},${g},${b})`; const toRgb = (r, g, b) => `rgb(${r},${g},${b})`;
const T20 = 20 * 1000; const T20 = 20 * 1000;
const T40 = 40 * 1000; const T40 = 40 * 1000;
const T60 = 60 * 1000; const T60 = 60 * 1000;
function getFreshnessColor(ageMs) { function getFreshnessColor(ageMs) {
if (ageMs <= T20) { if (ageMs <= T20) {
return toRgb(...GREEN); return toRgb(...GREEN);
@ -54,19 +49,16 @@
} }
return toRgb(...RED); return toRgb(...RED);
} }
function safeSetText(id, txt) { function safeSetText(id, txt) {
const el = document.getElementById(id); const el = document.getElementById(id);
if (el) el.textContent = txt; if (el) el.textContent = txt;
} }
/* ========================================================== /* ==========================================================
Get the short_id from the query string Get the short_id from the query string
========================================================== */ ========================================================== */
function getSelectedId() { function getSelectedId() {
return new URLSearchParams(window.location.search).get('host') || ''; return new URLSearchParams(window.location.search).get('host') || '';
} }
/* ========================================================== /* ==========================================================
Sidebar building - uses short_id for status key Sidebar building - uses short_id for status key
========================================================== */ ========================================================== */
@ -75,30 +67,24 @@
const current = Array.from(ul.children).map(li => li.dataset.id); const current = Array.from(ul.children).map(li => li.dataset.id);
const newIds = systemList.map(s => s.short_id); const newIds = systemList.map(s => s.short_id);
if (arraysEqual(current, newIds)) return; if (arraysEqual(current, newIds)) return;
const selected = getSelectedId().toLowerCase(); const selected = getSelectedId().toLowerCase();
ul.innerHTML = ''; // reset list ul.innerHTML = ''; // reset list
systemList.forEach(item => { systemList.forEach(item => {
const li = document.createElement('li'); const li = document.createElement('li');
// status dot - keyed by short_id // status dot - keyed by short_id
const status = document.createElement('span'); const status = document.createElement('span');
status.className = 'host-status'; status.className = 'host-status';
status.dataset.id = item.short_id; status.dataset.id = item.short_id;
// link - display hostname, encode short_id in URL // link - display hostname, encode short_id in URL
const a = document.createElement('a'); const a = document.createElement('a');
a.href = '?host=' + encodeURIComponent(item.short_id); a.href = '?host=' + encodeURIComponent(item.short_id);
a.textContent = item.hostname; a.textContent = item.hostname;
if (item.short_id.toLowerCase() === selected) a.classList.add('active'); if (item.short_id.toLowerCase() === selected) a.classList.add('active');
li.appendChild(status); li.appendChild(status);
li.appendChild(a); li.appendChild(a);
ul.appendChild(li); ul.appendChild(li);
}); });
} }
/* ========================================================== /* ==========================================================
Update status colors every second Update status colors every second
========================================================== */ ========================================================== */
@ -113,9 +99,7 @@
if (span) span.style.backgroundColor = color; if (span) span.style.backgroundColor = color;
}); });
} }
setInterval(updateStatusColors, 1000); setInterval(updateStatusColors, 1000);
/* ========================================================== /* ==========================================================
Utility helpers Utility helpers
========================================================== */ ========================================================== */
@ -124,7 +108,6 @@
for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false; for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false;
return true; return true;
} }
function renderGenericTable(containerId, data, emptyMsg) { function renderGenericTable(containerId, data, emptyMsg) {
const container = document.getElementById(containerId); const container = document.getElementById(containerId);
if (!Array.isArray(data) || !data.length) { if (!Array.isArray(data) || !data.length) {
@ -138,7 +121,6 @@
container.innerHTML = ''; container.innerHTML = '';
container.appendChild(table); container.appendChild(table);
} }
function mergeRowsByName(rows) { function mergeRowsByName(rows) {
const groups = {}; // { Source: { Metric: [], Data: [] } } const groups = {}; // { Source: { Metric: [], Data: [] } }
rows.forEach(r => { rows.forEach(r => {
@ -156,7 +138,6 @@
Data: g.Data, Data: g.Data,
})); }));
} }
function orderRows(rows) { function orderRows(rows) {
const priority = ['System', 'CPU', 'RAM']; const priority = ['System', 'CPU', 'RAM'];
const map = {}; const map = {};
@ -167,7 +148,6 @@
return ai - bi; return ai - bi;
}); });
} }
function buildTable(rows) { function buildTable(rows) {
const cols = ['Source', 'Metric', 'Data']; const cols = ['Source', 'Metric', 'Data'];
const table = document.createElement('table'); const table = document.createElement('table');
@ -200,12 +180,10 @@
}); });
return table; return table;
} }
/* ========================================================== /* ==========================================================
Handle incoming data Handle incoming data
========================================================== */ ========================================================== */
let lastUpdate = Date.now(); let lastUpdate = Date.now();
function handleSummary(raw) { function handleSummary(raw) {
lastUpdate = Date.now(); // reset watchdog lastUpdate = Date.now(); // reset watchdog
let payload; let payload;
@ -215,25 +193,20 @@
return; return;
} }
} else payload = raw; } else payload = raw;
if (!Array.isArray(payload) || !payload.length) { if (!Array.isArray(payload) || !payload.length) {
safeSetText('client_summary', 'No data available'); safeSetText('client_summary', 'No data available');
return; return;
} }
// Build the list first (so <span> elements exist) // Build the list first (so <span> elements exist)
buildList(payload); buildList(payload);
// Store the timestamp for every short_id // Store the timestamp for every short_id
payload.forEach(hostObj => { payload.forEach(hostObj => {
if (hostObj.short_id && hostObj.data_timestamp) { if (hostObj.short_id && hostObj.data_timestamp) {
hostTimestamps[hostObj.short_id] = hostObj.data_timestamp; // seconds hostTimestamps[hostObj.short_id] = hostObj.data_timestamp; // seconds
} }
}); });
// Immediately update colors for the current view // Immediately update colors for the current view
updateStatusColors(); updateStatusColors();
// Metric table for selected host // Metric table for selected host
const selectedId = getSelectedId(); const selectedId = getSelectedId();
const hostObj = payload.find(h => h.short_id === selectedId) || payload[0]; const hostObj = payload.find(h => h.short_id === selectedId) || payload[0];
@ -242,7 +215,6 @@
: []; : [];
renderGenericTable('host_metrics', hostData, 'No Stats available'); renderGenericTable('host_metrics', hostData, 'No Stats available');
} }
/* ========================================================== /* ==========================================================
Socket event wiring Socket event wiring
========================================================== */ ========================================================== */
@ -258,7 +230,6 @@
safeSetText('client_summary', `Re-connected (attempt ${attempt})`); safeSetText('client_summary', `Re-connected (attempt ${attempt})`);
requestSummary(); requestSummary();
}); });
/* ========================================================== /* ==========================================================
Request logic Request logic
========================================================== */ ========================================================== */
@ -266,7 +237,6 @@
if (!socket.connected) return; // guard against stale emits if (!socket.connected) return; // guard against stale emits
socket.emit('get_client_summary'); // server will reply via client_summary socket.emit('get_client_summary'); // server will reply via client_summary
} }
/* ========================================================== /* ==========================================================
Recursive polling Recursive polling
========================================================== */ ========================================================== */
@ -279,7 +249,6 @@
socket.on('connect', () => { socket.on('connect', () => {
if (!pollTimer) pollLoop(); if (!pollTimer) pollLoop();
}); });
/* ========================================================== /* ==========================================================
Watchdog - force reconnect if no data for 15s Watchdog - force reconnect if no data for 15s
========================================================== */ ========================================================== */
@ -291,7 +260,6 @@
setTimeout(watchdog, 5000); setTimeout(watchdog, 5000);
} }
watchdog(); watchdog();
/* ========================================================== /* ==========================================================
Keep the 'active' link in sync when the URL changes Keep the 'active' link in sync when the URL changes
========================================================== */ ========================================================== */

View File

@ -39,7 +39,7 @@
<?php <?php
# load API settings, this requires a simple yaml file # load API settings, this requires a simple yaml file
$raw_api_settings = file('/opt/api_settings/cosmostat_settings.yaml', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); $raw_api_settings = file('/app/cosmostat_settings.yaml', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$api_settings = []; $api_settings = [];
foreach ($raw_api_settings as $line) { foreach ($raw_api_settings as $line) {
if ($line[0] === '#') { if ($line[0] === '#') {

View File

@ -13,6 +13,15 @@
state: stopped state: stopped
scope: user scope: user
# create service working folder
- name: Cosmostat - API - create cosmos user service folder
file:
path: "{{ user_service_folder }}"
state: directory
owner: "{{ service_user }}"
group: "{{ service_user }}"
mode: '0755'
- name: Cosmostat - API - copy api files - name: Cosmostat - API - copy api files
copy: copy:
src: api/ src: api/

View File

@ -59,6 +59,14 @@
# allow user services to "linger" # allow user services to "linger"
- name: Cosmostat - Init - cosmos user enable linger - name: Cosmostat - Init - cosmos user enable linger
shell: "loginctl enable-linger {{ service_user }}" shell: "loginctl enable-linger {{ service_user }}"
register: user_linger
# - name: Reboot target after linger change
# reboot:
# msg: "Cosmostat - Init - Rebooting target for linger enable"
# pre_reboot_delay: 10
# reboot_timeout: 600
# when: user_linger.changed
# create service working folder # create service working folder
- name: Cosmostat - Init - create cosmostat service folder - name: Cosmostat - Init - create cosmostat service folder

View File

@ -1,5 +1,11 @@
--- ---
# refresh when refresh
#- name: Quick refresh
# when: refresh_special | bool
# set_fact:
# quick_refresh: true
# initializa environment # initializa environment
- name: Initialize Environment - name: Initialize Environment
when: not quick_refresh | bool when: not quick_refresh | bool
@ -7,6 +13,7 @@
# set up API # set up API
- name: Build API - name: Build API
when: false
include_tasks: api.yaml include_tasks: api.yaml
# set up web stack # set up web stack

View File

@ -3,45 +3,64 @@
# This part sets up cosmostat web dashboard # This part sets up cosmostat web dashboard
############################################### ###############################################
- name: Cosmostat - Web - stop containers #- name: Cosmostat - Web - stop containers
when: not quick_refresh | bool # community.docker.docker_compose_v2:
shell: "docker-compose -f {{ service_control_web_folder }}/docker-compose.yaml down" # project_src: "{{ service_control_docker_folder }}"
ignore_errors: yes # state: stopped
# ignore_errors: yes
# Create web Folder # Create web Folder
- name: "Cosmostat - Web - create {{ service_control_web_folder }}" #- name: "Cosmostat - Web - create {{ service_control_web_folder }}"
file: # file:
path: "{{ service_control_web_folder }}" # path: "{{ service_control_web_folder }}"
state: directory # state: directory
mode: '0755' # mode: '0755'
owner: "{{ service_user }}" # owner: "{{ service_user }}"
group: "{{ service_user }}" # group: "{{ service_user }}"
- name: Cosmostat - Web - copy docker files - name: Cosmostat - Web - copy docker files
copy: copy:
src: "web/" src: "docker/"
dest: "{{ service_control_web_folder }}" dest: "{{ service_control_docker_folder }}"
mode: 0755 mode: 0755
owner: "{{ service_user }}" owner: "{{ service_user }}"
group: "{{ service_user }}" group: "{{ service_user }}"
- name: Cosmostat - Web - copy web files
copy:
src: "web/"
dest: "{{ service_control_docker_folder }}/web"
mode: 0755
owner: "{{ service_user }}"
group: "{{ service_user }}"
- name: Cosmostat - Web - template docker-compose.yaml
template:
src: docker-compose-single.yaml
dest: "{{ service_control_docker_folder }}/docker-compose.yaml"
mode: 0644
- name: "Cosmostat - Web - template cosmostat_settings.yaml"
template:
src: cosmostat_settings.yaml
dest: "{{ service_control_docker_folder }}/cosmostat_settings.yaml"
owner: "{{ service_user }}"
group: "{{ service_user }}"
mode: 0644
####################### #######################
# configure as server # configure as server
- name: Cosmostat - Web - Configure Server Dashboard - name: Cosmostat - Web - Configure Server Dashboard
when: cosmostat_server | bool when: cosmostat_server | bool
include_tasks: server.yaml include_tasks: server.yaml
- name: Cosmostat - Web - template docker-compose.yaml #- name: Cosmostat - Web - Start containers
template: # community.docker.docker_compose_v2:
src: docker-compose-php.yaml # project_src: "{{ service_control_web_folder }}"
dest: "{{ service_control_web_folder }}/docker-compose.yaml" # state: present
mode: 0644 # register: docker_output
#- debug: |
# msg="{{ docker_output.actions }}"
- name: Cosmostat - Web - Start containers
shell: "docker-compose -f {{ service_control_web_folder }}/docker-compose.yaml up -d"
register: docker_output
- debug: |
msg="{{ docker_output.stdout_lines }}"
msg="{{ docker_output.stderr_lines }}"
... ...

View File

@ -34,12 +34,11 @@ services:
- "{{ docker_gateway }}:8080:80" - "{{ docker_gateway }}:8080:80"
volumes: volumes:
- ./html:/var/www/html/ - ./html:/var/www/html/
- "{{ api_service_folder }}/cosmostat_settings.yaml:/opt/api_settings/cosmostat_settings.yaml:ro" - "{{ api_service_folder }}/cosmostat_settings.yaml:/app/cosmostat_settings.yaml:ro"
networks: networks:
- cosmostat_net - cosmostat_net
restart: always restart: always
# public_dashboard: {{ public_dashboard }}
cosmostat_nginx_proxy: cosmostat_nginx_proxy:
container_name: cosmostat_nginx_proxy container_name: cosmostat_nginx_proxy
image: nginx:latest image: nginx:latest

View File

@ -0,0 +1,35 @@
services:
# cosmostat:
# container_name: cosmostat
# build:
# context: .
# dockerfile: Dockerfile
# ports:
# - "{{ docker_gateway }}:6379:6379"
# - "{{ (docker_gateway + ':') if not public_dashboard | bool else '' }}{{ custom_port }}:80"
# networks:
# - cosmostat_net
# restart: always
cosmostat_all:
container_name: cosmostat_all
image: cosmostat-all:latest
restart: always
build:
context: .
dockerfile: Dockerfile
networks:
- cosmostat_net
ports:
- "{{ docker_gateway }}:6379:6379"
- "{{ (docker_gateway + ':') if not public_dashboard | bool else '' }}{{ custom_port }}:80"
volumes:
- "/opt/cosmostat/docker/web/html:/var/www/html"
- "/opt/cosmostat/docker/web/node_server:/app"
- "/opt/cosmostat/cosmostat_settings.yaml:/app/cosmostat_settings.yaml:ro"
networks:
cosmostat_net:
external: true

View File

@ -11,4 +11,4 @@ Restart=always
{{ extra_service_options }} {{ extra_service_options }}
[Install] [Install]
WantedBy=multi-user.target WantedBy=default.target