from flask import Flask, jsonify, request from flask_apscheduler import APScheduler from typing import Dict, Union import json, time, redis, yaml from Components import * # declare flask apps app = Flask(__name__) scheduler = APScheduler() ####################################################################### ### Settings Handler Functions ####################################################################### # default application setting variables app_settings = { "noisy_test" : False, "debug_output" : False, "log_output" : False, "secure_api" : True, "push_redis" : False, "run_background" : True } with open('cosmostat_settings.yaml', 'r') as f: print("Loading cosmostat_settings file") cosmostat_settings = yaml.safe_load(f) print("...Done") # initialize system variables from settings file print("Checking for system var overrides") for setting in app_settings: if setting in cosmostat_settings: cosmos_setting = cosmostat_settings[setting] if app_settings["debug_output"]: print(f"{setting}: {cosmos_setting}") app_settings[setting] = cosmos_setting print("...Done") # this returns the docker gateway from the settings def docker_gateway_settings() -> str: return cosmostat_settings["docker_gateway"] # this returns the jenkins user that ran the pipeline def jenkins_user_settings() -> str: return cosmostat_settings["jenkins_user"] # this returns the ansible_hostname from setup def jenkins_hostname_settings() -> str: return cosmostat_settings["ansible_hostname"] # this returns the inventory_generation_timestamp def jenkins_inventory_generation_timestamp_settings() -> str: return cosmostat_settings["inventory_generation_timestamp"] def service_gateway_ip(): if cosmostat_settings["secure_api"]: return docker_gateway_settings() else: return "0.0.0.0" ####################################################################### ### Redis Functions ####################################################################### # Redis client – will publish updates r = redis.Redis(host=service_gateway_ip(), port=6379) def update_redis_channel(redis_channel, data): # Publish to the specified Redis channel r.publish(redis_channel, json.dumps(data)) if app_settings["noisy_test"]: print(f"{redis_channel} Redis Update") print(data) def update_redis_server(): # Update Stats Redis Channel update_redis_channel("host_stats", get_full_summary()) # Update history_stats Redis Channel update_redis_channel("history_stats", get_component_list()) ####################################################################### ### Other Functions ####################################################################### def get_component_summary(): result = [] for component in cosmostat_system.components: result.append(component.get_summary_key()) return result def get_full_summary(): result = [] for component in cosmostat_system.components: result.append(component.get_summary_key()) for sysvar in cosmostat_system.get_sysvars_summary_keys(): result.append(sysvar) return result # This will instantiate a System object def new_cosmos_system(): new_system = System(f"{jenkins_hostname_settings()}") if app_settings["log_output"]: print(f"New system object name: {new_system.name}") for component in new_system.components: print(component) return new_system def get_component_list(history_count = None): result = [] for component in cosmostat_system.components: if history_count is not None: history = component.get_history(history_count) else: history = component.get_history() result.append( { "info": component.get_info_key(), "history": history } ) return result def get_info(): device_summary = [] for component in cosmostat_system.components: device_summary.append( { "info": component.get_info_key(), } ) result = { "system_info": { "user": jenkins_user_settings(), "hostname": jenkins_hostname_settings(), "timestamp": jenkins_inventory_generation_timestamp_settings(), "component_count:": len(cosmostat_system.components), "object_name": cosmostat_system.name, "docker_gateway": docker_gateway_settings() }, "device_summary": device_summary } return result #def get_history_summary(): ####################################################################### ### Flask Routes ####################################################################### # full component list @app.route('/component_list', methods=['GET']) def component_list(): count = request.args.get('count', type=int) return jsonify(get_component_list(count)) # component summary @app.route('/component_summary', methods=['GET']) def component_summary(): return jsonify(get_component_summary()) # full summary @app.route('/full_summary', methods=['GET']) def full_summary(): return jsonify(get_full_summary()) # system info @app.route('/info', methods=['GET']) def info(): return jsonify(get_info()) # test route @app.route('/test', methods=['GET']) def test(): return jsonify( { "component_count:": len(cosmostat_system.components), "user": jenkins_user_settings(), "hostname": jenkins_hostname_settings() } ) ####################################################################### ### Main Subroutine ####################################################################### if __name__ == '__main__': # Background Loop Function def background_loop(): # Update all data on the System object cosmostat_system.update_values() if app_settings["push_redis"]: update_redis_server() if app_settings["noisy_test"]: print("Sorry about the mess...") print(f"Blame {jenkins_user_settings()}") # instantiate system cosmostat_system = new_cosmos_system() # send initial stats update to redis if app_settings["push_redis"]: update_redis_server() # Flask scheduler for scanner if app_settings["run_background"]: if app_settings["log_output"]: print("Loading flask background subroutine...") scheduler.add_job(id='background_loop', func=background_loop, trigger='interval', seconds=1) scheduler.init_app(app) scheduler.start() if app_settings["log_output"]: print("...Done") else: if app_settings["log_output"]: print("Skipping flask background task") # Flask API app.run(debug=True, host=service_gateway_ip(), port=5000)