Page MenuHomeDevCentral

server.py
No OneTemporary

server.py

#!/usr/bin/env python3
# -------------------------------------------------------------
# API to execute commands
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Project: Nasqueron
# Description: Run commands
# License: BSD-2-Clause
# Source file: roles/devserver/api-exec/files/server.py
# -------------------------------------------------------------
#
# <auto-generated>
# This file is managed by our rOPS SaltStack repository.
#
# Changes to this file may cause incorrect behavior
# and will be lost if the state is redeployed.
# </auto-generated>
import os
import subprocess
import sys
from flask import Flask, Response, abort
import yaml
# -------------------------------------------------------------
# Parse configuration
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
DEFAULT_CONFIGURATION_FILE = "/usr/local/etc/api-exec.conf"
DEFAULT_MIME_TYPE = "text/plain"
def load_config(config_file=None):
if config_file is None:
config_file = DEFAULT_CONFIGURATION_FILE
with open(config_file, "r") as file:
config = yaml.safe_load(file)
config["routes"] = {
key: ApiExecRoute.parse_config_entry(value)
for key, value in config["routes"].items()
}
return config
def set_environment(env):
for key, value in env.items():
os.environ[key] = value
class ApiExecRoute:
def __init__(self, command, mime_type):
self.command = command
self.mime_type = mime_type
@staticmethod
def parse_config_entry(entry):
if type(entry) is str:
return ApiExecRoute(entry, DEFAULT_MIME_TYPE)
mime_type = entry.get("mime_type", DEFAULT_MIME_TYPE)
return ApiExecRoute(entry["command"], mime_type)
# -------------------------------------------------------------
# Run commands
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
def execute_command(command):
result = subprocess.run(
command.split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True
)
return result.stdout, result.stderr, result.returncode == 0
# -------------------------------------------------------------
# Build Flask application
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
def initialize_app():
app = Flask(__name__)
app_config = load_config(os.environ.get("APP_EXEC_CONFIG_PATH"))
if not app_config:
print("Can't load configuration", file=sys.stderr)
sys.exit(1)
set_environment(app_config.get("env", {}))
app.config["routes"] = app_config["routes"]
return app
app = initialize_app()
# -------------------------------------------------------------
# Requests
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@app.route("/<route>", methods=["GET"])
def get_level1(route):
return handle_command_request("/" + route)
@app.route("/<route>/<subroute>", methods=["GET"])
def get_level2(route, subroute):
return handle_command_request(f"/{route}/{subroute}")
def handle_command_request(route):
args = app.config.get("routes", {}).get(route, None)
if not args:
return abort(404, description=f"Route '{route}' not found")
output, error, is_ok = execute_command(args.command)
if not is_ok:
if error is None or error.strip() == "":
description = "Error running command"
else:
description = f"Error running command: {error}"
return abort(500, description=description)
resp = Response(output, mimetype=args.mime_type)
resp.headers["Access-Control-Allow-Origin"] = "*"
resp.headers["X-API-Exec-Command"] = args.command
return resp
# -------------------------------------------------------------
# Application entry point
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
if __name__ == "__main__":
app.run(host="127.0.0.1", port=8000)

File Metadata

Mime Type
text/x-python
Expires
Tue, Jul 7, 23:53 (17 h, 50 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3875341
Default Alt Text
server.py (3 KB)

Event Timeline