]> git.immae.eu Git - github/bastienwirtz/homer.git/commitdiff
Added Portainer custom service
authorEvan Steinkerchner <esteinkerchner@gmail.com>
Wed, 2 Mar 2022 01:55:45 +0000 (20:55 -0500)
committerEvan Steinkerchner <esteinkerchner@gmail.com>
Wed, 2 Mar 2022 01:55:45 +0000 (20:55 -0500)
docs/customservices.md
src/components/services/Portainer.vue [new file with mode: 0644]

index 7e3e6b3e60a9c4f48962e10b3087f73e6ab180a3..cb68e1de961c283e090eb2771ed770c62b5ad8b3 100644 (file)
@@ -125,3 +125,19 @@ For Prometheus you need to set the type to Prometheus and provide a url.
   url: "http://192.168.0.151/"
   # subtitle: "Monitor data server"
 ```
+
+## Portainer
+
+This service displays info about the total number of containers managed by your Portainer instance.
+In order to use it, you must be using Portainer version 1.11 or later. Generate an access token from the UI and pass
+it to the apikey field.
+
+See https://docs.portainer.io/v/ce-2.11/user/account-settings#access-tokens
+
+```yaml
+- name: "Portainer"
+  logo: "assets/tools/sample.png"
+  url: "http://192.168.0.151/"
+  type: "Portainer"
+  apikey: "MY-SUPER-SECRET-API-KEY"
+```
diff --git a/src/components/services/Portainer.vue b/src/components/services/Portainer.vue
new file mode 100644 (file)
index 0000000..0af30eb
--- /dev/null
@@ -0,0 +1,122 @@
+<template>
+  <Generic :item="item">
+    <template #indicator>
+      <div class="notifs">
+        <strong v-if="running > 0" class="notif running" title="Running">
+          {{ running }}
+        </strong>
+        <strong v-if="dead > 0" class="notif dead" title="Dead">
+          {{ dead }}
+        </strong>
+        <strong v-if="misc > 0" class="notif misc" title="Other (creating, paused, exited, etc.)">
+          {{ misc }}
+        </strong>
+      </div>
+    </template>
+  </Generic>
+</template>
+
+<script>
+import service from "@/mixins/service.js";
+import Generic from "./Generic.vue";
+
+export default {
+  name: "Portainer",
+  mixins: [service],
+  props: {
+    item: Object,
+  },
+  components: {
+    Generic,
+  },
+  data: () => ({
+    endpoints: null,
+    containers: null,
+  }),
+  computed: {
+    running: function () {
+      if (!this.containers) {
+        return "";
+      }
+      return this.containers.filter((container) => {
+        return container.State.toLowerCase() === "running";
+      }).length;
+    },
+    dead: function () {
+      if (!this.containers) {
+        return "";
+      }
+      return this.containers.filter((container) => {
+        return container.State.toLowerCase() === "dead";
+      }).length || 1;
+    },
+    misc: function () {
+      if (!this.containers) {
+        return "";
+      }
+      return this.containers.filter((container) => {
+        return container.State.toLowerCase() !== "running" && container.State.toLowerCase() !== "dead";
+      }).length;
+    },
+  },
+  created() {
+    this.fetchStatus();
+  },
+  methods: {
+    fetchStatus: async function () {
+      const headers = {
+        "X-Api-Key": this.item.apikey,
+      };
+
+      this.endpoints = await this.fetch("/api/endpoints", { headers })
+        .catch((e) => {
+          console.error(e);
+        });
+
+      let containers = [];
+      for (let endpoint of this.endpoints) {
+        const uri = `/api/endpoints/${endpoint.Id}/docker/containers/json?all=1`;
+        const endpointContainers = await this.fetch(uri, { headers })
+          .catch((e) => {
+            console.error(e);
+          });
+
+        containers = containers.concat(endpointContainers);
+      }
+
+      this.containers = containers;
+    },
+  },
+};
+</script>
+
+<style scoped lang="scss">
+.notifs {
+  position: absolute;
+  color: white;
+  font-family: sans-serif;
+  top: 0.3em;
+  right: 0.5em;
+
+  .notif {
+    display: inline-block;
+    padding: 0.2em 0.35em;
+    border-radius: 0.25em;
+    position: relative;
+    margin-left: 0.3em;
+    font-size: 0.8em;
+
+    &.running {
+      background-color: #4fd671;
+    }
+
+    &.dead {
+      background-color: #e51111;
+    }
+
+    &.misc {
+      background-color: #2ed0c8;
+    }
+  }
+}
+</style>