constants module

class constants.Constants[source]

Bases: object

BUFF_SIZE = 1024

Buffer size for reading from SOCKET_FILE.

CHOME = '~/.conquers/'
CHOME_ABS_PATH = None
DEFAULT_CONFIG = 'config.yaml'
HTML_BOTTOM = '\n            </ul>\n\n            <div class="nav-stuff footer">\n            <label>🔗 LINKS:</label>\n              <ul class="links">\n                <li>\n                  <a \n                  href="https://github.com/medecaj/conquers"\n                  class="github"\n                  target="_blank">\n                    conquers\n                  </a>\n                </li>\n                <li>\n                  <a \n                  href="https://github.com/medecaj/conquers-report"\n                  class="github"\n                  target="_blank">\n                    conquers-report\n                  </a>\n                </li>\n              </ul>\n            </div>\n\n          </div>\n        </div>\n        <div class="host-content-wrapper">\n          <div class="host-content" id="host-content">\n            <span class="info-box">\n              Click a host on the left to see its report.\n            </span>\n          </div>\n        </div>\n      </div>\n\n    </div>\n    <!--<script src="js/main.js"></script>-->\n    <script>\n(() => {\n  \'use strict\';\n\n  class FilterHosts {\n    constructor() {\n      this.list = document.getElementsByClassName("sub-li-item");\n      this.search_input = document.getElementById("search-input");\n      this.addEvent();\n    }\n    addEvent() {\n      this.search_input.addEventListener("keyup", (e) => {\n        let value = this.search_input.value;\n        for(let i = 0; i < this.list.length; i++) {\n          if(this.list[i].textContent.toLowerCase().includes(\n            value.toLowerCase()\n            )\n          ) {\n            this.list[i].style.display = "block";\n          }\n          else {\n            this.list[i].style.display = "none";\n          }\n        }\n      });\n    }\n  }\n\n  class Expander {\n    constructor(elem, target, cssVisibleAttribute, useOpacityActive=false) {\n      this.elem = elem;\n      this.target = target\n      this.open = true;\n      this.cssVisibleAttribute = cssVisibleAttribute;\n      this.add_click_event();\n      this.useOpacityActive = useOpacityActive;\n    }\n\n    add_click_event() {\n      this.elem.addEventListener("click", (e) => {\n        if(this.useOpacityActive)\n          this.elem.style.opacity = (this.open) ? "0.5" : "1";\n        this.target.style.display = (this.open) ? "none" : this.cssVisibleAttribute;\n        this.open = !this.open;\n      });\n    }\n  }\n  /*** class Expander END *********************************/\n\n  class HTMLBuilder {\n    constructor(elem) {\n      this.clicked_node = elem;\n      this.obj = {};\n      this.group = "";\n      this.host_obj = {};\n      this.host = "";\n      this.error = "";\n      this.html = "";\n      this.json_string = "";\n      this.contentNode = this.gid("host-content");\n      this.check_error_set_color();\n      this.add_click_event(elem);\n      this.subListItemCssClass = "sub-li-item";\n      this.activeListCssClass = "sub-li-item-active";\n    }\n    /*** constructor END ***************/\n\n    /*\n     * Check for error length in dataset-json\n     * and sets hostname green for ok or red\n     * if errors occured.\n     */\n    check_error_set_color() {\n      this.json_string = this.clicked_node.dataset.json;\n\n      /*\n       * Get JSON object from dataset.\n       */\n      try {\n        this.obj = JSON.parse(this.json_string)\n      }\n      catch(e) {\n        let error = "[ERROR] No JSON data or erroneous data. This is a bug.";\n        this.error = this.ce("p");\n        this.error.textContent = error;\n        this.error.classList.add("error-red");\n        this.clicked_node.classList.add("error-red");\n        return;\n      }\n\n      // Get first key with is the group name.\n      for(let g in this.obj) {\n        this.group = g;\n        break;\n      }\n\n      // Get the host name and set object.\n      for(let h in this.obj[this.group][0]) {\n        this.host = h;\n        this.host_obj = this.obj[this.group][0][h]\n        break;\n      }\n\n      if(this.host_obj["errors"].length > 0)\n        this.clicked_node.classList.add("error-red");\n      else \n        this.clicked_node.classList.add("ok-green");\n    }\n    /*** check_error_set_color END *****/\n\n    /*\n     * shorteners\n     */\n    ce(elem) {\n      return document.createElement(elem);\n    }\n    gid(elem) {\n      return document.getElementById(elem);\n    }\n    gc(elem) {\n      return document.getElementsByClassName(elem);\n    }\n    gt(elem) {\n      return document.getElementsByTagName(elem);\n    }\n    /*** shorteners END ****************/\n\n    set_active(elem) {\n      let all_items = document.getElementsByClassName(this.subListItemCssClass);\n      for(let i = 0; i< all_items.length; i++) {\n        all_items[i].classList.remove(this.activeListCssClass);\n      }\n\n      elem.classList.add(this.activeListCssClass);\n    }\n    /*\n     * Add click event for host item:\n     *  * sets clicked elem avtive\n     *  * builds html\n     *  * shows html\n     *  * makes tables expandable using class Expander\n     */\n    add_click_event(elem) {\n      elem.addEventListener("click", (e) => {\n        this.set_active(elem);\n        this.buildHTML(elem);\n        this.show_html().then(\n          (resp) => {\n            setTimeout(() => {\n              let heads = document.getElementsByTagName("thead");\n\n              for(let i = 0; i < heads.length; i++) {\n                let target = heads[i].parentNode.getElementsByTagName("tbody")[0];\n                let expander = new Expander(\n                  heads[i],\n                  target,\n                  "table-row-group",\n                  true\n                );\n              }\n            }, 100);\n          }\n        )\n      });\n    }\n    /*** add_click_event END ***********/\n\n    create_commands_table(type) {\n      const t = {\n        table: { \n          node: this.ce("table")\n        },\n        thead: {\n          tr: this.ce("tr"),\n          node: this.ce("thead")\n        },\n        tbody: {\n          node: this.ce("tbody")\n        },\n      };\n\n      t.thead.node.appendChild(t.thead.tr);\n\n      [\n        type,\n        "output"\n      ].map((text, i) => {\n        let th = this.ce("th");\n        th.textContent = text;\n        t.thead.tr.appendChild(th);\n      });\n\n      t.table.node.append(\n        t.thead.node,\n        t.tbody.node,\n      );\n\n      if(typeof(this.host_obj["config"]["settings"][type]) === "object") {\n        /*\n         * One array can be larger than the other.\n         * Find the larger one and use its length in the for loop.\n         */\n        const len = (\n          this.host_obj["config"]["settings"][type].length >\n            this.host_obj["output"][type].length\n        ) ? this.host_obj["config"]["settings"][type].length :\n              this.host_obj["output"][type].length;\n\n        for(let i = 0; i < len; i++) {\n          let tr = this.ce("tr");\n          let td1 = this.ce("td");\n          let td2 = this.ce("td");\n\n          td1.textContent = (\n            typeof(this.host_obj["config"]["settings"][type][i]) === "undefined"\n          ) ? "" : this.host_obj["config"]["settings"][type][i];\n          td2.textContent = (\n            typeof(this.host_obj["output"][type][i]) === "undefined"\n          ) ? "" : this.host_obj["output"][type][i];\n\n          tr.append(td1, td2);\n\n          t.tbody.node.appendChild(tr);\n        }\n      }\n\n      return t;\n    }\n    /*** create_commands_table END *****/\n\n    buildHTML(elem) {\n      // No dataset -> return\n      // This should not happen.\n      if(Object.keys(this.obj).length === 0)\n        return;\n\n      const body = this.ce("div");\n\n      const heading = this.ce("h2");\n      heading.textContent = `Host ${this.host}`;\n\n      const hr = this.ce("hr");\n\n      body.appendChild(heading);\n      body.appendChild(hr);\n\n      const div = this.ce("div");\n\n      /*\n       * Create summary table.\n       */\n      const summary = {\n        table: {\n          node: this.ce("table")\n        },\n        tbody: {\n          node: this.ce("tbody"),\n          tr: this.ce("tr"),\n          group: {\n            node: this.ce("td")\n          },\n          host: {\n            node: this.ce("td"),\n          },\n          user: {\n            node: this.ce("td"),\n          },\n          message: {\n            node: this.ce("td")\n          },\n          rc: {\n            node: this.ce("td")\n          },\n          errors: {\n            node: this.ce("td")\n          }\n\n        },\n        thead: {\n          node: this.ce("thead"),\n          tr: {\n            node: this.ce("tr")\n          },\n          th: {\n            group: {\n              node: this.ce("th")\n            },\n            host: {\n              node: this.ce("th")\n            },\n            user: {\n              node: this.ce("th")\n            },\n            message: {\n              node: this.ce("th")\n            },\n            rc: {\n              node: this.ce("th")\n            },\n            errors: {\n              node: this.ce("th")\n            }\n          }\n        }\n      };\n\n      summary.table.node.append(\n        summary.thead.node,\n        summary.tbody.node\n      );\n      summary.thead.node.append(\n        summary.thead.tr.node\n      );\n      summary.thead.tr.node.append(\n        summary.thead.th.group.node,\n        summary.thead.th.host.node,\n        summary.thead.th.user.node,\n        summary.thead.th.message.node,\n        summary.thead.th.rc.node,\n        summary.thead.th.errors.node,\n      );\n      [\n        summary.thead.th.group.node,\n        summary.thead.th.host.node,\n        summary.thead.th.user.node,\n        summary.thead.th.message.node,\n        summary.thead.th.rc.node,\n        summary.thead.th.errors.node,\n      ].map((node, i) => { \n        node.setAttribute("scope", "col");\n\n        switch(i) {\n          case 0:\n            node.textContent = "Group";\n            break;\n          case 1:\n            node.textContent = "Host";\n            break;\n          case 2:\n            node.textContent = "User";\n            break;\n          case 3:\n            node.textContent = "Message";\n            break;\n          case 4:\n            node.textContent = "rc";\n            break;\n          case 5:\n            node.textContent = "Errors";\n            break;\n        }\n      })\n\n      /*\n       * Create summary body.\n       */\n\n      summary.tbody.group.node.textContent = this.group;\n      summary.tbody.host.node.textContent = this.host;\n      summary.tbody.user.node.textContent = this.host_obj["config"]["credentials"]["user"];\n      summary.tbody.message.node.textContent = this.host_obj["message"];\n      if(this.host_obj["message"] !== "ok")\n        summary.tbody.message.node.classList.add("error-red");\n      summary.tbody.rc.node.textContent = this.host_obj["rc"];\n      summary.tbody.errors.node.textContent = this.host_obj["errors"].length;\n      if(this.host_obj["errors"].length > 0)\n        summary.tbody.errors.node.classList.add("error-red");\n\n      summary.tbody.node.appendChild(summary.tbody.tr);\n\n      summary.tbody.tr.append(\n        summary.tbody.group.node,\n        summary.tbody.host.node,\n        summary.tbody.user.node,\n        summary.tbody.message.node,\n        summary.tbody.rc.node,\n        summary.tbody.errors.node,\n      );\n\n      /*** summary END *******************/\n\n      /*\n       * Create errors table.\n       */\n      const t_errors = {\n        table: {\n          node: this.ce("table"),\n        },\n        thead: {\n          tr: this.ce("tr"),\n          node: this.ce("thead"),\n        },\n        tbody: {\n          node: this.ce("tbody"),\n        }\n      };\n\n      let th = this.ce("th");\n      th.textContent = "Errors";\n      t_errors.thead.tr.appendChild(th);\n\n      t_errors.thead.node.appendChild(\n        t_errors.thead.tr\n      );\n\n      t_errors.table.node.append(\n        t_errors.thead.node,\n        t_errors.tbody.node\n      );\n\n      for(let e in this.host_obj["errors"]) {\n        let tr = this.ce("tr");\n        let td = this.ce("td");\n        td.textContent = this.host_obj["errors"][e];\n        tr.appendChild(td);\n        t_errors.tbody.node.appendChild(tr);\n      }\n\n      /*\n       * Create table for settings.\n       */\n      const settings = {\n        table: { \n          node: this.ce("table")\n        },\n        thead: {\n          tr: this.ce("tr"),\n          node: this.ce("thead")\n        },\n        tbody: {\n          tr: this.ce("tr"),\n          node: this.ce("tbody")\n        },\n      };\n\n      settings.thead.node.append(settings.thead.tr);\n      settings.tbody.node.append(settings.tbody.tr)\n\n      settings.table.node.append(\n        settings.thead.node,\n        settings.tbody.node,\n      );\n\n      for(let k in this.host_obj["config"]["settings"]) {\n        // do not add cmds, yet \n        if(k.includes("cmds"))\n          continue;\n        \n        let th = this.ce("th");\n        th.textContent = k;\n        settings.thead.tr.append(th)\n        let td = this.ce("td");\n        td.textContent = this.host_obj["config"]["settings"][k]\n        settings.tbody.tr.append(td)\n      }\n      /*** settings table END ************/\n\n      /*\n       * Create cmds_before table.\n       */\n      const cmds_before = this.create_commands_table("cmds_before");\n      const cmds_after = this.create_commands_table("cmds_after");\n      const conf_cmds = this.create_commands_table("conf_cmds");\n\n      div.append(\n        summary.table.node,\n        t_errors.table.node,\n        settings.table.node,\n        cmds_before.table.node,\n        cmds_after.table.node,\n        conf_cmds.table.node,\n      );\n\n      body.appendChild(div);\n\n      /*\n       * Set html.\n       */\n      this.html = body;\n\n    }\n    /*** buildHTML END *****************/\n\n    show_html() {\n      return new Promise((resolve, reject) => {\n        this.contentNode.innerHTML = "";\n        this.contentNode.appendChild(\n          (this.error) ? this.error : this.html\n        );\n\n        resolve("ready");\n      });\n    }\n  }\n  /*** class HTMLBuilder END ******************************/\n\n  /*\n   * Make Groups expandable\n   */\n  const all_groups = document.getElementsByClassName("group-entry");\n  for(let i = 0; i < all_groups.length; i++)\xa0{\n    let expander = new Expander(all_groups[i], all_groups[i].nextSibling.nextSibling, "block");\n  }\n\n  /*\n   * Show report when host clicked.\n   */\n  const all_lists = document.getElementsByClassName("hosts-nav-sub");\n  for(let i = 0; i < all_lists.length; i++) {\n    let all_hosts = all_lists[i].getElementsByTagName("li");\n    for(let j = 0; j < all_hosts.length; j++) {\n      try {\n        let builder = new HTMLBuilder(all_hosts[j]);\n      }\n      catch(e) {\n        console.log(e);\n      }\n    }\n  }\n  \n  /*\n   * Filter hosts.\n   */\n  const filter_hosts =  new FilterHosts();\n\n})();\n    </script>\n  </body>\n</html>\n    '

Bottom part of the html page that can be generated as a report. Yes, it’s ugly but it works.

HTML_TOP = '<!doctype html>\n<html lang="en">\n  <head>\n    <meta charset="utf-8">\n    <!--<link rel="stylesheet" href="css/main.css">-->\n    <title>conquers report</title>\n<style>\n* { \n  box-sizing: border-box;\n}\n\nhtml,body {\n  font-family: Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;\n  background: #fcfcfc;\n  color: #404040;\n  padding: 0;\n  margin: 0;\n  font-size: 14px;\n}\n\nul {\n  list-style: none;\n  padding: 0;\n}\n\nh1,h2,h3 {\n  font-family: sans-serif;\n  letter-spacing: .1rem;\n  color: #404040;\n}\nhr {\n  display: block;\n  height: 1px;\n  border: 0;\n  border-top-width: 0px;\n  border-top-style: none;\n  border-top-color: currentcolor;\n  border-top: 1px solid #e1e4e5;\n  margin: 24px 0 55px 0;\n  padding: 0;\n}\n\na {\n  text-decoration: none;\n  color: #bbb;\n  font-size: 1rem;\n}\n\n.wrapper {\n  position: relative;\n  width: 100%;\n  margin-left: auto;\n  margin-right: auto;\n}\n\n.nav-stuff {\n  background: #2980b9;\n  padding: 1rem;\n  display: flex;\n  height: 267px;\n  justify-content: space-between;\n  flex-direction: column;\n}\n.footer {\n  background: #343131 !important;\n  height: 144px;\n}\nul.links li {\n  display: flex;\n  justify-content: row;\n  align-items: center;\n  height: 34px;\n}\nul.links li span {\n  color: #fcfcfc;\n  margin-left: 21px;\n}\n.nav-stuff span.title {\n  text-align: center;\n  color: #fcfcfc;\n  font-weight: bold;\n}\n.logo {\n  display: flex;\n  align-items: center;\n  justify-content: center;\n}\n\n.search-box {\n  position: relative;\n  height: 2rem;\n  color: #333;\n  display: flex;\n  align-items: center;\n  margin-left: 2rem;\n}\n.search-box::before {\n  content: "🔎";\n  position: absolute;\n  height: 2rem;\n  display: flex;\n  align-items: center;\n  font-size: 1.2rem;\n  margin-left: 1rem;\n  z-index: 2;\n}\n.search-box input {\n  position: relative;\n  width: 15rem;\n  padding-left: 2rem;\n  z-index: 1;\n  padding: 0.5rem 0.5rem 0.5rem 3rem;\n  border-radius: 2rem;\n  border: 1px solid #2472a4;\n  background: #fcfcfc;\n  color: #aaa;\n  font-style: italic;\n  transition: width .3s;\n}\n.search-box input:focus,\n.search-box input:active {\n  outline: none;\n}\n\n.main {\n  display: flex;\n  flex-direction: row\n}\n\n.hosts-nav-wrapper {\n  background: #fcfcfc;\n  height: calc(100vh - 5rem + 70px);\n  padding: 0;\n}\n.host-content-wrapper {\n  padding: 0 1rem;\n  width: 100%;\n  background: #fcfcfc;\n  height: calc(100vh - 5rem + 70px);\n}\n.hosts-nav-content {\n  width: 300px;\n  white-space: nowrap;\n  background: #343131;\n}\n\n.hosts-nav-content, .host-content {\n  overflow: auto;\n  height: calc(100vh - 5rem + 70px);\n  transition: width .3s;\n}\n.host-content {\n  padding: 2rem;\n  background: #fcfcfc;\n}\n\nlabel {\n  color: #55a5d9;\n  font-weight: bold;\n}\n\nlabel.alone {\n  display: block;\n  padding: .8rem;\n  font-weight: bold;\n  color: #55a5d9;\n}\n\nul.hosts-nav-entries, ul.hosts-nav-sub {\n  width: 100%;\n  list-style: none;\n  margin: 0;\n  padding: 0;\n}\nul.hosts-nav-entries li {\n  width: 100%;\n  margin: 0;\n  padding: .8rem;\n  cursor: pointer;\n  color: #d9d9d9;\n  background: #4e4a4a;\n}\nul.hosts-nav-entries li:hover {\n  background: #555050;\n}\n\n.sub-li {\n  padding: 0 !important;\n}\n.sub-li:hover {\n  background: #fcfcfc;\n}\n\nul.hosts-nav-sub li.sub-li-item {\n  background: #e3e3e3;\n  padding: .5rem;\n  padding-left: 2rem;\n  overflow: hidden;\n  text-overflow: ellipsis;\n  color: #404040;\n  border-right: 1px solid #c9c9c9;\n}\nul.hosts-nav-sub li:hover, ul.hosts-nav-sub li:focus, ul.hosts-nav-sub li:active {\n  background: #d6d6d6;\n}\n\n.sub-li-item-active {\n  background: #fcfcfc !important;\n  border-right: 1px solid #fcfcfc !important;\n  border-top: 1px solid #c9c9c9;\n  border-bottom: 1px solid #c9c9c9;\n}\n\nspan.info-box {\n  color: #999;\n  font-style: italic;\n  background: #fcfcfc;\n  padding: 1rem;\n  border-radius: 1rem;\n}\nspan.info-box::before {\n  content: "ℹ️ ";\n  font-style: normal;\n}\n\ntable {\n\tborder-collapse: collapse;\n  width: 100%;\n  box-shadow: 0 0 20px rgba(0, 0, 0, 0.15);\n  color: #555;\n  margin-bottom: 21px;\n}\ntable thead {\n  cursor: pointer;\n}\ntable thead tr {\n  background: #fcfcfc;\n  color: #555;\n  text-align: left;\n}\n\ntable th, table td {\n\tpadding: 12px 15px;\n}\ntd {\n}\ntd:first-child {\n  font-style: normal;\n}\n\ntable tbody tr {\n    border-bottom: 1px solid #ececec;\n}\n\ntable tbody td {\n  font-family: monospace;\n}\n\ntable tbody tr:nth-of-type(even) {\n  background: #fcfcfc;\n}\ntable tbody tr:nth-of-type(odd) {\n  background: #f7f7f7;\n}\n\ntable tbody tr:last-of-type {\n    border-bottom: 2px solid #d5d5d5;\n}\n\n.error-red {\n  /*color: #671c1c;*/\n  color: red !important;\n}\n.ok-green {\n  color: #457045;\n}\n\n.github::before {\n  content: \'\';\n  border-bottom: 0;\n  display: inline-block;\n  vertical-align: middle;\n  margin-right: 21px;\n  width: 26px;\n  height: 26px;\n  background: url("data:image/png;base64,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");\n  background-repeat: no-repeat;\n  background-size: contain;\n}\n</style>\n  </head>\n  <body>\n    <div class="wrapper">\n      <div class="main">\n        <div class="hosts-nav-wrapper">\n          <div class="hosts-nav-content">\n\n            <div class="nav-stuff">\n              <span class="title">conquers\n                report</span>\n              <div class="logo">\n                <img src="https://cdn.amendes.me/conquers/logo.svg" width=144 alt="logo">\n              </div>\n              <div class="search-box">\n                <input id="search-input" placeholder="filter hosts">\n              </div>\n            </div>\n\n            <label class="alone">🏘️ GROUPS:</label>\n            <ul class="hosts-nav-entries">\n'

Top part of the html page that can be generated as a report. Yes, it’s ugly but it works.

SOCKET_FILE = '/tmp/conquers.socket'

UNIX socket for IPC.

VERSION = 'conquers v0.1'
static set_abs_path() None[source]

Convert CHOME to absolute path and set CHOME_ABS_PATH.