# lua_package_path '/usr/share/lua/5.1/?.lua;;'; server { listen 8080 default_server; root /var/www/html/; index index.html; access_log off; set_by_lua_block $application_url { return os.getenv("APPLICATION_URL") } set_by_lua_block $disable_tls { local env_var = os.getenv("DISABLE_TLS") if env_var then return env_var else return "false" end } set_by_lua_block $demo_mode { local env_var = os.getenv("PLATFORM_ENGINEERING_DEMO_MODE") if env_var then return env_var else return "false" end } set_by_lua_block $selected_env_vars { local selected_env_vars = {"KUBERNETES_SERVICE_HOST", "KUBERNETES_SERVICE_PORT_HTTPS", "NAMESPACE", "DISABLE_TLS", "APPLICATION_URL"} local result = {} for _, var_name in ipairs(selected_env_vars) do local value = os.getenv(var_name) if value then table.insert(result, var_name .. " = " .. value) else table.insert(result, var_name .. " = nil") end end return table.concat(result, ", ") } location / { add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range'; add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range'; try_files $uri $uri/ =404; add_header Last-Modified $date_gmt; if_modified_since off; expires off; etag off; sub_filter_types "*"; sub_filter demo_mode_placeholder $demo_mode; sub_filter application_url_placeholder $application_url; sub_filter disable_tls_placeholder $disable_tls; sub_filter selected_env_vars_placeholder $selected_env_vars; } location /kube/demo/deploy { access_by_lua_file "/usr/local/openresty/nginx/conf/kubeinvaders/demo_deploy.lua"; } location /kube/ingresses { access_by_lua_file "/usr/local/openresty/nginx/conf/kubeinvaders/ingress.lua"; } location /kube/vm { access_by_lua_file "/usr/local/openresty/nginx/conf/kubeinvaders/vm.lua"; } location /kube/vm_reboot { access_by_lua_file "/usr/local/openresty/nginx/conf/kubeinvaders/vm_reboot.lua"; } location /kube/healthz { content_by_lua_block { local https = require "ssl.https" local ltn12 = require "ltn12" local json = require "lunajson" local redis = require "resty.redis" ngx.header['Access-Control-Allow-Origin'] = '*' ngx.header['Access-Control-Allow-Methods'] = 'GET, POST, OPTIONS' ngx.header['Access-Control-Allow-Headers'] = 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' ngx.header['Access-Control-Expose-Headers'] = 'Content-Length,Content-Range'; if ngx.var.request_method == "OPTIONS" then ngx.status = 204 return end local args = ngx.req.get_uri_args() local target = args["target"] local ca_cert = nil if ngx.var.request_method == "POST" then ngx.req.read_body() local data = ngx.req.get_body_data() if data and data ~= "" then local ok, decoded = pcall(json.decode, data) if ok and decoded then if decoded["target"] and decoded["target"] ~= "" then target = decoded["target"] end if decoded["ca_cert"] and decoded["ca_cert"] ~= "" then ca_cert = decoded["ca_cert"] end end end end if not target or target == "" then if os.getenv("KUBERNETES_SERVICE_HOST") then target = "https://" .. os.getenv("KUBERNETES_SERVICE_HOST") .. ":" .. os.getenv("KUBERNETES_SERVICE_PORT_HTTPS") else target = os.getenv("ENDPOINT") end end if not target or target == "" then ngx.status = 400 ngx.say("Missing Kubernetes endpoint") return end if not string.match(target, "^https?://") then target = "https://" .. target end target = string.gsub(target, "/+$", "") -- Persist the user-configured endpoint so background loops can reuse it. local red = redis:new() local okredis, errredis = red:connect("unix:/tmp/redis.sock") if okredis then local okset, errset = red:set("k8s_api_endpoint", target) if not okset then ngx.log(ngx.WARN, "[kube/healthz] Unable to persist k8s_api_endpoint in Redis: ", tostring(errset)) end else ngx.log(ngx.WARN, "[kube/healthz] Redis connection failed while storing k8s_api_endpoint: ", tostring(errredis)) end local healthz_url = target .. "/healthz" local disable_tls_env = string.lower(tostring(os.getenv("DISABLE_TLS") or "false")) local disable_tls = disable_tls_env == "true" or disable_tls_env == "1" or disable_tls_env == "yes" local request_opts = { url = healthz_url, method = "GET", verify = disable_tls and "none" or "peer" } if not disable_tls and ca_cert and ca_cert ~= "" then local ca_file_path = "/tmp/kubeinv-custom-ca.crt" local ca_file = io.open(ca_file_path, "w") if not ca_file then ngx.status = 500 ngx.say("Unable to persist CA certificate") return end ca_file:write(ca_cert) ca_file:close() request_opts.cafile = ca_file_path end local resp = {} request_opts.sink = ltn12.sink.table(resp) local ok, statusCode, response_headers, status_line = https.request(request_opts) local numeric_status = tonumber(statusCode) if not numeric_status then numeric_status = ok and 200 or 502 end ngx.status = numeric_status ngx.header['Content-Type'] = 'application/json' local body = table.concat(resp) local response = { ok = ok and numeric_status >= 200 and numeric_status < 300, status = numeric_status, target = healthz_url } if body ~= "" then response["body"] = body end if not ok then response["error"] = tostring(statusCode or "unknown") end ngx.say(json.encode(response)) } } location /kube/chaos/programming_mode { access_by_lua_file "/usr/local/openresty/nginx/conf/kubeinvaders/programming_mode.lua"; } location /kube/pods { access_by_lua_file "/usr/local/openresty/nginx/conf/kubeinvaders/pod.lua"; } location /kube/delete/pods { access_by_lua_file "/usr/local/openresty/nginx/conf/kubeinvaders/pod.lua"; } location /kube/nodes { access_by_lua_file "/usr/local/openresty/nginx/conf/kubeinvaders/node.lua"; } location /kube/chaos/nodes { access_by_lua_file "/usr/local/openresty/nginx/conf/kubeinvaders/chaos-node.lua"; } location /kube/kube-linter { access_by_lua_file "/usr/local/openresty/nginx/conf/kubeinvaders/kube-linter.lua"; } location /kube/endpoint { content_by_lua_block { ngx.header['Access-Control-Allow-Origin'] = '*' ngx.header['Access-Control-Allow-Methods'] = 'GET, POST, OPTIONS' ngx.header['Access-Control-Allow-Headers'] = 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' ngx.header['Access-Control-Expose-Headers'] = 'Content-Length,Content-Range'; local endpoint = os.getenv("APPLICATION_URL") if not endpoint or endpoint == "" then if os.getenv("KUBERNETES_SERVICE_HOST") and os.getenv("KUBERNETES_SERVICE_PORT_HTTPS") then endpoint = "https://" .. os.getenv("KUBERNETES_SERVICE_HOST") .. ":" .. os.getenv("KUBERNETES_SERVICE_PORT_HTTPS") else endpoint = os.getenv("ENDPOINT") end end if not endpoint or endpoint == "" then ngx.status = 500 ngx.say("Error! No cluster endpoint configured (APPLICATION_URL, KUBERNETES_SERVICE_HOST, or ENDPOINT).") else ngx.say(endpoint) end } } location /chaos/redis/get { content_by_lua_block { local redis = require "resty.redis" local red = redis:new() local okredis, errredis = red:connect("unix:/tmp/redis.sock") ngx.header['Access-Control-Allow-Origin'] = '*' ngx.header['Access-Control-Allow-Methods'] = 'GET, POST, OPTIONS' ngx.header['Access-Control-Allow-Headers'] = 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' ngx.header['Access-Control-Expose-Headers'] = 'Content-Length,Content-Range'; ngx.req.read_body() local data = ngx.req.get_body_data() local args = ngx.req.get_uri_args() local key = args["key"] if red:exists(key) == 0 then ngx.say("Key not found") else ngx.say(tostring(red:get(key))) end } } location /chaos/redis/set { content_by_lua_block { local redis = require "resty.redis" local red = redis:new() local okredis, errredis = red:connect("unix:/tmp/redis.sock") ngx.header['Access-Control-Allow-Origin'] = '*' ngx.header['Access-Control-Allow-Methods'] = 'GET, POST, OPTIONS' ngx.header['Access-Control-Allow-Headers'] = 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' ngx.header['Access-Control-Expose-Headers'] = 'Content-Length,Content-Range'; ngx.req.read_body() local data = ngx.req.get_body_data() local args = ngx.req.get_uri_args() local key = args["key"] ngx.log(ngx.INFO, "[KUBEPING] Setting key " .. key .. " with data |" .. tostring(data) .. "|") ngx.say(tostring(red:set(key, tostring(data)))) if key == "kubeping" and data == "1" then local http = require("socket.http") local function get_data(url) local respbody = {} local code, response = http.request(url) if code == 200 then local json = require("json") respbody = json.decode(response) else print("Errore nella richiesta: " .. code) end return respbody end local data = get_data("https://devopstribe.it/kubeping?msg=" .. args["msg"]) print(data.result) end ngx.say("OK") } } location /kube/namespaces { content_by_lua_block { ngx.header['Access-Control-Allow-Origin'] = '*' ngx.header['Access-Control-Allow-Methods'] = 'GET, POST, OPTIONS' ngx.header['Access-Control-Allow-Headers'] = 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' ngx.header['Access-Control-Expose-Headers'] = 'Content-Length,Content-Range'; -- TO DO -- Check when NAMESPACE is nil ngx.say(os.getenv("NAMESPACE")) } } location /codename { content_by_lua_block { local open = io.open local function read_rand_line_from_file(path) local handle = io.popen("shuf -n 1 " .. path) local result = handle:read("*a") local rc = handle:close() return result end local random_word = read_rand_line_from_file("/usr/local/openresty/nginx/conf/kubeinvaders/data/codenames.txt") local redis = require "resty.redis" local red = redis:new() local okredis, errredis = red:connect("unix:/tmp/redis.sock") ngx.header['Access-Control-Allow-Origin'] = '*' ngx.header['Access-Control-Allow-Methods'] = 'GET, POST, OPTIONS' ngx.header['Access-Control-Allow-Headers'] = 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' ngx.header['Access-Control-Expose-Headers'] = 'Content-Length,Content-Range'; while (red:get("latest_codename") == random_word) do random_word = read_rand_line_from_file("/usr/local/openresty/nginx/conf/kubeinvaders/data/codenames.txt") end red:set("latest_codename", random_word) -- ngx.log(ngx.INFO, "[programming_mode_codename] Choosing random word " .. random_word) ngx.say(random_word) } } location /metrics { default_type text/plain; content_by_lua_block { ngx.header['Access-Control-Allow-Origin'] = '*' ngx.header['Access-Control-Allow-Methods'] = 'GET, POST, OPTIONS' ngx.header['Access-Control-Allow-Headers'] = 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' ngx.header['Access-Control-Expose-Headers'] = 'Content-Length,Content-Range' local redis = require "resty.redis" local red = redis:new() local okredis, errredis = red:connect("unix:/tmp/redis.sock") if not okredis then ngx.log(ngx.ERR, "[metrics] Redis connection failed: " .. tostring(errredis)) ngx.status = 500 ngx.say("Redis connection failed") return end local total_keys = red:keys("*total*") if total_keys and type(total_keys) == "table" then for i, res in ipairs(total_keys) do if string.find(res, "chaos_node_jobs_total_on") then local node = string.gsub(res, "chaos_node_jobs_total_on_", "") local metric = "chaos_jobs_node_count{node=\"".. node .."\"}" ngx.say(metric .. " " .. red:get(res)) elseif string.find(res, "deleted_pods_total_on") then local namespace = string.gsub(res, "deleted_pods_total_on_", "") local metric = "deleted_namespace_pods_count{namespace=\"".. namespace .."\"}" ngx.say(metric .. " " .. red:get(res)) end end end local regex_keys = red:keys("pods_match_regex:*") if regex_keys and type(regex_keys) == "table" then for i, res in ipairs(regex_keys) do ngx.say(res .. " " .. red:get(res)) end end local metrics = { 'chaos_node_jobs_total', 'deleted_pods_total', 'fewer_replicas_seconds', 'latest_fewer_replicas_seconds', 'pods_not_running_on_selected_ns', 'current_chaos_job_pod', 'pods_match_regex' } local metric_name = "" local metric_value = "" for key, value in ipairs(metrics) do metric_name = value if (red:exists(metric_name) == 1) then metric_value = red:get(metric_name) ngx.say(metric_name .. " " .. metric_value) end end local status_keys = red:keys("chaos_jobs_status*") if status_keys and type(status_keys) == "table" then for i, res in ipairs(status_keys) do ngx.say(res .. " " .. red:get(res)) end end } } location /chaos_jobs_pod_phase { default_type text/plain; content_by_lua_block { ngx.header['Access-Control-Allow-Origin'] = '*' ngx.header['Access-Control-Allow-Methods'] = 'GET, POST, OPTIONS' ngx.header['Access-Control-Allow-Headers'] = 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' ngx.header['Access-Control-Expose-Headers'] = 'Content-Length,Content-Range' local redis = require "resty.redis" local red = redis:new() local okredis, errredis = red:connect("unix:/tmp/redis.sock") if not okredis then ngx.log(ngx.ERR, "[chaos_jobs_pod_phase] Redis connection failed: " .. tostring(errredis)) ngx.status = 500 ngx.say("Redis connection failed") return end local phase_keys = red:keys("chaos_jobs_pod_phase*") if phase_keys and type(phase_keys) == "table" then for i, res in ipairs(phase_keys) do ngx.say(res .. " " .. red:get(res)) end end } } location /kube/chaos/containers { lua_need_request_body 'on'; access_by_lua_file "/usr/local/openresty/nginx/conf/kubeinvaders/chaos-containers.lua"; } location /chaos/logs/keepalive { content_by_lua_block { local redis = require "resty.redis" local red = redis:new() local args = ngx.req.get_uri_args() ngx.header['Access-Control-Allow-Origin'] = '*' ngx.header['Access-Control-Allow-Methods'] = 'GET, POST, OPTIONS' ngx.header['Access-Control-Allow-Headers'] = 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' ngx.header['Access-Control-Expose-Headers'] = 'Content-Length,Content-Range'; ngx.req.read_body() local data = ngx.req.get_body_data() local okredis, errredis = red:connect("unix:/tmp/redis.sock") local logid = args["logid"] red:set("do_not_clean_log:" .. logid, "1") red:expire("do_not_clean_log:" .. logid, "20") red:set("logs_enabled:" .. logid, "1") red:expire("logs_enabled:" .. logid, "10") if red:exists("log_status:".. logid) then ngx.say(red:get("log_status:".. logid)) else ngx.say('Waiting for log collector status...') end } } location /chaos/logs/count { default_type text/html; content_by_lua_block { local redis = require "resty.redis" local red = redis:new() local args = ngx.req.get_uri_args() ngx.header['Access-Control-Allow-Origin'] = '*' ngx.header['Access-Control-Allow-Methods'] = 'GET, POST, OPTIONS' ngx.header['Access-Control-Allow-Headers'] = 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' ngx.header['Access-Control-Expose-Headers'] = 'Content-Length,Content-Range'; ngx.req.read_body() local data = ngx.req.get_body_data() local okredis, errredis = red:connect("unix:/tmp/redis.sock") local logid = args["logid"] local res, err = red:get("logs:chaoslogs-" .. logid .. "-count") if res == ngx.null then ngx.say("0") else ngx.say(res) end } } location /chaos/logs { default_type text/html; content_by_lua_block { local redis = require "resty.redis" local red = redis:new() local args = ngx.req.get_uri_args() ngx.header['Access-Control-Allow-Origin'] = '*' ngx.header['Access-Control-Allow-Methods'] = 'GET, POST, OPTIONS' ngx.header['Access-Control-Allow-Headers'] = 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' ngx.header['Access-Control-Expose-Headers'] = 'Content-Length,Content-Range'; ngx.req.read_body() local data = ngx.req.get_body_data() local okredis, errredis = red:connect("unix:/tmp/redis.sock") local logid = args["logid"] local pos = args["pos"] local res = red:get("logs:chaoslogs-" .. logid .. "-" .. pos) ngx.say(res) } } location /chaos/loadpreset { content_by_lua_block { local redis = require "resty.redis" local red = redis:new() local args = ngx.req.get_uri_args() ngx.header['Access-Control-Allow-Origin'] = '*' ngx.header['Access-Control-Allow-Methods'] = 'GET, POST, OPTIONS' ngx.header['Access-Control-Allow-Headers'] = 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' ngx.header['Access-Control-Expose-Headers'] = 'Content-Length,Content-Range'; ngx.req.read_body() local okredis, errredis = red:connect("unix:/tmp/redis.sock") local key_name = args["lang"] .. "_" .. args["name"] local res, err = red:get(key_name) if res == ngx.null then ngx.say(err) else ngx.say(res) end } } location /chaos/loadpreset/reset { content_by_lua_block { local function mysplit (inputstr, sep) if sep == nil then sep = "%s" end local t={} for str in string.gmatch(inputstr, "([^"..sep.."]+)") do table.insert(t, str) end return t end local redis = require "resty.redis" local red = redis:new() local args = ngx.req.get_uri_args() ngx.header['Access-Control-Allow-Origin'] = '*' ngx.header['Access-Control-Allow-Methods'] = 'GET, POST, OPTIONS' ngx.header['Access-Control-Allow-Headers'] = 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' ngx.header['Access-Control-Expose-Headers'] = 'Content-Length,Content-Range'; ngx.req.read_body() local okredis, errredis = red:connect("unix:/tmp/redis.sock") local key_name = args["lang"] .. "_" .. args["name"] -- ngx.log(ngx.INFO, "[PRESETS-RESET] The item " .. key_name .. " should be removed from the key presets_list") local handle = io.popen("redis-cli --scan --pattern " .. key_name .. " | xargs redis-cli del") local result = handle:read("*a") local rc = handle:close() local res = red:get("presets_list") if res == ngx.null then ngx.say("There are no presets saved yet") else local preset = ""; local new_preset_list = ""; local cnt = 0; for key, value in ipairs(mysplit(res, ",")) do -- ngx.log(ngx.INFO, "[PRESETS-RESET] Split the key presets_list. Current preset is: " .. value) if value ~= key_name then preset = value if cnt > 0 then new_preset_list = new_preset_list .. "," .. preset else new_preset_list = preset end end cnt = cnt + 1 end -- ngx.log(ngx.INFO, "[PRESETS-RESET] New key presets_list is: " .. new_preset_list) red:set("presets_list", new_preset_list) end } } location /chaos/loadpreset/savedpresets { default_type text/html; content_by_lua_block { local redis = require "resty.redis" local red = redis:new() local args = ngx.req.get_uri_args() ngx.header['Access-Control-Allow-Origin'] = '*' ngx.header['Access-Control-Allow-Methods'] = 'GET, POST, OPTIONS' ngx.header['Access-Control-Allow-Headers'] = 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' ngx.header['Access-Control-Expose-Headers'] = 'Content-Length,Content-Range'; local okredis, errredis = red:connect("unix:/tmp/redis.sock") local res, err = red:get("presets_list") if res == ngx.null then ngx.say(err) else ngx.say(res) -- ngx.log(ngx.INFO, "[PRESETS_LIST] " .. res) end } } location /chaos/report/keepalive { content_by_lua_block { local function check_if_string_contain_project(project_list, project) if string.find(project_list, project) then return true end return false end local function add_project(project_list, new_project) local new_project_list = project_list .. "," .. new_project return new_project_list end local function check_if_redis_key_exists(redis, key) if redis:exists(key) == 1 then return true end return false end local redis = require "resty.redis" local red = redis:new() local args = ngx.req.get_uri_args() ngx.header['Access-Control-Allow-Origin'] = '*' ngx.header['Access-Control-Allow-Methods'] = 'GET, POST, OPTIONS' ngx.header['Access-Control-Allow-Headers'] = 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' ngx.header['Access-Control-Expose-Headers'] = 'Content-Length,Content-Range'; ngx.req.read_body() local data = ngx.req.get_body_data() local okredis, errredis = red:connect("unix:/tmp/redis.sock") if check_if_redis_key_exists(red, "chaos_report_project_list") then if not check_if_string_contain_project(red:get("chaos_report_project_list"), args["project"]) then red:set("chaos_report_project_list", add_project(red:get("chaos_report_project_list"), args["project"])) end else red:set("chaos_report_project_list", args["project"]) end red:expire("chaos_report_project_list", 120) } } location /chaos/report/save { content_by_lua_block { local function check_if_string_contain_project(project_list, project) if string.find(project_list, project) then return true end return false end local function add_project(project_list, new_project) local new_project_list = project_list .. "," .. new_project return new_project_list end local function check_if_redis_key_exists(redis, key) if redis:exists(key) == 1 then return true end return false end local redis = require "resty.redis" local red = redis:new() local args = ngx.req.get_uri_args() ngx.header['Access-Control-Allow-Origin'] = '*' ngx.header['Access-Control-Allow-Methods'] = 'GET, POST, OPTIONS' ngx.header['Access-Control-Allow-Headers'] = 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' ngx.header['Access-Control-Expose-Headers'] = 'Content-Length,Content-Range'; ngx.req.read_body() local data = ngx.req.get_body_data() local okredis, errredis = red:connect("unix:/tmp/redis.sock") red:set("chaos_report_project_" .. args["project"], data) local project = args["project"] or "" if project ~= "" then local check_url_counter_key = project .. "_check_url_counter" local check_url_status_code_key = project .. "_check_url_status_code" local check_url_elapsed_time_key = project .. "_check_url_elapsed_time" local check_url_start_time_key = project .. "_check_url_start_time" if red:exists(check_url_counter_key) == 0 then red:set(check_url_counter_key, 0) end if red:exists(check_url_status_code_key) == 0 then red:set(check_url_status_code_key, "Other") end if red:exists(check_url_elapsed_time_key) == 0 then red:set(check_url_elapsed_time_key, 0) end if red:exists(check_url_start_time_key) == 0 then red:set(check_url_start_time_key, os.date("%Y-%m-%d %H:%M:%S")) end end if check_if_redis_key_exists(red, "chaos_report_project_list") then if not check_if_string_contain_project(red:get("chaos_report_project_list"), args["project"]) then red:set("chaos_report_project_list", add_project(red:get("chaos_report_project_list"), args["project"])) end else red:set("chaos_report_project_list", args["project"]) end red:expire("chaos_report_project_list", 120) -- ngx.log(ngx.INFO, "[CHAOS-REPORT-SAVE] " .. data) } } location /chaos/loadpreset/save { content_by_lua_block { local redis = require "resty.redis" local red = redis:new() local args = ngx.req.get_uri_args() ngx.header['Access-Control-Allow-Origin'] = '*' ngx.header['Access-Control-Allow-Methods'] = 'GET, POST, OPTIONS' ngx.header['Access-Control-Allow-Headers'] = 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' ngx.header['Access-Control-Expose-Headers'] = 'Content-Length,Content-Range'; ngx.req.read_body() local data = ngx.req.get_body_data() local okredis, errredis = red:connect("unix:/tmp/redis.sock") local key_name = args["lang"] .. "_" .. args["name"] local all_presets_key = "" if data ~= nil then -- ngx.log(ngx.INFO, "[SAVE-PRESETS] lang:" .. args["lang"] .. ", name:" .. args["name"] .. ", payload:" .. data .. "\n key_name:" .. key_name .. "\n key_exists: " .. red:exists(key_name)) -- if (red:exists(key_name) == 0) then red:set(key_name, data) -- ngx.log(ngx.INFO, "[SAVE-PRESETS] key_name:" .. key_name .. ", data:" .. data) local res, err = red:get(key_name) if res == ngx.null then ngx.say("error: " .. args["name"] .. " has not been saved.") else local file = io.open("/var/www/html/" .. key_name, "w") io.output(file) io.write(data) io.close(file) ngx.say(args["name"] .. " has been saved.") local redis_presets_list = red:get("presets_list") if redis_presets_list == ngx.null then red:set("presets_list", key_name) else local presets_list = redis_presets_list .. "," .. key_name red:set("presets_list", presets_list) end end -- end else ngx.say("Error in payload sent by web interface.") end } } location /chaos/programs/json-flow { content_by_lua_block { local function key_exists(data, mykey) for key, value in pairs(data) do if key == mykey then return true end end return false end local function is_key_empty(data, mykey) local cnt = 0 for key, value in pairs(data[mykey]) do cnt = cnt + 1 end if cnt > 0 then return false end return true end local lyaml = require "lyaml" local json = require 'lunajson' ngx.header['Access-Control-Allow-Origin'] = '*' ngx.header['Access-Control-Allow-Methods'] = 'GET, POST, OPTIONS' ngx.header['Access-Control-Allow-Headers'] = 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' ngx.header['Access-Control-Expose-Headers'] = 'Content-Length,Content-Range'; ngx.req.read_body() local data = ngx.req.get_body_data() if data then ngx.log(ngx.INFO, "[PROGRAMMING_MODE] Chaos program payload sent from client: " .. data) end if data == nil then error = "[PROGRAMMING_MODE] No chaos program already loaded." ngx.status = 400 ngx.say(error) else local parse_ok, yaml_data = pcall(lyaml.load, data) if not parse_ok or type(yaml_data) ~= "table" then ngx.status = 400 ngx.say("Invalid YAML Chaos Program") return end if not key_exists(yaml_data, "k8s_jobs") then error = "[PROGRAMMING_MODE] Chaos program does not contain 'jobs' key." ngx.status = 400 ngx.say(error) elseif not key_exists(yaml_data, "experiments") then error = "[PROGRAMMING_MODE] Chaos program does not contain 'experiments' key." ngx.status = 400 ngx.say(error) elseif is_key_empty(yaml_data, "k8s_jobs") then error = "[PROGRAMMING_MODE] Chaos program does not contain valid 'jobs' key." ngx.status = 400 ngx.say(error) elseif is_key_empty(yaml_data, "experiments") then error = "[PROGRAMMING_MODE] Chaos program does not contain valid 'experiments' key." ngx.status = 400 ngx.say(error) else local response = json.encode(yaml_data) ngx.log(ngx.INFO, response) ngx.status = 200 ngx.say(response) end end } } }