Beginnings of secret admin w/dialog

This commit is contained in:
Roberto Alsina 2024-07-03 20:54:19 -03:00
parent 1f02e0af11
commit 6d1651f3ec
9 changed files with 152 additions and 16 deletions

View File

@ -1,7 +1,7 @@
require "kemal" require "kemal"
# This is a kemal app, you can add handlers, middleware, etc. # This is a kemal app, you can add handlers, middleware, etc.
# A basic hello world get endpoint # A basic hello world get endpoint
get "/" do get "/" do
"Hello World Crystal!" "Hello World Crystal!"
@ -10,7 +10,7 @@ end
# The `/ping/` endpoint is configured in the container as a healthcheck # The `/ping/` endpoint is configured in the container as a healthcheck
# You can make it better by checking that your database is responding # You can make it better by checking that your database is responding
# or whatever checks you think are important # or whatever checks you think are important
# #
get "/ping/" do get "/ping/" do
"OK" "OK"
end end

52
public/bars.svg Normal file
View File

@ -0,0 +1,52 @@
<svg width="16" height="16" viewBox="0 0 135 140" xmlns="http://www.w3.org/2000/svg" fill="#494949">
<rect y="10" width="15" height="120" rx="6">
<animate attributeName="height"
begin="0.5s" dur="1s"
values="120;110;100;90;80;70;60;50;40;140;120" calcMode="linear"
repeatCount="indefinite" />
<animate attributeName="y"
begin="0.5s" dur="1s"
values="10;15;20;25;30;35;40;45;50;0;10" calcMode="linear"
repeatCount="indefinite" />
</rect>
<rect x="30" y="10" width="15" height="120" rx="6">
<animate attributeName="height"
begin="0.25s" dur="1s"
values="120;110;100;90;80;70;60;50;40;140;120" calcMode="linear"
repeatCount="indefinite" />
<animate attributeName="y"
begin="0.25s" dur="1s"
values="10;15;20;25;30;35;40;45;50;0;10" calcMode="linear"
repeatCount="indefinite" />
</rect>
<rect x="60" width="15" height="140" rx="6">
<animate attributeName="height"
begin="0s" dur="1s"
values="120;110;100;90;80;70;60;50;40;140;120" calcMode="linear"
repeatCount="indefinite" />
<animate attributeName="y"
begin="0s" dur="1s"
values="10;15;20;25;30;35;40;45;50;0;10" calcMode="linear"
repeatCount="indefinite" />
</rect>
<rect x="90" y="10" width="15" height="120" rx="6">
<animate attributeName="height"
begin="0.25s" dur="1s"
values="120;110;100;90;80;70;60;50;40;140;120" calcMode="linear"
repeatCount="indefinite" />
<animate attributeName="y"
begin="0.25s" dur="1s"
values="10;15;20;25;30;35;40;45;50;0;10" calcMode="linear"
repeatCount="indefinite" />
</rect>
<rect x="120" y="10" width="15" height="120" rx="6">
<animate attributeName="height"
begin="0.5s" dur="1s"
values="120;110;100;90;80;70;60;50;40;140;120" calcMode="linear"
repeatCount="indefinite" />
<animate attributeName="y"
begin="0.5s" dur="1s"
values="10;15;20;25;30;35;40;45;50;0;10" calcMode="linear"
repeatCount="indefinite" />
</rect>
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -1,15 +1,23 @@
<!DOCTYPE html> <!DOCTYPE html>
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<link rel="stylesheet" href="https://matcha.mizu.sh/matcha.css" /> <link rel="stylesheet" href="https://matcha.mizu.sh/matcha.css" />
<script src="https://unpkg.com/htmx.org@2.0.0"></script> <script src="https://unpkg.com/htmx.org@2.0.0"></script>
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
</head> </head>
<body> <body>
<header class="container"> <header class="container">
<h1>Your Funko Collection</h1> <h1>FaaSO Admin Interface</h1>
</header> </header>
<main class=container> <main class=container>
<h2>Your Funko Collection
<button id="update-funkos" style="float:right; display:inline;" hx-trigger="load, click, every 60s"
hx-get="funkos/?format=html" hx-target="#funko-list">
Refresh
</button>
</h2>
<span id="message"></span> <span id="message"></span>
<table hx-target="#message"> <table hx-target="#message">
<thead> <thead>
@ -24,12 +32,60 @@
<tbody id="funko-list"> <tbody id="funko-list">
</tbody> </tbody>
</table> </table>
<button id="update-funkos" style="float:right;" hx-trigger="load, click, every 60s" hx-get="funkos/?format=html"
hx-target="#funko-list">Update</button>
</main> </main>
<script> <script>
update_funkos =function() { update_funkos = function () {
document.getElementById("update-funkos").click() document.getElementById("update-funkos").click()
} }
</script> </script>
</body> <main class=container>
<h2>
Your Secrets
<button id="update-secrets" style="float:right; display:inline;" hx-trigger="load, click, every 60s"
hx-get="secrets/?format=html" hx-target="#secret-list">
Refresh
</button>
<button style="float:right; display:inline;" onclick="show_new_secret()">
Add
</button>
</h2>
<span id="message"></span>
<table hx-target="#message">
<thead>
<tr>
<th>Funko</th>
<th>Name</th>
<th>Actions</th>
</tr>
</thead>
<tbody id="secret-list">
</tbody>
<dialog id="add-secret">
<topic>New Secret</topic>
<form hx-post="secrets/">
<input placeholder="funko name" id="new-secret-funko" name="funko">
<input placeholder="secret name" id="new-secret-name" name="name">
<input placeholder="secret value" type="password" id="new-secret-password" name="value">
<button type="submit" hx-on:htmx:after-request="update_secrets(); hide_new_secret()">CREATE</button>
<button onclick="hide_new_secret()">CANCEL</button>
</form>
</dialog>
<script>
update_secrets = function() {
document.getElementById("update-secrets").click()
}
show_new_secret = function() {
document.getElementById('new-secret-funko').value=""
document.getElementById('add-secret').value=""
document.getElementById('add-secret').value=""
document.getElementById('add-secret').show()
}
hide_new_secret = function() {
document.getElementById('new-secret-funko').value=""
document.getElementById('add-secret').value=""
document.getElementById('add-secret').value=""
document.getElementById('add-secret').hide()
}
</script>
</main>
</body>

View File

@ -39,7 +39,7 @@ module Proxy
ReverseOnly Yes ReverseOnly Yes
ReverseMagic Yes ReverseMagic Yes
ReversePath "/admin/" "http://127.0.0.1:3000/" ReversePath "/admin/" "http://127.0.0.1:3000/"
) + funkos.map { |funko| %(ReversePath "/faaso/#{funko}/" "http://#{funko}:3000/") }.join("\n") ) + funkos.map { |funko| %(ReversePath "/faaso/#{funko.split("-")[0]}/" "http://#{funko}:3000/") }.join("\n")
if @@current_config != config if @@current_config != config
File.open("tinyproxy.conf", "w") do |file| File.open("tinyproxy.conf", "w") do |file|

View File

@ -7,15 +7,30 @@ module Secrets
# Gets a secret in form {"name": "funko_name-secret_name", "value": "secret_value"} # Gets a secret in form {"name": "funko_name-secret_name", "value": "secret_value"}
post "/secrets/" do |env| post "/secrets/" do |env|
name = env.params.json["name"].as(String) funko = env.params.body["funko"].as(String)
value = env.params.json["value"].as(String) name = env.params.body["name"].as(String)
SECRETS[name] = value value = env.params.body["value"].as(String)
if funko.empty? || name.empty? || value.empty?
halt env, status_code: 400, response: "Bad request"
end
SECRETS["#{funko}-#{name}"] = value
Secrets.update_secrets Secrets.update_secrets
halt env, status_code: 201, response: "Created" halt env, status_code: 201, response: "Created"
end end
get "/secrets/" do |env| get "/secrets/" do |env|
halt env, status_code: 200, response: SECRETS.keys.to_json result = [] of Hash(String, String)
SECRETS.each { |k, _|
result << {
"funko" => k.split("-")[0],
"name" => k.split("-", 2)[1],
}
}
if env.params.query.fetch("format", "json") == "html"
render "src/views/secrets.ecr"
else
result.to_json
end
end end
# Deletes a secret from the disk and memory # Deletes a secret from the disk and memory

View File

@ -96,10 +96,11 @@ module Funko
Log.info { "Scaling #{name} from #{current_scale} to #{new_scale}" } Log.info { "Scaling #{name} from #{current_scale} to #{new_scale}" }
if new_scale > current_scale if new_scale > current_scale
Log.info { "Adding instance" }
(current_scale...new_scale).each { (current_scale...new_scale).each {
Log.info { "Adding instance" }
id = create_container id = create_container
start(id) start(id)
sleep 0.1.seconds
} }
else else
containers.select { |container| container.@state == "running" }.sort! { |i, j| containers.select { |container| container.@state == "running" }.sort! { |i, j|
@ -109,6 +110,7 @@ module Funko
docker_api.containers.stop(container.@id) docker_api.containers.stop(container.@id)
current_scale -= 1 current_scale -= 1
break if current_scale == new_scale break if current_scale == new_scale
sleep 0.1.seconds
} }
end end

View File

@ -17,7 +17,7 @@
<button hx-get="funkos/<%= f["name"] %>/restart" hx-on:htmx:after-request="update_funkos()">Restart</button> <button hx-get="funkos/<%= f["name"] %>/restart" hx-on:htmx:after-request="update_funkos()">Restart</button>
<%- end -%> <%- end -%>
<%- end -%> <%- end -%>
<img id="spinner-<%= f["name"] %>" src="https://htmx.org/img/bars.svg" class="htmx-indicator"> <img id="spinner-<%= f["name"] %>" src="bars.svg" class="htmx-indicator">
</td> </td>
</tr> </tr>
<%- end -%> <%- end -%>

11
src/views/secrets.ecr Normal file
View File

@ -0,0 +1,11 @@
<%- result.each do |f| -%>
<tr hx-indicator="#spinner-<%= f["name"] %>">
<td><%= f["funko"] %></td>
<td><%= f["name"] %></td>
<td>
<button hx-post="secrets/" hx-on:htmx:after-request="update_secrets()">Change</button>
<button hx-delete="secrets/<%= f["funko"] %>-<%= f["name"] %>/" hx-on:htmx:after-request="update_secrets()">Delete</button>
<img id="spinner-<%= f["name"] %>" src="bars.svg" class="htmx-indicator">
</td>
</tr>
<%- end -%>

View File

@ -8,4 +8,4 @@
ReverseOnly Yes ReverseOnly Yes
ReverseMagic Yes ReverseMagic Yes
ReversePath "/admin/" "http://127.0.0.1:3000/" ReversePath "/admin/" "http://127.0.0.1:3000/"
ReversePath "/faaso/hello-fkvrm2/" "http://hello-fkvrm2:3000/" ReversePath "/faaso/hello/" "http://hello-c9ge0d:3000/"