diff --git a/helm-charts/aws-ce-grafana-backend/mounted-files/webserver.py b/helm-charts/aws-ce-grafana-backend/mounted-files/webserver.py index f0baaab6fe..7606e09ac4 100644 --- a/helm-charts/aws-ce-grafana-backend/mounted-files/webserver.py +++ b/helm-charts/aws-ce-grafana-backend/mounted-files/webserver.py @@ -1,5 +1,5 @@ import logging -from datetime import date, datetime, timedelta, timezone +from datetime import datetime, timedelta, timezone from flask import Flask, request @@ -16,30 +16,41 @@ def _parse_from_to_in_query_params(): """ - Parse "from" and "to" query parameters, expected to arrive as YYYY-MM-DD - strings. - - # FIXME: Avoid... - # botocore.exceptions.ClientError: An error occurred (ValidationException) when calling the GetCostAndUsage operation: end date past the beginning of next month + Parse "from" and "to" query parameters, expected to be passed as YYYY-MM-DD + formatted strings or including time as well. - "to" defaults to current date (UTC) - "from" defaults to 30 days before what to is set to + + Note that Python 3.11 is required to parse a datetime like + 2024-07-27T15:50:18.231Z with a Z in the end, and that Grafana's + `${__from:date}` variable is UTC based, but as soon as its adjusted with a + custom format, it no longer is UTC based. Due to that, we need to be able to + parse the full datetime string. """ + now_date = datetime.now(timezone.utc).date() if request.args.get("to"): - to_dt = date.fromisoformat(request.args["to"]) + to_date = datetime.fromisoformat(request.args["to"]).date() else: - to_dt = datetime.now(timezone.utc).date() + to_date = now_date if request.args.get("from"): - from_dt = date.fromisoformat(request.args["from"]) + from_date = datetime.fromisoformat(request.args["from"]).date() else: - from_dt = to_dt - timedelta(days=30) - - # the end date gets excluded, so add one day to get it included - to_dt += timedelta(days=1) + from_date = to_date - timedelta(days=30) + + # the to_date isn't included when declaring start/end dates against the AWS + # CE API, so we try to add one day to it to make it inclusive + to_date = to_date + timedelta(days=1) + # prevent "end date past the beginning of next month" errors + if to_date > now_date: + to_date = now_date + # prevent "Start date (and hour) should be before end date (and hour)" + if from_date >= now_date: + from_date = to_date - timedelta(days=1) # format back to YYYY-MM-DD strings - from_date = from_dt.strftime("%Y-%m-%d") - to_date = to_dt.strftime("%Y-%m-%d") + from_date = from_date.strftime("%Y-%m-%d") + to_date = to_date.strftime("%Y-%m-%d") return from_date, to_date