Skip to content
Open

USAS #1069

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Shoko/shoko.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
96 changes: 96 additions & 0 deletions USAS/USAS.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<?php

namespace App\SupportedApps\USAS;

class USAS extends \App\SupportedApps implements \App\EnhancedApps
{
public $config;

// What the tile may show, short enough for its three columns. Anything else in the answer is
// ignored, so a spoofed answer can't put markup or other text on the dashboard.
private const PLAYBOOKS = [
"build-installer" => "ISO",
"provision" => "Install",
"baseline" => "Baseline",
"site" => "Site",
"keys" => "Keys",
];
private const RESULTS = [
"succeeded" => "OK",
"failed" => "Failed",
"stopped" => "Stopped",
"interrupted" => "Stopped",
];

public function __construct()
{
}

public function test()
{
$test = parent::appTest($this->url("api/status"), $this->getAttrs());
echo $test->status;
}

public function livestats()
{
$status = "inactive";
$data = [
"run_title" => "Run",
"run_value" => "-",
"vms" => "-",
"pending" => "-",
];

// GET /api/status (docs/interfaces.md#the-status-api in the USAS repository). execute() returns
// null when the connection fails and never throws for an error status.
$res = parent::execute($this->url("api/status"), $this->getAttrs());
if ($res === null || $res->getStatusCode() !== 200) {
return parent::getLiveStats($status, $data);
}
$body = json_decode($res->getBody());
if (!is_object($body) || ($body->schema ?? null) !== 1) {
return parent::getLiveStats($status, $data);
}

$running = $body->running ?? null;
$playbook = is_object($running) && is_string($running->playbook ?? null) ? $running->playbook : "";
if (isset(self::PLAYBOOKS[$playbook])) {
// Heimdall asks every 5 seconds while the status is active, every 30 otherwise.
$status = "active";
$data["run_title"] = "Now";
$data["run_value"] = self::PLAYBOOKS[$playbook];
} else {
$last = $body->last_run ?? null;
$result = is_object($last) && is_string($last->status ?? null) ? $last->status : "";
$data["run_value"] = is_object($last) ? (self::RESULTS[$result] ?? "-") : "None";
}

$vms = $body->vms ?? null;
if (is_object($vms) && is_int($vms->running ?? null) && is_int($vms->total ?? null)) {
$data["vms"] = $vms->running . "/" . $vms->total;
}
$servers = $body->servers ?? null;
if (is_object($servers) && is_int($servers->pending ?? null)) {
$data["pending"] = (string) $servers->pending;
}

return parent::getLiveStats($status, $data);
}

public function url($endpoint)
{
return parent::normaliseurl($this->config->url) . $endpoint;
}

private function getAttrs()
{
// The status token, made in USAS on the Account page. It goes only in this header, never in the URL.
return [
"headers" => [
"Accept" => "application/json",
"Authorization" => "Bearer " . trim($this->config->password ?? ""),
],
];
}
}
10 changes: 10 additions & 0 deletions USAS/app.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"appid": "a30b98c03a1facce720e0838722513881066a95f",
"name": "USAS",
"website": "https://github.com/HoneyBearTech/ubuntu-server-auto-setup",
"license": "MIT License",
"description": "USAS (Ubuntu Server Auto Setup) installs Ubuntu Server on new Proxmox VE VMs with nobody at the keyboard, loads the admin's GitHub SSH keys and applies a hardened baseline, from a web UI. The tile shows whether a run is going, how the last one ended, the cluster's running VMs and the servers still to install.",
"enhanced": true,
"tile_background": "dark",
"icon": "usas.svg"
}
15 changes: 15 additions & 0 deletions USAS/config.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<h2>{{ __('app.apps.config') }} ({{ __('app.optional') }}) @include('items.enable')</h2>
<div class="items">
<div class="input">
<label>{{ strtoupper(__('app.url')) }}</label>
{!! Form::text('config[override_url]', isset($item) ? $item->getconfig()->override_url : null, ['placeholder' => __('app.apps.override'), 'id' => 'override_url', 'class' => 'form-control']) !!}
</div>
<div class="input">
<label>Status token</label>
{!! Form::input('password', 'config[password]', '', ['placeholder' => 'usas_st_...', 'data-config' => 'password', 'class' => 'form-control config-item']) !!}
<p style="font-size: .8em;">Make it in USAS on the Account page, under <em>Status for dashboards</em>. It only reads the status.</p>
</div>
<div class="input">
<button style="margin-top: 32px;" class="btn test" id="test_config">Test</button>
</div>
</div>
14 changes: 14 additions & 0 deletions USAS/livestats.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<ul class="livestats">
<li>
<span class="title">{{ $run_title }}</span>
<strong>{{ $run_value }}</strong>
</li>
<li>
<span class="title">VMs</span>
<strong>{{ $vms }}</strong>
</li>
<li>
<span class="title">New</span>
<strong>{{ $pending }}</strong>
</li>
</ul>
1 change: 1 addition & 0 deletions USAS/usas.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion Verdaccio/verdaccio.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading