77 lines
1.7 KiB
Ruby
Executable File
77 lines
1.7 KiB
Ruby
Executable File
#!/usr/bin/env ruby
|
|
|
|
require "sinatra/base"
|
|
require "dotenv"
|
|
require "slim"
|
|
|
|
module RS
|
|
APP_ENV = ENV.fetch("REMOTE_SYSTEMCTL_ENV") { "development" }
|
|
LOADED_ENV = Dotenv.load(".env.#{APP_ENV}.local", ".env.local", ".env")
|
|
PASSWORDS = LOADED_ENV.filter { |k, _| k =~ /^PASSWORD_/ }.to_h
|
|
SERVICE_NAMES = PASSWORDS.map { |k, _| k.gsub(/^PASSWORD_/, '') }
|
|
|
|
class Service
|
|
attr_reader :name, :state
|
|
|
|
def initialize(name:)
|
|
@name = name
|
|
@state = "default"
|
|
end
|
|
|
|
def password = PASSWORDS["PASSWORD_#{@name}"]
|
|
def start! = act! :start
|
|
def stop! = act! :stop
|
|
|
|
private def act!(action)
|
|
`systemctl --user #{action} #{@name}`
|
|
@state = action
|
|
end
|
|
end
|
|
|
|
class ServiceIndex
|
|
def initialize(service_list)
|
|
@index = service_list.map { [_1, Service.new(name: _1)] }.to_h
|
|
end
|
|
|
|
def [](service_name) = @index[service_name]
|
|
def each(&block) = @index.values.each(&block)
|
|
end
|
|
|
|
SERVICES = ServiceIndex.new(SERVICE_NAMES)
|
|
|
|
class App < Sinatra::Base
|
|
get "/" do
|
|
slim :index, locals: { services: SERVICES }
|
|
end
|
|
|
|
post "/:service/:action" do
|
|
service = SERVICES[params["service"]]
|
|
if !service
|
|
status_code 404
|
|
return "Service not found"
|
|
end
|
|
|
|
if params["password"] != service.password
|
|
status_code 403
|
|
return "Invalid password"
|
|
end
|
|
|
|
case params["action"]
|
|
when "start"
|
|
service.start!
|
|
when "stop"
|
|
service.stop!
|
|
end
|
|
redirect "/"
|
|
end
|
|
|
|
set :bind, ENV["REMOTE_SYSTEMCTL_BIND"] || "127.0.0.1"
|
|
set :port, ENV["REMOTE_SYSTEMCTL_PORT"] || "10001"
|
|
|
|
set :environment, APP_ENV
|
|
ENV["RACK_ENV"] = APP_ENV
|
|
|
|
run! if app_file == $PROGRAM_NAME
|
|
end
|
|
end
|