From 56470c57185fd4b8b909244ca6f4191101cea2c8 Mon Sep 17 00:00:00 2001 From: Erik Sundell Date: Sat, 24 Aug 2024 17:27:23 +0200 Subject: [PATCH 1/3] terraform: add aws-ce-grafana-backend IAM requirements --- terraform/aws/aws-ce-grafana-backend-iam.tf | 48 +++++++++++++++++++++ terraform/aws/variables.tf | 10 ++++- 2 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 terraform/aws/aws-ce-grafana-backend-iam.tf diff --git a/terraform/aws/aws-ce-grafana-backend-iam.tf b/terraform/aws/aws-ce-grafana-backend-iam.tf new file mode 100644 index 000000000..225a60065 --- /dev/null +++ b/terraform/aws/aws-ce-grafana-backend-iam.tf @@ -0,0 +1,48 @@ +resource "aws_iam_role" "aws_ce_grafana_backend_iam_role" { + count = var.enable_aws_ce_grafana_backend_iam ? 1 : 0 + + name = "aws_ce_grafana_backend_iam_role" + tags = var.tags + + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [{ + Effect = "Allow", + Action = "sts:AssumeRoleWithWebIdentity", + Principal = { + Federated = "arn:${data.aws_partition.current.partition}:iam::${data.aws_caller_identity.current.account_id}:oidc-provider/${replace(data.aws_eks_cluster.cluster.identity[0].oidc[0].issuer, "https://", "")}" + }, + + # FIXME: Below we have a string including ce-test:ce-test, it should be support: + + Condition = { + StringEquals = { + "${replace(data.aws_eks_cluster.cluster.identity[0].oidc[0].issuer, "https://", "")}:sub" = "system:serviceaccount:ce-test:ce-test" + } + }, + }] + }) + + inline_policy { + name = "aws_ce_grafana_backend_iam_policy" + + # ref: https://docs.aws.amazon.com/service-authorization/latest/reference/list_awscostexplorerservice.html + policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Effect = "Allow", + Action = [ + "ce:Get*", + "ce:List*", + ], + Resource = "*", + }, + ] + }) + } +} + +output "aws_ce_grafana_backend_k8s_sa_annotation" { + value = var.enable_aws_ce_grafana_backend_iam ? "eks.amazonaws.com/role-arn: ${aws_iam_role.aws_ce_grafana_backend_iam_role[0].arn}" : null +} diff --git a/terraform/aws/variables.tf b/terraform/aws/variables.tf index 568d62f9e..226d58a55 100644 --- a/terraform/aws/variables.tf +++ b/terraform/aws/variables.tf @@ -273,4 +273,12 @@ variable "enable_grafana_athena_iam" { Create an IAM role with attached policy to permit a connection between a Grafana instance and AWS Athena service. EOT -} \ No newline at end of file +} + +variable "enable_aws_ce_grafana_backend_iam" { + type = bool + default = false + description = <<-EOT + Create an IAM role with attached policy to permit read use of AWS Cost Explorer API. + EOT +} From 4452ead91ec59dc6a0f6e551921997b5e3555d7e Mon Sep 17 00:00:00 2001 From: Erik Sundell Date: Sat, 24 Aug 2024 17:28:00 +0200 Subject: [PATCH 2/3] terraform, openscapes: opt-in to create AWS CE IAM Role --- terraform/aws/projects/openscapes.tfvars | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/terraform/aws/projects/openscapes.tfvars b/terraform/aws/projects/openscapes.tfvars index 16bba945e..a1470a00e 100644 --- a/terraform/aws/projects/openscapes.tfvars +++ b/terraform/aws/projects/openscapes.tfvars @@ -8,9 +8,10 @@ default_budget_alert = { "enabled" : false, } -enable_grafana_athena_iam = true -athena_write_storage_bucket = "openscapes-cost-usage-report" -athena_read_storage_bucket = "openscapes-2i2c-cur" +enable_grafana_athena_iam = true +enable_aws_ce_grafana_backend_iam = true +athena_write_storage_bucket = "openscapes-cost-usage-report" +athena_read_storage_bucket = "openscapes-2i2c-cur" # Remove this variable to tag all our resources with {"ManagedBy": "2i2c"} From 82e3ef24391cd202fa99f74beae29587d86d615a Mon Sep 17 00:00:00 2001 From: Erik Sundell Date: Fri, 23 Aug 2024 16:32:53 +0200 Subject: [PATCH 3/3] Add aws-ce-grafana-backend chart --- .pre-commit-config.yaml | 2 +- deployer/commands/validate/config.py | 4 + .../aws-ce-grafana-backend/.helmignore | 33 ++++ helm-charts/aws-ce-grafana-backend/Chart.yaml | 17 ++ .../ce-test-config.yaml | 4 + .../mounted-files/README.md | 69 ++++++++ .../mounted-files/__init__.py | 0 .../mounted-files/aws.py | 164 ++++++++++++++++++ .../mounted-files/webserver.py | 20 +++ .../templates/NOTES.txt | 73 ++++++++ .../templates/_helpers-extra-files.tpl | 72 ++++++++ .../templates/_helpers-labels.tpl | 19 ++ .../templates/_helpers-names.tpl | 113 ++++++++++++ .../templates/_helpers.tpl | 18 ++ .../templates/deployment.yaml | 76 ++++++++ .../templates/ingress.yaml | 35 ++++ .../templates/secret.yaml | 13 ++ .../templates/service.yaml | 19 ++ .../templates/serviceaccount.yaml | 12 ++ .../aws-ce-grafana-backend/values.schema.yaml | 140 +++++++++++++++ .../aws-ce-grafana-backend/values.yaml | 59 +++++++ helm-charts/chartpress.yaml | 5 + .../images/aws-ce-grafana-backend/Dockerfile | 53 ++++++ .../aws-ce-grafana-backend/requirements.txt | 2 + helm-charts/support/Chart.yaml | 7 + helm-charts/support/values.schema.yaml | 7 + helm-charts/support/values.yaml | 7 + 27 files changed, 1042 insertions(+), 1 deletion(-) create mode 100644 helm-charts/aws-ce-grafana-backend/.helmignore create mode 100644 helm-charts/aws-ce-grafana-backend/Chart.yaml create mode 100644 helm-charts/aws-ce-grafana-backend/ce-test-config.yaml create mode 100644 helm-charts/aws-ce-grafana-backend/mounted-files/README.md create mode 100644 helm-charts/aws-ce-grafana-backend/mounted-files/__init__.py create mode 100644 helm-charts/aws-ce-grafana-backend/mounted-files/aws.py create mode 100644 helm-charts/aws-ce-grafana-backend/mounted-files/webserver.py create mode 100644 helm-charts/aws-ce-grafana-backend/templates/NOTES.txt create mode 100644 helm-charts/aws-ce-grafana-backend/templates/_helpers-extra-files.tpl create mode 100644 helm-charts/aws-ce-grafana-backend/templates/_helpers-labels.tpl create mode 100644 helm-charts/aws-ce-grafana-backend/templates/_helpers-names.tpl create mode 100644 helm-charts/aws-ce-grafana-backend/templates/_helpers.tpl create mode 100644 helm-charts/aws-ce-grafana-backend/templates/deployment.yaml create mode 100644 helm-charts/aws-ce-grafana-backend/templates/ingress.yaml create mode 100644 helm-charts/aws-ce-grafana-backend/templates/secret.yaml create mode 100644 helm-charts/aws-ce-grafana-backend/templates/service.yaml create mode 100644 helm-charts/aws-ce-grafana-backend/templates/serviceaccount.yaml create mode 100644 helm-charts/aws-ce-grafana-backend/values.schema.yaml create mode 100644 helm-charts/aws-ce-grafana-backend/values.yaml create mode 100644 helm-charts/images/aws-ce-grafana-backend/Dockerfile create mode 100644 helm-charts/images/aws-ce-grafana-backend/requirements.txt diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c5a712bc2..7d51c1537 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -57,7 +57,7 @@ repos: hooks: - id: sops-encryption # Add files here if they contain the word 'secret' but should not be encrypted - exclude: secrets\.md|helm-charts/support/templates/prometheus-ingres-auth/secret\.yaml|helm-charts/basehub/templates/dex/secret\.yaml|helm-charts/basehub/templates/static/secret\.yaml|config/clusters/templates/common/support\.secret\.values\.yaml|helm-charts/basehub/templates/ingress-auth/secret\.yaml + exclude: secrets\.md|helm-charts/support/templates/prometheus-ingres-auth/secret\.yaml|helm-charts/basehub/templates/dex/secret\.yaml|helm-charts/basehub/templates/static/secret\.yaml|config/clusters/templates/common/support\.secret\.values\.yaml|helm-charts/basehub/templates/ingress-auth/secret\.yaml|helm-charts/aws-ce-grafana-backend/templates/secret\.yaml # Prevent known typos from being committed - repo: https://github.com/codespell-project/codespell diff --git a/deployer/commands/validate/config.py b/deployer/commands/validate/config.py index ee42f54d4..a83b29b97 100644 --- a/deployer/commands/validate/config.py +++ b/deployer/commands/validate/config.py @@ -64,6 +64,10 @@ def _prepare_helm_charts_dependencies_and_schemas(): _generate_values_schema_json(support_dir) subprocess.check_call(["helm", "dep", "up", support_dir]) + aws_ce_grafana_backend = HELM_CHARTS_DIR.joinpath("aws-ce-grafana-backend") + _generate_values_schema_json(aws_ce_grafana_backend) + subprocess.check_call(["helm", "dep", "up", aws_ce_grafana_backend]) + def get_list_of_hubs_to_operate_on(cluster_name, hub_name): config_file_path = find_absolute_path_to_cluster_file(cluster_name) diff --git a/helm-charts/aws-ce-grafana-backend/.helmignore b/helm-charts/aws-ce-grafana-backend/.helmignore new file mode 100644 index 000000000..1205485fa --- /dev/null +++ b/helm-charts/aws-ce-grafana-backend/.helmignore @@ -0,0 +1,33 @@ +# Anything within the root folder of the Helm chart, where Chart.yaml resides, +# will be embedded into the packaged Helm chart. This is reasonable since only +# when the templates render after the chart has been packaged and distributed, +# will the templates logic evaluate that determines if other files were +# referenced, such as our our files/hub/jupyterhub_config.py. +# +# Here are files that we intentionally ignore to avoid them being packaged, +# because we don't want to reference them from our templates anyhow. +values.schema.yaml + +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/helm-charts/aws-ce-grafana-backend/Chart.yaml b/helm-charts/aws-ce-grafana-backend/Chart.yaml new file mode 100644 index 000000000..0edc8b92c --- /dev/null +++ b/helm-charts/aws-ce-grafana-backend/Chart.yaml @@ -0,0 +1,17 @@ +# Chart.yaml v2 reference: https://helm.sh/docs/topics/charts/#the-chartyaml-file +apiVersion: v2 +name: aws-ce-grafana-backend +version: "0.0.1-set.by.chartpress" +appVersion: "1.0.0" +description: + A intermediate backend serving JSON from AWS Cost Explorer API, for use + by Grafana dashboard panels via the Infinity datasource plugin to present AWS cloud + costs. +keywords: [aws, cost explorer, grafana, infinity] +home: https://github.com/2i2c-org/aws-ce-grafana-backend +sources: [https://github.com/2i2c-org/aws-ce-grafana-backend] +# icon: +kubeVersion: ">=1.28.0-0" +maintainers: + - name: Erik Sundell + email: erik@2i2c.org diff --git a/helm-charts/aws-ce-grafana-backend/ce-test-config.yaml b/helm-charts/aws-ce-grafana-backend/ce-test-config.yaml new file mode 100644 index 000000000..8ad2443b4 --- /dev/null +++ b/helm-charts/aws-ce-grafana-backend/ce-test-config.yaml @@ -0,0 +1,4 @@ +fullnameOverride: ce-test +serviceAccount: + annotations: + eks.amazonaws.com/role-arn: arn:aws:iam::783616723547:role/aws_ce_grafana_backend_iam_role diff --git a/helm-charts/aws-ce-grafana-backend/mounted-files/README.md b/helm-charts/aws-ce-grafana-backend/mounted-files/README.md new file mode 100644 index 000000000..73cb11c83 --- /dev/null +++ b/helm-charts/aws-ce-grafana-backend/mounted-files/README.md @@ -0,0 +1,69 @@ +# About code files + +The code is meant to help serve grafana with JSON with cost related data, +initially only from AWS. + +## De-coupled from other k8s services + +This software doesn't rely to other k8s services, so it can deploy and be tested +by itself. + +## Bundling into Dockerfile vs. mounting in Helm chart + +By mounting the code files, development iterations running the code in k8s +becomes faster. + +## Development + +### Testing Python changes locally + +First authenticate yourself against the AWS openscapes account. + +```bash +cd helm-charts/aws-ce-grafana-backend/mounted-files +python -m flask --app=webserver run --port=8080 + +# visit http://localhost:8080/aws +``` + +### Testing Python changes in k8s + +This is currently being developed in the openscapes cluster. It depends on a k8s +ServiceAccount coupled to an IAM Role there as well. + +The image shouldn't need to be rebuilt unless additional dependencies needs to +be installed etc, so if you've only made code changes, you can do the following +to re-deploy. + +```bash +deployer use-cluster-credentials openscapes + +cd helm-charts/aws-ce-grafana-backend +helm upgrade --install --create-namespace -n ce-test --values ce-test-config.yaml ce-test . + +# note that port-forward to a service is just a way to port-forward to a pod +# behind the service, so you need to do the port-forwarding again if the pod +# restarts. +kubectl port-forward -n ce-test service/ce-test 8080:http + +# visit http://localhost:8080/aws +``` + +### Testing image changes in k8s + +```bash + +cd helm-charts + +# before doing this: commit the image change, and stash other changes +# git status should not report anything +chartpress --push + +# commit the updated image tag +git add aws-ce-grafana-backend/values.yaml +git commit -m "aws-ce-grafana-backend chart: update image to deploy" + +# WARNING: cleanup of uncommitted files, should be ok if your git status was +# clean before running chartpress --push +git reset --hard HEAD +``` diff --git a/helm-charts/aws-ce-grafana-backend/mounted-files/__init__.py b/helm-charts/aws-ce-grafana-backend/mounted-files/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/helm-charts/aws-ce-grafana-backend/mounted-files/aws.py b/helm-charts/aws-ce-grafana-backend/mounted-files/aws.py new file mode 100644 index 000000000..6f57058e2 --- /dev/null +++ b/helm-charts/aws-ce-grafana-backend/mounted-files/aws.py @@ -0,0 +1,164 @@ +import boto3 + +# AWS client functions most likely: +# +# - get_cost_and_usage +# - get_cost_categories +# - get_tags +# - list_cost_allocation_tags +# + + +def query_aws_cost_explorer(): + aws_ce_client = boto3.client("ce") + + # ref: https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ce/client/get_cost_and_usage.html#get-cost-and-usage + response = aws_ce_client.get_cost_and_usage( + Metrics=["UnblendedCost"], + Granularity="DAILY", + TimePeriod={ + "Start": "2024-07-01", + "End": "2024-08-01", + }, + Filter={ + "Dimensions": { + # RECORD_TYPE is also called Charge type. By filtering on this + # we avoid results related to credits, tax, etc. + "Key": "RECORD_TYPE", + "Values": ["Usage"], + }, + }, + GroupBy=[ + { + "Type": "DIMENSION", + "Key": "SERVICE", + }, + ], + ) + return response["ResultsByTime"] + + +# Granularity: +# +# - HOURLY, DAILY, or MONTHLY +# +# - Hourly resolution is only available for the last two days, so we'll use a +# daily resolution which is available for the last 13 months. +# +# +# +# Metrics: +# +# - Valid choices: +# - AmortizedCost +# - BlendedCosts +# - NetAmortizedCost +# - NetUnblendedCost +# - NormalizedUsageAmount +# - UnblendedCosts +# - UsageQuantity +# +# - UnblendedCosts is the default metric presented in the web console, it +# represents costs for an individual AWS account. When combining costs in an +# organization, 1 + 1 <= 2, because the accounts cumulative use can reduce +# rates. +# +# - We'll focus on UnblendedCosts though, because makes the service cost +# decoupled from other cloud accounts usage. +# +# Filter: +# +# - RECORD_TYPE is what's named Charge type in the web console, and looking at +# "Usage" only that helps us avoid responses related to credits, tax, etc. +# +# - Dimensions: +# - AZ +# - INSTANCE_TYPE +# - LINKED_ACCOUNT +# - LINKED_ACCOUNT_NAME +# - OPERATION +# - PURCHASE_TYPE +# - REGION +# - SERVICE +# - SERVICE_CODE +# - USAGE_TYPE +# - USAGE_TYPE_GROUP +# - RECORD_TYPE +# - OPERATING_SYSTEM +# - TENANCY +# - SCOPE +# - PLATFORM +# - SUBSCRIPTION_ID +# - LEGAL_ENTITY_NAME +# - DEPLOYMENT_OPTION +# - DATABASE_ENGINE +# - CACHE_ENGINE +# - INSTANCE_TYPE_FAMILY +# - BILLING_ENTITY +# - RESERVATION_ID +# - RESOURCE_ID (available only for the last 14 days of usage) +# - RIGHTSIZING_TYPE +# - SAVINGS_PLANS_TYPE +# - SAVINGS_PLAN_ARN +# - PAYMENT_OPTION +# - AGREEMENT_END_DATE_TIME_AFTER +# - AGREEMENT_END_DATE_TIME_BEFORE +# - INVOICING_ENTITY +# - ANOMALY_TOTAL_IMPACT_ABSOLUTE +# - ANOMALY_TOTAL_IMPACT_PERCENTAGE +# - Tags: +# - Refers to Cost Allocation Tags. +# - CostCategories: +# - Can include Cost Allocation Tags, but also references various services +# etc. +# +# GroupBy +# +# - Can be an array with up to two string elements, being either: +# - DIMENSION +# - TAG +# - COST_CATEGORY +# + +# Description of Grafana panels wanted by Yuvi: +# ref: https://github.com/2i2c-org/infrastructure/issues/4453#issuecomment-2298076415 +# +# Currently our AWS tag 2i2c:hub-name is only capturing a fraction of the costs, +# so initially only the following panels are easy to work on. +# +# - total cost (4) +# - total cost per component (2) +# +# The following panels are dependent on the 2i2c:hub-name tag though. +# +# - total cost per hub (1) +# - total cost per component, repeated per hub (3) +# +# Summarized notes about user facing labels: +# +# - fixed: +# - core nodepool +# - any PV needed for support chart or hub databases +# - Kubernetes master API +# - load balancer services +# - compute: +# - disks +# - networking +# - gpus +# - home storage: +# - backups +# - object storage: +# - tagged buckets +# - not counting requester pays +# - total: +# - all 2i2c managed infra +# +# Working against cost tags directly or cost categories +# +# Cost categories vs Cost allocation tags +# +# - It seems cost categories could be suitable to group misc data under +# categories, and split things like core node pool. +# - I think its worth exploring if we could offload all complexity about user +# facing labels etc by using cost categories to group and label costs. +# diff --git a/helm-charts/aws-ce-grafana-backend/mounted-files/webserver.py b/helm-charts/aws-ce-grafana-backend/mounted-files/webserver.py new file mode 100644 index 000000000..de1a515b2 --- /dev/null +++ b/helm-charts/aws-ce-grafana-backend/mounted-files/webserver.py @@ -0,0 +1,20 @@ +from flask import Flask + +from .aws import query_aws_cost_explorer + +app = Flask(__name__) + + +@app.route("/") +def hello_world(): + return "

Hello, World!

" + + +@app.route("/health/ready") +def ready(): + return ("", 204) + + +@app.route("/aws") +def aws(): + return query_aws_cost_explorer() diff --git a/helm-charts/aws-ce-grafana-backend/templates/NOTES.txt b/helm-charts/aws-ce-grafana-backend/templates/NOTES.txt new file mode 100644 index 000000000..632e0d43b --- /dev/null +++ b/helm-charts/aws-ce-grafana-backend/templates/NOTES.txt @@ -0,0 +1,73 @@ +{{- /* Generated with https://patorjk.com/software/taag/#p=display&h=0&f=Slant&t=BinderHub */}} +. ____ _ _ __ _____ _____ ___ + / __ `/| | /| / / / ___/ ______ / ___/ / _ \ ______ +/ /_/ / | |/ |/ / (__ ) /_____// /__ / __//_____/ +\__,_/ |__/|__/ /____/ ____\___/ \___/ + ____ _ _____ ____ _ / __/ ____ _ ____ ____ _ + / __ `/ / ___/ / __ `/ / /_ / __ `/ / __ \ / __ `/ ______ + / /_/ / / / / /_/ / / __/ / /_/ / / / / // /_/ / /_____/ + \__, / /_/ \__,_/ /_/ \__,_/ /_/ /_/ \__,_/ +/____/ __ __ + / /_ ____ _ _____ / /__ ___ ____ ____/ / + / __ \ / __ `/ / ___/ / //_/ / _ \ / __ \ / __ / + / /_/ // /_/ / / /__ / ,< / __/ / / / // /_/ / +/_.___/ \__,_/ \___/ /_/|_| \___/ /_/ /_/ \__,_/ + +You have successfully installed the AWS Cost Explorer Grafana Backend Helm chart! + +### Installation info + + - Kubernetes namespace: {{ .Release.Namespace }} + - Helm release name: {{ .Release.Name }} + - Helm chart version: {{ .Chart.Version }} + - Python packages: See https://github.com/2i2c-org/aws-ce-grafana-backend/blob/{{ include "aws-ce-grafana-backend.chart-version-to-git-ref" .Chart.Version }}/images/aws-ce-grafana-backend/requirements.txt + +### Followup links + + - Documentation: https://github.com/2i2c-org/aws-ce-grafana-backend#readme + - Issue tracking: https://github.com/2i2c-org/aws-ce-grafana-backend/issues + +### Post-installation checklist + + - Verify that created Pods enter a Running state: + + kubectl --namespace={{ .Release.Namespace }} get pod + + If a pod is stuck with a Pending or ContainerCreating status, diagnose with: + + kubectl --namespace={{ .Release.Namespace }} describe pod + + If a pod keeps restarting, diagnose with: + + kubectl --namespace={{ .Release.Namespace }} logs --previous + {{- println }} + + + +{{- /* + Breaking changes. +*/}} + +{{- $breaking := "" }} +{{- $breaking_title := "\n" }} +{{- $breaking_title = print $breaking_title "\n#################################################################################" }} +{{- $breaking_title = print $breaking_title "\n###### BREAKING: The config values passed contained no longer accepted #####" }} +{{- $breaking_title = print $breaking_title "\n###### options. See the messages below for more details. #####" }} +{{- $breaking_title = print $breaking_title "\n###### #####" }} +{{- $breaking_title = print $breaking_title "\n###### To verify your updated config is accepted, you can use #####" }} +{{- $breaking_title = print $breaking_title "\n###### the `helm template` command. #####" }} +{{- $breaking_title = print $breaking_title "\n#################################################################################" }} + + +{{- /* + This is an example (in a helm template comment) on how to detect and + communicate with regards to a breaking chart config change. + + {{- if hasKey .Values.singleuser.cloudMetadata "enabled" }} + {{- $breaking = print $breaking "\n\nCHANGED: singleuser.cloudMetadata.enabled must as of 1.0.0 be configured using singleuser.cloudMetadata.blockWithIptables with the opposite value." }} + {{- end }} +*/}} + +{{- if $breaking }} +{{- fail (print $breaking_title $breaking "\n\n") }} +{{- end }} diff --git a/helm-charts/aws-ce-grafana-backend/templates/_helpers-extra-files.tpl b/helm-charts/aws-ce-grafana-backend/templates/_helpers-extra-files.tpl new file mode 100644 index 000000000..889f13091 --- /dev/null +++ b/helm-charts/aws-ce-grafana-backend/templates/_helpers-extra-files.tpl @@ -0,0 +1,72 @@ +{{- /* + aws-ce-grafana-backend.extraFiles.data: + Renders content for a k8s Secret's data field, coming from extraFiles with + binaryData entries. +*/}} +{{- define "aws-ce-grafana-backend.extraFiles.data.withNewLineSuffix" -}} + {{- range $file_key, $file_details := . }} + {{- include "aws-ce-grafana-backend.extraFiles.validate-file" (list $file_key $file_details) }} + {{- if $file_details.binaryData }} + {{- $file_key | quote }}: {{ $file_details.binaryData | nospace | quote }}{{ println }} + {{- end }} + {{- end }} +{{- end }} +{{- define "aws-ce-grafana-backend.extraFiles.data" -}} + {{- include "aws-ce-grafana-backend.extraFiles.data.withNewLineSuffix" . | trimSuffix "\n" }} +{{- end }} + +{{- /* + aws-ce-grafana-backend.extraFiles.stringData: + Renders content for a k8s Secret's stringData field, coming from extraFiles + with either data or stringData entries. +*/}} +{{- define "aws-ce-grafana-backend.extraFiles.stringData.withNewLineSuffix" -}} + {{- range $file_key, $file_details := . }} + {{- include "aws-ce-grafana-backend.extraFiles.validate-file" (list $file_key $file_details) }} + {{- $file_name := $file_details.mountPath | base }} + {{- if $file_details.stringData }} + {{- $file_key | quote }}: | + {{- $file_details.stringData | trimSuffix "\n" | nindent 2 }}{{ println }} + {{- end }} + {{- if $file_details.data }} + {{- $file_key | quote }}: | + {{- if or (eq (ext $file_name) ".yaml") (eq (ext $file_name) ".yml") }} + {{- $file_details.data | toYaml | nindent 2 }}{{ println }} + {{- else if eq (ext $file_name) ".json" }} + {{- $file_details.data | toJson | nindent 2 }}{{ println }} + {{- else if eq (ext $file_name) ".toml" }} + {{- $file_details.data | toToml | trimSuffix "\n" | nindent 2 }}{{ println }} + {{- else }} + {{- print "\n\nextraFiles entries with 'data' (" $file_key " > " $file_details.mountPath ") needs to have a filename extension of .yaml, .yml, .json, or .toml!" | fail }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} +{{- define "aws-ce-grafana-backend.extraFiles.stringData" -}} + {{- include "aws-ce-grafana-backend.extraFiles.stringData.withNewLineSuffix" . | trimSuffix "\n" }} +{{- end }} + +{{- define "aws-ce-grafana-backend.extraFiles.validate-file" -}} + {{- $file_key := index . 0 }} + {{- $file_details := index . 1 }} + + {{- /* Use of mountPath. */}} + {{- if not ($file_details.mountPath) }} + {{- print "\n\nextraFiles entries (" $file_key ") must contain the field 'mountPath'." | fail }} + {{- end }} + + {{- /* Use one of stringData, binaryData, data. */}} + {{- $field_count := 0 }} + {{- if $file_details.data }} + {{- $field_count = add1 $field_count }} + {{- end }} + {{- if $file_details.stringData }} + {{- $field_count = add1 $field_count }} + {{- end }} + {{- if $file_details.binaryData }} + {{- $field_count = add1 $field_count }} + {{- end }} + {{- if ne $field_count 1 }} + {{- print "\n\nextraFiles entries (" $file_key ") must only contain one of the fields: 'data', 'stringData', and 'binaryData'." | fail }} + {{- end }} +{{- end }} diff --git a/helm-charts/aws-ce-grafana-backend/templates/_helpers-labels.tpl b/helm-charts/aws-ce-grafana-backend/templates/_helpers-labels.tpl new file mode 100644 index 000000000..0e3702d12 --- /dev/null +++ b/helm-charts/aws-ce-grafana-backend/templates/_helpers-labels.tpl @@ -0,0 +1,19 @@ +{{- /* + Common labels +*/}} +{{- define "aws-ce-grafana-backend.labels" -}} +helm.sh/chart: {{ printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{ include "aws-ce-grafana-backend.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{- /* + Selector labels +*/}} +{{- define "aws-ce-grafana-backend.selectorLabels" -}} +app.kubernetes.io/name: {{ .Values.nameOverride | default .Chart.Name | trunc 63 | trimSuffix "-" }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} diff --git a/helm-charts/aws-ce-grafana-backend/templates/_helpers-names.tpl b/helm-charts/aws-ce-grafana-backend/templates/_helpers-names.tpl new file mode 100644 index 000000000..37d9cacd2 --- /dev/null +++ b/helm-charts/aws-ce-grafana-backend/templates/_helpers-names.tpl @@ -0,0 +1,113 @@ +{{- /* + These helpers encapsulates logic on how we name resources. They also enable + parent charts to reference these dynamic resource names. + + To avoid duplicating documentation, for more information, please see the the + fullnameOverride entry the jupyterhub chart's configuration reference: + https://z2jh.jupyter.org/en/latest/resources/reference.html#fullnameOverride +*/}} + + + +{{- /* + Utility templates +*/}} + +{{- /* + Renders to a prefix for the chart's resource names. This prefix is assumed to + make the resource name cluster unique. +*/}} +{{- define "aws-ce-grafana-backend.fullname" -}} + {{- /* + We have implemented a trick to allow a parent chart depending on this + chart to call these named templates. + + Caveats and notes: + + 1. While parent charts can reference these, grandparent charts can't. + 2. Parent charts must not use an alias for this chart. + 3. There is no failsafe workaround to above due to + https://github.com/helm/helm/issues/9214. + 4. .Chart is of its own type (*chart.Metadata) and needs to be casted + using "toYaml | fromYaml" in order to be able to use normal helm + template functions on it. + */}} + {{- $fullname_override := .Values.fullnameOverride }} + {{- $name_override := .Values.nameOverride }} + {{- if ne .Chart.Name "aws-ce-grafana-backend" }} + {{- if .Values.jupyterhub }} + {{- $fullname_override = .Values.jupyterhub.fullnameOverride }} + {{- $name_override = .Values.jupyterhub.nameOverride }} + {{- end }} + {{- end }} + + {{- if eq (typeOf $fullname_override) "string" }} + {{- $fullname_override }} + {{- else }} + {{- $name := $name_override | default .Chart.Name }} + {{- if contains $name .Release.Name }} + {{- .Release.Name }} + {{- else }} + {{- .Release.Name }}-{{ $name }} + {{- end }} + {{- end }} +{{- end }} + +{{- /* + Renders to a blank string or if the fullname template is truthy renders to it + with an appended dash. +*/}} +{{- define "aws-ce-grafana-backend.fullname.dash" -}} + {{- if (include "aws-ce-grafana-backend.fullname" .) }} + {{- include "aws-ce-grafana-backend.fullname" . }}- + {{- end }} +{{- end }} + + + +{{- /* + Namespaced resources +*/}} + +{{- /* webserver resources' default name */}} +{{- define "aws-ce-grafana-backend.webserver.fullname" -}} + {{- if (include "aws-ce-grafana-backend.fullname" .) }} + {{- include "aws-ce-grafana-backend.fullname" . }} + {{- else -}} + aws-ce-grafana-backend + {{- end }} +{{- end }} + +{{- /* webserver's ServiceAccount name */}} +{{- define "aws-ce-grafana-backend.webserver.serviceaccount.fullname" -}} + {{- if .Values.serviceAccount.create }} + {{- .Values.serviceAccount.name | default (include "aws-ce-grafana-backend.webserver.fullname" .) }} + {{- else }} + {{- .Values.serviceAccount.name }} + {{- end }} +{{- end }} + +{{- /* webserver's Ingress name */}} +{{- define "aws-ce-grafana-backend.webserver.ingress.fullname" -}} + {{- if (include "aws-ce-grafana-backend.fullname" .) }} + {{- include "aws-ce-grafana-backend.fullname" . }} + {{- else -}} + aws-ce-grafana-backend + {{- end }} +{{- end }} + + + +{{- /* + Cluster wide resources + + We enforce uniqueness of names for our cluster wide resources. We assume that + the prefix from setting fullnameOverride to null or a string will be cluster + unique. +*/}} + +{{- /* + We currently have no cluster wide resources, but if you add one below in the + future, remove this comment and add an entry mimicking how the jupyterhub helm + chart does it. +*/}} diff --git a/helm-charts/aws-ce-grafana-backend/templates/_helpers.tpl b/helm-charts/aws-ce-grafana-backend/templates/_helpers.tpl new file mode 100644 index 000000000..fc8613049 --- /dev/null +++ b/helm-charts/aws-ce-grafana-backend/templates/_helpers.tpl @@ -0,0 +1,18 @@ +{{- /* + aws-ce-grafana-backend.chart-version-to-git-ref: + Renders a valid git reference from a chartpress generated version string. + In practice, either a git tag or a git commit hash will be returned. + + - The version string will follow a chartpress pattern, + like "0.1.0-0.dev.git.17.h8368bc0", see + https://github.com/jupyterhub/chartpress#examples-chart-versions-and-image-tags. + + - The regexReplaceAll function is a sprig library function, see + https://masterminds.github.io/sprig/strings.html. + + - The regular expression is in golang syntax, but \d had to become \\d for + example. +*/}} +{{- define "aws-ce-grafana-backend.chart-version-to-git-ref" -}} +{{- regexReplaceAll ".*\\.git\\.\\d+\\.h(.*)" . "${1}" }} +{{- end }} diff --git a/helm-charts/aws-ce-grafana-backend/templates/deployment.yaml b/helm-charts/aws-ce-grafana-backend/templates/deployment.yaml new file mode 100644 index 000000000..a9489f877 --- /dev/null +++ b/helm-charts/aws-ce-grafana-backend/templates/deployment.yaml @@ -0,0 +1,76 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "aws-ce-grafana-backend.webserver.fullname" . }} + labels: + {{- include "aws-ce-grafana-backend.labels" . | nindent 4 }} +spec: + replicas: 1 + selector: + matchLabels: + {{- include "aws-ce-grafana-backend.selectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + checksum/mounted-secret: {{ include (print .Template.BasePath "/secret.yaml") . | sha256sum }} + checksum/service-account: {{ include (print .Template.BasePath "/serviceaccount.yaml") . | sha256sum }} + {{- with .Values.podAnnotations }} + {{- . | toYaml | nindent 8 }} + {{- end }} + labels: + {{- include "aws-ce-grafana-backend.labels" . | nindent 8 }} + spec: + volumes: + - name: secret + secret: + secretName: {{ include "aws-ce-grafana-backend.webserver.fullname" . }} + containers: + - name: webserver + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + {{- with .Values.image.pullPolicy }} + imagePullPolicy: {{ . }} + {{- end }} + ports: + - name: http + containerPort: 8080 + volumeMounts: + - name: secret + mountPath: /srv/aws-ce-grafana-backend + readOnly: true + {{- with .Values.extraEnv }} + env: + {{- tpl (. | toYaml) $ | nindent 12 }} + {{- end }} + resources: + {{- .Values.resources | toYaml | nindent 12 }} + securityContext: + {{- .Values.securityContext | toYaml | nindent 12 }} + startupProbe: + periodSeconds: 1 + failureThreshold: 60 + httpGet: + path: /health/ready + port: http + {{- with .Values.image.pullSecrets }} + imagePullSecrets: + {{- . | toYaml | nindent 8 }} + {{- end }} + {{- with include "aws-ce-grafana-backend.webserver.serviceaccount.fullname" . }} + serviceAccountName: {{ . }} + {{- end }} + {{- with .Values.podSecurityContext }} + securityContext: + {{- . | toYaml | nindent 8 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- . | toYaml | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- . | toYaml | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- . | toYaml | nindent 8 }} + {{- end }} diff --git a/helm-charts/aws-ce-grafana-backend/templates/ingress.yaml b/helm-charts/aws-ce-grafana-backend/templates/ingress.yaml new file mode 100644 index 000000000..7e2bb5674 --- /dev/null +++ b/helm-charts/aws-ce-grafana-backend/templates/ingress.yaml @@ -0,0 +1,35 @@ +{{- if .Values.ingress.enabled -}} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ include "aws-ce-grafana-backend.webserver.ingress.fullname" . }} + labels: + {{- include "aws-ce-grafana-backend.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- . | toYaml | nindent 4 }} + {{- end }} +spec: + {{- with .Values.ingress.ingressClassName }} + ingressClassName: "{{ . }}" + {{- end }} + rules: + {{- range $host := .Values.ingress.hosts | default (list "") }} + - http: + paths: + - path: {{ $.Values.config.BinderHub.base_url | trimSuffix "/" }}/{{ $.Values.ingress.pathSuffix }} + pathType: {{ $.Values.ingress.pathType }} + backend: + service: + name: {{ include "aws-ce-grafana-backend.webserver.fullname" $ }} + port: + name: http + {{- if $host }} + host: {{ $host | quote }} + {{- end }} + {{- end }} + {{- with .Values.ingress.tls }} + tls: + {{- . | toYaml | nindent 4 }} + {{- end }} +{{- end }} diff --git a/helm-charts/aws-ce-grafana-backend/templates/secret.yaml b/helm-charts/aws-ce-grafana-backend/templates/secret.yaml new file mode 100644 index 000000000..01ed4c283 --- /dev/null +++ b/helm-charts/aws-ce-grafana-backend/templates/secret.yaml @@ -0,0 +1,13 @@ +{{- /* + Changes to this rendered manifest triggers a restart of the aws-ce-grafana-backend + pod as the pod specification includes an annotation with a checksum of this. +*/ -}} +kind: Secret +apiVersion: v1 +metadata: + name: {{ include "aws-ce-grafana-backend.webserver.fullname" . }} + labels: + {{- include "aws-ce-grafana-backend.labels" . | nindent 4 }} +type: Opaque +stringData: + {{- (.Files.Glob "mounted-files/*").AsConfig | nindent 2 }} diff --git a/helm-charts/aws-ce-grafana-backend/templates/service.yaml b/helm-charts/aws-ce-grafana-backend/templates/service.yaml new file mode 100644 index 000000000..f3822329b --- /dev/null +++ b/helm-charts/aws-ce-grafana-backend/templates/service.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "aws-ce-grafana-backend.webserver.fullname" . }} + labels: {{- include "aws-ce-grafana-backend.labels" . | nindent 4 }} + {{- with .Values.service.annotations }} + annotations: + {{- . | toYaml | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.service.type }} + ports: + - name: http + port: {{ .Values.service.port }} + targetPort: http + {{- with .Values.service.nodePort }} + nodePort: {{ . }} + {{- end }} + selector: {{- include "aws-ce-grafana-backend.selectorLabels" . | nindent 4 }} diff --git a/helm-charts/aws-ce-grafana-backend/templates/serviceaccount.yaml b/helm-charts/aws-ce-grafana-backend/templates/serviceaccount.yaml new file mode 100644 index 000000000..8fc552ece --- /dev/null +++ b/helm-charts/aws-ce-grafana-backend/templates/serviceaccount.yaml @@ -0,0 +1,12 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "aws-ce-grafana-backend.webserver.serviceaccount.fullname" . }} + labels: + {{- include "aws-ce-grafana-backend.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- . | toYaml | nindent 4 }} + {{- end }} +{{- end }} diff --git a/helm-charts/aws-ce-grafana-backend/values.schema.yaml b/helm-charts/aws-ce-grafana-backend/values.schema.yaml new file mode 100644 index 000000000..2d793009b --- /dev/null +++ b/helm-charts/aws-ce-grafana-backend/values.schema.yaml @@ -0,0 +1,140 @@ +# This schema (a JSONSchema in YAML format) is used to generate +# values.schema.json to be packaged with the Helm chart. +# +# This schema is also planned to be used by our documentation system to build +# the configuration reference section based on the description fields. See +# docs/source/conf.py for that logic in the future! +# +# We look to document everything we have default values for in values.yaml, but +# we don't look to enforce the perfect validation logic within this file. +# +# ref: https://helm.sh/docs/topics/charts/#schema-files +# ref: https://json-schema.org/learn/getting-started-step-by-step.html +# +$schema: http://json-schema.org/draft-07/schema# +type: object +additionalProperties: false +required: + # General configuration + - global + # Deployment resource + - image + # Other resources + - serviceAccount + - service + - ingress +properties: + # Flag to conditionally install the chart + # --------------------------------------------------------------------------- + # + enabled: + type: boolean + description: | + Configuration flag for charts depending on aws-ce-grafana-backend to toggle installing it. + + # General configuration + # --------------------------------------------------------------------------- + # + nameOverride: + type: [string, "null"] + fullnameOverride: + type: [string, "null"] + global: + type: object + additionalProperties: true + + # Deployment resource + # --------------------------------------------------------------------------- + # + replicas: + type: integer + extraEnv: + type: array + image: &image + type: object + additionalProperties: false + required: [repository, tag] + properties: + repository: + type: string + tag: + type: string + pullPolicy: + enum: [null, "", IfNotPresent, Always, Never] + pullSecrets: + type: array + resources: &resources + type: object + additionalProperties: true + securityContext: &securityContext + type: object + additionalProperties: true + podSecurityContext: &podSecurityContext + type: object + additionalProperties: true + podAnnotations: &labels-and-annotations + type: object + additionalProperties: false + patternProperties: + ".*": + type: string + nodeSelector: &nodeSelector + type: object + additionalProperties: true + affinity: &affinity + type: object + additionalProperties: true + tolerations: &tolerations + type: array + + # ServiceAccount resource + # --------------------------------------------------------------------------- + # + serviceAccount: + type: object + additionalProperties: false + required: [create, name] + properties: + create: + type: boolean + name: + type: string + annotations: *labels-and-annotations + + # Service resource + # --------------------------------------------------------------------------- + # + service: + type: object + additionalProperties: false + required: [type, port] + properties: + type: + type: string + port: + type: integer + nodePort: + type: integer + annotations: *labels-and-annotations + + # Ingress resource + # --------------------------------------------------------------------------- + # + ingress: + type: object + additionalProperties: false + required: [enabled] + properties: + enabled: + type: boolean + annotations: *labels-and-annotations + ingressClassName: + type: [string, "null"] + hosts: + type: array + pathSuffix: + type: [string, "null"] + pathType: + enum: [Prefix, Exact, ImplementationSpecific] + tls: + type: array diff --git a/helm-charts/aws-ce-grafana-backend/values.yaml b/helm-charts/aws-ce-grafana-backend/values.yaml new file mode 100644 index 000000000..479a18b45 --- /dev/null +++ b/helm-charts/aws-ce-grafana-backend/values.yaml @@ -0,0 +1,59 @@ +# General configuration +# ----------------------------------------------------------------------------- +# +nameOverride: "" +fullnameOverride: "" +global: {} + +# Deployment resource +# ----------------------------------------------------------------------------- +# +replicas: 1 +extraEnv: [] +image: + repository: quay.io/2i2c/aws-ce-grafana-backend + tag: "0.0.1-0.dev.git.10263.hc87b65cf" + pullPolicy: "" + pullSecrets: [] +resources: {} +securityContext: + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + runAsNonRoot: true + runAsUser: 65534 # nobody user + runAsGroup: 65534 # nobody group + +podSecurityContext: {} +podAnnotations: {} +nodeSelector: {} +affinity: {} +tolerations: [] + +# ServiceAccount resource +# ----------------------------------------------------------------------------- +# +serviceAccount: + create: true + name: "" + annotations: {} + +# Service resource +# ----------------------------------------------------------------------------- +# +service: + type: ClusterIP + port: 80 + +# Ingress resource +# ----------------------------------------------------------------------------- +# +ingress: + enabled: false + annotations: {} + ingressClassName: + hosts: [] + pathSuffix: + pathType: Prefix + tls: [] diff --git a/helm-charts/chartpress.yaml b/helm-charts/chartpress.yaml index f016fedb3..194892252 100644 --- a/helm-charts/chartpress.yaml +++ b/helm-charts/chartpress.yaml @@ -27,3 +27,8 @@ charts: gcp-filestore-backups: imageName: quay.io/2i2c/gcp-filestore-backups valuesPath: gcpFilestoreBackups.image + - name: aws-ce-grafana-backend + images: + aws-ce-grafana-backend: + imageName: quay.io/2i2c/aws-ce-grafana-backend + valuesPath: image diff --git a/helm-charts/images/aws-ce-grafana-backend/Dockerfile b/helm-charts/images/aws-ce-grafana-backend/Dockerfile new file mode 100644 index 000000000..0b9615d44 --- /dev/null +++ b/helm-charts/images/aws-ce-grafana-backend/Dockerfile @@ -0,0 +1,53 @@ +# syntax = docker/dockerfile:1.3 + + +# The build stage +# --------------- +# This stage is building Python wheels for use in later stages by using a base +# image that has more pre-requisites to do so, such as a C++ compiler. +# +FROM python:3.12-bullseye as build-stage + +# Build wheels +# +# We set pip's cache directory and expose it across build stages via an +# ephemeral docker cache (--mount=type=cache,target=${PIP_CACHE_DIR}). We use +# the same technique for the directory /tmp/wheels. +# +COPY requirements.txt requirements.txt +ARG PIP_CACHE_DIR=/tmp/pip-cache +RUN --mount=type=cache,target=${PIP_CACHE_DIR} \ + pip wheel \ + --wheel-dir=/tmp/wheels \ + -r requirements.txt + + +# The final stage +# --------------- +# +FROM python:3.12-slim-bullseye as slim-stage +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update \ + && apt-get upgrade -y \ + && apt-get install -y --no-install-recommends \ + tini \ + && rm -rf /var/lib/apt/lists/* + +# install wheels built in the build stage +# --no-index ensures _only_ wheels from the build stage are installed +COPY requirements.txt /tmp/requirements.txt +ARG PIP_CACHE_DIR=/tmp/pip-cache +RUN --mount=type=cache,target=${PIP_CACHE_DIR} \ + --mount=type=cache,from=build-stage,source=/tmp/wheels,target=/tmp/wheels \ + pip install \ + --no-index \ + --find-links=/tmp/wheels/ \ + -r /tmp/requirements.txt + +WORKDIR /srv/aws-ce-grafana-backend + +USER 65534 +EXPOSE 8080 +ENTRYPOINT ["tini", "--"] +CMD ["python", "-m", "flask", "--app=webserver", "run", "--host=0.0.0.0", "--port=8080"] diff --git a/helm-charts/images/aws-ce-grafana-backend/requirements.txt b/helm-charts/images/aws-ce-grafana-backend/requirements.txt new file mode 100644 index 000000000..aa55d9895 --- /dev/null +++ b/helm-charts/images/aws-ce-grafana-backend/requirements.txt @@ -0,0 +1,2 @@ +flask +boto3 diff --git a/helm-charts/support/Chart.yaml b/helm-charts/support/Chart.yaml index 7c58c47de..4c3f8b370 100644 --- a/helm-charts/support/Chart.yaml +++ b/helm-charts/support/Chart.yaml @@ -45,3 +45,10 @@ dependencies: version: "0.3.1-0.dev.git.143.hfc89744" repository: https://cryptnono.github.io/cryptnono/ condition: cryptnono.enabled + + # aws-ce-grafana-backend, exposes AWS Cost Explorer API info to Grafana + # Source code: https://github.com/2i2c/infrastructure/ + - name: aws-ce-grafana-backend + version: "0.0.1-set.by.chartpress" + repository: "file://../aws-ce-grafana-backend" + condition: aws-ce-grafana-backend.enabled diff --git a/helm-charts/support/values.schema.yaml b/helm-charts/support/values.schema.yaml index 3b29dfe2c..4f140aadf 100644 --- a/helm-charts/support/values.schema.yaml +++ b/helm-charts/support/values.schema.yaml @@ -20,6 +20,7 @@ required: - cryptnono - redirects - gcpFilestoreBackups + - aws-ce-grafana-backend - global properties: # cluster-autoscaler is a dependent helm chart, we rely on its schema @@ -46,6 +47,12 @@ properties: grafana: type: object additionalProperties: true + # aws-ce-grafana-backend is a dependent helm chart, we rely on its schema + # validation for values passed to it and are not imposing restrictions on them + # in this helm chart. + aws-ce-grafana-backend: + type: object + additionalProperties: true # Enables https://github.com/yuvipanda/cryptnono/ to prevent cryptomining cryptnono: type: object diff --git a/helm-charts/support/values.yaml b/helm-charts/support/values.yaml index 512facb16..18b6e3837 100644 --- a/helm-charts/support/values.yaml +++ b/helm-charts/support/values.yaml @@ -469,6 +469,13 @@ cryptnono: memory: 64Mi cpu: 1m +# aws-ce-grafana-backend exposes AWS Cost Explorer API info to Grafana +# +# values ref: https://github.com/2i2c-org/infrastructure/blob/main/helm-charts/aws-ce-grafana-backend/values.yaml +# +aws-ce-grafana-backend: + enabled: false + # Configuration of templates provided directly by this chart # ------------------------------------------------------------------------------- #