Merge pull request #391 from Roundaround/portainer

Added Portainer custom service
This commit is contained in:
Bastien Wirtz 2022-03-06 22:23:34 +01:00 committed by GitHub
commit 120ee25bf5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 138 additions and 0 deletions

View 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"
```

View File

@ -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;
},
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>