diff --git a/Makefile b/Makefile index 4c384b0..ca04efb 100644 --- a/Makefile +++ b/Makefile @@ -1,16 +1,42 @@ +IMAGE_NAME := mamercad/ambientweather-exporter + +ifeq ($(IMAGE_TAG),) +IMAGE_TAG := latest +endif + .PHONY: build build: - docker build -t docker.io/mamercad/ambientweather-exporter:latest . - docker build -t ghcr.io/mamercad/ambientweather-exporter:latest . + docker build -t docker.io/$(IMAGE_NAME):$(IMAGE_TAG) . + docker build -t ghcr.io/$(IMAGE_NAME):$(IMAGE_TAG) . .PHONY: push push: build - docker push docker.io/mamercad/ambientweather-exporter:latest - docker push ghcr.io/mamercad/ambientweather-exporter:latest + docker push docker.io/$(IMAGE_NAME):$(IMAGE_TAG) + docker push ghcr.io/$(IMAGE_NAME):$(IMAGE_TAG) + +.PHONY: run +run: build + docker run -it -p 10102:10102/tcp \ + -e AMBI_APP_KEY=$(AMBI_APP_KEY) \ + -e AMBI_API_KEY=$(AMBI_API_KEY) \ + docker.io/$(IMAGE_NAME):$(IMAGE_TAG) -.PHONY: compose -compose: - docker-compose up +.PHONY: run-influx +run-influx: build + docker run -it -p 10102:10102/tcp \ + -e AMBI_APP_KEY=$(AMBI_APP_KEY) \ + -e AMBI_API_KEY=$(AMBI_API_KEY) \ + -e INFLUX_ENABLE=True \ + -e INFLUX_HOST=$(INFLUX_HOST) \ + docker.io/$(IMAGE_NAME):$(IMAGE_TAG) + +.PHONY: compose-up +compose-up: build + docker compose up -d + +.PHONY: compose-down +compose-down: + docker compose down .PHONY: install install: @@ -19,3 +45,14 @@ install: systemctl daemon-reload systemctl enable ambientweather-exporter systemctl start ambientweather-exporter + +.PHONY: helm-local +helm-local: + helm install my-ambientweather-exporter \ + --namespace ambientweather --create-namespace \ + --set deployment.tag="$(IMAGE_TAG)" \ + --set service.type="LoadBalancer" \ + --set secret.ambi_app_key="$(AMBI_APP_KEY)" \ + --set secret.ambi_api_key="$(AMBI_API_KEY)" \ + --set influx.enable=false \ + ./charts/ambientweather-exporter diff --git a/README.md b/README.md index f2e90a1..ad3787f 100644 --- a/README.md +++ b/README.md @@ -1,40 +1,119 @@ # ambientweather-exporter -Simple Python/Flask exporter for [AmbientWeather](https://ambientweather.net) that can be scraped by [Prometheus](https://prometheus.io). With that said, you'll need `flask` installed. I've also added support for pushing to [InfluxDB](https://www.influxdata.com/products/influxdb-overview/), but, I haven't tested it, let me know (you can set `$INFLUX_HOST`, `$INFLUX_PORT`, and `$INFLUX_DB` to override the defaults, `influxdb`, `8086`, `ambientweather`, respectively). The endpoints `/influx` or `/influxdb` will trigger the sending. +Simple Python/Flask exporter for [AmbientWeather](https://ambientweather.net) for [Prometheus](https://prometheus.io/) and [InfluxDB](https://www.influxdata.com/). +You can use it to pull (for Prometheus) and push (for InfluxDB) metrics from your personal weather station. +You will need to set up [AmbientWeather](https://ambientweather.docs.apiary.io/#introduction/authentication) application and API keys. +Take it easy on the AmbientWeather API; it's the weather, it doesn't change that quickly *smile* (you'll get a `429` if you hit their limits). -## Environment variables -Read up on this [here](https://ambientweather.docs.apiary.io/#introduction/authentication) and then: +## Metrics (Prometheus) ```bash -$ export AMBI_API_KEY= -$ export AMBI_APP_KEY= -$ ./ambientweather-exporter.py -* Serving Flask app "ambientweather-exporter" (lazy loading) -* Environment: production -WARNING: This is a development server. Do not use it in a production deployment. -Use a production WSGI server instead. -* Debug mode: on -* Running on http://0.0.0.0:10102/ (Press CTRL+C to quit) -* Restarting with stat -* Debugger is active! -* Debugger PIN: 150-675-683 -127.0.0.1 - - [08/Sep/2020 16:49:10] "GET / HTTP/1.1" 200 - +❯ curl -s localhost:10102 | head -1 +ambientweather_dateutc{macAddress="...",name="...",lat="...",lon="...",address="...",location="...",tz="..."} 1645376160000 +ambientweather_tempinf{macAddress="...",name="...",lat="...",lon="...",address="...",location="...",tz="..."} 66.9 +ambientweather_humidityin{macAddress="...",name="...",lat="...",lon="...",address="...",location="...",tz="..."} 37 ``` -From a client: +## Metrics (Influx) ```bash -$ curl -s http://localhost:10102 2>&1 | tail -3 -ambientweather_dewPoint{macAddress="REDACTED",name="CLOUDMASON",lat="REDACTED",lon="REDACTED",address="REDACTED",location="REDACTED",tz="America/Detroit"} 53.01 -ambientweather_feelsLikein{macAddress="REDACTED",name="CLOUDMASON",lat="REDACTED",lon="REDACTED",address="REDACTED",location="REDACTED",tz="America/Detroit"} 67.3 -ambientweather_dewPointin{macAddress="REDACTED",name="CLOUDMASON",lat="REDACTED",lon="REDACTED",address="REDACTED",location="REDACTED",tz="America/Detroit"} 49.6 +❯ curl -s localhost:10102/influx | head -3 +ambientweather_dateutc,macAddress="...",name="...",lat="...",lon="...",address="...",location="...",tz="..." value=1645376820000 1645376888607487600 +ambientweather_tempinf,macAddress="...",name="...",lat="...",lon="...",address="...",location="...",tz="..." value=66.7 1645376888607507600 +ambientweather_humidityin,macAddress="...",name="...",lat="...",lon="...",address="...",location="...",tz="..." value=37 1645376888607516200 ``` +## Help + +```bash +❯ python3 ./ambientweather-exporter.py --help +usage: ambientweather-exporter.py [-h] [--listen-on LISTEN_ON] + [--listen-port LISTEN_PORT] + [--ambi-app-key AMBI_APP_KEY] + [--ambi-api-key AMBI_API_KEY] + [--influx-enable] + [--influx-host INFLUX_HOST] + [--influx-port INFLUX_PORT] + [--influx-db INFLUX_DB] + [--influx-interval INFLUX_INTERVAL] + +optional arguments: + -h, --help show this help message and exit + --listen-on LISTEN_ON + IP address to listen on (default $LISTEN_ON if set, + else, '0.0.0.0') + --listen-port LISTEN_PORT + Port to listen on (default 10102) + --ambi-app-key AMBI_APP_KEY + AmbientWeather application key + --ambi-api-key AMBI_API_KEY + AmbientWeather API key + --influx-enable Enable InfluxDB exporting (default False) + --influx-host INFLUX_HOST + InfluxDB host (default 'influxdb') + --influx-port INFLUX_PORT + InfluxDB port (default 8086) + --influx-db INFLUX_DB + InfluxDB database (default 'ambientweather') + --influx-interval INFLUX_INTERVAL + InfluxDB sending interval (default 300s) +``` + +## Python + +```bash +❯ pip3 install -r requirements.txt +... + +❯ AMBI_APP_KEY=hunter2 AMBI_API_KEY=hunter2 python3 ./ambientweather-exporter.py +INFO:ambientweather-exporter:Starting server + * Serving Flask app "ambientweather-exporter" (lazy loading) + * Environment: production + WARNING: This is a development server. Do not use it in a production deployment. + Use a production WSGI server instead. + * Debug mode: on +INFO:werkzeug: * Running on http://0.0.0.0:10102/ (Press CTRL+C to quit) +INFO:werkzeug: * Restarting with stat +INFO:ambientweather-exporter:Starting server +WARNING:werkzeug: * Debugger is active! +INFO:werkzeug: * Debugger PIN: 999-984-877 +``` + +## Docker + +Run a Prometheus exporter on `10102/tcp`: + +```bash +❯ docker run -it -p 10102:10102/tcp \ + -e AMBI_APP_KEY=$AMBI_APP_KEY \ + -e AMBI_API_KEY=$AMBI_API_KEY \ + mamercad/ambientweather-exporter:latest +... +``` + +Run a InfluxDB shipper (every 900s): + +```bash +❯ docker run -it \ + -e AMBI_APP_KEY=$AMBI_APP_KEY \ + -e AMBI_API_KEY=$AMBI_API_KEY \ + -e INFLUX_ENABLE=True \ + -e INFLUX_HOST=influxdb.example.com \ + -e INFLUX_PORT=8086 \ + -e INFLUX_INTERVAL=900 + mamercad/ambientweather-exporter:latest +... +``` + +## Docker Compose + +There is a [docker-compose.yml](./docker-compose.yml) to check out. + ## Helm -[Helm](https://helm.sh) must be installed to use the charts. Please refer to -Helm's [documentation](https://helm.sh/docs) to get started. +[Helm](https://helm.sh) must be installed to use the charts. +Please refer to Helm's [documentation](https://helm.sh/docs) to get started. Once Helm has been set up correctly, add the repo as follows: diff --git a/ambientweather-exporter.py b/ambientweather-exporter.py index 14fbe78..5ab6517 100755 --- a/ambientweather-exporter.py +++ b/ambientweather-exporter.py @@ -1,135 +1,322 @@ #!/usr/bin/env python3 +import argparse import json.decoder import logging import os import requests import sys import time - from flask import Flask -app = Flask(__name__) +class FormatInflux(object): + def __init__(self, logger, args, weather_data): + self.logger = logger + self.args = args + self.weather_data = weather_data + + def sanitize(self, metric): + m = str(metric) + m = m.replace(" ", "_") + m = m.replace(",", "_") + return m -listen_on = "0.0.0.0" -listen_port = os.getenv("EXPORTER_PORT", "10102") -ambi_app_key = os.getenv("AMBI_APP_KEY") -ambi_api_key = os.getenv("AMBI_API_KEY") -influx_host = os.getenv("INFLUX_HOST", "influxdb") -influx_port = os.getenv("INFLUX_PORT", "8086") -influx_db = os.getenv("INFLUX_DB", "ambientweather") + def get_metrics(self): + self.logger.info("Formatting Influx metrics") + influx_metrics = [] + tagset = 'macAddress="{}",name="{}",lat="{}",lon="{}",address="{}",location="{}",tz="{}"'.format( + self.sanitize(self.weather_data["macAddress"]), + self.sanitize(self.weather_data["info"]["name"]), + self.sanitize(self.weather_data["info"]["coords"]["coords"]["lat"]), + self.sanitize(self.weather_data["info"]["coords"]["coords"]["lon"]), + self.sanitize(self.weather_data["info"]["coords"]["address"]), + self.sanitize(self.weather_data["info"]["coords"]["location"]), + self.sanitize(self.weather_data["lastData"]["tz"]), + ) + for k in self.weather_data["lastData"].keys(): + if k not in ["lastRain", "tz", "date"]: + influx_metrics.append( + f"ambientweather_{k},{tagset} value={self.weather_data['lastData'][k]} {time.time_ns()}" + ) + self.logger.info(f"Returning {len(influx_metrics)} metrics for Influx") + return influx_metrics -logging.basicConfig( - stream=sys.stdout, - level=logging.DEBUG, -) -logger = logging.getLogger("ambientweather-exporter") + def create_database(self): + self.logger.info( + f"Creating InfluxDB database {self.args.influx_host}:{self.args.influx_port}/{self.args.influx_db}" + ) + r = requests.post( + f"http://{self.args.influx_host}:{self.args.influx_port}/query", + data={"q": f"CREATE DATABASE {self.args.influx_db}"}, + ) + status_code = r.status_code + if status_code != requests.codes.ok: + f"Got a {status_code} from InfluxDB at {self.args.influx_host}:{self.args.influx_port}/{self.args.influx_db}; creating the database" + else: + f"Created Influx database {self.args.influx_host}:{self.args.influx_port}/{self.args.influx_db}" + def post_metrics(self): + self.logger.info("Sending Influx metrics") + influx_metrics = self.get_metrics() + for metric in influx_metrics: + self.logger.info(metric) + r = requests.post( + f"http://{self.args.influx_host}:{self.args.influx_port}/write?db={self.args.influx_db}", + data=metric, + ) + status_code = r.status_code + if status_code != 204: + if status_code == 404: + self.logger.info( + f"Got a {status_code} from InfluxDB at {self.args.influx_host}:{self.args.influx_port}/{self.args.influx_db}; create the database" + ) + else: + self.logger.info( + f"Got a {status_code} from InfluxDB at {self.args.influx_host}:{self.args.influx_port}/{self.args.influx_db}; {metric}" + ) + else: + self.logger.info( + f"Sent {metric} to InfluxDB at {self.args.influx_host}:{self.args.influx_port}/{self.args.influx_db}" + ) -@app.route("/") -@app.route("/metrics") -def prometheus(): - metrics = ambientweather_prometheus() - logger.info(f"Prometheus scraped {len(metrics)} metrics from us") - return "\n".join(metrics) + "\n" +class FormatPrometheus(object): + def __init__(self, logger, args, weather_data): + self.logger = logger + self.args = args + self.weather_data = weather_data -@app.route("/influx") -@app.route("/influxdb") -def influx(): - metrics = ambientweather_influx() - logger.info(f"Shipped {len(metrics)} metrics to InfluxDB") - for metric in metrics: - r = requests.post( - f"http://{influx_host}:{influx_port}/write?db={influx_db}", data=metric + def get_metrics(self): + self.logger.info("Formatting Prometheus metrics") + prom_metrics = [] + labels = 'macAddress="{}",name="{}",lat="{}",lon="{}",address="{}",location="{}",tz="{}"'.format( + self.weather_data["macAddress"], + self.weather_data["info"]["name"], + self.weather_data["info"]["coords"]["coords"]["lat"], + self.weather_data["info"]["coords"]["coords"]["lon"], + self.weather_data["info"]["coords"]["address"], + self.weather_data["info"]["coords"]["location"], + self.weather_data["lastData"]["tz"], ) - status_code = r.status_code + for k in self.weather_data["lastData"].keys(): + if k not in ["lastRain", "tz", "date"]: + prom_metrics.append( + "ambientweather_{}{{{}}} {}".format( + k, labels, self.weather_data["lastData"][k] + ) + ) + self.logger.info(f"Returning {len(prom_metrics)} metrics for Prometheus") + return prom_metrics + + +class AmbientWeather(object): + def __init__(self, logger, args): + self.logger = logger + self.args = args + + def fetch_weather(self): + self.logger.info("Fetching data from AmbientWeather") + self.r = requests.get( + f"https://api.ambientweather.net/v1/devices?applicationKey={self.args.ambi_app_key}&apiKey={self.args.ambi_api_key}" + ) + status_code = self.r.status_code if status_code != requests.codes.ok: - raise Exception( - f"Got a {status_code} from InfluxDB at {influx_host}:{influx_port}" + self.logger.error( + f"Got a {status_code} from AmbientWeather; check your AmbientWeather application and API keys" ) + else: + try: + weather_data = self.r.json() + if len(weather_data) == 1: + self.logger.info("Got a row of data from AmbientWeather") + return weather_data[0] + else: + self.logger.error( + f"Didn't get a single result from AmbientWeather (got {len(weather_data)} results)" + ) + except json.decoder.JSONDecodeError: + self.logger.error("Could not decode AmbientWeather result into JSON") + raise + +class SetupLogger(object): + def __init__(self): + logging.basicConfig(stream=sys.stdout, level=logging.DEBUG) + self.logger = logging.getLogger("ambientweather-exporter") -def get_ambientweather_data(): - logger.info("Fetching data from AmbientWeather") - global ambi_app_key, ambi_api_key - r = requests.get( - f"https://api.ambientweather.net/v1/devices?applicationKey={ambi_app_key}&apiKey={ambi_api_key}" - ) - status_code = r.status_code - if status_code != requests.codes.ok: - raise Exception( - f"Got a {status_code} from AmbientWeather; check your $AMBI_APP_KEY and $AMBI_API_KEY" + def info(self, message): + self.logger.info(message) + + def error(self, message): + self.logger.error(message) + + +class GetArgs(object): + def __init__(self): + self.parser = argparse.ArgumentParser() + self.parser.add_argument( + "--listen-on", + help="IP address to listen on (default $LISTEN_ON if set, else, '0.0.0.0')", + default=os.getenv("LISTEN_ON", "0.0.0.0"), + ) + self.parser.add_argument( + "--listen-port", + help="Port to listen on (default 10102)", + type=int, + default=os.getenv("LISTEN_PORT", 10102), + ) + self.parser.add_argument( + "--ambi-app-key", + help="AmbientWeather application key", + default=os.getenv("AMBI_APP_KEY"), ) - try: - weather_data = r.json() - if len(weather_data) == 1: - logger.info("Got a row of data from AmbientWeather") - return weather_data[0] + self.parser.add_argument( + "--ambi-api-key", + help="AmbientWeather API key", + default=os.getenv("AMBI_API_KEY"), + ) + self.parser.add_argument( + "--influx-enable", + help="Enable InfluxDB exporting (default False)", + action="store_true", + default=os.getenv("INFLUX_ENABLE", False), + ) + self.parser.add_argument( + "--influx-host", + help="InfluxDB host (default 'influxdb')", + default=os.getenv("INFLUX_HOST", "influxdb"), + ) + self.parser.add_argument( + "--influx-port", + help="InfluxDB port (default 8086)", + type=int, + default=os.getenv("INFLUX_PORT", 8086), + ) + self.parser.add_argument( + "--influx-db", + help="InfluxDB database (default 'ambientweather')", + default=os.getenv("INFLUX_DB", "ambientweather"), + ) + self.parser.add_argument( + "--influx-interval", + help="InfluxDB sending interval in seconds (default 300)", + type=int, + default=os.getenv("INFLUX_INTERVAL", 300), + ) + self.args = self.parser.parse_args() + + @property + def listen_on(self): + return self.args.listen_on + + @property + def listen_port(self): + return self.args.listen_port + + @property + def ambi_app_key(self): + return self.args.ambi_app_key + + @property + def ambi_api_key(self): + return self.args.ambi_api_key + + @property + def influx_enable(self): + return self.args.influx_enable + + @property + def influx_host(self): + return self.args.influx_host + + @property + def influx_port(self): + return self.args.influx_port + + @property + def influx_db(self): + return self.args.influx_db + + @property + def influx_interval(self): + return self.args.influx_interval + + +class RunInflux(object): + def __init__(self, logger, args): + self.logger = logger + self.args = args + self.influx_host = self.args.influx_host + self.influx_port = self.args.influx_port + self.influx_interval = self.args.influx_interval + self.logger.info("Starting Influx shipper") + self.aw = AmbientWeather(logger, args) + self.ping() + self.ship() + + def ping(self): + try: + ping_endpoint = f"http://{self.influx_host}:{self.influx_port}/ping" + r = requests.get(ping_endpoint) + status_code = r.status_code + if status_code != 204: + self.logger.error( + f"Unhappy {status_code} from Influx at {ping_endpoint}" + ) + sys.exit(1) + else: + self.logger.info(f"Happy {status_code} from Influx at {ping_endpoint}") + except requests.exceptions.RequestException as e: # This is the correct syntax + self.logger.error(f"Could not connect to Influx at {ping_endpoint}") + raise SystemExit(e) + + def ship(self): + if self.influx_interval < 0: + self.logger.error("Influx sleep interval cannot be negative") + elif self.influx_interval == 0: + self.logger.error("Influx sleep interval is zero") else: - logger.error("Not expecting more than one row of data") - except json.decoder.JSONDecodeError: - logger.error("Could not decode AmbientWeather into JSON") - raise - - -def ambientweather_prometheus(): - logger.info("Collecting Prometheus metrics") - prom_data = [] - data = get_ambientweather_data() - labels = 'macAddress="{}",name="{}",lat="{}",lon="{}",address="{}",location="{}",tz="{}"'.format( - data["macAddress"], - data["info"]["name"], - data["info"]["coords"]["coords"]["lat"], - data["info"]["coords"]["coords"]["lon"], - data["info"]["coords"]["address"], - data["info"]["coords"]["location"], - data["lastData"]["tz"], - ) - for k in data["lastData"].keys(): - if k not in ["lastRain", "tz", "date"]: - prom_data.append( - "ambientweather_{}{{{}}} {}".format(k, labels, data["lastData"][k]) - ) - logger.info(f"Returning {len(prom_data)} metrics for Prometheus") - return prom_data - - -def ambientweather_influx(): - logger.info("Collecting Influx metrics") - influx_data = [] - data = get_ambientweather_data() - tagset = 'macAddress="{}",name="{}",lat="{}",lon="{}",address="{}",location="{}",tz="{}"'.format( - data["macAddress"], - data["info"]["name"], - data["info"]["coords"]["coords"]["lat"], - data["info"]["coords"]["coords"]["lon"], - data["info"]["coords"]["address"], - data["info"]["coords"]["location"], - data["lastData"]["tz"], - ) - for k in data["lastData"].keys(): - if k not in ["lastRain", "tz", "date"]: - influx_data.append( - f"ambientweather_{k},{tagset} value={data['lastData'][k]} {time.time_ns()}" + self.logger.info( + f"Shipping Influx metrics every {self.influx_interval} seconds" ) + influx = FormatInflux(self.logger, self.args, None) + influx.create_database() + while True: + self.logger.info( + f"Sleeping for {self.args.influx_interval} seconds before shipping to Influx" + ) + time.sleep(self.influx_interval) + weather_data = self.aw.fetch_weather() + influx = FormatInflux(self.logger, self.args, weather_data) + influx.post_metrics() + + +class RunPrometheus(object): + def __init__(self, logger, args): + self.app = Flask(__name__) + self.logger = logger + self.args = args + self.aw = AmbientWeather(logger, args) + self.logger.info("Starting Prometheus exporter") + + @self.app.route("/") + @self.app.route("/metrics") + def prometheus(): + self.logger.info("Prometheus metrics requested") + weather_data = self.aw.fetch_weather() + prom = FormatPrometheus(self.logger, self.args, weather_data) + metrics = prom.get_metrics() + self.logger.info(f"Prometheus scraped {len(metrics)} metrics from us") + return "\n".join(metrics) + "\n" - logger.info(f"Returning {len(influx_data)} metrics for Influx") - return influx_data + self.app.run(debug=True, host=self.args.listen_on, port=self.args.listen_port) if __name__ == "__main__": - if not ambi_app_key or not ambi_api_key: - raise Exception("Ensure that both $AMBI_APP_KEY and $AMBI_API_KEY are set!") - - logger.info(f"Listening on {listen_on}:{listen_port}") - logger.info( - f"Prometheus metrics at http://{listen_on}:{listen_port} or http://{listen_on}:{listen_port}/metrics" - ) - logger.info(f"InfluxDB destination set as {influx_host}:{influx_port}/{influx_db}") - logger.info( - f"Trigger sending to InfluxDB with http://{listen_on}:{listen_port}/influx or http://{listen_on}:{listen_port}/influxdb" - ) - - app.run(debug=True, host=listen_on, port=int(listen_port)) + logger = SetupLogger() + args = GetArgs() + if args.influx_enable: + RunInflux(logger, args) + else: + RunPrometheus(logger, args) diff --git a/ambientweather-exporter.service b/ambientweather-exporter.service index a97923c..9fcf970 100644 --- a/ambientweather-exporter.service +++ b/ambientweather-exporter.service @@ -1,5 +1,5 @@ [Unit] -Description=AmbientWeather Prometheus Exporter +Description=AmbientWeather Prometheus and InfluxDB Exporter After=network.target StartLimitIntervalSec=0 diff --git a/charts/ambientweather-exporter/Chart.yaml b/charts/ambientweather-exporter/Chart.yaml index 9e3044c..a48cd1a 100644 --- a/charts/ambientweather-exporter/Chart.yaml +++ b/charts/ambientweather-exporter/Chart.yaml @@ -2,5 +2,5 @@ apiVersion: v2 name: ambientweather-exporter description: A Helm chart for the AmbientWeather Exporter type: application -version: 0.4.0 -appVersion: "0.4.0" +version: 0.5.0 +appVersion: "0.5.0" diff --git a/charts/ambientweather-exporter/templates/deployment.yaml b/charts/ambientweather-exporter/templates/deployment.yaml index be01e07..07c7255 100644 --- a/charts/ambientweather-exporter/templates/deployment.yaml +++ b/charts/ambientweather-exporter/templates/deployment.yaml @@ -1,5 +1,5 @@ -kind: Deployment apiVersion: apps/v1 +kind: Deployment metadata: name: "{{ .Release.Name }}" namespace: "{{ .Release.Namespace }}" @@ -25,6 +25,10 @@ spec: - name: http containerPort: {{ .Values.service.exporter_port }} env: + - name: LISTEN_ON + value: "0.0.0.0" + - name: LISTEN_PORT + value: "{{ .Values.service.exporter_port }}" - name: AMBI_APP_KEY valueFrom: secretKeyRef: @@ -35,11 +39,15 @@ spec: secretKeyRef: name: "{{ .Release.Name }}-creds" key: AMBI_API_KEY +{{ if .Values.influx.enable }} + - name: INFLUX_ENABLE + value: "true" - name: INFLUX_HOST value: "{{ .Values.influx.host }}" - name: INFLUX_PORT value: "{{ .Values.influx.port }}" - name: INFLUX_DB value: "{{ .Values.influx.db }}" - - name: EXPORTER_PORT - value: "{{ .Values.service.exporter_port }}" + - name: INFLUX_INTERVAL + value: "{{ .Values.influx.interval }}" +{{ end }} diff --git a/charts/ambientweather-exporter/templates/secret.yaml b/charts/ambientweather-exporter/templates/secret.yaml index 0843a0f..2325d7b 100644 --- a/charts/ambientweather-exporter/templates/secret.yaml +++ b/charts/ambientweather-exporter/templates/secret.yaml @@ -1,5 +1,5 @@ -kind: Secret apiVersion: v1 +kind: Secret data: AMBI_APP_KEY: "{{ .Values.secret.ambi_app_key | b64enc }}" AMBI_API_KEY: "{{ .Values.secret.ambi_api_key | b64enc }}" diff --git a/charts/ambientweather-exporter/templates/service.yaml b/charts/ambientweather-exporter/templates/service.yaml index 5d9ab6f..9dd3d3a 100644 --- a/charts/ambientweather-exporter/templates/service.yaml +++ b/charts/ambientweather-exporter/templates/service.yaml @@ -3,6 +3,9 @@ kind: Service metadata: name: "{{ .Release.Name }}" namespace: "{{ .Release.Namespace }}" + annotations: + prometheus.io/port: "{{ .Values.service.exporter_port }}" + prometheus.io/scrape: "true" labels: deploy: "{{ .Release.Name }}" helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" diff --git a/charts/ambientweather-exporter/values.yaml b/charts/ambientweather-exporter/values.yaml index 90b15b7..7edc240 100644 --- a/charts/ambientweather-exporter/values.yaml +++ b/charts/ambientweather-exporter/values.yaml @@ -11,6 +11,8 @@ secret: ambi_api_key: hunter2 influx: + enable: false host: influxdb port: 8086 db: ambientweather + interval: 300 diff --git a/docker-compose.yml b/docker-compose.yml index 259fe07..878b884 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -5,14 +5,22 @@ services: ports: - "8086:8086" - exporter: + prom-exporter: image: ghcr.io/mamercad/ambientweather-exporter:latest ports: - - "${EXPORTER_PORT:-10102}:${EXPORTER_PORT:-10102}" + - "${LISTEN_PORT:-10102}:${LISTEN_PORT:-10102}" environment: + LISTEN_ON: 0.0.0.0 + LISTEN_PORT: 10102 AMBI_APP_KEY: ${AMBI_APP_KEY} AMBI_API_KEY: ${AMBI_API_KEY} + + influx-exporter: + image: ghcr.io/mamercad/ambientweather-exporter:latest + environment: + AMBI_APP_KEY: ${AMBI_APP_KEY} + AMBI_API_KEY: ${AMBI_API_KEY} + INFLUX_ENABLE: "True" INFLUX_HOST: ${INFLUX_HOST:-influxdb} INFLUX_PORT: ${INFLUX_PORT:-8086} INFLUX_DB: ${INFLUX_DB:-ambientweather} - EXPORTER_PORT: ${EXPORTER_PORT:-10102}