function revisionClicked(namespace, name, self) { let active = "active border-primary border-1 bg-white"; let inactive = "border-secondary bg-secondary"; revRow.find(".active").removeClass(active).addClass(inactive) self.removeClass(inactive).addClass(active) const elm = self.data("elm") setHashParam("revision", elm.revision) $("#sectionDetails span.rev").text("#" + elm.revision) statusStyle(elm.status, $("#none"), $("#sectionDetails .rev-details .rev-status")) const rdate = luxon.DateTime.fromISO(elm.updated); $("#sectionDetails .rev-date").text(rdate.toJSDate().toLocaleString()) $("#sectionDetails .rev-tags .rev-chart").text(elm.chart) $("#sectionDetails .rev-tags .rev-app").text(elm.app_version) $("#sectionDetails .rev-tags .rev-ns").text(getHashParam("namespace")) if (getHashParam("context")) { $("#sectionDetails .rev-tags .rev-cluster").text(getHashParam("context")) } else { $("#sectionDetails .rev-tags .rev-cluster").parent().hide() // TODO: makes UI jumpy, change to showing } $("#revDescr").text(elm.description).removeClass("text-danger") if (elm.status === "failed") { $("#revDescr").addClass("text-danger") } const rev = $("#specRev").data("last-rev") == elm.revision ? elm.revision - 1 : elm.revision if (!rev || getHashParam("revision") === $("#specRev").data("first-rev")) { $("#btnRollback").hide() } else { $("#btnRollback").show().data("rev", rev).find("span").text("Rollback to #" + rev) } const tab = getHashParam("tab") if (!tab) { $("#nav-tab [data-tab=resources]").click() } else { $("#nav-tab [data-tab=" + tab + "]").click() } } function loadContentWrapper() { let revDiff = 0 const revision = parseInt(getHashParam("revision")); if (revision === $("#specRev").data("first-rev")) { revDiff = 0 } else if (getHashParam("mode") === "diff-prev") { revDiff = revision - 1 } else if (getHashParam("mode") === "diff-rev") { revDiff = $("#specRev").val() } const flag = $("#userDefinedVals").prop("checked"); loadContent(getHashParam("tab"), getHashParam("namespace"), getHashParam("chart"), revision, revDiff, flag) } function loadContent(mode, namespace, name, revision, revDiff, userDefined) { let qstr = "revision=" + revision if (revDiff) { qstr += "&revisionDiff=" + revDiff } if (userDefined) { qstr += "&userDefined=" + userDefined } let url = "/api/helm/releases/" + namespace + "/" + name + "/" + mode url += "?" + qstr const diffDisplay = $("#manifestText"); diffDisplay.empty().append('') $.get(url).fail(function (xhr) { reportError("Failed to get diff of " + mode, xhr) }).done(function (data) { diffDisplay.empty(); if (data === "") { diffDisplay.text("No differences to display") } else { if (revDiff) { const targetElement = document.getElementById('manifestText'); const configuration = { inputFormat: 'diff', outputFormat: 'side-by-side', drawFileList: false, showFiles: false, highlight: true, //matching: 'lines', }; const diff2htmlUi = new Diff2HtmlUI(targetElement, data, configuration); diff2htmlUi.draw() } else { data = hljs.highlight(data, {language: 'yaml'}).value const code = $("#manifestText").empty().append("
").find("pre");
                code.html(data)
            }
        }
    })
}

$('#specRev').keyup(function (event) {
    let keycode = (event.keyCode ? event.keyCode : event.which);
    if (keycode == '13') {
        $("#diffModeRev").click()
    }
});

$("form").submit(function (e) {
    e.preventDefault();
});

$("#userDefinedVals").change(function () {
    const self = $(this)
    const flag = $("#userDefinedVals").prop("checked");
    setHashParam("udv", flag)
    loadContentWrapper()
})

$("#modePanel [data-mode]").click(function () {
    const self = $(this)
    const mode = self.data("mode")
    setHashParam("mode", mode)
    loadContentWrapper()
})

$("#nav-tab [data-tab]").click(function () {
    const self = $(this)
    setHashParam("tab", self.data("tab"))

    if (self.data("tab") === "values") {
        $("#userDefinedVals").parent().show()
    } else {
        $("#userDefinedVals").parent().hide()
    }

    const flag = getHashParam("udv") === "true";
    $("#userDefinedVals").prop("checked", flag)

    if (self.data("tab") === "resources") {
        showResources(getHashParam("namespace"), getHashParam("chart"), getHashParam("revision"))
    } else {
        const mode = getHashParam("mode")
        if (!mode) {
            $("#modePanel [data-mode=view]").trigger('click')
        } else {
            $("#modePanel [data-mode=" + mode + "]").trigger('click')
        }
    }
})


function showResources(namespace, chart, revision) {
    const resBody = $("#nav-resources .body");
    const interestingResources = ["STATEFULSET", "DEAMONSET", "DEPLOYMENT"];
    resBody.empty().append('');
    let url = "/api/helm/releases/" + namespace + "/" + chart + "/resources?health=true"
    $.getJSON(url).fail(function (xhr) {
        reportError("Failed to get list of resources", xhr)
    }).done(function (data) {
        const scanners = $("body").data("scanners");
        const scannableResKinds = new Set();
        for (let k in scanners) {
            scanners[k].SupportedResourceKinds.forEach(scannableResKinds.add, scannableResKinds)
        }

        resBody.empty();
        data = data.sort(function (a, b) {
            return interestingResources.indexOf(a.kind.toUpperCase()) - interestingResources.indexOf(b.kind.toUpperCase())
        }).reverse();
        for (let i = 0; i < data.length; i++) {
            const res = data[i]
            const resBlock = $(`
                    
Getting status...
`) resBlock.find(".res-kind").text(res.kind) resBlock.find(".res-name").text(res.metadata.name) resBody.append(resBlock) let ns = res.metadata.namespace ? res.metadata.namespace : namespace for (let k = 0; k < res.status.conditions.length; k++) { if (res.status.conditions[k].type !== "hdHealth") { // it's our custom condition type continue } const cond = res.status.conditions[k] const badge = $("").text(cond.reason); if (cond.status === "Healthy") { badge.addClass("bg-success text-dark") } else if (cond.status === "Progressing") { badge.addClass("bg-warning") } else { badge.addClass("bg-danger") } if (["Exists"].includes(cond.reason)) { badge.addClass("bg-opacity-50") } const statusBlock = resBlock.find(".res-status"); statusBlock.empty().append(badge).attr("title", cond.reason) const statusMessage = cond.message resBlock.find(".res-statusmsg").html("" + (statusMessage ? statusMessage : '') + "") if (badge.text() !== "NotFound" && revision == $("#specRev").data("last-rev")) { resBlock.find(".res-actions") const btn = $(""); resBlock.find(".res-actions").append(btn) btn.click(function () { showDescribe(ns, res.kind, res.metadata.name, badge.clone()) }) if (scannableResKinds.has(res.kind)) { const btn2 = $(""); resBlock.find(".res-actions").append(btn2) btn2.click(function () { scanResource(ns, res.kind, res.metadata.name, badge.clone()) }) } } if (badge.hasClass("bg-danger") || badge.hasClass("bg-warning")) { resBlock.find(".res-statusmsg").append("Troubleshoot in Komodor ") } } } }) } function showDescribe(ns, kind, name, badge) { $("#describeModal .offcanvas-header p").text(kind) $("#describeModalLabel").text(name).append(badge.addClass("ms-3 small fw-normal")) $("#describeModalBody").empty().append('') const myModal = new bootstrap.Offcanvas(document.getElementById('describeModal')); myModal.show() $.get("/api/k8s/" + kind.toLowerCase() + "/describe?name=" + name + "&namespace=" + ns).fail(function (xhr) { reportError("Failed to describe resource", xhr) }).done(function (data) { data = hljs.highlight(data, {language: 'yaml'}).value $("#describeModalBody").empty().append("
").find("pre").html(data)
    })
}

function scanResource(ns, kind, name, badge) {
    $("#describeModal .offcanvas-header p").text(kind)
    $("#describeModalLabel").text(name).append(badge.addClass("ms-3 small fw-normal"))
    const body = $("#describeModalBody");
    body.empty().append(' Scanning...')

    const myModal = new bootstrap.Offcanvas(document.getElementById('describeModal'));
    myModal.show()
    $.get("/api/scanners/resource/" + kind.toLowerCase() + "?name=" + name + "&namespace=" + ns).fail(function (xhr) {
        reportError("Failed to scan resource", xhr)
    }).done(function (data) {
        body.empty()
        if ($.isEmptyObject(data)) {
            body.append("No information from scanners. Make sure you have installed some and scanned object is supported.")
        }

        const tabs = $('')
        const content = $('
') for (let name in data) { const res = data[name] if (!res.OrigReport && !res.PassedCount) continue const hdr = $(``) if (res.FailedCount) { hdr.find('button').append("" + res.FailedCount + " failed") } if (res.PassedCount) { hdr.find('button').append("" + res.PassedCount + " passed") } const hl = hljs.highlight(res.OrigReport, {language: 'yaml'}).value const pre = $("
").html(hl)
            const div = $('
').append(pre) tabs.append(hdr) content.append(div) } body.append(tabs) body.append(content) tabs.find('li').first().find('button').click() }) }